From 7ad9d01f974ead17f5cca72c0717b8b69be68acb Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Mon, 13 Jan 2025 18:34:58 +0100 Subject: [PATCH 01/14] chore: removes unused primitives --- scripts/build.ts | 12 --- src/__helpers__/mocks.ts | 21 +---- src/primitives.ts | 178 --------------------------------------- 3 files changed, 1 insertion(+), 210 deletions(-) diff --git a/scripts/build.ts b/scripts/build.ts index 55bec9d..62bbd17 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -8,7 +8,6 @@ import { zodToJsonSchema } from 'zod-to-json-schema'; import { AccountMetadataSchema, - AmountSchema, AnyMediaSchema, AppMetadataSchema, ArticleSchema, @@ -24,8 +23,6 @@ import { GraphMetadataSchema, GroupMetadataSchema, ImageSchema, - LegacyProfileIdSchema, - LegacyPublicationIdSchema, LinkSchema, LiveStreamSchema, LocaleSchema, @@ -38,7 +35,6 @@ import { MetadataLicenseTypeSchema, MintSchema, ModuleMetadataSchema, - NetworkAddressSchema, Nft721MetadataAttributeSchema, NonEmptyStringSchema, PhysicalAddressSchema, @@ -92,20 +88,16 @@ for (const [path, Schema] of schemas) { NonEmptyString: NonEmptyStringSchema, Markdown: MarkdownSchema, URI: URISchema, - Amount: AmountSchema, AnyMedia: AnyMediaSchema, ChainId: ChainIdSchema, EvmAddress: EvmAddressSchema, GeoURI: GeoURISchema, - LegacyProfileId: LegacyProfileIdSchema, - LegacyPublicationId: LegacyPublicationIdSchema, MarketplaceMetadataAttribute: Nft721MetadataAttributeSchema, MediaAudio: MediaAudioSchema, MediaImage: MediaImageSchema, MediaVideo: MediaVideoSchema, MetadataAttribute: MetadataAttributeSchema, MetadataLicenseType: MetadataLicenseTypeSchema, - NetworkAddress: NetworkAddressSchema, PhysicalAddress: PhysicalAddressSchema, Tag: TagSchema, }, @@ -183,13 +175,10 @@ async function generateUmbrellaSchema() { Markdown: MarkdownSchema, URI: URISchema, MainContentFocus: PostMainFocusSchema, - Amount: AmountSchema, AnyMedia: AnyMediaSchema, ChainId: ChainIdSchema, EvmAddress: EvmAddressSchema, GeoURI: GeoURISchema, - LegacyProfileId: LegacyProfileIdSchema, - LegacyPublicationId: LegacyPublicationIdSchema, Locale: LocaleSchema, MarketplaceMetadataAttribute: Nft721MetadataAttributeSchema, MediaAudio: MediaAudioSchema, @@ -198,7 +187,6 @@ async function generateUmbrellaSchema() { MetadataAttribute: MetadataAttributeSchema, MetadataId: MetadataIdSchema, MetadataLicenseType: MetadataLicenseTypeSchema, - NetworkAddress: NetworkAddressSchema, PhysicalAddress: PhysicalAddressSchema, ContentWarning: ContentWarningSchema, Signature: SignatureSchema, diff --git a/src/__helpers__/mocks.ts b/src/__helpers__/mocks.ts index d83cb10..881f496 100644 --- a/src/__helpers__/mocks.ts +++ b/src/__helpers__/mocks.ts @@ -1,26 +1,7 @@ import { faker } from '@faker-js/faker'; -import { - type EvmAddress, - type LegacyProfileId, - type NetworkAddress, - toChainId, - toEvmAddress, - toProfileId, -} from '../primitives'; - -export function mockProfileId(): LegacyProfileId { - return toProfileId(faker.string.hexadecimal({ length: 2 })); -} +import { type EvmAddress, toEvmAddress } from '../primitives'; export function mockEvmAddress(): EvmAddress { return toEvmAddress(faker.string.hexadecimal({ length: 40 })); } - -export function mockNetworkAddress(overrides?: Partial): NetworkAddress { - return { - address: mockEvmAddress(), - chainId: toChainId(1), - ...overrides, - }; -} diff --git a/src/primitives.ts b/src/primitives.ts index ee56c42..edaad74 100644 --- a/src/primitives.ts +++ b/src/primitives.ts @@ -398,181 +398,3 @@ export const ChainIdSchema: z.ZodType = z .number() .positive() .transform(toChainId); - -/** - * An EVM compatible address on a specific chain. - */ -export type NetworkAddress = { - /** - * The chain id. - */ - chainId: ChainId; - /** - * The EVM address. - */ - address: EvmAddress; -}; -/** - * @internal - */ -export const NetworkAddressSchema: z.ZodType = z.object( - { - chainId: ChainIdSchema, - address: EvmAddressSchema, - }, - { - description: 'An EVM compatible address on a specific chain.', - }, -); - -/** - * An NFT token identifier. - */ -export type TokenId = Brand; -/** - * @internal - */ -export function toTokenId(value: string): TokenId { - return value as TokenId; -} -/** - * @internal - */ -export const TokenIdSchema: z.ZodType = z - .string() - .min(1) - .transform(toTokenId); - -/** - * A Fungible Tokens. Usually an ERC20 token. - */ -export type Asset = { - /** - * The asset contract address. - */ - contract: NetworkAddress; - /** - * The number of decimals of the asset (e.g. 18 for WETH) - */ - decimals: number; -}; -/** - * @internal - */ -export const AssetSchema: z.ZodType = z.object({ - contract: NetworkAddressSchema, - decimals: z.number({ description: 'The number of decimals of the asset.' }).int().nonnegative(), -}); -/** - * Creates an {@link Asset}. - * - * @internal - */ -export function asset(contract: NetworkAddressDetails, decimals: number): Asset { - return AssetSchema.parse({ contract, decimals }); -} - -/** - * An amount of a specific asset. - */ -export type Amount = { - /** - * The asset. - * - * See {@link asset} helper to create one. - */ - asset: Asset; - /** - * The amount in the smallest unit of the given asset (e.g. wei for ETH). - */ - value: string; -}; -/** - * @internal - */ -export const AmountSchema: z.ZodType = z.object( - { - asset: AssetSchema, - value: NonEmptyStringSchema.describe( - 'The amount in the smallest unit of the given asset (e.g. wei for ETH).', - ), - }, - { - description: 'An amount of a specific asset.', - }, -); - -export type NetworkAddressDetails = { - /** - * The chain id. - */ - chainId: number; - /** - * The EVM address. - */ - address: string; -}; - -/** - * @internal - */ -export type AmountDetails = { - contract: NetworkAddressDetails; - decimals: number; - value: string; -}; -/** - * @internal - */ -export function amount(input: AmountDetails): Amount { - return AmountSchema.parse({ - asset: asset(input.contract, input.decimals), - value: input.value, - }); -} - -/** - * A Legacy Lens Profile identifier. - * - * @example - * ``` - * 0x01 - * ``` - */ -export type LegacyProfileId = Brand; -/** - * @internal - */ -export function toProfileId(value: string): LegacyProfileId { - return value as LegacyProfileId; -} -/** - * @internal - */ -export const LegacyProfileIdSchema: z.ZodType = z - .string() - .min(4) - .transform(toProfileId); - -/** - * A Legacy on-chain Lens Publication identifier. - * - * @example - * ``` - * 0x01-0x01 - * ``` - */ -export type LegacyPublicationId = Brand; -/** - * @internal - */ -export function toLegacyPublicationId(value: string): LegacyPublicationId { - return value as LegacyPublicationId; -} -/** - * @internal - */ -export const LegacyPublicationIdSchema: z.ZodType = z - .string() - .min(9) - .transform(toLegacyPublicationId); From 5ec52542bd33e601f66f5e90189b7dd541ee118a Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Mon, 13 Jan 2025 18:35:59 +0100 Subject: [PATCH 02/14] chore: consolidates schema enums naming --- src/account/AccountMetadataSchema.ts | 6 +- ...SchemaId.ts => AccountMetadataSchemaId.ts} | 2 +- src/account/index.ts | 2 +- src/builders/account.ts | 4 +- src/builders/posts.ts | 34 +++++------ src/post/3D.ts | 6 +- src/post/ArticleSchema.ts | 6 +- src/post/AudioSchema.ts | 6 +- src/post/CheckingInSchema.ts | 6 +- src/post/EmbedSchema.ts | 6 +- src/post/EventSchema.ts | 6 +- src/post/ImageSchema.ts | 6 +- src/post/LinkSchema.ts | 6 +- src/post/LiveStreamSchema.ts | 6 +- src/post/MintSchema.ts | 6 +- ...ostSchemaId.ts => PostMetadataSchemaId.ts} | 2 +- src/post/SpaceSchema.ts | 6 +- src/post/StorySchema.ts | 6 +- src/post/TextOnlySchema.ts | 6 +- src/post/TransactionSchema.ts | 6 +- src/post/VideoSchema.ts | 6 +- src/post/__helpers__/mocks.ts | 9 ++- src/post/__tests__/PostMetadataSchema.spec.ts | 58 +++++++++---------- src/post/index.ts | 2 +- 24 files changed, 107 insertions(+), 102 deletions(-) rename src/account/{AccountSchemaId.ts => AccountMetadataSchemaId.ts} (72%) rename src/post/{PostSchemaId.ts => PostMetadataSchemaId.ts} (96%) diff --git a/src/account/AccountMetadataSchema.ts b/src/account/AccountMetadataSchema.ts index f07bcd9..338ff0d 100644 --- a/src/account/AccountMetadataSchema.ts +++ b/src/account/AccountMetadataSchema.ts @@ -10,7 +10,7 @@ import { type URI, URISchema, } from '../primitives.js'; -import { AccountSchemaId } from './AccountSchemaId.js'; +import { AccountMetadataSchemaId } from './AccountMetadataSchemaId.js'; export type AccountMetadataDetails = { /** @@ -72,7 +72,7 @@ export type AccountMetadata = { /** * The schema id. */ - $schema: AccountSchemaId.LATEST; + $schema: AccountMetadataSchemaId.LATEST; /** * The metadata details. */ @@ -107,7 +107,7 @@ export type AccountMetadata = { * ``` */ export const AccountMetadataSchema: z.ZodType = z.object({ - $schema: z.literal(AccountSchemaId.LATEST), + $schema: z.literal(AccountMetadataSchemaId.LATEST), lens: AccountMetadataDetailsSchema, signature: SignatureSchema.optional(), }); diff --git a/src/account/AccountSchemaId.ts b/src/account/AccountMetadataSchemaId.ts similarity index 72% rename from src/account/AccountSchemaId.ts rename to src/account/AccountMetadataSchemaId.ts index e7e9b6c..3748caa 100644 --- a/src/account/AccountSchemaId.ts +++ b/src/account/AccountMetadataSchemaId.ts @@ -1,5 +1,5 @@ import { SchemasRoot } from '../constants.js'; -export enum AccountSchemaId { +export enum AccountMetadataSchemaId { LATEST = `${SchemasRoot}/account/1.0.0.json`, } diff --git a/src/account/index.ts b/src/account/index.ts index 38e234e..ebec96a 100644 --- a/src/account/index.ts +++ b/src/account/index.ts @@ -1,2 +1,2 @@ export * from './AccountMetadataSchema.js'; -export * from './AccountSchemaId.js'; +export * from './AccountMetadataSchemaId.js'; diff --git a/src/builders/account.ts b/src/builders/account.ts index 6bf148d..58a4c55 100644 --- a/src/builders/account.ts +++ b/src/builders/account.ts @@ -4,7 +4,7 @@ import { type AccountMetadata, type AccountMetadataDetails, AccountMetadataSchema, - AccountSchemaId, + AccountMetadataSchemaId, } from '../account'; import type { Prettify } from '../utils.js'; import { evaluate } from './ValidationError.js'; @@ -84,7 +84,7 @@ export type AccountOptions = AccountDetails & { export function account({ id = v4(), ...others }: AccountOptions): AccountMetadata { return evaluate( AccountMetadataSchema.safeParse({ - $schema: AccountSchemaId.LATEST, + $schema: AccountMetadataSchemaId.LATEST, lens: { id, ...others, diff --git a/src/builders/posts.ts b/src/builders/posts.ts index 7d57faf..580addb 100644 --- a/src/builders/posts.ts +++ b/src/builders/posts.ts @@ -29,7 +29,7 @@ import { type MintMetadataDetails, MintSchema, PostMainFocus, - PostSchemaId, + PostMetadataSchemaId, type SpaceMetadata, type SpaceMetadataDetails, SpaceSchema, @@ -118,7 +118,7 @@ export function article({ }: ArticleOptions): ArticleMetadata { return evaluate( ArticleSchema.safeParse({ - $schema: PostSchemaId.ARTICLE_LATEST, + $schema: PostMetadataSchemaId.ARTICLE_LATEST, ...nft, lens: { id, @@ -202,7 +202,7 @@ export function audio({ }: AudioOptions): AudioMetadata { return evaluate( AudioSchema.safeParse({ - $schema: PostSchemaId.AUDIO_LATEST, + $schema: PostMetadataSchemaId.AUDIO_LATEST, ...nft, lens: { id, @@ -273,7 +273,7 @@ export function checkingIn({ }: CheckingInOptions): CheckingInMetadata { return evaluate( CheckingInSchema.safeParse({ - $schema: PostSchemaId.CHECKING_IN_LATEST, + $schema: PostMetadataSchemaId.CHECKING_IN_LATEST, ...nft, lens: { id, @@ -323,7 +323,7 @@ export function embed({ }: EmbedOptions): EmbedMetadata { return evaluate( EmbedSchema.safeParse({ - $schema: PostSchemaId.EMBED_LATEST, + $schema: PostMetadataSchemaId.EMBED_LATEST, ...nft, lens: { id, @@ -398,7 +398,7 @@ export function event({ }: EventOptions): EventMetadata { return evaluate( EventSchema.safeParse({ - $schema: PostSchemaId.EVENT_LATEST, + $schema: PostMetadataSchemaId.EVENT_LATEST, ...nft, lens: { id, @@ -484,7 +484,7 @@ export function image({ }: ImageOptions): ImageMetadata { return evaluate( ImageSchema.safeParse({ - $schema: PostSchemaId.IMAGE_LATEST, + $schema: PostMetadataSchemaId.IMAGE_LATEST, ...nft, lens: { id, @@ -535,7 +535,7 @@ export function link({ }: LinkOptions): LinkMetadata { return evaluate( LinkSchema.safeParse({ - $schema: PostSchemaId.LINK_LATEST, + $schema: PostMetadataSchemaId.LINK_LATEST, ...nft, lens: { id, @@ -588,7 +588,7 @@ export function liveStream({ }: LiveStreamOptions): LiveStreamMetadata { return evaluate( LiveStreamSchema.safeParse({ - $schema: PostSchemaId.LIVESTREAM_LATEST, + $schema: PostMetadataSchemaId.LIVESTREAM_LATEST, ...nft, lens: { id, @@ -640,7 +640,7 @@ export function mint({ }: MintOptions): MintMetadata { return evaluate( MintSchema.safeParse({ - $schema: PostSchemaId.MINT_LATEST, + $schema: PostMetadataSchemaId.MINT_LATEST, ...nft, lens: { id, @@ -692,7 +692,7 @@ export function space({ }: SpaceOptions): SpaceMetadata { return evaluate( SpaceSchema.safeParse({ - $schema: PostSchemaId.SPACE_LATEST, + $schema: PostMetadataSchemaId.SPACE_LATEST, ...nft, lens: { id, @@ -748,7 +748,7 @@ export function story({ }: StoryOptions): StoryMetadata { return evaluate( StorySchema.safeParse({ - $schema: PostSchemaId.STORY_LATEST, + $schema: PostMetadataSchemaId.STORY_LATEST, ...nft, lens: { id, @@ -798,7 +798,7 @@ export function textOnly({ }: TextOnlyOptions): TextOnlyMetadata { return evaluate( TextOnlySchema.safeParse({ - $schema: PostSchemaId.TEXT_ONLY_LATEST, + $schema: PostMetadataSchemaId.TEXT_ONLY_LATEST, ...nft, lens: { id, @@ -857,7 +857,7 @@ export function threeD({ }: ThreeDOptions): ThreeDMetadata { return evaluate( ThreeDSchema.safeParse({ - $schema: PostSchemaId.THREE_D_LATEST, + $schema: PostMetadataSchemaId.THREE_D_LATEST, ...nft, lens: { id, @@ -910,7 +910,7 @@ export function transaction({ }: TransactionOptions): TransactionMetadata { return evaluate( TransactionSchema.safeParse({ - $schema: PostSchemaId.TRANSACTION_LATEST, + $schema: PostMetadataSchemaId.TRANSACTION_LATEST, ...nft, lens: { id, @@ -997,7 +997,7 @@ export function video({ }: VideoOptions): VideoMetadata { return evaluate( VideoSchema.safeParse({ - $schema: PostSchemaId.VIDEO_LATEST, + $schema: PostMetadataSchemaId.VIDEO_LATEST, ...nft, lens: { id, @@ -1050,7 +1050,7 @@ export function shortVideo({ }: ShortVideoOptions): VideoMetadata { return evaluate( VideoSchema.safeParse({ - $schema: PostSchemaId.VIDEO_LATEST, + $schema: PostMetadataSchemaId.VIDEO_LATEST, ...nft, lens: { id, diff --git a/src/post/3D.ts b/src/post/3D.ts index 69fc204..2a456db 100644 --- a/src/post/3D.ts +++ b/src/post/3D.ts @@ -10,7 +10,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -113,7 +113,7 @@ export type ThreeDMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.THREE_D_LATEST; + $schema: PostMetadataSchemaId.THREE_D_LATEST; /** * The metadata details. */ @@ -128,7 +128,7 @@ export type ThreeDMetadata = NftMetadata & { * @internal */ export const ThreeDSchema = postWith({ - $schema: z.literal(PostSchemaId.THREE_D_LATEST), + $schema: z.literal(PostMetadataSchemaId.THREE_D_LATEST), lens: ThreeDMetadataDetailsSchema, }); diff --git a/src/post/ArticleSchema.ts b/src/post/ArticleSchema.ts index a501587..2cae68b 100644 --- a/src/post/ArticleSchema.ts +++ b/src/post/ArticleSchema.ts @@ -8,7 +8,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -57,7 +57,7 @@ export type ArticleMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.ARTICLE_LATEST; + $schema: PostMetadataSchemaId.ARTICLE_LATEST; /** * The metadata details. */ @@ -72,6 +72,6 @@ export type ArticleMetadata = NftMetadata & { * @internal */ export const ArticleSchema = postWith({ - $schema: z.literal(PostSchemaId.ARTICLE_LATEST), + $schema: z.literal(PostMetadataSchemaId.ARTICLE_LATEST), lens: ArticleMetadataDetailsSchema, }); diff --git a/src/post/AudioSchema.ts b/src/post/AudioSchema.ts index 8339fee..3734597 100644 --- a/src/post/AudioSchema.ts +++ b/src/post/AudioSchema.ts @@ -8,7 +8,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -68,7 +68,7 @@ export type AudioMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.AUDIO_LATEST; + $schema: PostMetadataSchemaId.AUDIO_LATEST; /** * The metadata details. */ @@ -83,6 +83,6 @@ export type AudioMetadata = NftMetadata & { * @internal */ export const AudioSchema = postWith({ - $schema: z.literal(PostSchemaId.AUDIO_LATEST), + $schema: z.literal(PostMetadataSchemaId.AUDIO_LATEST), lens: AudioMetadataDetailsSchema, }); diff --git a/src/post/CheckingInSchema.ts b/src/post/CheckingInSchema.ts index 4ac454b..c560d44 100644 --- a/src/post/CheckingInSchema.ts +++ b/src/post/CheckingInSchema.ts @@ -12,7 +12,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -74,7 +74,7 @@ export type CheckingInMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.CHECKING_IN_LATEST; + $schema: PostMetadataSchemaId.CHECKING_IN_LATEST; /** * The metadata details. */ @@ -89,6 +89,6 @@ export type CheckingInMetadata = NftMetadata & { * @internal */ export const CheckingInSchema = postWith({ - $schema: z.literal(PostSchemaId.CHECKING_IN_LATEST), + $schema: z.literal(PostMetadataSchemaId.CHECKING_IN_LATEST), lens: CheckingInMetadataDetailsSchema, }); diff --git a/src/post/EmbedSchema.ts b/src/post/EmbedSchema.ts index 6f93c8b..ee9ca17 100644 --- a/src/post/EmbedSchema.ts +++ b/src/post/EmbedSchema.ts @@ -9,7 +9,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -59,7 +59,7 @@ export type EmbedMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.EMBED_LATEST; + $schema: PostMetadataSchemaId.EMBED_LATEST; /** * The metadata details. */ @@ -74,6 +74,6 @@ export type EmbedMetadata = NftMetadata & { * @internal */ export const EmbedSchema = postWith({ - $schema: z.literal(PostSchemaId.EMBED_LATEST), + $schema: z.literal(PostMetadataSchemaId.EMBED_LATEST), lens: EmbedMetadataDetailsSchema, }); diff --git a/src/post/EventSchema.ts b/src/post/EventSchema.ts index 9c24b53..eab9643 100644 --- a/src/post/EventSchema.ts +++ b/src/post/EventSchema.ts @@ -16,7 +16,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -158,7 +158,7 @@ export type EventMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.EVENT_LATEST; + $schema: PostMetadataSchemaId.EVENT_LATEST; /** * The metadata details. */ @@ -173,6 +173,6 @@ export type EventMetadata = NftMetadata & { * @internal */ export const EventSchema = postWith({ - $schema: z.literal(PostSchemaId.EVENT_LATEST), + $schema: z.literal(PostMetadataSchemaId.EVENT_LATEST), lens: EventMetadataDetailsSchema, }); diff --git a/src/post/ImageSchema.ts b/src/post/ImageSchema.ts index 1a377e8..8dbe045 100644 --- a/src/post/ImageSchema.ts +++ b/src/post/ImageSchema.ts @@ -8,7 +8,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -68,7 +68,7 @@ export type ImageMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.IMAGE_LATEST; + $schema: PostMetadataSchemaId.IMAGE_LATEST; /** * The metadata details. */ @@ -83,6 +83,6 @@ export type ImageMetadata = NftMetadata & { * @internal */ export const ImageSchema = postWith({ - $schema: z.literal(PostSchemaId.IMAGE_LATEST), + $schema: z.literal(PostMetadataSchemaId.IMAGE_LATEST), lens: ImageMetadataDetailsSchema, }); diff --git a/src/post/LinkSchema.ts b/src/post/LinkSchema.ts index fac305e..ade9fea 100644 --- a/src/post/LinkSchema.ts +++ b/src/post/LinkSchema.ts @@ -9,7 +9,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -59,7 +59,7 @@ export type LinkMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.LINK_LATEST; + $schema: PostMetadataSchemaId.LINK_LATEST; /** * The metadata details. */ @@ -74,6 +74,6 @@ export type LinkMetadata = NftMetadata & { * @internal */ export const LinkSchema = postWith({ - $schema: z.literal(PostSchemaId.LINK_LATEST), + $schema: z.literal(PostMetadataSchemaId.LINK_LATEST), lens: LinkMetadataDetailsSchema, }); diff --git a/src/post/LiveStreamSchema.ts b/src/post/LiveStreamSchema.ts index 7fa7e19..0c562e8 100644 --- a/src/post/LiveStreamSchema.ts +++ b/src/post/LiveStreamSchema.ts @@ -12,7 +12,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -121,7 +121,7 @@ export type LiveStreamMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.LIVESTREAM_LATEST; + $schema: PostMetadataSchemaId.LIVESTREAM_LATEST; /** * The metadata details. */ @@ -136,6 +136,6 @@ export type LiveStreamMetadata = NftMetadata & { * @internal */ export const LiveStreamSchema = postWith({ - $schema: z.literal(PostSchemaId.LIVESTREAM_LATEST), + $schema: z.literal(PostMetadataSchemaId.LIVESTREAM_LATEST), lens: LiveStreamMetadataDetailsSchema, }); diff --git a/src/post/MintSchema.ts b/src/post/MintSchema.ts index 9f8df64..70bfcd3 100644 --- a/src/post/MintSchema.ts +++ b/src/post/MintSchema.ts @@ -9,7 +9,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -70,7 +70,7 @@ export type MintMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.MINT_LATEST; + $schema: PostMetadataSchemaId.MINT_LATEST; /** * The metadata details. */ @@ -85,6 +85,6 @@ export type MintMetadata = NftMetadata & { * @internal */ export const MintSchema = postWith({ - $schema: z.literal(PostSchemaId.MINT_LATEST), + $schema: z.literal(PostMetadataSchemaId.MINT_LATEST), lens: MintMetadataDetailsSchema, }); diff --git a/src/post/PostSchemaId.ts b/src/post/PostMetadataSchemaId.ts similarity index 96% rename from src/post/PostSchemaId.ts rename to src/post/PostMetadataSchemaId.ts index f69d562..a5ee6a8 100644 --- a/src/post/PostSchemaId.ts +++ b/src/post/PostMetadataSchemaId.ts @@ -5,7 +5,7 @@ const location = `${SchemasRoot}/posts`; /** * A list of all the post schema ids (past and present). */ -export enum PostSchemaId { +export enum PostMetadataSchemaId { THREE_D_LATEST = `${location}/3d/3.0.0.json`, ARTICLE_LATEST = `${location}/article/3.0.0.json`, AUDIO_LATEST = `${location}/audio/3.0.0.json`, diff --git a/src/post/SpaceSchema.ts b/src/post/SpaceSchema.ts index 6179632..6b0c07e 100644 --- a/src/post/SpaceSchema.ts +++ b/src/post/SpaceSchema.ts @@ -12,7 +12,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -76,7 +76,7 @@ export type SpaceMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.SPACE_LATEST; + $schema: PostMetadataSchemaId.SPACE_LATEST; /** * The metadata details. */ @@ -91,7 +91,7 @@ export type SpaceMetadata = NftMetadata & { * @internal */ export const SpaceSchema = postWith({ - $schema: z.literal(PostSchemaId.SPACE_LATEST), + $schema: z.literal(PostMetadataSchemaId.SPACE_LATEST), lens: SpaceMetadataDetailsSchema, }); diff --git a/src/post/StorySchema.ts b/src/post/StorySchema.ts index ff73592..c647a4d 100644 --- a/src/post/StorySchema.ts +++ b/src/post/StorySchema.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; import { type Markdown, MarkdownSchema, type Signature } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -44,7 +44,7 @@ export type StoryMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.STORY_LATEST; + $schema: PostMetadataSchemaId.STORY_LATEST; /** * The metadata details. */ @@ -59,6 +59,6 @@ export type StoryMetadata = NftMetadata & { * @internal */ export const StorySchema = postWith({ - $schema: z.literal(PostSchemaId.STORY_LATEST), + $schema: z.literal(PostMetadataSchemaId.STORY_LATEST), lens: StoryMetadataDetailsSchema, }); diff --git a/src/post/TextOnlySchema.ts b/src/post/TextOnlySchema.ts index ca6874d..9555815 100644 --- a/src/post/TextOnlySchema.ts +++ b/src/post/TextOnlySchema.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; import { type Markdown, MarkdownSchema, type Signature } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type PostMetadataCommon, mainContentFocus, metadataDetailsWith, postWith } from './common'; export type TextOnlyMetadataDetails = PostMetadataCommon & { @@ -33,7 +33,7 @@ export type TextOnlyMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.TEXT_ONLY_LATEST; + $schema: PostMetadataSchemaId.TEXT_ONLY_LATEST; /** * The metadata details. */ @@ -48,6 +48,6 @@ export type TextOnlyMetadata = NftMetadata & { * @internal */ export const TextOnlySchema = postWith({ - $schema: z.literal(PostSchemaId.TEXT_ONLY_LATEST), + $schema: z.literal(PostMetadataSchemaId.TEXT_ONLY_LATEST), lens: TextOnlyMetadataDetailsSchema, }); diff --git a/src/post/TransactionSchema.ts b/src/post/TransactionSchema.ts index 4bb2201..a1a0663 100644 --- a/src/post/TransactionSchema.ts +++ b/src/post/TransactionSchema.ts @@ -10,7 +10,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -84,7 +84,7 @@ export type TransactionMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.TRANSACTION_LATEST; + $schema: PostMetadataSchemaId.TRANSACTION_LATEST; /** * The metadata details. */ @@ -99,6 +99,6 @@ export type TransactionMetadata = NftMetadata & { * @internal */ export const TransactionSchema = postWith({ - $schema: z.literal(PostSchemaId.TRANSACTION_LATEST), + $schema: z.literal(PostMetadataSchemaId.TRANSACTION_LATEST), lens: TransactionMetadataDetailsSchema, }); diff --git a/src/post/VideoSchema.ts b/src/post/VideoSchema.ts index 8af1329..b70078f 100644 --- a/src/post/VideoSchema.ts +++ b/src/post/VideoSchema.ts @@ -8,7 +8,7 @@ import { } from '../primitives.js'; import type { NftMetadata } from '../tokens/eip721.js'; import { PostMainFocus } from './PostMainFocus.js'; -import { PostSchemaId } from './PostSchemaId.js'; +import { PostMetadataSchemaId } from './PostMetadataSchemaId.js'; import { type AnyMedia, AnyMediaSchema, @@ -68,7 +68,7 @@ export type VideoMetadata = NftMetadata & { /** * The schema id. */ - $schema: PostSchemaId.VIDEO_LATEST; + $schema: PostMetadataSchemaId.VIDEO_LATEST; /** * The metadata details. */ @@ -83,6 +83,6 @@ export type VideoMetadata = NftMetadata & { * @internal */ export const VideoSchema = postWith({ - $schema: z.literal(PostSchemaId.VIDEO_LATEST), + $schema: z.literal(PostMetadataSchemaId.VIDEO_LATEST), lens: VideoMetadataDetailsSchema, }); diff --git a/src/post/__helpers__/mocks.ts b/src/post/__helpers__/mocks.ts index 964b382..5dafe28 100644 --- a/src/post/__helpers__/mocks.ts +++ b/src/post/__helpers__/mocks.ts @@ -1,10 +1,15 @@ import { faker } from '@faker-js/faker'; -import { PostMainFocus, PostSchemaId, type TextOnlyMetadata, TextOnlySchema } from '../index.js'; +import { + PostMainFocus, + PostMetadataSchemaId, + type TextOnlyMetadata, + TextOnlySchema, +} from '../index.js'; export function mockTextOnlyMetadata(): TextOnlyMetadata { return TextOnlySchema.parse({ - $schema: PostSchemaId.TEXT_ONLY_LATEST, + $schema: PostMetadataSchemaId.TEXT_ONLY_LATEST, lens: { id: faker.string.uuid(), mainContentFocus: PostMainFocus.TEXT_ONLY, diff --git a/src/post/__tests__/PostMetadataSchema.spec.ts b/src/post/__tests__/PostMetadataSchema.spec.ts index 195ccd6..795d390 100644 --- a/src/post/__tests__/PostMetadataSchema.spec.ts +++ b/src/post/__tests__/PostMetadataSchema.spec.ts @@ -1,7 +1,7 @@ import { describe, it } from 'vitest'; import { expectResult } from '../../__helpers__/assertions.js'; -import { PostMetadataSchema, PostSchemaId } from '../index.js'; +import { PostMetadataSchema, PostMetadataSchemaId } from '../index.js'; describe('Given the PostMetadataSchema', () => { describe('when parsing an empty object', () => { @@ -13,11 +13,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.ARTICLE_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.ARTICLE_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.ARTICLE_LATEST, + $schema: PostMetadataSchemaId.ARTICLE_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -30,11 +30,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.AUDIO_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.AUDIO_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.AUDIO_LATEST, + $schema: PostMetadataSchemaId.AUDIO_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -47,11 +47,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.CHECKING_IN_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.CHECKING_IN_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.CHECKING_IN_LATEST, + $schema: PostMetadataSchemaId.CHECKING_IN_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -64,11 +64,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.EMBED_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.EMBED_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.EMBED_LATEST, + $schema: PostMetadataSchemaId.EMBED_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -81,11 +81,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.IMAGE_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.IMAGE_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.IMAGE_LATEST, + $schema: PostMetadataSchemaId.IMAGE_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -98,11 +98,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.LINK_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.LINK_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.LINK_LATEST, + $schema: PostMetadataSchemaId.LINK_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -115,11 +115,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.LIVESTREAM_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.LIVESTREAM_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.LIVESTREAM_LATEST, + $schema: PostMetadataSchemaId.LIVESTREAM_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -134,11 +134,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.MINT_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.MINT_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.MINT_LATEST, + $schema: PostMetadataSchemaId.MINT_LATEST, lens: { mintLink: ' ', }, @@ -154,11 +154,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.SPACE_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.SPACE_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.SPACE_LATEST, + $schema: PostMetadataSchemaId.SPACE_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -173,11 +173,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.STORY_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.STORY_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.STORY_LATEST, + $schema: PostMetadataSchemaId.STORY_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -190,11 +190,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.TEXT_ONLY_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.TEXT_ONLY_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.TEXT_ONLY_LATEST, + $schema: PostMetadataSchemaId.TEXT_ONLY_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -207,11 +207,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.THREE_D_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.THREE_D_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.THREE_D_LATEST, + $schema: PostMetadataSchemaId.THREE_D_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -224,11 +224,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.TRANSACTION_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.TRANSACTION_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.TRANSACTION_LATEST, + $schema: PostMetadataSchemaId.TRANSACTION_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` @@ -243,11 +243,11 @@ describe('Given the PostMetadataSchema', () => { }); }); - describe(`when parsing an invalid ${PostSchemaId.VIDEO_LATEST}`, () => { + describe(`when parsing an invalid ${PostMetadataSchemaId.VIDEO_LATEST}`, () => { it('then it should flag the missing fields', () => { expectResult(() => PostMetadataSchema.safeParse({ - $schema: PostSchemaId.VIDEO_LATEST, + $schema: PostMetadataSchemaId.VIDEO_LATEST, lens: {}, }), ).toMatchInlineSnapshot(` diff --git a/src/post/index.ts b/src/post/index.ts index 100b4b7..b2f274e 100644 --- a/src/post/index.ts +++ b/src/post/index.ts @@ -12,7 +12,7 @@ export * from './LinkSchema.js'; export * from './LiveStreamSchema.js'; export * from './MintSchema.js'; export * from './PostMainFocus.js'; -export * from './PostSchemaId.js'; +export * from './PostMetadataSchemaId.js'; export * from './SpaceSchema.js'; export * from './StorySchema.js'; export * from './TextOnlySchema.js'; From 249a06e140a4164606e3b2b911227fd03cf4523c Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Mon, 13 Jan 2025 21:59:58 +0100 Subject: [PATCH 03/14] feat: implements ActionMetadata spec --- jsonschemas/action/1.0.0.json | 240 ++++++++++++++++++ jsonschemas/posts/3d/3.0.0.json | 58 ----- jsonschemas/posts/article/3.0.0.json | 58 ----- jsonschemas/posts/audio/3.0.0.json | 58 ----- jsonschemas/posts/checking-in/3.0.0.json | 58 ----- jsonschemas/posts/embed/3.0.0.json | 58 ----- jsonschemas/posts/event/3.0.0.json | 58 ----- jsonschemas/posts/image/3.0.0.json | 58 ----- jsonschemas/posts/link/3.0.0.json | 58 ----- jsonschemas/posts/livestream/3.0.0.json | 58 ----- jsonschemas/posts/mint/3.0.0.json | 58 ----- jsonschemas/posts/space/3.0.0.json | 58 ----- jsonschemas/posts/story/3.0.0.json | 58 ----- jsonschemas/posts/text-only/3.0.0.json | 58 ----- jsonschemas/posts/transaction/3.0.0.json | 58 ----- jsonschemas/posts/video/3.0.0.json | 58 ----- jsonschemas/schema.json | 226 ++++++++--------- package.json | 1 + pnpm-lock.yaml | 20 +- scripts/build.ts | 12 +- src/__tests__/primitives.spec.ts | 85 +++++++ src/action/ActionMetadataSchema.ts | 133 ++++++++++ src/action/ActionMetadataSchemaId.ts | 8 + src/action/index.ts | 2 + .../__snapshots__/action.spec.ts.snap | 53 ++++ .../__snapshots__/modules.spec.ts.snap | 30 --- src/builders/__tests__/action.spec.ts | 59 +++++ src/builders/__tests__/modules.spec.ts | 55 ---- src/builders/action.ts | 67 +++++ src/builders/index.ts | 2 +- src/builders/modules.ts | 63 ----- src/index.ts | 2 +- src/module/ModuleMetadataSchema.ts | 98 ------- src/module/ModuleSchemaId.ts | 5 - src/module/index.ts | 2 - src/primitives.ts | 102 ++++++++ 36 files changed, 882 insertions(+), 1253 deletions(-) create mode 100644 jsonschemas/action/1.0.0.json create mode 100644 src/action/ActionMetadataSchema.ts create mode 100644 src/action/ActionMetadataSchemaId.ts create mode 100644 src/action/index.ts create mode 100644 src/builders/__tests__/__snapshots__/action.spec.ts.snap delete mode 100644 src/builders/__tests__/__snapshots__/modules.spec.ts.snap create mode 100644 src/builders/__tests__/action.spec.ts delete mode 100644 src/builders/__tests__/modules.spec.ts create mode 100644 src/builders/action.ts delete mode 100644 src/builders/modules.ts delete mode 100644 src/module/ModuleMetadataSchema.ts delete mode 100644 src/module/ModuleSchemaId.ts delete mode 100644 src/module/index.ts diff --git a/jsonschemas/action/1.0.0.json b/jsonschemas/action/1.0.0.json new file mode 100644 index 0000000..ae87474 --- /dev/null +++ b/jsonschemas/action/1.0.0.json @@ -0,0 +1,240 @@ +{ + "type": "object", + "properties": { + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/actions/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The name of the Action." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Action." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Action." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "type": "string", + "minLength": 6, + "format": "uri", + "description": "The link to the Action source code. Typically a GitHub repository." + }, + "configureParams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false + }, + "description": "An optional list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `configure` function." + }, + "executeParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `execute` function." + }, + "setDisabledParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/configureParams/items" + }, + "description": "An optional list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `setDisabledParams` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "executeParams" + ], + "additionalProperties": false + }, + "signature": { + "type": "string", + "minLength": 1, + "description": "A cryptographic signature of the Lens metadata." + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false, + "$defs": { + "NonEmptyString": { + "type": "string", + "minLength": 1 + }, + "MetadataAttribute": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Boolean" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "enum": [ + "true", + "false" + ], + "description": "A JS boolean value serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Date" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "format": "date-time", + "description": "A valid ISO 8601 date string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Number" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A valid JS number serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "String" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "Any string value." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "JSON" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A JSON string. It's consumer responsibility to validate and parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + } + ] + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/jsonschemas/posts/3d/3.0.0.json b/jsonschemas/posts/3d/3.0.0.json index 4e8a7ab..08d85e3 100644 --- a/jsonschemas/posts/3d/3.0.0.json +++ b/jsonschemas/posts/3d/3.0.0.json @@ -196,39 +196,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -257,14 +224,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -632,23 +591,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/article/3.0.0.json b/jsonschemas/posts/article/3.0.0.json index 0da99c8..fce0145 100644 --- a/jsonschemas/posts/article/3.0.0.json +++ b/jsonschemas/posts/article/3.0.0.json @@ -157,39 +157,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -218,14 +185,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -593,23 +552,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/audio/3.0.0.json b/jsonschemas/posts/audio/3.0.0.json index 534b840..c11d283 100644 --- a/jsonschemas/posts/audio/3.0.0.json +++ b/jsonschemas/posts/audio/3.0.0.json @@ -161,39 +161,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -222,14 +189,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -597,23 +556,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/checking-in/3.0.0.json b/jsonschemas/posts/checking-in/3.0.0.json index 84bfd23..a5c773e 100644 --- a/jsonschemas/posts/checking-in/3.0.0.json +++ b/jsonschemas/posts/checking-in/3.0.0.json @@ -166,39 +166,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -227,14 +194,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -602,23 +561,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/embed/3.0.0.json b/jsonschemas/posts/embed/3.0.0.json index e0d09ad..16d72c6 100644 --- a/jsonschemas/posts/embed/3.0.0.json +++ b/jsonschemas/posts/embed/3.0.0.json @@ -158,39 +158,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -219,14 +186,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -594,23 +553,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/event/3.0.0.json b/jsonschemas/posts/event/3.0.0.json index 309a93c..2b237e9 100644 --- a/jsonschemas/posts/event/3.0.0.json +++ b/jsonschemas/posts/event/3.0.0.json @@ -647,39 +647,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -708,14 +675,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -1083,23 +1042,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/image/3.0.0.json b/jsonschemas/posts/image/3.0.0.json index acf4764..91fd898 100644 --- a/jsonschemas/posts/image/3.0.0.json +++ b/jsonschemas/posts/image/3.0.0.json @@ -161,39 +161,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -222,14 +189,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -597,23 +556,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/link/3.0.0.json b/jsonschemas/posts/link/3.0.0.json index 155ba40..b46c232 100644 --- a/jsonschemas/posts/link/3.0.0.json +++ b/jsonschemas/posts/link/3.0.0.json @@ -158,39 +158,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -219,14 +186,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -594,23 +553,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/livestream/3.0.0.json b/jsonschemas/posts/livestream/3.0.0.json index d99331d..485b0f3 100644 --- a/jsonschemas/posts/livestream/3.0.0.json +++ b/jsonschemas/posts/livestream/3.0.0.json @@ -181,39 +181,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -242,14 +209,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -617,23 +576,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/mint/3.0.0.json b/jsonschemas/posts/mint/3.0.0.json index d47339e..7df5a49 100644 --- a/jsonschemas/posts/mint/3.0.0.json +++ b/jsonschemas/posts/mint/3.0.0.json @@ -158,39 +158,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -219,14 +186,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -594,23 +553,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/space/3.0.0.json b/jsonschemas/posts/space/3.0.0.json index a6483ce..1bcbf2b 100644 --- a/jsonschemas/posts/space/3.0.0.json +++ b/jsonschemas/posts/space/3.0.0.json @@ -169,39 +169,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -230,14 +197,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -605,23 +564,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/story/3.0.0.json b/jsonschemas/posts/story/3.0.0.json index 94707a8..999f424 100644 --- a/jsonschemas/posts/story/3.0.0.json +++ b/jsonschemas/posts/story/3.0.0.json @@ -150,39 +150,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -211,14 +178,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -586,23 +545,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/text-only/3.0.0.json b/jsonschemas/posts/text-only/3.0.0.json index 40dd736..44832ee 100644 --- a/jsonschemas/posts/text-only/3.0.0.json +++ b/jsonschemas/posts/text-only/3.0.0.json @@ -145,39 +145,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -206,14 +173,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -581,23 +540,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/transaction/3.0.0.json b/jsonschemas/posts/transaction/3.0.0.json index f9ff96d..338e21b 100644 --- a/jsonschemas/posts/transaction/3.0.0.json +++ b/jsonschemas/posts/transaction/3.0.0.json @@ -173,39 +173,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -234,14 +201,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -609,23 +568,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/posts/video/3.0.0.json b/jsonschemas/posts/video/3.0.0.json index ac5e121..797fc8d 100644 --- a/jsonschemas/posts/video/3.0.0.json +++ b/jsonschemas/posts/video/3.0.0.json @@ -164,39 +164,6 @@ "format": "uri", "description": "A Uniform Resource Identifier." }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -225,14 +192,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "MarketplaceMetadataAttribute": { "type": "object", "properties": { @@ -600,23 +559,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { diff --git a/jsonschemas/schema.json b/jsonschemas/schema.json index d6ae321..f32cfa8 100644 --- a/jsonschemas/schema.json +++ b/jsonschemas/schema.json @@ -81,39 +81,6 @@ "SPACE" ] }, - "Amount": { - "type": "object", - "properties": { - "asset": { - "type": "object", - "properties": { - "contract": { - "$ref": "#/$defs/NetworkAddress" - }, - "decimals": { - "type": "integer", - "minimum": 0, - "description": "The number of decimals of the asset." - } - }, - "required": [ - "contract", - "decimals" - ], - "additionalProperties": false - }, - "value": { - "$ref": "#/$defs/NonEmptyString", - "description": "The amount in the smallest unit of the given asset (e.g. wei for ETH)." - } - }, - "required": [ - "asset", - "value" - ], - "additionalProperties": false, - "description": "An amount of a specific asset." - }, "AnyMedia": { "anyOf": [ { @@ -142,14 +109,6 @@ "pattern": "^geo:(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*)$", "description": "A Geographic coordinate as subset of Geo URI (RFC 5870). Currently only supports the `geo:lat,lng` format." }, - "LegacyProfileId": { - "type": "string", - "minLength": 4 - }, - "LegacyPublicationId": { - "type": "string", - "minLength": 9 - }, "Locale": { "type": "string", "pattern": "^[a-z]{2}(?:-[a-zA-Z]{2})?$", @@ -526,23 +485,6 @@ "TBNL-NC-ND-NPL-Ledger" ] }, - "NetworkAddress": { - "type": "object", - "properties": { - "chainId": { - "$ref": "#/$defs/ChainId" - }, - "address": { - "$ref": "#/$defs/EvmAddress" - } - }, - "required": [ - "chainId", - "address" - ], - "additionalProperties": false, - "description": "An EVM compatible address on a specific chain." - }, "PhysicalAddress": { "type": "object", "properties": { @@ -3295,68 +3237,6 @@ ], "additionalProperties": false }, - "ModuleMetadata": { - "type": "object", - "properties": { - "name": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "The name of the module." - }, - "title": { - "$ref": "#/$defs/NonEmptyString", - "description": "The human-friendly title for the module." - }, - "description": { - "$ref": "#/$defs/NonEmptyString", - "description": "Markdown formatted description of the module." - }, - "authors": { - "type": "array", - "items": { - "type": "string", - "format": "email" - }, - "minItems": 1, - "description": "List of authors email addresses." - }, - "initializeCalldataABI": { - "type": "string", - "description": "The Solidity JSON ABI as JSON-string describing the initialization function calldata." - }, - "initializeResultDataABI": { - "type": "string", - "description": "The Solidity JSON ABI as JSON-string describing the initialization result data." - }, - "processCalldataABI": { - "type": "string", - "description": "The Solidity JSON ABI as JSON-string describing the process function calldata." - }, - "attributes": { - "type": "array", - "items": { - "$ref": "#/$defs/MetadataAttribute" - }, - "description": "An arbitrary bag of attributes." - }, - "$schema": { - "type": "string", - "const": "https://json-schemas.lens.dev/modules/1.0.0.json" - } - }, - "required": [ - "name", - "title", - "description", - "authors", - "initializeCalldataABI", - "processCalldataABI", - "attributes", - "$schema" - ], - "additionalProperties": false - }, "AppMetadata": { "type": "object", "properties": { @@ -3676,6 +3556,112 @@ "lens" ], "additionalProperties": false + }, + "ActionMetadata": { + "type": "object", + "properties": { + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/actions/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The name of the Action." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Action." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Action." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "$ref": "#/$defs/URI", + "description": "The link to the Action source code. Typically a GitHub repository." + }, + "configureParams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false + }, + "description": "An optional list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `configure` function." + }, + "executeParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `execute` function." + }, + "setDisabledParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "An optional list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `setDisabledParams` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "executeParams" + ], + "additionalProperties": false + }, + "signature": { + "$ref": "#/$defs/Signature", + "description": "A cryptographic signature of the Lens metadata." + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/package.json b/package.json index 8388e6a..04b527d 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ }, "packageManager": "pnpm@8.15.9", "dependencies": { + "abitype": "^1.0.8", "json-stable-stringify": "^1.1.1", "uuid": "^9.0.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 006ed94..11131f8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,6 +9,9 @@ overrides: ethers: ^5.7.2 dependencies: + abitype: + specifier: ^1.0.8 + version: 1.0.8(typescript@5.1.6)(zod@3.23.8) json-stable-stringify: specifier: ^1.1.1 version: 1.1.1 @@ -1710,6 +1713,21 @@ packages: tinyrainbow: 1.2.0 dev: true + /abitype@1.0.8(typescript@5.1.6)(zod@3.23.8): + resolution: {integrity: sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + dependencies: + typescript: 5.1.6 + zod: 3.23.8 + dev: false + /acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} @@ -4201,7 +4219,6 @@ packages: resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} engines: {node: '>=14.17'} hasBin: true - dev: true /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} @@ -4578,4 +4595,3 @@ packages: /zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - dev: true diff --git a/scripts/build.ts b/scripts/build.ts index 62bbd17..0697fb3 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -8,6 +8,7 @@ import { zodToJsonSchema } from 'zod-to-json-schema'; import { AccountMetadataSchema, + ActionMetadataSchema, AnyMediaSchema, AppMetadataSchema, ArticleSchema, @@ -34,7 +35,6 @@ import { MetadataIdSchema, MetadataLicenseTypeSchema, MintSchema, - ModuleMetadataSchema, Nft721MetadataAttributeSchema, NonEmptyStringSchema, PhysicalAddressSchema, @@ -139,12 +139,12 @@ for (const [path, Schema] of others) { await fs.writeJSON(outputFile, jsonSchema, { spaces: 2 }); } -// Module schema -const openActions = new Map>([ - ['module/1.0.0.json', ModuleMetadataSchema], +// Modules schemas +const modules = new Map>([ + ['action/1.0.0.json', ActionMetadataSchema], ]); -for (const [path, Schema] of openActions) { +for (const [path, Schema] of modules) { const outputFile = join(outputDir, path); await fs.ensureFile(outputFile); @@ -207,13 +207,13 @@ async function generateUmbrellaSchema() { ThreeDMetadata: ThreeDSchema, VideoMetadata: VideoSchema, AccountMetadata: AccountMetadataSchema, - ModuleMetadata: ModuleMetadataSchema, AppMetadata: AppMetadataSchema, GraphMetadata: GraphMetadataSchema, FeedMetadata: FeedMetadataSchema, GroupMetadata: GroupMetadataSchema, SponsorshipMetadata: SponsorshipMetadataSchema, UsernameMetadata: UsernameMetadataSchema, + ActionMetadata: ActionMetadataSchema, }, }); diff --git a/src/__tests__/primitives.spec.ts b/src/__tests__/primitives.spec.ts index c67fd6f..53e63f0 100644 --- a/src/__tests__/primitives.spec.ts +++ b/src/__tests__/primitives.spec.ts @@ -3,9 +3,11 @@ import { z } from 'zod'; import { expectResult } from '../__helpers__/assertions.js'; import { + Bytes32Schema, DateTimeSchema, GeoURISchema, LocaleSchema, + SolidityParametersSchema, geoPoint, geoUri, nonEmptySchema, @@ -170,4 +172,87 @@ describe('Given the primitives schemas', () => { expect(geoUri({ lat: 42.42, lng: -42.42 })).toMatchInlineSnapshot(`"geo:42.42,-42.42"`); }); }); + + describe('when parsing a Bytes32 string', () => { + it('then it should validate a string of 32 bytes', () => { + const valid = ['0x0ee423f45485fc56aebfc81a59082f66df211a1d77ca90757a2ee48cbe207fa1']; + + for (const value of valid) { + expectResult(() => Bytes32Schema.safeParse(value)).toEqual(value); + } + }); + + it('then it should flag invalid strings', () => { + expectResult(() => Bytes32Schema.safeParse('nonhexstring')).toMatchInlineSnapshot(` + "fix the following issues + String must contain exactly 66 character(s) + Should be a 32 bytes long hexadecimal string." + `); + + expectResult(() => Bytes32Schema.safeParse('0x')).toMatchInlineSnapshot(` + "fix the following issues + String must contain exactly 66 character(s) + Should be a 32 bytes long hexadecimal string." + `); + + expectResult(() => + Bytes32Schema.safeParse( + '0x0ee423f45485fc56aebfc81a59082f66df211a1d77ca90757a2ee48cbe207fa1a', + ), + ).toMatchInlineSnapshot(` + "fix the following issues + String must contain exactly 66 character(s) + Should be a 32 bytes long hexadecimal string." + `); + }); + }); + + describe('when parsing an ABI parameters string', () => { + it('then it should validate a string containing expected human-readable ABI parameters', () => { + const valid = [ + // simple + 'address', + 'uint256', + 'bytes', + 'bool', + 'string', + + // named + 'address foo', + 'uint256 foo', + 'bytes foo', + 'bool foo', + 'string foo', + + // arrays + 'address[]', + 'uint256[]', + 'bytes[]', + 'bool[]', + 'string[]', + + // named arrays + 'address[] foo', + 'uint256[] foo', + 'bytes[] foo', + 'bool[] foo', + 'string[] foo', + + // multiples + 'address, address', + 'address, uint256', + 'address, bytes', + + // tuples + '(address, address, uint256)', + '(address, (address, uint256))', + '(address source, (address addr, uint256 value) destination)', + '(address from, address to, uint256 amount), uint256', + ]; + + for (const value of valid) { + expectResult(() => SolidityParametersSchema.safeParse(value)).toEqual(value); + } + }); + }); }); diff --git a/src/action/ActionMetadataSchema.ts b/src/action/ActionMetadataSchema.ts new file mode 100644 index 0000000..13a86f4 --- /dev/null +++ b/src/action/ActionMetadataSchema.ts @@ -0,0 +1,133 @@ +import { z } from 'zod'; + +import { + type ContractKeyValuePairDescriptor, + ContractKeyValuePairDescriptorSchema, + type Markdown, + MarkdownSchema, + NonEmptyStringSchema, + type Signature, + SignatureSchema, + type URI, + URISchema, +} from '../primitives'; +import { ActionMetadataSchemaId } from './ActionMetadataSchemaId'; + +export type ActionMetadataDetails = { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure. + */ + id: string; + /** + * The name of the Action. + */ + name: string; + /** + * The human-friendly title for the Action. + */ + title: string; + /** + * Markdown formatted description of the Action. + * + * It should explain what this Action does, how to use it, examples just + * like you would if you were building an NPM package. + * The more detail the better to allow dApp to easily integrate it. + */ + description: Markdown; + /** + * List of authors email addresses. + */ + authors: string[]; + /** + * The link to the Action source code. Typically a GitHub repository. + */ + source: URI; + /** + * An optional list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `configure` function. + * + * ```sol + * function configure(address originalMsgSender, address feed, uint256 postId, KeyValue[] calldata params) + * external + * returns (bytes memory); + * ``` + * + * This will be used to know how to encode and decode the params for the `configuration` function. + * + * @see https://abitype.dev/api/human + */ + configureParams?: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `execute` function. + * + * ```sol + * function execute(address originalMsgSender, address feed, uint256 postId, KeyValue[] calldata params) + * external + * returns (bytes memory); + * ``` + * + * This will be used to know how to encode the calldata for the `execute` function. + */ + executeParams?: ContractKeyValuePairDescriptor[]; + /** + * An optional list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `setDisabledParams` function. + * + * ```sol + * function setDisabled( + * address originalMsgSender, + * address feed, + * uint256 postId, + * bool isDisabled, + * KeyValue[] calldata params + * ) external returns (bytes memory); + * ``` + * + * This will be used to know how to encode the calldata for the `setDisabled` function. + */ + setDisabledParams?: ContractKeyValuePairDescriptor[]; +}; + +const ActionMetadataDetailsSchema: z.ZodType = + z.object({ + id: NonEmptyStringSchema.describe( + 'A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure.', + ), + name: NonEmptyStringSchema.describe('The name of the Action.'), + title: NonEmptyStringSchema.describe('The human-friendly title for the Action.'), + description: MarkdownSchema.describe('Markdown formatted description of the Action.'), + authors: z + .array(z.string().email('Authors list should only contain valid emails')) + .min(1, 'You must supply at least one author') + .describe('List of authors email addresses.'), + source: URISchema.describe( + 'The link to the Action source code. Typically a GitHub repository.', + ), + configureParams: z + .array(ContractKeyValuePairDescriptorSchema) + .optional() + .describe( + 'An optional list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `configure` function.', + ), + executeParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `execute` function.', + ), + setDisabledParams: z + .array(ContractKeyValuePairDescriptorSchema) + .optional() + .describe( + 'An optional list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `setDisabledParams` function.', + ), + }); + +export type ActionMetadata = { + $schema: ActionMetadataSchemaId.LATEST; + lens: ActionMetadataDetails; + signature?: Signature; +}; + +export const ActionMetadataSchema: z.ZodType = z.object({ + $schema: z.literal(ActionMetadataSchemaId.LATEST), + lens: ActionMetadataDetailsSchema, + signature: SignatureSchema.optional(), +}); diff --git a/src/action/ActionMetadataSchemaId.ts b/src/action/ActionMetadataSchemaId.ts new file mode 100644 index 0000000..6f02634 --- /dev/null +++ b/src/action/ActionMetadataSchemaId.ts @@ -0,0 +1,8 @@ +import { SchemasRoot } from '../constants'; + +/** + * The Lens Action metadata schema id. + */ +export enum ActionMetadataSchemaId { + LATEST = `${SchemasRoot}/actions/1.0.0.json`, +} diff --git a/src/action/index.ts b/src/action/index.ts new file mode 100644 index 0000000..a0125d2 --- /dev/null +++ b/src/action/index.ts @@ -0,0 +1,2 @@ +export * from './ActionMetadataSchemaId'; +export * from './ActionMetadataSchema'; diff --git a/src/builders/__tests__/__snapshots__/action.spec.ts.snap b/src/builders/__tests__/__snapshots__/action.spec.ts.snap new file mode 100644 index 0000000..e5a57e5 --- /dev/null +++ b/src/builders/__tests__/__snapshots__/action.spec.ts.snap @@ -0,0 +1,53 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Given the "action" metadata builder > when using it > should return a valid AccountMetadata 1`] = ` +{ + "$schema": "https://json-schemas.lens.dev/actions/1.0.0.json", + "lens": { + "authors": [ + "awesome-dev@lens.xyz", + ], + "configureParams": [ + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "account", + "type": "address", + }, + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "recipients", + "type": "address[]", + }, + ], + "description": "Get ready for the future of social interaction!", + "executeParams": [ + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "amount", + "type": "uint256", + }, + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "recipients", + "type": "(address, uint256)[]", + }, + ], + "id": Any, + "name": "My Open Action", + "setDisabledParams": [ + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "amount", + "type": "uint256", + }, + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "recipients", + "type": "(address, uint256)[]", + }, + ], + "source": "https://github.com/foobarbaz/my-open-action", + "title": "This is my Open Action", + }, +} +`; diff --git a/src/builders/__tests__/__snapshots__/modules.spec.ts.snap b/src/builders/__tests__/__snapshots__/modules.spec.ts.snap deleted file mode 100644 index 9e6c2c0..0000000 --- a/src/builders/__tests__/__snapshots__/modules.spec.ts.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`Given the "module" metadata builder > when using it > should return a valid OpenActionMetadata 1`] = ` -{ - "$schema": "https://json-schemas.lens.dev/modules/1.0.0.json", - "attributes": [ - { - "key": "twitter", - "type": "String", - "value": "https://twitter.com/johndoe", - }, - { - "key": "dob", - "type": "String", - "value": "1990-01-01T00:00:00Z", - }, - ], - "authors": [ - "me@lens.xyz", - ], - "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. - - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. - - Donec a diam lectus.", - "initializeCalldataABI": "[{"type":"address","name":"address","indexed":true},{"type":"uint256","name":"price","indexed":true}]", - "name": "Open Action Name", - "processCalldataABI": "[{"type":"address","name":"collector","indexed":true}]", - "title": "Open Action Title", -} -`; diff --git a/src/builders/__tests__/action.spec.ts b/src/builders/__tests__/action.spec.ts new file mode 100644 index 0000000..13393d8 --- /dev/null +++ b/src/builders/__tests__/action.spec.ts @@ -0,0 +1,59 @@ +import { describe, expect, it } from 'vitest'; + +import { action } from '../action.js'; + +describe(`Given the "${action.name}" metadata builder`, () => { + describe('when using it', () => { + it('should return a valid AccountMetadata', () => { + const metadata = action({ + name: 'My Open Action', + title: 'This is my Open Action', + description: 'Get ready for the future of social interaction!', + authors: ['awesome-dev@lens.xyz'], + source: 'https://github.com/foobarbaz/my-open-action', + configureParams: [ + { + key: '0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49', + name: 'account', + type: 'address', + }, + { + key: '0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49', + name: 'recipients', + type: 'address[]', + }, + ], + executeParams: [ + { + key: '0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49', + name: 'amount', + type: 'uint256', + }, + { + key: '0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49', + name: 'recipients', + type: '(address, uint256)[]', + }, + ], + setDisabledParams: [ + { + key: '0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49', + name: 'amount', + type: 'uint256', + }, + { + key: '0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49', + name: 'recipients', + type: '(address, uint256)[]', + }, + ], + }); + + expect(metadata).toMatchSnapshot({ + lens: { + id: expect.any(String), + }, + }); + }); + }); +}); diff --git a/src/builders/__tests__/modules.spec.ts b/src/builders/__tests__/modules.spec.ts deleted file mode 100644 index 8511126..0000000 --- a/src/builders/__tests__/modules.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { describe, expect, it } from 'vitest'; - -import { MetadataAttributeType } from '../../MetadataAttribute.js'; -import { module } from '../modules.js'; - -describe(`Given the "${module.name}" metadata builder`, () => { - describe('when using it', () => { - it('should return a valid OpenActionMetadata', () => { - const metadata = module({ - name: 'Open Action Name', - title: 'Open Action Title', - authors: ['me@lens.xyz'], - attributes: [ - { - key: 'twitter', - type: MetadataAttributeType.STRING, - value: 'https://twitter.com/johndoe', - }, - { - key: 'dob', - type: MetadataAttributeType.STRING, - value: '1990-01-01T00:00:00Z', - }, - ], - description: ` - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. - - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. - - Donec a diam lectus. - `, - initializeCalldataABI: JSON.stringify([ - { - type: 'address', - name: 'address', - indexed: true, - }, - { - type: 'uint256', - name: 'price', - indexed: true, - }, - ]), - processCalldataABI: JSON.stringify([ - { - type: 'address', - name: 'collector', - indexed: true, - }, - ]), - }); - - expect(metadata).toMatchSnapshot(); - }); - }); -}); diff --git a/src/builders/action.ts b/src/builders/action.ts new file mode 100644 index 0000000..0b58e32 --- /dev/null +++ b/src/builders/action.ts @@ -0,0 +1,67 @@ +import { v4 } from 'uuid'; + +import { + type ActionMetadata, + type ActionMetadataDetails, + ActionMetadataSchema, + ActionMetadataSchemaId, +} from '../action/index.js'; +import type { Prettify } from '../utils.js'; +import { evaluate } from './ValidationError'; +import type { RecursiveUnbrand } from './utils'; + +/** + * @private + * @privateRemarks MUST stay very @private to produce usable docs + */ +type ActionDetails = Prettify>>; + +export type ActionOptions = ActionDetails & { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. + * + * @defaultValue a UUID + */ + id?: string; +}; + +/** + * Creates a valid ActionMetadata. + * + * @category Compose + * @param input - Use your IDE suggestions for an enhanced development experience + * + * @example + * ```ts + * const metadata = action({ + * name: 'My Open Action', + * title: 'This is my Open Action', + * description: 'Get ready for the future of social interaction!', + * authors: ['awesome-dev@lens.xyz'], + * source: 'https://github.com/foobarbaz/my-open-action', + * executeParams: [ + * { + * key: '83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95', + * name: 'recipient', + * type: 'address', + * }, + * { + * key: 'e4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99', + * name: 'amount', + * type: 'address token, uint256 value', + * } + * ] + * }); + * ``` + */ +export function action({ id = v4(), ...others }: ActionOptions): ActionMetadata { + return evaluate( + ActionMetadataSchema.safeParse({ + $schema: ActionMetadataSchemaId.LATEST, + lens: { + id, + ...others, + }, + }), + ); +} diff --git a/src/builders/index.ts b/src/builders/index.ts index 291dde0..f87940e 100644 --- a/src/builders/index.ts +++ b/src/builders/index.ts @@ -1,9 +1,9 @@ +export * from './action.js'; export * from './account.js'; export * from './app.js'; export * from './feed.js'; export * from './graph.js'; export * from './group.js'; -export * from './modules.js'; export * from './posts.js'; export * from './sponsorship.js'; export * from './username.js'; diff --git a/src/builders/modules.ts b/src/builders/modules.ts deleted file mode 100644 index 2612e69..0000000 --- a/src/builders/modules.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { MetadataAttribute } from '../MetadataAttribute'; -import { type ModuleMetadata, ModuleMetadataSchema, ModuleSchemaId } from '../module'; -import type { Prettify } from '../utils'; -import { evaluate } from './ValidationError'; -import type { RecursiveUnbrand } from './utils'; - -/** - * @private - * @privateRemarks MUST stay very @private to produce usable docs - */ -type ModuleDetails = Prettify>>; -/** - * All {@link ModuleMetadata} fields without `$schema` a with: - * - `attributes` defaults to an empty array - */ -export type ModuleOptions = ModuleDetails & { - /** - * An arbitrary bag of attributes you wish to add to the metadata. - */ - attributes?: MetadataAttribute[]; -}; - -/** - * Creates a valid ModuleMetadata. - * - * @category Compose - * @param input - Use your IDE suggestions for an enhanced development experience - * - * @example - * ```ts - * const metadata = module({ - * name: 'My Open Action', - * title: 'This is my Open Action', - * description: 'Get ready for the future of social interaction!', - * authors: ['awesome-dev@lens.xyz'], - * initializeCalldataABI: JSON.stringify([ - * { - * type: 'address', - * name: 'address', - * }, - * { - * type: 'uint256', - * name: 'price', - * }, - * ]), - * processCalldataABI: JSON.stringify([ - * { - * type: 'address', - * name: 'collector', - * }, - * ]), - * }); - * ``` - */ -export function module({ attributes = [], ...others }: ModuleOptions): ModuleMetadata { - return evaluate( - ModuleMetadataSchema.safeParse({ - $schema: ModuleSchemaId.LATEST, - attributes, - ...others, - }), - ); -} diff --git a/src/index.ts b/src/index.ts index 32c9c0b..966e6e1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +export * from './action/index.js'; export * from './account/index.js'; export * from './app/index.js'; export * from './builders/index.js'; @@ -7,7 +8,6 @@ export * from './feed/index.js'; export * from './formatters.js'; export * from './graph/index.js'; export * from './MetadataAttribute.js'; -export * from './module/index.js'; export * from './post/index.js'; export * from './primitives.js'; export * from './signMetadata.js'; diff --git a/src/module/ModuleMetadataSchema.ts b/src/module/ModuleMetadataSchema.ts deleted file mode 100644 index 8435ac7..0000000 --- a/src/module/ModuleMetadataSchema.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { z } from 'zod'; - -import { type MetadataAttribute, MetadataAttributeSchema } from '../MetadataAttribute'; -import { type Markdown, MarkdownSchema, NonEmptyStringSchema, nonEmptySchema } from '../primitives'; -import { ModuleSchemaId } from './ModuleSchemaId'; - -function isValidJsonString(str: string) { - try { - JSON.parse(str); - } catch (e) { - return false; - } - return true; -} - -function jsonString(description: string) { - return z.string({ description }).refine(isValidJsonString, { message: 'Invalid JSON string' }); -} - -/** - * The metadata standard for Lens Modules - */ -export type ModuleMetadata = { - /** - * The name of the module. - */ - name: string; - /** - * The human-friendly title for the module. - */ - title: string; - /** - * Markdown formatted description of the module. - * - * It should explain what this module does, how to use it, examples just - * like you would if you were building an NPM package. - * The more detail the better to allow dApp to easily integrate it. - */ - description: Markdown; - /** - * List of authors email addresses. - */ - authors: string[]; - /** - * The Solidity JSON ABI as JSON-string describing the initialization function calldata. - * - * This will be used to encode the calldata for the initialization function. - * - * It will also be used by the consumers of this module to decode the initialization - * calldata so to infer the initialization criteria. - */ - initializeCalldataABI: string; - /** - * The Solidity JSON ABI as JSON-string describing the initialization result data. - * - * This will be used by the consumers of this module to decode - * the result data from the initialization function so to infer the - * initialization result state. - */ - initializeResultDataABI?: string; - /** - * The Solidity JSON ABI as JSON-string describing the process function calldata. - * - * This will be used to encode the calldata for the process function. - * - * Some modules might non need to return any initialization result data. - */ - processCalldataABI: string; - /** - * An arbitrary bag of attributes you wish to add to the metadata. - */ - attributes: MetadataAttribute[]; - /** - * The schema ID. - */ - $schema: ModuleSchemaId.LATEST; -}; - -export const ModuleMetadataSchema: z.ZodType = z.object({ - name: nonEmptySchema(z.string().max(200)).describe('The name of the module.'), - title: NonEmptyStringSchema.describe('The human-friendly title for the module.'), - description: MarkdownSchema.describe('Markdown formatted description of the module.'), - authors: z - .array(z.string().email('Authors list should only contain valid emails')) - .min(1, 'You must supply at least one author') - .describe('List of authors email addresses.'), - initializeCalldataABI: jsonString( - 'The Solidity JSON ABI as JSON-string describing the initialization function calldata.', - ), - initializeResultDataABI: jsonString( - 'The Solidity JSON ABI as JSON-string describing the initialization result data.', - ).optional(), - processCalldataABI: jsonString( - 'The Solidity JSON ABI as JSON-string describing the process function calldata.', - ), - attributes: z.array(MetadataAttributeSchema).describe('An arbitrary bag of attributes.'), - $schema: z.literal(ModuleSchemaId.LATEST), -}); diff --git a/src/module/ModuleSchemaId.ts b/src/module/ModuleSchemaId.ts deleted file mode 100644 index 893209a..0000000 --- a/src/module/ModuleSchemaId.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SchemasRoot } from '../constants'; - -export enum ModuleSchemaId { - LATEST = `${SchemasRoot}/modules/1.0.0.json`, -} diff --git a/src/module/index.ts b/src/module/index.ts deleted file mode 100644 index 56fda56..0000000 --- a/src/module/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './ModuleMetadataSchema.js'; -export * from './ModuleSchemaId.js'; diff --git a/src/primitives.ts b/src/primitives.ts index edaad74..0c01f1c 100644 --- a/src/primitives.ts +++ b/src/primitives.ts @@ -1,5 +1,6 @@ import { z } from 'zod'; +import { BaseError, formatAbiParameters, parseAbiParameters } from 'abitype'; import { formatZodError } from './formatters.js'; import { type Brand, invariant, never } from './utils.js'; @@ -398,3 +399,104 @@ export const ChainIdSchema: z.ZodType = z .number() .positive() .transform(toChainId); + +/** + * A 32 bytes long hexadecimal string. + */ +export type Bytes32 = Brand; + +function toBytes32(value: string): Bytes32 { + return value as Bytes32; +} +/** + * @internal + */ +export const Bytes32Schema: z.ZodType = z + .string() + .length(66) + .regex(/^0x[0-9a-fA-F]{64}$/, 'Should be a 32 bytes long hexadecimal string.') + .transform(toBytes32); + +/** + * A human-readable ABI of Solidity parameters. + * - address + * - array + * - bool + * - bytes + * - int + * - string + * or tuples of the above. + * + * @example + * ```ts + * 'address' + * 'address[]' + * 'address, address, uint256' + * 'address from, address to, uint256 amount' + * '(address from, address to, uint256 amount), uint256' + * ``` + */ +export type SolidityParameters = Brand; + +/** + * @internal + */ +export const SolidityParametersSchema: z.ZodType = z + .string() + .superRefine((val, ctx): val is SolidityParameters => { + try { + // biome-ignore lint/suspicious/noExplicitAny: + const formatted = formatAbiParameters(parseAbiParameters(val) as any); + if (formatted !== val) { + ctx.addIssue({ + message: `Should be a valid Solidity ABI parameters string. Expected: \`${formatted}\`.`, + code: z.ZodIssueCode.custom, + }); + } + } catch (err) { + if (err instanceof BaseError && err.metaMessages) { + for (const message of err.metaMessages) { + ctx.addIssue({ + message: message, + code: z.ZodIssueCode.custom, + }); + } + } else { + ctx.addIssue({ + message: String(err), + code: z.ZodIssueCode.custom, + }); + } + } + return z.NEVER; + }); + +export type ContractKeyValuePairDescriptor = { + /** + * A unique 32 bytes long hexadecimal string key. + * + * This could be the keccak256 hash of the parameter name. + */ + key: Bytes32; + /** + * The human-readable name of the parameter. + */ + name: string; + /** + * The human-readable ABI description of the parameter. + */ + type: SolidityParameters; +}; + +/** + * @internal + */ +export const ContractKeyValuePairDescriptorSchema: z.ZodType< + ContractKeyValuePairDescriptor, + z.ZodTypeDef, + object +> = z.object({ + key: Bytes32Schema.describe('A unique 32 bytes long hexadecimal string key.'), + name: NonEmptyStringSchema.describe('The human-readable name of the parameter.'), + type: SolidityParametersSchema.describe('The human-readable ABI description of the parameter.'), +}); From e1fc46532cf7915d1fd0e3835c03df7b993c2a59 Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Tue, 14 Jan 2025 09:20:40 +0100 Subject: [PATCH 04/14] feat: FeedRuleMetadata implementation --- jsonschemas/action/1.0.0.json | 2 +- jsonschemas/rules/feed/1.0.0.json | 250 ++++++++++++++++++ jsonschemas/schema.json | 99 ++++++- scripts/build.ts | 8 + src/action/ActionMetadataSchema.ts | 8 +- .../__snapshots__/action.spec.ts.snap | 52 ++++ .../__snapshots__/rules.spec.ts.snap | 32 +++ src/builders/__tests__/action.spec.ts | 2 +- src/builders/__tests__/rules.spec.ts | 38 +++ src/builders/action.ts | 4 +- src/builders/rules.ts | 70 +++++ src/common.ts | 17 ++ src/rule/FeedRuleMetadataSchema.ts | 161 +++++++++++ src/rule/RuleMetadataSchemaId.ts | 13 + src/rule/index.ts | 16 ++ tsconfig.json | 4 +- 16 files changed, 767 insertions(+), 9 deletions(-) create mode 100644 jsonschemas/rules/feed/1.0.0.json create mode 100644 src/builders/__tests__/__snapshots__/rules.spec.ts.snap create mode 100644 src/builders/__tests__/rules.spec.ts create mode 100644 src/builders/rules.ts create mode 100644 src/common.ts create mode 100644 src/rule/FeedRuleMetadataSchema.ts create mode 100644 src/rule/RuleMetadataSchemaId.ts create mode 100644 src/rule/index.ts diff --git a/jsonschemas/action/1.0.0.json b/jsonschemas/action/1.0.0.json index ae87474..108d2ec 100644 --- a/jsonschemas/action/1.0.0.json +++ b/jsonschemas/action/1.0.0.json @@ -14,7 +14,7 @@ }, "name": { "$ref": "#/$defs/NonEmptyString", - "description": "The name of the Action." + "description": "A short name for the Action." }, "title": { "$ref": "#/$defs/NonEmptyString", diff --git a/jsonschemas/rules/feed/1.0.0.json b/jsonschemas/rules/feed/1.0.0.json new file mode 100644 index 0000000..3bb8c5d --- /dev/null +++ b/jsonschemas/rules/feed/1.0.0.json @@ -0,0 +1,250 @@ +{ + "type": "object", + "properties": { + "signature": { + "type": "string", + "minLength": 1, + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/feed/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "type": "string", + "minLength": 6, + "format": "uri", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processCreatePostParams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processCreatePost` function." + }, + "processEditPostParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processCreatePostParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processEditPost` function." + }, + "processRemovePostParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processCreatePostParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processRemovePost` function." + }, + "processPostRuleChangesParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processCreatePostParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processPostRuleChanges` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processCreatePostParams", + "processEditPostParams", + "processRemovePostParams", + "processPostRuleChangesParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false, + "$defs": { + "NonEmptyString": { + "type": "string", + "minLength": 1 + }, + "MetadataAttribute": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Boolean" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "enum": [ + "true", + "false" + ], + "description": "A JS boolean value serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Date" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "format": "date-time", + "description": "A valid ISO 8601 date string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Number" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A valid JS number serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "String" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "Any string value." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "JSON" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A JSON string. It's consumer responsibility to validate and parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + } + ] + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/jsonschemas/schema.json b/jsonschemas/schema.json index f32cfa8..e535026 100644 --- a/jsonschemas/schema.json +++ b/jsonschemas/schema.json @@ -3573,7 +3573,7 @@ }, "name": { "$ref": "#/$defs/NonEmptyString", - "description": "The name of the Action." + "description": "A short name for the Action." }, "title": { "$ref": "#/$defs/NonEmptyString", @@ -3662,6 +3662,103 @@ "lens" ], "additionalProperties": false + }, + "RuleMetadata": { + "anyOf": [ + { + "type": "object", + "properties": { + "signature": { + "$ref": "#/$defs/Signature", + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/feed/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "$ref": "#/$defs/URI", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processCreatePostParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processCreatePost` function." + }, + "processEditPostParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processEditPost` function." + }, + "processRemovePostParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processRemovePost` function." + }, + "processPostRuleChangesParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processPostRuleChanges` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processCreatePostParams", + "processEditPostParams", + "processRemovePostParams", + "processPostRuleChangesParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false + } + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/scripts/build.ts b/scripts/build.ts index 0697fb3..c57ec06 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -52,6 +52,7 @@ import { UsernameMetadataSchema, VideoSchema, } from '../src'; +import { FeedRuleMetadataSchema, RuleMetadataSchema } from '../src/rule'; const outputDir = 'jsonschemas'; @@ -142,6 +143,7 @@ for (const [path, Schema] of others) { // Modules schemas const modules = new Map>([ ['action/1.0.0.json', ActionMetadataSchema], + ['rules/feed/1.0.0.json', FeedRuleMetadataSchema], ]); for (const [path, Schema] of modules) { @@ -191,6 +193,7 @@ async function generateUmbrellaSchema() { ContentWarning: ContentWarningSchema, Signature: SignatureSchema, Tag: TagSchema, + // Post schemas ArticleMetadata: ArticleSchema, AudioMetadata: AudioSchema, CheckingInMetadata: CheckingInSchema, @@ -206,14 +209,19 @@ async function generateUmbrellaSchema() { TransactionMetadata: TransactionSchema, ThreeDMetadata: ThreeDSchema, VideoMetadata: VideoSchema, + // Account schemas AccountMetadata: AccountMetadataSchema, + // Primitives schemas AppMetadata: AppMetadataSchema, GraphMetadata: GraphMetadataSchema, FeedMetadata: FeedMetadataSchema, GroupMetadata: GroupMetadataSchema, SponsorshipMetadata: SponsorshipMetadataSchema, UsernameMetadata: UsernameMetadataSchema, + // Actions schemas ActionMetadata: ActionMetadataSchema, + // Rules schemas + RuleMetadata: RuleMetadataSchema, }, }); diff --git a/src/action/ActionMetadataSchema.ts b/src/action/ActionMetadataSchema.ts index 13a86f4..a622306 100644 --- a/src/action/ActionMetadataSchema.ts +++ b/src/action/ActionMetadataSchema.ts @@ -19,7 +19,7 @@ export type ActionMetadataDetails = { */ id: string; /** - * The name of the Action. + * A short name for the Action. */ name: string; /** @@ -66,6 +66,8 @@ export type ActionMetadataDetails = { * ``` * * This will be used to know how to encode the calldata for the `execute` function. + * + * @see https://abitype.dev/api/human */ executeParams?: ContractKeyValuePairDescriptor[]; /** @@ -82,6 +84,8 @@ export type ActionMetadataDetails = { * ``` * * This will be used to know how to encode the calldata for the `setDisabled` function. + * + * @see https://abitype.dev/api/human */ setDisabledParams?: ContractKeyValuePairDescriptor[]; }; @@ -91,7 +95,7 @@ const ActionMetadataDetailsSchema: z.ZodType when using it > should return a v }, } `; + +exports[`Given the "action" metadata builder > when using it > should return a valid ActionMetadata 1`] = ` +{ + "$schema": "https://json-schemas.lens.dev/actions/1.0.0.json", + "lens": { + "authors": [ + "awesome-dev@lens.xyz", + ], + "configureParams": [ + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "account", + "type": "address", + }, + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "recipients", + "type": "address[]", + }, + ], + "description": "Get ready for the future of social interaction!", + "executeParams": [ + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "amount", + "type": "uint256", + }, + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "recipients", + "type": "(address, uint256)[]", + }, + ], + "id": Any, + "name": "My Open Action", + "setDisabledParams": [ + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "amount", + "type": "uint256", + }, + { + "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", + "name": "recipients", + "type": "(address, uint256)[]", + }, + ], + "source": "https://github.com/foobarbaz/my-open-action", + "title": "This is my Open Action", + }, +} +`; diff --git a/src/builders/__tests__/__snapshots__/rules.spec.ts.snap b/src/builders/__tests__/__snapshots__/rules.spec.ts.snap new file mode 100644 index 0000000..4920129 --- /dev/null +++ b/src/builders/__tests__/__snapshots__/rules.spec.ts.snap @@ -0,0 +1,32 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Given the rule metadata builders > when using the feedRule > should return a valid FeedRuleMetadata 1`] = ` +{ + "$schema": "https://json-schemas.lens.dev/rules/feed/1.0.0.json", + "lens": { + "authors": [ + "awesome-dev@lens.xyz", + ], + "description": "Get ready for the future of social interaction!", + "id": Any, + "name": "MyFeedRule", + "processCreatePostParams": [ + { + "key": "0x83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95", + "name": "recipient", + "type": "address", + }, + { + "key": "0xe4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99", + "name": "fee", + "type": "address token, uint256 value", + }, + ], + "processEditPostParams": [], + "processPostRuleChangesParams": [], + "processRemovePostParams": [], + "source": "https://github.com/foobarbaz/my-open-action", + "title": "This is my Feed Rule", + }, +} +`; diff --git a/src/builders/__tests__/action.spec.ts b/src/builders/__tests__/action.spec.ts index 13393d8..e5fa1ff 100644 --- a/src/builders/__tests__/action.spec.ts +++ b/src/builders/__tests__/action.spec.ts @@ -4,7 +4,7 @@ import { action } from '../action.js'; describe(`Given the "${action.name}" metadata builder`, () => { describe('when using it', () => { - it('should return a valid AccountMetadata', () => { + it('should return a valid ActionMetadata', () => { const metadata = action({ name: 'My Open Action', title: 'This is my Open Action', diff --git a/src/builders/__tests__/rules.spec.ts b/src/builders/__tests__/rules.spec.ts new file mode 100644 index 0000000..a633518 --- /dev/null +++ b/src/builders/__tests__/rules.spec.ts @@ -0,0 +1,38 @@ +import { describe, expect, it } from 'vitest'; + +import { feedRule } from '../rules.js'; + +describe('Given the rule metadata builders', () => { + describe(`when using the ${feedRule.name}`, () => { + it('should return a valid FeedRuleMetadata', () => { + const metadata = feedRule({ + name: 'MyFeedRule', + title: 'This is my Feed Rule', + description: 'Get ready for the future of social interaction!', + authors: ['awesome-dev@lens.xyz'], + source: 'https://github.com/foobarbaz/my-open-action', + processCreatePostParams: [ + { + key: '0x83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95', + name: 'recipient', + type: 'address', + }, + { + key: '0xe4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99', + name: 'fee', + type: 'address token, uint256 value', + }, + ], + processEditPostParams: [], + processRemovePostParams: [], + processPostRuleChangesParams: [], + }); + + expect(metadata).toMatchSnapshot({ + lens: { + id: expect.any(String), + }, + }); + }); + }); +}); diff --git a/src/builders/action.ts b/src/builders/action.ts index 0b58e32..30e01a7 100644 --- a/src/builders/action.ts +++ b/src/builders/action.ts @@ -34,8 +34,8 @@ export type ActionOptions = ActionDetails & { * @example * ```ts * const metadata = action({ - * name: 'My Open Action', - * title: 'This is my Open Action', + * name: 'MyPostAction', + * title: 'This is my Post Open', * description: 'Get ready for the future of social interaction!', * authors: ['awesome-dev@lens.xyz'], * source: 'https://github.com/foobarbaz/my-open-action', diff --git a/src/builders/rules.ts b/src/builders/rules.ts new file mode 100644 index 0000000..4545e65 --- /dev/null +++ b/src/builders/rules.ts @@ -0,0 +1,70 @@ +import { v4 } from 'uuid'; + +import { + type FeedRuleMetadata, + type FeedRuleMetadataDetails, + FeedRuleMetadataSchema, +} from '../rule/FeedRuleMetadataSchema.js'; +import { RuleMetadataSchemaId } from '../rule/RuleMetadataSchemaId.js'; +import type { Prettify } from '../utils.js'; +import { evaluate } from './ValidationError.js'; +import type { RecursiveUnbrand } from './utils.js'; + +/** + * @private + * @privateRemarks MUST stay very @private to produce usable docs + */ +type FeedRuleDetails = Prettify>>; + +export type FeedRuleOptions = FeedRuleDetails & { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. + * + * @defaultValue a UUID + */ + id?: string; +}; + +/** + * Creates a valid FeedRuleMetadata. + * + * @category Compose + * @param input - Use your IDE suggestions for an enhanced development experience + * + * @example + * ```ts + * const metadata = feedRule({ + * name: 'MyFeedRule', + * title: 'This is my Feed Rule', + * description: 'Get ready for the future of social interaction!', + * authors: ['awesome-dev@lens.xyz'], + * source: 'https://github.com/foobarbaz/my-open-action', + * processCreatePostParams: [ + * { + * key: '83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95', + * name: 'recipient', + * type: 'address', + * }, + * { + * key: 'e4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99', + * name: 'fee', + * type: 'address token, uint256 value', + * } + * ], + * processEditPostParams: [], + * processRemovePostParams: [], + * processPostRuleChangesParams: [], + * }); + * ``` + */ +export function feedRule({ id = v4(), ...others }: FeedRuleOptions): FeedRuleMetadata { + return evaluate( + FeedRuleMetadataSchema.safeParse({ + $schema: RuleMetadataSchemaId.FEED_LATEST, + lens: { + id, + ...others, + }, + }), + ); +} diff --git a/src/common.ts b/src/common.ts new file mode 100644 index 0000000..02b04c3 --- /dev/null +++ b/src/common.ts @@ -0,0 +1,17 @@ +import { z } from 'zod'; +import { SignatureSchema } from './primitives'; + +/** + * @internal + */ +export function rootSchema< + Augmentation extends { + $schema: z.ZodLiteral; + lens: z.ZodType; + }, +>(augmentation: Augmentation) { + return z.object({ + signature: SignatureSchema.optional(), + ...augmentation, + }); +} diff --git a/src/rule/FeedRuleMetadataSchema.ts b/src/rule/FeedRuleMetadataSchema.ts new file mode 100644 index 0000000..707e078 --- /dev/null +++ b/src/rule/FeedRuleMetadataSchema.ts @@ -0,0 +1,161 @@ +import { z } from 'zod'; + +import { rootSchema } from '../common'; +import { + type ContractKeyValuePairDescriptor, + ContractKeyValuePairDescriptorSchema, + type Markdown, + MarkdownSchema, + NonEmptyStringSchema, + type Signature, + type URI, + URISchema, +} from '../primitives'; +import { RuleMetadataSchemaId } from './RuleMetadataSchemaId'; + +export type FeedRuleMetadataDetails = { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure. + */ + id: string; + /** + * A short name for the Rule. + */ + name: string; + /** + * The human-friendly title for the Rule. + */ + title: string; + /** + * Markdown formatted description of the Rule. + * + * It should explain what this Rule does, how to use it, examples just + * like you would if you were building an NPM package. + * The more detail the better to allow dApp to easily integrate it. + */ + description: Markdown; + /** + * List of authors email addresses. + */ + authors: string[]; + /** + * The link to the Rule source code. Typically a GitHub repository. + */ + source: URI; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `processCreatePost` function. + * + * ```sol + * function processCreatePost( + * bytes32 configSalt, + * uint256 postId, + * CreatePostParams calldata postParams, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode and decode the params for the `processCreatePost` function. + * + * @see https://abitype.dev/api/human + */ + processCreatePostParams: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `processEditPost` function. + * + * ```sol + * function processEditPost( + * bytes32 configSalt, + * uint256 postId, + * EditPostParams calldata postParams, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode the calldata for the `processEditPost` function. + * + * @see https://abitype.dev/api/human + */ + processEditPostParams: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `processRemovePost` function. + * + * ```sol + * function processRemovePost( + * bytes32 configSalt, + * uint256 postId, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode the calldata for the `processRemovePost` function. + * + * @see https://abitype.dev/api/human + */ + processRemovePostParams: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `processPostRuleChanges` function. + * + * ```sol + * function processPostRuleChanges( + * bytes32 configSalt, + * uint256 postId, + * RuleChange[] calldata ruleChanges, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode the calldata for the `processPostRuleChanges` function. + * + * @see https://abitype.dev/api/human + */ + processPostRuleChangesParams: ContractKeyValuePairDescriptor[]; +}; + +const FeedRuleMetadataDetailsSchema: z.ZodType = + z.object({ + id: NonEmptyStringSchema.describe( + 'A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure.', + ), + name: NonEmptyStringSchema.describe('A short name for the Rule.'), + title: NonEmptyStringSchema.describe('The human-friendly title for the Rule.'), + description: MarkdownSchema.describe('Markdown formatted description of the Rule.'), + authors: z + .array(z.string().email('Authors list should only contain valid emails')) + .min(1, 'You must supply at least one author') + .describe('List of authors email addresses.'), + source: URISchema.describe('The link to the Rule source code. Typically a GitHub repository.'), + processCreatePostParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processCreatePost` function.', + ), + processEditPostParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processEditPost` function.', + ), + processRemovePostParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processRemovePost` function.', + ), + processPostRuleChangesParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processPostRuleChanges` function.', + ), + }); + +export type FeedRuleMetadata = { + $schema: RuleMetadataSchemaId.FEED_LATEST; + lens: FeedRuleMetadataDetails; + signature?: Signature; +}; + +export const FeedRuleMetadataSchema = rootSchema({ + $schema: z.literal(RuleMetadataSchemaId.FEED_LATEST), + lens: FeedRuleMetadataDetailsSchema, +}); diff --git a/src/rule/RuleMetadataSchemaId.ts b/src/rule/RuleMetadataSchemaId.ts new file mode 100644 index 0000000..26422c5 --- /dev/null +++ b/src/rule/RuleMetadataSchemaId.ts @@ -0,0 +1,13 @@ +import { SchemasRoot } from '../constants'; + +/** + * The Lens Rule metadata schema id. + */ +export enum RuleMetadataSchemaId { + FEED_LATEST = `${SchemasRoot}/rules/feed/1.0.0.json`, + GRAPH_LATEST = `${SchemasRoot}/rules/graph/1.0.0.json`, + GROUP_LATEST = `${SchemasRoot}/rules/group/1.0.0.json`, + NAMESPACE_LATEST = `${SchemasRoot}/rules/namespace/1.0.0.json`, + POST_LATEST = `${SchemasRoot}/rules/post/1.0.0.json`, + FOLLOW_LATEST = `${SchemasRoot}/rules/follow/1.0.0.json`, +} diff --git a/src/rule/index.ts b/src/rule/index.ts new file mode 100644 index 0000000..1feed5e --- /dev/null +++ b/src/rule/index.ts @@ -0,0 +1,16 @@ +import { z } from 'zod'; +import { type FeedRuleMetadata, FeedRuleMetadataSchema } from './FeedRuleMetadataSchema.js'; + +export * from './RuleMetadataSchemaId.js'; +export * from './FeedRuleMetadataSchema.js'; + +/** + * @internal + */ +export type RuleMetadata = FeedRuleMetadata; + +/** + * @internal + */ +export const RuleMetadataSchema: z.ZodType = + z.discriminatedUnion('$schema', [FeedRuleMetadataSchema]); diff --git a/tsconfig.json b/tsconfig.json index 64c7165..1ede911 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,11 +18,11 @@ "noUnusedLocals": true, "noUnusedParameters": true, "resolveJsonModule": true, - "strictFunctionTypes": true, "skipLibCheck": true, "strict": true, + "strictFunctionTypes": true, "target": "ESNext", - "types": ["node"] + "types": ["node"], }, "include": ["**/*.ts"], "exclude": ["dist", "node_modules"] From d0426ea17476d412340327fe793bfdc89fa01b5b Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Tue, 14 Jan 2025 09:42:46 +0100 Subject: [PATCH 05/14] feat: GraphRuleMetadata spec --- jsonschemas/action/1.0.0.json | 6 +- jsonschemas/rules/feed/1.0.0.json | 8 +- jsonschemas/rules/graph/1.0.0.json | 242 ++++++++++++++++++ jsonschemas/schema.json | 99 ++++++- scripts/build.ts | 2 + src/action/ActionMetadataSchema.ts | 12 +- .../__snapshots__/action.spec.ts.snap | 52 ---- .../__snapshots__/rules.spec.ts.snap | 32 ++- src/builders/__tests__/rules.spec.ts | 36 ++- src/builders/rules.ts | 63 +++++ src/rule/FeedRuleMetadataSchema.ts | 16 +- src/rule/GraphRuleMetadataSchema.ts | 141 ++++++++++ src/rule/index.ts | 5 +- 13 files changed, 629 insertions(+), 85 deletions(-) create mode 100644 jsonschemas/rules/graph/1.0.0.json create mode 100644 src/rule/GraphRuleMetadataSchema.ts diff --git a/jsonschemas/action/1.0.0.json b/jsonschemas/action/1.0.0.json index 108d2ec..f60a055 100644 --- a/jsonschemas/action/1.0.0.json +++ b/jsonschemas/action/1.0.0.json @@ -67,21 +67,21 @@ ], "additionalProperties": false }, - "description": "An optional list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `configure` function." + "description": "An optional list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `configure` function." }, "executeParams": { "type": "array", "items": { "$ref": "#/properties/lens/properties/configureParams/items" }, - "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `execute` function." + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `execute` function." }, "setDisabledParams": { "type": "array", "items": { "$ref": "#/properties/lens/properties/configureParams/items" }, - "description": "An optional list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `setDisabledParams` function." + "description": "An optional list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `setDisabledParams` function." } }, "required": [ diff --git a/jsonschemas/rules/feed/1.0.0.json b/jsonschemas/rules/feed/1.0.0.json index 3bb8c5d..fecae65 100644 --- a/jsonschemas/rules/feed/1.0.0.json +++ b/jsonschemas/rules/feed/1.0.0.json @@ -72,28 +72,28 @@ ], "additionalProperties": false }, - "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processCreatePost` function." + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreatePost` function." }, "processEditPostParams": { "type": "array", "items": { "$ref": "#/properties/lens/properties/processCreatePostParams/items" }, - "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processEditPost` function." + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processEditPost` function." }, "processRemovePostParams": { "type": "array", "items": { "$ref": "#/properties/lens/properties/processCreatePostParams/items" }, - "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processRemovePost` function." + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemovePost` function." }, "processPostRuleChangesParams": { "type": "array", "items": { "$ref": "#/properties/lens/properties/processCreatePostParams/items" }, - "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processPostRuleChanges` function." + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processPostRuleChanges` function." } }, "required": [ diff --git a/jsonschemas/rules/graph/1.0.0.json b/jsonschemas/rules/graph/1.0.0.json new file mode 100644 index 0000000..79b5761 --- /dev/null +++ b/jsonschemas/rules/graph/1.0.0.json @@ -0,0 +1,242 @@ +{ + "type": "object", + "properties": { + "signature": { + "type": "string", + "minLength": 1, + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/graph/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "type": "string", + "minLength": 6, + "format": "uri", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processFollowParams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollow` function." + }, + "processUnfollowParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processFollowParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processUnfollow` function." + }, + "processFollowRuleChangesParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processFollowParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollowRuleChanges` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processFollowParams", + "processUnfollowParams", + "processFollowRuleChangesParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false, + "$defs": { + "NonEmptyString": { + "type": "string", + "minLength": 1 + }, + "MetadataAttribute": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Boolean" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "enum": [ + "true", + "false" + ], + "description": "A JS boolean value serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Date" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "format": "date-time", + "description": "A valid ISO 8601 date string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Number" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A valid JS number serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "String" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "Any string value." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "JSON" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A JSON string. It's consumer responsibility to validate and parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + } + ] + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/jsonschemas/schema.json b/jsonschemas/schema.json index e535026..650fa83 100644 --- a/jsonschemas/schema.json +++ b/jsonschemas/schema.json @@ -3624,21 +3624,21 @@ ], "additionalProperties": false }, - "description": "An optional list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `configure` function." + "description": "An optional list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `configure` function." }, "executeParams": { "type": "array", "items": { "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" }, - "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `execute` function." + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `execute` function." }, "setDisabledParams": { "type": "array", "items": { "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" }, - "description": "An optional list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `setDisabledParams` function." + "description": "An optional list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `setDisabledParams` function." } }, "required": [ @@ -3713,28 +3713,28 @@ "items": { "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" }, - "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processCreatePost` function." + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreatePost` function." }, "processEditPostParams": { "type": "array", "items": { "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" }, - "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processEditPost` function." + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processEditPost` function." }, "processRemovePostParams": { "type": "array", "items": { "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" }, - "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processRemovePost` function." + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemovePost` function." }, "processPostRuleChangesParams": { "type": "array", "items": { "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" }, - "description": "A list of `ContractKeyValuePairDescriptor` that describe the `params` argument of the `processPostRuleChanges` function." + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processPostRuleChanges` function." } }, "required": [ @@ -3757,6 +3757,91 @@ "lens" ], "additionalProperties": false + }, + { + "type": "object", + "properties": { + "signature": { + "$ref": "#/$defs/Signature", + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/graph/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "$ref": "#/$defs/URI", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processFollowParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollow` function." + }, + "processUnfollowParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processUnfollow` function." + }, + "processFollowRuleChangesParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollowRuleChanges` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processFollowParams", + "processUnfollowParams", + "processFollowRuleChangesParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false } ] } diff --git a/scripts/build.ts b/scripts/build.ts index c57ec06..f2f7008 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -53,6 +53,7 @@ import { VideoSchema, } from '../src'; import { FeedRuleMetadataSchema, RuleMetadataSchema } from '../src/rule'; +import { GraphRuleMetadataSchema } from '../src/rule/GraphRuleMetadataSchema'; const outputDir = 'jsonschemas'; @@ -144,6 +145,7 @@ for (const [path, Schema] of others) { const modules = new Map>([ ['action/1.0.0.json', ActionMetadataSchema], ['rules/feed/1.0.0.json', FeedRuleMetadataSchema], + ['rules/graph/1.0.0.json', GraphRuleMetadataSchema], ]); for (const [path, Schema] of modules) { diff --git a/src/action/ActionMetadataSchema.ts b/src/action/ActionMetadataSchema.ts index a622306..a22464e 100644 --- a/src/action/ActionMetadataSchema.ts +++ b/src/action/ActionMetadataSchema.ts @@ -43,7 +43,7 @@ export type ActionMetadataDetails = { */ source: URI; /** - * An optional list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `configure` function. + * An optional list of {@link ContractKeyValuePairDescriptor} that describes the `params` argument of the `configure` function. * * ```sol * function configure(address originalMsgSender, address feed, uint256 postId, KeyValue[] calldata params) @@ -57,7 +57,7 @@ export type ActionMetadataDetails = { */ configureParams?: ContractKeyValuePairDescriptor[]; /** - * A list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `execute` function. + * A list of {@link ContractKeyValuePairDescriptor} that describes the `params` argument of the `execute` function. * * ```sol * function execute(address originalMsgSender, address feed, uint256 postId, KeyValue[] calldata params) @@ -71,7 +71,7 @@ export type ActionMetadataDetails = { */ executeParams?: ContractKeyValuePairDescriptor[]; /** - * An optional list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `setDisabledParams` function. + * An optional list of {@link ContractKeyValuePairDescriptor} that describes the `params` argument of the `setDisabledParams` function. * * ```sol * function setDisabled( @@ -109,18 +109,18 @@ const ActionMetadataDetailsSchema: z.ZodType when using it > should return a valid AccountMetadata 1`] = ` -{ - "$schema": "https://json-schemas.lens.dev/actions/1.0.0.json", - "lens": { - "authors": [ - "awesome-dev@lens.xyz", - ], - "configureParams": [ - { - "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", - "name": "account", - "type": "address", - }, - { - "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", - "name": "recipients", - "type": "address[]", - }, - ], - "description": "Get ready for the future of social interaction!", - "executeParams": [ - { - "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", - "name": "amount", - "type": "uint256", - }, - { - "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", - "name": "recipients", - "type": "(address, uint256)[]", - }, - ], - "id": Any, - "name": "My Open Action", - "setDisabledParams": [ - { - "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", - "name": "amount", - "type": "uint256", - }, - { - "key": "0xc8a06abcb0f2366f32dc2741bdf075c3215e3108918311ec0ac742f1ffd37f49", - "name": "recipients", - "type": "(address, uint256)[]", - }, - ], - "source": "https://github.com/foobarbaz/my-open-action", - "title": "This is my Open Action", - }, -} -`; - exports[`Given the "action" metadata builder > when using it > should return a valid ActionMetadata 1`] = ` { "$schema": "https://json-schemas.lens.dev/actions/1.0.0.json", diff --git a/src/builders/__tests__/__snapshots__/rules.spec.ts.snap b/src/builders/__tests__/__snapshots__/rules.spec.ts.snap index 4920129..08619a1 100644 --- a/src/builders/__tests__/__snapshots__/rules.spec.ts.snap +++ b/src/builders/__tests__/__snapshots__/rules.spec.ts.snap @@ -1,6 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`Given the rule metadata builders > when using the feedRule > should return a valid FeedRuleMetadata 1`] = ` +exports[`Given the rule metadata builders > when using the 'feedRule' > should return a valid FeedRuleMetadata 1`] = ` { "$schema": "https://json-schemas.lens.dev/rules/feed/1.0.0.json", "lens": { @@ -30,3 +30,33 @@ exports[`Given the rule metadata builders > when using the feedRule > should ret }, } `; + +exports[`Given the rule metadata builders > when using the 'graphRule' > should return a valid GraphRuleMetadata 1`] = ` +{ + "$schema": "https://json-schemas.lens.dev/rules/graph/1.0.0.json", + "lens": { + "authors": [ + "awesome-dev@lens.xyz", + ], + "description": "Get ready for the future of social interaction!", + "id": Any, + "name": "MyGraphRule", + "processFollowParams": [ + { + "key": "0x83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95", + "name": "recipient", + "type": "address", + }, + { + "key": "0xe4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99", + "name": "fee", + "type": "address token, uint256 value", + }, + ], + "processFollowRuleChangesParams": [], + "processUnfollowParams": [], + "source": "https://github.com/foobarbaz/my-open-action", + "title": "This is my Graph Rule", + }, +} +`; diff --git a/src/builders/__tests__/rules.spec.ts b/src/builders/__tests__/rules.spec.ts index a633518..70d96bf 100644 --- a/src/builders/__tests__/rules.spec.ts +++ b/src/builders/__tests__/rules.spec.ts @@ -1,9 +1,9 @@ import { describe, expect, it } from 'vitest'; -import { feedRule } from '../rules.js'; +import { feedRule, graphRule } from '../rules.js'; describe('Given the rule metadata builders', () => { - describe(`when using the ${feedRule.name}`, () => { + describe(`when using the '${feedRule.name}'`, () => { it('should return a valid FeedRuleMetadata', () => { const metadata = feedRule({ name: 'MyFeedRule', @@ -35,4 +35,36 @@ describe('Given the rule metadata builders', () => { }); }); }); + + describe(`when using the '${graphRule.name}'`, () => { + it('should return a valid GraphRuleMetadata', () => { + const metadata = graphRule({ + name: 'MyGraphRule', + title: 'This is my Graph Rule', + description: 'Get ready for the future of social interaction!', + authors: ['awesome-dev@lens.xyz'], + source: 'https://github.com/foobarbaz/my-open-action', + processFollowParams: [ + { + key: '0x83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95', + name: 'recipient', + type: 'address', + }, + { + key: '0xe4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99', + name: 'fee', + type: 'address token, uint256 value', + }, + ], + processUnfollowParams: [], + processFollowRuleChangesParams: [], + }); + + expect(metadata).toMatchSnapshot({ + lens: { + id: expect.any(String), + }, + }); + }); + }); }); diff --git a/src/builders/rules.ts b/src/builders/rules.ts index 4545e65..924f28f 100644 --- a/src/builders/rules.ts +++ b/src/builders/rules.ts @@ -5,6 +5,11 @@ import { type FeedRuleMetadataDetails, FeedRuleMetadataSchema, } from '../rule/FeedRuleMetadataSchema.js'; +import { + type GraphRuleMetadata, + type GraphRuleMetadataDetails, + GraphRuleMetadataSchema, +} from '../rule/GraphRuleMetadataSchema.js'; import { RuleMetadataSchemaId } from '../rule/RuleMetadataSchemaId.js'; import type { Prettify } from '../utils.js'; import { evaluate } from './ValidationError.js'; @@ -68,3 +73,61 @@ export function feedRule({ id = v4(), ...others }: FeedRuleOptions): FeedRuleMet }), ); } + +/** + * @private + * @privateRemarks MUST stay very @private to produce usable docs + */ +type GraphRuleDetails = Prettify>>; + +export type GraphRuleOptions = GraphRuleDetails & { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. + * + * @defaultValue a UUID + */ + id?: string; +}; + +/** + * Creates a valid GraphRuleMetadata. + * + * @category Compose + * @param input - Use your IDE suggestions for an enhanced development experience + * + * @example + * ```ts + * const metadata = graphRule({ + * name: 'MyGraphRule', + * title: 'This is my Graph Rule', + * description: 'Get ready for the future of social interaction!', + * authors: ['awesome-dev@lens.xyz'], + * source: 'https://github.com/foobarbaz/my-open-action', + * processFollowParams: [ + * { + * key: '83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95', + * name: 'recipient', + * type: 'address', + * }, + * { + * key: 'e4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99', + * name: 'fee', + * type: 'address token, uint256 value', + * } + * ], + * processUnfollowParams: [], + * processFollowRuleChangesParams: [], + * }); + * ``` + */ +export function graphRule({ id = v4(), ...others }: GraphRuleOptions): GraphRuleMetadata { + return evaluate( + GraphRuleMetadataSchema.safeParse({ + $schema: RuleMetadataSchemaId.GRAPH_LATEST, + lens: { + id, + ...others, + }, + }), + ); +} diff --git a/src/rule/FeedRuleMetadataSchema.ts b/src/rule/FeedRuleMetadataSchema.ts index 707e078..95f344f 100644 --- a/src/rule/FeedRuleMetadataSchema.ts +++ b/src/rule/FeedRuleMetadataSchema.ts @@ -43,7 +43,7 @@ export type FeedRuleMetadataDetails = { */ source: URI; /** - * A list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `processCreatePost` function. + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processCreatePost` function. * * ```sol * function processCreatePost( @@ -61,7 +61,7 @@ export type FeedRuleMetadataDetails = { */ processCreatePostParams: ContractKeyValuePairDescriptor[]; /** - * A list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `processEditPost` function. + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processEditPost` function. * * ```sol * function processEditPost( @@ -79,7 +79,7 @@ export type FeedRuleMetadataDetails = { */ processEditPostParams: ContractKeyValuePairDescriptor[]; /** - * A list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `processRemovePost` function. + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processRemovePost` function. * * ```sol * function processRemovePost( @@ -96,7 +96,7 @@ export type FeedRuleMetadataDetails = { */ processRemovePostParams: ContractKeyValuePairDescriptor[]; /** - * A list of {@link ContractKeyValuePairDescriptor} that describe the `params` argument of the `processPostRuleChanges` function. + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processPostRuleChanges` function. * * ```sol * function processPostRuleChanges( @@ -130,22 +130,22 @@ const FeedRuleMetadataDetailsSchema: z.ZodType = + z.object({ + id: NonEmptyStringSchema.describe( + 'A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure.', + ), + name: NonEmptyStringSchema.describe('A short name for the Rule.'), + title: NonEmptyStringSchema.describe('The human-friendly title for the Rule.'), + description: MarkdownSchema.describe('Markdown formatted description of the Rule.'), + authors: z + .array(z.string().email('Authors list should only contain valid emails')) + .min(1, 'You must supply at least one author') + .describe('List of authors email addresses.'), + source: URISchema.describe('The link to the Rule source code. Typically a GitHub repository.'), + processFollowParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollow` function.', + ), + processUnfollowParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processUnfollow` function.', + ), + processFollowRuleChangesParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollowRuleChanges` function.', + ), + }); + +export type GraphRuleMetadata = { + $schema: RuleMetadataSchemaId.GRAPH_LATEST; + lens: GraphRuleMetadataDetails; + signature?: Signature; +}; + +export const GraphRuleMetadataSchema = rootSchema({ + $schema: z.literal(RuleMetadataSchemaId.GRAPH_LATEST), + lens: GraphRuleMetadataDetailsSchema, +}); diff --git a/src/rule/index.ts b/src/rule/index.ts index 1feed5e..7e68877 100644 --- a/src/rule/index.ts +++ b/src/rule/index.ts @@ -1,5 +1,6 @@ import { z } from 'zod'; import { type FeedRuleMetadata, FeedRuleMetadataSchema } from './FeedRuleMetadataSchema.js'; +import { type GraphRuleMetadata, GraphRuleMetadataSchema } from './GraphRuleMetadataSchema.js'; export * from './RuleMetadataSchemaId.js'; export * from './FeedRuleMetadataSchema.js'; @@ -7,10 +8,10 @@ export * from './FeedRuleMetadataSchema.js'; /** * @internal */ -export type RuleMetadata = FeedRuleMetadata; +export type RuleMetadata = FeedRuleMetadata | GraphRuleMetadata; /** * @internal */ export const RuleMetadataSchema: z.ZodType = - z.discriminatedUnion('$schema', [FeedRuleMetadataSchema]); + z.discriminatedUnion('$schema', [FeedRuleMetadataSchema, GraphRuleMetadataSchema]); From 994a0fc932d4ab2183be92eccbb628751da7113f Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Tue, 14 Jan 2025 21:16:59 +0100 Subject: [PATCH 06/14] feat: GroupRuleMetadata spec --- jsonschemas/rules/group/1.0.0.json | 250 ++++++++++++++++++++++++++++ scripts/build.ts | 3 +- src/builders/rules.ts | 64 +++++++ src/rule/GroupRuleMetadataSchema.ts | 161 ++++++++++++++++++ src/rule/index.ts | 4 +- 5 files changed, 480 insertions(+), 2 deletions(-) create mode 100644 jsonschemas/rules/group/1.0.0.json create mode 100644 src/rule/GroupRuleMetadataSchema.ts diff --git a/jsonschemas/rules/group/1.0.0.json b/jsonschemas/rules/group/1.0.0.json new file mode 100644 index 0000000..256ccac --- /dev/null +++ b/jsonschemas/rules/group/1.0.0.json @@ -0,0 +1,250 @@ +{ + "type": "object", + "properties": { + "signature": { + "type": "string", + "minLength": 1, + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/group/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "type": "string", + "minLength": 6, + "format": "uri", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processAdditionParams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processAddition` function." + }, + "processRemovalParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processAdditionParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemoval` function." + }, + "processJoiningParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processAdditionParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processJoining` function." + }, + "processLeavingParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processAdditionParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processLeaving` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processAdditionParams", + "processRemovalParams", + "processJoiningParams", + "processLeavingParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false, + "$defs": { + "NonEmptyString": { + "type": "string", + "minLength": 1 + }, + "MetadataAttribute": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Boolean" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "enum": [ + "true", + "false" + ], + "description": "A JS boolean value serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Date" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "format": "date-time", + "description": "A valid ISO 8601 date string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Number" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A valid JS number serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "String" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "Any string value." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "JSON" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A JSON string. It's consumer responsibility to validate and parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + } + ] + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/scripts/build.ts b/scripts/build.ts index f2f7008..48a5f32 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -52,7 +52,7 @@ import { UsernameMetadataSchema, VideoSchema, } from '../src'; -import { FeedRuleMetadataSchema, RuleMetadataSchema } from '../src/rule'; +import { FeedRuleMetadataSchema, GroupRuleMetadataSchema, RuleMetadataSchema } from '../src/rule'; import { GraphRuleMetadataSchema } from '../src/rule/GraphRuleMetadataSchema'; const outputDir = 'jsonschemas'; @@ -146,6 +146,7 @@ const modules = new Map>([ ['action/1.0.0.json', ActionMetadataSchema], ['rules/feed/1.0.0.json', FeedRuleMetadataSchema], ['rules/graph/1.0.0.json', GraphRuleMetadataSchema], + ['rules/group/1.0.0.json', GroupRuleMetadataSchema], ]); for (const [path, Schema] of modules) { diff --git a/src/builders/rules.ts b/src/builders/rules.ts index 924f28f..46abf1c 100644 --- a/src/builders/rules.ts +++ b/src/builders/rules.ts @@ -10,6 +10,11 @@ import { type GraphRuleMetadataDetails, GraphRuleMetadataSchema, } from '../rule/GraphRuleMetadataSchema.js'; +import { + type GroupRuleMetadata, + type GroupRuleMetadataDetails, + GroupRuleMetadataSchema, +} from '../rule/GroupRuleMetadataSchema.js'; import { RuleMetadataSchemaId } from '../rule/RuleMetadataSchemaId.js'; import type { Prettify } from '../utils.js'; import { evaluate } from './ValidationError.js'; @@ -131,3 +136,62 @@ export function graphRule({ id = v4(), ...others }: GraphRuleOptions): GraphRule }), ); } + +/** + * @private + * @privateRemarks MUST stay very @private to produce usable docs + */ +type GroupRuleDetails = Prettify>>; + +export type GroupRuleOptions = GroupRuleDetails & { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. + * + * @defaultValue a UUID + */ + id?: string; +}; + +/** + * Creates a valid GroupRuleMetadata. + * + * @category Compose + * @param input - Use your IDE suggestions for an enhanced development experience + * + * @example + * ```ts + * const metadata = groupRule({ + * name: 'MyGroupRule', + * title: 'This is my Group Rule', + * description: 'Get ready for the future of social interaction!', + * authors: ['awesome-dev@lens.xyz'], + * source: 'https://github.com/foobarbaz/my-open-action', + * processAdditionParams: [], + * processRemovalParams: [], + * processJoiningParams: [ + * { + * key: '83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95', + * name: 'recipient', + * type: 'address', + * }, + * { + * key: 'e4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99', + * name: 'fee', + * type: 'address token, uint256 value', + * } + * ], + * processLeavingParams: [], + * }); + * ``` + */ +export function groupRule({ id = v4(), ...others }: GroupRuleOptions): GroupRuleMetadata { + return evaluate( + GroupRuleMetadataSchema.safeParse({ + $schema: RuleMetadataSchemaId.GROUP_LATEST, + lens: { + id, + ...others, + }, + }), + ); +} diff --git a/src/rule/GroupRuleMetadataSchema.ts b/src/rule/GroupRuleMetadataSchema.ts new file mode 100644 index 0000000..6b7a416 --- /dev/null +++ b/src/rule/GroupRuleMetadataSchema.ts @@ -0,0 +1,161 @@ +import { z } from 'zod'; + +import { rootSchema } from '../common'; +import { + type ContractKeyValuePairDescriptor, + ContractKeyValuePairDescriptorSchema, + type Markdown, + MarkdownSchema, + NonEmptyStringSchema, + type Signature, + type URI, + URISchema, +} from '../primitives'; +import { RuleMetadataSchemaId } from './RuleMetadataSchemaId'; + +export type GroupRuleMetadataDetails = { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure. + */ + id: string; + /** + * A short name for the Rule. + */ + name: string; + /** + * The human-friendly title for the Rule. + */ + title: string; + /** + * Markdown formatted description of the Rule. + * + * It should explain what this Rule does, how to use it, examples just + * like you would if you were building an NPM package. + * The more detail the better to allow dApp to easily integrate it. + */ + description: Markdown; + /** + * List of authors email addresses. + */ + authors: string[]; + /** + * The link to the Rule source code. Typically a GitHub repository. + */ + source: URI; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processAddition` function. + * + * ```sol + * function processAddition( + * bytes32 configSalt, + * address originalMsgSender, + * address account, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode and decode the params for the `processAddition` function. + * + * @see https://abitype.dev/api/human + */ + processAdditionParams: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processRemoval` function. + * + * ```sol + * function processRemoval( + * bytes32 configSalt, + * address originalMsgSender, + * address account, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode the calldata for the `processRemoval` function. + * + * @see https://abitype.dev/api/human + */ + processRemovalParams: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processJoining` function. + * + * ```sol + * function processJoining( + * bytes32 configSalt, + * address account, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode the calldata for the `processJoining` function. + * + * @see https://abitype.dev/api/human + */ + processJoiningParams: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processLeaving` function. + * + * ```sol + * function processLeaving( + * bytes32 configSalt, + * address account, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode the calldata for the `processLeaving` function. + * + * @see https://abitype.dev/api/human + */ + processLeavingParams: ContractKeyValuePairDescriptor[]; +}; + +const GroupRuleMetadataDetailsSchema: z.ZodType = + z.object({ + id: NonEmptyStringSchema.describe( + 'A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure.', + ), + name: NonEmptyStringSchema.describe('A short name for the Rule.'), + title: NonEmptyStringSchema.describe('The human-friendly title for the Rule.'), + description: MarkdownSchema.describe('Markdown formatted description of the Rule.'), + authors: z + .array(z.string().email('Authors list should only contain valid emails')) + .min(1, 'You must supply at least one author') + .describe('List of authors email addresses.'), + source: URISchema.describe('The link to the Rule source code. Typically a GitHub repository.'), + processAdditionParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processAddition` function.', + ), + processRemovalParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemoval` function.', + ), + processJoiningParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processJoining` function.', + ), + processLeavingParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processLeaving` function.', + ), + }); + +export type GroupRuleMetadata = { + $schema: RuleMetadataSchemaId.GROUP_LATEST; + lens: GroupRuleMetadataDetails; + signature?: Signature; +}; + +export const GroupRuleMetadataSchema = rootSchema({ + $schema: z.literal(RuleMetadataSchemaId.GROUP_LATEST), + lens: GroupRuleMetadataDetailsSchema, +}); diff --git a/src/rule/index.ts b/src/rule/index.ts index 7e68877..0c11a9f 100644 --- a/src/rule/index.ts +++ b/src/rule/index.ts @@ -2,8 +2,10 @@ import { z } from 'zod'; import { type FeedRuleMetadata, FeedRuleMetadataSchema } from './FeedRuleMetadataSchema.js'; import { type GraphRuleMetadata, GraphRuleMetadataSchema } from './GraphRuleMetadataSchema.js'; -export * from './RuleMetadataSchemaId.js'; export * from './FeedRuleMetadataSchema.js'; +export * from './GraphRuleMetadataSchema.js'; +export * from './GroupRuleMetadataSchema.js'; +export * from './RuleMetadataSchemaId.js'; /** * @internal From 01a71e3e1b437457cdf23a86bb2df6252f3629cc Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Tue, 14 Jan 2025 21:29:11 +0100 Subject: [PATCH 07/14] feat: NamespaceRuleMetadata spec --- jsonschemas/rules/namespace/1.0.0.json | 250 ++++++++++++++++++++++++ jsonschemas/schema.json | 186 ++++++++++++++++++ scripts/build.ts | 8 +- src/builders/rules.ts | 67 +++++++ src/rule/NamespaceRuleMetadataSchema.ts | 169 ++++++++++++++++ src/rule/index.ts | 19 +- 6 files changed, 696 insertions(+), 3 deletions(-) create mode 100644 jsonschemas/rules/namespace/1.0.0.json create mode 100644 src/rule/NamespaceRuleMetadataSchema.ts diff --git a/jsonschemas/rules/namespace/1.0.0.json b/jsonschemas/rules/namespace/1.0.0.json new file mode 100644 index 0000000..7cc10bb --- /dev/null +++ b/jsonschemas/rules/namespace/1.0.0.json @@ -0,0 +1,250 @@ +{ + "type": "object", + "properties": { + "signature": { + "type": "string", + "minLength": 1, + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/namespace/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "type": "string", + "minLength": 6, + "format": "uri", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processCreationParams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreation` function." + }, + "processRemovalParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processCreationParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemoval` function." + }, + "processAssigningParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processCreationParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processAssigning` function." + }, + "processUnassigningParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processCreationParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processUnassigning` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processCreationParams", + "processRemovalParams", + "processAssigningParams", + "processUnassigningParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false, + "$defs": { + "NonEmptyString": { + "type": "string", + "minLength": 1 + }, + "MetadataAttribute": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Boolean" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "enum": [ + "true", + "false" + ], + "description": "A JS boolean value serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Date" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "format": "date-time", + "description": "A valid ISO 8601 date string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Number" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A valid JS number serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "String" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "Any string value." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "JSON" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A JSON string. It's consumer responsibility to validate and parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + } + ] + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/jsonschemas/schema.json b/jsonschemas/schema.json index 650fa83..49c6fff 100644 --- a/jsonschemas/schema.json +++ b/jsonschemas/schema.json @@ -3842,6 +3842,192 @@ "lens" ], "additionalProperties": false + }, + { + "type": "object", + "properties": { + "signature": { + "$ref": "#/$defs/Signature", + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/group/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "$ref": "#/$defs/URI", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processAdditionParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processAddition` function." + }, + "processRemovalParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemoval` function." + }, + "processJoiningParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processJoining` function." + }, + "processLeavingParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processLeaving` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processAdditionParams", + "processRemovalParams", + "processJoiningParams", + "processLeavingParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "signature": { + "$ref": "#/$defs/Signature", + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/namespace/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "$ref": "#/$defs/URI", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processCreationParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreation` function." + }, + "processRemovalParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemoval` function." + }, + "processAssigningParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processAssigning` function." + }, + "processUnassigningParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processUnassigning` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processCreationParams", + "processRemovalParams", + "processAssigningParams", + "processUnassigningParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false } ] } diff --git a/scripts/build.ts b/scripts/build.ts index 48a5f32..5b2effd 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -52,7 +52,12 @@ import { UsernameMetadataSchema, VideoSchema, } from '../src'; -import { FeedRuleMetadataSchema, GroupRuleMetadataSchema, RuleMetadataSchema } from '../src/rule'; +import { + FeedRuleMetadataSchema, + GroupRuleMetadataSchema, + NamespaceRuleMetadataSchema, + RuleMetadataSchema, +} from '../src/rule'; import { GraphRuleMetadataSchema } from '../src/rule/GraphRuleMetadataSchema'; const outputDir = 'jsonschemas'; @@ -147,6 +152,7 @@ const modules = new Map>([ ['rules/feed/1.0.0.json', FeedRuleMetadataSchema], ['rules/graph/1.0.0.json', GraphRuleMetadataSchema], ['rules/group/1.0.0.json', GroupRuleMetadataSchema], + ['rules/namespace/1.0.0.json', NamespaceRuleMetadataSchema], ]); for (const [path, Schema] of modules) { diff --git a/src/builders/rules.ts b/src/builders/rules.ts index 46abf1c..9f9ac08 100644 --- a/src/builders/rules.ts +++ b/src/builders/rules.ts @@ -15,6 +15,11 @@ import { type GroupRuleMetadataDetails, GroupRuleMetadataSchema, } from '../rule/GroupRuleMetadataSchema.js'; +import { + type NamespaceRuleMetadata, + type NamespaceRuleMetadataDetails, + NamespaceRuleMetadataSchema, +} from '../rule/NamespaceRuleMetadataSchema.js'; import { RuleMetadataSchemaId } from '../rule/RuleMetadataSchemaId.js'; import type { Prettify } from '../utils.js'; import { evaluate } from './ValidationError.js'; @@ -195,3 +200,65 @@ export function groupRule({ id = v4(), ...others }: GroupRuleOptions): GroupRule }), ); } + +/** + * @private + * @privateRemarks MUST stay very @private to produce usable docs + */ +type NamespaceRuleDetails = Prettify>>; + +export type NamespaceRuleOptions = NamespaceRuleDetails & { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. + * + * @defaultValue a UUID + */ + id?: string; +}; + +/** + * Creates a valid NamespaceRuleMetadata. + * + * @category Compose + * @param input - Use your IDE suggestions for an enhanced development experience + * + * @example + * ```ts + * const metadata = namespaceRule({ + * name: 'MyNamespaceRule', + * title: 'This is my Namespace Rule', + * description: 'Get ready for the future of social interaction!', + * authors: ['awesome-dev@lens.xyz'], + * source: 'https://github.com/foobarbaz/my-open-action', + * processCreationParams: [ + * { + * key: '83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95', + * name: 'recipient', + * type: 'address', + * }, + * { + * key: 'e4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99', + * name: 'fee', + * type: 'address token, uint256 value', + * } + * ], + * processRemovalParams: [], + * processAssigningParams: [], + * processUnassigningParams: [], + * }); + * ``` + */ +export function namespaceRule({ + id = v4(), + ...others +}: NamespaceRuleOptions): NamespaceRuleMetadata { + return evaluate( + NamespaceRuleMetadataSchema.safeParse({ + $schema: RuleMetadataSchemaId.NAMESPACE_LATEST, + lens: { + id, + ...others, + }, + }), + ); +} diff --git a/src/rule/NamespaceRuleMetadataSchema.ts b/src/rule/NamespaceRuleMetadataSchema.ts new file mode 100644 index 0000000..4086a70 --- /dev/null +++ b/src/rule/NamespaceRuleMetadataSchema.ts @@ -0,0 +1,169 @@ +import { z } from 'zod'; + +import { rootSchema } from '../common'; +import { + type ContractKeyValuePairDescriptor, + ContractKeyValuePairDescriptorSchema, + type Markdown, + MarkdownSchema, + NonEmptyStringSchema, + type Signature, + type URI, + URISchema, +} from '../primitives'; +import { RuleMetadataSchemaId } from './RuleMetadataSchemaId'; + +export type NamespaceRuleMetadataDetails = { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure. + */ + id: string; + /** + * A short name for the Rule. + */ + name: string; + /** + * The human-friendly title for the Rule. + */ + title: string; + /** + * Markdown formatted description of the Rule. + * + * It should explain what this Rule does, how to use it, examples just + * like you would if you were building an NPM package. + * The more detail the better to allow dApp to easily integrate it. + */ + description: Markdown; + /** + * List of authors email addresses. + */ + authors: string[]; + /** + * The link to the Rule source code. Typically a GitHub repository. + */ + source: URI; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processCreation` function. + * + * ```sol + * function processCreation( + * bytes32 configSalt, + * address originalMsgSender, + * address account, + * string calldata username, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode and decode the params for the `processCreation` function. + * + * @see https://abitype.dev/api/human + */ + processCreationParams: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processRemoval` function. + * + * ```sol + * function processRemoval( + * bytes32 configSalt, + * address originalMsgSender, + * string calldata username, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode the calldata for the `processRemoval` function. + * + * @see https://abitype.dev/api/human + */ + processRemovalParams: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processAssigning` function. + * + * ```sol + * function processAssigning( + * bytes32 configSalt, + * address originalMsgSender, + * address account, + * string calldata username, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode the calldata for the `processAssigning` function. + * + * @see https://abitype.dev/api/human + */ + processAssigningParams: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processUnassigning` function. + * + * ```sol + * function processUnassigning( + * bytes32 configSalt, + * address originalMsgSender, + * address account, + * string calldata username, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode the calldata for the `processUnassigning` function. + * + * @see https://abitype.dev/api/human + */ + processUnassigningParams: ContractKeyValuePairDescriptor[]; +}; + +const NamespaceRuleMetadataDetailsSchema: z.ZodType< + NamespaceRuleMetadataDetails, + z.ZodTypeDef, + object +> = z.object({ + id: NonEmptyStringSchema.describe( + 'A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure.', + ), + name: NonEmptyStringSchema.describe('A short name for the Rule.'), + title: NonEmptyStringSchema.describe('The human-friendly title for the Rule.'), + description: MarkdownSchema.describe('Markdown formatted description of the Rule.'), + authors: z + .array(z.string().email('Authors list should only contain valid emails')) + .min(1, 'You must supply at least one author') + .describe('List of authors email addresses.'), + source: URISchema.describe('The link to the Rule source code. Typically a GitHub repository.'), + processCreationParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreation` function.', + ), + processRemovalParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemoval` function.', + ), + processAssigningParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processAssigning` function.', + ), + processUnassigningParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processUnassigning` function.', + ), +}); + +export type NamespaceRuleMetadata = { + $schema: RuleMetadataSchemaId.NAMESPACE_LATEST; + lens: NamespaceRuleMetadataDetails; + signature?: Signature; +}; + +export const NamespaceRuleMetadataSchema = rootSchema({ + $schema: z.literal(RuleMetadataSchemaId.NAMESPACE_LATEST), + lens: NamespaceRuleMetadataDetailsSchema, +}); diff --git a/src/rule/index.ts b/src/rule/index.ts index 0c11a9f..460f7f1 100644 --- a/src/rule/index.ts +++ b/src/rule/index.ts @@ -1,19 +1,34 @@ import { z } from 'zod'; import { type FeedRuleMetadata, FeedRuleMetadataSchema } from './FeedRuleMetadataSchema.js'; import { type GraphRuleMetadata, GraphRuleMetadataSchema } from './GraphRuleMetadataSchema.js'; +import { type GroupRuleMetadata, GroupRuleMetadataSchema } from './GroupRuleMetadataSchema.js'; +import { + type NamespaceRuleMetadata, + NamespaceRuleMetadataSchema, +} from './NamespaceRuleMetadataSchema.js'; export * from './FeedRuleMetadataSchema.js'; export * from './GraphRuleMetadataSchema.js'; export * from './GroupRuleMetadataSchema.js'; +export * from './NamespaceRuleMetadataSchema.js'; export * from './RuleMetadataSchemaId.js'; /** * @internal */ -export type RuleMetadata = FeedRuleMetadata | GraphRuleMetadata; +export type RuleMetadata = + | FeedRuleMetadata + | GraphRuleMetadata + | GroupRuleMetadata + | NamespaceRuleMetadata; /** * @internal */ export const RuleMetadataSchema: z.ZodType = - z.discriminatedUnion('$schema', [FeedRuleMetadataSchema, GraphRuleMetadataSchema]); + z.discriminatedUnion('$schema', [ + FeedRuleMetadataSchema, + GraphRuleMetadataSchema, + GroupRuleMetadataSchema, + NamespaceRuleMetadataSchema, + ]); From 1fa07f0cba4935cdc95c0b744f469f0e471e703c Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Tue, 14 Jan 2025 21:40:32 +0100 Subject: [PATCH 08/14] feat: PostRuleMetadata spec --- jsonschemas/rules/post/1.0.0.json | 234 +++++++++++++++++++++++++++++ jsonschemas/schema.json | 77 ++++++++++ scripts/build.ts | 2 + src/builders/rules.ts | 62 ++++++++ src/rule/PostRuleMetadataSchema.ts | 119 +++++++++++++++ src/rule/index.ts | 5 +- 6 files changed, 498 insertions(+), 1 deletion(-) create mode 100644 jsonschemas/rules/post/1.0.0.json create mode 100644 src/rule/PostRuleMetadataSchema.ts diff --git a/jsonschemas/rules/post/1.0.0.json b/jsonschemas/rules/post/1.0.0.json new file mode 100644 index 0000000..5ccee34 --- /dev/null +++ b/jsonschemas/rules/post/1.0.0.json @@ -0,0 +1,234 @@ +{ + "type": "object", + "properties": { + "signature": { + "type": "string", + "minLength": 1, + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/post/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "type": "string", + "minLength": 6, + "format": "uri", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processCreatePostParams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreatePost` function." + }, + "processEditPostParams": { + "type": "array", + "items": { + "$ref": "#/properties/lens/properties/processCreatePostParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processEditPost` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processCreatePostParams", + "processEditPostParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false, + "$defs": { + "NonEmptyString": { + "type": "string", + "minLength": 1 + }, + "MetadataAttribute": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Boolean" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "enum": [ + "true", + "false" + ], + "description": "A JS boolean value serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Date" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "format": "date-time", + "description": "A valid ISO 8601 date string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Number" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A valid JS number serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "String" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "Any string value." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "JSON" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A JSON string. It's consumer responsibility to validate and parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + } + ] + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/jsonschemas/schema.json b/jsonschemas/schema.json index 49c6fff..45ac5c9 100644 --- a/jsonschemas/schema.json +++ b/jsonschemas/schema.json @@ -4028,6 +4028,83 @@ "lens" ], "additionalProperties": false + }, + { + "type": "object", + "properties": { + "signature": { + "$ref": "#/$defs/Signature", + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/post/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "$ref": "#/$defs/URI", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processCreatePostParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreatePost` function." + }, + "processEditPostParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processEditPost` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processCreatePostParams", + "processEditPostParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false } ] } diff --git a/scripts/build.ts b/scripts/build.ts index 5b2effd..b924d56 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -59,6 +59,7 @@ import { RuleMetadataSchema, } from '../src/rule'; import { GraphRuleMetadataSchema } from '../src/rule/GraphRuleMetadataSchema'; +import { PostRuleMetadataSchema } from '../src/rule/PostRuleMetadataSchema'; const outputDir = 'jsonschemas'; @@ -153,6 +154,7 @@ const modules = new Map>([ ['rules/graph/1.0.0.json', GraphRuleMetadataSchema], ['rules/group/1.0.0.json', GroupRuleMetadataSchema], ['rules/namespace/1.0.0.json', NamespaceRuleMetadataSchema], + ['rules/post/1.0.0.json', PostRuleMetadataSchema], ]); for (const [path, Schema] of modules) { diff --git a/src/builders/rules.ts b/src/builders/rules.ts index 9f9ac08..51c5767 100644 --- a/src/builders/rules.ts +++ b/src/builders/rules.ts @@ -20,6 +20,11 @@ import { type NamespaceRuleMetadataDetails, NamespaceRuleMetadataSchema, } from '../rule/NamespaceRuleMetadataSchema.js'; +import { + type PostRuleMetadata, + type PostRuleMetadataDetails, + PostRuleMetadataSchema, +} from '../rule/PostRuleMetadataSchema.js'; import { RuleMetadataSchemaId } from '../rule/RuleMetadataSchemaId.js'; import type { Prettify } from '../utils.js'; import { evaluate } from './ValidationError.js'; @@ -262,3 +267,60 @@ export function namespaceRule({ }), ); } + +/** + * @private + * @privateRemarks MUST stay very @private to produce usable docs + */ +type PostRuleDetails = Prettify>>; + +export type PostRuleOptions = PostRuleDetails & { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. + * + * @defaultValue a UUID + */ + id?: string; +}; + +/** + * Creates a valid PostRuleMetadata. + * + * @category Compose + * @param input - Use your IDE suggestions for an enhanced development experience + * + * @example + * ```ts + * const metadata = postRule({ + * name: 'MyPostRule', + * title: 'This is my Post Rule', + * description: 'Get ready for the future of social interaction!', + * authors: ['awesome-dev@lens.xyz'], + * source: 'https://github.com/foobarbaz/my-open-action', + * processCreatePostParams: [ + * { + * key: '83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95', + * name: 'recipient', + * type: 'address', + * }, + * { + * key: 'e4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99', + * name: 'fee', + * type: 'address token, uint256 value', + * } + * ], + * processEditPostParams: [], + * }); + * ``` + */ +export function postRule({ id = v4(), ...others }: PostRuleOptions): PostRuleMetadata { + return evaluate( + PostRuleMetadataSchema.safeParse({ + $schema: RuleMetadataSchemaId.POST_LATEST, + lens: { + id, + ...others, + }, + }), + ); +} diff --git a/src/rule/PostRuleMetadataSchema.ts b/src/rule/PostRuleMetadataSchema.ts new file mode 100644 index 0000000..9457219 --- /dev/null +++ b/src/rule/PostRuleMetadataSchema.ts @@ -0,0 +1,119 @@ +import { z } from 'zod'; + +import { rootSchema } from '../common'; +import { + type ContractKeyValuePairDescriptor, + ContractKeyValuePairDescriptorSchema, + type Markdown, + MarkdownSchema, + NonEmptyStringSchema, + type Signature, + type URI, + URISchema, +} from '../primitives'; +import { RuleMetadataSchemaId } from './RuleMetadataSchemaId'; + +export type PostRuleMetadataDetails = { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure. + */ + id: string; + /** + * A short name for the Rule. + */ + name: string; + /** + * The human-friendly title for the Rule. + */ + title: string; + /** + * Markdown formatted description of the Rule. + * + * It should explain what this Rule does, how to use it, examples just + * like you would if you were building an NPM package. + * The more detail the better to allow dApp to easily integrate it. + */ + description: Markdown; + /** + * List of authors email addresses. + */ + authors: string[]; + /** + * The link to the Rule source code. Typically a GitHub repository. + */ + source: URI; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processCreatePost` function. + * + * ```sol + * function processCreatePost( + * bytes32 configSalt, + * uint256 rootPostId, + * uint256 postId, + * CreatePostParams calldata postParams, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode and decode the params for the `processCreatePost` function. + * + * @see https://abitype.dev/api/human + */ + processCreatePostParams: ContractKeyValuePairDescriptor[]; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processEditPost` function. + * + * ```sol + * function processEditPost( + * bytes32 configSalt, + * uint256 rootPostId, + * uint256 postId, + * EditPostParams calldata postParams, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode the calldata for the `processEditPost` function. + * + * @see https://abitype.dev/api/human + */ + processEditPostParams: ContractKeyValuePairDescriptor[]; +}; + +const PostRuleMetadataDetailsSchema: z.ZodType = + z.object({ + id: NonEmptyStringSchema.describe( + 'A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure.', + ), + name: NonEmptyStringSchema.describe('A short name for the Rule.'), + title: NonEmptyStringSchema.describe('The human-friendly title for the Rule.'), + description: MarkdownSchema.describe('Markdown formatted description of the Rule.'), + authors: z + .array(z.string().email('Authors list should only contain valid emails')) + .min(1, 'You must supply at least one author') + .describe('List of authors email addresses.'), + source: URISchema.describe('The link to the Rule source code. Typically a GitHub repository.'), + processCreatePostParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreatePost` function.', + ), + processEditPostParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processEditPost` function.', + ), + }); + +export type PostRuleMetadata = { + $schema: RuleMetadataSchemaId.POST_LATEST; + lens: PostRuleMetadataDetails; + signature?: Signature; +}; + +export const PostRuleMetadataSchema = rootSchema({ + $schema: z.literal(RuleMetadataSchemaId.POST_LATEST), + lens: PostRuleMetadataDetailsSchema, +}); diff --git a/src/rule/index.ts b/src/rule/index.ts index 460f7f1..11c7bcf 100644 --- a/src/rule/index.ts +++ b/src/rule/index.ts @@ -6,6 +6,7 @@ import { type NamespaceRuleMetadata, NamespaceRuleMetadataSchema, } from './NamespaceRuleMetadataSchema.js'; +import { type PostRuleMetadata, PostRuleMetadataSchema } from './PostRuleMetadataSchema.js'; export * from './FeedRuleMetadataSchema.js'; export * from './GraphRuleMetadataSchema.js'; @@ -20,7 +21,8 @@ export type RuleMetadata = | FeedRuleMetadata | GraphRuleMetadata | GroupRuleMetadata - | NamespaceRuleMetadata; + | NamespaceRuleMetadata + | PostRuleMetadata; /** * @internal @@ -31,4 +33,5 @@ export const RuleMetadataSchema: z.ZodType = GraphRuleMetadataSchema, GroupRuleMetadataSchema, NamespaceRuleMetadataSchema, + PostRuleMetadataSchema, ]); From d64f0a85486bab43a4134b6c6138663ece4fbdff Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Tue, 14 Jan 2025 21:51:04 +0100 Subject: [PATCH 09/14] feat: FollowRuleMetadata spec --- jsonschemas/action/1.0.0.json | 55 +++--- jsonschemas/rules/feed/1.0.0.json | 57 +++--- jsonschemas/rules/follow/1.0.0.json | 229 +++++++++++++++++++++++++ jsonschemas/rules/graph/1.0.0.json | 55 +++--- jsonschemas/rules/group/1.0.0.json | 57 +++--- jsonschemas/rules/namespace/1.0.0.json | 57 +++--- jsonschemas/rules/post/1.0.0.json | 53 +++--- jsonschemas/schema.json | 158 ++++++++++++----- scripts/build.ts | 17 +- src/builders/index.ts | 1 + src/builders/rules.ts | 60 +++++++ src/index.ts | 1 + src/rule/FollowRuleMetadataSchema.ts | 95 ++++++++++ src/rule/index.ts | 3 + 14 files changed, 690 insertions(+), 208 deletions(-) create mode 100644 jsonschemas/rules/follow/1.0.0.json create mode 100644 src/rule/FollowRuleMetadataSchema.ts diff --git a/jsonschemas/action/1.0.0.json b/jsonschemas/action/1.0.0.json index f60a055..7527181 100644 --- a/jsonschemas/action/1.0.0.json +++ b/jsonschemas/action/1.0.0.json @@ -42,44 +42,21 @@ "configureParams": { "type": "array", "items": { - "type": "object", - "properties": { - "key": { - "type": "string", - "minLength": 66, - "maxLength": 66, - "pattern": "^0x[0-9a-fA-F]{64}$", - "description": "A unique 32 bytes long hexadecimal string key." - }, - "name": { - "$ref": "#/$defs/NonEmptyString", - "description": "The human-readable name of the parameter." - }, - "type": { - "type": "string", - "description": "The human-readable ABI description of the parameter." - } - }, - "required": [ - "key", - "name", - "type" - ], - "additionalProperties": false + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "An optional list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `configure` function." }, "executeParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `execute` function." }, "setDisabledParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "An optional list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `setDisabledParams` function." } @@ -234,6 +211,32 @@ "additionalProperties": false } ] + }, + "ContractKeyValuePairDescriptor": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/jsonschemas/rules/feed/1.0.0.json b/jsonschemas/rules/feed/1.0.0.json index fecae65..bfb8ac2 100644 --- a/jsonschemas/rules/feed/1.0.0.json +++ b/jsonschemas/rules/feed/1.0.0.json @@ -47,51 +47,28 @@ "processCreatePostParams": { "type": "array", "items": { - "type": "object", - "properties": { - "key": { - "type": "string", - "minLength": 66, - "maxLength": 66, - "pattern": "^0x[0-9a-fA-F]{64}$", - "description": "A unique 32 bytes long hexadecimal string key." - }, - "name": { - "$ref": "#/$defs/NonEmptyString", - "description": "The human-readable name of the parameter." - }, - "type": { - "type": "string", - "description": "The human-readable ABI description of the parameter." - } - }, - "required": [ - "key", - "name", - "type" - ], - "additionalProperties": false + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreatePost` function." }, "processEditPostParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processCreatePostParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processEditPost` function." }, "processRemovePostParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processCreatePostParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemovePost` function." }, "processPostRuleChangesParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processCreatePostParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processPostRuleChanges` function." } @@ -244,6 +221,32 @@ "additionalProperties": false } ] + }, + "ContractKeyValuePairDescriptor": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/jsonschemas/rules/follow/1.0.0.json b/jsonschemas/rules/follow/1.0.0.json new file mode 100644 index 0000000..c1253d4 --- /dev/null +++ b/jsonschemas/rules/follow/1.0.0.json @@ -0,0 +1,229 @@ +{ + "type": "object", + "properties": { + "signature": { + "type": "string", + "minLength": 1, + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/follow/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "type": "string", + "minLength": 6, + "format": "uri", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processFollowParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ContractKeyValuePairDescriptor" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollow` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processFollowParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false, + "$defs": { + "NonEmptyString": { + "type": "string", + "minLength": 1 + }, + "MetadataAttribute": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Boolean" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "enum": [ + "true", + "false" + ], + "description": "A JS boolean value serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Date" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "type": "string", + "format": "date-time", + "description": "A valid ISO 8601 date string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Number" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A valid JS number serialized as string. It's consumer responsibility to parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "String" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "Any string value." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "JSON" + }, + "key": { + "$ref": "#/$defs/NonEmptyString", + "description": "The attribute's unique identifier." + }, + "value": { + "$ref": "#/$defs/NonEmptyString", + "description": "A JSON string. It's consumer responsibility to validate and parse it." + } + }, + "required": [ + "type", + "key", + "value" + ], + "additionalProperties": false + } + ] + }, + "ContractKeyValuePairDescriptor": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/jsonschemas/rules/graph/1.0.0.json b/jsonschemas/rules/graph/1.0.0.json index 79b5761..ece37b4 100644 --- a/jsonschemas/rules/graph/1.0.0.json +++ b/jsonschemas/rules/graph/1.0.0.json @@ -47,44 +47,21 @@ "processFollowParams": { "type": "array", "items": { - "type": "object", - "properties": { - "key": { - "type": "string", - "minLength": 66, - "maxLength": 66, - "pattern": "^0x[0-9a-fA-F]{64}$", - "description": "A unique 32 bytes long hexadecimal string key." - }, - "name": { - "$ref": "#/$defs/NonEmptyString", - "description": "The human-readable name of the parameter." - }, - "type": { - "type": "string", - "description": "The human-readable ABI description of the parameter." - } - }, - "required": [ - "key", - "name", - "type" - ], - "additionalProperties": false + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollow` function." }, "processUnfollowParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processFollowParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processUnfollow` function." }, "processFollowRuleChangesParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processFollowParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollowRuleChanges` function." } @@ -236,6 +213,32 @@ "additionalProperties": false } ] + }, + "ContractKeyValuePairDescriptor": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/jsonschemas/rules/group/1.0.0.json b/jsonschemas/rules/group/1.0.0.json index 256ccac..97f235e 100644 --- a/jsonschemas/rules/group/1.0.0.json +++ b/jsonschemas/rules/group/1.0.0.json @@ -47,51 +47,28 @@ "processAdditionParams": { "type": "array", "items": { - "type": "object", - "properties": { - "key": { - "type": "string", - "minLength": 66, - "maxLength": 66, - "pattern": "^0x[0-9a-fA-F]{64}$", - "description": "A unique 32 bytes long hexadecimal string key." - }, - "name": { - "$ref": "#/$defs/NonEmptyString", - "description": "The human-readable name of the parameter." - }, - "type": { - "type": "string", - "description": "The human-readable ABI description of the parameter." - } - }, - "required": [ - "key", - "name", - "type" - ], - "additionalProperties": false + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processAddition` function." }, "processRemovalParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processAdditionParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemoval` function." }, "processJoiningParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processAdditionParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processJoining` function." }, "processLeavingParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processAdditionParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processLeaving` function." } @@ -244,6 +221,32 @@ "additionalProperties": false } ] + }, + "ContractKeyValuePairDescriptor": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/jsonschemas/rules/namespace/1.0.0.json b/jsonschemas/rules/namespace/1.0.0.json index 7cc10bb..104a004 100644 --- a/jsonschemas/rules/namespace/1.0.0.json +++ b/jsonschemas/rules/namespace/1.0.0.json @@ -47,51 +47,28 @@ "processCreationParams": { "type": "array", "items": { - "type": "object", - "properties": { - "key": { - "type": "string", - "minLength": 66, - "maxLength": 66, - "pattern": "^0x[0-9a-fA-F]{64}$", - "description": "A unique 32 bytes long hexadecimal string key." - }, - "name": { - "$ref": "#/$defs/NonEmptyString", - "description": "The human-readable name of the parameter." - }, - "type": { - "type": "string", - "description": "The human-readable ABI description of the parameter." - } - }, - "required": [ - "key", - "name", - "type" - ], - "additionalProperties": false + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreation` function." }, "processRemovalParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processCreationParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemoval` function." }, "processAssigningParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processCreationParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processAssigning` function." }, "processUnassigningParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processCreationParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processUnassigning` function." } @@ -244,6 +221,32 @@ "additionalProperties": false } ] + }, + "ContractKeyValuePairDescriptor": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/jsonschemas/rules/post/1.0.0.json b/jsonschemas/rules/post/1.0.0.json index 5ccee34..4eeb7ce 100644 --- a/jsonschemas/rules/post/1.0.0.json +++ b/jsonschemas/rules/post/1.0.0.json @@ -47,37 +47,14 @@ "processCreatePostParams": { "type": "array", "items": { - "type": "object", - "properties": { - "key": { - "type": "string", - "minLength": 66, - "maxLength": 66, - "pattern": "^0x[0-9a-fA-F]{64}$", - "description": "A unique 32 bytes long hexadecimal string key." - }, - "name": { - "$ref": "#/$defs/NonEmptyString", - "description": "The human-readable name of the parameter." - }, - "type": { - "type": "string", - "description": "The human-readable ABI description of the parameter." - } - }, - "required": [ - "key", - "name", - "type" - ], - "additionalProperties": false + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreatePost` function." }, "processEditPostParams": { "type": "array", "items": { - "$ref": "#/properties/lens/properties/processCreatePostParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processEditPost` function." } @@ -228,6 +205,32 @@ "additionalProperties": false } ] + }, + "ContractKeyValuePairDescriptor": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/jsonschemas/schema.json b/jsonschemas/schema.json index 45ac5c9..c5d1dfc 100644 --- a/jsonschemas/schema.json +++ b/jsonschemas/schema.json @@ -3599,44 +3599,21 @@ "configureParams": { "type": "array", "items": { - "type": "object", - "properties": { - "key": { - "type": "string", - "minLength": 66, - "maxLength": 66, - "pattern": "^0x[0-9a-fA-F]{64}$", - "description": "A unique 32 bytes long hexadecimal string key." - }, - "name": { - "$ref": "#/$defs/NonEmptyString", - "description": "The human-readable name of the parameter." - }, - "type": { - "type": "string", - "description": "The human-readable ABI description of the parameter." - } - }, - "required": [ - "key", - "name", - "type" - ], - "additionalProperties": false + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "An optional list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `configure` function." }, "executeParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `execute` function." }, "setDisabledParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "An optional list of `ContractKeyValuePairDescriptor` that describes the `params` argument of the `setDisabledParams` function." } @@ -3711,28 +3688,28 @@ "processCreatePostParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreatePost` function." }, "processEditPostParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processEditPost` function." }, "processRemovePostParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemovePost` function." }, "processPostRuleChangesParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processPostRuleChanges` function." } @@ -3758,6 +3735,75 @@ ], "additionalProperties": false }, + { + "type": "object", + "properties": { + "signature": { + "$ref": "#/$defs/Signature", + "description": "A cryptographic signature of the Lens metadata." + }, + "$schema": { + "type": "string", + "const": "https://json-schemas.lens.dev/rules/follow/1.0.0.json" + }, + "lens": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/NonEmptyString", + "description": "A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "A short name for the Rule." + }, + "title": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-friendly title for the Rule." + }, + "description": { + "$ref": "#/$defs/NonEmptyString", + "description": "Markdown formatted description of the Rule." + }, + "authors": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "description": "List of authors email addresses." + }, + "source": { + "$ref": "#/$defs/URI", + "description": "The link to the Rule source code. Typically a GitHub repository." + }, + "processFollowParams": { + "type": "array", + "items": { + "$ref": "#/$defs/ContractKeyValuePairDescriptor" + }, + "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollow` function." + } + }, + "required": [ + "id", + "name", + "title", + "description", + "authors", + "source", + "processFollowParams" + ], + "additionalProperties": false + } + }, + "required": [ + "$schema", + "lens" + ], + "additionalProperties": false + }, { "type": "object", "properties": { @@ -3804,21 +3850,21 @@ "processFollowParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollow` function." }, "processUnfollowParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processUnfollow` function." }, "processFollowRuleChangesParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollowRuleChanges` function." } @@ -3889,28 +3935,28 @@ "processAdditionParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processAddition` function." }, "processRemovalParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemoval` function." }, "processJoiningParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processJoining` function." }, "processLeavingParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processLeaving` function." } @@ -3982,28 +4028,28 @@ "processCreationParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreation` function." }, "processRemovalParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processRemoval` function." }, "processAssigningParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processAssigning` function." }, "processUnassigningParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processUnassigning` function." } @@ -4075,14 +4121,14 @@ "processCreatePostParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processCreatePost` function." }, "processEditPostParams": { "type": "array", "items": { - "$ref": "#/$defs/ActionMetadata/properties/lens/properties/configureParams/items" + "$ref": "#/$defs/ContractKeyValuePairDescriptor" }, "description": "A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processEditPost` function." } @@ -4107,6 +4153,32 @@ "additionalProperties": false } ] + }, + "ContractKeyValuePairDescriptor": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[0-9a-fA-F]{64}$", + "description": "A unique 32 bytes long hexadecimal string key." + }, + "name": { + "$ref": "#/$defs/NonEmptyString", + "description": "The human-readable name of the parameter." + }, + "type": { + "type": "string", + "description": "The human-readable ABI description of the parameter." + } + }, + "required": [ + "key", + "name", + "type" + ], + "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/scripts/build.ts b/scripts/build.ts index b924d56..f3880d3 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -16,13 +16,17 @@ import { ChainIdSchema, CheckingInSchema, ContentWarningSchema, + ContractKeyValuePairDescriptorSchema, EmbedSchema, EventSchema, EvmAddressSchema, FeedMetadataSchema, + FeedRuleMetadataSchema, GeoURISchema, GraphMetadataSchema, + GraphRuleMetadataSchema, GroupMetadataSchema, + GroupRuleMetadataSchema, ImageSchema, LinkSchema, LiveStreamSchema, @@ -35,11 +39,13 @@ import { MetadataIdSchema, MetadataLicenseTypeSchema, MintSchema, + NamespaceRuleMetadataSchema, Nft721MetadataAttributeSchema, NonEmptyStringSchema, PhysicalAddressSchema, PostMainFocusSchema, PostMetadataSchema, + RuleMetadataSchema, SignatureSchema, SpaceSchema, SponsorshipMetadataSchema, @@ -52,13 +58,7 @@ import { UsernameMetadataSchema, VideoSchema, } from '../src'; -import { - FeedRuleMetadataSchema, - GroupRuleMetadataSchema, - NamespaceRuleMetadataSchema, - RuleMetadataSchema, -} from '../src/rule'; -import { GraphRuleMetadataSchema } from '../src/rule/GraphRuleMetadataSchema'; +import { FollowRuleMetadataSchema } from '../src/rule/FollowRuleMetadataSchema'; import { PostRuleMetadataSchema } from '../src/rule/PostRuleMetadataSchema'; const outputDir = 'jsonschemas'; @@ -151,6 +151,7 @@ for (const [path, Schema] of others) { const modules = new Map>([ ['action/1.0.0.json', ActionMetadataSchema], ['rules/feed/1.0.0.json', FeedRuleMetadataSchema], + ['rules/follow/1.0.0.json', FollowRuleMetadataSchema], ['rules/graph/1.0.0.json', GraphRuleMetadataSchema], ['rules/group/1.0.0.json', GroupRuleMetadataSchema], ['rules/namespace/1.0.0.json', NamespaceRuleMetadataSchema], @@ -168,6 +169,7 @@ for (const [path, Schema] of modules) { definitions: { NonEmptyString: NonEmptyStringSchema, MetadataAttribute: MetadataAttributeSchema, + ContractKeyValuePairDescriptor: ContractKeyValuePairDescriptorSchema, }, }); @@ -233,6 +235,7 @@ async function generateUmbrellaSchema() { ActionMetadata: ActionMetadataSchema, // Rules schemas RuleMetadata: RuleMetadataSchema, + ContractKeyValuePairDescriptor: ContractKeyValuePairDescriptorSchema, }, }); diff --git a/src/builders/index.ts b/src/builders/index.ts index f87940e..40eed71 100644 --- a/src/builders/index.ts +++ b/src/builders/index.ts @@ -5,6 +5,7 @@ export * from './feed.js'; export * from './graph.js'; export * from './group.js'; export * from './posts.js'; +export * from './rules.js'; export * from './sponsorship.js'; export * from './username.js'; export { ValidationError } from './ValidationError.js'; diff --git a/src/builders/rules.ts b/src/builders/rules.ts index 51c5767..4fb566c 100644 --- a/src/builders/rules.ts +++ b/src/builders/rules.ts @@ -5,6 +5,11 @@ import { type FeedRuleMetadataDetails, FeedRuleMetadataSchema, } from '../rule/FeedRuleMetadataSchema.js'; +import { + type FollowRuleMetadata, + type FollowRuleMetadataDetails, + FollowRuleMetadataSchema, +} from '../rule/FollowRuleMetadataSchema.js'; import { type GraphRuleMetadata, type GraphRuleMetadataDetails, @@ -324,3 +329,58 @@ export function postRule({ id = v4(), ...others }: PostRuleOptions): PostRuleMet }), ); } +/** + * @private + * @privateRemarks MUST stay very @private to produce usable docs + */ +type FollowRuleDetails = Prettify>>; + +export type FollowRuleOptions = FollowRuleDetails & { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. + * + * @defaultValue a UUID + */ + id?: string; +}; + +/** + * Creates a valid FollowRuleMetadata. + * + * @category Compose + * @param input - Use your IDE suggestions for an enhanced development experience + * + * @example + * ```ts + * const metadata = followRule({ + * name: 'MyFollowRule', + * title: 'This is my Follow Rule', + * description: 'Get ready for the future of social interaction!', + * authors: ['awesome-dev@lens.xyz'], + * source: 'https://github.com/foobarbaz/my-open-action', + * processFollowParams: [ + * { + * key: '83b03721c31435de384ca9cc3799cdfa10e19123e6a48dbf11589e36a0ef0b95', + * name: 'recipient', + * type: 'address', + * }, + * { + * key: 'e4ddce99520beb836fc879fc2a7d0743f784ffb925f96544bb5ff27c441c8c99', + * name: 'fee', + * type: 'address token, uint256 value', + * } + * ], + * }); + * ``` + */ +export function followRule({ id = v4(), ...others }: FollowRuleOptions): FollowRuleMetadata { + return evaluate( + FollowRuleMetadataSchema.safeParse({ + $schema: RuleMetadataSchemaId.POST_LATEST, + lens: { + id, + ...others, + }, + }), + ); +} diff --git a/src/index.ts b/src/index.ts index 966e6e1..aa3d998 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ export * from './graph/index.js'; export * from './MetadataAttribute.js'; export * from './post/index.js'; export * from './primitives.js'; +export * from './rule/index.js'; export * from './signMetadata.js'; export * from './sponsorship/index.js'; export * from './tokens/eip721.js'; diff --git a/src/rule/FollowRuleMetadataSchema.ts b/src/rule/FollowRuleMetadataSchema.ts new file mode 100644 index 0000000..6b50e0b --- /dev/null +++ b/src/rule/FollowRuleMetadataSchema.ts @@ -0,0 +1,95 @@ +import { z } from 'zod'; + +import { rootSchema } from '../common'; +import { + type ContractKeyValuePairDescriptor, + ContractKeyValuePairDescriptorSchema, + type Markdown, + MarkdownSchema, + NonEmptyStringSchema, + type Signature, + type URI, + URISchema, +} from '../primitives'; +import { RuleMetadataSchemaId } from './RuleMetadataSchemaId'; + +export type FollowRuleMetadataDetails = { + /** + * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure. + */ + id: string; + /** + * A short name for the Rule. + */ + name: string; + /** + * The human-friendly title for the Rule. + */ + title: string; + /** + * Markdown formatted description of the Rule. + * + * It should explain what this Rule does, how to use it, examples just + * like you would if you were building an NPM package. + * The more detail the better to allow dApp to easily integrate it. + */ + description: Markdown; + /** + * List of authors email addresses. + */ + authors: string[]; + /** + * The link to the Rule source code. Typically a GitHub repository. + */ + source: URI; + /** + * A list of {@link ContractKeyValuePairDescriptor} that describes the `ruleParams` argument of the `processFollow` function. + * + * ```sol + * function processFollow( + * bytes32 configSalt, + * address originalMsgSender, + * address followerAccount, + * address accountToFollow, + * KeyValue[] calldata primitiveParams, + * KeyValue[] calldata ruleParams + * ) external; + * ``` + * + * This will be used to know how to encode and decode the params for the `processFollow` function. + * + * @see https://abitype.dev/api/human + */ + processFollowParams: ContractKeyValuePairDescriptor[]; +}; + +const FollowRuleMetadataDetailsSchema: z.ZodType = + z.object({ + id: NonEmptyStringSchema.describe( + 'A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure.', + ), + name: NonEmptyStringSchema.describe('A short name for the Rule.'), + title: NonEmptyStringSchema.describe('The human-friendly title for the Rule.'), + description: MarkdownSchema.describe('Markdown formatted description of the Rule.'), + authors: z + .array(z.string().email('Authors list should only contain valid emails')) + .min(1, 'You must supply at least one author') + .describe('List of authors email addresses.'), + source: URISchema.describe('The link to the Rule source code. Typically a GitHub repository.'), + processFollowParams: z + .array(ContractKeyValuePairDescriptorSchema) + .describe( + 'A list of `ContractKeyValuePairDescriptor` that describes the `ruleParams` argument of the `processFollow` function.', + ), + }); + +export type FollowRuleMetadata = { + $schema: RuleMetadataSchemaId.FOLLOW_LATEST; + lens: FollowRuleMetadataDetails; + signature?: Signature; +}; + +export const FollowRuleMetadataSchema = rootSchema({ + $schema: z.literal(RuleMetadataSchemaId.FOLLOW_LATEST), + lens: FollowRuleMetadataDetailsSchema, +}); diff --git a/src/rule/index.ts b/src/rule/index.ts index 11c7bcf..f404b01 100644 --- a/src/rule/index.ts +++ b/src/rule/index.ts @@ -1,5 +1,6 @@ import { z } from 'zod'; import { type FeedRuleMetadata, FeedRuleMetadataSchema } from './FeedRuleMetadataSchema.js'; +import { type FollowRuleMetadata, FollowRuleMetadataSchema } from './FollowRuleMetadataSchema.js'; import { type GraphRuleMetadata, GraphRuleMetadataSchema } from './GraphRuleMetadataSchema.js'; import { type GroupRuleMetadata, GroupRuleMetadataSchema } from './GroupRuleMetadataSchema.js'; import { @@ -19,6 +20,7 @@ export * from './RuleMetadataSchemaId.js'; */ export type RuleMetadata = | FeedRuleMetadata + | FollowRuleMetadata | GraphRuleMetadata | GroupRuleMetadata | NamespaceRuleMetadata @@ -30,6 +32,7 @@ export type RuleMetadata = export const RuleMetadataSchema: z.ZodType = z.discriminatedUnion('$schema', [ FeedRuleMetadataSchema, + FollowRuleMetadataSchema, GraphRuleMetadataSchema, GroupRuleMetadataSchema, NamespaceRuleMetadataSchema, From 5ee3d68926669643e5c66861e963476465e0a25a Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Tue, 14 Jan 2025 21:57:37 +0100 Subject: [PATCH 10/14] feat: renames UsernameMetadata into NamespaceMetadata --- .../{username => namespace}/1.0.0.json | 2 +- jsonschemas/schema.json | 4 +-- scripts/build.ts | 8 ++--- src/builders/index.ts | 2 +- src/builders/{username.ts => namespace.ts} | 32 +++++++++++-------- src/index.ts | 2 +- .../NamespaceMetadataSchema.ts} | 22 ++++++------- .../NamespaceMetadataSchemaId.ts} | 4 +-- src/namespace/index.ts | 2 ++ src/username/index.ts | 2 -- 10 files changed, 42 insertions(+), 38 deletions(-) rename jsonschemas/{username => namespace}/1.0.0.json (98%) rename src/builders/{username.ts => namespace.ts} (67%) rename src/{username/UsernameMetadataSchema.ts => namespace/NamespaceMetadataSchema.ts} (52%) rename src/{username/UsernameMetadataSchemaId.ts => namespace/NamespaceMetadataSchemaId.ts} (55%) create mode 100644 src/namespace/index.ts delete mode 100644 src/username/index.ts diff --git a/jsonschemas/username/1.0.0.json b/jsonschemas/namespace/1.0.0.json similarity index 98% rename from jsonschemas/username/1.0.0.json rename to jsonschemas/namespace/1.0.0.json index e65dcf8..29b407e 100644 --- a/jsonschemas/username/1.0.0.json +++ b/jsonschemas/namespace/1.0.0.json @@ -52,7 +52,7 @@ }, "description": { "$ref": "#/$defs/NonEmptyString", - "description": "An optional description of the Username collection." + "description": "An optional description of the username Namespace." } }, "required": [ diff --git a/jsonschemas/schema.json b/jsonschemas/schema.json index c5d1dfc..a7cc84a 100644 --- a/jsonschemas/schema.json +++ b/jsonschemas/schema.json @@ -3486,7 +3486,7 @@ ], "additionalProperties": false }, - "UsernameMetadata": { + "NamespaceMetadata": { "type": "object", "properties": { "name": { @@ -3537,7 +3537,7 @@ }, "description": { "$ref": "#/$defs/NonEmptyString", - "description": "An optional description of the Username collection." + "description": "An optional description of the username Namespace." } }, "required": [ diff --git a/scripts/build.ts b/scripts/build.ts index f3880d3..99ad0f1 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -39,6 +39,7 @@ import { MetadataIdSchema, MetadataLicenseTypeSchema, MintSchema, + NamespaceMetadataSchema, NamespaceRuleMetadataSchema, Nft721MetadataAttributeSchema, NonEmptyStringSchema, @@ -55,7 +56,6 @@ import { ThreeDSchema, TransactionSchema, URISchema, - UsernameMetadataSchema, VideoSchema, } from '../src'; import { FollowRuleMetadataSchema } from '../src/rule/FollowRuleMetadataSchema'; @@ -121,11 +121,11 @@ await generateUmbrellaSchema(); const others = new Map>([ ['account/1.0.0.json', AccountMetadataSchema], ['app/1.0.0.json', AppMetadataSchema], - ['graph/1.0.0.json', GraphMetadataSchema], ['feed/1.0.0.json', FeedMetadataSchema], + ['graph/1.0.0.json', GraphMetadataSchema], ['group/1.0.0.json', GroupMetadataSchema], + ['namespace/1.0.0.json', NamespaceMetadataSchema], ['sponsorship/1.0.0.json', SponsorshipMetadataSchema], - ['username/1.0.0.json', UsernameMetadataSchema], ]); for (const [path, Schema] of others) { @@ -230,7 +230,7 @@ async function generateUmbrellaSchema() { FeedMetadata: FeedMetadataSchema, GroupMetadata: GroupMetadataSchema, SponsorshipMetadata: SponsorshipMetadataSchema, - UsernameMetadata: UsernameMetadataSchema, + NamespaceMetadata: NamespaceMetadataSchema, // Actions schemas ActionMetadata: ActionMetadataSchema, // Rules schemas diff --git a/src/builders/index.ts b/src/builders/index.ts index 40eed71..2375873 100644 --- a/src/builders/index.ts +++ b/src/builders/index.ts @@ -4,8 +4,8 @@ export * from './app.js'; export * from './feed.js'; export * from './graph.js'; export * from './group.js'; +export * from './namespace.js'; export * from './posts.js'; export * from './rules.js'; export * from './sponsorship.js'; -export * from './username.js'; export { ValidationError } from './ValidationError.js'; diff --git a/src/builders/username.ts b/src/builders/namespace.ts similarity index 67% rename from src/builders/username.ts rename to src/builders/namespace.ts index f1e0ac3..ca7bb25 100644 --- a/src/builders/username.ts +++ b/src/builders/namespace.ts @@ -1,11 +1,11 @@ import { v4 } from 'uuid'; -import type { Eip7572 } from '../tokens/eip7572'; import { - type UsernameMetadata, - UsernameMetadataSchema, - UsernameMetadataSchemaId, -} from '../username'; + type NamespaceMetadata, + NamespaceMetadataSchema, + NamespaceMetadataSchemaId, +} from '../namespace/index.js'; +import type { Eip7572 } from '../tokens/eip7572'; import { evaluate } from './ValidationError'; import type { RecursiveUnbrand } from './utils'; @@ -15,7 +15,7 @@ import type { RecursiveUnbrand } from './utils'; */ type CollectionDetails = RecursiveUnbrand; -export type UsernameOptions = { +export type NamespaceOptions = { /** * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. * @@ -23,7 +23,7 @@ export type UsernameOptions = { */ id?: string; /** - * Optional markdown formatted description of the Username. + * Optional markdown formatted description of the Namespace. */ description?: string; @@ -34,10 +34,10 @@ export type UsernameOptions = { }; /** - * Creates a valid UsernameMetadata. + * Creates a valid NamespaceMetadata. * * ```ts - * const metadata = username({ + * const metadata = namespace({ * description: 'A collection of usernames', * }); * ``` @@ -45,10 +45,10 @@ export type UsernameOptions = { * With NFT contract-level metadata: * * ```ts - * const metadata = username({ + * const metadata = namespace({ * description: 'A collection of usernames', * collection: { - * name: 'Lens Usernames', + * name: 'Lens Namespace', * description: 'The official lens/ usernames', * } * }); @@ -58,10 +58,14 @@ export type UsernameOptions = { * @category Compose * @param input - Use your IDE suggestions for an enhanced development experience */ -export function username({ collection, id = v4(), ...others }: UsernameOptions): UsernameMetadata { +export function namespace({ + collection, + id = v4(), + ...others +}: NamespaceOptions): NamespaceMetadata { return evaluate( - UsernameMetadataSchema.safeParse({ - $schema: UsernameMetadataSchemaId.LATEST, + NamespaceMetadataSchema.safeParse({ + $schema: NamespaceMetadataSchemaId.LATEST, ...collection, lens: { id, diff --git a/src/index.ts b/src/index.ts index aa3d998..ceae672 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,7 @@ export * from './feed/index.js'; export * from './formatters.js'; export * from './graph/index.js'; export * from './MetadataAttribute.js'; +export * from './namespace/index.js'; export * from './post/index.js'; export * from './primitives.js'; export * from './rule/index.js'; @@ -15,5 +16,4 @@ export * from './signMetadata.js'; export * from './sponsorship/index.js'; export * from './tokens/eip721.js'; export * from './tokens/eip7572.js'; -export * from './username/index.js'; export type { Brand, DistributiveOmit, Overwrite, Prettify, TwoAtLeastArray } from './utils.js'; diff --git a/src/username/UsernameMetadataSchema.ts b/src/namespace/NamespaceMetadataSchema.ts similarity index 52% rename from src/username/UsernameMetadataSchema.ts rename to src/namespace/NamespaceMetadataSchema.ts index 2f1df6d..cf4ecd7 100644 --- a/src/username/UsernameMetadataSchema.ts +++ b/src/namespace/NamespaceMetadataSchema.ts @@ -2,38 +2,38 @@ import { z } from 'zod'; import { NonEmptyStringSchema, type Signature, SignatureSchema } from '../primitives'; import { type Eip7572, eip7572SchemaWith } from '../tokens/eip7572'; -import { UsernameMetadataSchemaId } from './UsernameMetadataSchemaId'; +import { NamespaceMetadataSchemaId } from './NamespaceMetadataSchemaId'; -export type UsernameMetadataDetails = { +export type NamespaceMetadataDetails = { /** * A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure. */ id: string; /** - * An optional description of the Username collection. + * An optional description of the username Namespace. */ description?: string; }; -const UsernameMetadataDetailsSchema: z.ZodType = +const NamespaceMetadataDetailsSchema: z.ZodType = z.object({ id: NonEmptyStringSchema.describe( 'A unique identifier that in storages like IPFS ensures the uniqueness of the metadata URI. Use a UUID if unsure.', ), description: NonEmptyStringSchema.optional().describe( - 'An optional description of the Username collection.', + 'An optional description of the username Namespace.', ), }); -export type UsernameMetadata = Eip7572 & { - $schema: UsernameMetadataSchemaId.LATEST; - lens: UsernameMetadataDetails; +export type NamespaceMetadata = Eip7572 & { + $schema: NamespaceMetadataSchemaId.LATEST; + lens: NamespaceMetadataDetails; signature?: Signature; }; -export const UsernameMetadataSchema: z.ZodType = +export const NamespaceMetadataSchema: z.ZodType = eip7572SchemaWith({ - $schema: z.literal(UsernameMetadataSchemaId.LATEST), - lens: UsernameMetadataDetailsSchema, + $schema: z.literal(NamespaceMetadataSchemaId.LATEST), + lens: NamespaceMetadataDetailsSchema, signature: SignatureSchema.optional(), }); diff --git a/src/username/UsernameMetadataSchemaId.ts b/src/namespace/NamespaceMetadataSchemaId.ts similarity index 55% rename from src/username/UsernameMetadataSchemaId.ts rename to src/namespace/NamespaceMetadataSchemaId.ts index fbefe7c..37910de 100644 --- a/src/username/UsernameMetadataSchemaId.ts +++ b/src/namespace/NamespaceMetadataSchemaId.ts @@ -1,8 +1,8 @@ import { SchemasRoot } from '../constants'; /** - * The Lens Username Metadata Schema Id. + * The Lens Namespace Metadata Schema Id. */ -export enum UsernameMetadataSchemaId { +export enum NamespaceMetadataSchemaId { LATEST = `${SchemasRoot}/username/1.0.0.json`, } diff --git a/src/namespace/index.ts b/src/namespace/index.ts new file mode 100644 index 0000000..52c54d5 --- /dev/null +++ b/src/namespace/index.ts @@ -0,0 +1,2 @@ +export * from './NamespaceMetadataSchema'; +export * from './NamespaceMetadataSchemaId'; diff --git a/src/username/index.ts b/src/username/index.ts deleted file mode 100644 index db63606..0000000 --- a/src/username/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './UsernameMetadataSchema'; -export * from './UsernameMetadataSchemaId'; From 5d3e6e716e3a6185a881ca8e4cfbdbb42b0c0039 Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Tue, 14 Jan 2025 22:00:33 +0100 Subject: [PATCH 11/14] chore: adds changeset --- .changeset/fair-pumas-bake.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fair-pumas-bake.md diff --git a/.changeset/fair-pumas-bake.md b/.changeset/fair-pumas-bake.md new file mode 100644 index 0000000..9bf35ed --- /dev/null +++ b/.changeset/fair-pumas-bake.md @@ -0,0 +1,5 @@ +--- +'@lens-protocol/metadata': patch +--- + +**feat:** ActionMetadata, FeedRuleMetadata, GraphRuleMetadata, GroupRuleMetadata, NamespaceRuleMetadata, PostRuleMetadata, FollowRuleMetadata specs. Renames UsernameMetadata into NamespaceMetadata. From 87c8b68afe1488ba570eb5783db3c67de3d67b31 Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Tue, 14 Jan 2025 22:06:30 +0100 Subject: [PATCH 12/14] fix: missing exports --- src/rule/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rule/index.ts b/src/rule/index.ts index f404b01..91b8c36 100644 --- a/src/rule/index.ts +++ b/src/rule/index.ts @@ -10,9 +10,11 @@ import { import { type PostRuleMetadata, PostRuleMetadataSchema } from './PostRuleMetadataSchema.js'; export * from './FeedRuleMetadataSchema.js'; +export * from './FollowRuleMetadataSchema.js'; export * from './GraphRuleMetadataSchema.js'; export * from './GroupRuleMetadataSchema.js'; export * from './NamespaceRuleMetadataSchema.js'; +export * from './PostRuleMetadataSchema.js'; export * from './RuleMetadataSchemaId.js'; /** From 714f54b11b53b6adc0f011c816c942c751686551 Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Tue, 14 Jan 2025 22:07:39 +0100 Subject: [PATCH 13/14] chore: update docs --- docs/assets/highlight.css | 28 +-- docs/assets/navigation.js | 2 +- docs/assets/search.js | 2 +- docs/classes/ValidationError.html | 10 +- ...maId.html => AccountMetadataSchemaId.html} | 22 +-- ...emaId.html => ActionMetadataSchemaId.html} | 28 +-- docs/enums/AppMetadataSchemaId.html | 10 +- docs/enums/ContentWarning.html | 10 +- docs/enums/FeedMetadataSchemaId.html | 10 +- docs/enums/GraphMetadataSchemaId.html | 10 +- docs/enums/GroupMetadataSchemaId.html | 10 +- docs/enums/MediaAudioKind.html | 10 +- docs/enums/MediaAudioMimeType.html | 10 +- docs/enums/MediaImageMimeType.html | 10 +- docs/enums/MediaVideoMimeType.html | 10 +- docs/enums/MetadataAttributeType.html | 10 +- docs/enums/MetadataLicenseType.html | 10 +- docs/enums/MetadataTransactionType.html | 10 +- ...Id.html => NamespaceMetadataSchemaId.html} | 24 +-- .../NftMetadataAttributeDisplayType.html | 10 +- docs/enums/Platform.html | 10 +- docs/enums/PostMainFocus.html | 10 +- ...chemaId.html => PostMetadataSchemaId.html} | 78 ++++----- docs/enums/RuleMetadataSchemaId.html | 117 +++++++++++++ docs/enums/SponsorshipMetadataSchemaId.html | 10 +- docs/enums/ThreeDFormat.html | 10 +- docs/functions/account.html | 14 +- docs/functions/{module.html => action.html} | 28 +-- docs/functions/app.html | 12 +- docs/functions/article.html | 12 +- docs/functions/audio.html | 14 +- docs/functions/checkingIn.html | 14 +- docs/functions/embed.html | 12 +- docs/functions/event.html | 14 +- docs/functions/feed.html | 12 +- docs/functions/feedRule.html | 76 +++++++++ docs/functions/followRule.html | 76 +++++++++ docs/functions/formatZodError.html | 12 +- docs/functions/geoPoint-1.html | 12 +- docs/functions/geoUri-1.html | 14 +- docs/functions/graph.html | 12 +- docs/functions/graphRule.html | 76 +++++++++ docs/functions/group.html | 12 +- docs/functions/groupRule.html | 76 +++++++++ docs/functions/image.html | 14 +- docs/functions/lensMessage.html | 10 +- docs/functions/link.html | 12 +- docs/functions/liveStream.html | 12 +- docs/functions/mainContentFocus.html | 10 +- docs/functions/mint.html | 12 +- .../{username.html => namespace.html} | 30 ++-- docs/functions/namespaceRule.html | 76 +++++++++ docs/functions/postRule.html | 76 +++++++++ docs/functions/shortVideo.html | 12 +- docs/functions/signMetadata.html | 10 +- docs/functions/space.html | 12 +- docs/functions/sponsorship.html | 12 +- docs/functions/story.html | 12 +- docs/functions/textOnly.html | 12 +- docs/functions/threeD.html | 12 +- docs/functions/transaction.html | 12 +- docs/functions/video.html | 14 +- docs/index.html | 72 +++++--- docs/types/AccountMetadata.html | 14 +- docs/types/AccountMetadataDetails.html | 10 +- docs/types/AccountOptions.html | 10 +- ...etworkAddress.html => ActionMetadata.html} | 35 ++-- ...tadata.html => ActionMetadataDetails.html} | 100 ++++++----- ...{ModuleOptions.html => ActionOptions.html} | 35 ++-- docs/types/Amount.html | 75 -------- docs/types/AnyMedia.html | 10 +- docs/types/AppMetadata.html | 10 +- docs/types/AppMetadataDetails.html | 10 +- docs/types/AppOptions.html | 10 +- docs/types/ArticleMetadata.html | 14 +- docs/types/ArticleMetadataDetails.html | 10 +- docs/types/ArticleOptions.html | 10 +- docs/types/AudioMetadata.html | 14 +- docs/types/AudioMetadataDetails.html | 10 +- docs/types/AudioOptions.html | 10 +- docs/types/BooleanAttribute.html | 10 +- docs/types/{TokenId.html => Bytes32.html} | 22 +-- docs/types/ChainId.html | 12 +- docs/types/CheckingInMetadata.html | 14 +- docs/types/CheckingInMetadataDetails.html | 10 +- docs/types/CheckingInOptions.html | 10 +- .../types/ContractKeyValuePairDescriptor.html | 77 +++++++++ docs/types/DateAttribute.html | 10 +- docs/types/DateTime.html | 12 +- docs/types/Eip7572.html | 10 +- docs/types/EmbedMetadata.html | 14 +- docs/types/EmbedMetadataDetails.html | 10 +- docs/types/EmbedOptions.html | 10 +- docs/types/EventMetadata.html | 14 +- docs/types/EventMetadataDetails.html | 10 +- docs/types/EventOptions.html | 10 +- docs/types/EvmAddress.html | 12 +- docs/types/FeedMetadata.html | 10 +- docs/types/FeedMetadataDetails.html | 10 +- docs/types/FeedOptions.html | 10 +- ...ameMetadata.html => FeedRuleMetadata.html} | 24 +-- docs/types/FeedRuleMetadataDetails.html | 156 +++++++++++++++++ ...acyProfileId.html => FeedRuleOptions.html} | 31 ++-- docs/types/FollowRuleOptions.html | 69 ++++++++ docs/types/GeoPoint.html | 12 +- docs/types/GeoURI.html | 12 +- docs/types/GraphMetadata.html | 10 +- docs/types/GraphMetadataDetails.html | 10 +- docs/types/GraphOptions.html | 10 +- docs/types/GraphRuleMetadata.html | 67 ++++++++ docs/types/GraphRuleMetadataDetails.html | 143 ++++++++++++++++ docs/types/GraphRuleOptions.html | 69 ++++++++ docs/types/GroupMetadata.html | 10 +- docs/types/GroupMetadataDetails.html | 10 +- docs/types/GroupOptions.html | 10 +- docs/types/GroupRuleMetadata.html | 67 ++++++++ docs/types/GroupRuleMetadataDetails.html | 156 +++++++++++++++++ docs/types/GroupRuleOptions.html | 69 ++++++++ docs/types/ImageMetadata.html | 14 +- docs/types/ImageMetadataDetails.html | 10 +- docs/types/ImageOptions.html | 10 +- docs/types/JSONAttribute.html | 10 +- docs/types/LinkMetadata.html | 14 +- docs/types/LinkMetadataDetails.html | 10 +- docs/types/LinkOptions.html | 10 +- docs/types/LiveStreamMetadata.html | 14 +- docs/types/LiveStreamMetadataDetails.html | 12 +- docs/types/LiveStreamOptions.html | 10 +- docs/types/Locale.html | 14 +- docs/types/Markdown.html | 12 +- docs/types/MediaAudio.html | 10 +- docs/types/MediaImage.html | 10 +- docs/types/MediaVideo.html | 10 +- docs/types/MetadataAttribute.html | 10 +- docs/types/MintMetadata.html | 14 +- docs/types/MintMetadataDetails.html | 10 +- docs/types/MintOptions.html | 10 +- .../{Asset.html => NamespaceMetadata.html} | 35 ++-- ...ils.html => NamespaceMetadataDetails.html} | 22 +-- ...nameOptions.html => NamespaceOptions.html} | 22 +-- ...etails.html => NamespaceRuleMetadata.html} | 32 ++-- docs/types/NamespaceRuleMetadataDetails.html | 161 ++++++++++++++++++ docs/types/NamespaceRuleOptions.html | 69 ++++++++ docs/types/NftMetadata.html | 10 +- docs/types/NftMetadataAttribute.html | 10 +- docs/types/NumberAttribute.html | 10 +- docs/types/PhysicalAddress.html | 12 +- docs/types/PostMetadata.html | 14 +- docs/types/PostMetadataCommon.html | 10 +- docs/types/PostRuleOptions.html | 69 ++++++++ docs/types/SchedulingAdjustments.html | 10 +- docs/types/ShortVideoOptions.html | 10 +- docs/types/SignMessage.html | 10 +- docs/types/Signature.html | 12 +- docs/types/SolidityParameters.html | 73 ++++++++ docs/types/SpaceMetadata.html | 14 +- docs/types/SpaceMetadataDetails.html | 10 +- docs/types/SpaceOptions.html | 10 +- docs/types/SponsorshipMetadata.html | 10 +- docs/types/SponsorshipMetadataDetails.html | 10 +- docs/types/SponsorshipOptions.html | 10 +- docs/types/StoryMetadata.html | 14 +- docs/types/StoryMetadataDetails.html | 10 +- docs/types/StoryOptions.html | 10 +- docs/types/StringAttribute.html | 10 +- docs/types/Tag.html | 12 +- docs/types/TextOnlyMetadata.html | 14 +- docs/types/TextOnlyMetadataDetails.html | 10 +- docs/types/TextOnlyOptions.html | 10 +- docs/types/ThreeDAsset.html | 10 +- docs/types/ThreeDMetadata.html | 14 +- docs/types/ThreeDMetadataDetails.html | 10 +- docs/types/ThreeDOptions.html | 10 +- docs/types/TimezoneId.html | 10 +- docs/types/TransactionMetadata.html | 14 +- docs/types/TransactionMetadataDetails.html | 10 +- docs/types/TransactionOptions.html | 10 +- docs/types/TwoAtLeastArray.html | 10 +- docs/types/URI.html | 12 +- docs/types/VideoMetadata.html | 14 +- docs/types/VideoMetadataDetails.html | 10 +- docs/types/VideoOptions.html | 10 +- docs/variables/AccountMetadataSchema.html | 14 +- ...aSchema.html => ActionMetadataSchema.html} | 20 +-- docs/variables/AppMetadataSchema.html | 10 +- docs/variables/ContentWarningSchema.html | 10 +- docs/variables/DEFAULT_LOCALE.html | 10 +- docs/variables/FeedMetadataSchema.html | 10 +- ...chema.html => FeedRuleMetadataSchema.html} | 38 +++-- docs/variables/GraphMetadataSchema.html | 10 +- docs/variables/GraphRuleMetadataSchema.html | 76 +++++++++ .../variables/GroupMetadataDetailsSchema.html | 10 +- docs/variables/GroupMetadataSchema.html | 10 +- docs/variables/GroupRuleMetadataSchema.html | 76 +++++++++ docs/variables/MetadataAttributeSchema.html | 12 +- docs/variables/MetadataIdSchema.html | 10 +- .../NamespaceMetadataSchema.html} | 26 ++- .../NamespaceRuleMetadataSchema.html | 76 +++++++++ docs/variables/PostMainFocusSchema.html | 10 +- docs/variables/PostMetadataSchema.html | 14 +- .../variables/SpaceMetadataDetailsSchema.html | 10 +- docs/variables/SponsorshipMetadataSchema.html | 10 +- docs/variables/timezones.html | 10 +- 203 files changed, 3306 insertions(+), 1299 deletions(-) rename docs/enums/{AccountSchemaId.html => AccountMetadataSchemaId.html} (90%) rename docs/enums/{ModuleSchemaId.html => ActionMetadataSchemaId.html} (89%) rename docs/enums/{UsernameMetadataSchemaId.html => NamespaceMetadataSchemaId.html} (90%) rename docs/enums/{PostSchemaId.html => PostMetadataSchemaId.html} (83%) create mode 100644 docs/enums/RuleMetadataSchemaId.html rename docs/functions/{module.html => action.html} (82%) create mode 100644 docs/functions/feedRule.html create mode 100644 docs/functions/followRule.html create mode 100644 docs/functions/graphRule.html create mode 100644 docs/functions/groupRule.html rename docs/functions/{username.html => namespace.html} (87%) create mode 100644 docs/functions/namespaceRule.html create mode 100644 docs/functions/postRule.html rename docs/types/{NetworkAddress.html => ActionMetadata.html} (87%) rename docs/types/{ModuleMetadata.html => ActionMetadataDetails.html} (71%) rename docs/types/{ModuleOptions.html => ActionOptions.html} (89%) delete mode 100644 docs/types/Amount.html rename docs/types/{TokenId.html => Bytes32.html} (92%) create mode 100644 docs/types/ContractKeyValuePairDescriptor.html rename docs/types/{UsernameMetadata.html => FeedRuleMetadata.html} (89%) create mode 100644 docs/types/FeedRuleMetadataDetails.html rename docs/types/{LegacyProfileId.html => FeedRuleOptions.html} (89%) create mode 100644 docs/types/FollowRuleOptions.html create mode 100644 docs/types/GraphRuleMetadata.html create mode 100644 docs/types/GraphRuleMetadataDetails.html create mode 100644 docs/types/GraphRuleOptions.html create mode 100644 docs/types/GroupRuleMetadata.html create mode 100644 docs/types/GroupRuleMetadataDetails.html create mode 100644 docs/types/GroupRuleOptions.html rename docs/types/{Asset.html => NamespaceMetadata.html} (84%) rename docs/types/{UsernameMetadataDetails.html => NamespaceMetadataDetails.html} (89%) rename docs/types/{UsernameOptions.html => NamespaceOptions.html} (88%) rename docs/types/{NetworkAddressDetails.html => NamespaceRuleMetadata.html} (87%) create mode 100644 docs/types/NamespaceRuleMetadataDetails.html create mode 100644 docs/types/NamespaceRuleOptions.html create mode 100644 docs/types/PostRuleOptions.html create mode 100644 docs/types/SolidityParameters.html rename docs/variables/{ModuleMetadataSchema.html => ActionMetadataSchema.html} (93%) rename docs/variables/{UsernameMetadataSchema.html => FeedRuleMetadataSchema.html} (73%) create mode 100644 docs/variables/GraphRuleMetadataSchema.html create mode 100644 docs/variables/GroupRuleMetadataSchema.html rename docs/{types/LegacyPublicationId.html => variables/NamespaceMetadataSchema.html} (88%) create mode 100644 docs/variables/NamespaceRuleMetadataSchema.html diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css index 0c8b522..6c472ec 100644 --- a/docs/assets/highlight.css +++ b/docs/assets/highlight.css @@ -7,20 +7,20 @@ --dark-hl-2: #4FC1FF; --light-hl-3: #A31515; --dark-hl-3: #CE9178; - --light-hl-4: #098658; - --dark-hl-4: #B5CEA8; - --light-hl-5: #0451A5; - --dark-hl-5: #9CDCFE; - --light-hl-6: #AF00DB; - --dark-hl-6: #C586C0; - --light-hl-7: #267F99; - --dark-hl-7: #4EC9B0; - --light-hl-8: #0000FF; - --dark-hl-8: #569CD6; - --light-hl-9: #008000; - --dark-hl-9: #6A9955; - --light-hl-10: #795E26; - --dark-hl-10: #DCDCAA; + --light-hl-4: #0451A5; + --dark-hl-4: #9CDCFE; + --light-hl-5: #AF00DB; + --dark-hl-5: #C586C0; + --light-hl-6: #267F99; + --dark-hl-6: #4EC9B0; + --light-hl-7: #0000FF; + --dark-hl-7: #569CD6; + --light-hl-8: #008000; + --dark-hl-8: #6A9955; + --light-hl-9: #795E26; + --dark-hl-9: #DCDCAA; + --light-hl-10: #098658; + --dark-hl-10: #B5CEA8; --light-code-background: #FFFFFF; --dark-code-background: #1E1E1E; } diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js index 4b41cf7..397a0d3 100644 --- a/docs/assets/navigation.js +++ b/docs/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAE52aW3PkNBCF/4ufA2EDSyBvQy5bgdxqM1mqoChKsZUZMbbkkuRkZyn+O2XPeKxLt1reV59zPlst27Il/flvYflnW5wVi7JUnbSP5Zo37LoqjoqW2XVxVnDZNeY4kL9d26YujoqNkFVx9tN/RxOnbW+5ZRWzDGXFFpx3rqTl0v7OtBRyFaJ8FadccV5RlwV5cOIHzdo1hQRNKabqyOqBJpx5yyvBFl0l1G+9FsB8NYdyKxq+3LYcJ40OgnbdsBVP0jwHQfskKp6+Ns+Rou0qu7BWi+fOIkDARDNvRMmlSRIdC81baiYNK61QMsUMbAmuqrqaYzeer+KUuxcb1edCmLZmW+gqCTt+noea2RelmxA4Hk8klbG3TMgrVXYmirtimoFVytVwwmOrpFHarAX5zCesOH+51pxfXCndMBsCXQ0nPBmuJWs4dXmYDyd/YrWoWH9HXmqt9AQsa2YMN8eBwSe9O/FGnN3QNJ58Ytltyw8j1yj7pJPvfj599/4Ep11wy0RtCOjelcm+b/t2Ycy9SrKa3hwxhqNkVm6HV2KU3h8n89MAHiEmaQYFq3LkyGBi1T0oJENbUdYcbaEvz6RhLQVdmWysxZ5Ksozh8e3UHySTw6CPVcsVZ5GwSgGeLC5WJUejOL8oVXMmD8NUyAp1ine+ZkK6r9MdZn+YTvNyI+TqWmLFjx3zmUg3oMb8MyAdEhko4gWzHO0ST8whLUUDQvrjVP5StKfvT0/C+P4wmW6epx+QiOGKs0hIB0KeLC7Sba5Gcl45Pl574iwS1lLAk8XFWupoNKdZVJXmBqCMCsVw/0tDiqvN4SClAiw5VKRQjkRRPnD1oET8PTMez8g/fbwG0k8fr8ms+5MeIVxxFgkpMeTJ4iJFdjWa40wdxCBHnEVCWxp7srhoSyeN4uymDpCWeuIsEtJSyJPFRVrqahTn18f7O3T080SKdMNXrNw+aPUiah5/lQRyJq17rkU5/MehRNdCUoXcYN3qanM4SKcClhwq0qWORFNe+aPVnDV4S0PHfCbaasSYfwa0AoGBJKqS1dEtvTtKZW+Z3lTqTYbp8TiZP8xmRoSDksUYHmWQMShZjGHmEmQMCs0IZtdiVGAgiQL/fHO1ORzkfgQsOVTkHnQkkjLMdqKt9NQ8FnZNrkiR7rh9U3qDfFP66jwWUn/QRJJf0NvDkWZQ0FsX8pDcrnnmGkf6MkV7WG+NKFmNdEkgk7R+8hkpnavN4ZyrplHRmzB2UMx+VrfqaiFXi+qfztiGSxu1FzSR5LXSdniXIc9IZCCJYiVvuTHAy9eRcijMdhpkDAJJaFmJvkQ8cRYJeVghTxYXK7uj0ZxoiSLGRZavoKJtx5wzzoHWIXSQTKv0Fq2DK84iYW0HPFlcrL2ORnN0/7Bjb9NApmhLtgoJS7YiU/yzvZc1WvBQn8tDyo7YculI8QOZpA0reeDsvSPlUdD6eeo8FlY7yJRHxurmiiRJNPyLksBv7qSQDLXhwF/t/jCZnhbl0bLHlq+gYh2AOmecA+uKyEEy39TC3nBm7EJrto2AvkzRgKnAjHnAcBU7QgT6XB7SEYgtl450QSBTtN3mGKThnjiLhDQZ8mRxkcbO+TIMVu53WxUm4CvTgj3X8RL/zujTv/fA4a42EBqaEkB/bxvOhHwJ7MXl1eLpZvn3zf354uYSAvqOBCreMQfhYlcCCeyYg5iALQmNZ6JTbMyde4pMNgmNfm1xMGLNgF9XNHX0pHDejEgCCfgSWG83Fk4FbBSUvNLYlUBCv144GncnT4FsAoPPgJgTJ4C3cUF02JlA2/1XlYFoBzEBYLu38RR/6eTwgWGO95If/vEHN9y2YLBtU6Hd9hkwuJNSYX/q2InGM8desDzsfoDSk5pA8H4lHkoPQirYL2yDwV5IBF84fML+eCo2bD/8Q1XBHkAH4DkSqFW0fjxBRu2bd2nAkxZI/EmLdLgfjcBsLySDqgNvzUFIBIW/rDAFRbyq4AVrLk00MTbFHTkFEXIDpoXcJGPjChAcHtUEomFC7r93gs27Eyj0pHDILdNEWw782DCGgcFBSUTNYSYTik9qCjFMYIaf6g7E0UPM0W6DbXFWVLzVvGSWV4XL7gcmENoLqYuaxhs4fpBTkH7eCYz3QiJo93MmUHbUUvFh6gAMD0oqOv3qgvlJTkC6/XAKEUYtEX/FbqdX8E76639H8zDX9TMAAA==" \ No newline at end of file +window.navigationData = "data:application/octet-stream;base64,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" \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js index 7f3fd3b..5a684a3 100644 --- a/docs/assets/search.js +++ b/docs/assets/search.js @@ -1 +1 @@ -window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file +window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file diff --git a/docs/classes/ValidationError.html b/docs/classes/ValidationError.html index 365ef6a..566e1ce 100644 --- a/docs/classes/ValidationError.html +++ b/docs/classes/ValidationError.html @@ -98,7 +98,8 @@

Lens Protocol Metadata Standards
\ No newline at end of file diff --git a/docs/enums/AccountSchemaId.html b/docs/enums/AccountMetadataSchemaId.html similarity index 90% rename from docs/enums/AccountSchemaId.html rename to docs/enums/AccountMetadataSchemaId.html index 75095e0..eb72961 100644 --- a/docs/enums/AccountSchemaId.html +++ b/docs/enums/AccountMetadataSchemaId.html @@ -1,4 +1,4 @@ -AccountSchemaId | Lens Protocol Metadata Standards
+AccountMetadataSchemaId | Lens Protocol Metadata Standards
+
  • Defined in src/account/AccountMetadataSchemaId.ts:3
  • @@ -24,7 +24,7 @@

    Enumeration Members

    @@ -32,7 +32,7 @@

    Enumeration Members

    LATEST: "https://json-schemas.lens.dev/account/1.0.0.json"
    +
  • Defined in src/account/AccountMetadataSchemaId.ts:4
  • \ No newline at end of file diff --git a/docs/enums/ModuleSchemaId.html b/docs/enums/ActionMetadataSchemaId.html similarity index 89% rename from docs/enums/ModuleSchemaId.html rename to docs/enums/ActionMetadataSchemaId.html index f5cfe00..c1603d2 100644 --- a/docs/enums/ModuleSchemaId.html +++ b/docs/enums/ActionMetadataSchemaId.html @@ -1,4 +1,4 @@ -ModuleSchemaId | Lens Protocol Metadata Standards
    +ActionMetadataSchemaId | Lens Protocol Metadata Standards
    +
    +

    The Lens Action metadata schema id.

    +
    +
    +
  • Defined in src/action/ActionMetadataSchemaId.ts:6
  • @@ -24,15 +28,15 @@

    Enumeration Members

    -
    LATEST: "https://json-schemas.lens.dev/modules/1.0.0.json"
    +
  • Defined in src/action/ActionMetadataSchemaId.ts:7
  • \ No newline at end of file diff --git a/docs/enums/AppMetadataSchemaId.html b/docs/enums/AppMetadataSchemaId.html index 75f416d..f7cd622 100644 --- a/docs/enums/AppMetadataSchemaId.html +++ b/docs/enums/AppMetadataSchemaId.html @@ -57,7 +57,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/ContentWarning.html b/docs/enums/ContentWarning.html index 025c6b3..425ea8b 100644 --- a/docs/enums/ContentWarning.html +++ b/docs/enums/ContentWarning.html @@ -67,7 +67,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/FeedMetadataSchemaId.html b/docs/enums/FeedMetadataSchemaId.html index 23cc0a6..f57c474 100644 --- a/docs/enums/FeedMetadataSchemaId.html +++ b/docs/enums/FeedMetadataSchemaId.html @@ -53,7 +53,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/GraphMetadataSchemaId.html b/docs/enums/GraphMetadataSchemaId.html index 6bc4eca..c61d555 100644 --- a/docs/enums/GraphMetadataSchemaId.html +++ b/docs/enums/GraphMetadataSchemaId.html @@ -57,7 +57,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/GroupMetadataSchemaId.html b/docs/enums/GroupMetadataSchemaId.html index 9d28375..ba39845 100644 --- a/docs/enums/GroupMetadataSchemaId.html +++ b/docs/enums/GroupMetadataSchemaId.html @@ -53,7 +53,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/MediaAudioKind.html b/docs/enums/MediaAudioKind.html index 7e7a726..0d169f9 100644 --- a/docs/enums/MediaAudioKind.html +++ b/docs/enums/MediaAudioKind.html @@ -92,7 +92,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/MediaAudioMimeType.html b/docs/enums/MediaAudioMimeType.html index 7f68dd5..23d9eab 100644 --- a/docs/enums/MediaAudioMimeType.html +++ b/docs/enums/MediaAudioMimeType.html @@ -106,7 +106,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/MediaImageMimeType.html b/docs/enums/MediaImageMimeType.html index 5d419cf..f86aa44 100644 --- a/docs/enums/MediaImageMimeType.html +++ b/docs/enums/MediaImageMimeType.html @@ -113,7 +113,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/MediaVideoMimeType.html b/docs/enums/MediaVideoMimeType.html index d8da906..1c70585 100644 --- a/docs/enums/MediaVideoMimeType.html +++ b/docs/enums/MediaVideoMimeType.html @@ -120,7 +120,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/MetadataAttributeType.html b/docs/enums/MetadataAttributeType.html index d8d86fc..e071940 100644 --- a/docs/enums/MetadataAttributeType.html +++ b/docs/enums/MetadataAttributeType.html @@ -85,7 +85,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/MetadataLicenseType.html b/docs/enums/MetadataLicenseType.html index f94a5ec..b44fcfa 100644 --- a/docs/enums/MetadataLicenseType.html +++ b/docs/enums/MetadataLicenseType.html @@ -302,7 +302,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/MetadataTransactionType.html b/docs/enums/MetadataTransactionType.html index c935c91..68393a8 100644 --- a/docs/enums/MetadataTransactionType.html +++ b/docs/enums/MetadataTransactionType.html @@ -71,7 +71,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/UsernameMetadataSchemaId.html b/docs/enums/NamespaceMetadataSchemaId.html similarity index 90% rename from docs/enums/UsernameMetadataSchemaId.html rename to docs/enums/NamespaceMetadataSchemaId.html index 2557e64..9a9c261 100644 --- a/docs/enums/UsernameMetadataSchemaId.html +++ b/docs/enums/NamespaceMetadataSchemaId.html @@ -1,4 +1,4 @@ -UsernameMetadataSchemaId | Lens Protocol Metadata Standards
    +NamespaceMetadataSchemaId | Lens Protocol Metadata Standards
    -

    The Lens Username Metadata Schema Id.

    +

    The Lens Namespace Metadata Schema Id.

    +
  • Defined in src/namespace/NamespaceMetadataSchemaId.ts:6
  • @@ -28,7 +28,7 @@

    Enumeration Members

    @@ -36,7 +36,7 @@

    Enumeration Members

    LATEST: "https://json-schemas.lens.dev/username/1.0.0.json"
    +
  • Defined in src/namespace/NamespaceMetadataSchemaId.ts:7
  • \ No newline at end of file diff --git a/docs/enums/NftMetadataAttributeDisplayType.html b/docs/enums/NftMetadataAttributeDisplayType.html index 7b1202a..2a93fb0 100644 --- a/docs/enums/NftMetadataAttributeDisplayType.html +++ b/docs/enums/NftMetadataAttributeDisplayType.html @@ -73,7 +73,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/Platform.html b/docs/enums/Platform.html index bdee995..b05915e 100644 --- a/docs/enums/Platform.html +++ b/docs/enums/Platform.html @@ -67,7 +67,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/PostMainFocus.html b/docs/enums/PostMainFocus.html index c6333d0..4d4ff1e 100644 --- a/docs/enums/PostMainFocus.html +++ b/docs/enums/PostMainFocus.html @@ -162,7 +162,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/PostSchemaId.html b/docs/enums/PostMetadataSchemaId.html similarity index 83% rename from docs/enums/PostSchemaId.html rename to docs/enums/PostMetadataSchemaId.html index 68e5c73..1f7a7f9 100644 --- a/docs/enums/PostSchemaId.html +++ b/docs/enums/PostMetadataSchemaId.html @@ -1,4 +1,4 @@ -PostSchemaId | Lens Protocol Metadata Standards
    +PostMetadataSchemaId | Lens Protocol Metadata Standards

    Enumeration Members

    @@ -50,77 +50,77 @@

    Enumeration Members

    ARTICLE_LATEST: "https://json-schemas.lens.dev/posts/article/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:10
  • AUDIO_LATEST: "https://json-schemas.lens.dev/posts/audio/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:11
  • CHECKING_IN_LATEST: "https://json-schemas.lens.dev/posts/checking-in/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:12
  • EMBED_LATEST: "https://json-schemas.lens.dev/posts/embed/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:13
  • EVENT_LATEST: "https://json-schemas.lens.dev/posts/event/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:14
  • IMAGE_LATEST: "https://json-schemas.lens.dev/posts/image/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:15
  • LINK_LATEST: "https://json-schemas.lens.dev/posts/link/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:16
  • LIVESTREAM_LATEST: "https://json-schemas.lens.dev/posts/livestream/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:17
  • MINT_LATEST: "https://json-schemas.lens.dev/posts/mint/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:18
  • SPACE_LATEST: "https://json-schemas.lens.dev/posts/space/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:19
  • STORY_LATEST: "https://json-schemas.lens.dev/posts/story/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:20
  • TEXT_ONLY_LATEST: "https://json-schemas.lens.dev/posts/text-only/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:22
  • THREE_D_LATEST: "https://json-schemas.lens.dev/posts/3d/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:9
  • TRANSACTION_LATEST: "https://json-schemas.lens.dev/posts/transaction/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:21
  • VIDEO_LATEST: "https://json-schemas.lens.dev/posts/video/3.0.0.json"
    +
  • Defined in src/post/PostMetadataSchemaId.ts:23
  • \ No newline at end of file diff --git a/docs/enums/RuleMetadataSchemaId.html b/docs/enums/RuleMetadataSchemaId.html new file mode 100644 index 0000000..2ff22d0 --- /dev/null +++ b/docs/enums/RuleMetadataSchemaId.html @@ -0,0 +1,117 @@ +RuleMetadataSchemaId | Lens Protocol Metadata Standards
    +
    + +
    +
    +
    +
    + +

    Enumeration RuleMetadataSchemaId

    +
    +

    The Lens Rule metadata schema id.

    +
    +
    +
    +
    +
    + +
    +
    +

    Enumeration Members

    +
    + +
    FEED_LATEST: "https://json-schemas.lens.dev/rules/feed/1.0.0.json"
    +
    + +
    FOLLOW_LATEST: "https://json-schemas.lens.dev/rules/follow/1.0.0.json"
    +
    + +
    GRAPH_LATEST: "https://json-schemas.lens.dev/rules/graph/1.0.0.json"
    +
    + +
    GROUP_LATEST: "https://json-schemas.lens.dev/rules/group/1.0.0.json"
    +
    + +
    NAMESPACE_LATEST: "https://json-schemas.lens.dev/rules/namespace/1.0.0.json"
    +
    + +
    POST_LATEST: "https://json-schemas.lens.dev/rules/post/1.0.0.json"
    +
    +
    \ No newline at end of file diff --git a/docs/enums/SponsorshipMetadataSchemaId.html b/docs/enums/SponsorshipMetadataSchemaId.html index 5761f63..2f521f1 100644 --- a/docs/enums/SponsorshipMetadataSchemaId.html +++ b/docs/enums/SponsorshipMetadataSchemaId.html @@ -57,7 +57,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/enums/ThreeDFormat.html b/docs/enums/ThreeDFormat.html index 2b54b6b..31917dc 100644 --- a/docs/enums/ThreeDFormat.html +++ b/docs/enums/ThreeDFormat.html @@ -78,7 +78,8 @@

    Lens Protocol Metadata Standards
    \ No newline at end of file diff --git a/docs/functions/account.html b/docs/functions/account.html index bc019fa..ab07327 100644 --- a/docs/functions/account.html +++ b/docs/functions/account.html @@ -31,11 +31,11 @@

    input:

    Returns AccountMetadata

    -

    Example

    const metadata = account({
    name: 'John Doe',
    bio: `
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris.

    - Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    - Donec a diam lectus.
    `,
    }); +

    Example

    const metadata = account({
    name: 'John Doe',
    bio: `
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris.

    - Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    - Donec a diam lectus.
    `,
    });

    Example

    With attributes:

    -
    const metadata = account({
    name: 'John Doe',
    picture: 'https://example.com/picture.png',
    attributes: [
    {
    key: 'twitter',
    type: MetadataAttributeType.STRING,
    value: 'https://twitter.com/johndoe',
    },
    {
    key: 'dob',
    type: MetadataAttributeType.DATE,
    value: '1990-01-01T00:00:00Z',
    },
    {
    key: 'enabled',
    type: MetadataAttributeType.BOOLEAN,
    value: 'true',
    },
    {
    key: 'height',
    type: MetadataAttributeType.NUMBER,
    value: '1.8',
    },
    {
    key: 'settings',
    type: MetadataAttributeType.JSON,
    value: '{"theme": "dark"}',
    },
    ],
    }); +
    const metadata = account({
    name: 'John Doe',
    picture: 'https://example.com/picture.png',
    attributes: [
    {
    key: 'twitter',
    type: MetadataAttributeType.STRING,
    value: 'https://twitter.com/johndoe',
    },
    {
    key: 'dob',
    type: MetadataAttributeType.DATE,
    value: '1990-01-01T00:00:00Z',
    },
    {
    key: 'enabled',
    type: MetadataAttributeType.BOOLEAN,
    value: 'true',
    },
    {
    key: 'height',
    type: MetadataAttributeType.NUMBER,
    value: '1.8',
    },
    {
    key: 'settings',
    type: MetadataAttributeType.JSON,
    value: '{"theme": "dark"}',
    },
    ],
    });
    \ No newline at end of file diff --git a/docs/functions/app.html b/docs/functions/app.html index a6a5217..fc304d4 100644 --- a/docs/functions/app.html +++ b/docs/functions/app.html @@ -20,7 +20,7 @@

    Function app

  • Creates a valid AppMetadata.

    -
    const metadata = app({
    name: 'XYZ',
    description: 'The next big thing',
    logo: 'lens://bafybeigdyrzt5sfp7udm7hu76u…',
    developer: 'John Doe <john.does@email.com>',
    url: 'https://example.com',
    termsOfService: 'https://example.com/terms',
    privacyPolicy: 'https://example.com/privacy',
    platforms: ['web', 'ios', 'android'],
    }); +
    const metadata = app({
    name: 'XYZ',
    description: 'The next big thing',
    logo: 'lens://bafybeigdyrzt5sfp7udm7hu76u…',
    developer: 'John Doe <john.does@email.com>',
    url: 'https://example.com',
    termsOfService: 'https://example.com/terms',
    privacyPolicy: 'https://example.com/privacy',
    platforms: ['web', 'ios', 'android'],
    });
    @@ -50,7 +50,8 @@

    Theme

  • MetadataLicenseType
  • MetadataTransactionType
  • -
  • ModuleSchemaId
  • +
  • NamespaceMetadataSchemaId
  • NftMetadataAttributeDisplayType
  • Platform
  • PostMainFocus
  • -
  • PostSchemaId
  • +
  • PostMetadataSchemaId
  • +
  • RuleMetadataSchemaId
  • SponsorshipMetadataSchemaId
  • -
  • ThreeDFormat
  • -
  • UsernameMetadataSchemaId
  • Loading...
  • \ No newline at end of file diff --git a/docs/functions/article.html b/docs/functions/article.html index 162eed7..252485c 100644 --- a/docs/functions/article.html +++ b/docs/functions/article.html @@ -31,7 +31,7 @@
    input:

    Returns ArticleMetadata

    -

    Example

    const metadata = article({
    title: 'Great Question'
    content: `
    ## Heading

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris.

    ## Question

    What is the answer to life, the universe and everything?

    ## Answer

    42

    ![The answer](https://example.com/answer.png)
    `,
    tags: ['question', '42'],
    }); +

    Example

    const metadata = article({
    title: 'Great Question'
    content: `
    ## Heading

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris.

    ## Question

    What is the answer to life, the universe and everything?

    ## Answer

    42

    ![The answer](https://example.com/answer.png)
    `,
    tags: ['question', '42'],
    });
    \ No newline at end of file diff --git a/docs/types/MediaAudio.html b/docs/types/MediaAudio.html index 7bdfb79..16ff76b 100644 --- a/docs/types/MediaAudio.html +++ b/docs/types/MediaAudio.html @@ -97,7 +97,8 @@

    Theme