nostr

package
v0.3.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 24, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Overview

Package nostr handles Nostr event generation and signing.

Index

Constants

View Source
const (
	KindAppMetadata   = 32267 // Software Application (name, description, icon, platforms)
	KindRelease       = 30063 // Software Release (version, changelog, asset links)
	KindSoftwareAsset = 3063  // Software Asset (hash, size, URLs, cert hash, platforms)
	KindBlossomAuth   = 24242 // Blossom upload authorization
	KindIdentityProof = 30509 // NIP-C1 Cryptographic Identity Proof (SPKI)

	// Legacy kind used by older relay.zapstore.dev format
	KindFileMetadataLegacy = 1063 // NIP-94 File Metadata (legacy asset format)
)

Event kinds for Zapstore

View Source
const (
	// DefaultRelay is the default relay URL.
	DefaultRelay = "wss://relay.zapstore.dev"

	// RelayTimeout is the timeout for relay operations.
	RelayTimeout = 30 * time.Second
)
View Source
const DefaultNIP07Port = 17007

DefaultNIP07Port is the default port for the NIP-07 browser signer.

View Source
const DefaultPreviewPort = 17008

DefaultPreviewPort is the default port for the HTML preview server.

View Source
const KindProfile = 0

KindProfile is the kind for profile metadata events (NIP-01).

Variables

This section is empty.

Functions

func BuildAppMetadataEvent

func BuildAppMetadataEvent(meta *AppMetadata, pubkey string) *nostr.Event

BuildAppMetadataEvent creates a Software Application event (kind 32267).

func BuildBlossomAuthEvent

func BuildBlossomAuthEvent(fileHash string, pubkey string, expiration time.Time) *nostr.Event

BuildBlossomAuthEvent creates a kind 24242 event for Blossom upload authorization.

func BuildIdentityProofEvent

func BuildIdentityProofEvent(tags nostr.Tags, pubkey string, createdAt int64) *nostr.Event

BuildIdentityProofEvent creates a kind 30509 identity proof event per NIP-C1. The createdAt timestamp must match the one used when signing the proof message.

func BuildReleaseEvent

func BuildReleaseEvent(meta *ReleaseMetadata, pubkey string) *nostr.Event

BuildReleaseEvent creates a Software Release event (kind 30063).

func BuildSoftwareAssetEvent

func BuildSoftwareAssetEvent(meta *AssetMetadata, pubkey string) *nostr.Event

BuildSoftwareAssetEvent creates a Software Asset event (kind 3063 or 1063 in legacy mode).

func EventsToJSON

func EventsToJSON(events *EventSet) ([]byte, error)

EventsToJSON converts events to JSON Lines format.

func SignEventSet

func SignEventSet(ctx context.Context, signer Signer, events *EventSet, relayHint string) error

SignEventSet signs all events in an event set. It signs the Software Assets first to get their IDs, adds the references to Software Release, then signs Software Release and Software Application.

Types

type AppMetadata

type AppMetadata struct {
	PackageID   string
	Name        string
	Description string
	Summary     string
	Website     string
	License     string
	Repository  string   // Repository URL (for display)
	NIP34Repo   string   // NIP-34 repository pointer (a tag): "30617:pubkey:identifier"
	NIP34Relay  string   // Relay hint for NIP-34 pointer
	Tags        []string // Category tags
	IconURL     string   // Blossom URL for icon
	ImageURLs   []string // Screenshot URLs
	Platforms   []string // Platform identifiers (e.g., "android-arm64-v8a")

	// Legacy format fields (for old relay.zapstore.dev compatibility)
	LegacyFormat   bool   // Enable legacy format
	ReleaseVersion string // Version for the a-tag pointing to release (legacy only)
}

AppMetadata contains Software Application metadata (kind 32267).

type AssetMetadata

type AssetMetadata struct {
	Identifier            string // Asset identifier (may differ from app identifier)
	Version               string
	VersionCode           int64
	SHA256                string
	Size                  int64
	URLs                  []string // Download URLs (Blossom)
	CertFingerprint       string   // APK signing certificate SHA256
	MinSDK                int32
	TargetSDK             int32
	Platforms             []string // Full platform identifiers (e.g., "android-arm64-v8a")
	Filename              string   // Original filename (for variant detection)
	Variant               string   // Explicit variant name (e.g., "fdroid", "google")
	Commit                string   // Git commit hash for reproducible builds
	SupportedNIPs         []string // Supported Nostr NIPs
	MinAllowedVersion     string   // Minimum allowed version string
	MinAllowedVersionCode int64    // Minimum allowed version code

	// Legacy format fields (for old relay.zapstore.dev compatibility)
	LegacyFormat bool // Enable legacy format (kind 1063 with different tags)
}

AssetMetadata contains Software Asset metadata (kind 3063).

type AssetPreviewData

type AssetPreviewData struct {
	SHA256          string
	FileSize        int64
	Filename        string
	CertFingerprint string
	MinSDK          int32
	TargetSDK       int32
	Platforms       []string // Platform identifiers for this specific asset
}

AssetPreviewData contains data for a single software asset.

type BatchSigner

type BatchSigner interface {
	SignBatch(ctx context.Context, events []*nostr.Event) error
}

BatchSigner is an optional interface for signers that support batch signing.

type BuildEventSetParams

type BuildEventSetParams struct {
	APKInfo          *apk.APKInfo
	Config           *config.Config
	Pubkey           string
	OriginalURL      string // Original download URL (from release source)
	BlossomServer    string // Blossom server URL (fallback when OriginalURL is empty)
	IconURL          string
	ImageURLs        []string
	Changelog        string    // Release notes (from remote source or local file)
	Variant          string    // Explicit variant name (from config variants map)
	Commit           string    // Git commit hash for reproducible builds
	Channel          string    // Release channel: main (default), beta, nightly, dev
	ReleaseURL       string    // Release page URL (for legacy format url/r tags)
	LegacyFormat     bool      // Use legacy event format (kind 1063, different tags)
	ReleaseTimestamp time.Time // Release publish date (zero means use current time)
	// UseReleaseTimestampForApp sets kind 32267 created_at to ReleaseTimestamp.
	// When false, app metadata keeps current-time created_at.
	UseReleaseTimestampForApp bool
	// MinReleaseTimestamp ensures Release.CreatedAt is strictly greater than this value.
	// Used with --overwrite-release to guarantee NIP-33 replacement when the relay
	// has an existing event with the same or newer timestamp.
	MinReleaseTimestamp time.Time
}

BuildEventSetParams contains parameters for building an event set.

type BunkerSigner

type BunkerSigner struct {
	// contains filtered or unexported fields
}

BunkerSigner signs events via NIP-46 remote signer.

func NewBunkerSigner

func NewBunkerSigner(ctx context.Context, bunkerURL string) (*BunkerSigner, error)

NewBunkerSigner creates a signer from a bunker:// URL.

func (*BunkerSigner) Close

func (s *BunkerSigner) Close() error

func (*BunkerSigner) PublicKey

func (s *BunkerSigner) PublicKey() string

func (*BunkerSigner) Sign

func (s *BunkerSigner) Sign(ctx context.Context, event *nostr.Event) error

func (*BunkerSigner) Type

func (s *BunkerSigner) Type() SignerType

type EventSet

type EventSet struct {
	AppMetadata    *nostr.Event
	Release        *nostr.Event
	SoftwareAssets []*nostr.Event // Multiple assets (e.g., different APK variants)
}

EventSet contains all events to be published for an app release.

func BuildEventSet

func BuildEventSet(params BuildEventSetParams) *EventSet

BuildEventSet creates all events for an APK release. The Release event's asset references (e tags) are populated by SignEventSet after the asset event is signed.

func (*EventSet) AddAssetReference

func (es *EventSet) AddAssetReference(assetEventID string, relayHint string)

AddAssetReference adds an asset event ID reference to the Release event. This must be called after the asset event is signed but before the release is signed.

func (*EventSet) AddAssetReferences

func (es *EventSet) AddAssetReferences(relayHint string)

AddAssetReferences adds all asset event ID references to the Release event. This must be called after the asset events are signed but before the release is signed.

type ExistingApp

type ExistingApp struct {
	Event    *nostr.Event
	RelayURL string
}

ExistingApp contains information about an existing app on relays.

type ExistingAsset

type ExistingAsset struct {
	Event    *nostr.Event
	RelayURL string
	Version  string
}

ExistingAsset contains information about an existing software asset on relays.

type NIP07Signer

type NIP07Signer struct {
	// contains filtered or unexported fields
}

NIP07Signer signs events via browser NIP-07 extension.

func NewNIP07Signer

func NewNIP07Signer(ctx context.Context, port int) (*NIP07Signer, error)

NewNIP07Signer creates and initializes a NIP-07 browser signer. If port is 0, the default port (17007) is used.

func (*NIP07Signer) Close

func (s *NIP07Signer) Close() error

func (*NIP07Signer) PublicKey

func (s *NIP07Signer) PublicKey() string

func (*NIP07Signer) Sign

func (s *NIP07Signer) Sign(ctx context.Context, event *nostr.Event) error

func (*NIP07Signer) SignBatch

func (s *NIP07Signer) SignBatch(ctx context.Context, events []*nostr.Event) error

SignBatch signs multiple events in a single browser interaction.

func (*NIP07Signer) Type

func (s *NIP07Signer) Type() SignerType

type NIP07SignerOptions

type NIP07SignerOptions struct {
	Port int // Custom port (0 = use default)
}

NIP07SignerOptions contains options for creating a NIP-07 signer.

type NpubSigner

type NpubSigner struct {
	// contains filtered or unexported fields
}

NpubSigner is a "signer" that outputs unsigned events. Used for external signing workflows.

func NewNpubSigner

func NewNpubSigner(npub string) (*NpubSigner, error)

NewNpubSigner creates a signer from an npub.

func (*NpubSigner) Close

func (s *NpubSigner) Close() error

func (*NpubSigner) PublicKey

func (s *NpubSigner) PublicKey() string

func (*NpubSigner) Sign

func (s *NpubSigner) Sign(ctx context.Context, event *nostr.Event) error

func (*NpubSigner) Type

func (s *NpubSigner) Type() SignerType

type NsecSigner

type NsecSigner struct {
	// contains filtered or unexported fields
}

NsecSigner signs events with a private key.

func NewNsecSigner

func NewNsecSigner(nsec string) (*NsecSigner, error)

NewNsecSigner creates a signer from an nsec.

func (*NsecSigner) Close

func (s *NsecSigner) Close() error

Close clears sensitive key material from memory. Note: Go strings are immutable, so we cannot truly zero them. Setting to empty string allows the original to be garbage collected sooner and reduces the window of exposure.

func (*NsecSigner) PublicKey

func (s *NsecSigner) PublicKey() string

func (*NsecSigner) Sign

func (s *NsecSigner) Sign(ctx context.Context, event *nostr.Event) error

func (*NsecSigner) Type

func (s *NsecSigner) Type() SignerType

type PreviewData

type PreviewData struct {
	// Software Application
	AppName     string
	PackageID   string
	Summary     string
	Description string
	Website     string
	Repository  string
	License     string
	Tags        []string
	IconData    []byte             // Raw PNG icon data
	IconURL     string             // URL if using remote icon
	ImageURLs   []string           // Screenshot URLs (remote or will be replaced with local)
	ImageData   []PreviewImageData // Pre-downloaded screenshot data (served locally)
	Platforms   []string           // All platforms (union of all assets)

	// Software Release
	Version     string
	VersionCode int64
	Channel     string
	Changelog   string

	// Software Assets (multiple)
	Assets []AssetPreviewData

	// Publish targets (where it WILL be published)
	BlossomServer string
	RelayURLs     []string

	// Events for JSON view (optional - may be nil before signing)
	AppMetadataEvent    *nostr.Event
	ReleaseEvent        *nostr.Event
	SoftwareAssetEvents []*nostr.Event
}

PreviewData contains all data needed to render the preview.

func BuildPreviewData

func BuildPreviewData(apkInfo *apk.APKInfo, cfg *config.Config, events *EventSet, changelog string, blossomURL string, relayURLs []string) *PreviewData

BuildPreviewData creates preview data from APK info, config, and events. Use this after signing when events are available.

func BuildPreviewDataFromAPK

func BuildPreviewDataFromAPK(apkInfo *apk.APKInfo, cfg *config.Config, changelog string, blossomURL string, relayURLs []string) *PreviewData

BuildPreviewDataFromAPK creates preview data from APK info and config (before signing). This is used for the pre-signing preview where events are not yet available.

func BuildPreviewDataFromAPKs

func BuildPreviewDataFromAPKs(apkInfos []*apk.APKInfo, cfg *config.Config, changelog string, blossomURL string, relayURLs []string) *PreviewData

BuildPreviewDataFromAPKs creates preview data from multiple APK infos and config (before signing). This is used for the pre-signing preview where events are not yet available.

func BuildPreviewDataFromEvents

func BuildPreviewDataFromEvents(apkInfos []*apk.APKInfo, cfg *config.Config, events *EventSet, changelog string, blossomURL string, relayURLs []string) *PreviewData

BuildPreviewDataFromEvents creates preview data from multiple APKs, config, and events. Use this after signing when events are available.

type PreviewImageData

type PreviewImageData struct {
	Data     []byte
	MimeType string
}

PreviewImageData holds pre-downloaded image data for local serving.

type PreviewServer

type PreviewServer struct {
	// contains filtered or unexported fields
}

PreviewServer serves the HTML preview.

func NewPreviewServer

func NewPreviewServer(data *PreviewData, changelog, iconURL string, port int) *PreviewServer

NewPreviewServer creates a preview server on the specified port. If port is 0, it uses the default port.

func (*PreviewServer) Close

func (s *PreviewServer) Close() error

Close shuts down the preview server.

func (*PreviewServer) ConfirmFromCLI

func (s *PreviewServer) ConfirmFromCLI()

ConfirmFromCLI confirms the preview from the CLI, which signals the browser to close.

func (*PreviewServer) Start

func (s *PreviewServer) Start() (string, error)

Start starts the preview server and opens the browser.

type PublishResult

type PublishResult struct {
	RelayURL    string
	Success     bool
	IsDuplicate bool
	Error       error
}

PublishResult contains the result of publishing to a single relay.

type Publisher

type Publisher struct {
	// contains filtered or unexported fields
}

Publisher handles publishing events to relays.

func NewPublisher

func NewPublisher(relayURLs []string) *Publisher

NewPublisher creates a new publisher.

func NewPublisherFromEnv

func NewPublisherFromEnv(relaysEnv string) *Publisher

NewPublisherFromEnv creates a publisher from the RELAY_URLS environment variable.

func (*Publisher) CheckExistingApp

func (p *Publisher) CheckExistingApp(ctx context.Context, identifier string) (*ExistingApp, error)

CheckExistingApp queries all relays to check if an App Metadata event already exists. It searches for kind 32267 events with a matching `d` tag (identifier). Returns the first existing App found, or nil if none exists.

func (*Publisher) CheckExistingAsset

func (p *Publisher) CheckExistingAsset(ctx context.Context, identifier, version string) (*ExistingAsset, error)

CheckExistingAsset queries all relays to check if a Software Asset already exists. It searches for kind 3063 events with a matching `i` tag (identifier) and `version` tag. Returns the first existing Software Asset found, or nil if none exists.

func (*Publisher) CheckExistingRelease added in v0.3.4

func (p *Publisher) CheckExistingRelease(ctx context.Context, pubkey, identifier, version string) (time.Time, error)

CheckExistingRelease queries all relays for the latest Software Release event (kind 30063). It searches by pubkey and d tag (identifier@version). Returns the CreatedAt of the most recent existing release, or zero time if none exists.

func (*Publisher) FetchAllIdentityProofs

func (p *Publisher) FetchAllIdentityProofs(ctx context.Context, pubkey string) ([]*nostr.Event, error)

FetchAllIdentityProofs queries relays for all kind 30509 identity proof events from a pubkey.

func (*Publisher) FetchIdentityProof

func (p *Publisher) FetchIdentityProof(ctx context.Context, pubkey, spkifp string) (*nostr.Event, error)

FetchIdentityProof queries relays for a kind 30509 identity proof event. If spkifp is provided, looks for that specific identity; otherwise returns any identity proof. Returns nil if no matching event is found.

func (*Publisher) Publish

func (p *Publisher) Publish(ctx context.Context, event *nostr.Event) []PublishResult

Publish publishes an event to all configured relays.

func (*Publisher) PublishEventSet

func (p *Publisher) PublishEventSet(ctx context.Context, events *EventSet) (map[string][]PublishResult, error)

PublishEventSet publishes all events in an event set.

func (*Publisher) RelayURLs

func (p *Publisher) RelayURLs() []string

RelayURLs returns the configured relay URLs.

type ReleaseMetadata

type ReleaseMetadata struct {
	PackageID      string
	Version        string
	VersionCode    int64
	Changelog      string   // Release notes (content field)
	Channel        string   // Release channel: main, beta, nightly, dev
	AssetEventIDs  []string // Event IDs of asset events (kind 3063)
	AssetRelayHint string   // Optional relay hint for asset events

	// Legacy format fields (for old relay.zapstore.dev compatibility)
	LegacyFormat bool   // Enable legacy format
	ReleaseURL   string // Release page URL (url/r tags in legacy mode)
	Commit       string // Git commit hash (in release for legacy, in asset for new)
}

ReleaseMetadata contains Software Release metadata (kind 30063).

type Signer

type Signer interface {
	// Type returns the signer type.
	Type() SignerType

	// PublicKey returns the public key (hex).
	PublicKey() string

	// Sign signs an event in place.
	Sign(ctx context.Context, event *nostr.Event) error

	// Close releases any resources.
	Close() error
}

Signer handles event signing.

func NewSigner

func NewSigner(ctx context.Context, signWith string) (Signer, error)

NewSigner creates a signer from a SIGN_WITH value.

func NewSignerWithOptions

func NewSignerWithOptions(ctx context.Context, signWith string, opts SignerOptions) (Signer, error)

NewSignerWithOptions creates a signer from a SIGN_WITH value with options.

type SignerOptions

type SignerOptions struct {
	Port int // Custom port for browser signer (0 = default)
}

SignerOptions contains options for creating a signer.

type SignerType

type SignerType int

SignerType represents the type of signer.

const (
	SignerNsec SignerType = iota
	SignerNpub
	SignerBunker
	SignerNIP07
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL