package main import ( "fmt" "os" "time" "git.mleku.dev/mleku/nostr/crypto/keys" "git.mleku.dev/mleku/nostr/encoders/hex" "next.orly.dev/pkg/find" "git.mleku.dev/mleku/nostr/interfaces/signer" "git.mleku.dev/mleku/nostr/interfaces/signer/p8k" ) func main() { if len(os.Args) < 2 { printUsage() os.Exit(1) } command := os.Args[1] switch command { case "register": handleRegister() case "transfer": handleTransfer() case "verify-name": handleVerifyName() case "generate-key": handleGenerateKey() case "issue-cert": handleIssueCert() case "help": printUsage() default: fmt.Printf("Unknown command: %s\n\n", command) printUsage() os.Exit(1) } } func printUsage() { fmt.Println("FIND - Free Internet Name Daemon") fmt.Println("Usage: find [options]") fmt.Println() fmt.Println("Commands:") fmt.Println(" register Create a registration proposal for a name") fmt.Println(" transfer Transfer a name to a new owner") fmt.Println(" verify-name Validate a name format") fmt.Println(" generate-key Generate a new key pair") fmt.Println(" issue-cert Issue a certificate for a name") fmt.Println(" help Show this help message") fmt.Println() fmt.Println("Examples:") fmt.Println(" find verify-name example.com") fmt.Println(" find register myname.nostr") fmt.Println(" find generate-key") } func handleRegister() { if len(os.Args) < 3 { fmt.Println("Usage: find register ") os.Exit(1) } name := os.Args[2] // Validate the name if err := find.ValidateName(name); err != nil { fmt.Printf("Invalid name: %v\n", err) os.Exit(1) } // Generate a key pair for this example // In production, this would load from a secure keystore signer, err := p8k.New() if err != nil { fmt.Printf("Failed to create signer: %v\n", err) os.Exit(1) } if err := signer.Generate(); err != nil { fmt.Printf("Failed to generate key: %v\n", err) os.Exit(1) } // Create registration proposal proposal, err := find.NewRegistrationProposal(name, find.ActionRegister, signer) if err != nil { fmt.Printf("Failed to create proposal: %v\n", err) os.Exit(1) } fmt.Printf("Registration Proposal Created\n") fmt.Printf("==============================\n") fmt.Printf("Name: %s\n", name) fmt.Printf("Pubkey: %s\n", hex.Enc(signer.Pub())) fmt.Printf("Event ID: %s\n", hex.Enc(proposal.GetIDBytes())) fmt.Printf("Kind: %d\n", proposal.Kind) fmt.Printf("Created At: %s\n", time.Unix(proposal.CreatedAt, 0)) fmt.Printf("\nEvent JSON:\n") json := proposal.Marshal(nil) fmt.Println(string(json)) } func handleTransfer() { if len(os.Args) < 4 { fmt.Println("Usage: find transfer ") os.Exit(1) } name := os.Args[2] newOwnerPubkey := os.Args[3] // Validate the name if err := find.ValidateName(name); err != nil { fmt.Printf("Invalid name: %v\n", err) os.Exit(1) } // Generate current owner key (in production, load from keystore) currentOwner, err := p8k.New() if err != nil { fmt.Printf("Failed to create current owner signer: %v\n", err) os.Exit(1) } if err := currentOwner.Generate(); err != nil { fmt.Printf("Failed to generate current owner key: %v\n", err) os.Exit(1) } // Authorize the transfer prevSig, timestamp, err := find.AuthorizeTransfer(name, newOwnerPubkey, currentOwner) if err != nil { fmt.Printf("Failed to authorize transfer: %v\n", err) os.Exit(1) } fmt.Printf("Transfer Authorization Created\n") fmt.Printf("===============================\n") fmt.Printf("Name: %s\n", name) fmt.Printf("Current Owner: %s\n", hex.Enc(currentOwner.Pub())) fmt.Printf("New Owner: %s\n", newOwnerPubkey) fmt.Printf("Timestamp: %s\n", timestamp) fmt.Printf("Signature: %s\n", prevSig) fmt.Printf("\nTo complete the transfer, the new owner must create a proposal with:") fmt.Printf(" prev_owner: %s\n", hex.Enc(currentOwner.Pub())) fmt.Printf(" prev_sig: %s\n", prevSig) } func handleVerifyName() { if len(os.Args) < 3 { fmt.Println("Usage: find verify-name ") os.Exit(1) } name := os.Args[2] // Validate the name if err := find.ValidateName(name); err != nil { fmt.Printf("❌ Invalid name: %v\n", err) os.Exit(1) } normalized := find.NormalizeName(name) isTLD := find.IsTLD(normalized) parent := find.GetParentDomain(normalized) fmt.Printf("✓ Valid name\n") fmt.Printf("==============\n") fmt.Printf("Original: %s\n", name) fmt.Printf("Normalized: %s\n", normalized) fmt.Printf("Is TLD: %v\n", isTLD) if parent != "" { fmt.Printf("Parent: %s\n", parent) } } func handleGenerateKey() { // Generate a new key pair secKey, err := keys.GenerateSecretKey() if err != nil { fmt.Printf("Failed to generate secret key: %v\n", err) os.Exit(1) } secKeyHex := hex.Enc(secKey) pubKeyHex, err := keys.GetPublicKeyHex(secKeyHex) if err != nil { fmt.Printf("Failed to derive public key: %v\n", err) os.Exit(1) } fmt.Println("New Key Pair Generated") fmt.Println("======================") fmt.Printf("Secret Key (keep safe!): %s\n", secKeyHex) fmt.Printf("Public Key: %s\n", pubKeyHex) fmt.Println() fmt.Println("⚠️ IMPORTANT: Store the secret key securely. Anyone with access to it can control your names.") } func handleIssueCert() { if len(os.Args) < 3 { fmt.Println("Usage: find issue-cert ") os.Exit(1) } name := os.Args[2] // Validate the name if err := find.ValidateName(name); err != nil { fmt.Printf("Invalid name: %v\n", err) os.Exit(1) } // Generate name owner key owner, err := p8k.New() if err != nil { fmt.Printf("Failed to create owner signer: %v\n", err) os.Exit(1) } if err := owner.Generate(); err != nil { fmt.Printf("Failed to generate owner key: %v\n", err) os.Exit(1) } // Generate certificate key (different from name owner) certSigner, err := p8k.New() if err != nil { fmt.Printf("Failed to create cert signer: %v\n", err) os.Exit(1) } if err := certSigner.Generate(); err != nil { fmt.Printf("Failed to generate cert key: %v\n", err) os.Exit(1) } certPubkey := hex.Enc(certSigner.Pub()) // Generate 3 witness signers (in production, these would be separate services) var witnesses []signer.I for i := 0; i < 3; i++ { witness, err := p8k.New() if err != nil { fmt.Printf("Failed to create witness %d: %v\n", i, err) os.Exit(1) } if err := witness.Generate(); err != nil { fmt.Printf("Failed to generate witness %d key: %v\n", i, err) os.Exit(1) } witnesses = append(witnesses, witness) } // Issue certificate (90 day validity) cert, err := find.IssueCertificate(name, certPubkey, find.CertificateValidity, owner, witnesses) if err != nil { fmt.Printf("Failed to issue certificate: %v\n", err) os.Exit(1) } fmt.Printf("Certificate Issued\n") fmt.Printf("==================\n") fmt.Printf("Name: %s\n", cert.Name) fmt.Printf("Cert Pubkey: %s\n", cert.CertPubkey) fmt.Printf("Valid From: %s\n", cert.ValidFrom) fmt.Printf("Valid Until: %s\n", cert.ValidUntil) fmt.Printf("Challenge: %s\n", cert.Challenge) fmt.Printf("Witnesses: %d\n", len(cert.Witnesses)) fmt.Printf("Algorithm: %s\n", cert.Algorithm) fmt.Printf("Usage: %s\n", cert.Usage) fmt.Printf("\nWitness Pubkeys:\n") for i, w := range cert.Witnesses { fmt.Printf(" %d: %s\n", i+1, w.Pubkey) } }