Making Decentrialized Social Easy
Getting started building on Decentralized Social is as easy as deploying a Web2 API.
Build What You Want
Gateway offers a suite of tools you can pick and choose from to build the best applications for your users.
- Add decentralized authentication and onboarding workflows
- Connect your users with their universal social graph
- Read, write, and interact with social media content
- More coming...
Web2 API Simplicity with Decentralized Power
- Build your applications faster
- Own your infrastructure
- OpenAPI/Swagger out of the box
- Optimized Docker images
Basic Architecture
Gateway provides a simple API to interact with the Frequency social layers of identity, graph, content, and more.
These microservices are completely independent of one another, so you can use only those pieces you want or need.
{{#svg-embed ./src/TopLevel.svg Gateway Application Microservice Diagram}}
Key Microservices
Account Service
The Account Service enables easy interaction with accounts on Frequency.
Accounts are defined as an msaId
(64-bit identifier) and can contain additional information such as a handle, keys, and more.
- Account authentication and creation using SIWF
- Delegation management
- User Handle creation and retrieval
- User key retrieval and management
Graph Service
The Graph Service enables easy interaction with social graphs on Frequency. Each Graph connection on Frequency can be private or public and can be unidirectional (a follow) or bidiectional (double opt-in friend connection).
- Fetch user graph
- Update delegated user graphs
- Watch graphs for external updates
Content Publishing Service
The Content Publishing Service enables the creation of new content-related activity on Frequency.
- Create posts to publicly broadcast
- Create replies to posts
- Create reactions to posts
- Create updates to existing content
- Request deletion of content
- Store and attach media with IPFS
Content Watcher Service
The Content Watcher Service enables client applications to process content found on Frequency by registering for webhook notifications, triggered when relevant content is found, eleminating the need to interact with the chain for new content.
- Parses and validates Frequency content
- Filterable webhooks
- Scanning control
Get Started
Getting Started
In this tutorial, you will setup the Social App Template Example Application that uses Gateway Services. These will all run locally and connect to the public Frequency Testnet. This will give you a quick introduction to a working integration with Gateway Services and a starting place to explore the possibilities.
Expected Time: ~5 minutes
Step 1: Prerequisites
Before you begin, ensure you have the following installed on your machine:
- Git
- Docker
- Node.js
- A Web3 Polkadot wallet (e.g. Polkadot extension)
Step 2: Register on Testnet
To have your application interact on Frequency Testnet, you will need to register as a Provider. This will enable users to delegate to you, and your chain actions to be free via Capacity.
Create an Application Account in a Wallet
- Open a wallet extension such as the Polkadot extension
- Follow account creation steps
- Make sure to keep the seed phrase for the service configuration step
Acquire Testnet Tokens
Visit the Frequency Testnet Faucet and get tokens: Testnet Faucet
Create a Provider
Creating your provider account is easy via the Provider Dashboard.
- Use the same browser with the wallet extension
- Visit the Provider Dashboard
- Select
Become a Provider
- Select the
Testnet Paseo
network - Connect the Application Account created earlier
- Select
Create an MSA
and approve the transaction popups - Choose a public Provider name (e.g. "Cool Test App") and continue via
Create Provider
- Stake for Capacity by selecting
Stake to Provider
and stake 100 XRQCY Tokens
Step 3: Configure and Run the Example
Clone the Example Repository
git clone https://github.com/ProjectLibertyLabs/social-app-template.git
cd social-app-template
Run the Configuration Script
./start.sh
Testnet Setup Help
Use default values when uncertain.
Do you want to start on Frequency Paseo Testnet?
Yes!Enter Provider ID
This is Provider Id from the Provider DashboardEnter Provider Seed Phrase
This is the seed phrase saved from the wallet setupDo you want to change the IPFS settings?
- No if this is just a test run
- Yes, if you want to use an IPFS pinning service
Step 4: Done & What Happened?
You should now be able to access the Social App Template at http://localhost:3000!
What happened in the background?
All the different services needed were started in Docker (Docker Desktop Screenshot):
Step 5: Shutdown
Stop all the Docker services via the script (with the option to remove saved data), or just use Docker Desktop.
./stop.sh
What's Next?
- Open the OpenAPI/Swagger Documentation for each service
- Learn about each service
- Read about Running in Production
Core Concepts
Global State
Frequency provides a shared global state to make interoperability and user control fundamental to the internet. Applications provide unique experiences to their users while accessing the content and graph connections from other applications. Your application can then interact with this shared global state seamlessly, in the same way that modern networking software allows isolated computers to interact seamlessly over a global network moving past the artificial application boundaries.
User Control with Delegation
Users are at the core of every application and network. While users must maintain ultimate control, delegation to your application gives you the ability to provide seamless experiences for your users and their data.
Learn more about Delegation in Frequency Documentation.
Interoperability Between Apps
Frequency enables seamless interaction and data sharing between different applications built on its platform. This interoperability is facilitated by:
- Standardized Protocols: Frequency uses the Decentralized Social Networking Protocol (DSNP), an open Web3 protocol that ensures compatibility between different applications.
- Common Data Structures: By using standardized data structures for user profiles, messages, and other social interactions, Frequency ensures that data can be easily shared and interpreted across different applications.
- User Control: Users can switch between different applications without losing their social connections or content, ensuring continuity and control over their digital presence.
By leveraging these principles and infrastructures, Frequency provides a robust platform for developing decentralized social applications that are secure, scalable, and user-centric.
Learn More
Blockchain Basics
Overview of Blockchain Principles for Social Applications
Blockchain technology is a decentralized ledger system where data is stored across multiple nodes, ensuring transparency, security, and immutability.
Reading the Blockchain
RPCs, Universal State, Finalized vs Non-Finalized
-
RPCs (Remote Procedure Calls): RPCs are used to interact with the blockchain network. They allow users to query the blockchain state, submit transactions, and perform other operations by sending requests to nodes in the network.
-
Universal State: The blockchain maintains a universal state that is agreed upon by all participating nodes. This state includes all the data and transactions that have been validated and confirmed.
-
Finalized vs Non-Finalized:
- Finalized Transactions: Once a transaction is confirmed and included in a block, it is considered finalized. Finalized transactions are immutable and cannot be changed or reverted.
- Non-Finalized Transactions: Transactions that have been submitted to the network but are not yet included in a block are considered non-finalized. They are pending confirmation and can still be altered or rejected.
Writing Changes to the Blockchain
Transactions
- Transactions are the primary means of updating the blockchain state. They can involve transferring tokens, or executing other predefined operations.
Nonces
- Each transaction includes a nonce, a unique number that prevents replay attacks. The nonce ensures that each transaction is processed only once and in the correct order.
Finalization
- Finalization is the process of confirming and adding a transaction to a block. Once a transaction is included in a block and the block is finalized, the transaction becomes immutable.
Block Time
- Block time refers to the interval at which new blocks are added to the blockchain. It determines the speed at which transactions are confirmed and finalized. Shorter block times lead to faster transaction confirmations but can increase the risk of network instability.
Why Blockchain
- Decentralization: Eliminates the need for a central authority, ensuring that users have control over their data and interactions.
- Transparency: All transactions are recorded on a public ledger, providing visibility into the operations of social platforms.
- Security: Advanced cryptographic methods secure user data and interactions, making it difficult for malicious actors to tamper with information.
- Immutability: Once data is recorded on the blockchain, it cannot be altered, ensuring the integrity of user posts, messages, and other social interactions.
- User Empowerment: Users can own their data and have the ability to move freely between different platforms without losing their social connections or content.
Interoperability Between Frequency Social Apps
Frequency enables seamless interaction and data sharing between different social dapps built on its platform. This interoperability is facilitated by:
- Standardized Protocols: Frequency uses the Decentralized Social Networking Protocol (DSNP), an open Web3 protocol that ensures compatibility between different social dapps.
- Common Data Structures: By using standardized data structures for user profiles, messages, and other social interactions, Frequency ensures that data can be easily shared and interpreted across different applications.
- Interoperable APIs: Frequency provides a set of REST APIs that allow developers to build applications capable of interacting with each other, ensuring a cohesive user experience across the ecosystem.
- User Control: Users can switch between different social dapps without losing their social connections or content, ensuring continuity and control over their digital presence.
By leveraging these principles and infrastructures, Frequency provides a robust platform for developing decentralized social applications that are secure, scalable, and user-centric.
Frequency Networks
Mainnet
The Frequency Mainnet is the primary, production-level network where real transactions and interactions occur. It is fully secure and operational, designed to support live applications and services. Users and developers interact with the Mainnet for all production activities, ensuring that all data and transactions are immutable and transparent.
Key Features:
- High Security: Enhanced security protocols to protect user data and transactions.
- Immutability: Once data is written to the Mainnet, it cannot be altered.
- Decentralization: Fully decentralized network ensuring no single point of control.
- Real Transactions: All transactions on the Mainnet are real and involve actual tokens.
URLs
- Public Mainnet RPC URLs
0.rpc.frequency.xyz
1.rpc.frequency.xyz
- Polkadot.js Block Explorer
Testnet
The Frequency Testnet is a testing environment that mirrors the Mainnet. It allows developers to test their applications and services in a safe environment without risking real tokens. The Testnet is crucial for identifying and fixing issues before deploying to the Mainnet.
Key Features:
- Safe Testing: Enables developers to test applications without real-world consequences.
- Simulated Environment: Mirrors the Mainnet to provide realistic testing conditions.
- No Real Tokens: Uses test tokens instead of real tokens, eliminating financial risk.
- Frequent Updates: Regularly updated to incorporate the latest features and fixes for testing purposes.
URLs
- Testnet RPC URL
0.rpc.testnet.amplica.io
- Polkadot.js Block Explorer
- Testnet Token Faucet
Local
The Local network setup is a private, local instance of the Frequency blockchain that developers can run on their own machines. It is used for development, debugging, and testing in a controlled environment. The Local network setup provides the flexibility to experiment with new features and configurations without affecting the Testnet or Mainnet.
Key Features:
- Local Development: Allows developers to work offline and test changes quickly.
- Customizable: Developers can configure the Local network to suit their specific needs.
- Isolation: Isolated from the Mainnet and Testnet, ensuring that testing does not interfere with live networks.
- Rapid Iteration: Facilitates rapid development and iteration, allowing for quick testing and debugging.
URLs
- Local Node: Typically run on
http://localhost:9933
or a similar local endpoint depending on the setup. - Documentation: Frequency Docs
- GitHub Repository: Frequency GitHub
- Project Website: Frequency Website
Using Polkadot.js Explorer
To interact with the Frequency networks using the Polkadot.js Explorer, follow these steps:
-
Open Polkadot.js Explorer:
- Go to Polkadot.js Explorer.
-
Select Frequency Network:
- Click on the network selection dropdown at the top left corner of the page.
- Choose "POLKADOT & PARACHAINS -> Frequency Polkadot Parachain" for the main network.
- Choose "TEST PASEO & PARACHAINS -> Frequency Paseo Parachain" for the test network.
- For local development, connect to your local node by selecting "DEVELOPMENT -> Local Node or Custom Endpoint" and entering the URL of your local node (e.g.,
http://localhost:9933
).
-
Connect Your Wallet:
- Ensure your Polkadot-supported wallet is connected.
- You will be able to see and interact with your accounts and transactions on the selected Frequency network.
By using these steps, you can easily switch between the different Frequency networks and manage your blockchain activities efficiently.
Gateway Architecture
Authentication
Gateway and Frequency provide authentication, but not session management. Using cryptographic signatures, you will get proof the user is authenticated without passwords or other complex identity systems to implement. Your application still must manage sessions as is best for your custom needs.
What does it mean for Applications?
- Web2 APIs: Typically use OAuth, API keys, or session tokens for authentication.
- Frequency APIs: Utilize cryptographic signatures for secure authentication, ensuring user identity and data integrity.
SIWF/SIWA
Sign In With Frequency (SIWF) and Sign In With Access (SIWA) are methods for authenticating users in the Frequency ecosystem. SIWF allows users to authenticate using their Frequency accounts, providing a secure and decentralized way to manage identities.
- SIWF Implementation: Users sign in using their Web3 wallets, which generate cryptographic signatures for authentication. This process eliminates the need for traditional usernames and passwords, enhancing security and user privacy.
Account Service
The Account Service in Gateway handles user account management, including creating accounts, managing keys, and delegating permissions. This service replaces traditional user models with decentralized identities and provides a robust framework for user authentication and authorization.
Data Storage
What does it mean for Frequency?
- Web2 APIs: Data is stored in centralized databases managed by the service provider.
- Frequency APIs: Data is stored on the decentralized blockchain (metadata) and off-chain storage (payload), ensuring transparency and user control.
IPFS
InterPlanetary File System (IPFS) is a decentralized storage solution used in the Frequency ecosystem to store large data payloads off-chain. IPFS provides a scalable and resilient way to manage data, ensuring that it is accessible and verifiable across the network.
- Usage in Gateway: Content Publishing Service uses IPFS to store user-generated content such as images, videos, and documents. The metadata associated with this content is stored on the blockchain, while the actual files are stored on IPFS, ensuring decentralization and availability.
Blockchain
The Frequency blockchain stores metadata and transaction records, providing a secure and user-controlled data store. This ensures that all interactions are transparent and traceable, enhancing trust in the system.
- Usage in Gateway: Metadata for user actions, such as content publication, follows/unfollows, and other social interactions, are stored on the blockchain. This ensures that all actions are verifiable and under user control.
Local/Application Data
For efficiency and performance, certain data may be stored locally or within application-specific storage systems. This allows for quick access and manipulation of frequently used data while ensuring that critical information remains secure on the blockchain.
Application / Middleware
Hooking Up All the Microservices
Gateway is designed to support a modular and microservices-based approach. Each service (e.g., Account Service, Graph Service, Content Publishing Service) operates independently but can interact through well-defined APIs.
Here is Where Your Custom Code Goes!
Developers can integrate their custom code within this modular framework, extending the functionality of the existing services or creating new services that interact with the Frequency ecosystem.
Standard Services Gateway Uses
Redis
Redis is a key-value store used for caching and fast data retrieval. It is often employed in microservices architectures to manage state and session data efficiently.
- Why Redis: Redis provides low-latency access to frequently used data, making it ideal for applications that require real-time performance.
- Usage in Gateway: Redis can be used to cache frequently accessed data, manage session states, and optimize database queries.
BullMQ
BullMQ is a Node.js library for creating robust job queues with Redis.
- Struture for Redis Queues: BullMQ enhances Redis by providing a reliable and scalable way to manage background jobs and task queues, ensuring that tasks are processed efficiently and reliably.
- Usage in Gateway: BullMQ can be used to handle background processing tasks such as sending notifications, processing user actions, and managing content updates.
IPFS Kubo API
Kubo is an IPFS implementation and standard API designed for high performance and scalability.
- Usage in Gateway: Kubo IPFS is used to manage the storage and retrieval of large files in the Frequency ecosystem, ensuring that data is decentralized and accessible.
Migrating from Web2 to Web3
Step-by-Step Migration Guide
-
Assess Your Current Web2 Application
- Identify core functionalities.
- Analyze data structures.
- Review user authentication.
-
Understand Frequency and Gateway Services
- Learn about Frequency blockchain architecture.
- Understand Gateway services (Account, Graph, Content Publishing, Content Watcher).
-
Set Up Your Development Environment
- Install Docker, Node.js, and a Web3 wallet.
- Clone the Gateway service repositories.
- Set up Docker containers.
-
Configure Gateway Services
- Create and configure
.env
files with necessary environment variables.
- Create and configure
-
Migrate User Authentication
- Integrate Web3 authentication using MetaMask or another Web3 wallet.
- Configure MetaMask to connect to the Frequency TestNet.
-
Migrate Data Storage
- Transition to decentralized storage.
- Use Frequency blockchain for metadata and off-chain storage for payload data.
-
Migrate Core Functionalities
- Use the Content Publishing Service for creating feeds and posting content.
- Use the Graph Service for managing social connections.
- Use the Content Watcher Service for retrieving the latest state of feeds and reactions.
-
Test and Validate
- Perform functional, performance, and security testing.
-
Optimize and Deploy
- Optimize your application for performance on the Frequency blockchain.
- Deploy your migrated application to the production environment.
-
Educate Your Users
- Provide documentation and support for user onboarding.
- Establish a feedback loop to gather user feedback and make improvements.
By following these steps, you can successfully migrate your Web2 application to the Gateway and Frequency Web3 environment.
Services
Account Service
The Account Service enables easy interaction with accounts on Frequency.
Accounts are defined as an msaId
(64-bit identifier) and can contain additional information such as a handle, keys, and more.
- Account authentication and creation using SIWF
- Delegation management
- User Handle creation and retrieval
- User key retrieval and management
See Account Service Details & API Reference
Graph Service
The Graph Service enables easy interaction with social graphs on Frequency. Each Graph connection on Frequency can be private or public and can be unidirectional (a follow) or bidiectional (double opt-in friend connection).
- Fetch user graph
- Update delegated user graphs
- Watch graphs for external updates
See Graph Service Details & API Reference
Content Publishing Service
The Content Publishing Service enables the creation of new content-related activity on Frequency.
- Create posts to publicly broadcast
- Create replies to posts
- Create reactions to posts
- Create updates to existing content
- Request deletion of content
- Store and attach media with IPFS
See Content Publishing Service Details & API Reference
Content Watcher Service
The Content Watcher Service enables client applications to process content found on Frequency by registering for webhook notifications, triggered when relevant content is found, eleminating the need to interact with the chain for new content.
- Parses and validates Frequency content
- Filterable webhooks
- Scanning control
See Content Watcher Service Details & API Reference
Account Service
The Account Service provides functionalities related to user accounts on the Frequency network. It includes endpoints for managing user authentication, account details, delegation, keys, and handles.
API Reference
Open Direct API Reference Page
Path Table
Method | Path | Description |
---|---|---|
GET | /v1/accounts/siwf | Get the Sign In With Frequency configuration |
POST | /v1/accounts/siwf | Request to Sign In With Frequency |
GET | /v1/accounts/{msaId} | Fetch an account given an MSA Id |
GET | /v1/accounts/account/{accountId} | Fetch an account given an Account Id |
GET | /v1/accounts/retireMsa/{accountId} | Get a retireMsa unsigned, encoded extrinsic payload. |
POST | /v1/accounts/retireMsa | Request to retire an MSA ID. |
GET | /v2/delegations/{msaId} | Get all delegation information associated with an MSA Id |
GET | /v2/delegations/{msaId}/{providerId} | Get an MSA's delegation information for a specific provider |
GET | /v1/delegation/{msaId} | Get the delegation information associated with an MSA Id |
GET | /v1/delegation/revokeDelegation/{accountId}/{providerId} | Get a properly encoded RevokeDelegationPayload that can be signed |
POST | /v1/delegation/revokeDelegation | Request to revoke a delegation |
POST | /v1/handles | Request to create a new handle for an account |
POST | /v1/handles/change | Request to change a handle |
GET | /v1/handles/change/{newHandle} | Get a properly encoded ClaimHandlePayload that can be signed. |
GET | /v1/handles/{msaId} | Fetch a handle given an MSA Id |
POST | /v1/keys/add | Add new control keys for an MSA Id |
GET | /v1/keys/{msaId} | Fetch public keys given an MSA Id |
GET | /v1/keys/publicKeyAgreements/getAddKeyPayload | Get a properly encoded StatefulStorageItemizedSignaturePayloadV2 that can be signed. |
POST | /v1/keys/publicKeyAgreements | Request to add a new public Key |
GET | /healthz | Check the health status of the service |
GET | /livez | Check the live status of the service |
GET | /readyz | Check the ready status of the service |
Reference Table
Path Details
[GET]/v1/accounts/siwf
- Summary
Get the Sign In With Frequency configuration
Responses
- 200 Returned SIWF Configuration data
application/json
{
providerId: string
siwfUrl: string
frequencyRpcUrl: string
}
[POST]/v1/accounts/siwf
- Summary
Request to Sign In With Frequency
RequestBody
- application/json
{
// The wallet login request information
signIn?: #/components/schemas/SignInResponseDto
signUp: {
extrinsics: {
pallet: string
extrinsicName: string
encodedExtrinsic: string
}[]
error: {
message: string
}
}
}
Responses
- 201 Signed in successfully
application/json
{
referenceId: string
msaId?: string
publicKey?: string
}
[GET]/v1/accounts/{msaId}
- Summary
Fetch an account given an MSA Id
Responses
- 200 Found account
application/json
{
msaId: string
handle: {
base_handle: string
canonical_base: string
suffix: number
}
}
[GET]/v1/accounts/account/{accountId}
- Summary
Fetch an account given an Account Id
Responses
- 200 Found account
application/json
{
msaId: string
handle: {
base_handle: string
canonical_base: string
suffix: number
}
}
[GET]/v1/accounts/retireMsa/{accountId}
- Summary
Get a retireMsa unsigned, encoded extrinsic payload.
Responses
- 200 Created extrinsic
application/json
{
encodedExtrinsic: string
payloadToSign: string
accountId: string
}
[POST]/v1/accounts/retireMsa
- Summary
Request to retire an MSA ID.
RequestBody
- application/json
{
encodedExtrinsic: string
payloadToSign: string
accountId: string
signature: string
}
Responses
- 201 Created and queued request to retire an MSA ID
application/json
{
referenceId: string
}
[GET]/v2/delegations/{msaId}
- Summary
Get all delegation information associated with an MSA Id
Responses
- 200 Found delegation information
application/json
{
msaId: string
delegations: {
providerId: string
schemaDelegations: {
schemaId: number
revokedAtBlock?: number
}[]
revokedAtBlock?: number
}[]
}
[GET]/v2/delegations/{msaId}/{providerId}
- Summary
Get an MSA's delegation information for a specific provider
Responses
- 200 Found delegation information
application/json
{
msaId: string
delegations: {
providerId: string
schemaDelegations: {
schemaId: number
revokedAtBlock?: number
}[]
revokedAtBlock?: number
}[]
}
[GET]/v1/delegation/{msaId}
- Summary
Get the delegation information associated with an MSA Id
Responses
- 200 Found delegation information
application/json
{
providerId: string
schemaPermissions: {
}
revokedAt: {
}
}
[GET]/v1/delegation/revokeDelegation/{accountId}/{providerId}
- Summary
Get a properly encoded RevokeDelegationPayload that can be signed
Responses
- 200 Returned an encoded RevokeDelegationPayload for signing
application/json
{
accountId: string
providerId: string
encodedExtrinsic: {
}
payloadToSign: {
}
}
[POST]/v1/delegation/revokeDelegation
- Summary
Request to revoke a delegation
RequestBody
- application/json
{
accountId: string
providerId: string
encodedExtrinsic: {
}
payloadToSign: {
}
signature: {
}
}
Responses
- 201 Created and queued request to revoke a delegation
application/json
{
referenceId: string
}
[POST]/v1/handles
- Summary
Request to create a new handle for an account
RequestBody
- application/json
{
accountId: string
payload: {
baseHandle: string
expiration: number
}
proof: string
}
Responses
- 200 Handle creation request enqueued
[POST]/v1/handles/change
- Summary
Request to change a handle
RequestBody
- application/json
{
accountId: string
payload: {
baseHandle: string
expiration: number
}
proof: string
}
Responses
- 200 Handle change request enqueued
[GET]/v1/handles/change/{newHandle}
- Summary
Get a properly encoded ClaimHandlePayload that can be signed.
Responses
- 200 Returned an encoded ClaimHandlePayload for signing
[GET]/v1/handles/{msaId}
- Summary
Fetch a handle given an MSA Id
Responses
- 200 Found a handle
[POST]/v1/keys/add
- Summary
Add new control keys for an MSA Id
RequestBody
- application/json
{
msaOwnerAddress: string
msaOwnerSignature: string
newKeyOwnerSignature: string
payload: {
msaId: string
expiration: number
newPublicKey: string
}
}
Responses
- 200 Found public keys
[GET]/v1/keys/{msaId}
- Summary
Fetch public keys given an MSA Id
Responses
- 200 Found public keys
[GET]/v1/keys/publicKeyAgreements/getAddKeyPayload
- Summary
Get a properly encoded StatefulStorageItemizedSignaturePayloadV2 that can be signed.
Parameters(Query)
msaId: string
newKey: string
Responses
- 200 Returned an encoded StatefulStorageItemizedSignaturePayloadV2 for signing
[POST]/v1/keys/publicKeyAgreements
- Summary
Request to add a new public Key
RequestBody
- application/json
{
accountId: string
payload: {
schemaId: number
targetHash: number
expiration: number
actions: {
}[]
}
proof: string
}
Responses
- 200 Add new key request enqueued
[GET]/healthz
- Summary
Check the health status of the service
Responses
- 200 Service is healthy
[GET]/livez
- Summary
Check the live status of the service
Responses
- 200 Service is live
[GET]/readyz
- Summary
Check the ready status of the service
Responses
- 200 Service is ready
References
#/components/schemas/WalletLoginConfigResponseDto
{
providerId: string
siwfUrl: string
frequencyRpcUrl: string
}
#/components/schemas/HandleResponseDto
{
base_handle: string
canonical_base: string
suffix: number
}
#/components/schemas/AccountResponseDto
{
msaId: string
handle: {
base_handle: string
canonical_base: string
suffix: number
}
}
#/components/schemas/SiwsPayloadDto
{
message: string
signature: string
}
#/components/schemas/ErrorResponseDto
{
message: string
}
#/components/schemas/SignInResponseDto
{
siwsPayload: {
message: string
signature: string
}
error: {
message: string
}
}
#/components/schemas/EncodedExtrinsicDto
{
pallet: string
extrinsicName: string
encodedExtrinsic: string
}
#/components/schemas/SignUpResponseDto
{
extrinsics: {
pallet: string
extrinsicName: string
encodedExtrinsic: string
}[]
error: {
message: string
}
}
#/components/schemas/WalletLoginRequestDto
{
// The wallet login request information
signIn?: #/components/schemas/SignInResponseDto
signUp: {
extrinsics: {
pallet: string
extrinsicName: string
encodedExtrinsic: string
}[]
error: {
message: string
}
}
}
#/components/schemas/WalletLoginResponseDto
{
referenceId: string
msaId?: string
publicKey?: string
}
#/components/schemas/RetireMsaPayloadResponseDto
{
encodedExtrinsic: string
payloadToSign: string
accountId: string
}
#/components/schemas/RetireMsaRequestDto
{
encodedExtrinsic: string
payloadToSign: string
accountId: string
signature: string
}
#/components/schemas/TransactionResponse
{
referenceId: string
}
#/components/schemas/SchemaDelegation
{
schemaId: number
revokedAtBlock?: number
}
#/components/schemas/Delegation
{
providerId: string
schemaDelegations: {
schemaId: number
revokedAtBlock?: number
}[]
revokedAtBlock?: number
}
#/components/schemas/DelegationResponseV2
{
msaId: string
delegations: {
providerId: string
schemaDelegations: {
schemaId: number
revokedAtBlock?: number
}[]
revokedAtBlock?: number
}[]
}
#/components/schemas/DelegationResponse
{
providerId: string
schemaPermissions: {
}
revokedAt: {
}
}
#/components/schemas/RevokeDelegationPayloadResponseDto
{
accountId: string
providerId: string
encodedExtrinsic: {
}
payloadToSign: {
}
}
#/components/schemas/RevokeDelegationPayloadRequestDto
{
accountId: string
providerId: string
encodedExtrinsic: {
}
payloadToSign: {
}
signature: {
}
}
#/components/schemas/HandlePayloadDto
{
baseHandle: string
expiration: number
}
#/components/schemas/HandleRequestDto
{
accountId: string
payload: {
baseHandle: string
expiration: number
}
proof: string
}
#/components/schemas/KeysRequestPayloadDto
{
msaId: string
expiration: number
newPublicKey: string
}
#/components/schemas/KeysRequestDto
{
msaOwnerAddress: string
msaOwnerSignature: string
newKeyOwnerSignature: string
payload: {
msaId: string
expiration: number
newPublicKey: string
}
}
#/components/schemas/ItemizedSignaturePayloadDto
{
schemaId: number
targetHash: number
expiration: number
actions: {
}[]
}
#/components/schemas/AddNewPublicKeyAgreementRequestDto
{
accountId: string
payload: {
schemaId: number
targetHash: number
expiration: number
actions: {
}[]
}
proof: string
}
Configuration
ℹ️ Feel free to adjust your environment variables to taste. This application recognizes the following environment variables:
Name | Description | Range/Type | Required? | Default |
---|---|---|---|---|
API_PORT | HTTP port that the application listens on | 1025 - 65535 | 3000 | |
BLOCKCHAIN_SCAN_INTERVAL_SECONDS | How many seconds to delay between successive scans of the chain for new content (after end of chain is reached) | > 0 | 12 | |
CACHE_KEY_PREFIX | Prefix to use for Redis cache keys | string | account: | |
CAPACITY_LIMIT | Maximum amount of provider capacity this app is allowed to use (per epoch) type: 'percentage' 'amount' value: number (may be percentage, ie '80', or absolute amount of capacity) | JSON (example) | Y | |
FREQUENCY_HTTP_URL | Blockchain node address resolvable from the client browser | http(s): URL | Y | |
FREQUENCY_URL | Blockchain node address | http(s): or ws(s): URL | Y | |
HEALTH_CHECK_MAX_RETRIES | Number of /health endpoint failures allowed before marking the provider webhook service down | >= 0 | 20 | |
HEALTH_CHECK_MAX_RETRY_INTERVAL_SECONDS | Number of seconds to retry provider webhook /health endpoint when failing | > 0 | 64 | |
HEALTH_CHECK_SUCCESS_THRESHOLD | Minimum number of consecutive successful calls to the provider webhook /health endpoint before it is marked up again | > 0 | 10 | |
PROVIDER_ACCESS_TOKEN | An optional bearer token authentication to the provider webhook | string | ||
PROVIDER_ACCOUNT_SEED_PHRASE | Seed phrase for provider MSA control key | string | Y | |
PROVIDER_ID | Provider MSA Id | integer | Y | |
REDIS_URL | Connection URL for Redis | URL | Y | |
TRUST_UNFINALIZED_BLOCKS | Whether to examine blocks that have not been finalized when tracking extrinsic completion | boolean | false | |
WEBHOOK_BASE_URL | Base URL for provider webhook endpoints | URL | Y | |
WEBHOOK_FAILURE_THRESHOLD | Number of failures allowed in the provider webhook before the service is marked down | > 0 | 3 | |
WEBHOOK_RETRY_INTERVAL_SECONDS | Number of seconds between provider webhook retry attempts when failing | > 0 | 10 | |
GRAPH_ENVIRONMENT_TYPE | Graph environment type. | Mainnet|TestnetPaseo | Y |
Best Practices
- Secure Authentication: Always use secure methods (e.g., JWT tokens) for authentication to protect user data.
- Validate Inputs: Ensure all input data is validated to prevent injection attacks and other vulnerabilities.
- Rate Limiting: Implement rate limiting to protect the service from abuse and ensure fair usage.
Content Publishing Service
The Content Publishing Service allows users to create, post, and manage content on the Frequency network. It supports various content types such as text, images, and videos.
API Reference
Path Table
Method | Path | Description |
---|---|---|
PUT | /v1/asset/upload | Upload asset files |
POST | /v1/content/{userDsnpId}/broadcast | Create DSNP Broadcast for user |
POST | /v1/content/{userDsnpId}/reply | Create DSNP Reply for user |
POST | /v1/content/{userDsnpId}/reaction | Create DSNP Reaction for user |
PUT | /v1/content/{userDsnpId} | Update DSNP Content for user |
DELETE | /v1/content/{userDsnpId} | Delete DSNP Content for user |
PUT | /v1/profile/{userDsnpId} | Update a user's Profile |
GET | /healthz | Check the health status of the service |
GET | /livez | Check the live status of the service |
GET | /readyz | Check the ready status of the service |
GET | /dev/request/{jobId} | Get a Job given a jobId |
GET | /dev/asset/{assetId} | Get an Asset given an assetId |
POST | /dev/dummy/announcement/{queueType}/{count} | Create dummy announcement data |
Reference Table
Name | Path | Description |
---|---|---|
FilesUploadDto | #/components/schemas/FilesUploadDto | |
UploadResponseDto | #/components/schemas/UploadResponseDto | |
AssetReferenceDto | #/components/schemas/AssetReferenceDto | |
AssetDto | #/components/schemas/AssetDto | |
TagDto | #/components/schemas/TagDto | |
LocationDto | #/components/schemas/LocationDto | |
NoteActivityDto | #/components/schemas/NoteActivityDto | |
BroadcastDto | #/components/schemas/BroadcastDto | |
AnnouncementResponseDto | #/components/schemas/AnnouncementResponseDto | |
ReplyDto | #/components/schemas/ReplyDto | |
ReactionDto | #/components/schemas/ReactionDto | |
UpdateDto | #/components/schemas/UpdateDto | |
TombstoneDto | #/components/schemas/TombstoneDto | |
ProfileActivityDto | #/components/schemas/ProfileActivityDto | |
ProfileDto | #/components/schemas/ProfileDto |
Path Details
[PUT]/v1/asset/upload
- Summary
Upload asset files
RequestBody
- multipart/form-data
{
files?: string[]
}
Responses
- 2XX
application/json
{
assetIds?: string[]
}
[POST]/v1/content/{userDsnpId}/broadcast
- Summary
Create DSNP Broadcast for user
RequestBody
- application/json
{
content: {
content: string
published: string
assets: {
references: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
name?: string
href?: string
}[]
name?: string
tag: {
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}[]
location: {
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
}
}
Responses
- 2XX
application/json
{
referenceId: string
}
[POST]/v1/content/{userDsnpId}/reply
- Summary
Create DSNP Reply for user
RequestBody
- application/json
{
inReplyTo: string
content: {
content: string
published: string
assets: {
references: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
name?: string
href?: string
}[]
name?: string
tag: {
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}[]
location: {
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
}
}
Responses
- 2XX
application/json
{
referenceId: string
}
[POST]/v1/content/{userDsnpId}/reaction
- Summary
Create DSNP Reaction for user
RequestBody
- application/json
{
emoji: string
apply: number
inReplyTo: string
}
Responses
- 2XX
application/json
{
referenceId: string
}
[PUT]/v1/content/{userDsnpId}
- Summary
Update DSNP Content for user
RequestBody
- application/json
{
targetContentHash: string
targetAnnouncementType: enum[broadcast, reply]
content: {
content: string
published: string
assets: {
references: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
name?: string
href?: string
}[]
name?: string
tag: {
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}[]
location: {
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
}
}
Responses
- 2XX
application/json
{
referenceId: string
}
[DELETE]/v1/content/{userDsnpId}
- Summary
Delete DSNP Content for user
RequestBody
- application/json
{
targetContentHash: string
targetAnnouncementType: enum[broadcast, reply]
}
Responses
- 2XX
application/json
{
referenceId: string
}
[PUT]/v1/profile/{userDsnpId}
- Summary
Update a user's Profile
RequestBody
- application/json
{
profile: {
icon: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
summary?: string
published?: string
name?: string
tag: {
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}[]
location: {
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
}
}
Responses
- 2XX
application/json
{
referenceId: string
}
[GET]/healthz
- Summary
Check the health status of the service
Responses
- 200 Service is healthy
[GET]/livez
- Summary
Check the live status of the service
Responses
- 200 Service is live
[GET]/readyz
- Summary
Check the ready status of the service
Responses
- 200 Service is ready
[GET]/dev/request/{jobId}
-
Summary
Get a Job given a jobId -
Description
ONLY enabled when ENVIRONMENT="dev".
Responses
- 200
[GET]/dev/asset/{assetId}
-
Summary
Get an Asset given an assetId -
Description
ONLY enabled when ENVIRONMENT="dev".
Responses
- 2XX
application/octet-stream
{
"type": "string",
"format": "binary"
}
[POST]/dev/dummy/announcement/{queueType}/{count}
-
Summary
Create dummy announcement data -
Description
ONLY enabled when ENVIRONMENT="dev".
Responses
- 201
References
#/components/schemas/FilesUploadDto
{
files?: string[]
}
#/components/schemas/UploadResponseDto
{
assetIds?: string[]
}
#/components/schemas/AssetReferenceDto
{
referenceId: string
height?: number
width?: number
duration?: string
}
#/components/schemas/AssetDto
{
references: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
name?: string
href?: string
}
#/components/schemas/TagDto
{
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}
#/components/schemas/LocationDto
{
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
#/components/schemas/NoteActivityDto
{
content: string
published: string
assets: {
references: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
name?: string
href?: string
}[]
name?: string
tag: {
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}[]
location: {
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
}
#/components/schemas/BroadcastDto
{
content: {
content: string
published: string
assets: {
references: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
name?: string
href?: string
}[]
name?: string
tag: {
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}[]
location: {
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
}
}
#/components/schemas/AnnouncementResponseDto
{
referenceId: string
}
#/components/schemas/ReplyDto
{
inReplyTo: string
content: {
content: string
published: string
assets: {
references: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
name?: string
href?: string
}[]
name?: string
tag: {
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}[]
location: {
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
}
}
#/components/schemas/ReactionDto
{
emoji: string
apply: number
inReplyTo: string
}
#/components/schemas/UpdateDto
{
targetContentHash: string
targetAnnouncementType: enum[broadcast, reply]
content: {
content: string
published: string
assets: {
references: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
name?: string
href?: string
}[]
name?: string
tag: {
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}[]
location: {
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
}
}
#/components/schemas/TombstoneDto
{
targetContentHash: string
targetAnnouncementType: enum[broadcast, reply]
}
#/components/schemas/ProfileActivityDto
{
icon: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
summary?: string
published?: string
name?: string
tag: {
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}[]
location: {
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
}
#/components/schemas/ProfileDto
{
profile: {
icon: {
referenceId: string
height?: number
width?: number
duration?: string
}[]
summary?: string
published?: string
name?: string
tag: {
type: enum[mention, hashtag]
name?: string
mentionedId?: string
}[]
location: {
name: string
accuracy?: number
altitude?: number
latitude?: number
longitude?: number
radius?: number
units?: enum[cm, m, km, inches, feet, miles]
}
}
}
Configuration
ℹ️ Feel free to adjust your environment variables to taste. This application recognizes the following environment variables:
Name | Description | Range/Type | Required? | Default |
---|---|---|---|---|
API_PORT | HTTP port that the application listens on | 1025 - 65535 | 3000 | |
ASSET_EXPIRATION_INTERVAL_SECONDS | Number of seconds to keep completed asset entries in the cache before expiring them | > 0 | Y | |
ASSET_UPLOAD_VERIFICATION_DELAY_SECONDS | Base delay in seconds used for exponential backoff while waiting for uploaded assets to be verified available before publishing a content notice | >= 0 | Y | |
BATCH_INTERVAL_SECONDS | Number of seconds between publishing batches. This is so that the service waits a reasonable amount of time for additional content to publish before submitting a batch--it represents a trade-off between maximum batch fullness and minimal wait time for content | > 0 | Y | |
BATCH_MAX_COUNT | Maximum number of items that can be submitted in a single batch | > 0 | Y | |
CACHE_KEY_PREFIX | Prefix to use for Redis cache keys | string | content-publishing-service: | |
CAPACITY_LIMIT | Maximum amount of provider capacity this app is allowed to use (per epoch) type: 'percentage' 'amount' value: number (may be percentage, ie '80', or absolute amount of capacity) | JSON (example) | Y | |
FILE_UPLOAD_MAX_SIZE_IN_BYTES | Max file size (in bytes) allowed for asset upload | > 0 | Y | |
FREQUENCY_URL | Blockchain node address | http(s): or ws(s): URL | Y | |
IPFS_BASIC_AUTH_SECRET | If using Infura, put auth token here, or leave blank for Kubo RPC | string | blank | |
IPFS_BASIC_AUTH_USER | If using Infura, put Project ID here, or leave blank for Kubo RPC | string | blank | |
IPFS_ENDPOINT | URL to IPFS endpoint | URL | Y | |
IPFS_GATEWAY_URL | IPFS gateway URL '[CID]' is a token that will be replaced with an actual content ID | URL template | Y | |
PROVIDER_ACCOUNT_SEED_PHRASE | Seed phrase for provider MSA control key | string | Y | |
PROVIDER_ID | Provider MSA Id | integer | Y | |
REDIS_URL | Connection URL for Redis | URL | Y |
Best Practices
- Metadata Management: Always ensure metadata is correctly associated with content to maintain data integrity.
- Content Validation: Validate content to prevent the submission of inappropriate or harmful material.
Content Watcher Service
The Content Watcher Service monitors and retrieves the latest feed state, including content updates, reactions, and other user interactions on the Frequency network. It ensures that applications can stay up-to-date with the latest content and user activity.
API Reference
Path Table
Method | Path | Description |
---|---|---|
POST | /v1/scanner/reset | Reset blockchain scan to a specific block number or offset from the current position |
GET | /v1/scanner/options | Get the current watch options for the blockchain content event scanner |
POST | /v1/scanner/options | Set watch options to filter the blockchain content scanner by schemas or MSA Ids |
POST | /v1/scanner/pause | Pause the blockchain scanner |
POST | /v1/scanner/start | Resume the blockchain content event scanner |
POST | /v1/search | Search for DSNP content by id, start/end block, and filters |
PUT | /v1/webhooks | Register a webhook to be called when new content is encountered on the chain |
DELETE | /v1/webhooks | Clear all previously registered webhooks |
GET | /v1/webhooks | Get the list of currently registered webhooks |
GET | /healthz | Check the health status of the service |
GET | /livez | Check the live status of the service |
GET | /readyz | Check the ready status of the service |
Reference Table
Name | Path | Description |
---|---|---|
ResetScannerDto | #/components/schemas/ResetScannerDto | |
ChainWatchOptionsDto | #/components/schemas/ChainWatchOptionsDto | |
ContentSearchRequestDto | #/components/schemas/ContentSearchRequestDto | |
AnnouncementTypeName | #/components/schemas/AnnouncementTypeName | Announcement types to send to the webhook |
WebhookRegistrationDto | #/components/schemas/WebhookRegistrationDto |
Path Details
[POST]/v1/scanner/reset
- Summary
Reset blockchain scan to a specific block number or offset from the current position
RequestBody
- application/json
{
// The block number to reset the scanner to
blockNumber?: number
// Number of blocks to rewind the scanner to (from `blockNumber` if supplied; else from latest block)
rewindOffset?: number
// Whether to schedule the new scan immediately or wait for the next scheduled interval
immediate?: boolean
}
Responses
- 201
[GET]/v1/scanner/options
- Summary
Get the current watch options for the blockchain content event scanner
Responses
- 200
application/json
{
schemaIds?: number[]
dsnpIds?: string[]
}
[POST]/v1/scanner/options
- Summary
Set watch options to filter the blockchain content scanner by schemas or MSA Ids
RequestBody
- application/json
{
schemaIds?: number[]
dsnpIds?: string[]
}
Responses
- 201
[POST]/v1/scanner/pause
- Summary
Pause the blockchain scanner
Responses
- 201
[POST]/v1/scanner/start
- Summary
Resume the blockchain content event scanner
Parameters(Query)
immediate?: boolean
Responses
- 201
[POST]/v1/search
- Summary
Search for DSNP content by id, start/end block, and filters
RequestBody
- application/json
{
// An optional client-supplied reference ID by which it can identify the result of this search
clientReferenceId?: string
// The block number to search (backward) from
startBlock?: number
// The number of blocks to scan (backwards)
blockCount: number
// The schemaIds/dsnpIds to filter by
filters?: #/components/schemas/ChainWatchOptionsDto
// A webhook URL to be notified of the results of this search
webhookUrl: string
}
Responses
- 200 Returns a jobId to be used to retrieve the results
application/json
{
"type": "string"
}
[PUT]/v1/webhooks
- Summary
Register a webhook to be called when new content is encountered on the chain
RequestBody
- application/json
{
// Webhook URL
url: string
// Announcement types to send to the webhook
announcementTypes?: enum[tombstone, broadcast, reply, reaction, profile, update][]
}
Responses
- 200
[DELETE]/v1/webhooks
- Summary
Clear all previously registered webhooks
Responses
- 200
[GET]/v1/webhooks
- Summary
Get the list of currently registered webhooks
Responses
- 200 Returns a list of registered webhooks
application/json
{
// Webhook URL
url: string
// Announcement types to send to the webhook
announcementTypes?: enum[tombstone, broadcast, reply, reaction, profile, update][]
}[]
[GET]/healthz
- Summary
Check the health status of the service
Responses
- 200 Service is healthy
[GET]/livez
- Summary
Check the live status of the service
Responses
- 200 Service is live
[GET]/readyz
- Summary
Check the ready status of the service
Responses
- 200 Service is ready
References
#/components/schemas/ResetScannerDto
{
// The block number to reset the scanner to
blockNumber?: number
// Number of blocks to rewind the scanner to (from `blockNumber` if supplied; else from latest block)
rewindOffset?: number
// Whether to schedule the new scan immediately or wait for the next scheduled interval
immediate?: boolean
}
#/components/schemas/ChainWatchOptionsDto
{
schemaIds?: number[]
dsnpIds?: string[]
}
#/components/schemas/ContentSearchRequestDto
{
// An optional client-supplied reference ID by which it can identify the result of this search
clientReferenceId?: string
// The block number to search (backward) from
startBlock?: number
// The number of blocks to scan (backwards)
blockCount: number
// The schemaIds/dsnpIds to filter by
filters?: #/components/schemas/ChainWatchOptionsDto
// A webhook URL to be notified of the results of this search
webhookUrl: string
}
#/components/schemas/AnnouncementTypeName
{
"type": "string",
"description": "Announcement types to send to the webhook",
"enum": [
"tombstone",
"broadcast",
"reply",
"reaction",
"profile",
"update"
]
}
#/components/schemas/WebhookRegistrationDto
{
// Webhook URL
url: string
// Announcement types to send to the webhook
announcementTypes?: enum[tombstone, broadcast, reply, reaction, profile, update][]
}
Configuration
ℹ️ Feel free to adjust your environment variables to taste. This application recognizes the following environment variables:
Name | Description | Range/Type | Required? | Default |
---|---|---|---|---|
API_PORT | HTTP port that the application listens on | 1025 - 65535 | 3000 | |
BLOCKCHAIN_SCAN_INTERVAL_SECONDS | How many seconds to delay between successive scans of the chain for new content (after end of chain is reached) | > 0 | 12 | |
CACHE_KEY_PREFIX | Prefix to use for Redis cache keys | string | content-watcher: | |
FREQUENCY_URL | Blockchain node address | http(s): or ws(s): URL | Y | |
IPFS_BASIC_AUTH_SECRET | If required for read requests, put Infura auth token here, or leave blank for default Kubo RPC | string | N | blank |
IPFS_BASIC_AUTH_USER | If required for read requests, put Infura Project ID here, or leave blank for default Kubo RPC | string | N | blank |
IPFS_ENDPOINT | URL to IPFS endpoint | URL | Y | |
IPFS_GATEWAY_URL | IPFS gateway URL '[CID]' is a token that will be replaced with an actual content ID | URL template | Y | |
QUEUE_HIGH_WATER | Max number of jobs allowed on the queue before blockchain scan will be paused to allow queue to drain | >= 100 | 1000 | |
REDIS_URL | Connection URL for Redis | URL | Y | |
STARTING_BLOCK | Block number from which the service will start scanning the chain | > 0 | 1 | |
WEBHOOK_FAILURE_THRESHOLD | Number of failures allowed in the provider webhook before the service is marked down | > 0 | 3 | |
WEBHOOK_RETRY_INTERVAL_SECONDS | Number of seconds between provider webhook retry attempts when failing | > 0 | 10 |
Best Practices
- Efficient Polling: Implement efficient polling mechanisms to minimize load on the service.
- Webhook Security: Secure webhooks by verifying the source of incoming requests.
- Rate Limiting: Apply rate limiting to prevent abuse and ensure fair usage of the service.
Graph Service
The Graph Service manages the social graphs, including follow/unfollow actions, blocking users, and other social interactions. It allows applications to maintain and query the social connections between users on the Frequency network.
API Reference
Path Table
Method | Path | Description |
---|---|---|
POST | /v1/graphs/getGraphs | Fetch graphs for specified MSA Ids and Block Number |
PUT | /v1/graphs | Request an update to a given user's graph |
GET | /v1/webhooks | Get all registered webhooks |
PUT | /v1/webhooks | Watch graphs for specified dsnpIds and receive updates |
DELETE | /v1/webhooks | Delete all registered webhooks |
GET | /v1/webhooks/users/{msaId} | Get all registered webhooks for a specific MSA Id |
DELETE | /v1/webhooks/users/{msaId} | Delete all webhooks registered for a specific MSA |
GET | /v1/webhooks/urls | Get all webhooks registered to the specified URL |
DELETE | /v1/webhooks/urls | Delete all MSA webhooks registered with the given URL |
GET | /healthz | Check the health status of the service |
GET | /livez | Check the live status of the service |
GET | /readyz | Check the ready status of the service |
Reference Table
Name | Path | Description |
---|---|---|
GraphKeyPairDto | #/components/schemas/GraphKeyPairDto | |
GraphsQueryParamsDto | #/components/schemas/GraphsQueryParamsDto | |
DsnpGraphEdgeDto | #/components/schemas/DsnpGraphEdgeDto | |
UserGraphDto | #/components/schemas/UserGraphDto | |
ConnectionDto | #/components/schemas/ConnectionDto | |
ConnectionDtoWrapper | #/components/schemas/ConnectionDtoWrapper | |
ProviderGraphDto | #/components/schemas/ProviderGraphDto | |
GraphChangeRepsonseDto | #/components/schemas/GraphChangeRepsonseDto | |
WatchGraphsDto | #/components/schemas/WatchGraphsDto |
Path Details
[POST]/v1/graphs/getGraphs
- Summary
Fetch graphs for specified MSA Ids and Block Number
RequestBody
- application/json
{
dsnpIds?: string[]
// Graph type to query (public or private)
privacyType: enum[private, public]
graphKeyPairs: {
// Public graph encryption key as a hex string (prefixed with "0x")
publicKey: string
// Private graph encryption key as a hex string (prefixed with "0x")
privateKey: string
// Key type of graph encryption keypair (currently only X25519 supported)
keyType: enum[X25519]
}[]
}
Responses
- 200 Graphs retrieved successfully
application/json
{
// MSA Id that is the owner of the graph represented by the graph edges in this object
dsnpId: string
dsnpGraphEdges: {
// MSA Id of the user represented by this graph edge
userId: string
// Block number when connection represented by this graph edge was created
since: number
}[]
}[]
[PUT]/v1/graphs
- Summary
Request an update to a given user's graph
RequestBody
- application/json
{
// MSA Id that owns the connections represented in this object
dsnpId: string
// Array of connections known to the Provider for ths MSA referenced in this object
connections: #/components/schemas/ConnectionDtoWrapper
graphKeyPairs: {
// Public graph encryption key as a hex string (prefixed with "0x")
publicKey: string
// Private graph encryption key as a hex string (prefixed with "0x")
privateKey: string
// Key type of graph encryption keypair (currently only X25519 supported)
keyType: enum[X25519]
}[]
// Optional URL of a webhook to invoke when the request is complete
webhookUrl?: string
}
Responses
- 201 Graph update request created successfully
application/json
{
// Reference ID by which the results/status of a submitted GraphChangeRequest may be retrieved
referenceId: string
}
[GET]/v1/webhooks
- Summary
Get all registered webhooks
Responses
- 200 Retrieved all registered webhooks
[PUT]/v1/webhooks
- Summary
Watch graphs for specified dsnpIds and receive updates
RequestBody
- application/json
{
dsnpIds?: string[]
// Webhook URL to call when graph changes for the referenced MSAs are detected
webhookEndpoint: string
}
Responses
- 200 Successfully started watching graphs
[DELETE]/v1/webhooks
- Summary
Delete all registered webhooks
Responses
- 200 Removed all registered webhooks
[GET]/v1/webhooks/users/{msaId}
- Summary
Get all registered webhooks for a specific MSA Id
Parameters(Query)
includeAll?: boolean
Responses
- 200 Retrieved all registered webhooks for the given MSA Id
[DELETE]/v1/webhooks/users/{msaId}
- Summary
Delete all webhooks registered for a specific MSA
Responses
- 200 Removed all registered webhooks for the specified MSA
[GET]/v1/webhooks/urls
- Summary
Get all webhooks registered to the specified URL
Parameters(Query)
url: string
Responses
- 200 Retrieved all webhooks registered to the specified URL
[DELETE]/v1/webhooks/urls
- Summary
Delete all MSA webhooks registered with the given URL
Parameters(Query)
url: string
Responses
- 200 Removed all webhooks registered to the specified URL
[GET]/healthz
- Summary
Check the health status of the service
Responses
- 200 Service is healthy
[GET]/livez
- Summary
Check the live status of the service
Responses
- 200 Service is live
[GET]/readyz
- Summary
Check the ready status of the service
Responses
- 200 Service is ready
References
#/components/schemas/GraphKeyPairDto
{
// Public graph encryption key as a hex string (prefixed with "0x")
publicKey: string
// Private graph encryption key as a hex string (prefixed with "0x")
privateKey: string
// Key type of graph encryption keypair (currently only X25519 supported)
keyType: enum[X25519]
}
#/components/schemas/GraphsQueryParamsDto
{
dsnpIds?: string[]
// Graph type to query (public or private)
privacyType: enum[private, public]
graphKeyPairs: {
// Public graph encryption key as a hex string (prefixed with "0x")
publicKey: string
// Private graph encryption key as a hex string (prefixed with "0x")
privateKey: string
// Key type of graph encryption keypair (currently only X25519 supported)
keyType: enum[X25519]
}[]
}
#/components/schemas/DsnpGraphEdgeDto
{
// MSA Id of the user represented by this graph edge
userId: string
// Block number when connection represented by this graph edge was created
since: number
}
#/components/schemas/UserGraphDto
{
// MSA Id that is the owner of the graph represented by the graph edges in this object
dsnpId: string
dsnpGraphEdges: {
// MSA Id of the user represented by this graph edge
userId: string
// Block number when connection represented by this graph edge was created
since: number
}[]
}
#/components/schemas/ConnectionDto
{
// MSA Id representing the target of this connection
dsnpId: string
// Indicator connection type (public or private)
privacyType: enum[private, public]
// Indicator of the direction of this connection
direction: enum[connectionTo, connectionFrom, bidirectional, disconnect]
// Indicator of the type of connection (follow or friendship)
connectionType: enum[follow, friendship]
}
#/components/schemas/ConnectionDtoWrapper
{
data: {
// MSA Id representing the target of this connection
dsnpId: string
// Indicator connection type (public or private)
privacyType: enum[private, public]
// Indicator of the direction of this connection
direction: enum[connectionTo, connectionFrom, bidirectional, disconnect]
// Indicator of the type of connection (follow or friendship)
connectionType: enum[follow, friendship]
}[]
}
#/components/schemas/ProviderGraphDto
{
// MSA Id that owns the connections represented in this object
dsnpId: string
// Array of connections known to the Provider for ths MSA referenced in this object
connections: #/components/schemas/ConnectionDtoWrapper
graphKeyPairs: {
// Public graph encryption key as a hex string (prefixed with "0x")
publicKey: string
// Private graph encryption key as a hex string (prefixed with "0x")
privateKey: string
// Key type of graph encryption keypair (currently only X25519 supported)
keyType: enum[X25519]
}[]
// Optional URL of a webhook to invoke when the request is complete
webhookUrl?: string
}
#/components/schemas/GraphChangeRepsonseDto
{
// Reference ID by which the results/status of a submitted GraphChangeRequest may be retrieved
referenceId: string
}
#/components/schemas/WatchGraphsDto
{
dsnpIds?: string[]
// Webhook URL to call when graph changes for the referenced MSAs are detected
webhookEndpoint: string
}
Configuration
ℹ️ Feel free to adjust your environment variables to taste. This application recognizes the following environment variables:
Name | Description | Range/Type | Required? | Default |
---|---|---|---|---|
API_PORT | HTTP port that the application listens on | 1025 - 65535 | 3000 | |
BLOCKCHAIN_SCAN_INTERVAL_SECONDS | How many seconds to delay between successive scans of the chain (after end of chain is reached) | > 0 | 180 | |
CACHE_KEY_PREFIX | Prefix to use for Redis cache keys | string | content-watcher: | |
CAPACITY_LIMIT | Maximum amount of provider capacity this app is allowed to use (per epoch) type: 'percentage' 'amount' value: number (may be percentage, ie '80', or absolute amount of capacity) | JSON (example) | Y | |
DEBOUNCE_SECONDS | Number of seconds to retain pending graph updates in the Redis cache to avoid redundant fetches from the chain | >= 0 | ||
FREQUENCY_URL | Blockchain node address | http(s): or ws(s): URL | Y | |
GRAPH_ENVIRONMENT_TYPE | Graph environment type. | Mainnet|TestnetPaseo | Y | |
HEALTH_CHECK_MAX_RETRIES | Number of /health endpoint failures allowed before marking the provider webhook service down | >= 0 | 20 | |
HEALTH_CHECK_MAX_RETRY_INTERVAL_SECONDS | Number of seconds to retry provider webhook /health endpoint when failing | > 0 | 64 | |
HEALTH_CHECK_SUCCESS_THRESHOLD | Minimum number of consecutive successful calls to the provider webhook /health endpoint before it is marked up again | > 0 | 10 | |
PROVIDER_ACCOUNT_SEED_PHRASE | Seed phrase for provider MSA control key | string | Y | |
PROVIDER_ID | Provider MSA Id | integer | Y | |
QUEUE_HIGH_WATER | Max number of jobs allowed on the 'graphUpdateQueue' before blockchain scan will be paused to allow queue to drain | >= 100 | 1000 | |
RECONNECTION_SERVICE_REQUIRED | Whether to instantiate/activate reconnection-service features | true/false | ||
REDIS_URL | Connection URL for Redis | URL | Y |
The following environment variables are only relevant if RECONNECTION_SERVICE_REQUESTED
is 'true':
Name | Description | Range/Type | Required? | Default |
---|---|---|---|---|
CONNECTIONS_PER_PROVIDER_RESPONSE_PAGE | Number of connection/page to request when requesting provider connections from webhook | > 0 | 100 | |
PROVIDER_ACCESS_TOKEN | An optional bearer token authentication to the provider webhook | string | ||
PROVIDER_BASE_URL | Base URL for provider webhook endpoints | URL | Y | |
WEBHOOK_FAILURE_THRESHOLD | Number of failures allowed in the provider webhook before the service is marked down | > 0 | 3 | |
WEBHOOK_RETRY_INTERVAL_SECONDS | Number of seconds between provider webhook retry attempts when failing | > 0 | 10 |
Best Practices
- Data Integrity: Ensure the integrity of social graph data by implementing robust validation checks.
- Efficient Queries: Optimize queries to handle large social graphs efficiently.
- User Privacy: Protect user privacy by ensuring that graph data is only accessible to authorized entities.
Run
Coming soon...
Deployment
Coming soon...
Security
Coming soon...
Performance
Coming soon...
Scalability
Coming soon...
FAQ
Coming soon...
Support Channels
Need help with Gateway or working through the Frequency ecosystem? There are many different options to meet your needs.
GitHub Issues
Checking and creating a GitHub issue is a easy place to start if you want to ask a question or file a bug report or documentation issue you find.
Frequency Discord
Frequency has a Discord where you can discuss Gateway and connect with the Frequency community.
Direct Partnership
Gateway is built by Project Liberty, a contributor to the Frequency ecosystem. If you want more help or just to connect, contact hello@projectliberty.io.
Community Resources
Gateway
All Gateway code is open source, and you are welcome to participate in its development.
Many of the Gateway related tools are also open source:
Frequency
Frequency is built using the Polkadot SDK. Most Polkadot SDK (also called Substrate) tooling works with Frequency.
- Frequency Homepage
- Frequency Documentation
- Frequency GitHub
- Polkadot SDK Documentation
- Polkadot.js Toolkit
- Frequency/Polkadot Wallets
IPFS
IPFS (the InterPlanetary File System) is a peer-to-peer network and protocol designed to make the web faster, safer, and more open. It uses "content-based addressing" which allows content to move to different servers and act as a distributed CDN on demand. While most users rely on providers to maintain the availability of files, users may move services and providers may help them to maintain the availability of their content.
DSNP
Gateway is built using DSNP (Decentralized Social Media Protocol).
Project Liberty
Project Liberty is a contributor to the Frequency ecosystem and the maintainer of the open source Gateway tool.