@yallet/rwa-sdk 0.2.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.
Files changed (58) hide show
  1. package/README.md +365 -0
  2. package/dist/credential-nft-server.d.ts +75 -0
  3. package/dist/credential-nft-server.d.ts.map +1 -0
  4. package/dist/credential-nft-server.js +122 -0
  5. package/dist/credential-nft-server.js.map +1 -0
  6. package/dist/credential-nft.d.ts +31 -0
  7. package/dist/credential-nft.d.ts.map +1 -0
  8. package/dist/credential-nft.js +38 -0
  9. package/dist/credential-nft.js.map +1 -0
  10. package/dist/encryption.d.ts +107 -0
  11. package/dist/encryption.d.ts.map +1 -0
  12. package/dist/encryption.js +176 -0
  13. package/dist/encryption.js.map +1 -0
  14. package/dist/index.d.ts +56 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +66 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/metadata.d.ts +161 -0
  19. package/dist/metadata.d.ts.map +1 -0
  20. package/dist/metadata.js +180 -0
  21. package/dist/metadata.js.map +1 -0
  22. package/dist/minting.d.ts +63 -0
  23. package/dist/minting.d.ts.map +1 -0
  24. package/dist/minting.js +194 -0
  25. package/dist/minting.js.map +1 -0
  26. package/dist/payloads.d.ts +120 -0
  27. package/dist/payloads.d.ts.map +1 -0
  28. package/dist/payloads.js +118 -0
  29. package/dist/payloads.js.map +1 -0
  30. package/dist/registry.d.ts +77 -0
  31. package/dist/registry.d.ts.map +1 -0
  32. package/dist/registry.js +173 -0
  33. package/dist/registry.js.map +1 -0
  34. package/dist/sdk.d.ts +158 -0
  35. package/dist/sdk.d.ts.map +1 -0
  36. package/dist/sdk.js +346 -0
  37. package/dist/sdk.js.map +1 -0
  38. package/dist/storage.d.ts +80 -0
  39. package/dist/storage.d.ts.map +1 -0
  40. package/dist/storage.js +284 -0
  41. package/dist/storage.js.map +1 -0
  42. package/dist/types.d.ts +278 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +19 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +64 -0
  47. package/src/credential-nft-server.ts +201 -0
  48. package/src/credential-nft.ts +64 -0
  49. package/src/encryption.ts +308 -0
  50. package/src/index.ts +151 -0
  51. package/src/metadata.ts +336 -0
  52. package/src/minting.ts +266 -0
  53. package/src/payloads.ts +238 -0
  54. package/src/registry.ts +236 -0
  55. package/src/sdk.ts +507 -0
  56. package/src/storage.ts +364 -0
  57. package/src/types.ts +318 -0
  58. package/wasm/README.md +33 -0
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Yallet RWA SDK - User Registry Module
3
+ *
4
+ * Manages registered users with their xidentity public keys
5
+ */
6
+
7
+ import type { RegisteredUser, UserRegistry } from './types.js';
8
+
9
+ // ======================================
10
+ // In-Memory Registry (For Development)
11
+ // ======================================
12
+
13
+ /**
14
+ * Simple in-memory user registry
15
+ * For production, implement a database-backed registry
16
+ */
17
+ export class InMemoryRegistry implements UserRegistry {
18
+ private users: Map<string, RegisteredUser> = new Map();
19
+
20
+ async getUser(solanaAddress: string): Promise<RegisteredUser | null> {
21
+ return this.users.get(solanaAddress) || null;
22
+ }
23
+
24
+ async registerUser(user: RegisteredUser): Promise<void> {
25
+ this.users.set(user.solanaAddress, {
26
+ ...user,
27
+ registeredAt: user.registeredAt || Date.now(),
28
+ });
29
+ }
30
+
31
+ async updateUser(
32
+ solanaAddress: string,
33
+ updates: Partial<RegisteredUser>
34
+ ): Promise<void> {
35
+ const existing = this.users.get(solanaAddress);
36
+ if (!existing) {
37
+ throw new Error(`User not found: ${solanaAddress}`);
38
+ }
39
+ this.users.set(solanaAddress, { ...existing, ...updates });
40
+ }
41
+
42
+ async deleteUser(solanaAddress: string): Promise<void> {
43
+ this.users.delete(solanaAddress);
44
+ }
45
+
46
+ async listUsers(): Promise<RegisteredUser[]> {
47
+ return Array.from(this.users.values());
48
+ }
49
+ }
50
+
51
+ // ======================================
52
+ // HTTP Registry (For Production)
53
+ // ======================================
54
+
55
+ export interface HTTPRegistryConfig {
56
+ /** Base URL of the registry API */
57
+ baseUrl: string;
58
+ /** API key for authentication */
59
+ apiKey?: string;
60
+ /** Custom headers */
61
+ headers?: Record<string, string>;
62
+ }
63
+
64
+ /**
65
+ * HTTP-backed user registry
66
+ * Connects to a backend API for user management
67
+ */
68
+ export class HTTPRegistry implements UserRegistry {
69
+ private config: HTTPRegistryConfig;
70
+
71
+ constructor(config: HTTPRegistryConfig) {
72
+ this.config = config;
73
+ }
74
+
75
+ private async fetch<T>(
76
+ path: string,
77
+ options: RequestInit = {}
78
+ ): Promise<T> {
79
+ const url = `${this.config.baseUrl}${path}`;
80
+
81
+ const headers: Record<string, string> = {
82
+ 'Content-Type': 'application/json',
83
+ ...this.config.headers,
84
+ };
85
+
86
+ if (this.config.apiKey) {
87
+ headers['Authorization'] = `Bearer ${this.config.apiKey}`;
88
+ }
89
+
90
+ const response = await fetch(url, {
91
+ ...options,
92
+ headers: { ...headers, ...options.headers },
93
+ });
94
+
95
+ if (!response.ok) {
96
+ const error = await response.text();
97
+ throw new Error(`Registry API error: ${response.status} - ${error}`);
98
+ }
99
+
100
+ return response.json() as Promise<T>;
101
+ }
102
+
103
+ async getUser(solanaAddress: string): Promise<RegisteredUser | null> {
104
+ try {
105
+ return await this.fetch<RegisteredUser>(
106
+ `/users/${encodeURIComponent(solanaAddress)}`
107
+ );
108
+ } catch (err) {
109
+ if (err instanceof Error && err.message.includes('404')) {
110
+ return null;
111
+ }
112
+ throw err;
113
+ }
114
+ }
115
+
116
+ async registerUser(user: RegisteredUser): Promise<void> {
117
+ await this.fetch('/users', {
118
+ method: 'POST',
119
+ body: JSON.stringify(user),
120
+ });
121
+ }
122
+
123
+ async updateUser(
124
+ solanaAddress: string,
125
+ updates: Partial<RegisteredUser>
126
+ ): Promise<void> {
127
+ await this.fetch(`/users/${encodeURIComponent(solanaAddress)}`, {
128
+ method: 'PATCH',
129
+ body: JSON.stringify(updates),
130
+ });
131
+ }
132
+
133
+ async deleteUser(solanaAddress: string): Promise<void> {
134
+ await this.fetch(`/users/${encodeURIComponent(solanaAddress)}`, {
135
+ method: 'DELETE',
136
+ });
137
+ }
138
+
139
+ async listUsers(): Promise<RegisteredUser[]> {
140
+ return this.fetch<RegisteredUser[]>('/users');
141
+ }
142
+ }
143
+
144
+ // ======================================
145
+ // Registry Factory
146
+ // ======================================
147
+
148
+ export type RegistryType = 'memory' | 'http';
149
+
150
+ export interface RegistryOptions {
151
+ type: RegistryType;
152
+ httpConfig?: HTTPRegistryConfig;
153
+ }
154
+
155
+ /**
156
+ * Create a user registry instance
157
+ *
158
+ * @param options - Registry options
159
+ * @returns UserRegistry instance
160
+ */
161
+ export function createRegistry(options: RegistryOptions): UserRegistry {
162
+ switch (options.type) {
163
+ case 'memory':
164
+ return new InMemoryRegistry();
165
+ case 'http':
166
+ if (!options.httpConfig) {
167
+ throw new Error('httpConfig is required for HTTP registry');
168
+ }
169
+ return new HTTPRegistry(options.httpConfig);
170
+ default:
171
+ throw new Error(`Unknown registry type: ${options.type}`);
172
+ }
173
+ }
174
+
175
+ // ======================================
176
+ // Validation Helpers
177
+ // ======================================
178
+
179
+ /**
180
+ * Validate a Solana address
181
+ *
182
+ * @param address - Address to validate
183
+ * @returns true if valid
184
+ */
185
+ export function isValidSolanaAddress(address: string): boolean {
186
+ // Basic validation: 32-44 characters, base58
187
+ const base58Regex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
188
+ return base58Regex.test(address);
189
+ }
190
+
191
+ /**
192
+ * Validate an xidentity public key (base64)
193
+ *
194
+ * @param xidentity - xidentity to validate
195
+ * @returns true if valid
196
+ */
197
+ export function isValidXidentity(xidentity: string): boolean {
198
+ // Check if it's valid base64
199
+ try {
200
+ const decoded = atob(xidentity);
201
+ // X25519 public key should be 32 bytes
202
+ return decoded.length === 32;
203
+ } catch {
204
+ return false;
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Validate a registered user
210
+ *
211
+ * @param user - User to validate
212
+ * @returns Validation result
213
+ */
214
+ export function validateUser(user: Partial<RegisteredUser>): {
215
+ valid: boolean;
216
+ errors: string[];
217
+ } {
218
+ const errors: string[] = [];
219
+
220
+ if (!user.solanaAddress) {
221
+ errors.push('solanaAddress is required');
222
+ } else if (!isValidSolanaAddress(user.solanaAddress)) {
223
+ errors.push('Invalid Solana address format');
224
+ }
225
+
226
+ if (!user.xidentity) {
227
+ errors.push('xidentity is required');
228
+ } else if (!isValidXidentity(user.xidentity)) {
229
+ errors.push('Invalid xidentity format (must be base64-encoded 32-byte key)');
230
+ }
231
+
232
+ return {
233
+ valid: errors.length === 0,
234
+ errors,
235
+ };
236
+ }