-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnip-20.ts
139 lines (120 loc) · 3.43 KB
/
nip-20.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
* @file NIP-20 Command Results implementation
* @module nips/nip-20
*/
import { NostrWSMessage } from '../types/index.js';
import { getLogger } from '../utils/logger.js';
const logger = getLogger('NIP-20');
/**
* Command status types
*/
export enum CommandStatus {
SUCCESS = 'success',
error = 'error',
PENDING = 'pending',
RATE_LIMITED = 'rate_limited',
AUTH_REQUIRED = 'auth_required',
RESTRICTED = 'restricted'
}
export type CommandStatusType = CommandStatus;
/**
* Command result interface
*/
export interface CommandResult {
status: boolean;
message?: string;
code?: CommandStatusType;
details?: Record<string, unknown>;
}
/**
* Represents the data structure for command messages
* @interface CommandMessageData
* @property {string} [event_id] - ID of the event this command relates to
* @property {boolean} [status] - Status of the command execution
* @property {string} [message] - Human-readable message about the command result
* @property {CommandStatusType} [code] - Status code of the command result
* @property {Record<string, unknown>} [details] - Additional details about the command result
*/
interface CommandMessageData {
event_id?: string;
status?: boolean;
message?: string;
code?: CommandStatusType;
details?: Record<string, unknown>;
}
/**
* Validates a command message according to NIP-20
*/
export function validateCommandMessage(message: NostrWSMessage): boolean {
if (!Array.isArray(message) || message.length < 2) {
logger.debug('Invalid command message format');
return false;
}
const [type, data] = message;
if (typeof data !== 'object' || !data) {
logger.debug('Invalid command message data');
return false;
}
const commandData = data as CommandMessageData;
// For OK/NOTICE messages
if (type === 'OK') {
if (!commandData.event_id || typeof commandData.event_id !== 'string') {
logger.debug('Invalid event_id in OK message');
return false;
}
if (typeof commandData.status !== 'boolean') {
logger.debug('Invalid status in OK message');
return false;
}
}
// For NOTICE messages
if (type === 'NOTICE' && commandData.code) {
if (!Object.values(CommandStatus).includes(commandData.code as CommandStatus)) {
logger.debug('Invalid command status code');
return false;
}
}
// Optional fields validation
if (commandData.message && typeof commandData.message !== 'string') {
logger.debug('Invalid message field');
return false;
}
if (commandData.details && typeof commandData.details !== 'object') {
logger.debug('Invalid details field');
return false;
}
return true;
}
/**
* Creates a command result message
*/
export function createCommandResult(data: CommandMessageData): CommandResult {
const status = data.status ?? false;
const code = status ? CommandStatus.SUCCESS : data.code;
return {
status,
code,
message: data.message,
details: data.details
};
}
/**
* Creates an OK message
*/
export function createOkMessage(eventId: string, success = true, details?: Record<string, unknown>): NostrWSMessage {
return ['OK', {
event_id: eventId,
status: success,
...details && { details }
}];
}
/**
* Creates a NOTICE message
*/
export function createCommandNoticeMessage(code: CommandStatusType, message: string, details?: Record<string, unknown>): NostrWSMessage {
return ['NOTICE', {
code,
message,
...details && { details }
}];
}