@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
package/src/index.ts ADDED
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Yallet RWA SDK
3
+ *
4
+ * SDK for minting encrypted RWA (Real World Assets) as Solana cNFTs
5
+ *
6
+ * Features:
7
+ * - End-to-end encryption using xidentity (X25519) public keys
8
+ * - Permanent storage on Arweave via ArDrive Turbo
9
+ * - Compressed NFT minting via Metaplex Bubblegum
10
+ * - User registry for xidentity management
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { createRWASDK, AssetType } from '@yallet/rwa-sdk';
15
+ *
16
+ * // Create SDK instance
17
+ * const sdk = createRWASDK({
18
+ * rpcEndpoint: 'https://api.mainnet-beta.solana.com',
19
+ * network: 'mainnet',
20
+ * merkleTreeAddress: 'YOUR_TREE_ADDRESS',
21
+ * });
22
+ *
23
+ * // Register a user with their xidentity
24
+ * await sdk.registerUser({
25
+ * solanaAddress: 'RECIPIENT_ADDRESS',
26
+ * xidentity: 'BASE64_XIDENTITY_PUBLIC_KEY',
27
+ * name: 'Customer Name',
28
+ * });
29
+ *
30
+ * // Mint an encrypted invoice
31
+ * const result = await sdk.mintInvoice(
32
+ * {
33
+ * invoiceId: 'INV-001',
34
+ * amount: 100,
35
+ * currency: 'USD',
36
+ * date: new Date().toISOString(),
37
+ * },
38
+ * 'RECIPIENT_ADDRESS'
39
+ * );
40
+ *
41
+ * console.log('Minted:', result.assetId);
42
+ * ```
43
+ *
44
+ * @packageDocumentation
45
+ */
46
+
47
+ // Main SDK
48
+ export { YalletRWASDK, createRWASDK } from './sdk.js';
49
+
50
+ // Types
51
+ export {
52
+ AssetType,
53
+ type SDKConfig,
54
+ type MintRequest,
55
+ type MintResult,
56
+ type RegisteredUser,
57
+ type UserRegistry,
58
+ type InvoiceData,
59
+ type InvoiceItem,
60
+ type NoteData,
61
+ type ContactData,
62
+ type FileData,
63
+ type PhotoData,
64
+ type EncryptedPayload,
65
+ type EncryptFunction,
66
+ type TreeConfig,
67
+ type Signer,
68
+ } from './types.js';
69
+
70
+ // Payload builders (extension-compatible JSON)
71
+ export {
72
+ buildInvoicePayload,
73
+ buildFilePayload,
74
+ buildMessagePayload,
75
+ buildPhotoPayload,
76
+ type InvoicePayloadBundle,
77
+ type ExtensionInvoicePayload,
78
+ type ExtensionLineItem,
79
+ type ExtensionFilePayload,
80
+ type ExtensionNotePayload,
81
+ type ExtensionPhotoPayload,
82
+ } from './payloads.js';
83
+
84
+ // Encryption
85
+ export {
86
+ ECIESEncryptor,
87
+ createWasmEncryptor,
88
+ createAcegfEncryptor,
89
+ encryptAsset,
90
+ prepareAssetData,
91
+ type PrepareAssetOptions,
92
+ type EncryptAssetOptions,
93
+ type EncryptedAssetResult,
94
+ } from './encryption.js';
95
+
96
+ // Storage
97
+ export {
98
+ uploadToArweave,
99
+ uploadEncryptedAsset,
100
+ uploadMetadata,
101
+ downloadFromArweave,
102
+ downloadJsonFromArweave,
103
+ type UploadOptions,
104
+ type UploadResult,
105
+ } from './storage.js';
106
+
107
+ // Metadata
108
+ export {
109
+ generateNFTMetadata,
110
+ generateInvoiceMetadata,
111
+ parseRWAMetadata,
112
+ type NFTMetadata,
113
+ type NFTMetadataParams,
114
+ type ParsedRWAMetadata,
115
+ } from './metadata.js';
116
+
117
+ // Minting
118
+ export {
119
+ CNFTMinter,
120
+ createMinter,
121
+ estimateMintCost,
122
+ } from './minting.js';
123
+
124
+ // Registry
125
+ export {
126
+ InMemoryRegistry,
127
+ HTTPRegistry,
128
+ createRegistry,
129
+ isValidSolanaAddress,
130
+ isValidXidentity,
131
+ validateUser,
132
+ type HTTPRegistryConfig,
133
+ type RegistryOptions,
134
+ } from './registry.js';
135
+
136
+ // Yault credential NFT (mint user_cred + mnemonic as encrypted note cNFT)
137
+ export {
138
+ mintCredentialNft,
139
+ type CredentialNftPayload,
140
+ type CredentialMintResult,
141
+ } from './credential-nft.js';
142
+
143
+ // Server-side mint (no registry/signer; caller provides xidentity)
144
+ export {
145
+ mintCredentialNftViaServer,
146
+ prepareCredentialNftPayload,
147
+ RWA_UPLOAD_AND_MINT_ENDPOINTS,
148
+ type MintCredentialNftViaServerOptions,
149
+ type PrepareCredentialNftPayloadOptions,
150
+ type PreparedCredentialNftPayload,
151
+ } from './credential-nft-server.js';
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Yallet RWA SDK - NFT Metadata Module
3
+ *
4
+ * Generates Metaplex-compatible NFT metadata for RWA assets
5
+ */
6
+
7
+ import { AssetType } from './types.js';
8
+
9
+ // ======================================
10
+ // Metadata Generation
11
+ // ======================================
12
+
13
+ export interface NFTMetadataParams {
14
+ /** NFT name */
15
+ name: string;
16
+ /** NFT description */
17
+ description?: string;
18
+ /** Asset type */
19
+ assetType: AssetType;
20
+ /** Arweave URI for encrypted data */
21
+ encryptedDataUri: string;
22
+ /** Owner's Solana address */
23
+ owner: string;
24
+ /** Direction: owned, sent, or received */
25
+ direction?: 'owned' | 'sent' | 'received';
26
+ /** Additional attributes */
27
+ additionalAttributes?: Array<{ trait_type: string; value: string }>;
28
+ /** External URL */
29
+ externalUrl?: string;
30
+ /** Unique identifier for tracking */
31
+ uuid?: string;
32
+ /** Creation timestamp (Unix epoch seconds) */
33
+ timestamp?: number;
34
+ /** Previous token address for version chain */
35
+ previousToken?: string;
36
+ /** Schema identifier for data format */
37
+ schema?: string;
38
+ /** MIME type of the content */
39
+ mimeType?: string;
40
+ /** Size of the data in bytes */
41
+ dataSize?: number;
42
+ }
43
+
44
+ export interface NFTMetadata {
45
+ name: string;
46
+ symbol: string;
47
+ description: string;
48
+ image: string;
49
+ external_url: string;
50
+ attributes: Array<{ trait_type: string; value: string }>;
51
+ properties: {
52
+ files: Array<{ uri: string; type: string }>;
53
+ category: string;
54
+ creators: Array<{ address: string; share: number }>;
55
+ };
56
+ yallet_rwa: {
57
+ version: number;
58
+ assetType: AssetType;
59
+ direction: string;
60
+ encryptedDataUri: string;
61
+ /** Unique identifier for tracking */
62
+ uuid: string;
63
+ /** Creation timestamp (Unix epoch seconds) */
64
+ timestamp: number;
65
+ /** Previous token address for version chain (null for first version) */
66
+ previousToken: string | null;
67
+ /** Schema identifier for data format */
68
+ schema: string | null;
69
+ /** MIME type of the content */
70
+ mimeType: string | null;
71
+ /** Size of the data in bytes */
72
+ dataSize: number | null;
73
+ };
74
+ }
75
+
76
+ /**
77
+ * Get icon URL for asset type
78
+ */
79
+ function getAssetTypeIcon(assetType: AssetType): string {
80
+ const icons: Record<AssetType, string> = {
81
+ [AssetType.NOTE]: 'https://yallet.app/icons/rwa-note.png',
82
+ [AssetType.INVOICE]: 'https://yallet.app/icons/rwa-invoice.png',
83
+ [AssetType.PHOTO]: 'https://yallet.app/icons/rwa-photo.png',
84
+ [AssetType.FILE]: 'https://yallet.app/icons/rwa-file.png',
85
+ [AssetType.CONTACT]: 'https://yallet.app/icons/rwa-contact.png',
86
+ };
87
+ return icons[assetType] || icons[AssetType.FILE];
88
+ }
89
+
90
+ /**
91
+ * Get default description for asset type
92
+ */
93
+ function getDefaultDescription(assetType: AssetType, direction: string): string {
94
+ const descriptions: Record<AssetType, string> = {
95
+ [AssetType.NOTE]: 'Encrypted note',
96
+ [AssetType.INVOICE]: 'Encrypted invoice',
97
+ [AssetType.PHOTO]: 'Encrypted photo',
98
+ [AssetType.FILE]: 'Encrypted file',
99
+ [AssetType.CONTACT]: 'Encrypted contact',
100
+ };
101
+
102
+ const base = descriptions[assetType] || 'Encrypted asset';
103
+ const directionSuffix = direction === 'received' ? ' (Received)' : '';
104
+
105
+ return `${base}${directionSuffix} - Decryptable only by the owner`;
106
+ }
107
+
108
+ /**
109
+ * Generate a UUID v4
110
+ */
111
+ function generateUUID(): string {
112
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) {
113
+ return crypto.randomUUID();
114
+ }
115
+ // Fallback for environments without crypto.randomUUID
116
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
117
+ const r = (Math.random() * 16) | 0;
118
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
119
+ return v.toString(16);
120
+ });
121
+ }
122
+
123
+ /**
124
+ * Generate Metaplex-compatible NFT metadata
125
+ *
126
+ * @param params - Metadata parameters
127
+ * @returns NFT metadata object
128
+ */
129
+ export function generateNFTMetadata(params: NFTMetadataParams): NFTMetadata {
130
+ const {
131
+ name,
132
+ description,
133
+ assetType,
134
+ encryptedDataUri,
135
+ owner,
136
+ direction = 'sent',
137
+ additionalAttributes = [],
138
+ externalUrl = 'https://yallet.app',
139
+ // New fields with defaults
140
+ uuid = generateUUID(),
141
+ timestamp = Math.floor(Date.now() / 1000),
142
+ previousToken = null,
143
+ schema = null,
144
+ mimeType = null,
145
+ dataSize = null,
146
+ } = params;
147
+
148
+ const finalDescription = description || getDefaultDescription(assetType, direction);
149
+
150
+ // Build attributes array with required and optional fields
151
+ const attributes: Array<{ trait_type: string; value: string }> = [
152
+ { trait_type: 'Asset Type', value: assetType },
153
+ { trait_type: 'Direction', value: direction },
154
+ { trait_type: 'Encrypted', value: 'true' },
155
+ { trait_type: 'Version', value: '1' },
156
+ { trait_type: 'UUID', value: uuid },
157
+ { trait_type: 'Timestamp', value: String(timestamp) },
158
+ ];
159
+
160
+ // Add optional attributes only if they have values
161
+ if (previousToken) {
162
+ attributes.push({ trait_type: 'Previous Token', value: previousToken });
163
+ }
164
+ if (schema) {
165
+ attributes.push({ trait_type: 'Schema', value: schema });
166
+ }
167
+ if (mimeType) {
168
+ attributes.push({ trait_type: 'MIME Type', value: mimeType });
169
+ }
170
+ if (dataSize !== null && dataSize !== undefined) {
171
+ attributes.push({ trait_type: 'Data Size', value: String(dataSize) });
172
+ }
173
+
174
+ // Add any additional custom attributes
175
+ attributes.push(...additionalAttributes);
176
+
177
+ return {
178
+ name,
179
+ symbol: 'YRWA', // Yallet RWA
180
+ description: finalDescription,
181
+ image: getAssetTypeIcon(assetType),
182
+ external_url: externalUrl,
183
+ attributes,
184
+ properties: {
185
+ files: [
186
+ {
187
+ uri: encryptedDataUri,
188
+ type: mimeType || 'application/octet-stream',
189
+ },
190
+ ],
191
+ category: 'document',
192
+ creators: [
193
+ {
194
+ address: owner,
195
+ share: 100,
196
+ },
197
+ ],
198
+ },
199
+ yallet_rwa: {
200
+ version: 1,
201
+ assetType,
202
+ direction,
203
+ encryptedDataUri,
204
+ uuid,
205
+ timestamp,
206
+ previousToken,
207
+ schema,
208
+ mimeType,
209
+ dataSize,
210
+ },
211
+ };
212
+ }
213
+
214
+ /**
215
+ * Generate invoice-specific NFT metadata
216
+ *
217
+ * @param invoiceData - Invoice data
218
+ * @param encryptedDataUri - Arweave URI
219
+ * @param owner - Owner's Solana address
220
+ * @param options - Additional options
221
+ * @returns NFT metadata
222
+ */
223
+ export function generateInvoiceMetadata(
224
+ invoiceData: {
225
+ invoiceId: string;
226
+ amount: number;
227
+ currency: string;
228
+ description?: string;
229
+ },
230
+ encryptedDataUri: string,
231
+ owner: string,
232
+ options: {
233
+ uuid?: string;
234
+ timestamp?: number;
235
+ previousToken?: string;
236
+ schema?: string;
237
+ dataSize?: number;
238
+ } = {}
239
+ ): NFTMetadata {
240
+ return generateNFTMetadata({
241
+ name: `Invoice #${invoiceData.invoiceId}`,
242
+ description: invoiceData.description || `Invoice for ${invoiceData.amount} ${invoiceData.currency}`,
243
+ assetType: AssetType.INVOICE,
244
+ encryptedDataUri,
245
+ owner,
246
+ direction: 'sent',
247
+ additionalAttributes: [
248
+ { trait_type: 'Invoice ID', value: invoiceData.invoiceId },
249
+ { trait_type: 'Amount', value: `${invoiceData.amount} ${invoiceData.currency}` },
250
+ ],
251
+ mimeType: 'application/json',
252
+ schema: options.schema || 'yallet-invoice-v1',
253
+ ...options,
254
+ });
255
+ }
256
+
257
+ /**
258
+ * Parsed RWA metadata structure
259
+ */
260
+ export interface ParsedRWAMetadata {
261
+ id: string;
262
+ name: string;
263
+ description: string;
264
+ assetType: AssetType | null;
265
+ direction: string | null;
266
+ encrypted: boolean;
267
+ version: string | null;
268
+ image: string | null;
269
+ encryptedDataUri: string | null;
270
+ owner: string | null;
271
+ // New fields
272
+ uuid: string | null;
273
+ timestamp: number | null;
274
+ previousToken: string | null;
275
+ schema: string | null;
276
+ mimeType: string | null;
277
+ dataSize: number | null;
278
+ }
279
+
280
+ /**
281
+ * Parse RWA NFT metadata from on-chain data
282
+ *
283
+ * @param nftData - NFT data from DAS API
284
+ * @returns Parsed RWA metadata
285
+ */
286
+ export function parseRWAMetadata(nftData: {
287
+ id: string;
288
+ content?: {
289
+ metadata?: {
290
+ name?: string;
291
+ description?: string;
292
+ attributes?: Array<{ trait_type?: string; name?: string; value?: string }>;
293
+ properties?: {
294
+ files?: Array<{ uri?: string; type?: string }>;
295
+ };
296
+ };
297
+ links?: {
298
+ image?: string;
299
+ };
300
+ };
301
+ ownership?: {
302
+ owner?: string;
303
+ };
304
+ }): ParsedRWAMetadata {
305
+ const attributes = nftData.content?.metadata?.attributes || [];
306
+
307
+ const getAttr = (traitType: string): string | null => {
308
+ const attr = attributes.find(
309
+ (a) => (a.trait_type || a.name) === traitType
310
+ );
311
+ return attr?.value || null;
312
+ };
313
+
314
+ const timestampStr = getAttr('Timestamp');
315
+ const dataSizeStr = getAttr('Data Size');
316
+
317
+ return {
318
+ id: nftData.id,
319
+ name: nftData.content?.metadata?.name || 'Unnamed',
320
+ description: nftData.content?.metadata?.description || '',
321
+ assetType: getAttr('Asset Type') as AssetType | null,
322
+ direction: getAttr('Direction'),
323
+ encrypted: getAttr('Encrypted') === 'true',
324
+ version: getAttr('Version'),
325
+ image: nftData.content?.links?.image || null,
326
+ encryptedDataUri: nftData.content?.metadata?.properties?.files?.[0]?.uri || null,
327
+ owner: nftData.ownership?.owner || null,
328
+ // New fields
329
+ uuid: getAttr('UUID'),
330
+ timestamp: timestampStr ? parseInt(timestampStr, 10) : null,
331
+ previousToken: getAttr('Previous Token'),
332
+ schema: getAttr('Schema'),
333
+ mimeType: getAttr('MIME Type') || nftData.content?.metadata?.properties?.files?.[0]?.type || null,
334
+ dataSize: dataSizeStr ? parseInt(dataSizeStr, 10) : null,
335
+ };
336
+ }