Advanced SDK Usage
Coming Soon — The ChainSocial SDK is not yet published. This documentation describes the planned API. Use the REST API for current integrations.
Delegation, meta-transactions, and advanced patterns.
Delegation
Delegation lets users grant specific permissions to other addresses. This enables:
- Session Keys — Better UX with fewer wallet popups
- Gasless Transactions — Relayers can act on behalf of users
- Bots & Assistants — Automated actions with limited scope
Permission Types
| Permission | Value | Description |
|---|---|---|
POST | 0 | Create posts, replies, quotes |
UPDATE_PROFILE | 1 | Modify profile fields |
SEND_DMS | 2 | Send direct messages |
FOLLOW | 3 | Follow/unfollow users |
Creating a Delegation
import { DelegationPermission } from '@chainsocial/client'
// Grant posting permission to another address for 7 days
const sevenDays = Math.floor(Date.now() / 1000) + (7 * 24 * 60 * 60)
await client.delegation.createDelegation(
delegateAddress,
DelegationPermission.POST,
sevenDays // validUntil timestamp
)Revoking a Delegation
await client.delegation.revokeDelegation(
delegateAddress,
DelegationPermission.POST
)Checking Authorization
const isAuthorized = await client.delegation.isDelegateAuthorized(
delegatorAddress, // Original user
delegateAddress, // Acting address
DelegationPermission.POST
)Using Delegated Permissions
Once delegated, the delegate wallet can use OnBehalfOf methods:
// Delegate creates post as the delegator
await client.post.createInlinePostOnBehalfOf(
delegatorAddress,
'Posted via delegation!',
PostVisibility.PUBLIC
)Delegations expire automatically at the validUntil timestamp. Maximum delegation duration is 365 days.
Meta-Transactions (Signed Operations)
Meta-transactions let users sign operations off-chain, then have a relayer submit them. This enables gasless UX.
How It Works
- User signs an EIP-712 typed message
- Relayer receives the signature
- Relayer submits the transaction and pays gas
- User’s action is recorded on-chain
Signing an Operation
import { SignedOperations } from '@chainsocial/client'
const signedOps = new SignedOperations({
worldAddress,
chainId: 8453,
walletClient
})
// Sign a post creation
const signature = await signedOps.signCreatePost({
contentId: '0x...',
visibility: PostVisibility.PUBLIC,
nonce: currentNonce,
deadline: Math.floor(Date.now() / 1000) + 3600 // 1 hour expiry
})
// Send signature to relayer
await fetch('/api/relay', {
method: 'POST',
body: JSON.stringify({ signature, params: { contentId, visibility } })
})Supported Signed Operations
| Category | Operations |
|---|---|
| Content | Create/Edit/Delete posts, replies, quotes |
| Social | Follow/unfollow, block/unblock |
| Reactions | Add/remove reactions |
| DMs | Send messages |
| Profile | Update profile fields |
| Delegation | Create/revoke delegations |
Relayer System
ChainSocial includes built-in relayer support with fee management.
Relayer Vault
Users can deposit ETH into a relayer vault for gasless transactions:
// Deposit ETH for gas coverage
await client.relayerVault.deposit({ value: parseEther('0.1') })
// Check balance
const balance = await client.relayerVault.getBalance(userAddress)
// Withdraw
await client.relayerVault.withdraw(parseEther('0.05'))Relayer Fee Configuration
Relayers charge fees based on gas used, with configurable bounds:
const feeConfig = await client.relayerFee.getFeeConfig()
console.log('Min fee:', feeConfig.minFee)
console.log('Max fee:', feeConfig.maxFee)
console.log('Fixed gas price:', feeConfig.fixedGasPrice)Signed Operations with Max Fee
Users can cap the fee they’re willing to pay:
const signature = await signedOps.signCreatePost({
contentId: '0x...',
visibility: PostVisibility.PUBLIC,
nonce: currentNonce,
deadline: deadline,
maxFee: parseEther('0.001') // Won't pay more than 0.001 ETH
})Content System
The content system handles storage of text and media.
Storage Types
import { ContentStorageType } from '@chainsocial/client'
// Inline (on-chain, up to 4KB)
const id1 = await client.content.createInlineContent('Hello world')
// IPFS reference
const id2 = await client.content.createIpfsContent(
'bafkrei...', // CID
'image/png',
12345 // size in bytes
)
// URL reference
const id3 = await client.content.createUrlContent(
'https://example.com/post.json',
'application/json'
)Reading Content
const contentData = await client.content.getContent(contentId)
console.log('Storage type:', contentData.storageType)
console.log('MIME type:', contentData.mimeType)
console.log('Size:', contentData.size)
console.log('Data:', contentData.data) // For inline contentUsername System
Usernames can have fees and expiration (configurable by namespace owner).
Claiming a Username
import { stringToHex, padHex } from 'viem'
const username = padHex(stringToHex('alice'), { size: 32 })
const fee = await client.username.getFee(username)
await client.username.claimUsername(username, { value: fee })Renewing a Username
const renewalFee = await client.username.getRenewalFee(username)
await client.username.renewUsername(username, { value: renewalFee })Releasing a Username
await client.username.releaseUsername(username)Plugin System
Users can install and manage plugins:
// Install a plugin
await client.pluginInstall.installPlugin(pluginId)
// Grant consent for plugin to act
await client.pluginInstall.grantConsent(pluginId)
// Uninstall
await client.pluginInstall.uninstallPlugin(pluginId)Moderation System
Reporting Content
await client.moderation.reportPost(postId, 'spam', 'This is spam content')
await client.moderation.reportUser(userAddress, 'harassment')Hiding Content (Personal)
// Hide a post from your feed (only affects you)
await client.moderation.hideContent(postId)
// Unhide
await client.moderation.unhideContent(postId)Best Practices
Transaction Batching
Combine multiple operations when possible:
// Instead of 3 transactions
await client.follow.follow(user1)
await client.follow.follow(user2)
await client.follow.follow(user3)
// Use 1 batch transaction
await client.follow.followBatch([user1, user2, user3])Error Handling
try {
await client.post.createInlinePost('Hello!')
} catch (error) {
// Contract reverts include reason strings
if (error.message.includes('ProfileNotFound')) {
// User needs a profile
} else if (error.message.includes('InsufficientFee')) {
// Need to send more ETH
} else if (error.message.includes('ContentTooLong')) {
// Inline content exceeds 4KB
}
throw error
}Gas Optimization
- Use inline content for small text (under 1KB)
- Use IPFS for larger content (saves on-chain storage)
- Batch operations when possible
- Use delegation for apps with high transaction volume
Next Steps
- API Reference — REST endpoints
- Smart Contracts — Understand the on-chain systems