Wednesday, December 18, 2024

Getting Started: A Simple Smart Contract for Beginners

 I have written several articles about smart contracts, but many of my readers requested a tutorial on creating a very simple smart contract and interacting with it using the Ganache Ethereum network and Python. To fulfill their request, I worked overnight to bring this guide to life. Here’s an overview of what we’ll cover in this tutorial:

Here’s a brief explanation of each step:

  1. Create a smart contract in Solidity using Remix IDE

    In this step, you'll write a simple smart contract that allows users to store a message, read the currently stored message, and update it with a new one.

    The contract has two key functionalities:

    • Read the Current Message:
      The greeting variable is marked as public, meaning it can be accessed directly from outside the contract. This allows anyone to view the currently stored message without calling a specific function.

    • Update the Message:
      The setGreeting function allows users to update the greeting variable with a new message. This updates the contract's state and reflects the new message for future reads

2. Compile and deploy the smart contract in the Ganache test environment
Compile the contract in Remix, then connect to Ganache (a personal Ethereum blockchain) to deploy it. This step mimics real-world deployment in a safe, controlled environment.
3. Download and set up the Ganache application
Install Ganache to create a local blockchain. It generates test accounts with Ether, making it perfect for testing smart contract interactions.
4.Write a Python script to interact with the deployed smart contract
Use Python libraries like web3.py to connect to the Ganache network, call functions, and interact with your deployed smart contract programmatically.

 

to be continued....

 

Simple NFT Marketplace Code Explained: A Detailed Breakdown of Minting, Listing, and Buying NFTs

 In this post, I created a simple NFT marketplace contract. The program listing follows, and I will explain each line to help basic learners understand what it does.

Here is the complete program listing:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract SimpleNFTMarketplace is ERC721, Ownable {
    uint256 public nextTokenId;
    mapping(uint256 => uint256) public prices;
    mapping(uint256 => bool) public forSale;

    constructor() ERC721('SimpleNFT', 'SNFT') {}

    function mint(address to) external onlyOwner {
        _safeMint(to, nextTokenId);
        nextTokenId++;
    }

    function listForSale(uint256 tokenId, uint256 price) external {
        require(ownerOf(tokenId) == msg.sender, "You do not own this token");
        require(price > 0, "Price must be greater than zero");
        prices[tokenId] = price;
        forSale[tokenId] = true;
    }

    function buy(uint256 tokenId) external payable {
        require(forSale[tokenId], "Token is not for sale");
        require(msg.value >= prices[tokenId], "Insufficient funds sent");

        address seller = ownerOf(tokenId);
        _transfer(seller, msg.sender, tokenId);

        payable(seller).transfer(msg.value);

        forSale[tokenId] = false;
        prices[tokenId] = 0;
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return "https://api.example.com/metadata/";
    }
}

License and Solidity Version

1
2
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

  • License Identifier: // SPDX-License-Identifier: MIT specifies that this contract uses the MIT license, making it open source and freely usable by others.
  • Solidity Version: pragma solidity ^0.8.0; ensures that the contract is compiled with Solidity version 0.8.0 or later, but not with versions that are not backward-compatible.

Imports

1
2
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";


  • ERC721: This is an import from the OpenZeppelin library, which provides a standard implementation of the ERC-721 non-fungible token standard.
  • Ownable: This is another import from OpenZeppelin, which provides basic access control where there is an owner account that can be granted exclusive access to specific functions.

Contract Definition

1
contract SimpleNFTMarketplace is ERC721, Ownable {

  • Inheritance: The contract SimpleNFTMarketplace inherits from ERC721 and Ownable, meaning it has all the functionalities of a standard ERC-721 token and basic ownership functionalities.

State Variables

1
2
3
uint256 public nextTokenId;
mapping(uint256 => uint256) public prices;
mapping(uint256 => bool) public forSale;

  • nextTokenId: This variable keeps track of the next token ID to be minted.
  • prices: This mapping associates each token ID with a price in wei (the smallest unit of Ether).
  • forSale: This mapping keeps track of whether a token is listed for sale or not.

Constructor

1
constructor() ERC721('SimpleNFT', 'SNFT') {}

  • Constructor: The constructor initializes the contract. It calls the constructor of the ERC721 contract with the name "SimpleNFT" and the symbol "SNFT".

Mint Function

1
2
3
4
function mint(address to) external onlyOwner {
    _safeMint(to, nextTokenId);
    nextTokenId++;
}

  • mint: This function allows the contract owner to mint new NFTs.
    • onlyOwner: This modifier ensures that only the owner of the contract can call this function.
    • _safeMint: This is an internal function from the ERC721 contract that safely mints a new token and assigns it to the specified address.
    • Increment Token ID: After minting a new token, nextTokenId is incremented to ensure the next token has a unique ID.

List for Sale Function

1
2
3
4
5
6
function listForSale(uint256 tokenId, uint256 price) external {
    require(ownerOf(tokenId) == msg.sender, "You do not own this token");
    require(price > 0, "Price must be greater than zero");
    prices[tokenId] = price;
    forSale[tokenId] = true;
}

  •  listForSale: This function allows the owner of an NFT to list it for sale.

  • Check Ownership: require(ownerOf(tokenId) == msg.sender, "You do not own this token"); ensures that only the owner of the token can list it for sale.
  • Check Price: require(price > 0, "Price must be greater than zero"); ensures that the sale price is positive.
  • Set Price and Sale Status: The price and sale status of the token are updated in the prices and forSale mappings, respectively.

 Buy Function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function buy(uint256 tokenId) external payable {
    require(forSale[tokenId], "Token is not for sale");
    require(msg.value >= prices[tokenId], "Insufficient funds sent");

    address seller = ownerOf(tokenId);
    _transfer(seller, msg.sender, tokenId);

    payable(seller).transfer(msg.value);

    forSale[tokenId] = false;
    prices[tokenId] = 0;
}

  • buy: This function allows a user to purchase an NFT that is listed for sale.
    • Check Sale Status: require(forSale[tokenId], "Token is not for sale"); ensures the token is actually listed for sale.
    • Check Funds: require(msg.value >= prices[tokenId], "Insufficient funds sent"); ensures the buyer has sent enough Ether to cover the price.
    • Transfer Token: _transfer(seller, msg.sender, tokenId); transfers the token from the seller to the buyer.
    • Transfer Payment: payable(seller).transfer(msg.value); transfers the payment to the seller.
    • Update Sale Status: The sale status and price of the token are reset.

Base URI Function

1
2
3
function _baseURI() internal view virtual override returns (string memory) {
    return "https://api.example.com/metadata/";
}

  • _baseURI: This function returns the base URI for the token metadata. It overrides the _baseURI function from the ERC721 contract.
    • Metadata URI: https://api.example.com/metadata/ is the base URI where the metadata for the tokens is hosted. This should be replaced with your actual metadata URL.

Summary

  • Minting NFTs: The contract owner can mint new NFTs.
  • Listing NFTs for Sale: NFT owners can list their tokens for sale by setting a price.
  • Buying NFTs: Users can buy listed NFTs by sending sufficient Ether to the contract, which then transfers the token and payment.
  • Metadata Management: The base URI for the token metadata can be customized to point to the appropriate metadata location.

This contract forms the basis for a simple NFT marketplace where users can mint, list, and buy NFTs. It can be extended with more features such as auctions, royalties, or advanced metadata handling based on your requirements.

Monday, December 16, 2024

Profit-Driven Wallet Detection and Blockchain Monitoring Dashboard

 

Architecture Overview

  1. Data Source: Use blockchain APIs like Alchemy, Infura, or Etherscan to fetch real-time transactions.
  2. Real-Time Monitoring: Connect to the blockchain node using web3.py or WebSocket APIs to monitor the mempool or blocks.
  3. Transaction Analysis:
    • Identify patterns of wallets making profit-driven transactions.
    • Cluster wallets into groups (cabals) using techniques like graph analysis or machine learning.
  4. Dashboard Visualization: Use tools like Dash, Plotly, or Streamlit to create a live dashboard for actionable insights.

Step-by-Step Implementation

1. Environment Setup

Install the required libraries:

pip install web3 pandas networkx dash plotly matplotlib requests
 

 

2. Monitor Real-Time Blockchain Transactions

Use web3.py to connect to an Ethereum node and monitor transactions in real-time.

Example Code to Fetch Transactions:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from web3 import Web3
import time

# Connect to an Ethereum Node (Infura or Alchemy endpoint)
infura_url = "https://mainnet.infura.io/v3/YOUR_PROJECT_ID"
web3 = Web3(Web3.HTTPProvider(infura_url))

if not web3.isConnected():
    print("Failed to connect to the Ethereum blockchain")
    exit()

print("Connected to Ethereum Blockchain")

def monitor_transactions():
    latest_block = web3.eth.blockNumber
    print(f"Monitoring transactions from block {latest_block}...")

    while True:
        try:
            new_block = web3.eth.blockNumber
            if new_block > latest_block:
                print(f"New Block Found: {new_block}")
                block = web3.eth.getBlock(new_block, full_transactions=True)

                for tx in block.transactions:
                    print(f"Tx Hash: {tx.hash.hex()} | From: {tx['from']} -> To: {tx['to']} | Value: {web3.fromWei(tx['value'], 'ether')} ETH")

                latest_block = new_block
            time.sleep(5)  # Check for new blocks every 5 seconds
        except Exception as e:
            print(f"Error: {e}")
            time.sleep(5)

monitor_transactions()

 

3. Identifying Profit-Driven Wallet Groups (Cabals)

To identify wallet groups that act together for profit-driven behavior:

  1. Track Repeated Interactions: Analyze wallets that frequently interact with each other.
  2. Profit Behavior: Monitor transactions where wallets buy low and sell high.
  3. Graph Clustering: Use NetworkX to create a graph of wallets and transactions to find tightly connected groups.

Example Code for Wallet Clustering:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import networkx as nx
import pandas as pd

# Sample transaction data (replace with real-time data)
transactions = [
    {"from": "0xWalletA", "to": "0xWalletB", "value": 5},
    {"from": "0xWalletB", "to": "0xWalletC", "value": 2},
    {"from": "0xWalletC", "to": "0xWalletA", "value": 3},
    {"from": "0xWalletD", "to": "0xWalletE", "value": 4},
]

# Build a graph of wallet interactions
G = nx.DiGraph()

for tx in transactions:
    G.add_edge(tx["from"], tx["to"], weight=tx["value"])

# Detect tightly connected components (cabals)
cabals = list(nx.strongly_connected_components(G))

print("Identified Wallet Groups (Cabals):")
for idx, cabal in enumerate(cabals):
    print(f"Group {idx + 1}: {cabal}")

# Visualize the graph
import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_color="skyblue", node_size=2000, font_size=10, font_weight="bold")
nx.draw_networkx_edge_labels(G, pos, edge_labels={(u, v): f"{d['weight']} ETH" for u, v, d in G.edges(data=True)})
plt.title("Wallet Interaction Graph")
plt.show()

 


4. Real-Time Dashboard for Insights

Use Dash and Plotly to build a real-time dashboard to visualize transactions, wallet groups, and actionable insights.

Example Code for Dashboard:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import dash
from dash import dcc, html
import plotly.graph_objs as go

# Sample wallet groups
wallet_groups = {
    "Group 1": ["0xWalletA", "0xWalletB", "0xWalletC"],
    "Group 2": ["0xWalletD", "0xWalletE"],
}

# Real-time transaction data (mocked for now)
transactions = [
    {"block": 1, "wallet": "0xWalletA", "action": "Buy", "value": 10},
    {"block": 2, "wallet": "0xWalletB", "action": "Sell", "value": 12},
    {"block": 3, "wallet": "0xWalletC", "action": "Buy", "value": 8},
]

# Initialize Dash app
app = dash.Dash(__name__)

app.layout = html.Div([
    html.H1("Blockchain Wallet Monitoring Dashboard", style={"textAlign": "center"}),

    # Wallet Groups Section
    html.Div([
        html.H3("Identified Wallet Groups (Cabals):"),
        html.Ul([html.Li(f"{group}: {', '.join(wallets)}") for group, wallets in wallet_groups.items()])
    ]),

    # Real-time Transactions
    dcc.Graph(
        id="transaction-graph",
        figure={
            "data": [
                go.Bar(
                    x=[tx["block"] for tx in transactions],
                    y=[tx["value"] for tx in transactions],
                    text=[tx["wallet"] for tx in transactions],
                    name="Transaction Value",
                )
            ],
            "layout": go.Layout(
                title="Real-Time Transactions",
                xaxis={"title": "Block Number"},
                yaxis={"title": "Transaction Value (ETH)"},
            ),
        },
    ),
])

if __name__ == "__main__":
    app.run_server(debug=True)

 

How It Works:

  1. Transaction Monitoring:

    • Real-time transactions are fetched using web3.py.
  2. Wallet Analysis:

    • Transactions are analyzed to identify wallets that frequently interact and form groups (cabals).
    • Graph-based clustering finds tightly connected wallets.
  3. Dashboard Insights:

    • Wallet groups, transaction activity, and profits are visualized in a live dashboard.

Next Steps for Production-Ready System:

  1. Enhance Data Source: Use WebSockets for near-instant transaction updates.
  2. Profit Analysis: Track wallet balances using on-chain data.
  3. Machine Learning: Use clustering algorithms like DBSCAN or K-Means to identify patterns automatically.
  4. Live Deployment: Host the dashboard on a cloud platform like AWS, Heroku, or Azure.

Sunday, December 8, 2024

Building an NFT Marketplace with Python: A Comprehensive Guide

 Non-Fungible Tokens (NFTs) have revolutionized the digital economy, enabling creators to monetize their work and collectors to own unique digital assets. In this blog post, we'll explore how to build a simple NFT marketplace using Python, leveraging blockchain technology and the Ethereum network.


What Is an NFT Marketplace?

An NFT marketplace is a platform where users can mint, buy, sell, and trade NFTs. It typically includes features such as:

  • Minting NFTs: Creating unique tokens on the blockchain.
  • Listing NFTs: Displaying NFTs for sale or auction.
  • Buying and Selling NFTs: Enabling peer-to-peer transactions.

Tools and Libraries

To create our Python-based NFT marketplace, we'll use the following tools:

  1. web3.py: A Python library for interacting with the Ethereum blockchain.
  2. Flask: A lightweight web framework for building the frontend and backend.
  3. Solidity: For writing the smart contract that governs the NFT.
  4. MetaMask: A browser wallet to interact with the blockchain.
  5. Infura or Alchemy: For connecting to the Ethereum network.

Smart Contract for NFTs

NFTs are created using the ERC-721 standard on Ethereum. Below is a sample Solidity contract:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";

contract NFTMarketplace is ERC721URIStorage {
    uint256 public tokenCounter;

    constructor() ERC721("MyNFT", "MNFT") {
        tokenCounter = 0;
    }

    function mintNFT(string memory tokenURI) public returns (uint256) {
        uint256 newTokenId = tokenCounter;
        _safeMint(msg.sender, newTokenId);
        _setTokenURI(newTokenId, tokenURI);
        tokenCounter++;
        return newTokenId;
    }
}

Python Backend

Step 1: Connect to Ethereum


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from web3 import Web3

# Connect to Ethereum network
infura_url = "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"
web3 = Web3(Web3.HTTPProvider(infura_url))

# Check connection
if web3.isConnected():
    print("Connected to Ethereum network")
else:
    print("Connection failed")

Step 2: Interact with the Smart Contract

Get the contract's address and ABI:

1
2
3
4
5
6
7
contract_address = "0xYourContractAddress"
abi = [
    # Include the ABI of the contract
]

# Load the contract
contract = web3.eth.contract(address=contract_address, abi=abi)

Step 3: Mint an NFT

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def mint_nft(user_address, token_uri):
    transaction = contract.functions.mintNFT(token_uri).buildTransaction({
        'from': user_address,
        'nonce': web3.eth.getTransactionCount(user_address),
        'gas': 3000000,
        'gasPrice': web3.toWei('20', 'gwei')
    })
    signed_txn = web3.eth.account.signTransaction(transaction, private_key="YOUR_PRIVATE_KEY")
    tx_hash = web3.eth.sendRawTransaction(signed_txn.rawTransaction)
    print(f"Transaction sent: {tx_hash.hex()}")
    receipt = web3.eth.waitForTransactionReceipt(tx_hash)
    print("Transaction mined:", receipt)

Flask Frontend

Create a Flask app to interact with the blockchain:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/mint', methods=['POST'])
def mint():
    data = request.json
    user_address = data['address']
    token_uri = data['token_uri']
    try:
        mint_nft(user_address, token_uri)
        return jsonify({'message': 'NFT minted successfully!'}), 200
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == "__main__":
    app.run(debug=True)


Testing the Application

  1. Deploy the smart contract to a test network (like Rinkeby).
  2. Start the Flask server and use tools like Postman to test the /mint endpoint.
  3. Mint an NFT by sending the user address and metadata URL (stored in IPFS or a similar service).

Future Enhancements

To create a full-fledged marketplace, consider adding the following features:

  • NFT Listings: Store NFTs for sale in a database or directly on the blockchain.
  • Purchase Mechanism: Enable users to buy listed NFTs using cryptocurrency.
  • Frontend: Use a framework like React to build an interactive UI.

Conclusion

Building an NFT marketplace with Python provides hands-on experience in blockchain development and decentralized applications. This example demonstrated minting an NFT and the foundational steps to create a marketplace.

Start coding, and take a step into the future of digital ownership!

Would you like the complete source code or help with setting up the environment?