commit 6694d39692f20dc6d2d2a2d74a84db2b3449599e
parent e86b22e408fd76ac5a976600af98784ef1130e05
Author: triesap <triesap@radroots.dev>
Date: Mon, 3 Nov 2025 07:28:33 +0000
utils-nostr: introduce trade listing workflow primitives with request and result builders, add job event helpers and tagging utilities, migrate types to events bindings with per-event tag modules, expand public exports, remove an obsolete dependency, and retire legacy price and quantity types
Diffstat:
31 files changed, 963 insertions(+), 156 deletions(-)
diff --git a/utils-nostr/package.json b/utils-nostr/package.json
@@ -36,7 +36,6 @@
"@noble/curves": "^1.6.0",
"@noble/hashes": "^1.4.0",
"@nostr-dev-kit/ndk": "2.14.33",
- "@radroots/radroots-common-bindings": "*",
"nostr-geotags": "*",
"nostr-tools": "^2.10.4"
}
diff --git a/utils-nostr/src/domain/trade/lib.ts b/utils-nostr/src/domain/trade/lib.ts
@@ -0,0 +1,25 @@
+import { KIND_TRADE_LISTING_ACCEPT_REQ, KIND_TRADE_LISTING_ACCEPT_RES, KIND_TRADE_LISTING_CANCEL_REQ, KIND_TRADE_LISTING_CANCEL_RES, KIND_TRADE_LISTING_CONVEYANCE_REQ, KIND_TRADE_LISTING_CONVEYANCE_RES, KIND_TRADE_LISTING_FULFILL_REQ, KIND_TRADE_LISTING_FULFILL_RES, KIND_TRADE_LISTING_INVOICE_REQ, KIND_TRADE_LISTING_INVOICE_RES, KIND_TRADE_LISTING_ORDER_REQ, KIND_TRADE_LISTING_ORDER_RES, KIND_TRADE_LISTING_PAYMENT_REQ, KIND_TRADE_LISTING_PAYMENT_RES, KIND_TRADE_LISTING_RECEIPT_REQ, KIND_TRADE_LISTING_RECEIPT_RES, KIND_TRADE_LISTING_REFUND_REQ, KIND_TRADE_LISTING_REFUND_RES } from "@radroots/trade-bindings";
+
+export const REQUEST_KINDS: Record<string, number> = {
+ order: KIND_TRADE_LISTING_ORDER_REQ,
+ accept: KIND_TRADE_LISTING_ACCEPT_REQ,
+ conveyance: KIND_TRADE_LISTING_CONVEYANCE_REQ,
+ invoice: KIND_TRADE_LISTING_INVOICE_REQ,
+ payment: KIND_TRADE_LISTING_PAYMENT_REQ,
+ fulfillment: KIND_TRADE_LISTING_FULFILL_REQ,
+ receipt: KIND_TRADE_LISTING_RECEIPT_REQ,
+ cancel: KIND_TRADE_LISTING_CANCEL_REQ,
+ refund: KIND_TRADE_LISTING_REFUND_REQ,
+};
+
+export const RESULT_KINDS: Record<string, number> = {
+ order: KIND_TRADE_LISTING_ORDER_RES,
+ accept: KIND_TRADE_LISTING_ACCEPT_RES,
+ conveyance: KIND_TRADE_LISTING_CONVEYANCE_RES,
+ invoice: KIND_TRADE_LISTING_INVOICE_RES,
+ payment: KIND_TRADE_LISTING_PAYMENT_RES,
+ fulfillment: KIND_TRADE_LISTING_FULFILL_RES,
+ receipt: KIND_TRADE_LISTING_RECEIPT_RES,
+ cancel: KIND_TRADE_LISTING_CANCEL_RES,
+ refund: KIND_TRADE_LISTING_REFUND_RES,
+};
diff --git a/utils-nostr/src/domain/trade/listing/accept/lib.ts b/utils-nostr/src/domain/trade/listing/accept/lib.ts
@@ -0,0 +1,62 @@
+import { NDKEvent } from "@nostr-dev-kit/ndk";
+import { RadrootsJobInput } from "@radroots/events-bindings";
+import { KIND_TRADE_LISTING_ACCEPT_REQ, KIND_TRADE_LISTING_ACCEPT_RES, MARKER_LISTING, MARKER_PREVIOUS, TradeListingAcceptRequest, TradeListingAcceptResult } from "@radroots/trade-bindings";
+import { ndk_event } from "../../../../events/lib.js";
+import { NDKEventFigure } from "../../../../types/ndk.js";
+import {
+ build_request_tags,
+ build_result_tags,
+ CommonRequestOpts,
+ CommonResultOpts,
+ make_event_input
+} from "../../tags.js";
+import { tags_trade_listing_chain } from "../tags.js";
+
+export const ndk_event_trade_listing_accept_request = async (
+ opts: NDKEventFigure<{ data: TradeListingAcceptRequest; options?: CommonRequestOpts }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data, options } = opts;
+
+ const inputs: RadrootsJobInput[] = [
+ make_event_input(data.order_result_event_id, MARKER_PREVIOUS),
+ make_event_input(data.listing_event_id, MARKER_LISTING),
+ ];
+
+ const tags = build_request_tags(KIND_TRADE_LISTING_ACCEPT_REQ, inputs, options);
+
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_ACCEPT_REQ, content: "", tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+
+export const ndk_event_trade_listing_accept_result = async (
+ opts: NDKEventFigure<{
+ request_event_id: string;
+ content: TradeListingAcceptResult | string;
+ options?: CommonResultOpts;
+ }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, request_event_id, content, options } = opts;
+
+ const base_tags = build_result_tags(
+ KIND_TRADE_LISTING_ACCEPT_RES,
+ request_event_id,
+ options
+ );
+ const tags = options?.chain
+ ? [...base_tags, ...tags_trade_listing_chain(options.chain)]
+ : base_tags;
+
+ const content_body = typeof content === "string" ? content : JSON.stringify(content);
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_ACCEPT_RES, content: content_body, tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
diff --git a/utils-nostr/src/domain/trade/listing/conveyance/lib.ts b/utils-nostr/src/domain/trade/listing/conveyance/lib.ts
@@ -0,0 +1,63 @@
+import { NDKEvent } from "@nostr-dev-kit/ndk";
+import { RadrootsJobInput } from "@radroots/events-bindings";
+import { KIND_TRADE_LISTING_CONVEYANCE_REQ, KIND_TRADE_LISTING_CONVEYANCE_RES, MARKER_ACCEPT_RESULT, MARKER_PAYLOAD, TradeListingConveyanceRequest, TradeListingConveyanceResult } from "@radroots/trade-bindings";
+import { ndk_event } from "../../../../events/lib.js";
+import { NDKEventFigure } from "../../../../types/ndk.js";
+import {
+ build_request_tags,
+ build_result_tags,
+ CommonRequestOpts,
+ CommonResultOpts,
+ make_event_input,
+ make_text_input,
+} from "../../tags.js";
+import { tags_trade_listing_chain } from "../tags.js";
+
+export const ndk_event_trade_listing_conveyance_request = async (
+ opts: NDKEventFigure<{ data: TradeListingConveyanceRequest; options?: CommonRequestOpts }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data, options } = opts;
+
+ const inputs: RadrootsJobInput[] = [
+ make_event_input(data.accept_result_event_id, MARKER_ACCEPT_RESULT),
+ make_text_input({ method: data.method }, MARKER_PAYLOAD),
+ ];
+
+ const tags = build_request_tags(KIND_TRADE_LISTING_CONVEYANCE_REQ, inputs, options);
+
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_CONVEYANCE_REQ, content: "", tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+
+export const ndk_event_trade_listing_conveyance_result = async (
+ opts: NDKEventFigure<{
+ request_event_id: string;
+ content: TradeListingConveyanceResult | string;
+ options?: CommonResultOpts;
+ }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, request_event_id, content, options } = opts;
+
+ const base_tags = build_result_tags(
+ KIND_TRADE_LISTING_CONVEYANCE_RES,
+ request_event_id,
+ options
+ );
+ const tags = options?.chain
+ ? [...base_tags, ...tags_trade_listing_chain(options.chain)]
+ : base_tags;
+
+ const content_body = typeof content === "string" ? content : JSON.stringify(content);
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_CONVEYANCE_RES, content: content_body, tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+\ No newline at end of file
diff --git a/utils-nostr/src/domain/trade/listing/fulfillment/lib.ts b/utils-nostr/src/domain/trade/listing/fulfillment/lib.ts
@@ -0,0 +1,61 @@
+import { NDKEvent } from "@nostr-dev-kit/ndk";
+import { RadrootsJobInput } from "@radroots/events-bindings";
+import { KIND_TRADE_LISTING_FULFILL_REQ, KIND_TRADE_LISTING_FULFILL_RES, MARKER_PREVIOUS, TradeListingFulfillmentRequest, TradeListingFulfillmentState } from "@radroots/trade-bindings";
+import { ndk_event } from "../../../../events/lib.js";
+import { NDKEventFigure } from "../../../../types/ndk.js";
+import {
+ build_request_tags,
+ build_result_tags,
+ CommonRequestOpts,
+ CommonResultOpts,
+ make_event_input
+} from "../../tags.js";
+import { tags_trade_listing_chain } from "../tags.js";
+
+export const ndk_event_trade_listing_fulfillment_request = async (
+ opts: NDKEventFigure<{ data: TradeListingFulfillmentRequest; options?: CommonRequestOpts }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data, options } = opts;
+
+ const inputs: RadrootsJobInput[] = [
+ make_event_input(data.payment_result_event_id, MARKER_PREVIOUS),
+ ];
+
+ const tags = build_request_tags(KIND_TRADE_LISTING_FULFILL_REQ, inputs, options);
+
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_FULFILL_REQ, content: "", tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+
+export const ndk_event_trade_listing_fulfillment_result = async (
+ opts: NDKEventFigure<{
+ request_event_id: string;
+ content: TradeListingFulfillmentState | string;
+ options?: CommonResultOpts;
+ }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, request_event_id, content, options } = opts;
+
+ const base_tags = build_result_tags(
+ KIND_TRADE_LISTING_FULFILL_RES,
+ request_event_id,
+ options
+ );
+ const tags = options?.chain
+ ? [...base_tags, ...tags_trade_listing_chain(options.chain)]
+ : base_tags;
+
+ const content_body = typeof content === "string" ? content : JSON.stringify(content);
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_FULFILL_RES, content: content_body, tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+\ No newline at end of file
diff --git a/utils-nostr/src/domain/trade/listing/invoice/lib.ts b/utils-nostr/src/domain/trade/listing/invoice/lib.ts
@@ -0,0 +1,73 @@
+import { NDKEvent } from "@nostr-dev-kit/ndk";
+import { RadrootsJobInput } from "@radroots/events-bindings";
+import { KIND_TRADE_LISTING_INVOICE_REQ, KIND_TRADE_LISTING_INVOICE_RES, MARKER_ACCEPT_RESULT, TradeListingInvoiceRequest, TradeListingInvoiceResult } from "@radroots/trade-bindings";
+import { ndk_event } from "../../../../events/lib.js";
+import { NDKEventFigure } from "../../../../types/ndk.js";
+import {
+ build_request_tags,
+ build_result_tags,
+ CommonRequestOpts,
+ CommonResultOpts,
+ make_event_input
+} from "../../tags.js";
+import { tags_trade_listing_chain } from "../tags.js";
+
+export const ndk_event_trade_listing_invoice_request = async (
+ opts: NDKEventFigure<{ data: TradeListingInvoiceRequest; options?: CommonRequestOpts }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data, options } = opts;
+
+ const inputs: RadrootsJobInput[] = [
+ make_event_input(data.accept_result_event_id, MARKER_ACCEPT_RESULT),
+ ];
+
+ const tags = build_request_tags(KIND_TRADE_LISTING_INVOICE_REQ, inputs, options);
+
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_INVOICE_REQ, content: "", tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+
+export const ndk_event_trade_listing_invoice_result = async (
+ opts: NDKEventFigure<{
+ request_event_id: string;
+ content: TradeListingInvoiceResult | string;
+ options?: Omit<CommonResultOpts, "payment_sat" | "payment_bolt11"> & {
+ chain?: { e_root: string; d?: string; e_prev?: string };
+ };
+ }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, request_event_id, content, options } = opts;
+
+ const parsed: TradeListingInvoiceResult | undefined =
+ typeof content === "string" ? undefined : (content as TradeListingInvoiceResult);
+
+ const base_tags = build_result_tags(
+ KIND_TRADE_LISTING_INVOICE_RES,
+ request_event_id,
+ options,
+ parsed
+ ? {
+ payment_sat: parsed.total_sat,
+ payment_bolt11: parsed.bolt11,
+ }
+ : undefined
+ );
+
+ const tags = options?.chain
+ ? [...base_tags, ...tags_trade_listing_chain(options.chain)]
+ : base_tags;
+
+ const content_body = typeof content === "string" ? content : JSON.stringify(content);
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_INVOICE_RES, content: content_body, tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+\ No newline at end of file
diff --git a/utils-nostr/src/domain/trade/listing/order/lib.ts b/utils-nostr/src/domain/trade/listing/order/lib.ts
@@ -0,0 +1,70 @@
+import { NDKEvent } from "@nostr-dev-kit/ndk";
+import { RadrootsJobInput } from "@radroots/events-bindings";
+import { KIND_TRADE_LISTING_ORDER_REQ, KIND_TRADE_LISTING_ORDER_RES, MARKER_LISTING, MARKER_PAYLOAD, TradeListingOrderResult, type TradeListingOrderRequest } from "@radroots/trade-bindings";
+import { ndk_event } from "../../../../events/lib.js";
+import { NDKEventFigure } from "../../../../types/ndk.js";
+import {
+ build_request_tags,
+ build_result_tags,
+ CommonRequestOpts,
+ CommonResultOpts,
+ make_event_input,
+ make_text_input,
+} from "../../tags.js";
+import { tags_trade_listing_chain } from "../tags.js";
+
+export const ndk_event_trade_listing_order_request = async (
+ opts: NDKEventFigure<{ data: TradeListingOrderRequest; options?: CommonRequestOpts }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data, options } = opts;
+
+ const inputs: RadrootsJobInput[] = [
+ make_event_input(data.event.id, MARKER_LISTING),
+ make_text_input(data.payload, MARKER_PAYLOAD),
+ ];
+
+ const tags = build_request_tags(KIND_TRADE_LISTING_ORDER_REQ, inputs, options);
+
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_ORDER_REQ, content: "", tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+
+export const ndk_event_trade_listing_order_result = async (
+ opts: NDKEventFigure<{
+ request_event_id: string;
+ content: TradeListingOrderResult | string;
+ options?: CommonResultOpts;
+ }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, request_event_id, content, options } = opts;
+
+ const include_inputs =
+ options?.include_inputs && !options.encrypted
+ ? options.include_inputs.map(s => make_text_input(s, MARKER_PAYLOAD))
+ : [];
+
+ const base_tags = build_result_tags(
+ KIND_TRADE_LISTING_ORDER_RES,
+ request_event_id,
+ options,
+ { inputs: include_inputs }
+ );
+
+ const tags = options?.chain
+ ? [...base_tags, ...tags_trade_listing_chain(options.chain)]
+ : base_tags;
+
+ const content_body = typeof content === "string" ? content : JSON.stringify(content);
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_ORDER_RES, content: content_body, tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
diff --git a/utils-nostr/src/domain/trade/listing/payment/lib.ts b/utils-nostr/src/domain/trade/listing/payment/lib.ts
@@ -0,0 +1,63 @@
+import { NDKEvent } from "@nostr-dev-kit/ndk";
+import { RadrootsJobInput } from "@radroots/events-bindings";
+import { KIND_TRADE_LISTING_PAYMENT_REQ, KIND_TRADE_LISTING_PAYMENT_RES, MARKER_INVOICE_RESULT, MARKER_PROOF, TradeListingPaymentProofRequest, TradeListingPaymentResult } from "@radroots/trade-bindings";
+import { ndk_event } from "../../../../events/lib.js";
+import { NDKEventFigure } from "../../../../types/ndk.js";
+import {
+ build_request_tags,
+ build_result_tags,
+ CommonRequestOpts,
+ CommonResultOpts,
+ make_event_input,
+ make_text_input,
+} from "../../tags.js";
+import { tags_trade_listing_chain } from "../tags.js";
+
+export const ndk_event_trade_listing_payment_request = async (
+ opts: NDKEventFigure<{ data: TradeListingPaymentProofRequest; options?: CommonRequestOpts }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data, options } = opts;
+
+ const inputs: RadrootsJobInput[] = [
+ make_event_input(data.invoice_result_event_id, MARKER_INVOICE_RESULT),
+ make_text_input(data.proof, MARKER_PROOF),
+ ];
+
+ const tags = build_request_tags(KIND_TRADE_LISTING_PAYMENT_REQ, inputs, options);
+
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_PAYMENT_REQ, content: "", tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+
+export const ndk_event_trade_listing_payment_result = async (
+ opts: NDKEventFigure<{
+ request_event_id: string;
+ content: TradeListingPaymentResult | string;
+ options?: CommonResultOpts;
+ }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, request_event_id, content, options } = opts;
+
+ const base_tags = build_result_tags(
+ KIND_TRADE_LISTING_PAYMENT_RES,
+ request_event_id,
+ options
+ );
+ const tags = options?.chain
+ ? [...base_tags, ...tags_trade_listing_chain(options.chain)]
+ : base_tags;
+
+ const content_body = typeof content === "string" ? content : JSON.stringify(content);
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_PAYMENT_RES, content: content_body, tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
diff --git a/utils-nostr/src/domain/trade/listing/receipt/lib.ts b/utils-nostr/src/domain/trade/listing/receipt/lib.ts
@@ -0,0 +1,63 @@
+import { NDKEvent } from "@nostr-dev-kit/ndk";
+import { RadrootsJobInput } from "@radroots/events-bindings";
+import { KIND_TRADE_LISTING_RECEIPT_REQ, KIND_TRADE_LISTING_RECEIPT_RES, MARKER_FULFILLMENT_RESULT, MARKER_PAYLOAD, TradeListingReceiptRequest, TradeListingReceiptResult } from "@radroots/trade-bindings";
+import { ndk_event } from "../../../../events/lib.js";
+import { NDKEventFigure } from "../../../../types/ndk.js";
+import {
+ build_request_tags,
+ build_result_tags,
+ CommonRequestOpts,
+ CommonResultOpts,
+ make_event_input,
+ make_text_input,
+} from "../../tags.js";
+import { tags_trade_listing_chain } from "../tags.js";
+
+export const ndk_event_trade_listing_receipt_request = async (
+ opts: NDKEventFigure<{ data: TradeListingReceiptRequest; options?: CommonRequestOpts }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data, options } = opts;
+
+ const inputs: RadrootsJobInput[] = [
+ make_event_input(data.fulfillment_result_event_id, MARKER_FULFILLMENT_RESULT),
+ ...(data.note ? [make_text_input({ note: data.note }, MARKER_PAYLOAD)] : []),
+ ];
+
+ const tags = build_request_tags(KIND_TRADE_LISTING_RECEIPT_REQ, inputs, options);
+
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_RECEIPT_REQ, content: "", tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+
+export const ndk_event_trade_listing_receipt_result = async (
+ opts: NDKEventFigure<{
+ request_event_id: string;
+ content: TradeListingReceiptResult | string;
+ options?: CommonResultOpts;
+ }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, request_event_id, content, options } = opts;
+
+ const base_tags = build_result_tags(
+ KIND_TRADE_LISTING_RECEIPT_RES,
+ request_event_id,
+ options
+ );
+ const tags = options?.chain
+ ? [...base_tags, ...tags_trade_listing_chain(options.chain)]
+ : base_tags;
+
+ const content_body = typeof content === "string" ? content : JSON.stringify(content);
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_TRADE_LISTING_RECEIPT_RES, content: content_body, tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
diff --git a/utils-nostr/src/domain/trade/listing/tags.ts b/utils-nostr/src/domain/trade/listing/tags.ts
@@ -0,0 +1,14 @@
+import { TAG_D, TAG_E_PREV, TAG_E_ROOT } from "@radroots/events-bindings";
+import { NostrEventTags } from "../../../types/lib.js";
+
+export const tags_trade_listing_chain = (opts: {
+ e_root: string;
+ d?: string;
+ e_prev?: string;
+}): NostrEventTags => {
+ const tags: NostrEventTags = [];
+ tags.push([TAG_E_ROOT, opts.e_root]);
+ if (opts.e_prev) tags.push([TAG_E_PREV, opts.e_prev]);
+ if (opts.d) tags.push([TAG_D, opts.d]);
+ return tags;
+};
diff --git a/utils-nostr/src/domain/trade/tags.ts b/utils-nostr/src/domain/trade/tags.ts
@@ -0,0 +1,88 @@
+import { JobInputType, RadrootsJobInput } from "@radroots/events-bindings";
+import { tags_job_request, tags_job_result } from "../../events/job/tags.js";
+
+export type CommonRequestOpts = {
+ output?: string;
+ bid_sat?: number;
+ relays?: string[];
+ providers?: string[];
+ topics?: string[];
+ encrypted?: boolean;
+ params?: Array<{ key: string; value: string }>;
+};
+
+export type CommonResultOpts = {
+ request_relay_hint?: string;
+ request_json?: string;
+ customer_pubkey?: string;
+ payment_sat?: number;
+ payment_bolt11?: string;
+ encrypted?: boolean;
+ include_inputs?: string[];
+ chain?: { e_root: string; d?: string; e_prev?: string };
+};
+
+export const make_event_input = (
+ id: string,
+ marker: string,
+ relay?: string
+): RadrootsJobInput => ({
+ data: id,
+ input_type: JobInputType.Event,
+ ...(relay ? { relay } : {}),
+ marker,
+});
+
+export const make_text_input = (
+ payload: unknown,
+ marker: string
+): RadrootsJobInput => ({
+ data: typeof payload === "string" ? payload : JSON.stringify(payload),
+ input_type: JobInputType.Text,
+ marker,
+});
+
+export const build_request_tags = (
+ kind: number,
+ inputs: RadrootsJobInput[],
+ opts?: CommonRequestOpts
+) =>
+ tags_job_request({
+ kind,
+ inputs,
+ output: opts?.output,
+ params: opts?.params ?? [],
+ bid_sat: opts?.bid_sat,
+ relays: opts?.relays ?? [],
+ providers: opts?.providers ?? [],
+ topics: opts?.topics ?? [],
+ encrypted: !!opts?.encrypted,
+ });
+
+export const build_result_tags = (
+ kind: number,
+ request_event_id: string,
+ opts?: CommonResultOpts,
+ extra?: {
+ inputs?: RadrootsJobInput[];
+ payment_sat?: number;
+ payment_bolt11?: string;
+ }
+) =>
+ tags_job_result({
+ kind,
+ request_event: {
+ id: request_event_id,
+ ...(opts?.request_relay_hint ? { relays: opts.request_relay_hint } : {}),
+ },
+ request_json: opts?.request_json,
+ inputs: !opts?.encrypted && extra?.inputs?.length ? extra.inputs : [],
+ customer_pubkey: opts?.customer_pubkey,
+ payment:
+ extra?.payment_sat !== undefined
+ ? { amount_sat: extra.payment_sat, bolt11: extra.payment_bolt11 }
+ : opts?.payment_sat !== undefined
+ ? { amount_sat: opts.payment_sat, bolt11: opts.payment_bolt11 }
+ : undefined,
+ encrypted: !!opts?.encrypted,
+ });
diff --git a/utils-nostr/src/events/comment/lib.ts b/utils-nostr/src/events/comment/lib.ts
@@ -1,8 +1,8 @@
import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
-import { type RadrootsComment, } from "@radroots/radroots-common-bindings";
+import { RadrootsComment } from "@radroots/events-bindings";
import { NDKEventFigure } from "../../types/ndk.js";
-import { tags_comment } from "../../utils/tags.js";
import { ndk_event } from "../lib.js";
+import { tags_comment } from "./tags.js";
export const KIND_RADROOTS_COMMENT = 1111;
export type KindRadrootsComment = typeof KIND_RADROOTS_COMMENT;
diff --git a/utils-nostr/src/events/comment/parse.ts b/utils-nostr/src/events/comment/parse.ts
@@ -1,5 +1,5 @@
import { NDKEvent } from "@nostr-dev-kit/ndk";
-import { type RadrootsComment, radroots_comment_schema } from "@radroots/radroots-common-bindings";
+import { radroots_comment_schema, RadrootsComment } from "@radroots/events-bindings";
import { parse_nostr_event_basis } from "../lib.js";
import { NdkEventBasis } from "../subscription.js";
import { KIND_RADROOTS_COMMENT, type KindRadrootsComment } from "./lib.js";
diff --git a/utils-nostr/src/events/comment/tags.ts b/utils-nostr/src/events/comment/tags.ts
@@ -0,0 +1,37 @@
+import { RadrootsComment } from "@radroots/events-bindings";
+import { NostrEventTags } from "../../types/lib.js";
+
+export const tags_comment = (opts: RadrootsComment): NostrEventTags => {
+ const { root: root_event, parent: parent_event } = opts;
+
+ const root = {
+ kind: root_event.kind.toString(),
+ author: root_event.author,
+ id: root_event.id,
+ d_tag: root_event.d_tag,
+ relays: root_event.relays || [],
+ };
+
+ const parent = (parent_event && parent_event.id)
+ ? {
+ kind: parent_event.kind.toString(),
+ author: parent_event.author,
+ id: parent_event.id,
+ d_tag: parent_event.d_tag,
+ relays: parent_event.relays || [],
+ }
+ : root;
+
+ const tags: NostrEventTags = [
+ ["E", root.id, ...root.relays],
+ ["P", root.author],
+ ["K", root.kind],
+ ...(root.d_tag ? [["A", `${root.kind}:${root.author}:${root.d_tag}`, ...root.relays]] : []),
+ ["e", parent.id, ...parent.relays],
+ ["p", parent.author],
+ ["k", parent.kind],
+ ...(parent.d_tag ? [["a", `${parent.kind}:${parent.author}:${parent.d_tag}`, ...parent.relays]] : []),
+ ];
+
+ return tags;
+};
+\ No newline at end of file
diff --git a/utils-nostr/src/events/follow/lib.ts b/utils-nostr/src/events/follow/lib.ts
@@ -1,8 +1,8 @@
import { NDKEvent } from "@nostr-dev-kit/ndk";
-import { type RadrootsFollow } from "@radroots/radroots-common-bindings";
+import { RadrootsFollow } from "@radroots/events-bindings";
import { NDKEventFigure } from "../../types/ndk.js";
-import { tags_follow_list } from "../../utils/tags.js";
import { ndk_event } from "../lib.js";
+import { tags_follow_list } from "./tags.js";
export const KIND_RADROOTS_FOLLOW = 3;
export type KindRadrootsFollow = typeof KIND_RADROOTS_FOLLOW;
diff --git a/utils-nostr/src/events/follow/parse.ts b/utils-nostr/src/events/follow/parse.ts
@@ -1,5 +1,5 @@
import { NDKEvent } from "@nostr-dev-kit/ndk";
-import { type RadrootsFollow, radroots_follow_schema } from "@radroots/radroots-common-bindings";
+import { RadrootsFollow, radroots_follow_schema } from "@radroots/events-bindings";
import { parse_nostr_event_basis } from "../lib.js";
import { NdkEventBasis } from "../subscription.js";
import { KIND_RADROOTS_FOLLOW, type KindRadrootsFollow } from "./lib.js";
diff --git a/utils-nostr/src/events/follow/tags.ts b/utils-nostr/src/events/follow/tags.ts
@@ -0,0 +1,11 @@
+import { RadrootsFollowProfile } from "@radroots/events-bindings";
+import { NostrEventTags } from "../../types/lib.js";
+
+export const tags_follow_list = (list: RadrootsFollowProfile[]): NostrEventTags => {
+ return list.map(({ public_key, relay_url, contact_name }) => {
+ const entry = [`p`, public_key];
+ if (relay_url) entry.push(relay_url);
+ if (contact_name) entry.push(contact_name);
+ return entry;
+ });
+};
+\ No newline at end of file
diff --git a/utils-nostr/src/events/job/lib.ts b/utils-nostr/src/events/job/lib.ts
@@ -0,0 +1,95 @@
+import { NDKEvent } from "@nostr-dev-kit/ndk";
+import { JobFeedbackStatus, KIND_JOB_FEEDBACK, RadrootsJobFeedback, RadrootsJobRequest, RadrootsJobResult } from "@radroots/events-bindings";
+import { NDKEventFigure } from "../../types/ndk.js";
+import { ndk_event } from "../lib.js";
+import { tags_job_feedback, tags_job_request, tags_job_result } from "./tags.js";
+
+export const ndk_event_job_request = async (opts: NDKEventFigure<{ data: RadrootsJobRequest; }>): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data } = opts;
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: {
+ kind: data.kind,
+ content: "",
+ tags: tags_job_request(data),
+ },
+ });
+};
+
+export const ndk_event_job_result = async (opts: NDKEventFigure<{ data: RadrootsJobResult; }>): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data } = opts;
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: {
+ kind: data.kind,
+ content: data.content || "",
+ tags: tags_job_result(data),
+ },
+ });
+};
+
+export const ndk_event_job_feedback = async (opts: NDKEventFigure<{ data: RadrootsJobFeedback; }>): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data } = opts;
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: {
+ kind: data.kind,
+ content: data.content || "",
+ tags: tags_job_feedback(data),
+ },
+ });
+};
+
+export const ndk_event_job_feedback_todo = async (
+ opts: NDKEventFigure<{
+ request_event_id: string;
+ status:
+ | JobFeedbackStatus
+ | "payment-required"
+ | "processing"
+ | "error"
+ | "success"
+ | "partial";
+ content?: string;
+ options?: {
+ request_relay_hint?: string;
+ extra_info?: string;
+ customer_pubkey?: string;
+ amount_sat?: number;
+ bolt11?: string;
+ encrypted?: boolean;
+ };
+ }>
+): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, request_event_id, status, content, options } = opts;
+
+ const fb: RadrootsJobFeedback = {
+ kind: KIND_JOB_FEEDBACK,
+ status: status as JobFeedbackStatus,
+ extra_info: options?.extra_info,
+ request_event: {
+ id: request_event_id,
+ ...(options?.request_relay_hint ? { relays: options.request_relay_hint } : {}),
+ },
+ customer_pubkey: options?.customer_pubkey,
+ payment:
+ options?.amount_sat !== undefined
+ ? { amount_sat: options.amount_sat, bolt11: options?.bolt11 }
+ : undefined,
+ content,
+ encrypted: !!options?.encrypted,
+ };
+
+ const tags = tags_job_feedback(fb);
+
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: { kind: KIND_JOB_FEEDBACK, content: content ?? "", tags },
+ client: opts.client,
+ date_published: opts.date_published,
+ });
+};
+\ No newline at end of file
diff --git a/utils-nostr/src/events/job/tags.ts b/utils-nostr/src/events/job/tags.ts
@@ -0,0 +1,75 @@
+import { RadrootsJobFeedback, RadrootsJobInput, RadrootsJobRequest, RadrootsJobResult } from "@radroots/events-bindings";
+import { NostrEventTag, NostrEventTags } from "../../types/lib.js";
+
+export const tag_job_input = (input: RadrootsJobInput): NostrEventTag => {
+ const t: NostrEventTag = ["i", input.data, input.input_type];
+ if (input.relay) t.push(input.relay);
+ if (input.marker) t.push(input.marker);
+ return t;
+};
+
+export const tag_job_output = (mime: string): NostrEventTag => ["output", mime];
+
+export const tag_job_param = (key: string, value: string): NostrEventTag => ["param", key, value];
+
+export const tag_job_bid = (sat: number): NostrEventTag => ["bid", String(sat)];
+
+export const tags_job_relays = (relays: string[]): NostrEventTags =>
+ relays.map(r => ["relays", r]);
+
+export const tags_job_providers = (pubkeys: string[]): NostrEventTags =>
+ pubkeys.map(p => ["p", p]);
+
+export const tags_job_topics = (topics: string[]): NostrEventTags =>
+ topics.map(t => ["t", t]);
+
+export const tag_job_amount = (msat: number, bolt11?: string): NostrEventTag =>
+ bolt11 ? ["amount", String(msat), bolt11] : ["amount", String(msat)];
+
+export const tag_job_encrypted = (): NostrEventTag => ["encrypted"];
+
+export const tags_job_request = (opts: RadrootsJobRequest): NostrEventTags => {
+ const tags: NostrEventTags = [];
+ for (const input of opts.inputs) tags.push(tag_job_input(input));
+ if (opts.output) tags.push(tag_job_output(opts.output));
+ if (opts.params) for (const p of opts.params) tags.push(tag_job_param(p.key, p.value));
+ if (typeof opts.bid_sat === "number") tags.push(tag_job_bid(opts.bid_sat));
+ if (opts.relays?.length) tags.push(...tags_job_relays(opts.relays));
+ if (opts.providers?.length) tags.push(...tags_job_providers(opts.providers));
+ if (opts.topics?.length) tags.push(...tags_job_topics(opts.topics));
+ if (opts.encrypted) tags.push(tag_job_encrypted());
+ return tags;
+};
+
+export const tags_job_result = (opts: RadrootsJobResult): NostrEventTags => {
+ const tags: NostrEventTags = [];
+ const event_tag: NostrEventTag = ["e", opts.request_event.id];
+ if (opts.request_event.relays) event_tag.push(opts.request_event.relays);
+ tags.push(event_tag);
+ if (opts.request_json) tags.push(["request", opts.request_json]);
+ if (!opts.encrypted && opts.inputs?.length) for (const input of opts.inputs) tags.push(tag_job_input(input));
+ if (opts.customer_pubkey) tags.push(["p", opts.customer_pubkey]);
+ if (opts.payment?.amount_sat !== undefined) {
+ const msat = Math.round(Number(opts.payment.amount_sat) * 1000);
+ tags.push(tag_job_amount(msat, opts.payment.bolt11));
+ }
+ if (opts.encrypted) tags.push(tag_job_encrypted());
+ return tags;
+}
+
+export const tags_job_feedback = (opts: RadrootsJobFeedback): NostrEventTags => {
+ const tags: NostrEventTags = [];
+ const status_tag: NostrEventTag = ["status", String(opts.status)];
+ if (opts.extra_info) status_tag.push(opts.extra_info);
+ tags.push(status_tag);
+ if (opts.payment?.amount_sat !== undefined) {
+ const msat = Math.round(Number(opts.payment.amount_sat) * 1000);
+ tags.push(tag_job_amount(msat, opts.payment.bolt11));
+ }
+ const event_tag: NostrEventTag = ["e", opts.request_event.id];
+ if (opts.request_event.relays) event_tag.push(opts.request_event.relays);
+ tags.push(event_tag);
+ if (opts.customer_pubkey) tags.push(["p", opts.customer_pubkey]);
+ if (opts.encrypted) tags.push(tag_job_encrypted());
+ return tags;
+}
+\ No newline at end of file
diff --git a/utils-nostr/src/events/job/utils.ts b/utils-nostr/src/events/job/utils.ts
@@ -0,0 +1,34 @@
+import { JobInputType, KIND_JOB_FEEDBACK } from "@radroots/events-bindings";
+import { TradeListingStage } from "@radroots/trade-bindings";
+import {
+ REQUEST_KINDS,
+ RESULT_KINDS,
+} from "../../domain/trade/lib.js";
+import type { NostrEventTags } from "../../types/lib.js";
+
+export function get_job_input_data_for_marker(
+ tags: NostrEventTags,
+ marker: string,
+ input_type: JobInputType = JobInputType.Event
+): string | undefined {
+ for (const t of tags) {
+ if (t[0] !== "i") continue;
+ if (t[2] !== input_type) continue;
+ const tag_marker = t.length >= 5 ? t[4] : t.length >= 4 ? t[3] : undefined;
+ if (tag_marker === marker) return t[1];
+ }
+ return undefined;
+}
+
+export function get_trade_listing_stage_from_event_kind(
+ kind: number
+): TradeListingStage | undefined {
+ for (const key of Object.keys(REQUEST_KINDS) as TradeListingStage[]) {
+ if (REQUEST_KINDS[key] === kind) return key;
+ }
+ for (const key of Object.keys(RESULT_KINDS) as TradeListingStage[]) {
+ if (RESULT_KINDS[key] === kind) return key;
+ }
+ if (kind === KIND_JOB_FEEDBACK) return TradeListingStage.Order;
+ return undefined;
+}
diff --git a/utils-nostr/src/events/listing/lib.ts b/utils-nostr/src/events/listing/lib.ts
@@ -1,8 +1,8 @@
import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
-import { type RadrootsListing } from "@radroots/radroots-common-bindings";
+import { type RadrootsListing } from "@radroots/events-bindings";
import { NDKEventFigure } from "../../types/ndk.js";
-import { tags_classified } from "../../utils/tags.js";
import { ndk_event } from "../lib.js";
+import { tags_listing } from "./tags.js";
export const KIND_RADROOTS_LISTING = 30402;
export type KindRadrootsListing = typeof KIND_RADROOTS_LISTING;
@@ -15,7 +15,7 @@ export const ndk_event_classified = async (opts: NDKEventFigure<{ data: Radroots
basis: {
kind: NDKKind.Classified,
content: ``,
- tags: tags_classified(data),
+ tags: tags_listing(data),
},
});
};
\ No newline at end of file
diff --git a/utils-nostr/src/events/listing/parse.ts b/utils-nostr/src/events/listing/parse.ts
@@ -1,5 +1,5 @@
import { NDKEvent } from "@nostr-dev-kit/ndk";
-import { type RadrootsListing, radroots_listing_location_schema, radroots_listing_price_schema, radroots_listing_product_schema, radroots_listing_quantity_schema, radroots_listing_schema } from "@radroots/radroots-common-bindings";
+import { type RadrootsListing, radroots_listing_location_schema, radroots_listing_price_schema, radroots_listing_product_schema, radroots_listing_quantity_schema, radroots_listing_schema } from "@radroots/events-bindings";
import { get_event_tag, get_event_tags, parse_nostr_event_basis } from "../lib.js";
import { NdkEventBasis } from "../subscription.js";
import { KIND_RADROOTS_LISTING, type KindRadrootsListing } from "./lib.js";
diff --git a/utils-nostr/src/events/listing/tags.ts b/utils-nostr/src/events/listing/tags.ts
@@ -0,0 +1,67 @@
+import { RadrootsListingDiscount, RadrootsListingPrice, RadrootsListingQuantity, type RadrootsListing } from "@radroots/events-bindings";
+import ngeotags, { type InputData as NostrGeotagsInputData } from "nostr-geotags";
+import { NostrEventTag, NostrEventTagImage, NostrEventTagLocation, NostrEventTags } from "../../types/lib.js";
+
+const tags_map = (tag: any[]) => tag.map(i => String(i).toLowerCase());
+
+export const tag_listing_quantity = (opts: RadrootsListingQuantity): NostrEventTag => {
+ const tag = [`quantity`, opts.value.amount, opts.value.unit];
+ if (opts.label) tag.push(opts.label);
+ return tags_map(tag);
+};
+
+export const tag_listing_price = (price: RadrootsListingPrice): NostrEventTag => {
+ const tag = [`price`, price.amount, price.amount.amount, price.quantity.amount, price.quantity.unit, price.quantity.label || ``];
+ return tags_map(tag);
+};
+
+export const tag_listing_price_discount = (discount: RadrootsListingDiscount): NostrEventTag => {
+ const tag = [`price-discount-${Object.keys(discount)[0]}`];
+ for (const [key, value] of Object.entries(discount.amount)) tag.push(`${key}:${value}`);
+ return tags_map(tag);
+};
+
+export const tag_listing_location = (opts: NostrEventTagLocation): NostrEventTag => {
+ if (!opts.primary) return [];
+ const tag = [`location`, opts.primary];
+ if (opts.city) tag.push(opts.city);
+ if (opts.region) tag.push(opts.region);
+ if (opts.country) tag.push(opts.country);
+ return tag;
+};
+
+export const tags_listing_location_geotags = (opts: NostrEventTagLocation): NostrEventTags => {
+ const { lat, lng: lon, city, region: regionName, country } = opts;
+ const country_raw = country || ``;
+ const countryCode = country_raw && country_raw?.length <= 3 ? country_raw : undefined;
+ const countryName = country_raw && country_raw?.length > 3 ? country_raw : undefined;
+ return ngeotags({ lat, lon, city, regionName, countryCode, countryName } satisfies NostrGeotagsInputData, { geohash: true, gps: true, city: true, iso31662: true });
+};
+
+
+export const tag_listing_image = (opts: NostrEventTagImage): NostrEventTag => {
+ const tag = [`image`, opts.url];
+ if (opts.size) tag.push(`${opts.size.w}x${opts.size.h}`)
+ return tag;
+};
+
+export const tags_listing = (opts: RadrootsListing): NostrEventTags => {
+ const { d_tag, product, quantities, prices } = opts;
+ const tags: NostrEventTags = [[`d`, d_tag]];
+ for (const [k, v] of Object.entries(product)) if (v) tags.push([k, v]);
+ for (const quantity of quantities) {
+ tags.push(tag_listing_quantity(quantity));
+ }
+ for (const price of prices) {
+ tags.push(tag_listing_price(price));
+ }
+ for (const discount of opts.discounts || []) {
+ tags.push(tag_listing_price_discount(discount));
+ }
+ if (opts.location) {
+ tags.push(tag_listing_location(opts.location));
+ tags.push(...tags_listing_location_geotags(opts.location));
+ }
+ if (opts.images) for (const image_tags of opts.images) tags.push(tag_listing_image(image_tags));
+ return tags;
+};
+\ No newline at end of file
diff --git a/utils-nostr/src/events/profile/lib.ts b/utils-nostr/src/events/profile/lib.ts
@@ -1,5 +1,5 @@
import { NDKEvent } from "@nostr-dev-kit/ndk";
-import { RadrootsProfile } from "@radroots/radroots-common-bindings";
+import { type RadrootsProfile } from "@radroots/events-bindings";
import { NDKEventFigure } from "../../types/ndk.js";
import { ndk_event } from "../lib.js";
diff --git a/utils-nostr/src/events/profile/parse.ts b/utils-nostr/src/events/profile/parse.ts
@@ -1,5 +1,5 @@
import { NDKEvent } from "@nostr-dev-kit/ndk";
-import { type RadrootsProfile, radroots_profile_schema } from "@radroots/radroots-common-bindings";
+import { type RadrootsProfile, radroots_profile_schema } from "@radroots/events-bindings";
import { parse_nostr_event_basis } from "../lib.js";
import { NdkEventBasis } from "../subscription.js";
import { KIND_RADROOTS_PROFILE, type KindRadrootsProfile } from "./lib.js";
diff --git a/utils-nostr/src/events/reaction/lib.ts b/utils-nostr/src/events/reaction/lib.ts
@@ -1,8 +1,8 @@
import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
-import { type RadrootsReaction, } from "@radroots/radroots-common-bindings";
+import { RadrootsReaction } from "@radroots/events-bindings";
import { NDKEventFigure } from "../../types/ndk.js";
-import { tags_reaction } from "../../utils/tags.js";
import { ndk_event } from "../lib.js";
+import { tags_reaction } from "./tags.js";
export const KIND_RADROOTS_REACTION = 7;
export type KindRadrootsReaction = typeof KIND_RADROOTS_REACTION;
diff --git a/utils-nostr/src/events/reaction/parse.ts b/utils-nostr/src/events/reaction/parse.ts
@@ -1,5 +1,5 @@
import { NDKEvent } from "@nostr-dev-kit/ndk";
-import { type RadrootsReaction, radroots_reaction_schema } from "@radroots/radroots-common-bindings";
+import { RadrootsReaction, radroots_reaction_schema } from "@radroots/events-bindings";
import { parse_nostr_event_basis } from "../lib.js";
import { NdkEventBasis } from "../subscription.js";
import { KIND_RADROOTS_REACTION, type KindRadrootsReaction } from "./lib.js";
diff --git a/utils-nostr/src/events/reaction/tags.ts b/utils-nostr/src/events/reaction/tags.ts
@@ -0,0 +1,15 @@
+import { RadrootsReaction } from "@radroots/events-bindings";
+import { NostrEventTags } from "../../types/lib.js";
+
+export const tags_reaction = (opts: RadrootsReaction): NostrEventTags => {
+ const { root } = opts;
+ const ref_kind = root.kind.toString();
+ const ref_author = root.author;
+ const tags: NostrEventTags = [
+ [`e`, root.id, ...root.relays || ``],
+ [`p`, ref_author],
+ [`k`, ref_kind],
+ ];
+ if (root.d_tag) tags.push([`a`, `${ref_kind}:${ref_author}:${root.d_tag}`, ...root.relays || ``])
+ return tags;
+};
+\ No newline at end of file
diff --git a/utils-nostr/src/index.ts b/utils-nostr/src/index.ts
@@ -1,14 +1,31 @@
+export * from "./domain/trade/lib.js"
+export * from "./domain/trade/listing/accept/lib.js"
+export * from "./domain/trade/listing/conveyance/lib.js"
+export * from "./domain/trade/listing/fulfillment/lib.js"
+export * from "./domain/trade/listing/invoice/lib.js"
+export * from "./domain/trade/listing/order/lib.js"
+export * from "./domain/trade/listing/payment/lib.js"
+export * from "./domain/trade/listing/receipt/lib.js"
+export * from "./domain/trade/listing/tags.js"
+export * from "./domain/trade/tags.js"
export * from "./events/comment/lib.js"
export * from "./events/comment/parse.js"
+export * from "./events/comment/tags.js"
export * from "./events/follow/lib.js"
export * from "./events/follow/parse.js"
+export * from "./events/follow/tags.js"
+export * from "./events/job/lib.js"
+export * from "./events/job/tags.js"
+export * from "./events/job/utils.js"
export * from "./events/lib.js"
export * from "./events/listing/lib.js"
export * from "./events/listing/parse.js"
+export * from "./events/listing/tags.js"
export * from "./events/profile/lib.js"
export * from "./events/profile/parse.js"
export * from "./events/reaction/lib.js"
export * from "./events/reaction/parse.js"
+export * from "./events/reaction/tags.js"
export * from "./events/subscription.js"
export * from "./keys/lib.js"
export * from "./relay/lib.js"
diff --git a/utils-nostr/src/types/lib.ts b/utils-nostr/src/types/lib.ts
@@ -12,20 +12,7 @@ export type NostrEventTagClient = {
relay: string;
};
-export type NostrEventTagQuantity = {
- amt: string;
- unit: string;
- label?: string;
-};
-
-export type NostrEventTagPrice = {
- amt: string;
- currency: string;
- qty_amt: string;
- qty_unit: string;
- qty_key: string;
-};
-
+/*
export type NostrEventTagPriceDiscount = (
{
quantity: {
@@ -60,6 +47,7 @@ export type NostrEventTagPriceDiscount = (
}
}
);
+*/
export type NostrEventTagLocation = {
primary: string;
diff --git a/utils-nostr/src/utils/tags.ts b/utils-nostr/src/utils/tags.ts
@@ -1,6 +1,7 @@
-import { RadrootsComment, RadrootsFollowProfile, RadrootsListing, RadrootsReaction, } from "@radroots/radroots-common-bindings";
-import ngeotags, { type InputData as NostrGeotagsInputData } from "nostr-geotags";
-import { NostrEventTag, NostrEventTagClient, NostrEventTagImage, NostrEventTagLocation, NostrEventTagPrice, NostrEventTagPriceDiscount, NostrEventTagQuantity, NostrEventTags } from "../types/lib.js";
+import { NostrEventTag, NostrEventTagClient } from "../types/lib.js";
+
+export const TAG_E = 'e';
+export const TAG_I = 'i';
export const tag_client = (opts: NostrEventTagClient, d_tag?: string): NostrEventTag => {
const tag = [`client`, opts.name];
@@ -8,125 +9,3 @@ export const tag_client = (opts: NostrEventTagClient, d_tag?: string): NostrEven
tag.push(opts.relay);
return tag;
};
-
-export const tag_classified_quantity = (opts: NostrEventTagQuantity): NostrEventTag => {
- const tag = [`quantity`, opts.amt, opts.unit];
- if (opts.label) tag.push(opts.label);
- return tag.map(i => i.toLowerCase());
-};
-
-export const tag_classified_price = (price: NostrEventTagPrice): NostrEventTag => {
- const tag = [`price`, price.amt, price.currency, price.qty_amt, price.qty_unit, price.qty_key];
- return tag.map(i => i.toLowerCase());
-};
-
-export const tag_classified_price_discount = (discount: NostrEventTagPriceDiscount): NostrEventTag => {
- const tag = [`price-discount-${Object.keys(discount)[0]}`];
- if (`mass` in discount) tag.push(...Object.values(discount.mass));
- else if (`quantity` in discount) tag.push(...Object.values(discount.quantity));
- else if (`subtotal` in discount) tag.push(...Object.values(discount.subtotal));
- else if (`total` in discount) tag.push(...Object.values(discount.total));
- return tag.map(i => i.toLowerCase());
-};
-
-export const tag_classified_location = (opts: NostrEventTagLocation): NostrEventTag => {
- if (!opts.primary) return [];
- const tag = [`location`, opts.primary];
- if (opts.city) tag.push(opts.city);
- if (opts.region) tag.push(opts.region);
- if (opts.country) tag.push(opts.country);
- return tag;
-};
-
-export const tags_classified_location_geotags = (opts: NostrEventTagLocation): NostrEventTags => {
- const { lat, lng: lon, city, region: regionName, country } = opts;
- const country_raw = country || ``;
- const countryCode = country_raw && country_raw?.length <= 3 ? country_raw : undefined;
- const countryName = country_raw && country_raw?.length > 3 ? country_raw : undefined;
- return ngeotags({ lat, lon, city, regionName, countryCode, countryName } satisfies NostrGeotagsInputData, { geohash: true, gps: true, city: true, iso31662: true });
-};
-
-
-export const tag_classified_image = (opts: NostrEventTagImage): NostrEventTag => {
- const tag = [`image`, opts.url];
- if (opts.size) tag.push(`${opts.size.w}x${opts.size.h}`)
- return tag;
-};
-
-export const tags_classified = (opts: RadrootsListing): NostrEventTags => {
- const { d_tag, product, quantities, prices } = opts;
- const tags: NostrEventTags = [[`d`, d_tag]];
- for (const [k, v] of Object.entries(product)) if (v) tags.push([k, v]);
- for (const quantity of quantities) {
- tags.push(tag_classified_quantity(quantity));
- }
- for (const price of prices) {
- tags.push(tag_classified_price(price));
- }
- for (const discount of opts.discounts || []) {
- tags.push(tag_classified_price_discount(discount));
- }
- if (opts.location) {
- tags.push(tag_classified_location(opts.location));
- tags.push(...tags_classified_location_geotags(opts.location));
- }
- if (opts.images) for (const image_tags of opts.images) tags.push(tag_classified_image(image_tags));
- return tags;
-};
-
-export const tags_comment = (opts: RadrootsComment): NostrEventTags => {
- const { root: root_event, parent: parent_event } = opts;
-
- const root = {
- kind: root_event.kind.toString(),
- author: root_event.author,
- id: root_event.id,
- d_tag: root_event.d_tag,
- relays: root_event.relays || [],
- };
-
- const parent = (parent_event && parent_event.id)
- ? {
- kind: parent_event.kind.toString(),
- author: parent_event.author,
- id: parent_event.id,
- d_tag: parent_event.d_tag,
- relays: parent_event.relays || [],
- }
- : root;
-
- const tags: NostrEventTags = [
- ["E", root.id, ...root.relays],
- ["P", root.author],
- ["K", root.kind],
- ...(root.d_tag ? [["A", `${root.kind}:${root.author}:${root.d_tag}`, ...root.relays]] : []),
- ["e", parent.id, ...parent.relays],
- ["p", parent.author],
- ["k", parent.kind],
- ...(parent.d_tag ? [["a", `${parent.kind}:${parent.author}:${parent.d_tag}`, ...parent.relays]] : []),
- ];
-
- return tags;
-};
-
-export const tags_reaction = (opts: RadrootsReaction): NostrEventTags => {
- const { root } = opts;
- const ref_kind = root.kind.toString();
- const ref_author = root.author;
- const tags: NostrEventTags = [
- [`e`, root.id, ...root.relays || ``],
- [`p`, ref_author],
- [`k`, ref_kind],
- ];
- if (root.d_tag) tags.push([`a`, `${ref_kind}:${ref_author}:${root.d_tag}`, ...root.relays || ``])
- return tags;
-};
-
-export const tags_follow_list = (list: RadrootsFollowProfile[]): NostrEventTags => {
- return list.map(({ public_key, relay_url, contact_name }) => {
- const entry = [`p`, public_key];
- if (relay_url) entry.push(relay_url);
- if (contact_name) entry.push(contact_name);
- return entry;
- });
-};
-\ No newline at end of file