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