NAME

Net::Nostr::DVM - NIP-90 Data Vending Machine

SYNOPSIS

use Net::Nostr::DVM;

# Job request (kind 5000-5999)
my $event = Net::Nostr::DVM->job_request(
    pubkey => $hex_pubkey,
    kind   => 5001,
    inputs => [['https://example.com/audio.mp3', 'url']],
    output => 'text/plain',
);

# Job result (kind 6000-6999)
my $result = Net::Nostr::DVM->job_result(
    pubkey  => $hex_pubkey,
    request => $event,
    content => 'Transcribed text here.',
    amount  => '5000',
);

# Job feedback (kind 7000)
my $feedback = Net::Nostr::DVM->job_feedback(
    pubkey     => $hex_pubkey,
    request_id => $job_request_id,
    customer   => $customer_pubkey,
    status     => 'processing',
);

# Parse any DVM event
my $parsed = Net::Nostr::DVM->from_event($event);

# Validate
Net::Nostr::DVM->validate($event);

# Kind helpers
Net::Nostr::DVM->is_job_request(5001);   # true
Net::Nostr::DVM->is_job_result(6001);    # true
Net::Nostr::DVM->is_job_feedback(7000);  # true
Net::Nostr::DVM->result_kind(5001);      # 6001
Net::Nostr::DVM->request_kind(6001);     # 5001

DESCRIPTION

Implements NIP-90 (Data Vending Machine). Nostr acts as a marketplace for data processing where customers request jobs and service providers compete to fulfill them. Three event kind ranges are used:

  • Job Request (kind 5000-5999) - Published by a customer to request data processing. Contains input data, expected output format, optional parameters, a bid amount, and preferred relays and service providers. All tags are optional.

  • Job Result (kind 6000-6999) - Published by a service provider with the output of processed data. The kind is always 1000 higher than the corresponding request kind. References the original request event and includes the customer's pubkey.

  • Job Feedback (kind 7000) - Published by a service provider to communicate status updates. Status values include payment-required, processing, error, success, and partial. MAY include partial results in content.

Job requests support encrypted parameters via the encrypted tag. When encrypted, input and param tags are encrypted with the service provider's key using NIP-04 and placed in the content field.

CONSTANTS

SP_DISCOVERY_KIND

my $kind = Net::Nostr::DVM::SP_DISCOVERY_KIND;  # 31990

NIP-89 kind for service provider discoverability announcements.

CONSTRUCTOR

new

my $dvm = Net::Nostr::DVM->new(
    status => 'processing',
);

Creates a new Net::Nostr::DVM object. Croaks on unknown arguments. Array fields (inputs, params, relays, providers, hashtags) default to [].

CLASS METHODS

job_request

my $event = Net::Nostr::DVM->job_request(
    pubkey    => $hex_pubkey,                      # required
    kind      => 5001,                             # required (5000-5999)
    inputs    => [[$data, $type, $relay, $marker], ...], # optional (i tags)
    output    => $mime_type,                        # optional
    params    => [[$key, $value], ...],             # optional (param tags)
    bid       => $millisats,                       # optional
    relays    => [$url, ...],                      # optional
    providers => [$pubkey, ...],                   # optional (p tags)
    hashtags  => [$tag, ...],                      # optional (t tags)
    encrypted => 1,                                # optional
    content   => $encrypted_payload,               # optional, defaults to ''
);

Creates a job request Net::Nostr::Event. The kind must be in the 5000-5999 range. Input types are url, event, job, or text. When encrypted is set, an encrypted tag is added and content should contain the NIP-04 encrypted parameters.

job_result

my $event = Net::Nostr::DVM->job_result(
    pubkey     => $hex_pubkey,      # required
    request    => $request_event,   # required (Net::Nostr::Event)
    content    => $payload,         # optional, defaults to ''
    relay_hint => $relay_url,       # optional
    amount     => $millisats,       # optional
    bolt11     => $invoice,         # optional
    encrypted  => 1,               # optional
);

Creates a job result Net::Nostr::Event. The kind is automatically set to the request kind + 1000. The request tag contains the stringified JSON of the original request. When encrypted is set, input tags from the request are omitted to avoid leaking clear text.

job_feedback

my $event = Net::Nostr::DVM->job_feedback(
    pubkey     => $hex_pubkey,      # required
    request_id => $event_id,        # required (e tag)
    customer   => $customer_pubkey, # required (p tag)
    status     => $status,          # required
    extra_info => $description,     # optional
    relay_hint => $relay_url,       # optional
    amount     => $millisats,       # optional
    bolt11     => $invoice,         # optional
    content    => $partial_result,  # optional, defaults to ''
    encrypted  => 1,               # optional, adds 'encrypted' tag
);

Creates a kind 7000 job feedback Net::Nostr::Event. Valid status values: payment-required, processing, error, success, partial.

from_event

my $dvm = Net::Nostr::DVM->from_event($event);

Parses a DVM event (kind 5000-5999, 6000-6999, or 7000) into a Net::Nostr::DVM object. Returns undef for unrecognized kinds.

validate

Net::Nostr::DVM->validate($event);

Validates a NIP-90 event. Croaks if:

  • Kind is not in 5000-5999, 6000-6999, or 7000

  • Job result missing e, p, or request tag

  • Job feedback missing status, e, or p tag

Returns 1 on success.

is_job_request

Net::Nostr::DVM->is_job_request(5001);  # true

Returns true if the kind is in the 5000-5999 range.

is_job_result

Net::Nostr::DVM->is_job_result(6001);  # true

Returns true if the kind is in the 6000-6999 range.

is_job_feedback

Net::Nostr::DVM->is_job_feedback(7000);  # true

Returns true if the kind is 7000.

result_kind

my $rk = Net::Nostr::DVM->result_kind(5001);  # 6001

Returns the result kind for a given request kind (request + 1000).

request_kind

my $rk = Net::Nostr::DVM->request_kind(6001);  # 5001

Returns the request kind for a given result kind (result - 1000).

ACCESSORS

inputs

Arrayref of arrayrefs from i tags. Each contains [$data, $type, $relay, $marker]. Defaults to [].

output

Expected output MIME type from output tag.

params

Arrayref of arrayrefs from param tags. Each contains [$key, $value]. Defaults to [].

bid

Maximum payment amount in millisats from bid tag.

relays

Arrayref of relay URLs from relays tag. Defaults to [].

providers

Arrayref of service provider pubkeys from p tags. Defaults to [].

hashtags

Arrayref of hashtag strings from t tags. Defaults to [].

encrypted

True if the event has an encrypted tag.

request_id

Job request event ID from e tag (results and feedback).

request_event

Stringified JSON of the original request from request tag (results).

relay_hint

Relay hint from e tag.

customer

Customer pubkey from p tag (results and feedback).

amount

Payment amount in millisats from amount tag.

bolt11

Bolt11 invoice from amount tag.

status

Feedback status from status tag. One of payment-required, processing, error, success, or partial.

extra_info

Extra human-readable info from status tag.

SEE ALSO

NIP-90, Net::Nostr, Net::Nostr::Event