Skip to main content

GO-SDK

DeBox 机器人 区块链按钮 使用文档

基本介绍

区块链按钮 用于在 DeBox 聊天机器人中集成区块链的功能组件。

基于 debox-chat-go-sdk,您可以轻松实现查询区块链信息、签名、转账、合约调用、Swap等功能:

本指南将详细介绍 区块链按钮 的主要功能,并提供完整的示例代码,帮助开发者快速上手并高效开发。

目录

说明

debox-chat-go-sdk对区块链按钮进行了封装,开发者只需要按约定的格式编写 RPC-JSON 字符串,组装成按钮消息,
然后调用debox-chat-go-sdk的函数,将按钮消息发送出去,用户收到消息,点击按钮,即可触发区块链功能调用。
开放平台会把用户交互后的结果通知开发者,开发者可以据此进行下一步的业务逻辑处理。

eth_XXX 获取公开信息

支持所有EVM 链的查询接口, 比如:
eth_getBalance
eth_getCode
eth_gasPrice
eth_getBlockByHash
eth_getTransactionCount
eth_getTransactionByHash
……
var eth_getBalanceStr = `{
"jsonrpc": "2.0",
"id": 101,
"method": "eth_getBalance",
"params": [
{ "chainId": 56 },
"selfAddress",
"latest"
]
}`

personal_sign

personal_sign签名,参数如下:

var personal_signStr = `{
"jsonrpc": "2.0",
"id": 102,
"method": "personal_sign",
"params": [
{ "chainId": 56 },
"0x506c65617365207369676e2074686973206d65737361676520746f20636f6e6669726d20796f7572206964656e746974792e",
"selfAddress"
]
}`

eth_signTypedData_v4

eth_signTypedData_v4签名,参数如下:

// 发送消息时用到的参数
var eth_signTypedData_v4Str = `{
"jsonrpc": "2.0",
"id": 103,
"method": "eth_signTypedData_v4",
"params": [
"selfAddress",
{
"types": {
"EIP712Domain": [
{
"name": "name",
"type": "string"
},
{
"name": "version",
"type": "string"
},
{
"name": "chainId",
"type": "uint256"
},
{
"name": "verifyingContract",
"type": "address"
}
],
"Person": [
{
"name": "name",
"type": "string"
},
{
"name": "wallet",
"type": "address"
}
],
"Mail": [
{
"name": "from",
"type": "Person"
},
{
"name": "to",
"type": "Person"
},
{
"name": "contents",
"type": "string"
}
]
},
"primaryType": "Mail",
"domain": {
"name": "Ether Mail",
"version": "1",
"chainId": 1,
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
},
"message": {
"from": {
"name": "Cow",
"wallet": "selfAddress"
},
"to": {
"name": "Bob",
"wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
},
"contents": "Hello, Bob!"
}
}
]
}`

eth_sendTransaction 原生币转账

eth_sendTransaction 原生币转账,参数如下:

var eth_sendTransactionStrNative = `{
"jsonrpc": "2.0",
"id": 104,
"method": "eth_sendTransaction",
"params": [
{ "chainId": 56 },
{
"to": "0x6C663fF4B23bA3452E5aD1ad0C567E54b5CeeE2e",
"from": "selfAddress",
"gas": "0x76c0",
"value": "0x38D7EA4C68000",
"data": "0x",
"gasPrice": "0x4a817c800"
}
]
}`

eth_sendTransaction 合约币转账

eth_sendTransaction 合约币转账,参数如下:

// 处理接收到的消息更新
var eth_sendTransactionStrToken = `{
"jsonrpc": "2.0",
"id": 105,
"method": "eth_sendTransaction",
"params": [
{ "chainId": 56 },
{
"from": "selfAddress",
"to": "0x6386Adc4BC9c21984E34fD916BB349dD861742af",
"value": "0x0",
"data": "0xa9059cbb0000000000000000000000006c663ff4b23ba3452e5ad1ad0c567e54b5ceee2e0000000000000000000000000000000000000000000000000de0b6b3a7640000",
"gas": "0x76c0",
"gasPrice": "0x4a817c800"
}
]
}`

Swap 交易

Swap 交易,参数如下:

			var sendTransactionStrSwap = `{
"jsonrpc": "2.0",
"id": 106,
"method": "swap",
"params": [
{
"fromAddress": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"toAddress": "0x6386Adc4BC9c21984E34fD916BB349dD861742af",
"fromChainId": 56,
"toChainId": 56
}
]
}`

参考使用示例

我们提供了一个综合示例,演示如何使用sdk监听Bot消息、处理消息、构造区块链按钮、消息发送、处理交互结果等,供您参考:

package main

import (
"context"
"log"
"os"
"os/signal"
"strings"
"syscall"
"time"

boxbotapi "github.com/debox-pro/debox-chat-go-sdk/boxbotapi"
)

var (
// Button texts
homeInfoContent = "home content"

eth_getBalance = "eth_getBalance"
eth_gasPrice = "eth_gasPrice"
personal_sign = "personal_sign"
eth_signTypedData_v4 = "eth_signTypedData_v4"
eth_sendTransaction_native = "eth_sendTransaction_native"
eth_sendTransaction_token = "eth_sendTransaction_token"
eth_sendTransaction_swap = "swap"
boxTokenUrl = "https://deswap.pro/?from_chain_id=1&from_address=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&to_chain_id=1&to_address=0x32b77729cd87f1ef2bea4c650c16f89f08472c69&native=true"
privateChatUrl = "https://m.debox.pro/user/chat?id="
userHomePage = "https://m.debox.pro/card?id="

walletRequest = "debox://wallet/request"

bot *boxbotapi.BotAPI
// Keyboard layout for the second menu. Two buttons, one per row
homeMenuMarkup = boxbotapi.NewInlineKeyboardMarkup(
boxbotapi.NewInlineKeyboardRow(
boxbotapi.NewInlineKeyboardButtonDataWithColor("", eth_getBalance, walletRequest, eth_getBalance, "#21C161"),
),
boxbotapi.NewInlineKeyboardRow(
boxbotapi.NewInlineKeyboardButtonDataWithColor("", eth_gasPrice, walletRequest, eth_gasPrice, "#21C161"),
),
boxbotapi.NewInlineKeyboardRow(
boxbotapi.NewInlineKeyboardButtonDataWithColor("", personal_sign, walletRequest, personal_sign, "#21C161"),
),
boxbotapi.NewInlineKeyboardRow(
boxbotapi.NewInlineKeyboardButtonDataWithColor("", eth_signTypedData_v4, walletRequest, eth_signTypedData_v4, "#21C161"),
),
boxbotapi.NewInlineKeyboardRow(
boxbotapi.NewInlineKeyboardButtonDataWithColor("", eth_sendTransaction_native, walletRequest, eth_sendTransaction_native, "#21C161"),
),
boxbotapi.NewInlineKeyboardRow(
boxbotapi.NewInlineKeyboardButtonDataWithColor("", eth_sendTransaction_token, walletRequest, eth_sendTransaction_token, "#21C161"),
),
boxbotapi.NewInlineKeyboardRow(
boxbotapi.NewInlineKeyboardButtonDataWithColor("", eth_sendTransaction_swap, walletRequest, eth_sendTransaction_swap, "#21C161"),
),
)
)

func main() {
var err error
bot, err = boxbotapi.NewBotAPI("YOUR-API-KEY") //replace with your token
if err != nil {
// Abort if something is wrong
log.Panic(err)
}
// Set this to true to log all interactions with debox servers
bot.Debug = false

u := boxbotapi.NewUpdate(0)
u.Timeout = 60

// Create a new cancellable background context. Calling `cancel()` leads to the cancellation of the context
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
// `updates` is a golang channel which receives debox updates
updates := bot.GetUpdatesChan(u)
// Pass cancellable context to goroutine
go receiveUpdates(ctx, updates)
// Tell the user the bot is online
log.Println("Start listening for updates. Press enter to stop")
//new stop
// 创建一个信号通道,用于接收系统信号
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
// 等待信号
<-sigs
// 接收到信号后,取消上下文
cancel()
// 等待一段时间,让 goroutine 有时间优雅退出
select {
case <-ctx.Done():
case <-time.After(2 * time.Second):
}
log.Println("Bot stopped.")
}
func receiveUpdates(ctx context.Context, updates boxbotapi.UpdatesChannel) {
// `for {` means the loop is infinite until we manually stop it
for {
select {
// stop looping if ctx is cancelled
case <-ctx.Done():
return
// receive update from channel and then handle it
case update := <-updates:
handleUpdate(update)
}
}
}
func handleUpdate(update boxbotapi.Update) {
switch {
// Handle messages
case update.Message != nil:
handleMessage(update.Message)
break

// Handle button clicks
case update.CallbackQuery != nil:
handleButton(update.CallbackQuery)
break
}
}
func handleMessage(message *boxbotapi.Message) {
user := message.From
text := message.Text

if user == nil {
return
}
// Print to console
log.Printf("%s wrote %s", user.Name, text)
var err error
if len(text) > 0 {
msg := boxbotapi.NewMessage(message.Chat.ID, message.Chat.Type, message.Text)
msg.ParseMode = boxbotapi.ModeHTML
if text == "/start" {
msg.Text = homeInfoContent
msg.ReplyMarkup = homeMenuMarkup
var eth_getBalanceStr = `{
"jsonrpc": "2.0",
"id": 101,
"method": "eth_getBalance",
"params": [
{ "chainId": 56 },
"selfAddress",
"latest"
]
}`

//hexString := hex.EncodeToString(byteData)
var personal_signStr = `{
"jsonrpc": "2.0",
"id": 102,
"method": "personal_sign",
"params": [
{ "chainId": 56 },
"0x506c65617365207369676e2074686973206d65737361676520746f20636f6e6669726d20796f7572206964656e746974792e",
"selfAddress"
]
}`

//typedata_v4
// 使用 any 类型代替 interface{}
var eth_signTypedData_v4Str = `{
"jsonrpc": "2.0",
"id": 103,
"method": "eth_signTypedData_v4",
"params": [
"selfAddress",
{
"types": {
"EIP712Domain": [
{
"name": "name",
"type": "string"
},
{
"name": "version",
"type": "string"
},
{
"name": "chainId",
"type": "uint256"
},
{
"name": "verifyingContract",
"type": "address"
}
],
"Person": [
{
"name": "name",
"type": "string"
},
{
"name": "wallet",
"type": "address"
}
],
"Mail": [
{
"name": "from",
"type": "Person"
},
{
"name": "to",
"type": "Person"
},
{
"name": "contents",
"type": "string"
}
]
},
"primaryType": "Mail",
"domain": {
"name": "Ether Mail",
"version": "1",
"chainId": 1,
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
},
"message": {
"from": {
"name": "Cow",
"wallet": "selfAddress"
},
"to": {
"name": "Bob",
"wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
},
"contents": "Hello, Bob!"
}
}
]
}`
var eth_sendTransactionStrNative = `{
"jsonrpc": "2.0",
"id": 104,
"method": "eth_sendTransaction",
"params": [
{ "chainId": 56 },
{
"to": "0x6C663fF4B23bA3452E5aD1ad0C567E54b5CeeE2e",
"from": "selfAddress",
"gas": "0x76c0",
"value": "0x38D7EA4C68000",
"data": "0x",
"gasPrice": "0x4a817c800"
}
]
}`
var eth_sendTransactionStrToken = `{
"jsonrpc": "2.0",
"id": 105,
"method": "eth_sendTransaction",
"params": [
{ "chainId": 56 },
{
"from": "selfAddress",
"to": "0x6386Adc4BC9c21984E34fD916BB349dD861742af",
"value": "0x0",
"data": "0xa9059cbb0000000000000000000000006c663ff4b23ba3452e5ad1ad0c567e54b5ceee2e0000000000000000000000000000000000000000000000000de0b6b3a7640000",
"gas": "0x76c0",
"gasPrice": "0x4a817c800"
}
]
}`
var sendTransactionStrSwap = `{
"jsonrpc": "2.0",
"id": 106,
"method": "swap",
"params": [
{
"fromAddress": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"toAddress": "0x6386Adc4BC9c21984E34fD916BB349dD861742af",
"fromChainId": 56,
"toChainId": 56
}
]
}`

// balanceParamsStr, _ := json.Marshal(balanceParams)
eth_getBalanceStr = escapeAllStr(eth_getBalanceStr, "selfAddress", user.Address)
personal_signStr = escapeAllStr(personal_signStr, "selfAddress", user.Address)
eth_signTypedData_v4Str = escapeAllStr(eth_signTypedData_v4Str, "selfAddress", user.Address)
eth_sendTransactionStrNative = escapeAllStr(eth_sendTransactionStrNative, "selfAddress", user.Address)
eth_sendTransactionStrToken = escapeAllStr(eth_sendTransactionStrToken, "selfAddress", user.Address)
sendTransactionStrSwap = escapeAllStr(sendTransactionStrSwap, "selfAddress", user.Address)
homeMenuMarkup.InlineKeyboard[0][0].CallbackData = &eth_getBalanceStr
homeMenuMarkup.InlineKeyboard[2][0].CallbackData = &personal_signStr
homeMenuMarkup.InlineKeyboard[3][0].CallbackData = &eth_signTypedData_v4Str
homeMenuMarkup.InlineKeyboard[4][0].CallbackData = &eth_sendTransactionStrNative
homeMenuMarkup.InlineKeyboard[5][0].CallbackData = &eth_sendTransactionStrToken
homeMenuMarkup.InlineKeyboard[6][0].CallbackData = &sendTransactionStrSwap
}

_, err = bot.Send(msg)
}
if err != nil {
log.Printf("An error occured: %s", err.Error())
}
}
func escapeAllStr(text, old, new string) string {
text = strings.ReplaceAll(text, "\n", "")
text = strings.ReplaceAll(text, "\t", "")
text = strings.ReplaceAll(text, " ", "")
text = strings.ReplaceAll(text, old, new)
return text
}
func handleButton(query *boxbotapi.CallbackQuery) {
message := query.Message
var text = query.Data

markup := boxbotapi.NewInlineKeyboardMarkup()
markup = homeMenuMarkup

// Replace menu text and keyboard
msg := boxbotapi.NewEditMessageTextAndMarkup(message.Chat.ID, message.Chat.Type, message.MessageID, text, markup)
msg.ParseMode = boxbotapi.ModeHTML
bot.Send(msg)
}

常见问题

1. 点击按钮没有反应?

  • 请确保参数正确, 可能是参数错误导致按钮点击无效。