@explorins/pers-sdk 1.2.3 → 1.2.4

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 (85) hide show
  1. package/dist/auth-admin/api/auth-admin-api.d.ts +3 -2
  2. package/dist/auth-admin/api/auth-admin-api.d.ts.map +1 -1
  3. package/dist/auth-admin.cjs +7 -3
  4. package/dist/auth-admin.cjs.map +1 -1
  5. package/dist/auth-admin.js +7 -3
  6. package/dist/auth-admin.js.map +1 -1
  7. package/dist/business/api/business-api.d.ts +17 -32
  8. package/dist/business/api/business-api.d.ts.map +1 -1
  9. package/dist/business.cjs +26 -50
  10. package/dist/business.cjs.map +1 -1
  11. package/dist/business.js +26 -50
  12. package/dist/business.js.map +1 -1
  13. package/dist/campaign/api/campaign-api.d.ts +47 -30
  14. package/dist/campaign/api/campaign-api.d.ts.map +1 -1
  15. package/dist/campaign/index.d.ts +5 -5
  16. package/dist/campaign/services/campaign-service.d.ts +6 -6
  17. package/dist/campaign/services/campaign-service.d.ts.map +1 -1
  18. package/dist/campaign.cjs +62 -41
  19. package/dist/campaign.cjs.map +1 -1
  20. package/dist/campaign.js +62 -41
  21. package/dist/campaign.js.map +1 -1
  22. package/dist/index.cjs +719 -439
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.js +718 -440
  25. package/dist/index.js.map +1 -1
  26. package/dist/package.json +1 -1
  27. package/dist/redemption/api/redemption-api.d.ts +58 -14
  28. package/dist/redemption/api/redemption-api.d.ts.map +1 -1
  29. package/dist/redemption/index.d.ts +2 -2
  30. package/dist/redemption/models/index.d.ts +1 -1
  31. package/dist/redemption/models/index.d.ts.map +1 -1
  32. package/dist/redemption/services/redemption-service.d.ts +3 -3
  33. package/dist/redemption/services/redemption-service.d.ts.map +1 -1
  34. package/dist/redemption.cjs +89 -15
  35. package/dist/redemption.cjs.map +1 -1
  36. package/dist/redemption.js +89 -15
  37. package/dist/redemption.js.map +1 -1
  38. package/dist/shared/interfaces/pers-shared-lib.interfaces.d.ts +3 -3
  39. package/dist/shared/interfaces/pers-shared-lib.interfaces.d.ts.map +1 -1
  40. package/dist/transaction/api/transaction-api.d.ts +23 -19
  41. package/dist/transaction/api/transaction-api.d.ts.map +1 -1
  42. package/dist/transaction/index.d.ts +3 -7
  43. package/dist/transaction/index.d.ts.map +1 -1
  44. package/dist/transaction/models/index.d.ts +0 -1
  45. package/dist/transaction/models/index.d.ts.map +1 -1
  46. package/dist/transaction/services/transaction-service.d.ts +5 -7
  47. package/dist/transaction/services/transaction-service.d.ts.map +1 -1
  48. package/dist/transaction.cjs +85 -50
  49. package/dist/transaction.cjs.map +1 -1
  50. package/dist/transaction.js +85 -50
  51. package/dist/transaction.js.map +1 -1
  52. package/dist/web3/application/index.d.ts +6 -0
  53. package/dist/web3/application/index.d.ts.map +1 -0
  54. package/dist/web3/application/web3-application.service.d.ts +53 -0
  55. package/dist/web3/application/web3-application.service.d.ts.map +1 -0
  56. package/dist/web3/domain/models/index.d.ts +58 -0
  57. package/dist/web3/domain/models/index.d.ts.map +1 -0
  58. package/dist/web3/domain/services/contract-domain.service.d.ts +20 -0
  59. package/dist/web3/domain/services/contract-domain.service.d.ts.map +1 -0
  60. package/dist/web3/domain/services/index.d.ts +8 -0
  61. package/dist/web3/domain/services/index.d.ts.map +1 -0
  62. package/dist/web3/domain/services/metadata-domain.service.d.ts +12 -0
  63. package/dist/web3/domain/services/metadata-domain.service.d.ts.map +1 -0
  64. package/dist/web3/domain/services/token-domain.service.d.ts +48 -0
  65. package/dist/web3/domain/services/token-domain.service.d.ts.map +1 -0
  66. package/dist/web3/index.d.ts +10 -11
  67. package/dist/web3/index.d.ts.map +1 -1
  68. package/dist/web3/infrastructure/api/index.d.ts +6 -0
  69. package/dist/web3/infrastructure/api/index.d.ts.map +1 -0
  70. package/dist/web3/infrastructure/api/ipfs-api.d.ts +15 -0
  71. package/dist/web3/infrastructure/api/ipfs-api.d.ts.map +1 -0
  72. package/dist/web3/{api → infrastructure/api}/web3-api.d.ts +6 -2
  73. package/dist/web3/infrastructure/api/web3-api.d.ts.map +1 -0
  74. package/dist/web3/infrastructure/index.d.ts +2 -0
  75. package/dist/web3/infrastructure/index.d.ts.map +1 -0
  76. package/dist/web3.cjs +509 -336
  77. package/dist/web3.cjs.map +1 -1
  78. package/dist/web3.js +507 -336
  79. package/dist/web3.js.map +1 -1
  80. package/package.json +1 -1
  81. package/dist/web3/api/web3-api.d.ts.map +0 -1
  82. package/dist/web3/models/index.d.ts +0 -92
  83. package/dist/web3/models/index.d.ts.map +0 -1
  84. package/dist/web3/services/web3-service.d.ts +0 -21
  85. package/dist/web3/services/web3-service.d.ts.map +0 -1
package/dist/web3.cjs CHANGED
@@ -1,335 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var web3Ts = require('@explorins/web3-ts');
4
3
  var jwtDecode = require('jwt-decode');
5
4
  var Web3 = require('web3');
6
5
  var ethers = require('ethers');
7
-
8
- class Web3Api {
9
- constructor(web3ChainService) {
10
- this.web3ChainService = web3ChainService;
11
- }
12
- async getTokenBalance(request) {
13
- const web3 = await this.web3ChainService.getWeb3ByChainId(request.chainId);
14
- const tokenContract = web3Ts.getSmartContractInstance(request.contractAddress, request.abi, web3);
15
- const balance = await web3Ts.getAddressTokenBalanceByContract(tokenContract, request.accountAddress, request.tokenId);
16
- return Number(balance);
17
- }
18
- async getTokenUri(request) {
19
- const web3 = await this.web3ChainService.getWeb3ByChainId(request.chainId);
20
- // ✅ DIRECT: Use web3-ts functions directly
21
- const tokenContract = web3Ts.getSmartContractInstance(request.contractAddress, request.abi, web3);
22
- const tokenId = Number(request.tokenId);
23
- const tokenUri = await web3Ts.getTokenUri(tokenContract, tokenId);
24
- return String(tokenUri);
25
- }
26
- async getTokenOfOwnerByIndex(request) {
27
- const web3 = await this.web3ChainService.getWeb3ByChainId(request.chainId);
28
- // ✅ DIRECT: Use web3-ts functions directly
29
- const tokenContract = web3Ts.getSmartContractInstance(request.contractAddress, request.abi, web3);
30
- const tokenId = await web3Ts.getTokenOfOwnerByIndex(tokenContract, request.accountAddress, request.tokenIndex);
31
- return String(tokenId);
32
- }
33
- }
34
-
35
- class SimpleCache {
36
- constructor() {
37
- this.storage = {};
38
- this.defaultTTL = 10 * 1000; // 10 seconds
39
- }
40
- set(key, data, ttl) {
41
- this.storage[key] = {
42
- data,
43
- timestamp: Date.now(),
44
- ttl: ttl ?? this.defaultTTL
45
- };
46
- }
47
- get(key) {
48
- const entry = this.storage[key];
49
- if (!entry) {
50
- return null;
51
- }
52
- const now = Date.now();
53
- const isExpired = (now - entry.timestamp) > entry.ttl;
54
- if (isExpired) {
55
- delete this.storage[key];
56
- return null;
57
- }
58
- return entry.data;
59
- }
60
- clear() {
61
- this.storage = {};
62
- }
63
- cleanup() {
64
- const now = Date.now();
65
- Object.keys(this.storage).forEach(key => {
66
- const entry = this.storage[key];
67
- if ((now - entry.timestamp) > entry.ttl) {
68
- delete this.storage[key];
69
- }
70
- });
71
- }
72
- }
73
-
74
- class Web3Service {
75
- constructor(web3Api, web3ChainService) {
76
- this.web3Api = web3Api;
77
- this.web3ChainService = web3ChainService;
78
- //temporary fix, remove when the backend supports custom gateways
79
- this.defaultIpfsGatewayDomain = 'pers.mypinata.cloud';
80
- // ✅ CACHE: Simple 10-second cache instance
81
- this.cache = new SimpleCache();
82
- this.cleanupInterval = null;
83
- this.cleanupInterval = setInterval(() => {
84
- this.cache.cleanup();
85
- }, 30 * 1000);
86
- }
87
- destroy() {
88
- if (this.cleanupInterval) {
89
- clearInterval(this.cleanupInterval);
90
- this.cleanupInterval = null;
91
- }
92
- this.cache.clear();
93
- }
94
- async getERC20Balance(request) {
95
- const cacheKey = `erc20_balance_${request.accountAddress}_${request.token.contractAddress}_${request.token.chainId}`;
96
- // ✅ CACHE CHECK: Try to get from cache first
97
- const cached = this.cache.get(cacheKey);
98
- if (cached) {
99
- console.debug(`💾 [Web3Service] Using cached ERC20 balance for ${request.token.symbol}`);
100
- return cached;
101
- }
102
- console.debug(`🔄 [Web3Service] Fetching fresh ERC20 balance for ${request.token.symbol}`);
103
- const rawBalance = await this.web3Api.getTokenBalance({
104
- accountAddress: request.accountAddress,
105
- contractAddress: request.token.contractAddress,
106
- abi: request.token.abi,
107
- tokenId: null, // Always null for ERC20
108
- chainId: request.token.chainId
109
- });
110
- const decimals = request.token.decimals ?? 18;
111
- const symbol = request.token.symbol ?? 'UNKNOWN';
112
- const response = {
113
- rawBalance,
114
- formattedBalance: this.formatBalance(rawBalance, decimals),
115
- decimals,
116
- symbol,
117
- hasBalance: rawBalance > 0
118
- };
119
- // ✅ CACHE SET: Store result in cache
120
- this.cache.set(cacheKey, response);
121
- return response;
122
- }
123
- async getERC1155Collection(request) {
124
- // ✅ CACHE KEY: Create unique cache key for collection request
125
- const contractAddresses = request.tokens.map(t => t.contractAddress).sort().join(',');
126
- const cacheKey = `erc1155_collection_${request.accountAddress}_${contractAddresses}`;
127
- // ✅ CACHE CHECK: Try to get from cache first
128
- const cached = this.cache.get(cacheKey);
129
- if (cached) {
130
- console.debug(`💾 [Web3Service] Using cached ERC1155 collection for ${request.accountAddress}`);
131
- return cached;
132
- }
133
- console.debug(`🔄 [Web3Service] Fetching fresh ERC1155 collection for ${request.accountAddress}`);
134
- const tokenResults = await Promise.all(request.tokens.map(async (token) => {
135
- // ✅ FIXED: Handle null metadata properly
136
- const tokenIds = token.metadata?.map(m => m.tokenMetadataIncrementalId?.toString()).filter((id) => id !== undefined) ?? [];
137
- // Check balance for each known tokenId
138
- const balanceResults = await Promise.allSettled(tokenIds.map(async (tokenId) => {
139
- try {
140
- const rawBalance = await this.web3Api.getTokenBalance({
141
- accountAddress: request.accountAddress,
142
- contractAddress: token.contractAddress,
143
- abi: token.abi,
144
- tokenId,
145
- chainId: token.chainId
146
- });
147
- const decimals = token.decimals ?? 0; // ERC1155 usually no decimals
148
- return {
149
- tokenId,
150
- balance: rawBalance,
151
- formattedBalance: this.formatBalance(rawBalance, decimals),
152
- hasBalance: rawBalance > 0,
153
- // ✅ FIXED: Convert null to undefined for findMetadata
154
- metadata: this.findMetadata(token.metadata ?? undefined, tokenId)
155
- };
156
- }
157
- catch (error) {
158
- console.warn(`Failed to get balance for token ${token.contractAddress}:${tokenId}`, error);
159
- return null; // Skip failed tokens
160
- }
161
- }));
162
- // Filter successful results with balance > 0
163
- const successfulResults = [];
164
- for (const result of balanceResults) {
165
- if (result.status === 'fulfilled' && result.value !== null && result.value.hasBalance) {
166
- successfulResults.push(result.value);
167
- }
168
- }
169
- return {
170
- token,
171
- results: successfulResults
172
- };
173
- }));
174
- const response = {
175
- accountAddress: request.accountAddress,
176
- tokens: tokenResults.filter(t => t.results.length > 0)
177
- };
178
- // ✅ CACHE SET: Store complete collection result
179
- this.cache.set(cacheKey, response);
180
- return response;
181
- }
182
- async getERC721Collection(request) {
183
- // ✅ CACHE KEY: Create unique cache key for NFT collection
184
- const contractAddresses = request.nftContracts.map(t => t.contractAddress).sort().join(',');
185
- const maxNFTs = request.maxNFTsPerContract || 50;
186
- const cacheKey = `erc721_collection_${request.accountAddress}_${contractAddresses}_${maxNFTs}`;
187
- // ✅ CACHE CHECK: Try to get from cache first
188
- const cached = this.cache.get(cacheKey);
189
- if (cached) {
190
- console.debug(`💾 [Web3Service] Using cached ERC721 collection for ${request.accountAddress}`);
191
- return cached;
192
- }
193
- console.debug(`🔄 [Web3Service] Fetching fresh ERC721 collection for ${request.accountAddress}`);
194
- const startTime = Date.now();
195
- const contractResults = await Promise.all(request.nftContracts.map(async (token) => {
196
- try {
197
- const totalBalance = await this.web3Api.getTokenBalance({
198
- accountAddress: request.accountAddress,
199
- contractAddress: token.contractAddress,
200
- abi: token.abi,
201
- tokenId: null,
202
- chainId: token.chainId
203
- });
204
- if (totalBalance === 0) {
205
- return {
206
- token,
207
- totalNFTs: 0,
208
- nfts: [],
209
- hasMore: false
210
- };
211
- }
212
- const nftsToLoad = Math.min(totalBalance, maxNFTs);
213
- const nftResults = await Promise.allSettled(Array.from({ length: nftsToLoad }, async (_, index) => {
214
- try {
215
- const tokenId = await this.web3Api.getTokenOfOwnerByIndex({
216
- contractAddress: token.contractAddress,
217
- abi: token.abi,
218
- accountAddress: request.accountAddress,
219
- tokenIndex: index,
220
- chainId: token.chainId
221
- });
222
- const tokenUri = await this.web3Api.getTokenUri({
223
- contractAddress: token.contractAddress,
224
- abi: token.abi,
225
- tokenId,
226
- chainId: token.chainId
227
- });
228
- const metadata = await this.fetchMetadata(tokenUri, token.chainId);
229
- const nftItem = {
230
- tokenId,
231
- name: metadata?.name || `Token #${tokenId}`,
232
- description: metadata?.description || '',
233
- imageUrl: await this.resolveIPFSUrl(metadata?.image || '', token.chainId),
234
- rawBalance: 1,
235
- formattedBalance: '1',
236
- hasBalance: true,
237
- metadata,
238
- tokenIndex: index
239
- };
240
- return nftItem;
241
- }
242
- catch (error) {
243
- console.warn(`Failed to load NFT at index ${index} for ${token.symbol}:`, error);
244
- return null;
245
- }
246
- }));
247
- // ✅ FIXED: Usar tipo específico NFTItem
248
- const successfulNFTs = nftResults
249
- .filter((result) => result.status === 'fulfilled' && result.value !== null)
250
- .map(result => result.value);
251
- return {
252
- token,
253
- totalNFTs: totalBalance,
254
- nfts: successfulNFTs,
255
- hasMore: totalBalance > maxNFTs
256
- };
257
- }
258
- catch (error) {
259
- console.error(`Failed to load NFT collection for ${token.symbol}:`, error);
260
- return {
261
- token,
262
- totalNFTs: 0,
263
- nfts: [],
264
- hasMore: false
265
- };
266
- }
267
- }));
268
- const totalNFTs = contractResults.reduce((sum, contract) => sum + contract.nfts.length, 0);
269
- const loadingTime = Date.now() - startTime;
270
- const response = {
271
- accountAddress: request.accountAddress,
272
- contracts: contractResults,
273
- summary: {
274
- totalContracts: request.nftContracts.length,
275
- totalNFTs,
276
- loadingTime
277
- }
278
- };
279
- // ✅ CACHE SET: Store complete collection response
280
- this.cache.set(cacheKey, response);
281
- return response;
282
- }
283
- // ==========================================
284
- // HELPER METHODS
285
- // ==========================================
286
- formatBalance(rawBalance, decimals) {
287
- const balance = rawBalance / Math.pow(10, decimals);
288
- return balance.toLocaleString('en-US', {
289
- minimumFractionDigits: 0,
290
- maximumFractionDigits: decimals > 0 ? 2 : 0
291
- });
292
- }
293
- // ✅ FIXED: Update method signature to handle null properly
294
- findMetadata(metadata, tokenId) {
295
- if (!metadata || tokenId === null)
296
- return null;
297
- return metadata.find(m => m.tokenMetadataIncrementalId?.toString() === tokenId) || null;
298
- }
299
- async fetchMetadata(uri, chainId) {
300
- try {
301
- const httpUrl = await this.resolveIPFSUrl(uri, chainId);
302
- const response = await fetch(httpUrl);
303
- if (!response.ok) {
304
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
305
- }
306
- return await response.json();
307
- }
308
- catch (error) {
309
- console.warn('Failed to fetch NFT metadata:', error);
310
- return null;
311
- }
312
- }
313
- async getIpfsGatewayDomain(chainId) {
314
- try {
315
- const chainData = await this.web3ChainService.getChainDataWithCache(chainId);
316
- return chainData.ipfsGatewayDomain || this.defaultIpfsGatewayDomain;
317
- }
318
- catch (error) {
319
- console.warn(`Failed to get chain data for chainId ${chainId}, using default IPFS gateway:`, error);
320
- return this.defaultIpfsGatewayDomain;
321
- }
322
- }
323
- async resolveIPFSUrl(url, chainId) {
324
- if (!url)
325
- return '';
326
- if (url.startsWith('ipfs://')) {
327
- const gatewayDomain = await this.getIpfsGatewayDomain(chainId);
328
- return `https://${gatewayDomain}/ipfs/${url.slice(7)}`;
329
- }
330
- return url;
331
- }
332
- }
6
+ var web3Ts = require('@explorins/web3-ts');
333
7
 
334
8
  /**
335
9
  * Platform-Agnostic Web3 Chain API Client
@@ -863,22 +537,521 @@ function createWeb3ChainSDK(apiClient, providerService) {
863
537
  };
864
538
  }
865
539
 
866
- //import { PublicHttpProviderService } from '../web3-chain/services/public-http-provider.service';
540
+ /**
541
+ * TokenDomainService - Domain service for token operations
542
+ * Implements business logic for token balance, metadata, and collection operations
543
+ */
544
+ class TokenDomainService {
545
+ constructor(web3Api, metadataService, contractService) {
546
+ this.web3Api = web3Api;
547
+ this.metadataService = metadataService;
548
+ this.contractService = contractService;
549
+ }
550
+ async getTokenBalance(request) {
551
+ const balance = await this.web3Api.getTokenBalance({
552
+ accountAddress: request.accountAddress,
553
+ contractAddress: request.contractAddress,
554
+ abi: request.abi,
555
+ tokenId: request.tokenId,
556
+ chainId: request.chainId
557
+ });
558
+ return {
559
+ tokenId: request.tokenId,
560
+ balance,
561
+ hasBalance: balance > 0,
562
+ metadata: null
563
+ };
564
+ }
565
+ async getTokenWithMetadata(params) {
566
+ try {
567
+ const balance = await this.web3Api.getTokenBalance({
568
+ accountAddress: params.accountAddress,
569
+ contractAddress: params.contractAddress,
570
+ abi: params.abi,
571
+ tokenId: params.tokenId,
572
+ chainId: params.chainId
573
+ });
574
+ let metadata = null;
575
+ if (balance > 0) {
576
+ const tokenUri = await this.web3Api.getTokenUri({
577
+ contractAddress: params.contractAddress,
578
+ abi: params.abi,
579
+ tokenId: params.tokenId,
580
+ chainId: params.chainId
581
+ });
582
+ if (tokenUri) {
583
+ metadata = await this.metadataService.fetchAndProcessMetadata(tokenUri, params.chainId);
584
+ }
585
+ }
586
+ return {
587
+ tokenId: params.tokenId,
588
+ balance,
589
+ hasBalance: balance > 0,
590
+ metadata
591
+ };
592
+ }
593
+ catch (error) {
594
+ console.error('Error getting token with metadata:', error);
595
+ return {
596
+ tokenId: params.tokenId,
597
+ balance: 0,
598
+ hasBalance: false,
599
+ metadata: null
600
+ };
601
+ }
602
+ }
603
+ async getTokenCollection(params) {
604
+ try {
605
+ const contractAnalysis = this.contractService.analyzeContract(params.abi);
606
+ const tokens = [];
607
+ if (!contractAnalysis.hasEnumeration && !contractAnalysis.isERC1155) {
608
+ console.warn('Contract does not support enumeration, cannot retrieve full collection');
609
+ return {
610
+ accountAddress: params.accountAddress,
611
+ contractAddress: params.contractAddress,
612
+ totalBalance: 0,
613
+ tokensRetrieved: 0,
614
+ tokens: [],
615
+ note: 'Contract does not support enumeration'
616
+ };
617
+ }
618
+ else if (contractAnalysis.isERC1155) {
619
+ const tokenIdsToProcess = params.tokenIds || [];
620
+ if (tokenIdsToProcess.length > 0) {
621
+ for (const tokenId of tokenIdsToProcess) {
622
+ const tokenBalance = await this.getTokenWithMetadata({
623
+ accountAddress: params.accountAddress,
624
+ contractAddress: params.contractAddress,
625
+ abi: params.abi,
626
+ tokenId,
627
+ chainId: params.chainId
628
+ });
629
+ tokens.push(tokenBalance);
630
+ }
631
+ }
632
+ console.log('ERC-1155 User balances:', tokens);
633
+ // ERC-1155: Cannot enumerate without knowing token IDs
634
+ // Would need to use events or provide specific token IDs
635
+ console.warn('ERC-1155 collection retrieval requires specific token IDs or event analysis');
636
+ return {
637
+ accountAddress: params.accountAddress,
638
+ contractAddress: params.contractAddress,
639
+ totalBalance: 0,
640
+ tokensRetrieved: 0,
641
+ tokens: tokens,
642
+ note: 'ERC-1155 collection retrieval requires specific token IDs. Use getTokenWithMetadata() for individual tokens.'
643
+ };
644
+ }
645
+ // Handle different token standards
646
+ if (contractAnalysis.isERC721) {
647
+ // ERC-721: Get user's total balance and enumerate through tokens
648
+ const userBalance = await this.web3Api.getTokenBalance({
649
+ accountAddress: params.accountAddress,
650
+ contractAddress: params.contractAddress,
651
+ abi: params.abi,
652
+ tokenId: null, // null for ERC-721 total balance
653
+ chainId: params.chainId
654
+ });
655
+ console.log(`ERC-721 User balance for ${params.accountAddress}:`, userBalance);
656
+ if (userBalance === 0) {
657
+ return {
658
+ accountAddress: params.accountAddress,
659
+ contractAddress: params.contractAddress,
660
+ totalBalance: 0,
661
+ tokensRetrieved: 0,
662
+ tokens: []
663
+ };
664
+ }
665
+ // Enumerate through user's tokens
666
+ const maxTokens = params.maxTokens || userBalance;
667
+ const tokensToRetrieve = Math.min(maxTokens, userBalance);
668
+ for (let i = 0; i < tokensToRetrieve; i++) {
669
+ try {
670
+ const tokenId = await this.web3Api.getTokenOfOwnerByIndex({
671
+ contractAddress: params.contractAddress,
672
+ abi: params.abi,
673
+ accountAddress: params.accountAddress,
674
+ tokenIndex: i,
675
+ chainId: params.chainId
676
+ });
677
+ const tokenWithMetadata = await this.getTokenWithMetadata({
678
+ accountAddress: params.accountAddress,
679
+ contractAddress: params.contractAddress,
680
+ abi: params.abi,
681
+ tokenId,
682
+ chainId: params.chainId
683
+ });
684
+ if (tokenWithMetadata.hasBalance) {
685
+ tokens.push(tokenWithMetadata);
686
+ }
687
+ }
688
+ catch (error) {
689
+ console.warn(`Error retrieving ERC-721 token at index ${i}:`, error);
690
+ continue;
691
+ }
692
+ }
693
+ }
694
+ else {
695
+ // Unknown standard
696
+ return {
697
+ accountAddress: params.accountAddress,
698
+ contractAddress: params.contractAddress,
699
+ totalBalance: 0,
700
+ tokensRetrieved: 0,
701
+ tokens: [],
702
+ note: 'Unsupported token standard for collection retrieval'
703
+ };
704
+ }
705
+ // Calculate total balance based on retrieved tokens
706
+ let totalBalance = 0;
707
+ if (contractAnalysis.isERC721) {
708
+ // For ERC-721, total balance is the number of unique tokens owned
709
+ totalBalance = tokens.length;
710
+ }
711
+ else {
712
+ // For other standards, sum up individual token balances
713
+ totalBalance = tokens.reduce((sum, token) => sum + token.balance, 0);
714
+ }
715
+ return {
716
+ accountAddress: params.accountAddress,
717
+ contractAddress: params.contractAddress,
718
+ totalBalance,
719
+ tokensRetrieved: tokens.length,
720
+ tokens
721
+ };
722
+ }
723
+ catch (error) {
724
+ console.error('Error getting token collection:', error);
725
+ return {
726
+ accountAddress: params.accountAddress,
727
+ contractAddress: params.contractAddress,
728
+ totalBalance: 0,
729
+ tokensRetrieved: 0,
730
+ tokens: [],
731
+ note: 'Error retrieving collection'
732
+ };
733
+ }
734
+ }
735
+ async getTokenMetadata(params) {
736
+ try {
737
+ const tokenUri = await this.web3Api.getTokenUri({
738
+ contractAddress: params.contractAddress,
739
+ abi: params.abi,
740
+ tokenId: params.tokenId,
741
+ chainId: params.chainId
742
+ });
743
+ let metadata = null;
744
+ if (tokenUri) {
745
+ metadata = await this.metadataService.fetchAndProcessMetadata(tokenUri, params.chainId);
746
+ }
747
+ return {
748
+ tokenId: params.tokenId,
749
+ tokenUri,
750
+ metadata
751
+ };
752
+ }
753
+ catch (error) {
754
+ console.error('Error getting token metadata:', error);
755
+ return {
756
+ tokenId: params.tokenId,
757
+ tokenUri: null,
758
+ metadata: null
759
+ };
760
+ }
761
+ }
762
+ }
763
+
764
+ /**
765
+ * MetadataDomainService - Clean IPFS metadata resolution
766
+ */
767
+ class MetadataDomainService {
768
+ constructor(ipfsApi) {
769
+ this.ipfsApi = ipfsApi;
770
+ }
771
+ async fetchAndProcessMetadata(tokenUri, chainId) {
772
+ return this.ipfsApi.fetchAndProcessMetadata(tokenUri, chainId);
773
+ }
774
+ async resolveIPFSUrl(url, chainId) {
775
+ return this.ipfsApi.resolveIPFSUrl(url, chainId);
776
+ }
777
+ }
778
+
779
+ /**
780
+ * ContractDomainService - Clean contract analysis without external dependencies
781
+ */
782
+ class ContractDomainService {
783
+ constructor() { }
784
+ analyzeContract(abi) {
785
+ const methods = abi.filter(item => item.type === 'function').map(item => item.name);
786
+ // ERC-721 detection
787
+ const hasOwnerOf = methods.includes('ownerOf');
788
+ const hasTokenURI = methods.includes('tokenURI');
789
+ const hasTransferFrom = methods.includes('transferFrom');
790
+ const isERC721 = hasOwnerOf && hasTokenURI && hasTransferFrom;
791
+ // ERC-1155 detection
792
+ const hasBalanceOfBatch = methods.includes('balanceOfBatch');
793
+ const hasSafeBatchTransferFrom = methods.includes('safeBatchTransferFrom');
794
+ const hasURI = methods.includes('uri');
795
+ const isERC1155 = hasBalanceOfBatch && hasSafeBatchTransferFrom && hasURI;
796
+ return {
797
+ hasEnumeration: methods.includes('tokenByIndex') && methods.includes('totalSupply'),
798
+ hasOwnerOf,
799
+ hasBalanceOf: methods.includes('balanceOf'),
800
+ hasTokenURI,
801
+ hasTransfer: methods.includes('transfer') || methods.includes('transferFrom'),
802
+ hasApprove: methods.includes('approve'),
803
+ isERC721,
804
+ isERC1155
805
+ };
806
+ }
807
+ supportsEnumeration(abi) {
808
+ return this.analyzeContract(abi).hasEnumeration;
809
+ }
810
+ supportsMethod(abi, methodName) {
811
+ const methods = abi.filter(item => item.type === 'function').map(item => item.name);
812
+ return methods.includes(methodName);
813
+ }
814
+ }
815
+
816
+ /**
817
+ * Web3ApplicationService - Application layer entrance point
818
+ * Orchestrates domain services and provides clean public interface
819
+ * Simplified architecture with concrete classes
820
+ */
821
+ class Web3ApplicationService {
822
+ constructor(web3Api, ipfsApi) {
823
+ // Type-safe metadata conversion methods for ERC-721/ERC-1155 standards
824
+ this.metadataMapper = {
825
+ fromERCStandard: (ercMetadata) => ({
826
+ name: ercMetadata.name || '',
827
+ description: ercMetadata.description || '',
828
+ imageUrl: ercMetadata.image || '',
829
+ externalUrl: ercMetadata.external_url,
830
+ animationUrl: ercMetadata.animation_url,
831
+ animationUrlConverted: undefined, // Will be set by IPFS conversion
832
+ attributes: ercMetadata.attributes || [],
833
+ ...ercMetadata
834
+ }),
835
+ toERCStandard: (metadata) => ({
836
+ name: metadata.name,
837
+ description: metadata.description,
838
+ image: metadata.imageUrl,
839
+ animation_url: metadata.animationUrl,
840
+ external_url: metadata.externalUrl,
841
+ attributes: metadata.attributes,
842
+ ...Object.fromEntries(Object.entries(metadata).filter(([key]) => !['name', 'description', 'imageUrl', 'animationUrl', 'externalUrl', 'attributes', 'animationUrlConverted'].includes(key)))
843
+ })
844
+ };
845
+ // Create domain services with injected infrastructure dependencies
846
+ this.contractDomainService = new ContractDomainService();
847
+ this.metadataDomainService = new MetadataDomainService(ipfsApi);
848
+ this.tokenDomainService = new TokenDomainService(web3Api, this.metadataDomainService, this.contractDomainService);
849
+ }
850
+ /**
851
+ * Get balance and metadata for a specific token
852
+ */
853
+ async getSpecificTokenBalance(request) {
854
+ if (!request.tokenId) {
855
+ return this.tokenDomainService.getTokenBalance({
856
+ accountAddress: request.accountAddress || '',
857
+ contractAddress: request.contractAddress,
858
+ abi: request.abi,
859
+ tokenId: '',
860
+ chainId: request.chainId
861
+ });
862
+ }
863
+ return this.tokenDomainService.getTokenWithMetadata({
864
+ accountAddress: request.accountAddress || '',
865
+ contractAddress: request.contractAddress,
866
+ abi: request.abi,
867
+ tokenId: request.tokenId || '',
868
+ chainId: request.chainId
869
+ });
870
+ }
871
+ /**
872
+ * Get metadata for a specific token from on-chain
873
+ */
874
+ async getTokenMetadata(request) {
875
+ const domainResult = await this.tokenDomainService.getTokenMetadata({
876
+ contractAddress: request.contractAddress,
877
+ abi: request.abi,
878
+ tokenId: request.tokenId || '',
879
+ chainId: request.chainId
880
+ });
881
+ return domainResult.metadata;
882
+ }
883
+ /**
884
+ * Retrieve entire collection of tokens with balance and metadata
885
+ */
886
+ async getTokenCollection(request) {
887
+ return this.tokenDomainService.getTokenCollection({
888
+ accountAddress: request.accountAddress || '',
889
+ contractAddress: request.contractAddress,
890
+ abi: request.abi,
891
+ chainId: request.chainId,
892
+ maxTokens: request.maxTokens,
893
+ tokenIds: request.tokenIds
894
+ });
895
+ }
896
+ /**
897
+ * Resolve IPFS URLs to HTTPS if needed
898
+ */
899
+ async resolveIPFSUrl(url, chainId) {
900
+ return this.metadataDomainService.resolveIPFSUrl(url, chainId);
901
+ }
902
+ /**
903
+ * Fetch and process metadata from URI with IPFS conversion
904
+ */
905
+ async fetchAndProcessMetadata(tokenUri, chainId) {
906
+ const domainMetadata = await this.metadataDomainService.fetchAndProcessMetadata(tokenUri, chainId);
907
+ if (!domainMetadata)
908
+ return null;
909
+ // Convert from ERC token standard to our clean interface
910
+ const cleanMetadata = this.metadataMapper.fromERCStandard(domainMetadata);
911
+ // Add IPFS conversion if needed
912
+ if (cleanMetadata.animationUrl?.startsWith('ipfs://')) {
913
+ return {
914
+ ...cleanMetadata,
915
+ animationUrlConverted: await this.resolveIPFSUrl(cleanMetadata.animationUrl, chainId)
916
+ };
917
+ }
918
+ return cleanMetadata;
919
+ }
920
+ }
921
+
922
+ /**
923
+ * Web3InfrastructureApi - Infrastructure implementation for blockchain operations
924
+ * Uses @explorins/web3-ts for Web3 interactions
925
+ */
926
+ class Web3InfrastructureApi {
927
+ constructor(web3ChainService) {
928
+ this.web3ChainService = web3ChainService;
929
+ }
930
+ async getTokenBalance(request) {
931
+ try {
932
+ if (request.tokenId !== null)
933
+ request.tokenId = request.tokenId.toString();
934
+ const web3 = await this.web3ChainService.getWeb3ByChainId(request.chainId);
935
+ const contract = web3Ts.getSmartContractInstance(request.contractAddress, request.abi, web3);
936
+ return await web3Ts.getAccountTokenBalance(contract, request.accountAddress, request.tokenId);
937
+ }
938
+ catch (error) {
939
+ console.error(`Failed to get token balance for ${request.accountAddress} for ${request.contractAddress} and tokenId ${request.tokenId}, return 0 instead:`, error);
940
+ return 0;
941
+ }
942
+ }
943
+ async getTokenUri(request) {
944
+ try {
945
+ const web3 = await this.web3ChainService.getWeb3ByChainId(request.chainId);
946
+ const contract = web3Ts.getSmartContractInstance(request.contractAddress, request.abi, web3);
947
+ const tokenId = Number(request.tokenId);
948
+ const tokenUri = await web3Ts.getTokenUri(contract, tokenId);
949
+ return String(tokenUri);
950
+ }
951
+ catch (error) {
952
+ console.error(`Failed to get token URI for tokenId ${request.tokenId}:`, error);
953
+ throw error;
954
+ }
955
+ }
956
+ async getTokenOfOwnerByIndex(request) {
957
+ try {
958
+ const web3 = await this.web3ChainService.getWeb3ByChainId(request.chainId);
959
+ const tokenContract = web3Ts.getSmartContractInstance(request.contractAddress, request.abi, web3);
960
+ const tokenId = await web3Ts.getTokenOfOwnerByIndex(tokenContract, request.accountAddress, request.tokenIndex);
961
+ return String(tokenId);
962
+ }
963
+ catch (error) {
964
+ console.error(`Failed to get token by index ${request.tokenIndex} for ${request.accountAddress}:`, error);
965
+ throw error;
966
+ }
967
+ }
968
+ }
969
+
970
+ /**
971
+ * IPFSInfrastructureApi - Infrastructure implementation for IPFS operations
972
+ * Uses Web3ChainService for IPFS gateway resolution
973
+ */
974
+ class IPFSInfrastructureApi {
975
+ constructor(web3ChainService) {
976
+ this.web3ChainService = web3ChainService;
977
+ this.defaultIpfsGatewayDomain = 'pers.mypinata.cloud';
978
+ }
979
+ async getIpfsGatewayDomain(chainId) {
980
+ try {
981
+ const chainData = await this.web3ChainService.getChainDataWithCache(chainId);
982
+ return chainData.ipfsGatewayDomain || this.defaultIpfsGatewayDomain;
983
+ }
984
+ catch (error) {
985
+ console.warn(`Failed to get chain data for chainId ${chainId}, using default IPFS gateway:`, error);
986
+ return this.defaultIpfsGatewayDomain;
987
+ }
988
+ }
989
+ async resolveIPFSUrl(url, chainId) {
990
+ if (url.startsWith('ipfs://')) {
991
+ const gateway = await this.getIpfsGatewayDomain(chainId);
992
+ return url.replace('ipfs://', `https://${gateway}/ipfs/`);
993
+ }
994
+ return url;
995
+ }
996
+ async fetchAndProcessMetadata(tokenUri, chainId) {
997
+ try {
998
+ const resolvedUri = await this.resolveIPFSUrl(tokenUri, chainId);
999
+ const response = await fetch(resolvedUri);
1000
+ if (!response.ok) {
1001
+ throw new Error(`HTTP error! status: ${response.status}`);
1002
+ }
1003
+ const metadata = await response.json();
1004
+ // Process and return clean metadata
1005
+ return {
1006
+ name: metadata.name || '',
1007
+ description: metadata.description || '',
1008
+ image: metadata.image ? await this.resolveIPFSUrl(metadata.image, chainId) : '',
1009
+ attributes: metadata.attributes || [],
1010
+ animation_url: metadata.animation_url ? await this.resolveIPFSUrl(metadata.animation_url, chainId) : undefined,
1011
+ external_url: metadata.external_url || undefined
1012
+ };
1013
+ }
1014
+ catch (error) {
1015
+ console.error('Error fetching metadata:', error);
1016
+ return null;
1017
+ }
1018
+ }
1019
+ async fetchFromUrl(url) {
1020
+ try {
1021
+ const response = await fetch(url);
1022
+ if (!response.ok) {
1023
+ throw new Error(`Failed to fetch from ${url}: ${response.statusText}`);
1024
+ }
1025
+ return await response.json();
1026
+ }
1027
+ catch (error) {
1028
+ console.error(`Error fetching from URL ${url}:`, error);
1029
+ throw error;
1030
+ }
1031
+ }
1032
+ }
1033
+
867
1034
  function createWeb3SDK(apiClient) {
868
1035
  // TODO: FIX LATER - TEMPORARY CONSTRUCTION
869
1036
  const web3ProviderService = new Web3ProviderService();
870
1037
  const web3ChainSDK = createWeb3ChainSDK(apiClient, web3ProviderService);
871
- const web3Api = new Web3Api(web3ChainSDK.service);
872
- const web3Service = new Web3Service(web3Api, web3ChainSDK.service);
1038
+ // Create Web3ApplicationService - main entry point for all Web3 operations
1039
+ const web3InfrastructureApi = new Web3InfrastructureApi(web3ChainSDK.service);
1040
+ const ipfsInfrastructureApi = new IPFSInfrastructureApi(web3ChainSDK.service);
1041
+ const web3ApplicationService = new Web3ApplicationService(web3InfrastructureApi, ipfsInfrastructureApi);
1042
+ // Clean SDK - all functions route through Web3ApplicationService
873
1043
  return {
874
- getCreditsBalance: (request) => web3Service.getERC20Balance(request),
875
- getRewardsCollection: (request) => web3Service.getERC1155Collection(request),
876
- getStampsCollection: (request) => web3Service.getERC721Collection(request),
877
- api: web3Api,
878
- service: web3Service
1044
+ getTokenBalance: (request) => web3ApplicationService.getSpecificTokenBalance(request),
1045
+ getTokenMetadata: (request) => web3ApplicationService.getTokenMetadata(request),
1046
+ getTokenCollection: (request) => web3ApplicationService.getTokenCollection(request),
1047
+ resolveIPFSUrl: (url, chainId) => web3ApplicationService.resolveIPFSUrl(url, chainId),
1048
+ fetchAndProcessMetadata: (tokenUri, chainId) => web3ApplicationService.fetchAndProcessMetadata(tokenUri, chainId),
1049
+ applicationService: web3ApplicationService
879
1050
  };
880
1051
  }
881
1052
 
882
- exports.SimpleCache = SimpleCache;
1053
+ exports.IPFSInfrastructureApi = IPFSInfrastructureApi;
1054
+ exports.Web3ApplicationService = Web3ApplicationService;
1055
+ exports.Web3InfrastructureApi = Web3InfrastructureApi;
883
1056
  exports.createWeb3SDK = createWeb3SDK;
884
1057
  //# sourceMappingURL=web3.cjs.map