
Economic · 경제 / Gaming NFT
Solple Metaverse Exchange
1인 개발로 진행한 메타버스/게임 자산용 멀티테넌트 NFT 거래소 컨셉 프로젝트입니다.
- 역할
- 1인 개발 · 아키텍처, 구현, 운영 도구
- 기간
- 2022
- 맥락
- Side Project
1인 개발로 진행한 메타버스/게임 자산용 멀티테넌트 NFT 거래소 컨셉 프로젝트입니다.
무엇이 시스템을 어렵게 만들었는가.
서로 다른 자산 타입을 지원하면서도 테넌트별 마켓을 분리 운영할 수 있어야 했습니다.
어떤 경계와 흐름으로 답했는가.
자산 카테고리/메타데이터 확장 및 테넌트 단위 마켓 구성 패턴을 설계했습니다.
Metaverse NFT Exchange for Game Companies
Developed a specialized NFT exchange platform designed for metaverse and gaming ecosystems, enabling game companies to manage in-game assets as tradable NFTs with full on-chain implementation.
Platform Architecture
Game-Centric Design
Built a multi-tenant marketplace where each game company operates its own branded NFT storefront within the unified platform.
Key Features:
- Isolated marketplaces per game
- Cross-game asset trading support
- Unified wallet integration
- Customizable storefronts
Smart Contract Implementation
Multi-Game NFT Management
Designed contracts to handle diverse game asset types on a single platform.
// Solple Multi-Game Marketplace
contract SolpleMarketplace {
struct Game {
string name;
address admin;
uint256 feePercent;
bool active;
}
struct Listing {
address nftContract;
uint256 tokenId;
address seller;
uint256 price;
string gameId;
bool isActive;
}
mapping(string => Game) public games;
mapping(bytes32 => Listing) public listings;
function registerGame(
string memory gameId,
string memory gameName,
address admin,
uint256 feePercent
) external onlyOwner {
games[gameId] = Game({
name: gameName,
admin: admin,
feePercent: feePercent,
active: true
});
}
function listAsset(
string memory gameId,
address nftContract,
uint256 tokenId,
uint256 price
) external {
require(games[gameId].active, "Game not active");
bytes32 listingId = keccak256(abi.encodePacked(
nftContract,
tokenId,
msg.sender,
block.timestamp
));
listings[listingId] = Listing({
nftContract: nftContract,
tokenId: tokenId,
seller: msg.sender,
price: price,
gameId: gameId,
isActive: true
});
// Transfer NFT to marketplace escrow
IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);
}
function purchaseAsset(bytes32 listingId) external payable {
Listing storage listing = listings[listingId];
require(listing.isActive, "Listing not active");
require(msg.value >= listing.price, "Insufficient payment");
Game memory game = games[listing.gameId];
// Calculate fees
uint256 gameFee = (listing.price * game.feePercent) / 10000;
uint256 platformFee = (listing.price * 250) / 10000; // 2.5%
uint256 sellerProceeds = listing.price - gameFee - platformFee;
// Distribute funds
payable(game.admin).transfer(gameFee);
payable(platformAddress).transfer(platformFee);
payable(listing.seller).transfer(sellerProceeds);
// Transfer NFT to buyer
IERC721(listing.nftContract).transferFrom(
address(this),
msg.sender,
listing.tokenId
);
listing.isActive = false;
}
}
In-Game Asset Types
Supported NFT Categories
Implemented support for various metaverse asset types:
-
Avatars & Skins
- Character appearances
- Customization items
- Accessories
-
Virtual Land
- Parcels and estates
- Building rights
- Location metadata
-
In-Game Items
- Weapons and tools
- Consumables
- Collectibles
-
Virtual Currency
- Game-specific tokens (ERC-20)
- Currency bundles
- Reward points
On-Chain Implementation
NFT Standard Customization
Extended ERC-721 with game-specific metadata:
contract GameAssetNFT is ERC721 {
struct AssetMetadata {
string assetType; // 'avatar', 'land', 'item', 'currency'
string gameId;
uint256 rarity; // 1-5 scale
mapping(string => string) attributes; // Dynamic attributes
bool transferable;
bool tradable;
}
mapping(uint256 => AssetMetadata) public assetData;
function mintGameAsset(
address to,
string memory gameId,
string memory assetType,
uint256 rarity,
string[] memory attrKeys,
string[] memory attrValues
) external onlyGameAdmin(gameId) returns (uint256) {
uint256 tokenId = _nextTokenId++;
_safeMint(to, tokenId);
AssetMetadata storage metadata = assetData[tokenId];
metadata.assetType = assetType;
metadata.gameId = gameId;
metadata.rarity = rarity;
metadata.transferable = true;
metadata.tradable = true;
for (uint256 i = 0; i < attrKeys.length; i++) {
metadata.attributes[attrKeys[i]] = attrValues[i];
}
return tokenId;
}
}
Backend Services
Game Integration API
Developed RESTful API for game studios to integrate with the platform:
Endpoints:
- POST /api/game/register: Register new game
- POST /api/asset/mint: Mint new in-game asset
- GET /api/marketplace/{gameId}: Get game marketplace listings
- POST /api/trade/initiate: Start asset trade
- GET /api/player/{address}/inventory: Get player assets
Metadata Management
Implemented off-chain metadata storage with IPFS:
// Asset Metadata Service
class MetadataService {
async uploadAssetMetadata(assetData) {
const metadata = {
name: assetData.name,
description: assetData.description,
image: assetData.imageUrl,
attributes: assetData.attributes,
game_info: {
game_id: assetData.gameId,
asset_type: assetData.assetType,
rarity: assetData.rarity
},
created_at: new Date().toISOString()
};
// Upload to IPFS
const cid = await ipfs.add(JSON.stringify(metadata));
const metadataURI = `ipfs://${cid}`;
// Store mapping in database
await db.assetMetadata.create({
tokenId: assetData.tokenId,
metadataURI: metadataURI,
cid: cid
});
return metadataURI;
}
}
Frontend Development
Player Dashboard
Built comprehensive UI for asset management:
- Portfolio View: Display all owned assets across games
- Marketplace Browser: Search and filter by game/type/rarity
- Trade Interface: Initiate trades and accept offers
- Transaction History: Track all asset movements
Game Studio Portal
Admin interface for game companies:
- Asset minting tools
- Marketplace configuration
- Revenue analytics
- Player statistics
Cross-Game Features
Universal Inventory System
Enabled players to view all their metaverse assets in one place:
// Unified Inventory Query
async function getPlayerInventory(playerAddress) {
const registeredGames = await solpleContract.getActiveGames();
const inventory = [];
for (const game of registeredGames) {
const nftContract = await solpleContract.getGameNFTContract(game.id);
const tokenIds = await nftContract.tokensOfOwner(playerAddress);
for (const tokenId of tokenIds) {
const metadata = await fetchMetadata(nftContract, tokenId);
inventory.push({
game: game.name,
tokenId: tokenId,
...metadata
});
}
}
return inventory;
}
Technical Achievements
| Feature | Implementation |
|---|---|
| Multi-Tenancy | Isolated game marketplaces |
| Asset Types | 4+ categories supported |
| On-Chain | Full blockchain implementation |
| Metadata | IPFS decentralized storage |
| Cross-Game | Unified inventory system |
