https://github.com/bluesky-social/goat but with tangled's CI
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

goat plc genesis

+76
+76
plc.go
··· 13 13 "github.com/bluesky-social/indigo/atproto/syntax" 14 14 "github.com/bluesky-social/indigo/util" 15 15 16 + "github.com/did-method-plc/go-didplc" 17 + 16 18 "github.com/urfave/cli/v2" 17 19 ) 18 20 ··· 70 72 }, 71 73 }, 72 74 Action: runPLCDump, 75 + }, 76 + &cli.Command{ 77 + Name: "genesis", 78 + Usage: "produce an unsigned genesis operation, as JSON", 79 + Flags: []cli.Flag{ 80 + &cli.StringFlag{ 81 + Name: "handle", 82 + Usage: "atproto handle", 83 + }, 84 + &cli.StringSliceFlag{ 85 + Name: "rotation-key", 86 + Usage: "rotation public key, in did:key format", 87 + }, 88 + &cli.StringFlag{ 89 + Name: "atproto-key", 90 + Usage: "atproto repo signing public key, in did:key format", 91 + }, 92 + &cli.StringFlag{ 93 + Name: "pds", 94 + Usage: "atproto PDS service URL", 95 + }, 96 + }, 97 + Action: runPLCGenesis, 73 98 }, 74 99 }, 75 100 } ··· 320 345 } 321 346 return &d, nil 322 347 } 348 + 349 + func runPLCGenesis(cctx *cli.Context) error { 350 + // TODO: helper function in didplc to make an empty op like this? 351 + services := make(map[string]didplc.OpService) 352 + verifMethods := make(map[string]string) 353 + op := didplc.RegularOp{ 354 + Type: "plc_operation", 355 + RotationKeys: []string{}, 356 + VerificationMethods: verifMethods, 357 + AlsoKnownAs: []string{}, 358 + Services: services, 359 + } 360 + 361 + for _, rotationKey := range cctx.StringSlice("rotation-key") { 362 + if !strings.HasPrefix(rotationKey, "did:key:") { 363 + return fmt.Errorf("rotation keys must be in did:key format") 364 + } 365 + op.RotationKeys = append(op.RotationKeys, rotationKey) 366 + } 367 + 368 + handle := cctx.String("handle") 369 + if handle != "" { 370 + // add at:// prefix if not already present 371 + op.AlsoKnownAs = append(op.AlsoKnownAs, "at://"+strings.TrimPrefix(handle, "at://")) 372 + } 373 + 374 + atprotoKey := cctx.String("atproto-key") 375 + if atprotoKey != "" { 376 + if !strings.HasPrefix(atprotoKey, "did:key:") { 377 + return fmt.Errorf("atproto key must be in did:key format") 378 + } 379 + op.VerificationMethods["atproto"] = atprotoKey 380 + } 381 + 382 + pds := cctx.String("pds") 383 + if pds != "" { 384 + // TODO: check pds is valid URI? 385 + op.Services["atproto_pds"] = didplc.OpService{ 386 + Type: "AtprotoPersonalDataServer", 387 + Endpoint: pds, 388 + } 389 + } 390 + 391 + res, err := json.MarshalIndent(op, "", " ") 392 + if err != nil { 393 + return err 394 + } 395 + fmt.Println(string(res)) 396 + 397 + return nil 398 + }