פיתוח שוק נדל"ן וירטואלי מותאם אישית

עולם הנדל"ן הווירטואלי מתפתח במהירות, ופלטפורמות NFT סטנדרטיות כבר לא מתמודדות עם משימות השכרה, קואורדינטות ופיתוח. אנחנו בונים שווקי נדל"ן וירטואליים במפתח מלא, תוך שילוב השכרות on-chain וניהול נכסים דיגיטליים. הצוות שלנו מוביל את הפרויקט שלך מהקונספט ועד לתמיכה שוטפת, ומבטיח אמינות וסקלביליות.

שירותי פיתוח בלוקצ'יין

שאלות נפוצות

העבודות האחרונות

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1481
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1335
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1034
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1293
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    738
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1031

לפני כמה שנים, כשדצ׳נטרלנד השיקה את LAND, קואורדינטות החלקות אוחסנו בחוזה אחד. מטאוורסים מודרניים דורשים פתרונות גמישים: השכרות על-רשת, מכירות פומביות, פרמיית סמיכות. אנו בונים שווקים לנכסי נדל״ן וירטואליים התומכים ב-Decentraland LAND, Sandbox LAND, Otherside Otherdeed, ופתרונות L2 מותאמים אישית. כל פרויקט זקוק לפלטפורמת מסחר משני, השכרה ופיתוח משלו. פיתוח שוק נדל״ן וירטואלי הוא המפגש בין תשתית שוק NFT, מכניקת השכרה על-רשת, וניהול נתונים מרחביים. הניסיון שלנו כולל מעל 5 פרויקטים בתחום זה, ואנו מבטיחים ביקורת חוזים חכמים.

ההבדלים הטכניים לעומת שוק NFT כללי: לחלקות יש קואורדינטות (x, y), סמיכות ובונוסי סמיכות אפשריים, השכרה היא זמנית עם החזרת זכויות, ופיתוח יוצר קשרי מטא-דאטה בין NFT של LAND ל-NFT של תוכן. ניואנסים אלה דורשים פתרונות לא סטנדרטיים: מ-tokenId מבוסס קואורדינטות ועד האצלת זכויות זמנית דרך ERC-4907.

איך עובדת השכרה על-רשת של נדל״ן וירטואלי

ERC-4907: תקן NFT להשכרה

השכרת קרקע היא מקרה שימוש משמעותי: הבעלים מחזיק ב-LAND כהשקעה, השוכר משתמש בו לפיתוח/אירועים. יש צורך להפריד בין בעלות (NFT עם בעלים) לבין זכויות שימוש (עם שוכר). ERC-4907 מוסיף תפקיד user ל-ERC-721 — משתמש זמני עם חותמת זמן לתפוגה. חוזים יכולים לבדוק userOf(tokenId) במקום ownerOf לצורך גישה.

contract RentalMarketplace {
    struct RentalOffer {
        uint256 tokenId;
        address landContract;
        uint256 pricePerDay;
        uint256 minDays;
        uint256 maxDays;
        address paymentToken; // ERC-20 или address(0) для native
        bool active;
    }

    mapping(bytes32 => RentalOffer) public rentalOffers;

    function createRentalOffer(
        uint256 tokenId,
        address landContract,
        uint256 pricePerDay,
        uint256 minDays,
        uint256 maxDays,
        address paymentToken
    ) external {
        require(IERC721(landContract).ownerOf(tokenId) == msg.sender, "Not owner");
        bytes32 offerId = keccak256(abi.encode(tokenId, landContract, msg.sender, block.timestamp));
        rentalOffers[offerId] = RentalOffer({
            tokenId: tokenId,
            landContract: landContract,
            pricePerDay: pricePerDay,
            minDays: minDays,
            maxDays: maxDays,
            paymentToken: paymentToken,
            active: true
        });
    }

    function rent(bytes32 offerId, uint256 days) external payable {
        RentalOffer storage offer = rentalOffers[offerId];
        require(offer.active, "Offer not active");
        require(days >= offer.minDays && days <= offer.maxDays, "Invalid duration");
        uint256 totalCost = offer.pricePerDay * days;
        uint256 expiry = block.timestamp + days * 1 days;

        // Оплата
        if (offer.paymentToken == address(0)) {
            require(msg.value >= totalCost, "Insufficient payment");
        } else {
            IERC20(offer.paymentToken).safeTransferFrom(msg.sender, address(this), totalCost);
        }

        // Устанавливаем user через ERC-4907
        IERC4907(offer.landContract).setUser(offer.tokenId, msg.sender, uint64(expiry));

        // Выплачиваем владельцу (minus protocol fee)
        uint256 fee = totalCost * PROTOCOL_FEE_BPS / 10000;
        _transferPayment(offer.paymentToken, IERC721(offer.landContract).ownerOf(offer.tokenId), totalCost - fee);
        emit Rented(offerId, msg.sender, days, expiry);
    }
}

השכרה עם בטחון (ללא ERC-4907)

אם חוזה ה-LAND אינו תומך ב-ERC-4907: העברת NFT זמנית עם בטחון. השוכר מפקיד בטחון (שווה או גדול מערך ה-LAND), ה-NFT מועבר, ועם התפוגה הוא מוחזר אוטומטית דרך keeper או תביעה ידנית. בעיה: הבעלים מאבד את החזקה הפיזית ב-NFT במהלך תקופת ההשכרה (למרות שיש לו זכות להחזירו). סיכון: השוכר מוכר את ה-NFT למרות הבטחון. פתרון: ה-NFT מועבר לחוזה נאמנות (escrow), לא לשוכר.

אילו מכניקות שוק נדרשות?

רשימה ומכירות פומביות

enum SaleType {
    FIXED_PRICE,
    ENGLISH_AUCTION,
    DUTCH_AUCTION
}

struct Listing {
    uint256 tokenId;
    address seller;
    SaleType saleType;
    address paymentToken;
    uint256 startPrice;
    uint256 endPrice; // для Dutch auction: конечная цена
    uint256 startTime;
    uint256 endTime;
    uint256 highestBid; // для English auction
    address highestBidder;
}

מכירה פומבית הולנדית רלוונטית במיוחד למכירות ראשוניות של LAND: המחיר מתחיל גבוה ויורד אוטומטית למחיר רצפה. זה מבטל מלחמות גז במהלך mint — השוואה: מכירה הולנדית מפחיתה עמלות ב-40% לעומת mint במחיר קבוע.

מכירה פומבית אנגלית לשוק המשני של אחוזות נדירות: הצעות עם הגנה מפני הצעות יתר (הפרש מינימלי של X% בין הצעות).

תמלוגים ומבנה עמלות

ERC-2981 לתמלוגים על-רשת. מבנה עמלות סטנדרטי לשוק נדל״ן וירטואלי:

עמלה נמען סכום
עמלת שוק אוצר הפרוטוקול 2-2.5%
תמלוג יוצר היוצר המקורי של המטאוורס 2.5-5%
עמלת הפניה אם קיימת תוכנית הפניות 0.5-1%
מוכר בעל ה-LAND היתרה

תמלוגים לנדל״ן וירטואלי הם נושא שנוי במחלוקת. פלטפורמות כמו Blur ערערו את האכיפה. פתרון: אכיפת תמלוגים דרך החוזה (בלתי תלוי בשוק), או מודל ללא תמלוגים עם חלוקת הכנסות חלופית.

מהי פרמיית סמיכות?

תכונה ייחודית של שווקי קרקע: חלקות סמוכות שוות יותר יחד מאשר בנפרד. אלגוריתם חיפוש הסמיכות בודק קואורדינטות לרציפות קרדינלית ואלכסונית. הממשק מציג חלקות סמוכות מודגשות בעת ריחוף על אחת — המשתמש רואה רכישות חבילה פוטנציאליות. פרמיה טיפוסית ליצירת אחוזה היא 15-30% מסכום החלקות הבודדות. לדוגמה, שתי חלקות סמוכות שוות בנפרד 10 ETH כל אחת, אך בשילוב כאחוזה מחירן הכולל הוא 23 ETH במקום 20, פרמיה של 3 ETH (15%).

LAND NFT: פרטי נתונים

מערכת קואורדינטות על-רשת

כל חלקה היא NFT עם קואורדינטות ברשת. גישה סטנדרטית: tokenId מקודד קואורדינטות.

contract VirtualLand is ERC721 {
    struct Parcel {
        int256 x;
        int256 y;
        address tenant; // текущий арендатор (если сдан)
        uint256 leaseExpiry; // timestamp окончания аренды
        string contentURI; // что построено на участке
        uint8 zoneType; // 0=residential, 1=commercial, 2=plaza
    }

    mapping(uint256 => Parcel) public parcels;
    mapping(int256 => mapping(int256 => uint256)) public coordToTokenId; // coordToTokenId[x][y] = tokenId

    int256 public constant GRID_MIN = -150;
    int256 public constant GRID_MAX = 150;

    // tokenId = уникальный индекс из координат
    function coordsToTokenId(int256 x, int256 y) public pure returns (uint256) {
        // Сдвигаем в неотрицательные значения
        uint256 ux = uint256(x - GRID_MIN);
        uint256 uy = uint256(y - GRID_MIN);
        uint256 size = uint256(GRID_MAX - GRID_MIN + 1);
        return ux * size + uy;
    }

    function tokenIdToCoords(uint256 tokenId) public pure returns (int256 x, int256 y) {
        uint256 size = uint256(GRID_MAX - GRID_MIN + 1);
        x = int256(tokenId / size) + GRID_MIN;
        y = int256(tokenId % size) + GRID_MIN;
    }
}

אחוזה: חלקות מאוחדות

אחוזה = מספר חלקות סמוכות המאוחדות לנכס אחד. זה משמעותי: חלקה גדולה ומפותחת שווה יותר מסכום חלקיה. מכניקה:

contract EstateRegistry is ERC721 {
    struct Estate {
        uint256[] parcels; // массив tokenId входящих парцелей
        address landContract;
    }

    mapping(uint256 => Estate) public estates; // парцель → estate (если входит в estate)
    mapping(uint256 => uint256) public parcelToEstate;

    function createEstate(uint256[] calldata parcelIds) external returns (uint256 estateId) {
        // Проверяем adjacency
        require(_areAdjacent(parcelIds), "Parcels must be adjacent");

        // Проверяем ownership всех парцелей
        for (uint i = 0; i < parcelIds.length; i++) {
            require(landNft.ownerOf(parcelIds[i]) == msg.sender, "Not owner");
        }

        estateId = ++_estateIdCounter;

        // Передаём парцели в escrow этого контракта
        for (uint i = 0; i < parcelIds.length; i++) {
            landNft.transferFrom(msg.sender, address(this), parcelIds[i]);
            parcelToEstate[parcelIds[i]] = estateId;
        }

        estates[estateId] = Estate({
            parcels: parcelIds,
            landContract: address(landNft)
        });

        _mint(msg.sender, estateId);
    }
}

נתונים מרחביים וממשק מפה

מפה אינטראקטיבית — ממשק המשתמש הראשי של השוק. דרישות: הצגת אלפי חלקות עם קידוד צבע (למכירה, להשכרה, תפוסות), זום/פאן חלק, לחיצה על חלקה → מידע מפורט.

WebGL ו-deck.gl — האפשרויות היעילות ביותר לעיבוד מרחבי של אלפי אובייקטים. deck.gl (Uber) מותאם לנתונים גיאוגרפיים ועובד עם WebGL.

import { DeckGL } from '@deck.gl/react'
import { ScatterplotLayer } from '@deck.gl/layers'

const parcelLayer = new ScatterplotLayer({
  data: parcels,
  getPosition: (d) => [d.x * PARCEL_SIZE, d.y * PARCEL_SIZE, 0],
  getFillColor: (d) => {
    if (d.forSale) return [0, 200, 100] // зелёный — на продаже
    if (d.forRent) return [0, 100, 200] // синий — в аренду
    if (d.hasContent) return [150, 100, 200] // фиолетовый — застроен
    return [100, 100, 100] // серый — пусто
  },
  getRadius: PARCEL_SIZE / 2,
  pickable: true,
  onClick: ({ object }) => setSelectedParcel(object),
})

שכבת תוכן: מה נבנה על LAND

פיתוח קרקע הוא שכבת נתונים נפרדת. פורמטים סטנדרטיים: סצנת Decentraland SDK (מבוססת Babylon.js), נכסי GLTF/GLB, תוכן מבוסס iframe. URI התוכן מאוחסן במטא-דאטה של NFT ה-LAND. כאשר הפיתוח משתנה, הבעלים מעדכן את contentURI דרך contract RentalMarketplace { struct RentalOffer { uint256 tokenId; address landContract; uint256 pricePerDay; uint256 minDays; uint256 maxDays; address paymentToken; // ERC-20 или address(0) для native bool active; } mapping(bytes32 => RentalOffer) public rentalOffers; function createRentalOffer( uint256 tokenId, address landContract, uint256 pricePerDay, uint256 minDays, uint256 maxDays, address paymentToken ) external { require(IERC721(landContract).ownerOf(tokenId) == msg.sender, "Not owner"); bytes32 offerId = keccak256(abi.encode(tokenId, landContract, msg.sender, block.timestamp)); rentalOffers[offerId] = RentalOffer({ tokenId: tokenId, landContract: landContract, pricePerDay: pricePerDay, minDays: minDays, maxDays: maxDays, paymentToken: paymentToken, active: true }); } function rent(bytes32 offerId, uint256 days) external payable { RentalOffer storage offer = rentalOffers[offerId]; require(offer.active, "Offer not active"); require(days >= offer.minDays && days <= offer.maxDays, "Invalid duration"); uint256 totalCost = offer.pricePerDay * days; uint256 expiry = block.timestamp + days * 1 days; // Оплата if (offer.paymentToken == address(0)) { require(msg.value >= totalCost, "Insufficient payment"); } else { IERC20(offer.paymentToken).safeTransferFrom(msg.sender, address(this), totalCost); } // Устанавливаем user через ERC-4907 IERC4907(offer.landContract).setUser(offer.tokenId, msg.sender, uint64(expiry)); // Выплачиваем владельцу (minus protocol fee) uint256 fee = totalCost * PROTOCOL_FEE_BPS / 10000; _transferPayment(offer.paymentToken, IERC721(offer.landContract).ownerOf(offer.tokenId), totalCost - fee); emit Rented(offerId, msg.sender, days, expiry); } } . זו עסקה על-רשת, והיסטוריית השינויים נשמרת.

אנליטיקה וגילוי מחירים

שוק ללא אנליטיקה אינו תחרותי. המינימום הנדרש: מחיר רצפה לפי אזורים, היסטוריית מחירים, נפח, מפת חום של פעילות, מחשבון תשואת השכרה. נתונים מתועדים דרך The Graph subgraph לאירועים על-רשת ו-PostgreSQL עם PostGIS למטא-דאטה מחוץ לרשת ושאילתות מרחביות.

איך לבנות שוק נדל״ן וירטואלי: מדריך שלב-אחר-שלב

  1. עיצוב מוצר (1-2 שבועות). מפת עולם, אזורים, מודל מכירה ראשונית, מודל השכרה, מבנה עמלות.
  2. חוזים חכמים (4-6 שבועות). LAND NFT, חוזה אחוזה, שוק השכרה, שוק מכירה. ביקורת חובה.
  3. בקאנד ואינדקסר (3-4 שבועות). Subgraph, REST/GraphQL API, שאילתות מרחביות, אנליטיקת מחירים.
  4. פרונטאנד מפה (4-6 שבועות). מפה אינטראקטיבית, דף פרטי חלקה, ממשק רישום/השכרה, לוח אנליטיקה.
  5. תצוגה מקדימה של תוכן תלת-ממדי (2-3 שבועות, אופציונלי). תצוגת GLTF לחלקות מפותחות.
  6. בדיקות והשקה. בדיקת end-to-end, בדיקת עומס של המפה.

MVP ללא אחוזה ותוכן תלת-ממדי לוקח 3-4 חודשים. גרסה מלאה עם אחוזה, השכרה, אנליטיקה ותצוגה תלת-ממדית — 6-8 חודשים.

ערימת פיתוח

רכיב טכנולוגיה
LAND NFT Solidity ERC-721 + ERC-4907
חוזה אחוזה Solidity עם אימות סמיכות
חוזה השכרה Solidity + ERC-4907
חוזה שוק Solidity + ERC-2981
אינדקסר The Graph (subgraph)
מסד נתונים מרחבי PostgreSQL + PostGIS
פרונטאנד מפה deck.gl / Mapbox GL JS + React
תצוגה תלת-ממדית Three.js / Babylon.js
API בקאנד Node.js + Fastify
אחסון IPFS (Pinata) + Arweave

הזמינו פיתוח turnkey — המהנדסים שלנו עם ניסיון של 5+ שנים בבלוקצ׳יין יעריכו את הפרויקט שלכם ויציעו את הפתרון האופטימלי.

מה כלול בעבודה

  • פיתוח וביקורת חוזים חכמים (Solidity, Foundry)
  • אינטגרציה עם The Graph לאינדוקס
  • יישום מפה אינטראקטיבית (deck.gl)
  • API בקאנד ומסד נתונים (PostgreSQL + PostGIS)
  • תיעוד אינטגרציה והתקנה
  • תמיכה טכנית למשך חודש לאחר ההשקה

קבלו ייעוץ על פיתוח שוק נדל״ן וירטואלי. בעלי LAND חוסכים עד 30% במכירות חבילה בזכות פרמיית סמיכות.