小试牛刀-Telebot区块链游戏机器人

简介: 本文章为记录自己开发基于区块链和Telebot实现的[石头、剪刀、布]游戏的过程,加深自己对区块链知识的理解和使用,加深对TeleBot依赖库的使用,同时希望可以帮助到有想实现相关功能的朋友.

 目录

1.编写目的

2.实现功能

2.1 Wallet功能

2.2  游戏功能

2.3  提出功能

2.4  辅助功能

3.功能实现详解

3.1 wallet功能

3.2 游戏功能

3.3 提出功能

3.4 辅助功能

4.测试视频


Welcome to Code Block's blog

本篇文章主要介绍了

[Telebot区块链游戏机器人]

❤博主广交技术好友,喜欢文章的可以关注一下❤

1.编写目的

       本文章为记录自己开发基于区块链和Telebot实现的[石头、剪刀、布]游戏的过程,加深自己对区块链知识的理解和使用,加深对TeleBot依赖库的使用,同时希望可以帮助到有想实现相关功能的朋友.    

2.实现功能

2.1 Wallet功能

      用户可以通过/create命令命令创建游戏wallet,同时可以输入地址或扫码向该wallet发送一定数量的游戏代币,使用/wallet命令可以显示当前游戏wallet内的剩余代币数量。

2.2  游戏功能

       用户可以将bot机器人添加到公开群组,同时在群组内发送/game命令创建具有奖励随机结果的游戏,使用不同的人向群组内回复该游戏/pk进行对战,获取对战结果并向游戏wallet发送设定的奖励游戏代币,用户可以使用/del删除当前已创建游戏。

2.3  提出功能

       用户可以通过/bind命令绑定外部wallet并进行代币提出.

2.4  辅助功能

       用户可以输入/rules查看游戏规则,输入/help命令查看机器人命令及解释。

3.功能实现详解

3.1 wallet功能

       用户通过/create命令命令创建游戏wallet可以参考我的博客生成solana公私钥,/wallet显示wallet信息是通过solana.py根据保存的用户公钥查询.

def getBalance(publicKey:str):
    solana_client = Client(rpc_url)
    #公钥转换
    pubkey=Pubkey.from_string(publicKey)
    tokenPublicKey=Pubkey.from_string(BOGGY_TOKEN_MINT)
    #获取SOL余额
    sol_balance = solana_client.get_balance(pubkey)
    #获取SPL代币余额
    token_account=solana_client.get_token_accounts_by_owner_json_parsed(pubkey,TokenAccountOpts(mint=tokenPublicKey))
    if noTokenAccount(token_account):
        #不存在代币账户时,则余额为0
        token_balance=0.0
    else:
        token_account_json=token_account.value[0].account.to_json()
        token_balance=json.loads(token_account_json)['data']['parsed']['info']['tokenAmount']['uiAmount']
    sol_balance=(sol_balance.value/10**9)
    return sol_balance,token_balance

image.gif

       同时为方便用户使用,这边会将用户公钥通过qrcode库转换为二维码供用户扫码,主要代码为:

import qrcode
from io import BytesIO
from PIL import Image
import qrcode.main
def generate_qr(data):
    # 生成普通二维码
    qr = qrcode.main.QRCode(
        version=1,
        box_size=10,
        border=4,
    )
    qr.add_data(data)
    qr.make(fit=True)
    qr_img = qr.make_image(fill_color="black", back_color="white")
    
    # 将二维码图片保存到 BytesIO 对象中
    img_io = BytesIO()
    qr_img.save(img_io, format='PNG')
    img_io.seek(0)
    
    return img_io

image.gif

实现效果:

image.gif 编辑

3.2 游戏功能

       游戏功能的设计思路是当用户在群组内输入/game时,根据(群组id+用户id+消息id)生成唯一的游戏id并通过json文件存储创建者生成的随机值信息.存储信息如下:

{
  "create_user_id": 5385955983,
  "create_username": "GameOfBoggy",
  "create_select": 0,
  "pk_user_id": 2038830708,
  "pk_username": "USERT1223",
  "pk_select": 1,
  "pk_select_hex": "4b32e3c83744655cd4ab5cc991a342c99f52c73fa83f2393a995d53baf7aeb42",
  "amount": 20,
  "winner": "USERT1223",
  "create_select_hex": "bd55d5aa6e461c63c811ff78bb00753c517eba47f086e563783a5e023ff342af",
  "timestamp": 1721092512.869742,
  "create_drand_hex": "e3b4d8b6af061ddc40449d87c57c06d93de8fa73dff0055a07cc8dadb047dd1e",
  "pk_drand_hex": "808391bb3761db7f5be8ba296e143154f043ecced8e7a693698c8490300fe34f"
}

image.gif

这里的是使用本地secrets库和调用远程的drand随机数链生成两个hash值(create_drand_hex和create_select_hex为创建者游戏结果计算hash,pk_select_hex和pk_drand_hex为pk者游戏结果计算hash,这些结果面会保存到链上以保证游戏结果公平性和随机性.),这两个hash值转换为整数相加并对3取余获得随机结果,以保证游戏的随机性和不可预测性:

调用远程drand API:

def get_drand_randomness():
    # Drand API endpoint
    url = "https://api.drand.sh/52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971/public/latest"
    # Send request to Drand
    response = requests.get(url)
    if response.status_code == 200:
        # Parse the JSON response
        data = response.json()
        randomness = data['randomness']
        return randomness
    else:
        return secrets.token_hex()

image.gif

计算游戏随机结果:

def get_random_hex_int():
    select_hex=secrets.token_hex()
    drand_hex=get_drand_randomness()
    hex_int = int(select_hex, 16)
    drand_int = int(drand_hex,16)
    select=(drand_int+hex_int)%3
    return select,select_hex,drand_hex

image.gif

为保证游戏的美观性,这边使用图片+文字方式让机器人回复用户随机结果:

def random_game(bot,message,type,create_username):
    select,select_hex,drand_hex = get_random_hex_int()
    imgPath="./img/{}.png".format(img[select])
    msgText="<b>[{}] You random [{}]! @{}</b>".format(type,img[select],create_username)
    send_message=bot.send_photo(message.chat.id, open(imgPath, 'rb'), caption=msgText,parse_mode='HTML')
    return select,send_message,select_hex,drand_hex

image.gif

游戏奖励发放给获胜者为代币转移操作,实现代码如下(这里的draw_data即为计算出结果的hash值,将其备注添加链上):

#向绑定账户发送代币
def drawTokenAccount(sender_public_key:str,privateKey:str,draw_public_key:str,tokenAmount,draw_data):
    solana_client = Client(rpc_url)
    #发送者
    sender_pubkey = Pubkey.from_string(sender_public_key)
    #接收者
    draw_pubkey = Pubkey.from_string(draw_public_key)
    #Token代币地址
    token_mint_address = Pubkey.from_string(BOGGY_TOKEN_MINT)
    #发送者keypair
    sender_keypair=Keypair.from_base58_string(privateKey)
    
    try:
        #spl_client客户端
        source_token_account=get_associated_token_address(sender_pubkey,token_mint_address)
        dest_token_account=get_associated_token_address(draw_pubkey,token_mint_address)
        #交易
        transfer_instruction = transfer_checked(
            TransferCheckedParams(
                program_id=TOKEN_PROGRAM_ID,
                source=source_token_account,
                mint=token_mint_address,
                dest=dest_token_account,
                owner=sender_pubkey,
                amount=int(float(tokenAmount) * 1000000000),
                decimals=9,
            )
        )
        memo_instruction=create_memo(MemoParams(
            program_id=MEMO_PROGRAM_ID,
            signer=sender_pubkey,
            message=draw_data.encode('utf-8')
        ))
        # #获取最新的区块hash
        recent_blockhash_resp = solana_client.get_latest_blockhash()
        recent_blockhash=recent_blockhash_resp.value.blockhash
        # # 创建交易并添加转账指令
        transaction = Transaction()
        transaction.add(set_compute_unit_limit(200000))
        transaction.add(set_compute_unit_price(7500))
        transaction.add(transfer_instruction)
        transaction.add(memo_instruction)
        #设置最新区块hash
        transaction.recent_blockhash=recent_blockhash
        #设置手续费支付地址为发送者
        transaction.fee_payer=sender_pubkey
        #签名
        transaction.sign(sender_keypair)
        #发送交易
        response = solana_client.send_raw_transaction(transaction.serialize())
        #打印交易
        return response.value
    except Exception as e:
        print(f"Exception occurred: {str(e)}")
        return "error"

image.gif

实现效果:

/game 20 即创建了一个奖励为20代币的游戏,这里随机的是[剪刀]

image.gif 编辑

/pk pk者出了[布],所以创建者获得了奖励.

image.gif 编辑

我们可以点击按钮在链上查看奖励内容.

image.gif 编辑

可以看到这里包含了一个转移代币操作,是从pk者转移到创建者中的,同时包含了生成随机结果的hash值以保证游戏的公开和公平性。

3.3 提出功能

       用户输入/bind 绑定自己的链上地址后,提出功能即为代币转移操作,主要实现代码如下,这边直接根据用户的ID查到用户的创建的游戏wallet公钥私钥并进行转移:

def drawTokenFromUserId(send_user_id,draw_user_id,gameId,draw_data):
    publicKey,privateKey=get_account(send_user_id)
    drawPublicKey=getPublicKey(draw_user_id)
    amount=get_game_amount(gameId)
    tx=drawTokenAccount(publicKey,privateKey,drawPublicKey,amount,draw_data)
    return amount,tx

image.gif

3.4 辅助功能

       辅助功能即为telebot消息的回复,实现代码如下:

/rules:

from telebot import types
def handle_rules(bot, message):
    # 处理 /start 命令
    markup = types.InlineKeyboardMarkup()
    item1 = types.InlineKeyboardButton("BOGGY GROUP",url="https://t.me/BoggyCoin")
    markup.add(item1)
    welcome_message=(
        "<b>"
        "1.Before starting the game, you need to create(/create) a game wallet and transfer a small amount of sol and BOGGY tokens inward\n\n"
        "2.You can send '/game [amount]' create a game(default amount:500),and the Pker reply /pk with [GAME](need enough sol and BOGGY)\n\n"
        "3.Waiting for the results, the winner will receive the bonus set by the game creator\n\n"
        "4.The [Scissors] will win [Paper],[Parer] will win [Rock],[Rock] will win [Scissors]\n\n"
        "5.You Can at /wallet,draw you all token in you bind wallet,you can send '/bind [address]' bind you wallet\n\n"
        "[Create With #BOGGY]"
        "</b>"
    )
    bot.send_photo(message.chat.id,open("./img/rules.jpeg","rb"),welcome_message,parse_mode='HTML',reply_markup=markup)
def register_handlers(bot):
    bot.message_handler(commands=['rules'])(lambda message: handle_rules(bot, message))

image.gif

/help:

from telebot import types
def handle_help(bot, message):
    markup = types.InlineKeyboardMarkup()
    item1 = types.InlineKeyboardButton("BOGGY GROUP",url="https://t.me/BoggyCoin")
    markup.add(item1)
    help_text = (
        "<b>Welcome!</b>\n" 
        "<b>Here are the available commands:</b>\n"
        "<b>[/create]         Create you game wallet [DM*]</b>\n"
        "<b>[/bind]           Bind you draw wallet [DM*]</b> \n"
        "<b>[/wallet]         Show you wallet Info and Draw [DM*]</b>\n\n"
        "<b>[/game]           Create Game with amount</b>\n"
        "<b>[/pk]             Reply the Game Message and Pk it</b>\n"
        "<b>[/rules]          View more detailed game rules</b>\n\n"
        "<b>The [DM*] need DM Bot</b>"
    )
    
    bot.send_photo(message.chat.id,open("./img/help.jpeg","rb"),help_text, parse_mode='HTML',reply_markup=markup)
def register_handlers(bot):
    bot.message_handler(commands=['help'])(lambda message: handle_help(bot, message))

image.gif

4.测试视频

video_2024-07-16_11-48-41

image.gif

 

感谢您的关注和收藏!!!!!!

image.gif 编辑

目录
相关文章
|
SQL 分布式计算 资源调度
阿里云MaxCompute-Hive作业迁移语法兼容性踩坑记录
阿里云MaxCompute-Hive作业迁移语法兼容性踩坑记录
2246 0
|
9月前
|
API
Lua 的 Math 模块
这个库提供了基本的数学函数。 所以函数都放在表 math 中。 注解有 "integer/float" 的函数会对整数参数返回整数结果, 对浮点(或混合)参数返回浮点结果。 圆整函数(math.ceil, math.floor, math.modf) 在结果在整数范围内时返回整数,否则返回浮点数。
|
9月前
|
JSON API 数据格式
微店商品列表API接口文档
微店商品列表API(micro.item_search)支持通过关键词、分页和筛选条件获取商品信息,返回含ID、名称、价格、库存、图片等JSON数据。适用于电商工具、竞品分析等场景,具备分页灵活、数据实时等优势。
|
小程序
【01】微信支付商户申请下户到配置完整流程-微信商户申请-资料准备以及提交-微信商户密钥申请-申请+配置完整流程-优雅草卓伊凡
【01】微信支付商户申请下户到配置完整流程-微信商户申请-资料准备以及提交-微信商户密钥申请-申请+配置完整流程-优雅草卓伊凡
1001 2
【01】微信支付商户申请下户到配置完整流程-微信商户申请-资料准备以及提交-微信商户密钥申请-申请+配置完整流程-优雅草卓伊凡
|
Ubuntu 安全 Linux
Ubuntu 24.10 发行版登场:Linux 6.11 内核、GNOME 47 桌面环境
Ubuntu 24.10 还带来了 GNOME 47,增强了性能和稳定性,并引入了新功能。此版本的 Ubuntu 还默认在采用 Nvidia 显卡的硬件上切换到 Wayland,并在支持的硬件上默认使用开源的 Nvidia 560 内核模块。 另外需要注意的是,Ubuntu 24.10 是稳定版本,但作为非 LTS 版本,仅支持 9 个月。
|
人工智能 自然语言处理 监控
PMP认证有哪些要求:干货分享
本文详细介绍PMP的报考要求、考试内容与形式、认证有效期及价值,以及备考策略和推荐的学习工具,帮助考生高效准备。
741 2
|
供应链 监控 安全
云 HIS 系统的药品库存管理功能的特性
云HIS系统在药品库存管理方面引入了实时监控、智能预警、高效采购、精确追溯等多项新特性,提升了管理效率和准确性。系统支持多终端访问,实现自动化流程,并确保合规性和数据安全,同时还可与供应链集成,优化库存结构,提供全方位的药品管理解决方案。
708 5
云 HIS 系统的药品库存管理功能的特性
|
传感器
同步器的介绍
一、同步器的原理 同步器是一种电子电路,主要用于实现信号同步。它的工作原理是通过对输入信号进行采样和比较,判断信号的相位和频率,从而实现对信号的同步和输出。同步器可以分为基于时钟的同步器和基于相位的同步器两种类型。 1. 基于时钟的同步器 基于时钟的同步器是一种常见的同步器类型,它的工作原理是通过时钟信号对输入信号进行采样和比较,从而实现对信号的同步和输出。基于时钟的同步器主要由时钟源、采样电路和比较器等组成。时钟源用于产生时钟信号,采样电路用于对输入信号进行采样,比较器用于比较采样信号和时钟信号的相位和频率。 2. 基于相位的同步器 基于相位的同步器是另一种常见的同步器类型,它的工作原理
854 0
|
图形学
Unity UGUI拖拽移动
本文介绍了两种UI拖拽实现方式:精准拖拽和克隆拖拽。精准拖拽通过计算鼠标点击点与UI中心的偏移量,使UI跟随鼠标移动,适用于需要精确控制的场景。代码中通过`IBeginDragHandler`、`IDragHandler`和`IEndDragHandler`接口实现拖拽逻辑。克隆拖拽则在拖拽时克隆一个UI对象,使其跟随鼠标移动,适合视觉效果需求较高的场景。代码中同样使用上述接口,并在拖拽结束时销毁克隆对象。具体实现可参考提供的代码示例。
743 10
|
传感器 人工智能 搜索推荐
只靠一个头,能做出被“可爱攻击”的AI智能宠物吗?
本文探讨了AI实体化的一个具体方向——AI智能宠物,尤其是仅靠“一个头”设计的可行性与潜力。相比复杂的人形机器人,头部AI宠物成本更低、技术门槛更小,且能聚焦语言和表情交互,打造情感连接。文章分析了AI宠物的市场机遇,如满足孤独经济需求、成为消费电子新趋势,并指出“可爱”只是入场券,真正留住用户的在于深度交互体验。最后强调,精准洞察用户需求是关键,避免陷入“有趣但无用”的陷阱,为AI实体化找到切实可行的商业化路径。
568 0