github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/cmd/swarm/feeds.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:33</date>
    10  //</624450070770618368>
    11  
    12  
    13  //命令feed允许用户创建和更新签名的swarm feed
    14  package main
    15  
    16  import (
    17  	"fmt"
    18  	"strings"
    19  
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/common/hexutil"
    22  	"github.com/ethereum/go-ethereum/crypto"
    23  
    24  	"github.com/ethereum/go-ethereum/cmd/utils"
    25  	swarm "github.com/ethereum/go-ethereum/swarm/api/client"
    26  	"github.com/ethereum/go-ethereum/swarm/storage/feed"
    27  	"gopkg.in/urfave/cli.v1"
    28  )
    29  
    30  var feedCommand = cli.Command{
    31  	CustomHelpTemplate: helpTemplate,
    32  	Name:               "feed",
    33  	Usage:              "(Advanced) Create and update Swarm Feeds",
    34  	ArgsUsage:          "<create|update|info>",
    35  	Description:        "Works with Swarm Feeds",
    36  	Subcommands: []cli.Command{
    37  		{
    38  			Action:             feedCreateManifest,
    39  			CustomHelpTemplate: helpTemplate,
    40  			Name:               "create",
    41  			Usage:              "creates and publishes a new feed manifest",
    42  			Description: `creates and publishes a new feed manifest pointing to a specified user's updates about a particular topic.
    43  					The feed topic can be built in the following ways:
    44  					* use --topic to set the topic to an arbitrary binary hex string.
    45  					* use --name to set the topic to a human-readable name.
    46  					    For example --name could be set to "profile-picture", meaning this feed allows to get this user's current profile picture.
    47  					* use both --topic and --name to create named subtopics. 
    48  						For example, --topic could be set to an Ethereum contract address and --name could be set to "comments", meaning
    49  						this feed tracks a discussion about that contract.
    50  					The --user flag allows to have this manifest refer to a user other than yourself. If not specified,
    51  					it will then default to your local account (--bzzaccount)`,
    52  			Flags: []cli.Flag{SwarmFeedNameFlag, SwarmFeedTopicFlag, SwarmFeedUserFlag},
    53  		},
    54  		{
    55  			Action:             feedUpdate,
    56  			CustomHelpTemplate: helpTemplate,
    57  			Name:               "update",
    58  			Usage:              "updates the content of an existing Swarm Feed",
    59  			ArgsUsage:          "<0x Hex data>",
    60  			Description: `publishes a new update on the specified topic
    61  					The feed topic can be built in the following ways:
    62  					* use --topic to set the topic to an arbitrary binary hex string.
    63  					* use --name to set the topic to a human-readable name.
    64  					    For example --name could be set to "profile-picture", meaning this feed allows to get this user's current profile picture.
    65  					* use both --topic and --name to create named subtopics. 
    66  						For example, --topic could be set to an Ethereum contract address and --name could be set to "comments", meaning
    67  						this feed tracks a discussion about that contract.
    68  					
    69  					If you have a manifest, you can specify it with --manifest to refer to the feed,
    70  					instead of using --topic / --name
    71  					`,
    72  			Flags: []cli.Flag{SwarmFeedManifestFlag, SwarmFeedNameFlag, SwarmFeedTopicFlag},
    73  		},
    74  		{
    75  			Action:             feedInfo,
    76  			CustomHelpTemplate: helpTemplate,
    77  			Name:               "info",
    78  			Usage:              "obtains information about an existing Swarm feed",
    79  			Description: `obtains information about an existing Swarm feed
    80  					The topic can be specified directly with the --topic flag as an hex string
    81  					If no topic is specified, the default topic (zero) will be used
    82  					The --name flag can be used to specify subtopics with a specific name.
    83  					The --user flag allows to refer to a user other than yourself. If not specified,
    84  					it will then default to your local account (--bzzaccount)
    85  					If you have a manifest, you can specify it with --manifest instead of --topic / --name / ---user
    86  					to refer to the feed`,
    87  			Flags: []cli.Flag{SwarmFeedManifestFlag, SwarmFeedNameFlag, SwarmFeedTopicFlag, SwarmFeedUserFlag},
    88  		},
    89  	},
    90  }
    91  
    92  func NewGenericSigner(ctx *cli.Context) feed.Signer {
    93  	return feed.NewGenericSigner(getPrivKey(ctx))
    94  }
    95  
    96  func getTopic(ctx *cli.Context) (topic feed.Topic) {
    97  	var name = ctx.String(SwarmFeedNameFlag.Name)
    98  	var relatedTopic = ctx.String(SwarmFeedTopicFlag.Name)
    99  	var relatedTopicBytes []byte
   100  	var err error
   101  
   102  	if relatedTopic != "" {
   103  		relatedTopicBytes, err = hexutil.Decode(relatedTopic)
   104  		if err != nil {
   105  			utils.Fatalf("Error parsing topic: %s", err)
   106  		}
   107  	}
   108  
   109  	topic, err = feed.NewTopic(name, relatedTopicBytes)
   110  	if err != nil {
   111  		utils.Fatalf("Error parsing topic: %s", err)
   112  	}
   113  	return topic
   114  }
   115  
   116  //
   117  //swarm feed update<manifest address or ens domain><0x hexdata>[--multihash=false]
   118  //
   119  
   120  func feedCreateManifest(ctx *cli.Context) {
   121  	var (
   122  		bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
   123  		client = swarm.NewClient(bzzapi)
   124  	)
   125  
   126  	newFeedUpdateRequest := feed.NewFirstRequest(getTopic(ctx))
   127  	newFeedUpdateRequest.Feed.User = feedGetUser(ctx)
   128  
   129  	manifestAddress, err := client.CreateFeedWithManifest(newFeedUpdateRequest)
   130  	if err != nil {
   131  		utils.Fatalf("Error creating feed manifest: %s", err.Error())
   132  		return
   133  	}
   134  fmt.Println(manifestAddress) //
   135  
   136  }
   137  
   138  func feedUpdate(ctx *cli.Context) {
   139  	args := ctx.Args()
   140  
   141  	var (
   142  		bzzapi                  = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
   143  		client                  = swarm.NewClient(bzzapi)
   144  		manifestAddressOrDomain = ctx.String(SwarmFeedManifestFlag.Name)
   145  	)
   146  
   147  	if len(args) < 1 {
   148  		fmt.Println("Incorrect number of arguments")
   149  		cli.ShowCommandHelpAndExit(ctx, "update", 1)
   150  		return
   151  	}
   152  
   153  	signer := NewGenericSigner(ctx)
   154  
   155  	data, err := hexutil.Decode(args[0])
   156  	if err != nil {
   157  		utils.Fatalf("Error parsing data: %s", err.Error())
   158  		return
   159  	}
   160  
   161  	var updateRequest *feed.Request
   162  	var query *feed.Query
   163  
   164  	if manifestAddressOrDomain == "" {
   165  		query = new(feed.Query)
   166  		query.User = signer.Address()
   167  		query.Topic = getTopic(ctx)
   168  	}
   169  
   170  //
   171  	updateRequest, err = client.GetFeedRequest(query, manifestAddressOrDomain)
   172  	if err != nil {
   173  		utils.Fatalf("Error retrieving feed status: %s", err.Error())
   174  	}
   175  
   176  //
   177  	if updateRequest.User != signer.Address() {
   178  		utils.Fatalf("Signer address does not match the update request")
   179  	}
   180  
   181  //设置新数据
   182  	updateRequest.SetData(data)
   183  
   184  //
   185  	if err = updateRequest.Sign(signer); err != nil {
   186  		utils.Fatalf("Error signing feed update: %s", err.Error())
   187  	}
   188  
   189  //更新后
   190  	err = client.UpdateFeed(updateRequest)
   191  	if err != nil {
   192  		utils.Fatalf("Error updating feed: %s", err.Error())
   193  		return
   194  	}
   195  }
   196  
   197  func feedInfo(ctx *cli.Context) {
   198  	var (
   199  		bzzapi                  = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
   200  		client                  = swarm.NewClient(bzzapi)
   201  		manifestAddressOrDomain = ctx.String(SwarmFeedManifestFlag.Name)
   202  	)
   203  
   204  	var query *feed.Query
   205  	if manifestAddressOrDomain == "" {
   206  		query = new(feed.Query)
   207  		query.Topic = getTopic(ctx)
   208  		query.User = feedGetUser(ctx)
   209  	}
   210  
   211  	metadata, err := client.GetFeedRequest(query, manifestAddressOrDomain)
   212  	if err != nil {
   213  		utils.Fatalf("Error retrieving feed metadata: %s", err.Error())
   214  		return
   215  	}
   216  	encodedMetadata, err := metadata.MarshalJSON()
   217  	if err != nil {
   218  		utils.Fatalf("Error encoding metadata to JSON for display:%s", err)
   219  	}
   220  	fmt.Println(string(encodedMetadata))
   221  }
   222  
   223  func feedGetUser(ctx *cli.Context) common.Address {
   224  	var user = ctx.String(SwarmFeedUserFlag.Name)
   225  	if user != "" {
   226  		return common.HexToAddress(user)
   227  	}
   228  	pk := getPrivKey(ctx)
   229  	if pk == nil {
   230  		utils.Fatalf("Cannot read private key. Must specify --user or --bzzaccount")
   231  	}
   232  	return crypto.PubkeyToAddress(pk.PublicKey)
   233  
   234  }
   235