Skip to main content

NEAR Python SDK

A Pythonic interface for building NEAR smart contracts.

PyPI version License: MIT Python Versions

✨ Highlights

  • Class-Based Contracts - Clean, intuitive inheritance pattern
  • Pythonic Storage - Dictionary-like interface for on-chain data
  • Elegant Promise API - Intuitive chaining for cross-contract calls
  • Native Exception Handling - Use try/except like regular Python
  • Ergonomic Context Access - Properties instead of static methods

🚀 Getting Started

0️⃣ Install SDK

uv init your-contract
cd your-contract
uv add near-sdk-py

1️⃣ Create Your Contract

from near_sdk_py import Contract, view, call, init

class GreetingContract(Contract):
    @init
    def initialize(self, default_message="Hello"):
        self.storage["greeting"] = default_message
        return {"success": True}
    
    @view
    def get_greeting(self):
        return self.storage.get("greeting", "Hello, world!")
    
    @call
    def set_greeting(self, message):
        self.storage["greeting"] = message
        return {"success": True}

2️⃣ Build and Deploy

uvx nearc build
near deploy your-contract.testnet greeting_contract.wasm

3️⃣ Interact With Your Contract

# Call a view method (free, no gas needed)
near view your-contract.testnet get_greeting

# Call a change method (requires gas)
near call your-contract.testnet set_greeting '{"message":"Hello, NEAR!"}' --accountId your-account.testnet

📚 SDK Components

Contract Base Class

All contracts inherit from the Contract class, which provides:

from near_sdk_py import Contract, call, view

class MyContract(Contract):
    @init
    def initialize(self):
        self.storage["owner"] = self.predecessor_account_id
        
    @view
    def get_status(self):
        # Access context properties directly
        return {
            "contract_id": self.current_account_id,
            "caller": self.predecessor_account_id,
            "owner": self.storage.get("owner"),
            "block_height": self.block_height,
            "timestamp": self.block_timestamp
        }
    
    @call
    def update_config(self, key, value):
        # Simple validation
        self.assert_owner()
        
        # Use dict-like storage access
        self.storage[key] = value
        
        # Easy logging
        self.log_event("config_updated", {"key": key})
        return {"success": True}

Storage Interface

The storage interface is now more Pythonic with dictionary-like access:

# Store values with dict syntax
self.storage["key"] = "value"                # String value
self.storage["config"] = {"active": True}    # Any JSON-serializable value

# Retrieve values with easy defaults 
value = self.storage.get("key", "default")   # With default
config = self.storage["config"]              # Direct access

# Check for keys
if "owner" in self.storage:
    # Do something
    
# Delete keys
del self.storage["old_key"]

Context Properties

Access blockchain context directly as properties:

# Account information
account_id = self.current_account_id      # This contract's account
caller = self.predecessor_account_id      # Who called this function
signer = self.signer_account_id           # Who signed the transaction

# Transaction details
deposit = self.attached_deposit           # NEAR tokens attached
gas = self.prepaid_gas                    # Gas allocated to this call

# Blockchain state 
height = self.block_height                # Current block height
timestamp = self.block_timestamp          # Current block timestamp

Logging Helpers

# Simple logging
self.log_info("Operation completed successfully")
self.log_warning("Approaching storage limit")
self.log_error("Transaction failed: insufficient deposit")

# NEP-standard event logging 
self.log_event("nft_mint", {
    "token_id": "token-123",
    "owner_id": "alice.near",
    "memo": "Happy birthday!"
})

Exception Handling

Use native Python exceptions for error handling:

from near_sdk_py import Contract, call, InvalidInput, AccessDenied

class MyContract(Contract):
    @call
    def restricted_method(self):
        if self.predecessor_account_id != self.storage.get("owner"):
            raise AccessDenied("Only the owner can call this method")
            
        if self.attached_deposit < self.storage.get("min_deposit", 0):
            raise InvalidInput("Insufficient deposit")
            
        try:
            # Do something that might fail
            result = some_operation()
        except Exception as e:
            raise ContractError(f"Operation failed: {e}")

🔄 Cross-Contract Calls

The SDK provides a powerful Promises API for making cross-contract calls with elegant method chaining:

from near_sdk_py import call, callback, CrossContract, PromiseResult

class CrossContractExample(Contract):
    @call
    def get_token_balance(self, token_contract_id: str, account_id: str):
        # Create a contract instance and chain the operations
        promise = (
            CrossContract(token_contract_id)
            .call("ft_balance_of", account_id=account_id)
            .then("process_balance", account_id=account_id)
            .value()
        )
        return promise
    
    @callback
    def process_balance(self, result: PromiseResult, account_id: str):
        if result.success:
            return {
                "account_id": account_id,
                "balance": result.data
            }
        else:
            return {
                "account_id": account_id,
                "error": "Failed to retrieve balance"
            }

Key features of the Promises API:

  • Fluent interface for chaining operations
  • Automatic callback registration
  • Promise result handling
  • Support for batch operations

Read the Promises documentation →

🔐 Security Best Practices

The Contract class provides built-in validation helpers:

from near_sdk_py import call, ONE_NEAR

class SecureContract(Contract):
    @call
    def transfer_ownership(self, new_owner):
        self.assert_one_yocto()  # Ensures tx is signed (non-delegated)
        self.assert_owner()      # Verifies caller is the owner
        # Implementation...
    
    @call
    def place_bid(self, token_id):
        self.assert_min_deposit(ONE_NEAR)  # At least 1 NEAR required
        # Implementation...

🧪 Testing with near-pytest

The NEAR Python SDK works seamlessly with near-pytest, a pytest-native framework for testing NEAR smart contracts. Together, they provide a powerful toolchain for developing and testing contracts.

Key Features of near-pytest

  • Zero-config setup - Automatic sandbox management, contract compilation, and account creation
  • Lightning-fast tests - State snapshots between tests make test suites run significantly faster
  • Intuitive API - Simple, Pythonic interfaces for interacting with contracts and accounts

Example Test Setup

from near_pytest.testing import NearTestCase

class TestGreetingContract(NearTestCase):
    @classmethod
    def setup_class(cls):
        super().setup_class()
        
        # Compile the contract
        wasm_path = cls.compile_contract(
            "contracts/greeting.py", 
            single_file=True
        )
        
        # Deploy the contract
        cls.contract_account = cls.create_account("contract")
        cls.instance = cls.deploy_contract(cls.contract_account, wasm_path)
        
        # Create test user
        cls.user = cls.create_account("user")
        
        # Save state for future resets - this is crucial for performance
        cls.save_state()
    
    def setup_method(self):
        # Reset to initial state before each test method
        # This makes tests run much faster than re-deploying
        self.reset_state()
        
    def test_greeting(self):
        # Set greeting as user
        result = self.instance.call_as(
            account=self.user,
            method_name="set_greeting",
            args={"message": "Hello, tests!"}
        )
        result = json.loads(result)
        assert result["success"] == True
        
        # Get greeting
        greeting = self.instance.call_as(
            account=self.user,
            method_name="get_greeting"
        )
        assert greeting == "Hello, tests!"

Running Tests

Simply run with pytest:

pytest test_greeting_contract.py -v

State Management in Tests

The state management pattern (save_state/reset_state) is what makes near-pytest tests run significantly faster than traditional approaches. Rather than re-deploying contracts and recreating accounts for each test, it:

  1. Sets up the full environment once in setup_class
  2. Takes a snapshot of the blockchain state
  3. Quickly resets to this snapshot before each test

This approach can make test suites run orders of magnitude faster, especially as your test suite grows.

📊 Example Projects

The SDK includes starter templates for common contract types:

📈 Performance Considerations

  • Group related data in a single storage entry to reduce calls
  • Implement pagination for methods that return large collections
  • For collections, use the SDK's storage primitives which are optimized for gas efficiency

🤝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for details on how to submit pull requests, report issues, and suggest improvements.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.


Made with ❤️ by r-near

Metadata

Release files for near-sdk-py 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for near-sdk-py 1.0.0
File Size Uploaded
near_sdk_py-1.0.0.tar.gz 159.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for near-sdk-py 1.0.0
File Interpreter ABI Platform
near_sdk_py-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 201.5 kB

Release files / near_sdk_py-1.0.0.tar.gz

Download URL near_sdk_py-1.0.0.tar.gz
Size 159.7 kB
Tags Source
SHA-256 checksum
How to use checksums
c7e20b4ea7259262b1c1308134c2d1f43c5a447ddd6d68d12ecc13169a88da48
BLAKE2b-256 checksum
How to use checksums
d7664de0abdcaef64a637e446df18eb56d1f05b26312cffadfd6a3997dafd399
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.1

Release files / near_sdk_py-1.0.0-py3-none-any.whl

Download URL near_sdk_py-1.0.0-py3-none-any.whl
Size 41.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9a604a226f3d146ff99e37b1d8668234d75136e7570bb2389b7f206d08d7d17d
BLAKE2b-256 checksum
How to use checksums
0af6e5f26ec862e4d71832669743976267547e7a2e424acdddf8103d0935be6b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.1

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page