RSS3 Protocol v0.4.0-rc.2

WARNING

Documentation is not yet complete and content may be very unstable

1. Abstract

The right to create, disseminate and distribute information should not be in the hands of centralized governing. It is the basic right of cyber lives.

Gradually over the past two decades, several data superpowers have controlled contents and links to create a toxic centralized atmosphere, where privacy and freedom are sacrificed for profits. This atmosphere further hinders innovations: No matter how well you design and engineer your application, there is no way to compete with the data monopolies.

The world has been eager for a new way of information syndication. RSS used to be the pioneer of its time, now itโ€™s time for us to pick up the baton and carry on.

Derived from the best out of RSS, RSS3 is an open information syndication protocol that aims to support efficient and decentralized information distribution in Web3. It defines the format of information presence and communication, with this elegantly designed, user-friendly content format, clients can easily access a variety of content sources in a uniform format without the need for extensive compatibility logic.

2. Status of This Document

This version is a beta version, although this protocol is well established in theory, it still needs to be tested in practice, so it is not guaranteed to be compatible with subsequent versions, but breaking updates will be kept to a minimum.

3. Dependencies

4. Main Concepts

4.1. Basic Properties

RSS3 clients exchange data with the server using fixed-structure JSON.

The mime_type of RSS3 file is application/rss3+json, it is recommended to include content-type: application/rss3+json; charset=utf-8 in the Response Headers of RSS3 file response.

Each response has some basic properties.

type ResponseBase<URIType, ElementType> = {
    version: 'v0.4.0';
    date_updated: string;

    identifier: URIType;
    identifier_next?: URIType;

    total: number;
    list?: ElementType[];
}

4.1.1. version

Version of the protocol, the current is v0.4.0.

4.1.2. date_updated

The update time of the response, in the format of extended ISO 8601 with 3 decimals (YYYY-MM-DDTHH:mm:ss.sssZ).

4.1.3. identifier

The protocol uses a number of Uniform Resource Identifiers (URIs) that conform to the RFC 3986open in new window standard to identify things in RSS3.

4.1.3.1. Scheme

The scheme is rss3. I.e. RSS3 URI starts with rss3://.

4.1.3.2. Authority

The protocol uses Instance as an authority.

4.1.3.3. URI

You don't need to know what each URI means now, as will be explained separately later.

For example,

4.1.3.4. identifier_next

The URI used to identify the next page. If not specified, the current page is the last one by default.

For example:

{
    "identifier":      "rss3://account:[email protected]/notes?limit=5",
    "identifier_next": "rss3://account:[email protected]/notes?limit=5&last_identifier=rss3%3A%2F%2Fnote%3A0x22c1f6050e56d2876009903609a2cc3fef83b415-4643291%40gnosis"
}

4.1.4. total

Total number of elements in this page and its next pages.

4.1.5. list

List elements, depending on the type of the response, may be profile, link, backlink, asset, note, etc.

4.2. Instance

An instance is an RSS3 interactive object and an RSS3 presence unit.

4.2.1. URI

InstanceURI = rss3://<prefix>:<identity>@<platform>
4.2.1.1. Account Instance

There are two types of accounts

  • Main Account: the account in the Instance URI, which represents the instance.

  • Connected Accounts: accounts in the profile.connected_accounts field, which represents other accounts belonging to the instance.

An account consists of two pieces of information: the account ID and the platform to which the account belongs.

AccountInstanceURI = rss3://account:<identity>@<account_platform>

For example,

4.2.1.2. Asset Instance and Note Instance

An asset or a note can be interacted with independently as an instance.

AssetInstanceURI = rss3://asset:<metadata_proof>@<metadata_network>
NoteInstanceURI  = rss3://note:<metadata_proof>@<metadata_network>

For example,

4.2.2. Response

Specify the URIs of profiles, links, assets, notes of the current instance.

type InstanceResponse = ResponseBase<InstanceURI, {
    type: "profiles" | "links" | "backlinks" | "assets" | "notes",
    identifier: ProfilesURI | LinksURI | BacklinksURI | AssetsURI | NotesURI,
}>

4.2.3. Examples

Account Instance URI rss3://account:[email protected]

{
    "version": "v0.4.0",
    "date_updated": "2022-01-01T00:00:000Z",

    "identifier": "rss3://account:[email protected]",

    "total": 5,
    "list": [
        {
            "type": "profiles",
            "identifier": "rss3://account:[email protected]/profiles"
        },
        {
            "type": "links",
            "identifier": "rss3://account:[email protected]/links"
        },
        {
            "type": "backlinks",
            "identifier": "rss3://asset:[email protected]/backlinks"
        },
        {
            "type": "assets",
            "identifier": "rss3://account:[email protected]/assets"
        },
        {
            "type": "notes",
            "identifier": "rss3://account:[email protected]/notes"
        },
    ]
}

Asset Instance URI rss3://asset:[email protected]

{
    "version": "v0.4.0",
    "date_updated": "2022-01-01T00:00:000Z",

    "identifier": "rss3://asset:[email protected]",

    "total": 5,
    "list": [
        {
            "type": "profiles",
            "identifier": "rss3://asset:[email protected]/profiles"
        },
        {
            "type": "links",
            "identifier": "rss3://asset:[email protected]/links"
        },
        {
            "type": "backlinks",
            "identifier": "rss3://asset:[email protected]/backlinks"
        },
        {
            "type": "assets",
            "identifier": "rss3://asset:[email protected]/assets"
        },
        {
            "type": "notes",
            "identifier": "rss3://asset:[email protected]/notes"
        },
    ]
}

4.3. Profiles

Profiles record the basic information of the instance, including the name, avatar, profile, configs, etc.

4.3.1. URI

ProfilesURI = <InstanceURI>/profiles[?<query_string>]

Available queries:

KeyUsage
profile_sourcesIf specified, returning only profiles with sources field in the filter list. Multiple values are separated by commas.

E.g.,

  • All profiles of a instance from all supported netwroks:

    rss3://account:[email protected]/profiles
    
  • The profile from Crossbell Netwrok:

    rss3://account:[email protected]/profiles?profile_sources=Crossbell
    

4.3.2. Response

type ProfilesResponse = ResponseBase<ProfilesURI, {
    date_created: string;
    date_updated: string;

    name?: string;
    avatars?: URI[];
    bio?: string;
    attachments?: {
        type?: string;
        content?: string;
        address?: URI;
        mime_type: string;
        size_in_bytes?: number;
    }[];

    connected_accounts?: AccountInstanceURI[];

    source: ProfileSource;

    metadata?: {
        network: Network;
        proof: string;

        [key: string]: any;
    };
}>
4.3.2.1. profile.name

The name of the instance, such as the user's screen name, the asset's title.

4.3.2.2. profile.avatars

Instance icons, such as the user's avatar and asset images, can be set multiple at the same time, and applications should generally choose the first to display.

4.3.2.3. profile.bio

Textual introduction to the instance.

4.3.2.4. profile.attachments

profile is a very flexible and diverse information. The protocol cannot predict all requirements, so only a few of the most commonly used information are defined, and it is expected to use the attachments field to record the profile information that is not clearly defined, such as websites, banner.

For example:

{
    "attachments": [
        {
            "type": "websites",
            "content": "https://rss3.io\nhttps://diygod.me",
            "mime_type": "text/uri-list",
        },
        {
            "type": "banner",
            "content": "ipfs://QmT1zZNHvXxdTzHesfEdvFjMPvw536Ltbup7B4ijGVib7t",
            "mime_type": "image/jpeg",
        }
    ]
}
4.3.2.5. profile.connected_accounts

The main account can connect to other accounts, including accounts of cryptography-based decentralized and centralized platforms.

When getting links, assets or notes, client can get not only the content of the main account, but also the content of the connected account.

4.3.2.5. profile.source

The source service that this profile was posted on. Defined by RIP-5: Registered Profile Sources.

4.5.2.11. profile.metadata

Defined by RIP-5: Registered Profile Sources.

4.5.2.11.1. profile.metadata.network

The network where this profile is stored. Defined by RIP-3: Registered Networks.

4.5.2.11.2. profile.metadata.proof

This records the credentials for indexing this profile, such as the contract address and token id of the profile in the network.

4.3.3. Examples

Profiles URI rss3://account:[email protected]/profiles

{
    "version": "v0.4.0",
    "date_updated": "2022-01-01T00:00:000Z",

    "identifier": "rss3://account:[email protected]/profiles",

    "total": 2,
    "list": [
        {
            "date_created": "2021-01-01T00:00:000Z",
            "date_updated": "2022-01-01T00:00:000Z",
            "name": "DIYgod",
            "avatars": [
                "ipfs://QmT1zZNHvXxdTzHesfEdvFjMPvw536Ltbup7B4ijGVib7t"
            ],
            "bio": "I love RSS3",
            "attachments": [
                {
                    "type": "websites",
                    "content": "https://rss3.io\nhttps://diygod.me",
                    "mime_type": "text/uri-list",
                },
                {
                    "type": "banner",
                    "content": "ipfs://QmT1zZNHvXxdTzHesfEdvFjMPvw536Ltbup7B4ijGVib7t",
                    "mime_type": "image/jpeg",
                }
            ],

            "connected_accounts": [
                "rss3://account:[email protected]",
                "rss3://account:[email protected]"
            ],

            "source": "Crossbell",

            "metadata": {
                "network": "Crossbell",
                "proof": "todo",
            },
        },
        {
            "date_created": "2021-11-16T05:54:430Z",
            "date_updated": "2021-11-16T05:54:430Z",
            "name": "diygod.eth",
            "avatars": [
                "ipfs://QmT1zZNHvXxdTzHesfEdvFjMPvw536Ltbup7B4ijGVib7t"
            ],

            "attachments": [
                {
                    "type": "date_expiration",
                    "content": "2031-11-16T16:06:43.000Z",
                    "mime_type": "text/plain",
                }
            ],

            "source": "ENS",

            "metadata": {
                "network": "Ethereum",
                "proof": "0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85-38772411775600185392141164298857056901123186294823286690051165662418535698832",
            },
        },
    ]
}

Links describes the relationship between two instances.

4.4.1. URI

LinksURI     = <InstanceURI>/links[?<query_string>]
BacklinksURI = <InstanceURI>/backlinks[?<query_string>]

Available queries:

KeyUsage
typeReturning only links with this type. Defined by RIP-4: Registered Link Types.
limitUsed for pagination, limiting the count of the returning elements. There should be a maximum and minimal value when implementing.
last_identifierUsed for pagination. If specified, returning the instances after this instance.
toIf specified, returning only the list containing this instance. If specified but no list satisfies, returning null list.
link_sourcesIf specified, returning only links with source field in the filter list. Multiple values are separated by commas.
profile_sourcesIf specified, try to get Connected Accounts from this source, and return items belonging to Connected Accounts and Main Account, empty to get all profiles' Connected Accounts. Multiple values are separated by commas.

E.g.

  • The following list

    rss3://account:[email protected]/links?type=follow
    
  • The followed list

    rss3://account:[email protected]/backlinks?type=follow
    
  • Query if an instance is followed by another instance:

    rss3://account:[email protected]/links?type=follow&to=rss3%3A%2F%2F0x8768515270aA67C624d3EA3B98CA464672C50183%40ethereum
    
  • Query if an instance follows another instance:

    rss3://account:[email protected]/backlinks?type=follow&to=rss3%3A%2F%2F0x8768515270aA67C624d3EA3B98CA464672C50183%40ethereum
    
  • A noteโ€™s comments:

    rss3://note:[email protected]/backlinks?type=comment
    

4.4.2. Response

type LinksResponse = ResponseBase<LinksURI, {
    date_created: string;
    from: InstanceURI;
    to: InstanceURI;
    type: LinkType;

    source: LinkSource;

    metadata?: {
        network: Network;
        proof: string;

        [key: string]: any;
    };
}>

The starting point of the link. For link, it must be one of the instance's Main Account and Connected Accounts. For backlink, it can be any instance.

The end point of the link. For link, it can be any instance. For backlink, it must be one of the instance's Main Account and Connected Accounts.

Defined by RIP-4: Registered Link Types.

The source service that this link was posted on. Defined by RIP-6: Registered Link Sources.

Defined by RIP-6: Registered Link Sources.

The network where this link is stored. Defined by RIP-3: Registered Networks.

This records the credentials for indexing this link, such as the contract address and token id of the link in the network.

4.4.3. Examples

Links URI rss3://account:[email protected]/links

{
    "version": "v0.4.0",
    "date_updated": "2022-01-01T00:00:000Z",

    "identifier": "rss3://account:[email protected]/links",

    "total": 2,
    "list": [
        {
            "date_created": "2021-01-01T00:00:000Z",
            "from": "rss3://account:[email protected]",
            "to": "rss3://account:[email protected]",

            "source": "Corssbell",

            "metadata": {
                "network": "Crossbell",
                "proof": "todo",
            },
        },
        {
            "date_created": "2021-01-01T00:00:000Z",
            "from": "rss3://account:[email protected]",
            "to": "rss3://account:[email protected]",

            "source": "Lens",

            "metadata": {
                "network": "Polygon",
                "proof": "todo",
            },
        },
    ]
}

Backlinks URI rss3://account:[email protected]/backlinks

{
    "version": "v0.4.0",
    "date_updated": "2022-01-01T00:00:000Z",

    "identifier": "rss3://account:[email protected]/backlinks",

    "total": 2,
    "list": [
        {
            "date_created": "2021-01-01T00:00:000Z",
            "from": "rss3://account:[email protected]",
            "to": "rss3://account:[email protected]",

            "source": "Corssbell",

            "metadata": {
                "network": "Crossbell",
                "proof": "todo",
            },
        },
        {
            "date_created": "2021-01-01T00:00:000Z",
            "from": "rss3://account:[email protected]",
            "to": "rss3://account:[email protected]",

            "source": "Lens",

            "metadata": {
                "network": "Polygon",
                "proof": "todo",
            },
        },
    ]
}

4.5. Assets and Notes

Assets are the assets owned by instances, which can also be extended and interpreted as any fixed display content according to different usage scenarios, such as an NFT, a game achievement, a physical figure, a commodity for sale, etc.

Notes are the actions or events generated by the instance, which can also be extended and interpreted as any stream content according to different usage scenarios, such as writing a blog post, getting a NFT dynamic, writing a forum post, posting a reply to other notes, posting a comment to an assets, donation to others, etc.

Both are in the same format, so the protocol describes them together, and together they are called item

4.5.1. URI

AssetsURI = <InstanceURI>/assets[?<query_string>]
NotesURI = <InstanceURI>/notes[?<query_string>]

Available queries:

KeyUsage
limitUsed for pagination, limiting the count of the returning elements. There should be a maximum and minimal value when implementing.
last_identifierUsed for pagination. If specified, returning the instances after this instance.
tagsIf specified, returning only items of the corresponding tags (filtered using the tags attribute of items). Multiple values are separated by commas.
mime_typesIf specified, returning only items with attachments.mime_type field containing the corresponding values. Multiple values are separated by commas.
item_sourcesIf specified, returning only items with source field in the filter list. Multiple values are separated by commas.
link_sourceIf specified, items belonging to instances linked by current instance are returned
link_typeIf specified, items belonging to instances linked by current instance are returned
profile_sourcesIf specified, try to get Connected Accounts from this source, and return items belonging to Connected Accounts and Main Account, empty to get all profiles' Connected Accounts. Multiple values are separated by commas.

E.g.,

  • The list of the first 5 notes:

    rss3://account:[email protected]/notes?limit=5
    
  • Assuming that the date_created of the 5th item is 2022-01-01T00:00:000Z, then the list of the second 5 notes:

    rss3://account:[email protected]/notes?limit=5&last_identifier=rss3%3A%2F%2Fnote%3A0x22c1f6050e56d2876009903609a2cc3fef83b415-4643291%40gnosis
    
  • You can get not only the item of the Main Account, but also the item of the Connected Accounts in profile:

    rss3://account:[email protected]/notes?limit=5&profile_source=Crossbell
    
  • In addition to getting your own notes, you can also get the notes of people you follow:

    rss3://account:[email protected]/notes?limit=5&link_source=Crossbell&link_type=follow
    

4.5.2. Response

type ItemsResponse = ResponseBase<AssetsURI | NotesURI, {
    identifier: AssetInstanceURI | NoteInstanceURI;
    date_created: string;
    date_updated: string;

    related_urls?: string[];

    links: LinksURI;
    backlinks: BacklinksURI;

    tags?: string[];
    authors: AccountInstanceURI[];
    title?: string;
    summary?: string;
    attachments?: {
        type?: string;
        content?: string;
        address?: URI;
        mime_type: string;
        size_in_bytes?: number;
    }[];

    source: AssetSource | NoteSource;

    metadata?: {
        network: Network;
        proof: string;

        [key: string]: any;
    };
}>
4.5.2.1. item.identifier

identifier is the uri of the item. See Instance URI.

4.5.2.2. item.date_created

The time when the notes or assets was posted or generated, in the format of ISO 8601, such as the time when the article was published, the time when the NFT was mint, the time when the product was put on the shelf, etc.

4.5.2.3. item.date_updated

The time of an action or item change, in the format of ISO 8601, such as article modification time, last transaction or modification time of an NFT, etc.

URLs associated with the item, such as the address of the item in the indexed network.

Links URI of current item. It must be <AssetInstanceURI | NoteInstanceURI>/links

Backlinks URI of current item. It must be <AssetInstanceURI | NoteInstanceURI>/backlinks

4.5.2.7. item.tags

tags is an array of strings. Similar to the concept of tags commonly used in personal blogs, you can add multiple tags to an article; the Indexed Items will also have tags, indicating the type of the item, and the specific value is limited in RIP-7: Registered Asset Sources and RIP-8: Registered Note Sources.

4.5.2.8. item.authors

authors is an array of Accounts, indicating the accounts who have produced this item, such as the author of the article, the seller of the product, etc. It can be omitted if it is the current instance address.

If the item is an Indexed Item and the author is a Connected Account, it will additionally contain the Main Account.

4.5.2.9. item.title and item.summary

The content of a summary cannot be too long, and the RSS3 Network should set a maximum length.

If it is a short content, then it is likely to only have a summary without a title, such as a Tweet from Twitter.

If it is a long article and its word count exceeds the size limit, then its summary should only be a summary or truncation of the article, and the complete content should be placed in attachments.

4.5.2.10. item.attachments

attachments records the attachments of this item, such as images of the article, etc. If it is a long article, it may also contain the full text of the article.

4.5.2.10.1. item.attachments[i].type

The type of attachment, indicating the function or classification of this attachment, such as thumbnail, detailed description, etc.

This value can be any string.

4.5.2.10.2. item.attachments[i].content and item.attachments[i].address

content is the actual content of the attachment, such as the full body of the article or the base64 string of an image. The content of this field may be very long, but the RSS3 Network should also be limited to the maximum length of the content to avoid affecting the storage efficiency of the entire network. Content that exceeds the maximum length limit should be placed in the address field using third-party storage.

address is the URI of this attachment pointing to a third-party address, such as a markdown file address or an image address.

content and address are mutually exclusive, one attachment can only have one and only one of them.

4.5.2.10.3. item.attachments[i].mime_type

This records the media type of this attachment. The format must conform to the RFC 6838 standard, such as image/png, text/markdown, etc. This is an important but easily overlooked field from an application presentation point of view, so the protocol specifies it as a required field.

4.5.2.10.4. item.attachments[i].size_in_bytes

This records the size of this attachment in bytes. It is useful for displaying large files such as videos and audios. It is also a field that is easily overlooked. The protocol recommends that the existence and accuracy of this field be ensured as much as possible.

4.3.2.5. item.source

The source service that this item was posted on. Defined by RIP-7: Registered Asset Sources and RIP-8: Registered Note Sources.

4.5.2.11. item.metadata

Defined by RIP-7: Registered Asset Sources and RIP-8: Registered Note Sources.

4.5.2.11.1. item.metadata.network

The network where this item is stored. Defined by RIP-3: Registered Networks.

4.5.2.11.2. item.metadata.proof

This records the credentials for indexing this item, such as the contract address and token id of the item in the network.

4.5.3. Examples

Assets URI rss3://account:[email protected]/assets

{
    "version": "v0.4.0",
    "date_updated": "2022-01-01T00:00:000Z",

    "identifier": "rss3://account:[email protected]/assets",

    "total": 1,
    "list": [
        {
            "identifier":  "rss3://asset:[email protected]",
            "date_created": "2022-01-19T02:06:38.000Z",
            "date_updated": "2022-01-19T02:06:38.000Z",

            "related_urls": ["https://etherscan.io/nft/0xb9619cf4f875cdf0e3ce48b28a1c725bc4f6c0fb/1800", "https://opensea.io/assets/0xb9619cf4f875cdf0e3ce48b28a1c725bc4f6c0fb/1800"],

            "links": "rss3://asset:[email protected]/links",
            "backlinks": "rss3://asset:[email protected]/backlinks",

            "tags": [
                "NFT"
            ],
            "authors": [
                "rss3://account:[email protected]"
            ],

            "title": "RSS3 Whitepaper v1.0",
            "summary": "RSS3 Whitepaper v1.0 - Commemorative & Limited Edition",

            "attachments": [
                {
                    "type": "object",
                    "address": "ipfs://bafybeicij6vw6xcsgwldofnmmh3c3j4w5yiocs6l72yubpbcldxcglkvqe/rss3-whitepaper-no-1800.glb",
                    "mime_type": "model/gltf-binary",
                    "size_in_bytes": 3983376
                },
                {
                    "type": "preview",
                    "address": "ipfs://bafybeianto7koyrfwkdjymx7byjrs3hzy7ldipfxc343vra2t7pbd557sy/rss3-whitepaper-no-1800.png",
                    "mime_type": "image/png",
                    "size_in_bytes": 117310
                },
                {
                    "type": "attributes",
                    "content": "{\"Author(s)\":\"Natural Selection Labs\",\"Edition\":\"First Edition\",\"Edition Language\":\"English\",\"File Format\":\"PDF\",\"No.\":1800,\"date\":1610323200}",
                    "mime_type": "text/json"
                },
                {
                    "type": "external_url",
                    "content": "https://rss3.io/RSS3-Whitepaper.pdf",
                    "mime_type": "text/uri-list"
                }
            ],

            "source": "Ethereum NFT",

            "metadata": {
                "network": "Ethereum",
                "proof": "0xb9619cf4f875cdf0e3ce48b28a1c725bc4f6c0fb-1800",

                "token_standard": "ERC-721",
                "token_id": "1800",
                "token_symbol": "RWP",

                "collection_address": "0xb9619cf4f875cdf0e3ce48b28a1c725bc4f6c0fb",
                "collection_name": "RSS3 Whitepaper"
            }
        }
    ]
}

Notes URI rss3://account:[email protected]/notes

{
    "version": "v0.4.0",
    "date_updated": "2022-01-01T00:00:000Z",

    "identifier": "rss3://account:[email protected]/notes",

    "total": 4,
    "list": [
         {
            "identifier": "rss3://note:0x0[email protected]ethereum",
            "date_created": "2022-04-28T02:09:35.000Z",
            "date_updated": "2022-04-28T02:09:35.000Z",

            "related_urls": ["https://etherscan.io/tx/0x019de070d39c1055afbe9c0165b96309dcb76bff55fde624ce728b3d97e7c243"],

            "links": "rss3://note:0x0[email protected]ethereum/links",
            "backlinks": "rss3://note:0x0[email protected]ethereum/backlinks",

            "tags": [
                "Cryptocurrency"
            ],
            "authors": [
                "rss3://account:[email protected]"
            ],

            "source": "Ethereum Cryptocurrency",

            "metadata": {
                "network": "Ethereum",
                "proof": "0x019de070d39c1055afbe9c0165b96309dcb76bff55fde624ce728b3d97e7c243",

                "from": "0xC8b960D09C0078c18Dcbe7eB9AB9d816BcCa8944",
                "to": "0x8768515270aa67c624d3ea3b98ca464672c50183",
                "amount": 0.04,

                "token_standard": "Native",
                "token_symbol": "ETH"
            }
        },
        {
            "identifier": "rss3://note:0x4[email protected]ethereum",
            "date_created": "2021-06-07T11:33:44.000Z",
            "date_updated": "2021-06-07T11:33:44.000Z",

            "related_urls": ["https://etherscan.io/tx/0x4694cd7cc66fc0f4ee47e9f8ab560c4382663f576bf4f0321225d254f21fa7eb"],

            "links": "rss3://note:0x4[email protected]ethereum/links",
            "backlinks": "rss3://note:0x4[email protected]ethereum/backlinks",

            "tags": [
                "Cryptocurrency"
            ],
            "authors": [
                "rss3://account:[email protected]"
            ],

            "source": "Ethereum Cryptocurrency",

            "metadata": {
                "network": "Ethereum",
                "proof": "0x4694cd7cc66fc0f4ee47e9f8ab560c4382663f576bf4f0321225d254f21fa7eb",

                "from": "0xC8b960D09C0078c18Dcbe7eB9AB9d816BcCa8944",
                "to": "0x41697fe616ee1377e53ace44da3bcafddff04b17",
                "amount": 671,
                
                "token_standard": "ERC-20",
                "token_symbol": "USDC",
                "token_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
            }
        },
        {
            "identifier": "rss3://note:0x0[email protected]ethereum",
            "date_created": "2022-01-19T02:06:38.000Z",
            "date_updated": "2022-01-19T02:06:38.000Z",

            "related_urls": ["https://etherscan.io/tx/0x0b97d6caf6ade4cb0ec6f483463371b97d04fb1a74f72bcc411e480572d712af", "https://etherscan.io/nft/0xb9619cf4f875cdf0e3ce48b28a1c725bc4f6c0fb/1800", "https://opensea.io/assets/0xb9619cf4f875cdf0e3ce48b28a1c725bc4f6c0fb/1800"],

            "links": "rss3://note:0x0[email protected]ethereum/links",
            "backlinks": "rss3://note:0x0[email protected]ethereum/backlinks",

            "tags": [
                "NFT"
            ],
            "authors": [
                "rss3://account:[email protected]"
            ],

            "attachments": [
                {
                    "type": "name",
                    "content": "RSS3 Whitepaper v1.0",
                    "mime_type": "text/plain"
                },
                {
                    "type": "description",
                    "content": "RSS3 Whitepaper v1.0 - Commemorative & Limited Edition",
                    "mime_type": "text/plain"
                },
                {
                    "type": "object",
                    "address": "ipfs://bafybeicij6vw6xcsgwldofnmmh3c3j4w5yiocs6l72yubpbcldxcglkvqe/rss3-whitepaper-no-1800.glb",
                    "mime_type": "model/gltf-binary",
                    "size_in_bytes": 3983376
                },
                {
                    "type": "preview",
                    "address": "ipfs://bafybeianto7koyrfwkdjymx7byjrs3hzy7ldipfxc343vra2t7pbd557sy/rss3-whitepaper-no-1800.png",
                    "mime_type": "image/png",
                    "size_in_bytes": 117310
                },
                {
                    "type": "attributes",
                    "content": "{\"Author(s)\":\"Natural Selection Labs\",\"Edition\":\"First Edition\",\"Edition Language\":\"English\",\"File Format\":\"PDF\",\"No.\":1800,\"date\":1610323200}",
                    "mime_type": "text/json"
                },
                {
                    "type": "external_url",
                    "content": "https://rss3.io/RSS3-Whitepaper.pdf",
                    "mime_type": "text/uri-list"
                }
            ],

            "source": "Ethereum NFT",

            "metadata": {
                "network": "Ethereum",
                "proof": "0x0b97d6caf6ade4cb0ec6f483463371b97d04fb1a74f72bcc411e480572d712af",

                "from": "0x0000000000000000000000000000000000000000",
                "to": "0xc8b960d09c0078c18dcbe7eb9ab9d816bcca8944",

                "token_standard": "ERC-721",
                "token_id": "1800",
                "token_symbol": "RWP",

                "collection_address": "0xb9619cf4f875cdf0e3ce48b28a1c725bc4f6c0fb",
                "collection_name": "RSS3 Whitepaper"
            }
        },
        {
            "identifier": "rss3://note:[email protected]",
            "date_created": "2022-01-20T01:20:08.000Z",
            "date_updated": "2022-01-20T01:20:08.000Z",

            "related_urls": ["https://twitter.com/DIYgod/status/1483972580616949762"],

            "links": "rss3://note:[email protected]/links",
            "backlinks": "rss3://note:[email protected]/backlinks",

            "authors": [
                "[email protected]",
                "[email protected]"
            ],

            "summary": "YES!",

            "attachments": [
                {
                    "type": "media",
                    "address": "https://pbs.twimg.com/media/FJghAOqXIAUPAqJ.jpg?name=orig",
                    "mime_type": "image/png",
                    "size_in_bytes": 73876
                },
                {
                    "type": "quote_address",
                    "content": "https://twitter.com/rss3_/status/1483803568327262210",
                    "mime_type": "text/uri-list"
                },
                {
                    "type": "quote_text",
                    "content": "6 mins for all Whitepaper NFTs! Thank you all!",
                    "mime_type": "text/plain"
                }
            ],

            "source": "Twitter Tweet",

            "metadata": {
                "network": "Twitter",
                "proof": "1483972580616949762"
            }
        }
    ]
}

5. Validation

5.1. TypeScript

type AccountInstanceURI = string;
type AssetInstanceURI = string;
type NoteInstanceURI = string;
type InstanceURI = string;
type ProfilesURI = string;
type LinksURI = string;
type BacklinksURI = string;
type AssetsURI = string;
type NotesURI = string;

type URI = string;

type Network = string;
type LinkType = string;
type ProfileSource = string;
type LinkSource = string;
type AssetSource = string;
type NoteSource = string;

type ResponseBase<URIType, ElementType> = {
    version: 'v0.4.0';
    date_updated: string;

    identifier: URIType;
    identifier_next?: URIType;

    total: number;
    list?: ElementType[];
}

type InstanceResponse = ResponseBase<InstanceURI, {
    type: "profiles" | "links" | "backlinks" | "assets" | "notes",
    identifier: ProfilesURI | LinksURI | BacklinksURI | AssetsURI | NotesURI,
}>

type ProfilesResponse = ResponseBase<ProfilesURI, {
    name?: string;
    avatars?: URI[];
    bio?: string;
    attachments?: {
        type?: string;
        content?: string;
        address?: URI;
        mime_type: string;
        size_in_bytes?: number;
    }[];

    connected_accounts?: AccountInstanceURI[];

    source: ProfileSource;

    metadata?: {
        network: Network;
        proof: string;

        [key: string]: any;
    };
}>

type LinksResponse = ResponseBase<LinksURI, {
    from: InstanceURI;
    to: InstanceURI;
    type: LinkType;

    source: LinkSource;

    metadata?: {
        network: Network;
        proof: string;

        [key: string]: any;
    };
}>

type ItemsResponse = ResponseBase<AssetsURI | NotesURI, {
    identifier: AssetInstanceURI | NoteInstanceURI;
    date_created: string;
    date_updated: string;

    related_urls?: string[];

    links: LinksURI;
    backlinks: BacklinksURI;

    tags?: string[];
    authors: AccountInstanceURI[];
    title?: string;
    summary?: string;
    attachments?: {
        type?: string;
        content?: string;
        address?: URI;
        mime_type: string;
        size_in_bytes?: number;
    }[];

    source: AssetSource | NoteSource;

    metadata?: {
        network: Network;
        proof: string;

        [key: string]: any;
    };
}>

5.2. JSON Schema

TODO