nostr-attestations 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -6
- package/dist/builders.d.ts +5 -0
- package/dist/builders.d.ts.map +1 -1
- package/dist/builders.js +94 -16
- package/dist/builders.js.map +1 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -1
- package/dist/filters.d.ts +11 -0
- package/dist/filters.d.ts.map +1 -1
- package/dist/filters.js +28 -7
- package/dist/filters.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/parsers.d.ts +2 -0
- package/dist/parsers.d.ts.map +1 -1
- package/dist/parsers.js +21 -3
- package/dist/parsers.js.map +1 -1
- package/dist/types.d.ts +43 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +74 -8
- package/dist/validators.js.map +1 -1
- package/package.json +4 -1
- package/vectors/attestations.json +480 -10
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# nostr-attestations
|
|
2
2
|
|
|
3
|
-
One Nostr event kind for all attestations — credentials, endorsements, vouches, provenance, licensing, and trust.
|
|
3
|
+
One Nostr event kind for all attestations — credentials, endorsements, vouches, provenance, licensing, and trust. Supports both direct attestation and assertion-first patterns within a single kind.
|
|
4
4
|
|
|
5
5
|
**Nostr:** [`npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2`](https://njump.me/npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2)
|
|
6
6
|
|
|
@@ -31,12 +31,34 @@ const event = createAttestation({
|
|
|
31
31
|
|
|
32
32
|
No relay client, no signing library, no crypto. Bring your own. Works with nostr-tools, any Nostr SDK, or bare WebSocket code.
|
|
33
33
|
|
|
34
|
+
### Assertion-First Pattern
|
|
35
|
+
|
|
36
|
+
Attest to someone else's claim — the individual makes an assertion, you verify it:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { createAttestation } from 'nostr-attestations'
|
|
40
|
+
|
|
41
|
+
// Attest to a first-person assertion event
|
|
42
|
+
const event = createAttestation({
|
|
43
|
+
assertion: { id: '<assertion-event-id>', relay: 'wss://relay.example.com' },
|
|
44
|
+
subject: '<subject-pubkey>',
|
|
45
|
+
content: 'Identity verified in person',
|
|
46
|
+
})
|
|
47
|
+
// type is inferred from the referenced assertion — no type tag needed
|
|
48
|
+
```
|
|
49
|
+
|
|
34
50
|
## Why This?
|
|
35
51
|
|
|
36
52
|
Nostr has several ways to label or badge identities, but none designed for verifiable attestations. [NIP-58](https://github.com/nostr-protocol/nips/blob/master/58.md) badges are display-only — no expiry, no revocation, no structured claims. [NIP-85](https://github.com/nostr-protocol/nips/blob/master/85.md) covers social graph metrics, not arbitrary claims. [NIP-32](https://github.com/nostr-protocol/nips/blob/master/32.md) labels are lightweight but not individually replaceable per subject.
|
|
37
53
|
|
|
38
54
|
nostr-attestations uses **one kind (31000) with a `type` tag** instead of inventing a new event kind for every attestation use case. Credentials, endorsements, vouches, licensing, provenance, and revocations all share the same event structure. New attestation types need zero protocol changes — just define a new `type` value.
|
|
39
55
|
|
|
56
|
+
It supports two attestation patterns within the same kind:
|
|
57
|
+
- **Direct attestation** — the attestor defines the type and makes a claim about a subject
|
|
58
|
+
- **Assertion-first** — the subject makes their own claim, and the attestor references and verifies it
|
|
59
|
+
|
|
60
|
+
The base layer is **semantically neutral** — it carries attestations but does not interpret them. Application profiles (identity verification, professional licensing, service reputation) are built downstream, not in the library.
|
|
61
|
+
|
|
40
62
|
## Revocation
|
|
41
63
|
|
|
42
64
|
```typescript
|
|
@@ -64,13 +86,20 @@ import { parseAttestation } from 'nostr-attestations'
|
|
|
64
86
|
const attestation = parseAttestation(event)
|
|
65
87
|
// {
|
|
66
88
|
// kind: 31000,
|
|
67
|
-
// type: 'credential',
|
|
89
|
+
// type: 'credential', // "assertion" for assertion-only attestations
|
|
68
90
|
// pubkey: '<attestor-pubkey>',
|
|
69
91
|
// createdAt: 1700000000,
|
|
70
92
|
// identifier: '<subject-pubkey>',
|
|
71
93
|
// subject: '<subject-pubkey>',
|
|
94
|
+
// assertionId: null, // event ID if assertion-first
|
|
95
|
+
// assertionAddress: null, // addressable coord if assertion-first
|
|
96
|
+
// assertionRelay: null, // relay hint for assertion
|
|
72
97
|
// summary: 'Professional credential verified',
|
|
73
98
|
// expiration: 1735689600,
|
|
99
|
+
// validFrom: null,
|
|
100
|
+
// validTo: null, // validity window end
|
|
101
|
+
// request: null, // what prompted this attestation
|
|
102
|
+
// schema: null, // machine-readable schema URI
|
|
74
103
|
// revoked: false,
|
|
75
104
|
// reason: null,
|
|
76
105
|
// tags: [...],
|
|
@@ -105,9 +134,10 @@ const attestation = parseAttestation(event)
|
|
|
105
134
|
| Function | Signature | Returns |
|
|
106
135
|
|----------|-----------|---------|
|
|
107
136
|
| `attestationFilter` | `(params: FilterParams) => NostrFilter` | Relay query filter |
|
|
108
|
-
| `revocationFilter` | `(type
|
|
137
|
+
| `revocationFilter` | `(type, identifier)` or `({ assertionId \| assertionAddress })` | Revocation check filter |
|
|
109
138
|
| `buildDTag` | `(type: string, identifier: string) => string` | `"type:identifier"` string |
|
|
110
|
-
| `
|
|
139
|
+
| `buildAssertionDTag` | `(ref: string) => string` | `"assertion:ref"` string |
|
|
140
|
+
| `parseDTag` | `(dTag: string) => { type: string; identifier: string } \| null` | Parsed d-tag (type is `"assertion"` for assertion-only) |
|
|
111
141
|
|
|
112
142
|
### Constants
|
|
113
143
|
|
|
@@ -118,11 +148,11 @@ const attestation = parseAttestation(event)
|
|
|
118
148
|
|
|
119
149
|
### Types
|
|
120
150
|
|
|
121
|
-
`AttestationParams`, `RevocationParams`, `Attestation`, `ValidationResult`, `FilterParams`, `NostrFilter`, `NostrEvent`, `EventTemplate` — all exported from the package root.
|
|
151
|
+
`AssertionRef`, `AttestationParams`, `RevocationParams`, `Attestation`, `ValidationResult`, `FilterParams`, `NostrFilter`, `NostrEvent`, `EventTemplate` — all exported from the package root and from `nostr-attestations/types` (zero-runtime import).
|
|
122
152
|
|
|
123
153
|
## Test Vectors
|
|
124
154
|
|
|
125
|
-
`vectors/attestations.json` contains
|
|
155
|
+
`vectors/attestations.json` contains 16 frozen conformance test vectors covering the full range of attestation types (credential, endorsement, vouch, verifier, provenance) and states (active, revoked, self-attestation). Any conformant implementation must produce identical parse results from these inputs. The vectors are pinned — if tests against them fail, the implementation is broken, not the vector.
|
|
126
156
|
|
|
127
157
|
## Attested on Nostr
|
|
128
158
|
|
package/dist/builders.d.ts
CHANGED
|
@@ -2,11 +2,16 @@ import type { AttestationParams, RevocationParams, EventTemplate } from './types
|
|
|
2
2
|
/**
|
|
3
3
|
* Create an unsigned attestation event template.
|
|
4
4
|
* The caller is responsible for signing (adding pubkey, id, sig, created_at).
|
|
5
|
+
*
|
|
6
|
+
* At least one of `type` or `assertion` must be provided.
|
|
5
7
|
*/
|
|
6
8
|
export declare function createAttestation(params: AttestationParams): EventTemplate;
|
|
7
9
|
/**
|
|
8
10
|
* Create an unsigned revocation event template.
|
|
9
11
|
* When published, this replaces the original attestation via addressable event semantics.
|
|
12
|
+
*
|
|
13
|
+
* For typed attestations: provide `type` + `identifier`.
|
|
14
|
+
* For assertion-only attestations: provide `assertionId` or `assertionAddress`.
|
|
10
15
|
*/
|
|
11
16
|
export declare function createRevocation(params: RevocationParams): EventTemplate;
|
|
12
17
|
//# sourceMappingURL=builders.d.ts.map
|
package/dist/builders.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAEpF
|
|
1
|
+
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAEpF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,aAAa,CAyG1E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,CA0CxE"}
|
package/dist/builders.js
CHANGED
|
@@ -1,27 +1,80 @@
|
|
|
1
1
|
import { ATTESTATION_KIND } from './constants.js';
|
|
2
|
-
import { buildDTag } from './filters.js';
|
|
2
|
+
import { buildDTag, buildAssertionDTag } from './filters.js';
|
|
3
3
|
/**
|
|
4
4
|
* Create an unsigned attestation event template.
|
|
5
5
|
* The caller is responsible for signing (adding pubkey, id, sig, created_at).
|
|
6
|
+
*
|
|
7
|
+
* At least one of `type` or `assertion` must be provided.
|
|
6
8
|
*/
|
|
7
9
|
export function createAttestation(params) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (
|
|
11
|
-
throw new Error('type must
|
|
10
|
+
const hasType = !!params.type;
|
|
11
|
+
const hasAssertion = !!params.assertion;
|
|
12
|
+
if (!hasType && !hasAssertion) {
|
|
13
|
+
throw new Error('at least one of type or assertion must be provided');
|
|
14
|
+
}
|
|
15
|
+
if (hasType) {
|
|
16
|
+
if (params.type.includes(':'))
|
|
17
|
+
throw new Error('type must not contain colons');
|
|
18
|
+
}
|
|
19
|
+
if (hasAssertion) {
|
|
20
|
+
const a = params.assertion;
|
|
21
|
+
if (a.id && a.address)
|
|
22
|
+
throw new Error('assertion must have id or address, not both');
|
|
23
|
+
if (!a.id && !a.address)
|
|
24
|
+
throw new Error('assertion must have id or address');
|
|
25
|
+
}
|
|
26
|
+
if (params.validTo != null) {
|
|
27
|
+
if (!Number.isFinite(params.validTo))
|
|
28
|
+
throw new Error('validTo must be a finite number');
|
|
29
|
+
if (params.validFrom != null && params.validTo <= params.validFrom) {
|
|
30
|
+
throw new Error('validTo must be greater than validFrom');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (params.schema != null && !params.schema.trim()) {
|
|
34
|
+
throw new Error('schema must not be empty');
|
|
35
|
+
}
|
|
12
36
|
const tags = [];
|
|
13
|
-
// d-tag
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
37
|
+
// d-tag construction
|
|
38
|
+
if (hasType) {
|
|
39
|
+
const identifier = params.identifier ?? params.subject;
|
|
40
|
+
if (identifier) {
|
|
41
|
+
tags.push(['d', buildDTag(params.type, identifier)]);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
tags.push(['d', params.type]);
|
|
45
|
+
}
|
|
46
|
+
tags.push(['type', params.type]);
|
|
17
47
|
}
|
|
18
48
|
else {
|
|
19
|
-
|
|
49
|
+
// assertion-only: d-tag uses assertion: prefix
|
|
50
|
+
const ref = params.assertion.id ?? params.assertion.address;
|
|
51
|
+
tags.push(['d', buildAssertionDTag(ref)]);
|
|
20
52
|
}
|
|
21
|
-
tags.push(['type', params.type]);
|
|
22
53
|
if (params.subject) {
|
|
23
54
|
tags.push(['p', params.subject]);
|
|
24
55
|
}
|
|
56
|
+
// Assertion reference tags
|
|
57
|
+
if (hasAssertion) {
|
|
58
|
+
const a = params.assertion;
|
|
59
|
+
if (a.id) {
|
|
60
|
+
const eTag = ['e', a.id];
|
|
61
|
+
if (a.relay)
|
|
62
|
+
eTag.push(a.relay);
|
|
63
|
+
else
|
|
64
|
+
eTag.push('');
|
|
65
|
+
eTag.push('assertion');
|
|
66
|
+
tags.push(eTag);
|
|
67
|
+
}
|
|
68
|
+
else if (a.address) {
|
|
69
|
+
const aTag = ['a', a.address];
|
|
70
|
+
if (a.relay)
|
|
71
|
+
aTag.push(a.relay);
|
|
72
|
+
else
|
|
73
|
+
aTag.push('');
|
|
74
|
+
aTag.push('assertion');
|
|
75
|
+
tags.push(aTag);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
25
78
|
if (params.summary) {
|
|
26
79
|
tags.push(['summary', params.summary]);
|
|
27
80
|
}
|
|
@@ -35,6 +88,15 @@ export function createAttestation(params) {
|
|
|
35
88
|
throw new Error('validFrom must be a finite number');
|
|
36
89
|
tags.push(['valid_from', String(params.validFrom)]);
|
|
37
90
|
}
|
|
91
|
+
if (params.validTo != null) {
|
|
92
|
+
tags.push(['valid_to', String(params.validTo)]);
|
|
93
|
+
}
|
|
94
|
+
if (params.request) {
|
|
95
|
+
tags.push(['request', params.request]);
|
|
96
|
+
}
|
|
97
|
+
if (params.schema) {
|
|
98
|
+
tags.push(['schema', params.schema]);
|
|
99
|
+
}
|
|
38
100
|
if (params.tags) {
|
|
39
101
|
for (const tag of params.tags) {
|
|
40
102
|
tags.push(tag);
|
|
@@ -49,13 +111,29 @@ export function createAttestation(params) {
|
|
|
49
111
|
/**
|
|
50
112
|
* Create an unsigned revocation event template.
|
|
51
113
|
* When published, this replaces the original attestation via addressable event semantics.
|
|
114
|
+
*
|
|
115
|
+
* For typed attestations: provide `type` + `identifier`.
|
|
116
|
+
* For assertion-only attestations: provide `assertionId` or `assertionAddress`.
|
|
52
117
|
*/
|
|
53
118
|
export function createRevocation(params) {
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
119
|
+
const hasTyped = !!params.type && params.identifier != null;
|
|
120
|
+
const hasAssertion = !!params.assertionId || !!params.assertionAddress;
|
|
121
|
+
if (!hasTyped && !hasAssertion) {
|
|
122
|
+
throw new Error('provide (type + identifier) or (assertionId | assertionAddress)');
|
|
123
|
+
}
|
|
124
|
+
if (params.assertionId && params.assertionAddress) {
|
|
125
|
+
throw new Error('provide assertionId or assertionAddress, not both');
|
|
126
|
+
}
|
|
127
|
+
const tags = [];
|
|
128
|
+
if (hasTyped) {
|
|
129
|
+
tags.push(['d', buildDTag(params.type, params.identifier)]);
|
|
130
|
+
tags.push(['type', params.type]);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
const ref = (params.assertionId ?? params.assertionAddress);
|
|
134
|
+
tags.push(['d', buildAssertionDTag(ref)]);
|
|
135
|
+
}
|
|
136
|
+
tags.push(['status', 'revoked']);
|
|
59
137
|
if (params.subject) {
|
|
60
138
|
tags.push(['p', params.subject]);
|
|
61
139
|
}
|
package/dist/builders.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builders.js","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"builders.js","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"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"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -10,5 +10,7 @@ export declare const TYPES: {
|
|
|
10
10
|
readonly VOUCH: "vouch";
|
|
11
11
|
readonly VERIFIER: "verifier";
|
|
12
12
|
readonly PROVENANCE: "provenance";
|
|
13
|
+
/** Synthetic type for assertion-only attestations (no explicit type tag). */
|
|
14
|
+
readonly ASSERTION: "assertion";
|
|
13
15
|
};
|
|
14
16
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,EAAG,KAAc,CAAA;AAE9C;;;GAGG;AACH,eAAO,MAAM,KAAK;;;;;;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,EAAG,KAAc,CAAA;AAE9C;;;GAGG;AACH,eAAO,MAAM,KAAK;;;;;;IAMhB,6EAA6E;;CAErE,CAAA"}
|
package/dist/constants.js
CHANGED
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAc,CAAA;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,UAAU,EAAE,YAAY;IACxB,WAAW,EAAE,aAAa;IAC1B,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,UAAU,EAAE,YAAY;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAc,CAAA;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,UAAU,EAAE,YAAY;IACxB,WAAW,EAAE,aAAa;IAC1B,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,UAAU,EAAE,YAAY;IACxB,6EAA6E;IAC7E,SAAS,EAAE,WAAW;CACd,CAAA"}
|
package/dist/filters.d.ts
CHANGED
|
@@ -4,9 +4,15 @@ import type { FilterParams, NostrFilter } from './types.js';
|
|
|
4
4
|
* Type values must not contain colons — the first colon is the delimiter.
|
|
5
5
|
*/
|
|
6
6
|
export declare function buildDTag(type: string, identifier: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Build a d-tag for an assertion-only attestation.
|
|
9
|
+
* Uses the `assertion:` prefix followed by the assertion reference.
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildAssertionDTag(ref: string): string;
|
|
7
12
|
/**
|
|
8
13
|
* Parse a d-tag into type and identifier.
|
|
9
14
|
* Returns null if the d-tag does not contain a colon.
|
|
15
|
+
* For assertion-only attestations (prefix `assertion:`), returns type as null.
|
|
10
16
|
*/
|
|
11
17
|
export declare function parseDTag(dTag: string): {
|
|
12
18
|
type: string;
|
|
@@ -16,4 +22,9 @@ export declare function parseDTag(dTag: string): {
|
|
|
16
22
|
export declare function attestationFilter(params: FilterParams): NostrFilter;
|
|
17
23
|
/** Build a Nostr relay filter for fetching the latest version of a specific attestation (for revocation checking). */
|
|
18
24
|
export declare function revocationFilter(type: string, identifier: string): NostrFilter;
|
|
25
|
+
/** Build a Nostr relay filter for an assertion-only attestation by its reference. */
|
|
26
|
+
export declare function revocationFilter(options: {
|
|
27
|
+
assertionId?: string;
|
|
28
|
+
assertionAddress?: string;
|
|
29
|
+
}): NostrFilter;
|
|
19
30
|
//# sourceMappingURL=filters.d.ts.map
|
package/dist/filters.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../src/filters.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../src/filters.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAK3D;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAIlE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGtD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAMnF;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,CAOnE;AAED,sHAAsH;AACtH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAAA;AAC/E,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAAA"}
|
package/dist/filters.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { ATTESTATION_KIND } from './constants.js';
|
|
2
|
+
/** Assertion d-tag prefix for assertion-only attestations. */
|
|
3
|
+
const ASSERTION_PREFIX = 'assertion';
|
|
2
4
|
/**
|
|
3
5
|
* Build a d-tag from type and identifier.
|
|
4
6
|
* Type values must not contain colons — the first colon is the delimiter.
|
|
@@ -10,18 +12,27 @@ export function buildDTag(type, identifier) {
|
|
|
10
12
|
throw new Error('type must not contain colons');
|
|
11
13
|
return `${type}:${identifier}`;
|
|
12
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Build a d-tag for an assertion-only attestation.
|
|
17
|
+
* Uses the `assertion:` prefix followed by the assertion reference.
|
|
18
|
+
*/
|
|
19
|
+
export function buildAssertionDTag(ref) {
|
|
20
|
+
if (!ref)
|
|
21
|
+
throw new Error('assertion reference must not be empty');
|
|
22
|
+
return `${ASSERTION_PREFIX}:${ref}`;
|
|
23
|
+
}
|
|
13
24
|
/**
|
|
14
25
|
* Parse a d-tag into type and identifier.
|
|
15
26
|
* Returns null if the d-tag does not contain a colon.
|
|
27
|
+
* For assertion-only attestations (prefix `assertion:`), returns type as null.
|
|
16
28
|
*/
|
|
17
29
|
export function parseDTag(dTag) {
|
|
18
30
|
const idx = dTag.indexOf(':');
|
|
19
31
|
if (idx <= 0)
|
|
20
32
|
return null;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
33
|
+
const prefix = dTag.slice(0, idx);
|
|
34
|
+
const rest = dTag.slice(idx + 1);
|
|
35
|
+
return { type: prefix, identifier: rest };
|
|
25
36
|
}
|
|
26
37
|
/** Build a Nostr relay filter for querying attestation events. */
|
|
27
38
|
export function attestationFilter(params) {
|
|
@@ -32,13 +43,23 @@ export function attestationFilter(params) {
|
|
|
32
43
|
filter['#p'] = [params.subject];
|
|
33
44
|
if (params.type)
|
|
34
45
|
filter['#type'] = [params.type];
|
|
46
|
+
if (params.schema)
|
|
47
|
+
filter['#schema'] = [params.schema];
|
|
35
48
|
return filter;
|
|
36
49
|
}
|
|
37
|
-
|
|
38
|
-
|
|
50
|
+
export function revocationFilter(typeOrOptions, identifier) {
|
|
51
|
+
if (typeof typeOrOptions === 'string') {
|
|
52
|
+
return {
|
|
53
|
+
kinds: [ATTESTATION_KIND],
|
|
54
|
+
'#d': [buildDTag(typeOrOptions, identifier)],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const ref = typeOrOptions.assertionId ?? typeOrOptions.assertionAddress;
|
|
58
|
+
if (!ref)
|
|
59
|
+
throw new Error('assertionId or assertionAddress required');
|
|
39
60
|
return {
|
|
40
61
|
kinds: [ATTESTATION_KIND],
|
|
41
|
-
'#d': [
|
|
62
|
+
'#d': [buildAssertionDTag(ref)],
|
|
42
63
|
};
|
|
43
64
|
}
|
|
44
65
|
//# sourceMappingURL=filters.js.map
|
package/dist/filters.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filters.js","sourceRoot":"","sources":["../src/filters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAGjD;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,UAAkB;IACxD,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAA;IACpD,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;IACvE,OAAO,GAAG,IAAI,IAAI,UAAU,EAAE,CAAA;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAC7B,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IACzB,
|
|
1
|
+
{"version":3,"file":"filters.js","sourceRoot":"","sources":["../src/filters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAGjD,8DAA8D;AAC9D,MAAM,gBAAgB,GAAG,WAAW,CAAA;AAEpC;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,UAAkB;IACxD,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAA;IACpD,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;IACvE,OAAO,GAAG,IAAI,IAAI,UAAU,EAAE,CAAA;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAA;IAClE,OAAO,GAAG,gBAAgB,IAAI,GAAG,EAAE,CAAA;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAC7B,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IACzB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;IAChC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;AAC3C,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,iBAAiB,CAAC,MAAoB;IACpD,MAAM,MAAM,GAAgB,EAAE,KAAK,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAA;IACzD,IAAI,MAAM,CAAC,OAAO,EAAE,MAAM;QAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAA;IAC3D,IAAI,MAAM,CAAC,OAAO;QAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACnD,IAAI,MAAM,CAAC,IAAI;QAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAChD,IAAI,MAAM,CAAC,MAAM;QAAE,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACtD,OAAO,MAAM,CAAA;AACf,CAAC;AAMD,MAAM,UAAU,gBAAgB,CAC9B,aAA2E,EAC3E,UAAmB;IAEnB,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO;YACL,KAAK,EAAE,CAAC,gBAAgB,CAAC;YACzB,IAAI,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,UAAW,CAAC,CAAC;SAC9C,CAAA;IACH,CAAC;IACD,MAAM,GAAG,GAAG,aAAa,CAAC,WAAW,IAAI,aAAa,CAAC,gBAAgB,CAAA;IACvE,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IACrE,OAAO;QACL,KAAK,EAAE,CAAC,gBAAgB,CAAC;QACzB,IAAI,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;KAChC,CAAA;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ export { ATTESTATION_KIND, TYPES } from './constants.js';
|
|
|
2
2
|
export { createAttestation, createRevocation } from './builders.js';
|
|
3
3
|
export { parseAttestation, isRevoked } from './parsers.js';
|
|
4
4
|
export { validateAttestation } from './validators.js';
|
|
5
|
-
export { buildDTag, parseDTag, attestationFilter, revocationFilter } from './filters.js';
|
|
6
|
-
export type { AttestationParams, RevocationParams, Attestation, ValidationResult, FilterParams, NostrFilter, NostrEvent, EventTemplate, } from './types.js';
|
|
5
|
+
export { buildDTag, buildAssertionDTag, parseDTag, attestationFilter, revocationFilter } from './filters.js';
|
|
6
|
+
export type { AssertionRef, AttestationParams, RevocationParams, Attestation, ValidationResult, FilterParams, NostrFilter, NostrEvent, EventTemplate, } from './types.js';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAExD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEnE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAErD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAExD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEnE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAErD,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE5G,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,aAAa,GACd,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -2,5 +2,5 @@ export { ATTESTATION_KIND, TYPES } from './constants.js';
|
|
|
2
2
|
export { createAttestation, createRevocation } from './builders.js';
|
|
3
3
|
export { parseAttestation, isRevoked } from './parsers.js';
|
|
4
4
|
export { validateAttestation } from './validators.js';
|
|
5
|
-
export { buildDTag, parseDTag, attestationFilter, revocationFilter } from './filters.js';
|
|
5
|
+
export { buildDTag, buildAssertionDTag, parseDTag, attestationFilter, revocationFilter } from './filters.js';
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAExD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEnE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAErD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAExD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEnE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAErD,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/parsers.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { NostrEvent, Attestation } from './types.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Parse a NostrEvent into a typed Attestation.
|
|
4
4
|
* Returns null if the event is not a valid kind 31000 attestation.
|
|
5
|
+
*
|
|
6
|
+
* An attestation must have either a type tag or an assertion reference.
|
|
5
7
|
*/
|
|
6
8
|
export declare function parseAttestation(event: NostrEvent): Attestation | null;
|
|
7
9
|
/**
|
package/dist/parsers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsers.d.ts","sourceRoot":"","sources":["../src/parsers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"parsers.d.ts","sourceRoot":"","sources":["../src/parsers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAUzD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI,CAqCtE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAGpD"}
|
package/dist/parsers.js
CHANGED
|
@@ -1,30 +1,48 @@
|
|
|
1
|
-
import { ATTESTATION_KIND } from './constants.js';
|
|
1
|
+
import { ATTESTATION_KIND, TYPES } from './constants.js';
|
|
2
2
|
import { findTag } from './helpers.js';
|
|
3
3
|
import { parseDTag } from './filters.js';
|
|
4
|
+
/**
|
|
5
|
+
* Find an e or a tag with the "assertion" marker (fourth element).
|
|
6
|
+
* Returns the tag array or null.
|
|
7
|
+
*/
|
|
8
|
+
function findAssertionTag(tags) {
|
|
9
|
+
return tags.find(t => (t[0] === 'e' || t[0] === 'a') && t[3] === 'assertion') ?? null;
|
|
10
|
+
}
|
|
4
11
|
/**
|
|
5
12
|
* Parse a NostrEvent into a typed Attestation.
|
|
6
13
|
* Returns null if the event is not a valid kind 31000 attestation.
|
|
14
|
+
*
|
|
15
|
+
* An attestation must have either a type tag or an assertion reference.
|
|
7
16
|
*/
|
|
8
17
|
export function parseAttestation(event) {
|
|
9
18
|
if (event.kind !== ATTESTATION_KIND)
|
|
10
19
|
return null;
|
|
11
20
|
const type = findTag(event.tags, 'type');
|
|
12
|
-
|
|
21
|
+
const assertionTag = findAssertionTag(event.tags);
|
|
22
|
+
// Must have type or assertion reference
|
|
23
|
+
if (!type && !assertionTag)
|
|
13
24
|
return null;
|
|
14
25
|
const dTag = findTag(event.tags, 'd');
|
|
15
26
|
const parsed = dTag ? parseDTag(dTag) : null;
|
|
16
27
|
const expirationStr = findTag(event.tags, 'expiration');
|
|
17
28
|
const validFromStr = findTag(event.tags, 'valid_from');
|
|
29
|
+
const validToStr = findTag(event.tags, 'valid_to');
|
|
18
30
|
return {
|
|
19
31
|
kind: ATTESTATION_KIND,
|
|
20
|
-
type,
|
|
32
|
+
type: type ?? TYPES.ASSERTION,
|
|
21
33
|
pubkey: event.pubkey,
|
|
22
34
|
createdAt: event.created_at,
|
|
23
35
|
identifier: parsed?.identifier ?? null,
|
|
24
36
|
subject: findTag(event.tags, 'p'),
|
|
37
|
+
assertionId: assertionTag !== null && assertionTag[0] === 'e' ? (assertionTag[1] ?? null) : null,
|
|
38
|
+
assertionAddress: assertionTag !== null && assertionTag[0] === 'a' ? (assertionTag[1] ?? null) : null,
|
|
39
|
+
assertionRelay: (assertionTag !== null && assertionTag[2]) ? assertionTag[2] : null,
|
|
25
40
|
summary: findTag(event.tags, 'summary'),
|
|
26
41
|
expiration: expirationStr ? Number(expirationStr) : null,
|
|
27
42
|
validFrom: validFromStr ? Number(validFromStr) : null,
|
|
43
|
+
validTo: validToStr ? Number(validToStr) : null,
|
|
44
|
+
request: findTag(event.tags, 'request'),
|
|
45
|
+
schema: findTag(event.tags, 'schema'),
|
|
28
46
|
revoked: findTag(event.tags, 'status') === 'revoked',
|
|
29
47
|
reason: findTag(event.tags, 'reason'),
|
|
30
48
|
tags: event.tags,
|
package/dist/parsers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsers.js","sourceRoot":"","sources":["../src/parsers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"parsers.js","sourceRoot":"","sources":["../src/parsers.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -15,20 +15,37 @@ export interface NostrEvent {
|
|
|
15
15
|
id: string;
|
|
16
16
|
sig: string;
|
|
17
17
|
}
|
|
18
|
+
/** Reference to a first-person assertion event being attested. */
|
|
19
|
+
export interface AssertionRef {
|
|
20
|
+
/** Event ID of the assertion (produces an e-tag with "assertion" marker). */
|
|
21
|
+
id?: string;
|
|
22
|
+
/** Addressable event coordinate kind:pubkey:d-tag (produces an a-tag). */
|
|
23
|
+
address?: string;
|
|
24
|
+
/** Relay hint for fetching the referenced event. */
|
|
25
|
+
relay?: string;
|
|
26
|
+
}
|
|
18
27
|
/** Parameters for creating an attestation event. */
|
|
19
28
|
export interface AttestationParams {
|
|
20
|
-
/** Application-defined attestation type (must not contain colons). */
|
|
21
|
-
type
|
|
29
|
+
/** Application-defined attestation type (must not contain colons). Optional when assertion is provided. */
|
|
30
|
+
type?: string;
|
|
22
31
|
/** D-tag second segment: hex pubkey or context string. */
|
|
23
32
|
identifier?: string;
|
|
24
33
|
/** P-tag: hex pubkey of the subject (for third-party attestations). */
|
|
25
34
|
subject?: string;
|
|
35
|
+
/** Reference to a first-person assertion event being confirmed. */
|
|
36
|
+
assertion?: AssertionRef;
|
|
26
37
|
/** Human-readable fallback for clients that do not understand the type. */
|
|
27
38
|
summary?: string;
|
|
28
39
|
/** Unix timestamp for attestation expiry (NIP-40). */
|
|
29
40
|
expiration?: number;
|
|
30
41
|
/** Unix timestamp for deferred activation (valid_from). */
|
|
31
42
|
validFrom?: number;
|
|
43
|
+
/** Unix timestamp for validity window end (valid_to). */
|
|
44
|
+
validTo?: number;
|
|
45
|
+
/** Reference to the event that prompted this attestation (opaque string, conventionally an addressable coordinate). */
|
|
46
|
+
request?: string;
|
|
47
|
+
/** Machine-readable schema URI for regulatory mapping or application-profile identification. */
|
|
48
|
+
schema?: string;
|
|
32
49
|
/** Additional application-specific tags. */
|
|
33
50
|
tags?: string[][];
|
|
34
51
|
/** Event content: empty string, human-readable text, or JSON. */
|
|
@@ -36,12 +53,16 @@ export interface AttestationParams {
|
|
|
36
53
|
}
|
|
37
54
|
/** Parameters for creating a revocation event. */
|
|
38
55
|
export interface RevocationParams {
|
|
39
|
-
/** Type of the attestation being revoked. */
|
|
40
|
-
type
|
|
41
|
-
/** D-tag second segment — must match the original attestation. */
|
|
42
|
-
identifier
|
|
56
|
+
/** Type of the attestation being revoked. Required for typed attestations. */
|
|
57
|
+
type?: string;
|
|
58
|
+
/** D-tag second segment — must match the original attestation. Required for typed attestations. */
|
|
59
|
+
identifier?: string;
|
|
43
60
|
/** P-tag — include if the original attestation had one. */
|
|
44
61
|
subject?: string;
|
|
62
|
+
/** Event ID of the referenced assertion (for revoking assertion-only attestations). */
|
|
63
|
+
assertionId?: string;
|
|
64
|
+
/** Addressable coordinate of the referenced assertion (for revoking assertion-only attestations). */
|
|
65
|
+
assertionAddress?: string;
|
|
45
66
|
/** Human-readable revocation reason. */
|
|
46
67
|
reason?: string;
|
|
47
68
|
/** Unix timestamp for when the revocation takes effect. */
|
|
@@ -50,6 +71,7 @@ export interface RevocationParams {
|
|
|
50
71
|
/** Parsed attestation data extracted from a NostrEvent. */
|
|
51
72
|
export interface Attestation {
|
|
52
73
|
kind: 31000;
|
|
74
|
+
/** Attestation type. Value is "assertion" when the type is defined by a referenced assertion event. */
|
|
53
75
|
type: string;
|
|
54
76
|
/** Attestor's pubkey (from outer event). */
|
|
55
77
|
pubkey: string;
|
|
@@ -59,10 +81,22 @@ export interface Attestation {
|
|
|
59
81
|
identifier: string | null;
|
|
60
82
|
/** P-tag value (hex pubkey of subject, if present). */
|
|
61
83
|
subject: string | null;
|
|
84
|
+
/** Referenced assertion event ID (from e-tag with "assertion" marker). */
|
|
85
|
+
assertionId: string | null;
|
|
86
|
+
/** Referenced assertion address (from a-tag with "assertion" marker). */
|
|
87
|
+
assertionAddress: string | null;
|
|
88
|
+
/** Relay hint from the assertion reference tag. */
|
|
89
|
+
assertionRelay: string | null;
|
|
62
90
|
summary: string | null;
|
|
63
91
|
expiration: number | null;
|
|
64
92
|
/** Earliest time the attestation is valid (deferred activation). */
|
|
65
93
|
validFrom: number | null;
|
|
94
|
+
/** Latest time the attestation is valid (validity window end). */
|
|
95
|
+
validTo: number | null;
|
|
96
|
+
/** Reference to the event that prompted this attestation. */
|
|
97
|
+
request: string | null;
|
|
98
|
+
/** Machine-readable schema URI. */
|
|
99
|
+
schema: string | null;
|
|
66
100
|
revoked: boolean;
|
|
67
101
|
reason: string | null;
|
|
68
102
|
/** All tags from the original event (for application-specific access). */
|
|
@@ -82,6 +116,8 @@ export interface FilterParams {
|
|
|
82
116
|
subject?: string;
|
|
83
117
|
/** Filter by attestor pubkeys. */
|
|
84
118
|
authors?: string[];
|
|
119
|
+
/** Filter by schema URI. */
|
|
120
|
+
schema?: string;
|
|
85
121
|
}
|
|
86
122
|
/** Nostr relay filter object. */
|
|
87
123
|
export interface NostrFilter {
|
|
@@ -90,5 +126,6 @@ export interface NostrFilter {
|
|
|
90
126
|
'#p'?: string[];
|
|
91
127
|
'#d'?: string[];
|
|
92
128
|
'#type'?: string[];
|
|
129
|
+
'#schema'?: string[];
|
|
93
130
|
}
|
|
94
131
|
//# sourceMappingURL=types.d.ts.map
|