SkateSpots/src/hooks/useTradeAttestations.test.ts
SkateSpots 883338f060 feat(marketplace): mutual trade attestations + reputation (kind 31871)
Built on the Attestations NIP (31871); a listing is the Assertion Event:
- Seller 'Mark as sold' now opens a dialog (buyer npub + self-reported method +
  optional amount) that marks the listing sold AND publishes a trade attestation
- Buyer sees 'Confirm this trade' on the listing and publishes the mirror
  attestation -> mutual pair = a verified trade
- useTradeReputation aggregates sales/purchases/verified + counterparties
- Profile 'Trades' card; seller 'N verified trades' badge on listing cards
- NIP.md documents kind 31871 usage + our p/method/amount extensions
Payment method is self-reported metadata, never proof of payment.
2026-09-26 20:17:38 +07:00

58 lines
2 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import type { NostrEvent } from '@nostrify/nostrify';
import { parseListingCoord, isTradeAttestation, TRADE_ATTESTATION_KIND } from './useTradeAttestations';
function ev(partial: Partial<NostrEvent> & Pick<NostrEvent, 'kind' | 'pubkey' | 'id'>): NostrEvent {
return { content: '', created_at: 0, sig: '', tags: [], ...partial } as NostrEvent;
}
describe('parseListingCoord', () => {
it('parses a 30402 coordinate', () => {
expect(parseListingCoord('30402:abc123:my-listing')).toEqual({
kind: 30402,
pubkey: 'abc123',
identifier: 'my-listing',
});
});
it('keeps colons that are part of the identifier', () => {
expect(parseListingCoord('30402:abc123:slug:part2')?.identifier).toBe('slug:part2');
});
it('returns null for missing or malformed coords', () => {
expect(parseListingCoord(undefined)).toBeNull();
expect(parseListingCoord('nope')).toBeNull();
expect(parseListingCoord('30402:onlypubkey')).toBeNull();
});
});
describe('isTradeAttestation', () => {
it('accepts a 31871 attestation of a 30402 listing with a counterparty', () => {
const e = ev({
kind: TRADE_ATTESTATION_KIND,
pubkey: 'seller',
id: 'a1',
tags: [['a', '30402:seller:deck'], ['p', 'buyer'], ['s', 'valid']],
});
expect(isTradeAttestation(e)).toBe(true);
});
it('rejects an attestation without a counterparty', () => {
const e = ev({
kind: TRADE_ATTESTATION_KIND,
pubkey: 'x',
id: 'a2',
tags: [['a', '30402:x:y'], ['s', 'valid']],
});
expect(isTradeAttestation(e)).toBe(false);
});
it('rejects non-listing assertions and other kinds', () => {
expect(
isTradeAttestation(ev({ kind: TRADE_ATTESTATION_KIND, pubkey: 'x', id: 'a3', tags: [['a', '35000:x:y'], ['p', 'z']] })),
).toBe(false);
expect(
isTradeAttestation(ev({ kind: 1, pubkey: 'x', id: 'a4', tags: [['a', '30402:x:y'], ['p', 'z']] })),
).toBe(false);
});
});