Blockplot Soroban — Technical Documentation

Blockplot Protocol Docs

Complete reference for the Blockplot Soroban permissioned RWA tokenization protocol — smart contracts, API, user flows, and wallet integration.

Overview

Blockplot Soroban is a compliant Real World Asset (RWA) tokenization platform that enables users globally to invest in fractionalized, yield-bearing assets such as real estate, infrastructure, and treasury-backed instruments.

The platform uses Soroban smart contracts on the Stellar network to tokenize off-chain assets into transferable digital ownership units while enforcing compliance, identity verification, governance rules, and reward distribution entirely on-chain.

Blockplot lowers the entry barrier to global asset ownership by enabling investments from as little as $1, while providing liquidity, transparent reward distribution, and decentralized governance.

$1
Min. Investment
Stellar / Soroban
Built On
Rust
Contract Language
KYC / AML
Compliance

Problem Statement

Traditional real-world asset investing suffers from structural barriers that exclude the majority of the world:

High Capital Requirements
Most real estate or infrastructure deals require tens of thousands of dollars minimum.
Illiquidity
Assets are locked up for years with no secondary market for exit.
Geographic Restrictions
Regulatory fragmentation prevents global investors from participating.
Lack of Transparency
Opaque structures make it difficult to verify ownership or yield.
Slow Settlement
Traditional settlement takes days; cross-border transfers take weeks.
Missing Compliance Tooling
Existing blockchain RWA systems lack built-in KYC and permissioning.

Blockplot solves these challenges through compliant fractional ownership infrastructure built on Stellar — where transactions settle in seconds for fractions of a cent.

Architecture

Blockplot is composed of three layers: on-chain contracts, an off-chain API, and the user-facing web application.

┌─────────────────────────────────────────────────────────┐
│                    blockplot-frontend                    │
│        Next.js · Tailwind · Freighter SDK               │
└───────────────────────┬─────────────────────────────────┘
                        │ REST
┌───────────────────────▼─────────────────────────────────┐
│                    blockplot-backend                     │
│        NestJS · Identity · Assets · Yield modules       │
└───────────────────────┬─────────────────────────────────┘
                        │ Soroban RPC
┌───────────────────────▼─────────────────────────────────┐
│                   blockplot-contracts                    │
│                                                         │
│  BlockplotID ──► FractionalAsset ──► PublicSale         │
│                        │                                │
│                  YieldDistributor                       │
│                                                         │
│              Stellar · Soroban Runtime                  │
└─────────────────────────────────────────────────────────┘

Contract Interaction Flow

User wallet
    │
    ├─ 1. identity check  →  BlockplotID.is_verified()
    │
    ├─ 2. purchase        →  PublicSale.purchase()
    │                              │
    │                        FractionalAsset.mint()
    │
    └─ 3. claim yield     →  YieldDistributor.claim()

Smart Contracts

All contracts are written in Rust targeting the Soroban WASM runtime. The workspace lives at github.com/Stellar-Land/blockplot-contracts.

Build all contracts with: cargo build --target wasm32-unknown-unknown --release

BlockplotID

The identity and compliance layer. Every wallet that interacts with the protocol must first be verified through this contract. An admin (the compliance provider) controls status transitions.

FunctionAccessDescription
initialize(admin)OnceSets the compliance admin
set_status(user, status)AdminSets identity state for a wallet
get_status(user)PublicReturns current IdentityStatus
is_verified(user)PublicReturns true if status is Verified

Identity States

None ──► Pending ──► Verified
                            │
                         Revoked

Usage

// Approve a user on testnet
stellar contract invoke \
  --id <BLOCKPLOT_ID_CONTRACT> \
  --source admin \
  --network testnet \
  -- set_status \
  --user GABC...XYZ \
  --status Verified

FractionalAsset

An ownership token contract representing fractional exposure to an off-chain asset. Each deployed instance corresponds to one real-world asset. A per-wallet owner_cap prevents concentration and enforces ownership limits.

FunctionAccessDescription
initialize(admin, name, total_supply, owner_cap)OnceDeploys and configures the asset token
mint(to, amount)AdminIssues tokens, enforces cap
transfer(from, to, amount)HolderTransfers tokens, cap-checked on recipient
balance_of(account)PublicReturns token balance for a wallet
total_supply()PublicReturns total issued supply
owner_cap()PublicReturns max tokens any wallet may hold
Transfers do not verify KYC status — the application layer must call BlockplotID.is_verified() before constructing a transfer transaction.

PublicSale

The primary issuance marketplace. An admin opens and closes sale phases, sets the token price, and the contract tracks total funds raised. It returns the number of tokens to issue — token minting is handled by a subsequent FractionalAsset.mint() call.

FunctionAccessDescription
initialize(admin, token_price)OnceSets admin and per-token price in stroops
set_active(active)AdminOpens (true) or closes (false) the sale
purchase(buyer, payment_amount)Verified buyerRecords purchase, returns token count
total_raised()PublicCumulative funds raised
is_active()PublicWhether the sale is currently open
token_price()PublicCurrent price per token

Purchase flow

// 1. Check identity
const verified = await contract.is_verified(walletAddress)
if (!verified) throw new Error("KYC required")

// 2. Call purchase — returns token count
const tokens = await publicSale.purchase(buyer, paymentAmount)

// 3. Mint the tokens to the buyer
await fractionalAsset.mint(buyer, tokens)

YieldDistributor

Collects asset-generated income (rent, treasury yield, revenue sharing) and distributes it proportionally to token holders. Allocation is expressed in basis points (bps) where 10,000 bps = 100%.

FunctionAccessDescription
initialize(admin)OnceSets the distribution admin
deposit(caller, amount)AdminDeposits yield into the pool
allocate(holder, allocation_bps)AdminCredits yield share to a holder
claimable(holder)PublicReturns unclaimed yield for a wallet
claim(holder)HolderWithdraws all claimable yield, returns amount
total_deposited()PublicTotal yield deposited to date

Allocation formula

claimable = (total_deposited × allocation_bps) / 10_000

// Example: holder owns 5% of the asset (500 bps)
// Total deposited: $10,000
// Claimable: (10_000 × 500) / 10_000 = $500
Allocation basis points should mirror the holder's share oftotal_supply. The backend computes this off-chain after indexing balance_of values.

User Flows

1 — Onboarding

User connects Freighter wallet
        │
        ▼
User submits KYC form (name, country, ID)
        │
        ▼
Backend stores submission, status = "pending"
        │
        ▼
Compliance admin reviews and calls set_status(..., Verified)
        │
        ▼
User gains protocol access — can purchase asset tokens

2 — Investing in an Asset

User browses asset catalog → selects an asset
        │
        ▼
Protocol checks:  BlockplotID.is_verified(user) ✓
                  PublicSale.is_active()         ✓
                  payment ≥ token_price          ✓
        │
        ▼
PublicSale.purchase(buyer, amount)  →  returns token_count
        │
        ▼
FractionalAsset.mint(buyer, token_count)
        │
        ▼
Tokens appear in user's portfolio

3 — Claiming Yield

Asset generates income (rent collected, yield received)
        │
        ▼
Admin calls YieldDistributor.deposit(caller, income_amount)
        │
        ▼
Backend indexes balance_of for all holders
Computes each holder's allocation_bps
        │
        ▼
Admin calls YieldDistributor.allocate(holder, bps) for each holder
        │
        ▼
User opens /claim dashboard
User calls YieldDistributor.claim(wallet) via Freighter
        │
        ▼
Rewards land in user's Stellar wallet

API Reference

The backend exposes a REST API at http://localhost:3000 in development. All endpoints return JSON.

Identity — /identity

MethodEndpointDescription
POST/identity/submitSubmit KYC data for a wallet address
GET/identity/:walletAddressGet current identity status
PATCH/identity/:walletAddress/approveApprove and verify a wallet (admin)
PATCH/identity/:walletAddress/revokeRevoke a wallet's verified status (admin)
// Submit KYC
POST /identity/submit
{
  "walletAddress": "GABC...XYZ",
  "kycData": { "name": "Alice", "country": "NG" }
}

// Response
{ "walletAddress": "GABC...XYZ", "status": "pending", "updatedAt": "..." }

// Approve (admin)
PATCH /identity/GABC...XYZ/approve
// → { "status": "verified", "updatedAt": "..." }

Assets — /assets

MethodEndpointDescription
POST/assetsRegister a new tokenized asset
GET/assetsList all registered assets
GET/assets/:idGet a single asset by ID
// Create asset
POST /assets
{
  "name": "Lagos Commercial Tower A",
  "totalSupply": 1000000,
  "ownerCap": 100000,
  "priceUsd": 1
}

// Response
{
  "id": "uuid-here",
  "name": "Lagos Commercial Tower A",
  "totalSupply": 1000000,
  "ownerCap": 100000,
  "priceUsd": 1,
  "createdAt": "..."
}

Yield — /yield

MethodEndpointDescription
POST/yield/:assetId/depositDeposit yield into an asset's pool
GET/yield/:assetId/claimable/:walletAddressGet claimable amount for a holder
POST/yield/:assetId/claim/:walletAddressClaim all yield for a holder
// Deposit yield
POST /yield/asset-id-123/deposit
{ "amount": 5000 }

// Check claimable
GET /yield/asset-id-123/claimable/GABC...XYZ
// → { "walletAddress": "GABC...XYZ", "claimable": 250 }

// Claim
POST /yield/asset-id-123/claim/GABC...XYZ
// → { "walletAddress": "GABC...XYZ", "claimed": 250 }

Wallet Integration

Blockplot uses Freighter — the official Stellar browser extension wallet. Install it from freighter.app before connecting.

Connecting a wallet

import { isConnected, requestAccess, getAddress } from "@stellar/freighter-api"

// Check if Freighter is installed
const { isConnected: installed } = await isConnected()

// Request access — opens the Freighter popup
const { address, error } = await requestAccess()
if (error) throw new Error(error)

console.log("Connected:", address)
// → "GABC...XYZ"

Checking an existing session

// Silently restore a previous connection (no popup)
const { address } = await getAddress()
if (address) console.log("Already connected:", address)

Signing a transaction

import { signTransaction } from "@stellar/freighter-api"
import { Transaction } from "@stellar/stellar-sdk"

const { signedTxXdr, error } = await signTransaction(unsignedXDR, {
  networkPassphrase: Networks.TESTNET,
})
if (error) throw new Error(error)

// Submit the signed XDR to Stellar
await server.submitTransaction(TransactionBuilder.fromXDR(signedTxXdr, Networks.TESTNET))
Blockplot Frontend handles wallet state through the WalletProvider context in lib/wallet-context.tsx. Use the useWallet() hook in any client component to access address, connect(), and disconnect().

Supported wallets

WalletStatusNotes
Freighter✓ SupportedPrimary integration
AlbedoPlannedPhase 2
WalletConnectPlannedPhase 3 — mobile support
RabetPlannedPhase 2

Roadmap

Phase 1 — MVP (Current)

Identity system (BlockplotID contract)
Asset tokenization (FractionalAsset contract)
Primary sale marketplace (PublicSale contract)
Yield distribution (YieldDistributor contract)
NestJS backend with identity, asset, and yield modules
Frontend landing page with Freighter wallet connection
KYC submission UI
Asset catalog and detail pages
Investor portfolio dashboard
Yield claim UI

Phase 2 — Expansion

Governance contract — on-chain proposals and voting
Secondary marketplace — peer-to-peer token transfers
Albedo and Rabet wallet support
PostgreSQL persistence with Prisma ORM
Soroban event indexer
Advanced portfolio analytics

Phase 3 — Advanced RWA Infrastructure

AI-powered asset scoring and risk profiling
Cross-chain interoperability via Stellar anchors
Lending markets against tokenized collateral
Institutional onboarding and white-label protocol
Mobile app (React Native) with WalletConnect

Ready to start building on Blockplot?