@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.
- package/README.md +365 -0
- package/dist/credential-nft-server.d.ts +75 -0
- package/dist/credential-nft-server.d.ts.map +1 -0
- package/dist/credential-nft-server.js +122 -0
- package/dist/credential-nft-server.js.map +1 -0
- package/dist/credential-nft.d.ts +31 -0
- package/dist/credential-nft.d.ts.map +1 -0
- package/dist/credential-nft.js +38 -0
- package/dist/credential-nft.js.map +1 -0
- package/dist/encryption.d.ts +107 -0
- package/dist/encryption.d.ts.map +1 -0
- package/dist/encryption.js +176 -0
- package/dist/encryption.js.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/dist/metadata.d.ts +161 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +180 -0
- package/dist/metadata.js.map +1 -0
- package/dist/minting.d.ts +63 -0
- package/dist/minting.d.ts.map +1 -0
- package/dist/minting.js +194 -0
- package/dist/minting.js.map +1 -0
- package/dist/payloads.d.ts +120 -0
- package/dist/payloads.d.ts.map +1 -0
- package/dist/payloads.js +118 -0
- package/dist/payloads.js.map +1 -0
- package/dist/registry.d.ts +77 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +173 -0
- package/dist/registry.js.map +1 -0
- package/dist/sdk.d.ts +158 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +346 -0
- package/dist/sdk.js.map +1 -0
- package/dist/storage.d.ts +80 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +284 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.d.ts +278 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
- package/src/credential-nft-server.ts +201 -0
- package/src/credential-nft.ts +64 -0
- package/src/encryption.ts +308 -0
- package/src/index.ts +151 -0
- package/src/metadata.ts +336 -0
- package/src/minting.ts +266 -0
- package/src/payloads.ts +238 -0
- package/src/registry.ts +236 -0
- package/src/sdk.ts +507 -0
- package/src/storage.ts +364 -0
- package/src/types.ts +318 -0
- 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';
|
package/src/metadata.ts
ADDED
|
@@ -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
|
+
}
|