package main import ( "context" "crypto/x509" "encoding/base64" "encoding/pem" "fmt" "io" "net/http" "os" "strings" "time" "github.com/nacorid/naco-api/internal/server" ) func main() { facilitatorURL := os.Getenv("X402_FACILITATOR_URL") if facilitatorURL == "" { facilitatorURL = "https://api.cdp.coinbase.com/platform/v2/x402" } isMogami := strings.Contains(facilitatorURL, "mogami.tech") isPayAI := strings.Contains(facilitatorURL, "payai.network") isCDP := strings.Contains(facilitatorURL, "cdp.coinbase.com") var req *http.Request var err error if isMogami || isPayAI { // Mogami and PayAI facilitators don't require auth req, err = http.NewRequestWithContext(context.Background(), "GET", facilitatorURL+"/supported", nil) if err != nil { fmt.Fprintf(os.Stderr, "Failed to create request: %v\n", err) os.Exit(1) } if isPayAI { fmt.Println("Using PayAI facilitator (no auth)") } else { fmt.Println("Using Mogami facilitator (no auth)") } } else if isCDP { keyName := os.Getenv("CDP_API_KEY_ID") privateKeyPEM := os.Getenv("CDP_API_SECRET") if keyName == "" || privateKeyPEM == "" { fmt.Fprintf(os.Stderr, "CDP_API_KEY_ID and CDP_API_SECRET must be set for CDP facilitator\n") os.Exit(1) } // Debug: print key info fmt.Fprintf(os.Stderr, "DEBUG: keyName=%s, secretLen=%d\n", keyName, len(privateKeyPEM)) fmt.Fprintf(os.Stderr, "DEBUG: secretStart=%s\n", privateKeyPEM[:min(80, len(privateKeyPEM))]) fmt.Fprintf(os.Stderr, "DEBUG: hasLiteralNewline=%v, hasActualNewline=%v\n", strings.Contains(privateKeyPEM, "\\n"), strings.Contains(privateKeyPEM, "\n")) // Test key parsing manually first processedPEM := strings.ReplaceAll(privateKeyPEM, "\\n", "\n") fmt.Fprintf(os.Stderr, "DEBUG: after replaceAll, startsWith=%s\n", processedPEM[:min(50, len(processedPEM))]) block, _ := pem.Decode([]byte(processedPEM)) if block != nil { fmt.Fprintf(os.Stderr, "DEBUG: pem block type=%s, bytes=%d\n", block.Type, len(block.Bytes)) if strings.Contains(block.Type, "EC PRIVATE KEY") { if _, err := x509.ParseECPrivateKey(block.Bytes); err == nil { fmt.Fprintf(os.Stderr, "DEBUG: parsed as SEC1 EC key\n") } else if parsed, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil { fmt.Fprintf(os.Stderr, "DEBUG: parsed as PKCS8 key, type=%T\n", parsed) } } } auth, err := server.NewCDPAuth(keyName, privateKeyPEM) if err != nil { fmt.Fprintf(os.Stderr, "Failed to create CDP auth: %v\n", err) os.Exit(1) } fmt.Fprintf(os.Stderr, "DEBUG: auth created, signingMethod=%v\n", auth.GetSigningMethod()) headers, err := auth.GetAuthHeaders(context.Background()) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get auth headers: %v\n", err) os.Exit(1) } // Debug: print generated tokens for name, header := range map[string]string{ "Verify": headers.Verify["Authorization"], "Settle": headers.Settle["Authorization"], "Supported": headers.Supported["Authorization"], } { if len(header) > 7 { token := header[7:] // strip "Bearer " if parts := strings.Split(token, "."); len(parts) == 3 { if payload, err := base64.RawURLEncoding.DecodeString(parts[1]); err == nil { fmt.Fprintf(os.Stderr, "DEBUG: %s token claims: %s\n", name, string(payload)) } } } } req, err = http.NewRequestWithContext(context.Background(), "GET", facilitatorURL+"/supported", nil) if err != nil { fmt.Fprintf(os.Stderr, "Failed to create request: %v\n", err) os.Exit(1) } for k, v := range headers.Supported { req.Header.Set(k, v) } fmt.Println("Using CDP facilitator (with auth)") } else { fmt.Fprintf(os.Stderr, "Unknown facilitator URL: %s\n", facilitatorURL) os.Exit(1) } httpClient := &http.Client{ Timeout: 30 * time.Second, } resp, err := httpClient.Do(req) if err != nil { fmt.Fprintf(os.Stderr, "Request failed: %v\n", err) os.Exit(1) } defer resp.Body.Close() maxBytes := int64(5 * 1024 * 1024) body, err := io.ReadAll(io.LimitReader(resp.Body, maxBytes)) if err != nil { fmt.Printf("failed reading response body: %v", err) } fmt.Printf("Status: %d\n", resp.StatusCode) fmt.Printf("Response: %s\n", body) }