Skip to content

Social Platform

The SocialSDK provides a fully on-chain social nanopayments platform on Algorand. Every social interaction is a direct economic transaction in AKTA — posts cost 100 AKTA, upvotes and replies cost 10 AKTA (the majority paid directly to the content creator after an Impact-based protocol fee). Content rises in the feed based on the economic weight of interactions it receives, weighted by the reputation of the users behind them. There is no ad layer or engagement algorithm — only direct value exchange between users.

import { SocialSDK } from '@akta/sdk/social'
const social = new SocialSDK({ algorand })

Post content (text, images, metadata) is stored on IPFS. The on-chain contract only stores a 36-byte CIDv1 (Content Identifier) pointing to the IPFS content. This keeps on-chain costs low while making content permanently addressable and verifiable.

┌─────────────┐ CIDv1 (36 bytes) ┌─────────────┐
│ Algorand │ ◄──────────────────────── │ IPFS │
│ (on-chain) │ stored in post box │ (content) │
└─────────────┘ └─────────────┘

Every post is identified by a deterministic 32-byte post key derived from:

postKey = sha256(creatorAddress + timestamp + nonce)
  • Creator address — the poster’s Algorand address
  • Timestamp — must be within 60 seconds of the current block time
  • Nonce — a random 24-byte value (auto-generated by the SDK)

The SDK returns the post key after creation, which is used to reference the post for replies, votes, reactions, and edits.

Before using any social features, a user must initialize their on-chain social meta:

const metaIndex = await social.initMeta({})

With optional configuration:

const metaIndex = await social.initMeta({
nfd: nfdAssetId, // Link an NFD (Non-Fungible Domain)
akitaNFT: nftAssetId, // Link an Akita NFT as profile
})

Update meta settings later:

await social.updateMeta({
followGateId: gateAppId, // Gate who can follow you
addressGateId: gateAppId, // Gate address-level interactions
defaultPayWallId: payWallId, // Default x402 paywall for bot access
})

Upload your content to IPFS first, then pass the CIDv1 bytes to the SDK:

// 1. Upload content to IPFS (your app handles this)
const cid = await uploadToIPFS({ text: 'Hello from Akita!' })
// 2. Create the on-chain post
const { postKey, timestamp, nonce } = await social.post({
cid, // 36-byte IPFS CIDv1 as Uint8Array
})

The SDK automatically:

  • Generates a random 24-byte nonce
  • Fetches the current blockchain timestamp
  • Pays the post MBR (box storage) in ALGO
  • Pays the post fee in AKTA (read from the DAO contract)

Restrict who can view or interact with a post using a gate:

const { postKey } = await social.post({
cid,
gateId: gateAppId, // Only users who pass this gate can interact
})

Paywalls let you monetize content for bots and AI agents via the x402 payment protocol. When a bot encounters an x402-paywalled post, it pays on-chain to unlock access — enabling machine-to-machine content monetization without human intervention.

You can configure separate payment terms for human users vs. agent/bot access:

// Create a paywall with bot-specific pricing
const payWallId = await social.createPayWall({
userPayInfo: [
// Human users: one-time ALGO payment
{ type: PayWallType.OneTimePayment, assetOrSubId: 0n, amount: 1_000_000n },
],
agentPayInfo: [
// Bots/agents: per-access AKTA payment via x402
{ type: PayWallType.OneTimePayment, assetOrSubId: aktaAssetId, amount: 500_000n },
],
})
// Attach it to a post
const { postKey } = await social.post({
cid,
usePayWall: true,
payWallId,
})

The agentPayInfo array defines the x402 payment terms that bots must satisfy. When an agent wallet encounters a paywalled post, it can automatically pay via its escrow within configured spending allowances.

Edits create an amendment linked to the original post. The edit key is deterministic — editing with the same new CID always produces the same key.

const editKey = await social.editPost({
cid: newCid, // Updated IPFS CIDv1
amendment: postKey, // Original post's 32-byte key
})

Replies reference another post (or asset, address, app, or external content):

import { RefType } from '@akta/sdk/social'
const { replyKey } = await social.reply({
cid, // Reply content on IPFS
ref: parentPostKey, // 32-byte reference of the parent
refType: RefType.Post,
})

Replies can target different on-chain entities:

RefTypeValueDescription
Post10Reply to another post
Asset20Comment on an ASA
Address30Comment on an address
App40Comment on an application
External50Reference external content (e.g., Twitter)
const { replyKey } = await social.reply({
cid,
ref: parentPostKey,
refType: RefType.Post,
gateTxn: gateCallTxn, // Gate proof transaction
})

Upvote or downvote any post. Votes contribute to the author’s impact score.

// Upvote
await social.vote({
ref: postKey,
refType: RefType.Post,
isUp: true,
})
// Downvote
await social.vote({
ref: postKey,
refType: RefType.Post,
isUp: false,
})

Flip an existing vote:

await social.invertVote({ ref: postKey })

Remove a vote entirely (refunds the MBR):

await social.deleteVote({ ref: postKey })

Users react to posts using NFTs they hold. Each NFT-reaction pair is tracked, and reaction counts are stored on-chain.

await social.react({
ref: postKey,
refType: RefType.Post,
nft: reactionNftId, // ASA ID of the NFT used as a reaction
})

Remove a reaction:

await social.deleteReaction({ ref: postKey, nft: reactionNftId })
const { reactions, userReactedNfts } = await social.getPostReactions({
ref: postKey,
userAddress: myAddress, // Optional — check which NFTs this user reacted with
})
// reactions: [{ nftId: 123n, count: 5n }, { nftId: 456n, count: 12n }]
// userReactedNfts: Set<bigint> of NFT IDs the user has used
// Get a single post
const post = await social.getPost({ ref: postKey })
// Get a post with its creator's meta
const { post, meta } = await social.getPostAndCreatorMeta({ ref: postKey })
// Check a user's vote on a post
const vote = await social.getVote({ account: userAddress, ref: postKey })
// Batch read votes
const votes = await social.getVotes({
keys: [
{ account: userAddress, ref: postKey1 },
{ account: userAddress, ref: postKey2 },
],
})

Every write operation pays two costs:

CostCurrencyPurpose
MBRALGOMinimum Balance Requirement for on-chain box storage
FeeAKTAProtocol fee — majority goes to the content creator, remainder to DAO treasury
OperationAKTA CostCreator Receives
Post100 AKTA
Upvote / Reply10 AKTAMajority (after Impact-based protocol fee)

Higher-Impact users pay lower protocol fees (1–20% of the interaction cost, based on Impact score), meaning more of the payment reaches the creator. The SDK reads fees from the DAO contract automatically. You can pre-calculate MBR costs:

const postMbr = social.calculatePostMBR()
const replyMbr = social.calculateReplyMBR()
const reactMbr = social.calculateReactMBR()
const followMbr = social.calculateFollowMBR()

The social system spans four contracts, all accessed through SocialSDK:

ContractPurpose
Akita SocialPosts, reactions, votes, x402 paywalls, meta
Social GraphFollow/unfollow, block/unblock
Social ImpactImpact scoring from social activity
Social ModerationModerator roles, bans, content flagging

See also: Social Graph, Social Impact, Moderation

Social operations through a wallet use the SocialPlugin. See Wallet Plugins.