steemgosdk : Opérations de diffusion
L'instance Broadcast du SDK Go pour Steem gère automatiquement la préparation de la transaction (ref_block_num, ref_block_prefix, expiration) et la signature — vous fournissez seulement les opérations (operation) et les clés privées (private key). Cette page reprend tous les exemples de diffusion de la documentation du SDK ; la configuration du client et la génération de clés se trouvent dans le Démarrage rapide.
⚠️ Avertissement de sécurité : les clés privées utilisées dans les exemples ci-dessous (
5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg) sont des clés de test/d'exemple uniquement. Elles sont publiquement connues et ne doivent JAMAIS être utilisées en production. Générez toujours vos propres clés privées à partir de votre nom de compte et de votre mot de passe avec les méthodesauth.ToWif()ouauth.GetPrivateKeys().
Les détails « on the wire » de chaque opération sont documentés dans la référence des opérations de diffusion générée.
Exemples de diffusion
Exemples de diffusion
Voter pour un post
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))
}Transférer des STEEM ou des dollars 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))
}Transférer avec un mémo chiffré
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))
}Créer un commentaire
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))
}Post avec options de commentaire (bénéficiaires)
Utilisez CommentOptionsOperation pour définir les bénéficiaires qui recevront une partie des récompenses du post :
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))
}Post avec options de commentaire (sans bénéficiaires)
Vous pouvez aussi utiliser CommentOptionsOperation sans définir de bénéficiaires :
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))
}Plusieurs opérations dans une seule transaction
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))
}Exemples complets
Exemples complets
Exemple complet de transfert
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))
}Exemple complet de vote et de commentaire
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))
}Exemples CustomJson
Exemples CustomJson
Opération CustomJson de base
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))
}Opération de notification (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 avec autorité active (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))
}Utiliser directement 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))
}Prix de flux d'un witness (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))
}Remarques
Remarques
- Sécurité : n'intégrez jamais en dur des clés privées ou des mots de passe dans du code de production. Utilisez des variables d'environnement ou des systèmes de gestion de clés sécurisés.
- Clés privées de test : la clé privée
5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLgutilisée dans les exemples est une clé de test/d'exemple uniquement. Elle est publiquement connue et ne doit JAMAIS être utilisée en production. Utilisez toujours vos propres clés privées générées à partir de votre nom de compte et de votre mot de passe. - Gestion des erreurs : vérifiez toujours les erreurs renvoyées par les méthodes du SDK.
- Autorité CustomJson :
- si
requiredAuthsn'est pas vide, vous devez fournir une clé privée active - si seul
requiredPostingAuthsest défini, vous devez fournir une clé privée de publication - la méthode
CustomJson()détermine automatiquement le type de clé à utiliser selon les autorités fournies
- si
- Réseau : les exemples utilisent
https://api.steemit.comcomme nœud par défaut. Vous pouvez utiliser n'importe quelle URL de nœud Steem. - Format WIF : les clés privées doivent être au format Wallet Import Format (WIF) et commencer par '5'.
- Clés publiques : les clés publiques doivent être au format Steem et commencer par 'STM'.
- Chiffrement des mémos : les mémos commençant par '#' sont chiffrés automatiquement. Les mémos en texte brut sont envoyés tels quels.
- Méthodes d'API : le SDK fournit des méthodes pratiques comme
GetBlock(),GetBlocks(),GetDynamicGlobalProperties()etGetTransactionHex()sur l'instanceAPI. Utilisez-les de préférence auCall()générique, pour une meilleure sûreté de typage et un code plus simple. - Diffusion : l'instance
Broadcastgère automatiquement la préparation de la transaction (ref_block_num, ref_block_prefix, expiration) et la signature. Vous n'avez qu'à fournir les opérations et les clés privées. L'instance Broadcast crée en interne une instance d'API pour récupérer les propriétés globales dynamiques.
Pour aller plus loin
- Démarrage rapide - configuration du client, authentification/clés et exemples Steem URI.
- SignedCall API - lectures authentifiées depuis Go.