Web3-Python-Development
January 13

СМАРТ КОНТРАКТЫ | Python edition

Сегодня Кратко Разберем Взаимодействие со смарт-контрактами на Python

План:

  1. Что такое Смарт-Контракты
  2. Что необходимо для написания скрипта
  3. Код
  4. Анализ

1. Что такое Смарт-Контракт?

Смарт-Контракт - программный код, который автоматически выполняет, контролирует и документирует выполнение условий соглашения между сторонами.

Он работает на блокчейне и выполняется, когда выполняются заранее определённые условия. Смарт-контракты гарантируют безопасность, прозрачность и автоматизацию, так как они не требуют посредников для исполнения условий контракта.

В блокчейне смарт-контракты могут использоваться для:

  • фунционирование децентрализованных приложений (dApps)
  • создания токенов
  • поддержки финансовых продуктов (DeFi)

и других сервисов, позволяя выполнять операции по заранее заданным правилам, которые не могут быть изменены после их размещения в сети. Это делает блокчейн прозрачным, защищённым и автономным.

Более Подробно про смарт-контракты рассказал в этом видео

youtu.be/zUeX0z03C3M

2. Что Необходимо

  1. Сеть (Mainnet, Ropsten, Rinkeby) или локальная сеть (Ganache или HardHat).
  2. Для публичной ноды используем сервисы (Infura или Alchemy) - они предоставляют API для работы с Ethereum.
  3. Смарт-контракт должен быть уже развернут на выбранной сети, и у вас должны быть его ABI (Application Binary Interface) и адрес. (ABI описывает функции контракта, которые можно вызвать, и типы данных, которые они используют.)
  4. Python + Web3Py библиотека

3. Код Скрипта

from web3 import web3
infuraURL = "https://mainnet.infura.io/v3/InfuraКлюч"

web3 = Web3(Web3.HTTPProvider(infuraURL))

if web3.is_connected():    
     print("Connected to Ethereum network ✅")    
     print(f"Current block number: {web3.eth.block_number}")

    USDT_contract_address = web3.to_checksum_address("0xdac17f958d2ee523a2206206994597c13d831ec7")
    contract_abi = [      
    {            
         "constant": True,  
         "inputs": [],
         "name": "name",
         "outputs": [{"name": "", "type": "string"}],
         "payable": False,
         "stateMutability": "view",   
         "type": "function"        
      },
      
      {            
      "constant": True,
      "inputs": [],            
      "name": "symbol",            
      "outputs": [{"name": "", "type": "string"}],            
      "payable": False,            
      "stateMutability": "view",            
      "type": "function"        
      },        
      
      {            
      "constant": True,            
      "inputs": [],            
      "name": "totalSupply",            
      "outputs": [{"name": "", "type": "uint256"}],            
      "payable": False,            
      "stateMutability": "view",            
      "type": "function"        
      },  
            
      {            
      "constant": True,            
      "inputs": [{"name": "_owner", "type": "address"}],            
      "name": "balanceOf",            
      "outputs": [{"name": "balance", "type": "uint256"}],            
      "payable": False,            
      "stateMutability": "view",            
      "type": "function"        
      },        
      
      {            
      "constant": True,            
      "inputs": [],            
      "name": "decimals",            
      "outputs": [{"name": "", "type": "uint8"}],            
      "payable": False,            
      "stateMutability": "view",            
      "type": "function"        
      }     
    ]
    
    contract = web3.eth.contract(address=USDT_contract_address, abi=contract_abi)
    
    name = contract.functions.name().call()    
    symbol = contract.functions.symbol().call()    
    total_supply = contract.functions.totalSupply().call()   
    decimals = contract.functions.decimals().call()  
    
    # get readable total supply
    readableTotalSupply = total_supply / (10 ** decimals)    
    formattedTotalSupply = "{:,.2f}".format(readableTotalSupply) 
    
    print(f"Name: {name}")   
    print(f"Symbol: {symbol}")    
    print(f"Total supply: {formattedTotalSupply}")
    

    # check balance 
    addressMy = web3.to_checksum_address("0x5041ed759Dd4aFc3a72b8192C143F72f4724081A")    
    balance = contract.functions.balanceOf(addressMy).call()    
    readableBalance = balance / (10 ** decimals)    
    formattedBalance = "{:,.2f}".format(readableBalance)    
    
    print(f"Balance of {addressMy}: {formattedBalance} {symbol}") 
    
else:    

    print("Failed to connect to Ethereum network ❌")

4. Анализ

Процесс Выполнения Скрипта:

  1. Подключение web3py библиотеки
  2. Получение и подключение к Ethereum Ноде через API Infura
  3. Получение адреса USDT (доступен публично на etherscan)
  4. Форматирование Адреса USDT в checksum для избежания ошибок.
  5. Получение ABI смарт-контракта USDT, также на etherscan
  6. Создаём объект контракта в Ethereum, который позволяет взаимодействовать с конкретным смарт-контрактом. (переменная contract)
  7. Вызов функций смарт-контракта - name, symbol, total_supply, decimals
  8. Форматирование - процесс далее
  9. Считываем балланс кошелька OKX на количество USDT (вызываем balanceOf функцию) + форматируем
  10. Вывод баланса OKX адреса

Справки:

checksum - используем для проверки точности и корректности данных, таких как адреса в сети Ethereum или другие идентификаторы.

decimals - функция смарт-контракта, которая возвращает количество знаков после запятой для токена. Например, для токенов ERC-20 это обычно 18.

Как форматируются балансы:

readableTotalSupply = total_supply / (10 ** decimals)

  1. Преобразуем общее количество токенов, хранящихся в переменной total_supply, в более читаемый формат, принимая во внимание количество десятичных знаков, определённых функцией decimals()
  2. total_supply — это общее количество токенов, но в реальности оно может быть задано с дополнительными десятичными знаками (например, для токенов ERC-20 это часто бывает 18 знаков после запятой).
  3. 10 ** decimals — вычисляем число 10 (десятичые знаки), возведённое в степень, равную количеству десятичных знаков для токена. Например, если токен имеет 18 десятичных знаков, то результатом будет число 1000000000000000000 (то есть 10^18).
  4. total_supply / (10 ** decimals) — деление общего количества токенов на это число 10 ** decimals приводит к преобразованию величины в более привычный формат, в котором число имеет точность, соответствующую количеству десятичных знаков. Например, если в сети токенов 18 десятичных знаков, то для значения 1000000000000000000 результат будет 1.0, что более интуитивно понятно.

далее

formattedTotalSupply = "{:,.2f}".format(readableTotalSupply)
форматирования числа в строку с двумя знаками после запятой и разделением разрядов с помощью запятой, что улучшает читаемость.

  1. :, — добавляет разделение тысячных разрядов запятой.
  2. .2f — ограничивает число двумя знаками после запятой (форматирует число как десятичное с точностью до двух знаков)
  3. format(readableTotalSupply) — форматирует значение readableTotalSupply с применением указанного шаблона (как было показано выше)

+ formattedTotalSupply обеспечит, что даже если число не имеет десятичных знаков, оно будет отображаться с двумя знаками после запятой, например, "1.00" вместо просто "1".

Теперь мы изучили смарт-контракты и освоили методы их интеграции с Python

все обновления по блокчейн-разработке в моем Telegram-Канале

t.me/code_vartcall

13.01.2025

by vartcall