steemgosdk: Операции широковещания
Экземпляр Broadcast Steem Go SDK автоматически выполняет подготовку транзакции (ref_block_num, ref_block_prefix, expiration) и подписание — вы предоставляете только операции (operation) и приватные ключи (private key). На этой странице собраны все примеры широковещания из документации SDK; настройка клиента и генерация ключей описаны в Быстром старте.
⚠️ Предупреждение о безопасности: приватные ключи, используемые в примерах ниже (
5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg), — только тестовые/примерные ключи. Они общеизвестны, и их НИКОГДА не следует использовать в продакшене. Всегда генерируйте собственные приватные ключи из имени аккаунта и пароля с помощью методовauth.ToWif()илиauth.GetPrivateKeys().
Детали каждой операции «на проводе» документированы в сгенерированном справочнике операций широковещания.
Примеры широковещания
Примеры широковещания
Голосование за пост
package main
import (
"fmt"
"time"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemutil/protocol"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
// Create a vote operation
voteOp := &protocol.VoteOperation{
Voter: "your-account-name",
Author: "steemit",
Permlink: "firstpost",
Weight: 10000, // 100% vote weight (10000 = 100%)
}
// Your posting private key in WIF format
// WARNING: This is a test/example key. NEVER use it in production!
// Generate your own key using: auth.ToWif(accountName, password, "posting")
postingWif := "5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg"
// Broadcast the vote
result, err := broadcast.SendWith(voteOp, postingWif)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Transaction broadcasted: %s\n", string(result))
}Перевод STEEM или долларов STEEM (SBD)
package main
import (
"fmt"
"time"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemutil/protocol"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
// Create a transfer operation
transferOp := &protocol.TransferOperation{
From: "your-account-name",
To: "recipient-account",
Amount: "1.000 STEEM",
Memo: "Hello from Steem Go SDK!",
}
// Your active private key in WIF format
// WARNING: This is a test/example key. NEVER use it in production!
activeWif := "5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg"
// Broadcast the transfer
result, err := broadcast.SendWith(transferOp, activeWif)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Transfer broadcasted: %s\n", string(result))
}Перевод с зашифрованным memo
package main
import (
"fmt"
"time"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemutil/protocol"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
auth := client.GetAuth()
// Recipient's memo public key
recipientMemoKey := "STM8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA"
// Your memo private key
// WARNING: This is a test/example key. NEVER use it in production!
yourMemoWif := "5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg"
// Encrypt the memo (memos starting with '#' are encrypted)
encryptedMemo, err := auth.EncodeMemo(yourMemoWif, recipientMemoKey, "#Secret message")
if err != nil {
fmt.Printf("Error encrypting memo: %v\n", err)
return
}
// Create transfer with encrypted memo
transferOp := &protocol.TransferOperation{
From: "your-account-name",
To: "recipient-account",
Amount: "1.000 STEEM",
Memo: encryptedMemo,
}
// Your active private key
// WARNING: This is a test/example key. NEVER use it in production!
activeWif := "5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg"
// Broadcast the transfer
result, err := broadcast.SendWith(transferOp, activeWif)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Transfer with encrypted memo broadcasted: %s\n", string(result))
}Создание комментария
package main
import (
"fmt"
"time"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemutil/protocol"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
// Create a comment operation
commentOp := &protocol.CommentOperation{
ParentAuthor: "steemit",
ParentPermlink: "firstpost",
Author: "your-account-name",
Permlink: "my-comment-permlink",
Title: "My Comment Title",
Body: "This is the body of my comment.",
JsonMetadata: `{"tags":["steem"],"app":"steemgosdk/1.0"}`,
}
// Your posting private key
// WARNING: This is a test/example key. NEVER use it in production!
postingWif := "5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg"
// Broadcast the comment
result, err := broadcast.SendWith(commentOp, postingWif)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Comment broadcasted: %s\n", string(result))
}Пост с опциями комментария (бенефициары)
Используйте CommentOptionsOperation, чтобы задать бенефициаров, которые получат часть наград за пост:
package main
import (
"encoding/json"
"fmt"
"time"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemutil/protocol"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
author := "your-account-name"
permlink := "my-post-with-beneficiaries"
tags := []string{"test", "steem"}
jsonMeta, _ := json.Marshal(map[string]interface{}{
"tags": tags,
"app": "steemgosdk/1.0",
})
// Create comment operation
commentOp := &protocol.CommentOperation{
ParentAuthor: "",
ParentPermlink: tags[0],
Author: author,
Permlink: permlink,
Title: "Post with Beneficiaries",
Body: "This post has beneficiaries set.",
JsonMetadata: string(jsonMeta),
}
// Define beneficiaries (weight is in basis points: 3000 = 30%)
// Note: steemutil v0.0.19+ automatically sorts beneficiaries alphabetically
beneficiaries := []protocol.Beneficiary{
{Account: "alice", Weight: 2000}, // 20%
{Account: "bob", Weight: 1000}, // 10%
}
// Create comment options with beneficiaries extension
optionsOp := &protocol.CommentOptionsOperation{
Author: author,
Permlink: permlink,
MaxAcceptedPayout: "1000000.000 SBD",
PercentSteemDollars: 10000,
AllowVotes: true,
AllowCurationRewards: true,
Extensions: protocol.CommentOptionsExtensions{
protocol.NewBeneficiariesExtension(beneficiaries),
},
}
// Broadcast both operations in one transaction
// WARNING: This is a test/example key. NEVER use it in production!
postingWif := "5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg"
result, err := broadcast.Send([]protocol.Operation{commentOp, optionsOp}, map[string]string{
"posting": postingWif,
})
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Post with beneficiaries broadcasted: %s\n", string(result))
}Пост с опциями комментария (без бенефициаров)
Можно также использовать CommentOptionsOperation без задания бенефициаров:
package main
import (
"encoding/json"
"fmt"
"time"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemutil/protocol"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
author := "your-account-name"
permlink := "my-post-with-options"
tags := []string{"test", "steem"}
jsonMeta, _ := json.Marshal(map[string]interface{}{
"tags": tags,
"app": "steemgosdk/1.0",
})
commentOp := &protocol.CommentOperation{
ParentAuthor: "",
ParentPermlink: tags[0],
Author: author,
Permlink: permlink,
Title: "Post with Options",
Body: "This post has comment options but no beneficiaries.",
JsonMetadata: string(jsonMeta),
}
// Comment options with empty extensions (no beneficiaries)
optionsOp := &protocol.CommentOptionsOperation{
Author: author,
Permlink: permlink,
MaxAcceptedPayout: "1000000.000 SBD",
PercentSteemDollars: 10000,
AllowVotes: true,
AllowCurationRewards: true,
Extensions: protocol.CommentOptionsExtensions{}, // Empty extensions
}
// WARNING: This is a test/example key. NEVER use it in production!
postingWif := "5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg"
result, err := broadcast.Send([]protocol.Operation{commentOp, optionsOp}, map[string]string{
"posting": postingWif,
})
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Post with options broadcasted: %s\n", string(result))
}Несколько операций в одной транзакции
package main
import (
"fmt"
"time"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemutil/protocol"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
// Create multiple operations
voteOp := &protocol.VoteOperation{
Voter: "your-account-name",
Author: "steemit",
Permlink: "firstpost",
Weight: 10000,
}
commentOp := &protocol.CommentOperation{
ParentAuthor: "steemit",
ParentPermlink: "firstpost",
Author: "your-account-name",
Permlink: "my-comment-permlink",
Title: "My Comment",
Body: "Great post!",
JsonMetadata: "{}",
}
// Prepare private keys (posting key for both operations)
// WARNING: This is a test/example key. NEVER use it in production!
privKeys := map[string]string{
"posting": "5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg",
}
// Broadcast multiple operations in one transaction
result, err := broadcast.Send([]protocol.Operation{voteOp, commentOp}, privKeys)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Transaction with multiple operations broadcasted: %s\n", string(result))
}Полные примеры
Полные примеры
Полный пример перевода
package main
import (
"fmt"
"time"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemutil/protocol"
)
func main() {
// Initialize client
url := "https://api.steemit.com"
client := steemgosdk.GetClient(url)
// Get instances
api := client.GetAPI()
broadcast := client.GetBroadcast()
auth := client.GetAuth()
// 1. Check account balance (optional)
result, err := api.Call("condenser_api", "get_accounts", []interface{}{
[]interface{}{"your-account-name"},
})
if err != nil {
fmt.Printf("Error getting account: %v\n", err)
return
}
fmt.Println("Account retrieved successfully")
fmt.Printf("Account data: %v\n", result.Result)
// 2. Prepare transfer operation
transferOp := &protocol.TransferOperation{
From: "your-account-name",
To: "recipient-account",
Amount: "1.000 STEEM",
Memo: "Transfer from Steem Go SDK",
}
// 3. Get private key (in production, store securely)
// WARNING: This is a test/example key. NEVER use it in production!
activeWif := "5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg"
// Or generate from account name and password
// keys, _ := auth.GetPrivateKeys("your-account-name", "your-password", []string{"active"})
// activeWif := keys["active"]
// 4. Broadcast transaction
result, err := broadcast.SendWith(transferOp, activeWif)
if err != nil {
fmt.Printf("Error broadcasting: %v\n", err)
return
}
fmt.Printf("Transfer successful! Result: %s\n", string(result))
}Полный пример голосования и комментария
package main
import (
"fmt"
"time"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemutil/protocol"
)
func main() {
// Initialize
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
auth := client.GetAuth()
// Get posting key
accountName := "your-account-name"
password := "your-password"
keys, err := auth.GetPrivateKeys(accountName, password, []string{"posting"})
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
postingWif := keys["posting"]
// 1. Vote on a post
voteOp := &protocol.VoteOperation{
Voter: accountName,
Author: "steemit",
Permlink: "firstpost",
Weight: 10000, // 100%
}
result, err := broadcast.SendWith(voteOp, postingWif)
if err != nil {
fmt.Printf("Error voting: %v\n", err)
return
}
fmt.Printf("Vote broadcasted: %s\n", string(result))
// 2. Comment on the same post
commentOp := &protocol.CommentOperation{
ParentAuthor: "steemit",
ParentPermlink: "firstpost",
Author: accountName,
Permlink: "my-comment-" + fmt.Sprintf("%d", time.Now().Unix()),
Title: "",
Body: "Great post! Thanks for sharing.",
JsonMetadata: `{"tags":["steem"],"app":"steemgosdk/1.0"}`,
}
result, err = broadcast.SendWith(commentOp, postingWif)
if err != nil {
fmt.Printf("Error commenting: %v\n", err)
return
}
fmt.Printf("Comment broadcasted: %s\n", string(result))
}Примеры CustomJson
Примеры CustomJson
Базовая операция CustomJson
package main
import (
"encoding/json"
"fmt"
"github.com/steemit/steemgosdk"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
// Create a follow operation using custom_json
followData := []interface{}{
"follow",
map[string]interface{}{
"follower": "your-account-name",
"following": "steemit",
"what": []string{"blog"},
},
}
jsonStr, _ := json.Marshal(followData)
// Broadcast custom_json operation
// Parameters: requiredAuths, requiredPostingAuths, id, json, privKeyWif
result, err := broadcast.CustomJson(
[]string{}, // required_auths (empty for posting auth)
[]string{"your-account-name"}, // required_posting_auths
"follow", // id
string(jsonStr), // json
"your-posting-private-key", // posting WIF
)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("CustomJson operation broadcasted: %s\n", string(result))
}Операция уведомления (setLastRead)
package main
import (
"encoding/json"
"fmt"
"time"
"github.com/steemit/steemgosdk"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
// Create a notify operation to set last read date
notifyData := []interface{}{
"setLastRead",
map[string]interface{}{
"date": time.Now().UTC().Format(time.RFC3339),
},
}
jsonStr, _ := json.Marshal(notifyData)
// Broadcast custom_json operation
result, err := broadcast.CustomJson(
[]string{}, // required_auths (empty)
[]string{"your-account-name"}, // required_posting_auths
"notify", // id
string(jsonStr), // json
"your-posting-private-key", // posting WIF
)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Notify operation broadcasted: %s\n", string(result))
}CustomJson с активным полномочием (active authority)
package main
import (
"encoding/json"
"fmt"
"github.com/steemit/steemgosdk"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
// Create custom operation data
customData := map[string]interface{}{
"action": "custom_action",
"data": "some custom data",
}
jsonStr, _ := json.Marshal(customData)
// Broadcast custom_json operation with active authority
// When requiredAuths is not empty, active key is required
result, err := broadcast.CustomJson(
[]string{"your-account-name"}, // required_auths (requires active key)
[]string{}, // required_posting_auths (empty)
"custom_id", // id
string(jsonStr), // json
"your-active-private-key", // active WIF
)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("CustomJson with active auth broadcasted: %s\n", string(result))
}Использование CustomJSONOperation напрямую
package main
import (
"encoding/json"
"fmt"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemutil/protocol"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
broadcast := client.GetBroadcast()
// Create CustomJSONOperation directly
followData := []interface{}{
"follow",
map[string]interface{}{
"follower": "your-account-name",
"following": "steemit",
"what": []string{"blog"},
},
}
jsonStr, _ := json.Marshal(followData)
op := &protocol.CustomJSONOperation{
RequiredAuths: []string{},
RequiredPostingAuths: []string{"your-account-name"},
ID: "follow",
JSON: string(jsonStr),
}
// Use SendWith to broadcast
privKeys := map[string]string{
"posting": "your-posting-private-key",
}
result, err := broadcast.Send([]protocol.Operation{op}, privKeys)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("CustomJSONOperation broadcasted: %s\n", string(result))
}Цена фида свидетеля (feed_publish)
package main
import (
"fmt"
"log"
"github.com/steemit/steemgosdk"
"github.com/steemit/steemgosdk/broadcast"
)
func main() {
client := steemgosdk.GetClient("https://api.steemit.com")
bc := client.GetBroadcast()
rate := broadcast.ExchangeRate{
Base: "0.500 SBD",
Quote: "1.000 STEEM",
}
// Use the witness account active key (WIF). Block signing keys cannot sign feed_publish.
result, err := bc.FeedPublish("your-witness-account", rate, "your-active-private-key")
if err != nil {
log.Fatal(err)
}
fmt.Printf("feed_publish result: %s\n", string(result))
}Примечания
Примечания
- Безопасность: никогда не встраивайте приватные ключи или пароли в продакшен-код. Используйте переменные окружения или системы безопасного управления ключами.
- Тестовые приватные ключи: приватный ключ
5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg, используемый в примерах, — только тестовый/примерный ключ. Он общеизвестен, и его НИКОГДА не следует использовать в продакшене. Всегда используйте собственные приватные ключи, сгенерированные из имени аккаунта и пароля. - Обработка ошибок: всегда проверяйте ошибки, возвращаемые методами SDK.
- Полномочия CustomJson:
- если
requiredAuthsне пуст, нужно предоставить активный (active) приватный ключ - если задан только
requiredPostingAuths, нужно предоставить постинг (posting) приватный ключ - метод
CustomJson()автоматически определяет, какой тип ключа использовать, по предоставленным полномочиям
- если
- Сеть: в примерах
https://api.steemit.comиспользуется как узел по умолчанию. Можно использовать любой URL узла Steem. - Формат WIF: приватные ключи должны быть в формате Wallet Import Format (WIF) и начинаться с '5'.
- Публичные ключи: публичные ключи должны быть в формате Steem и начинаться с 'STM'.
- Шифрование memo: memo, начинающиеся с '#', шифруются автоматически. Обычные текстовые memo отправляются как есть.
- Методы API: SDK предоставляет удобные методы, такие как
GetBlock(),GetBlocks(),GetDynamicGlobalProperties()иGetTransactionHex(), в экземпляреAPI. По возможности используйте их вместо универсальногоCall()— это даёт лучшую типобезопасность и более простой код. - Широковещание: экземпляр
Broadcastавтоматически выполняет подготовку транзакции (ref_block_num, ref_block_prefix, expiration) и подписание. Нужно предоставить только операции и приватные ключи. Внутри экземпляр Broadcast создаёт экземпляр API для получения динамических глобальных свойств (dynamic global properties).
Что дальше
- Быстрый старт - настройка клиента, аутентификация/ключи и примеры Steem URI.
- SignedCall API - аутентифицированное чтение из Go.