@lumiapassport/core 1.14.1 → 1.14.3
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 +125 -108
- package/dist/internal/error-tracking.cjs +1 -1
- package/dist/internal/error-tracking.js +1 -1
- package/dist/read/index.cjs +83 -0
- package/dist/read/index.cjs.map +1 -1
- package/dist/read/index.d.cts +92 -1
- package/dist/read/index.d.ts +92 -1
- package/dist/read/index.js +83 -1
- package/dist/read/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,164 +7,164 @@ Framework-agnostic core SDK for Lumia Passport smart accounts.
|
|
|
7
7
|
- ✅ **Zero React dependencies** - Works in Node.js, browser, and edge functions
|
|
8
8
|
- ✅ **TypeScript-first** - Full type safety
|
|
9
9
|
- ✅ **Modular** - Import only what you need
|
|
10
|
-
- ✅ **Storage abstraction** - Works with
|
|
10
|
+
- ✅ **Storage abstraction** - Works with file storage, memory, or custom storage
|
|
11
11
|
- ✅ **Account Abstraction** - Full ERC-4337 support
|
|
12
12
|
- ✅ **MPC/TSS** - Secure key management
|
|
13
13
|
- ✅ **Server-side wallets** - Backend wallet management with API keys
|
|
14
|
+
- ✅ **Zero configuration** - Works out of the box with Lumia Beam testnet
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
16
17
|
|
|
17
18
|
```bash
|
|
18
|
-
npm install @lumiapassport/core viem
|
|
19
|
+
npm install @lumiapassport/core viem dkls23-wasm
|
|
19
20
|
# or
|
|
20
|
-
pnpm add @lumiapassport/core viem
|
|
21
|
+
pnpm add @lumiapassport/core viem dkls23-wasm
|
|
21
22
|
# or
|
|
22
|
-
yarn add @lumiapassport/core viem
|
|
23
|
+
yarn add @lumiapassport/core viem dkls23-wasm
|
|
23
24
|
```
|
|
24
25
|
|
|
25
|
-
##
|
|
26
|
+
## Quick Start
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
The SDK works out of the box with Lumia Beam testnet. No additional configuration required:
|
|
28
29
|
|
|
29
30
|
```typescript
|
|
30
|
-
import {
|
|
31
|
-
|
|
32
|
-
const core = createLumiaPassportCore({
|
|
33
|
-
tssUrl: process.env.LUMIA_TSS_URL,
|
|
34
|
-
bundlerUrl: process.env.LUMIA_BUNDLER_URL,
|
|
35
|
-
chainId: 2030232745,
|
|
36
|
-
tokenStorage: new MemoryStorage(),
|
|
37
|
-
keyshareStorage: new MemoryStorage(),
|
|
38
|
-
});
|
|
31
|
+
import { createServerWalletManager, MemoryKeyshareStorage } from '@lumiapassport/core';
|
|
39
32
|
|
|
40
|
-
// Create
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
// Create manager with just API key
|
|
34
|
+
const manager = createServerWalletManager({
|
|
35
|
+
apiKey: process.env.LUMIA_PASSPORT_API_KEY!, // Get from dashboard.lumiapassport.com
|
|
36
|
+
storage: new MemoryKeyshareStorage(),
|
|
44
37
|
});
|
|
45
38
|
|
|
46
|
-
//
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
|
|
50
|
-
'1000000000000000000' // 1 ETH in wei
|
|
51
|
-
);
|
|
39
|
+
// Create a wallet
|
|
40
|
+
const wallet = await manager.createWallet('my-wallet');
|
|
41
|
+
console.log('Smart Account address:', wallet.smartAccountAddress);
|
|
52
42
|
```
|
|
53
43
|
|
|
54
|
-
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
### Server-Side Wallets (Recommended)
|
|
47
|
+
|
|
48
|
+
Create and manage backend wallets with a simple high-level API:
|
|
55
49
|
|
|
56
50
|
```typescript
|
|
57
|
-
import {
|
|
51
|
+
import { createServerWalletManager, MemoryKeyshareStorage } from '@lumiapassport/core';
|
|
58
52
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
keyshareStorage: new LocalStorageAdapter(),
|
|
53
|
+
// Create manager
|
|
54
|
+
const manager = createServerWalletManager({
|
|
55
|
+
apiKey: process.env.LUMIA_PASSPORT_API_KEY!, // Get from dashboard.lumiapassport.com
|
|
56
|
+
storage: new MemoryKeyshareStorage(), // Use FileKeyshareStorage or custom storage in production
|
|
64
57
|
});
|
|
65
58
|
|
|
66
|
-
//
|
|
67
|
-
const
|
|
68
|
-
console.log('
|
|
69
|
-
|
|
59
|
+
// Create a wallet (handles all TSS protocol complexity)
|
|
60
|
+
const wallet = await manager.createWallet('treasury_main');
|
|
61
|
+
console.log('Owner address (EOA):', wallet.ownerAddress);
|
|
62
|
+
console.log('Smart Account address:', wallet.smartAccountAddress);
|
|
70
63
|
|
|
71
|
-
|
|
64
|
+
// Send a transaction (Account Abstraction with ERC-4337)
|
|
65
|
+
const userOpHash = await wallet.sendUserOperation(
|
|
66
|
+
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', // recipient
|
|
67
|
+
'1000000000000000000', // 1 ETH in wei
|
|
68
|
+
'0x', // optional contract call data
|
|
69
|
+
'standard' // fee type: 'economy' | 'standard' | 'fast'
|
|
70
|
+
);
|
|
71
|
+
console.log('UserOp hash:', userOpHash);
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
// Wait for transaction confirmation
|
|
74
|
+
const receipt = await manager.waitForUserOperationReceipt(userOpHash);
|
|
75
|
+
console.log('Transaction hash:', receipt.transactionHash);
|
|
76
76
|
|
|
77
|
-
//
|
|
78
|
-
const
|
|
77
|
+
// Sign a message
|
|
78
|
+
const signature = await wallet.signDigest(messageHash);
|
|
79
79
|
|
|
80
|
-
//
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
// List all wallets
|
|
81
|
+
const wallets = await manager.listWallets();
|
|
82
|
+
wallets.forEach(w => {
|
|
83
|
+
console.log(`${w.userId}: ${w.smartAccountAddress}`);
|
|
84
84
|
});
|
|
85
|
+
```
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
throw new Error('Invalid signature');
|
|
88
|
-
}
|
|
87
|
+
### Storage Options
|
|
89
88
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
// Poll for receipt to get transaction hash and status
|
|
95
|
-
const waitForReceipt = async (userOpHash: string, maxAttempts = 60, delayMs = 1000) => {
|
|
96
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
97
|
-
const receipt = await getUserOperationReceipt(userOpHash as `0x${string}`);
|
|
98
|
-
if (receipt) {
|
|
99
|
-
return {
|
|
100
|
-
success: receipt.success,
|
|
101
|
-
transactionHash: receipt.receipt?.transactionHash,
|
|
102
|
-
blockNumber: receipt.receipt?.blockNumber,
|
|
103
|
-
gasUsed: receipt.actualGasUsed,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
107
|
-
}
|
|
108
|
-
throw new Error('Transaction timeout');
|
|
109
|
-
};
|
|
89
|
+
#### MemoryKeyshareStorage (Development only)
|
|
90
|
+
|
|
91
|
+
Simple in-memory storage. **Keyshares are lost on restart!**
|
|
110
92
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
93
|
+
```typescript
|
|
94
|
+
import { MemoryKeyshareStorage } from '@lumiapassport/core';
|
|
95
|
+
|
|
96
|
+
const storage = new MemoryKeyshareStorage();
|
|
114
97
|
```
|
|
115
98
|
|
|
116
|
-
|
|
99
|
+
#### FileKeyshareStorage (Production-ready)
|
|
100
|
+
|
|
101
|
+
Encrypted file-based storage using AES-256-CBC. Available in Node.js only:
|
|
117
102
|
|
|
118
103
|
```typescript
|
|
119
|
-
import {
|
|
104
|
+
import { FileKeyshareStorage } from '@lumiapassport/core/clients/node';
|
|
105
|
+
|
|
106
|
+
const storage = new FileKeyshareStorage({
|
|
107
|
+
storageDir: './data/keyshares',
|
|
108
|
+
encryptionPassword: process.env.LUMIA_PASSPORT_KEYSHARE_ENCRYPTION_PASSWORD!,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Initialize storage directory
|
|
112
|
+
await storage.init();
|
|
120
113
|
|
|
121
|
-
const
|
|
114
|
+
const manager = createServerWalletManager({
|
|
115
|
+
apiKey: process.env.LUMIA_PASSPORT_API_KEY!,
|
|
116
|
+
storage,
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### Custom Storage
|
|
122
121
|
|
|
123
|
-
|
|
124
|
-
const verification = await core.auth.verifyToken(token);
|
|
122
|
+
Implement the `KeyshareStorage` interface for custom backends (AWS KMS, Vault, etc.):
|
|
125
123
|
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
```typescript
|
|
125
|
+
interface KeyshareStorage {
|
|
126
|
+
set(userId: string, keyshare: string): Promise<void> | void;
|
|
127
|
+
get(userId: string): Promise<string | null> | string | null;
|
|
128
|
+
has(userId: string): Promise<boolean> | boolean;
|
|
129
|
+
list(): Promise<string[]> | string[];
|
|
128
130
|
}
|
|
129
131
|
```
|
|
130
132
|
|
|
131
|
-
###
|
|
133
|
+
### Keyshare Backup and Restore
|
|
132
134
|
|
|
133
|
-
|
|
135
|
+
Backup keyshares to Lumia ShareVault for recovery:
|
|
134
136
|
|
|
135
137
|
```typescript
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
MemoryKeyshareStorage,
|
|
139
|
-
} from '@lumiapassport/core';
|
|
138
|
+
// Check if wallet exists on TSS service
|
|
139
|
+
const exists = await manager.walletExists('my-wallet');
|
|
140
140
|
|
|
141
|
-
//
|
|
142
|
-
const
|
|
143
|
-
apiKey: process.env.LUMIA_PASSPORT_API_KEY!, // Get from dashboard
|
|
144
|
-
storage: new MemoryKeyshareStorage(), // Use AWS KMS, Vault, etc. in production
|
|
145
|
-
});
|
|
141
|
+
// Check if we have keyshare locally
|
|
142
|
+
const hasKeyshare = await manager.hasKeyshare('my-wallet');
|
|
146
143
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
console.log('Smart Account address:', wallet.smartAccountAddress);
|
|
144
|
+
if (!hasKeyshare) {
|
|
145
|
+
// Check if backup exists in vault
|
|
146
|
+
const { hasBackup } = await manager.checkBackupExists('my-wallet');
|
|
151
147
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
);
|
|
159
|
-
console.log('Transaction hash:', userOpHash);
|
|
148
|
+
if (hasBackup) {
|
|
149
|
+
// Restore from vault
|
|
150
|
+
await manager.restoreFromVault('my-wallet', process.env.BACKUP_PASSWORD!);
|
|
151
|
+
console.log('Keyshare restored from vault');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
160
154
|
|
|
161
|
-
//
|
|
162
|
-
|
|
155
|
+
// Backup keyshare to vault
|
|
156
|
+
await manager.backupToVault('my-wallet', process.env.BACKUP_PASSWORD!);
|
|
157
|
+
```
|
|
163
158
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
159
|
+
### Using Paymaster (Sponsored Transactions)
|
|
160
|
+
|
|
161
|
+
Configure paymaster for gasless transactions:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
const manager = createServerWalletManager({
|
|
165
|
+
apiKey: process.env.LUMIA_PASSPORT_API_KEY!,
|
|
166
|
+
storage,
|
|
167
|
+
paymasterAddress: '0x...' as `0x${string}`, // Your paymaster contract
|
|
168
168
|
});
|
|
169
169
|
```
|
|
170
170
|
|
|
@@ -381,6 +381,22 @@ const logs = await client.getLogs({
|
|
|
381
381
|
fromBlock: 1000000n,
|
|
382
382
|
toBlock: 'latest',
|
|
383
383
|
});
|
|
384
|
+
|
|
385
|
+
// Get transaction receipt (returns null if pending)
|
|
386
|
+
const receipt = await client.getTransactionReceipt({
|
|
387
|
+
hash: '0x...transactionHash',
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// Wait for transaction to be mined
|
|
391
|
+
const receipt = await client.waitForTransactionReceipt({
|
|
392
|
+
hash: '0x...transactionHash',
|
|
393
|
+
confirmations: 1, // optional, default: 1
|
|
394
|
+
pollingInterval: 4000, // optional, default: 4000ms
|
|
395
|
+
timeout: 60000, // optional, default: 60000ms
|
|
396
|
+
onReplaced: (response) => {
|
|
397
|
+
console.log('Transaction replaced:', response.reason);
|
|
398
|
+
},
|
|
399
|
+
});
|
|
384
400
|
```
|
|
385
401
|
|
|
386
402
|
**Features:**
|
|
@@ -388,6 +404,7 @@ const logs = await client.getLogs({
|
|
|
388
404
|
- **RPC Fallback** - Automatic failover to backup RPCs
|
|
389
405
|
- **Multicall Batching** - Batch reads for better performance
|
|
390
406
|
- **Log Pagination** - Automatic chunking for large block ranges
|
|
407
|
+
- **Transaction Receipts** - Get receipt or wait with polling/timeout
|
|
391
408
|
|
|
392
409
|
## API
|
|
393
410
|
|
|
@@ -45,7 +45,7 @@ function initSdkErrorTracking() {
|
|
|
45
45
|
// Don't track performance for SDK (only errors)
|
|
46
46
|
tracesSampleRate: 0,
|
|
47
47
|
// Release version from package.json
|
|
48
|
-
release: `@lumiapassport/core@${"1.14.
|
|
48
|
+
release: `@lumiapassport/core@${"1.14.3"}`,
|
|
49
49
|
environment: "production",
|
|
50
50
|
// Filter to only track SDK errors
|
|
51
51
|
beforeSend(event) {
|
|
@@ -23,7 +23,7 @@ function initSdkErrorTracking() {
|
|
|
23
23
|
// Don't track performance for SDK (only errors)
|
|
24
24
|
tracesSampleRate: 0,
|
|
25
25
|
// Release version from package.json
|
|
26
|
-
release: `@lumiapassport/core@${"1.14.
|
|
26
|
+
release: `@lumiapassport/core@${"1.14.3"}`,
|
|
27
27
|
environment: "production",
|
|
28
28
|
// Filter to only track SDK errors
|
|
29
29
|
beforeSend(event) {
|
package/dist/read/index.cjs
CHANGED
|
@@ -288,6 +288,17 @@ var ChainNotSupportedError = class extends ReadLayerError {
|
|
|
288
288
|
this.name = "ChainNotSupportedError";
|
|
289
289
|
}
|
|
290
290
|
};
|
|
291
|
+
var TransactionReceiptTimeoutError = class extends ReadLayerError {
|
|
292
|
+
constructor(hash, timeout) {
|
|
293
|
+
super(
|
|
294
|
+
`Transaction receipt not found within ${timeout}ms: ${hash}`,
|
|
295
|
+
"TRANSACTION_RECEIPT_TIMEOUT"
|
|
296
|
+
);
|
|
297
|
+
this.hash = hash;
|
|
298
|
+
this.timeout = timeout;
|
|
299
|
+
this.name = "TransactionReceiptTimeoutError";
|
|
300
|
+
}
|
|
301
|
+
};
|
|
291
302
|
|
|
292
303
|
// src/read/public-client.ts
|
|
293
304
|
var PublicReadClientImpl = class {
|
|
@@ -456,6 +467,77 @@ var PublicReadClientImpl = class {
|
|
|
456
467
|
eventName: "eventName" in log ? log.eventName : void 0
|
|
457
468
|
}));
|
|
458
469
|
}
|
|
470
|
+
async getTransactionReceipt(params) {
|
|
471
|
+
const { hash } = params;
|
|
472
|
+
try {
|
|
473
|
+
const receipt = await this.viemClient.getTransactionReceipt({ hash });
|
|
474
|
+
return this.mapReceipt(receipt);
|
|
475
|
+
} catch (error) {
|
|
476
|
+
if (error instanceof Error && (error.message.includes("could not be found") || error.message.includes("not found"))) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
throw error;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
async waitForTransactionReceipt(params) {
|
|
483
|
+
const {
|
|
484
|
+
hash,
|
|
485
|
+
confirmations = 1,
|
|
486
|
+
pollingInterval = 4e3,
|
|
487
|
+
timeout = 6e4,
|
|
488
|
+
onReplaced
|
|
489
|
+
} = params;
|
|
490
|
+
try {
|
|
491
|
+
const receipt = await this.viemClient.waitForTransactionReceipt({
|
|
492
|
+
hash,
|
|
493
|
+
confirmations,
|
|
494
|
+
pollingInterval,
|
|
495
|
+
timeout,
|
|
496
|
+
onReplaced: onReplaced ? (response) => {
|
|
497
|
+
onReplaced({
|
|
498
|
+
reason: response.reason,
|
|
499
|
+
replacedTransaction: { hash: response.replacedTransaction.hash },
|
|
500
|
+
transaction: { hash: response.transaction.hash },
|
|
501
|
+
transactionReceipt: this.mapReceipt(response.transactionReceipt)
|
|
502
|
+
});
|
|
503
|
+
} : void 0
|
|
504
|
+
});
|
|
505
|
+
return this.mapReceipt(receipt);
|
|
506
|
+
} catch (error) {
|
|
507
|
+
if (error instanceof Error && error.message.includes("timed out")) {
|
|
508
|
+
throw new TransactionReceiptTimeoutError(hash, timeout);
|
|
509
|
+
}
|
|
510
|
+
throw error;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
mapReceipt(receipt) {
|
|
514
|
+
return {
|
|
515
|
+
blockHash: receipt.blockHash,
|
|
516
|
+
blockNumber: receipt.blockNumber,
|
|
517
|
+
contractAddress: receipt.contractAddress,
|
|
518
|
+
cumulativeGasUsed: receipt.cumulativeGasUsed,
|
|
519
|
+
effectiveGasPrice: receipt.effectiveGasPrice,
|
|
520
|
+
from: receipt.from,
|
|
521
|
+
gasUsed: receipt.gasUsed,
|
|
522
|
+
logs: receipt.logs.map((log) => ({
|
|
523
|
+
address: log.address,
|
|
524
|
+
topics: log.topics,
|
|
525
|
+
data: log.data,
|
|
526
|
+
blockNumber: log.blockNumber,
|
|
527
|
+
blockHash: log.blockHash,
|
|
528
|
+
transactionHash: log.transactionHash,
|
|
529
|
+
transactionIndex: log.transactionIndex,
|
|
530
|
+
logIndex: log.logIndex,
|
|
531
|
+
removed: log.removed
|
|
532
|
+
})),
|
|
533
|
+
logsBloom: receipt.logsBloom,
|
|
534
|
+
status: receipt.status,
|
|
535
|
+
to: receipt.to,
|
|
536
|
+
transactionHash: receipt.transactionHash,
|
|
537
|
+
transactionIndex: receipt.transactionIndex,
|
|
538
|
+
type: receipt.type
|
|
539
|
+
};
|
|
540
|
+
}
|
|
459
541
|
clearCache() {
|
|
460
542
|
this.cache?.clear();
|
|
461
543
|
}
|
|
@@ -534,6 +616,7 @@ exports.MULTICALL3_ADDRESS = MULTICALL3_ADDRESS;
|
|
|
534
616
|
exports.RateLimitedError = RateLimitedError;
|
|
535
617
|
exports.ReadLayerError = ReadLayerError;
|
|
536
618
|
exports.RpcConnectionError = RpcConnectionError;
|
|
619
|
+
exports.TransactionReceiptTimeoutError = TransactionReceiptTimeoutError;
|
|
537
620
|
exports.generateCacheKey = generateCacheKey;
|
|
538
621
|
exports.getChainConfig = getChainConfig;
|
|
539
622
|
exports.getPublicClient = getPublicClient;
|
package/dist/read/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/read/cache.ts","../../src/read/rpc-fallback.ts","../../src/read/constants.ts","../../src/read/errors.ts","../../src/read/public-client.ts"],"names":["createPublicClient","http","fallback"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * LRU Cache implementation for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport type { CacheConfig, CacheStats, BlockTag } from './types';\nimport type { Address } from 'viem';\n\n/**\n * Internal cache entry structure\n */\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\n/**\n * Default cache configuration\n */\nexport const DEFAULT_CACHE_CONFIG: CacheConfig = {\n maxSize: 1000,\n ttl: 12000, // 12 seconds (~1 block)\n};\n\n/**\n * LRU Cache with TTL support for blockchain read operations\n */\nexport class LRUCache<T = unknown> {\n private cache: Map<string, CacheEntry<T>>;\n private readonly maxSize: number;\n private readonly ttl: number;\n private hits = 0;\n private misses = 0;\n\n constructor(config: Partial<CacheConfig> = {}) {\n this.maxSize = config.maxSize ?? DEFAULT_CACHE_CONFIG.maxSize;\n this.ttl = config.ttl ?? DEFAULT_CACHE_CONFIG.ttl;\n this.cache = new Map();\n }\n\n /**\n * Get a value from cache\n * Returns undefined if not found or expired\n */\n get(key: string): T | undefined {\n const entry = this.cache.get(key);\n\n if (!entry) {\n this.misses++;\n return undefined;\n }\n\n // Check if expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n this.misses++;\n return undefined;\n }\n\n // Move to end (most recently used) by deleting and re-adding\n this.cache.delete(key);\n this.cache.set(key, entry);\n this.hits++;\n\n return entry.value;\n }\n\n /**\n * Set a value in cache with optional custom TTL\n */\n set(key: string, value: T, customTtl?: number): void {\n // If key exists, delete it first to update position\n if (this.cache.has(key)) {\n this.cache.delete(key);\n }\n\n // Evict oldest entries if at capacity\n while (this.cache.size >= this.maxSize) {\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey !== undefined) {\n this.cache.delete(oldestKey);\n }\n }\n\n const ttlToUse = customTtl ?? this.ttl;\n this.cache.set(key, {\n value,\n expiresAt: Date.now() + ttlToUse,\n });\n }\n\n /**\n * Check if key exists and is not expired\n */\n has(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) return false;\n\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return false;\n }\n\n return true;\n }\n\n /**\n * Delete a specific key\n */\n delete(key: string): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.cache.clear();\n this.hits = 0;\n this.misses = 0;\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n // Clean expired entries before reporting\n this.cleanExpired();\n\n return {\n size: this.cache.size,\n maxSize: this.maxSize,\n hits: this.hits,\n misses: this.misses,\n };\n }\n\n /**\n * Remove expired entries\n */\n private cleanExpired(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n\n/**\n * Generate a deterministic cache key for contract reads\n */\nexport function generateCacheKey(params: {\n chainId: number;\n address: Address;\n functionName: string;\n args: readonly unknown[];\n blockTag: BlockTag;\n from?: Address;\n}): string {\n const keyParts = {\n c: params.chainId,\n a: params.address.toLowerCase(),\n f: params.functionName,\n r: params.args,\n b: serializeBlockTag(params.blockTag),\n s: params.from?.toLowerCase(),\n };\n\n return JSON.stringify(keyParts);\n}\n\n/**\n * Serialize block tag for cache key\n */\nfunction serializeBlockTag(blockTag: BlockTag): string {\n if (typeof blockTag === 'bigint') {\n return `n:${blockTag.toString()}`;\n }\n return blockTag;\n}\n","/**\n * RPC Fallback Transport for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport {\n createPublicClient,\n fallback,\n http,\n type Chain,\n type PublicClient,\n} from 'viem';\n\n/**\n * Configuration for fallback transport\n */\nexport interface FallbackTransportConfig {\n /**\n * RPC URLs in priority order\n */\n urls: string[];\n\n /**\n * Number of retries per endpoint before failover\n * @default 1\n */\n retriesPerEndpoint?: number;\n\n /**\n * Request timeout in ms\n * @default 10000\n */\n timeout?: number;\n}\n\n/**\n * Default configuration\n */\nconst DEFAULT_CONFIG = {\n retriesPerEndpoint: 1,\n timeout: 10000,\n};\n\n/**\n * Create a viem public client with fallback RPC support\n */\nexport function createFallbackClient(\n chain: Chain,\n config: FallbackTransportConfig,\n): PublicClient {\n const {\n urls,\n retriesPerEndpoint = DEFAULT_CONFIG.retriesPerEndpoint,\n timeout = DEFAULT_CONFIG.timeout,\n } = config;\n\n if (urls.length === 0) {\n throw new Error('At least one RPC URL is required');\n }\n\n // For single URL, use simple http transport\n if (urls.length === 1) {\n return createPublicClient({\n chain,\n transport: http(urls[0], { timeout }),\n }) as PublicClient;\n }\n\n // For multiple URLs, use viem's built-in fallback transport\n const transports = urls.map((url) =>\n http(url, {\n timeout,\n retryCount: retriesPerEndpoint,\n retryDelay: 150,\n }),\n );\n\n return createPublicClient({\n chain,\n transport: fallback(transports, {\n rank: true, // Automatically rank transports by latency\n retryCount: 1,\n }),\n }) as PublicClient;\n}\n\n/**\n * Check if an error is recoverable (worth retrying)\n */\nexport function isRecoverableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n\n // Network errors are recoverable\n if (\n message.includes('network') ||\n message.includes('timeout') ||\n message.includes('econnrefused') ||\n message.includes('econnreset') ||\n message.includes('socket')\n ) {\n return true;\n }\n\n // Server errors are recoverable\n if (\n message.includes('500') ||\n message.includes('502') ||\n message.includes('503') ||\n message.includes('504')\n ) {\n return true;\n }\n\n // Rate limits are recoverable with backoff\n if (isRateLimitError(error)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if error is a rate limit error\n */\nfunction isRateLimitError(error: Error): boolean {\n const message = error.message.toLowerCase();\n return (\n message.includes('rate limit') ||\n message.includes('too many requests') ||\n message.includes('429') ||\n message.includes('throttle')\n );\n}\n","/**\n * Blockchain Read Layer - Constants and Chain Configurations\n * @module @lumiapassport/core/read\n */\n\nimport type { Address } from 'viem';\nimport type { ChainConfig } from './types';\n\n/**\n * Well-known Multicall3 contract address\n * Deployed at the same address on most EVM chains\n */\nexport const MULTICALL3_ADDRESS: Address = '0xcA11bde05977b3631167028862bE2a173976CA11';\n\n/**\n * Lumia Mainnet chain ID\n */\nexport const LUMIA_MAINNET_CHAIN_ID = 994873017;\n\n/**\n * Lumia Testnet chain ID\n */\nexport const LUMIA_TESTNET_CHAIN_ID = 1952959480;\n\n/**\n * Lumia Mainnet configuration\n */\nexport const LUMIA_MAINNET: ChainConfig = {\n id: LUMIA_MAINNET_CHAIN_ID,\n name: 'Lumia',\n rpcUrls: ['https://rpc.lumia.org'],\n multicall3: MULTICALL3_ADDRESS,\n blockTime: 2, // ~2 seconds per block\n};\n\n/**\n * Lumia Testnet configuration\n */\nexport const LUMIA_TESTNET: ChainConfig = {\n id: LUMIA_TESTNET_CHAIN_ID,\n name: 'Lumia Testnet',\n rpcUrls: ['https://testnet-rpc.lumia.org'],\n multicall3: MULTICALL3_ADDRESS,\n blockTime: 2,\n};\n\n/**\n * All supported chains with built-in configurations\n */\nexport const SUPPORTED_CHAINS: Map<number, ChainConfig> = new Map([\n [LUMIA_MAINNET_CHAIN_ID, LUMIA_MAINNET],\n [LUMIA_TESTNET_CHAIN_ID, LUMIA_TESTNET],\n]);\n\n/**\n * Get chain configuration by chain ID\n * Returns undefined for unsupported chains\n */\nexport function getChainConfig(chainId: number): ChainConfig | undefined {\n return SUPPORTED_CHAINS.get(chainId);\n}\n\n/**\n * Check if a chain is supported with built-in configuration\n */\nexport function isChainSupported(chainId: number): boolean {\n return SUPPORTED_CHAINS.has(chainId);\n}\n\n/**\n * Default cache TTL in milliseconds (12 seconds, ~1 block)\n */\nexport const DEFAULT_CACHE_TTL = 12000;\n\n/**\n * Default maximum cache entries\n */\nexport const DEFAULT_CACHE_MAX_SIZE = 1000;\n\n/**\n * Default maximum calls per multicall batch\n */\nexport const DEFAULT_MULTICALL_BATCH_SIZE = 100;\n\n/**\n * Default block range for getLogs queries (to avoid RPC limits)\n */\nexport const DEFAULT_LOGS_BLOCK_RANGE = 2000n;\n\n/**\n * Maximum block range for a single getLogs query\n */\nexport const MAX_LOGS_BLOCK_RANGE = 10000n;\n","/**\n * Blockchain Read Layer - Error Classes\n * @module @lumiapassport/core/read\n */\n\nimport type { Address } from 'viem';\n\n/**\n * Base error class for read layer errors\n */\nexport class ReadLayerError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n ) {\n super(message);\n this.name = 'ReadLayerError';\n }\n}\n\n/**\n * Contract does not exist at the specified address\n */\nexport class ContractNotFoundError extends ReadLayerError {\n constructor(\n public readonly address: Address,\n public readonly chainId: number,\n ) {\n super(\n `Contract not found at ${address} on chain ${chainId}`,\n 'CONTRACT_NOT_FOUND',\n );\n this.name = 'ContractNotFoundError';\n }\n}\n\n/**\n * Contract call reverted with a reason\n */\nexport class ContractRevertError extends ReadLayerError {\n constructor(\n public readonly address: Address,\n public readonly functionName: string,\n public readonly reason: string,\n ) {\n super(\n `Contract call to ${functionName} at ${address} reverted: ${reason}`,\n 'CONTRACT_REVERTED',\n );\n this.name = 'ContractRevertError';\n }\n}\n\n/**\n * Failed to connect to RPC endpoint\n */\nexport class RpcConnectionError extends ReadLayerError {\n constructor(\n public readonly url: string,\n public readonly cause?: Error,\n ) {\n super(`Failed to connect to RPC: ${url}`, 'RPC_CONNECTION_FAILED');\n this.name = 'RpcConnectionError';\n }\n}\n\n/**\n * All configured RPC endpoints failed\n */\nexport class AllRpcsFailedError extends ReadLayerError {\n constructor(\n public readonly urls: string[],\n public readonly errors: Error[],\n ) {\n super(\n `All ${urls.length} RPC endpoint(s) failed`,\n 'ALL_RPCS_FAILED',\n );\n this.name = 'AllRpcsFailedError';\n }\n}\n\n/**\n * RPC returned rate limit response\n */\nexport class RateLimitedError extends ReadLayerError {\n constructor(\n public readonly url: string,\n public readonly retryAfter?: number,\n ) {\n super(\n `Rate limited by RPC: ${url}${retryAfter ? `, retry after ${retryAfter}s` : ''}`,\n 'RATE_LIMITED',\n );\n this.name = 'RateLimitedError';\n }\n}\n\n/**\n * Requested block has been pruned from RPC node\n */\nexport class BlockPrunedError extends ReadLayerError {\n constructor(public readonly blockNumber: bigint) {\n super(\n `Block ${blockNumber} has been pruned and is not available`,\n 'BLOCK_PRUNED',\n );\n this.name = 'BlockPrunedError';\n }\n}\n\n/**\n * Invalid ABI provided - function not found\n */\nexport class InvalidAbiError extends ReadLayerError {\n constructor(\n public readonly functionName: string,\n public readonly address: Address,\n ) {\n super(\n `Function '${functionName}' not found in ABI for contract at ${address}`,\n 'INVALID_ABI',\n );\n this.name = 'InvalidAbiError';\n }\n}\n\n/**\n * Chain configuration not found\n */\nexport class ChainNotSupportedError extends ReadLayerError {\n constructor(public readonly chainId: number) {\n super(\n `Chain ${chainId} is not supported. Please provide an RPC URL.`,\n 'CHAIN_NOT_SUPPORTED',\n );\n this.name = 'ChainNotSupportedError';\n }\n}\n","/**\n * Public Client Factory for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport {\n createPublicClient,\n http,\n type Chain,\n type PublicClient as ViemPublicClient,\n type BlockTag as ViemBlockTag,\n} from 'viem';\nimport { LRUCache, generateCacheKey } from './cache';\nimport { createFallbackClient } from './rpc-fallback';\nimport {\n getChainConfig,\n DEFAULT_CACHE_TTL,\n DEFAULT_CACHE_MAX_SIZE,\n MULTICALL3_ADDRESS,\n} from './constants';\nimport { ChainNotSupportedError } from './errors';\nimport type {\n PublicReadClientConfig,\n PublicReadClient,\n ReadContractParams,\n MulticallParams,\n MulticallResult,\n GetLogsParams,\n LogEntry,\n CacheStats,\n ContractCall,\n BlockTag,\n} from './types';\nimport type { Abi, Address } from 'viem';\n\n/**\n * Internal client implementation\n */\nclass PublicReadClientImpl implements PublicReadClient {\n readonly chainId: number;\n private readonly viemClient: ViemPublicClient;\n private readonly cache: LRUCache | null;\n private readonly multicall3Address: Address | null;\n\n constructor(\n chainId: number,\n viemClient: ViemPublicClient,\n cache: LRUCache | null,\n multicall3Address: Address | null,\n ) {\n this.chainId = chainId;\n this.viemClient = viemClient;\n this.cache = cache;\n this.multicall3Address = multicall3Address;\n }\n\n async readContract<TAbi extends Abi, TFunctionName extends string>(\n params: ReadContractParams<TAbi, TFunctionName>,\n ): Promise<unknown> {\n const {\n address,\n abi,\n functionName,\n args = [],\n blockTag = 'latest',\n from,\n forceRefresh = false,\n } = params;\n\n // Check cache first (unless forceRefresh)\n if (this.cache && !forceRefresh) {\n const cacheKey = generateCacheKey({\n chainId: this.chainId,\n address,\n functionName,\n args,\n blockTag,\n from,\n });\n\n const cached = this.cache.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n }\n\n // Make the RPC call\n const result = await this.viemClient.readContract({\n address,\n abi,\n functionName,\n args: args as unknown[],\n blockTag: normalizeBlockTag(blockTag),\n account: from,\n } as Parameters<typeof this.viemClient.readContract>[0]);\n\n // Store in cache\n if (this.cache) {\n const cacheKey = generateCacheKey({\n chainId: this.chainId,\n address,\n functionName,\n args,\n blockTag,\n from,\n });\n this.cache.set(cacheKey, result);\n }\n\n return result;\n }\n\n async multicall<TContracts extends readonly ContractCall[]>(\n params: MulticallParams<TContracts>,\n ): Promise<MulticallResult[]> {\n const {\n contracts,\n allowFailure = true,\n blockTag = 'latest',\n batchSize = 100,\n } = params;\n\n // If no multicall3 or only one contract, use sequential calls\n if (!this.multicall3Address || contracts.length === 1) {\n return this.sequentialMulticall(contracts, allowFailure, blockTag);\n }\n\n // Chunk large batches\n const results: MulticallResult[] = [];\n for (let i = 0; i < contracts.length; i += batchSize) {\n const chunk = contracts.slice(i, i + batchSize);\n const chunkResults = await this.executeMulticallBatch(\n chunk,\n allowFailure,\n blockTag,\n );\n results.push(...chunkResults);\n }\n\n return results;\n }\n\n private async executeMulticallBatch(\n contracts: readonly ContractCall[],\n allowFailure: boolean,\n blockTag: BlockTag,\n ): Promise<MulticallResult[]> {\n try {\n const results = await this.viemClient.multicall({\n contracts: contracts.map((c) => ({\n address: c.address,\n abi: c.abi,\n functionName: c.functionName,\n args: c.args as unknown[],\n })),\n allowFailure,\n blockTag: blockTag as ViemBlockTag,\n multicallAddress: this.multicall3Address!,\n });\n\n // Cast results to known shape - viem returns either success or failure objects\n const typedResults = results as Array<\n { status: 'success'; result: unknown } | { status: 'failure'; error: Error }\n >;\n\n return typedResults.map((r) => {\n if (r.status === 'success') {\n return { status: 'success' as const, result: r.result };\n } else {\n return { status: 'failure' as const, error: r.error };\n }\n });\n } catch (error) {\n // If multicall fails entirely, fall back to sequential\n return this.sequentialMulticall(contracts, allowFailure, blockTag);\n }\n }\n\n private async sequentialMulticall(\n contracts: readonly ContractCall[],\n allowFailure: boolean,\n blockTag: BlockTag,\n ): Promise<MulticallResult[]> {\n const results: MulticallResult[] = [];\n\n for (const contract of contracts) {\n try {\n const result = await this.readContract({\n address: contract.address,\n abi: contract.abi,\n functionName: contract.functionName,\n args: contract.args,\n blockTag,\n });\n results.push({ status: 'success', result });\n } catch (error) {\n if (allowFailure) {\n results.push({\n status: 'failure',\n error: error instanceof Error ? error : new Error(String(error)),\n });\n } else {\n throw error;\n }\n }\n }\n\n return results;\n }\n\n async getLogs(params: GetLogsParams): Promise<LogEntry[]> {\n const { address, event, args, fromBlock, toBlock, blockHash } = params;\n\n // Build parameters conditionally based on what's provided\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const logsParams: any = {};\n\n if (address !== undefined) {\n logsParams.address = address;\n }\n\n if (event !== undefined) {\n logsParams.event = event;\n }\n\n if (args !== undefined) {\n logsParams.args = args;\n }\n\n if (blockHash !== undefined) {\n logsParams.blockHash = blockHash;\n } else {\n if (fromBlock !== undefined) {\n logsParams.fromBlock = normalizeBlockTag(fromBlock);\n }\n if (toBlock !== undefined) {\n logsParams.toBlock = normalizeBlockTag(toBlock);\n }\n }\n\n const logs = await this.viemClient.getLogs(logsParams);\n\n return logs.map((log) => ({\n address: log.address,\n topics: log.topics as [Address, ...Address[]] | [],\n data: log.data,\n blockNumber: log.blockNumber,\n blockHash: log.blockHash,\n transactionHash: log.transactionHash,\n transactionIndex: log.transactionIndex,\n logIndex: log.logIndex,\n removed: log.removed,\n // These properties only exist when an event ABI is provided\n args: 'args' in log ? (log.args as Record<string, unknown>) : undefined,\n eventName: 'eventName' in log ? (log.eventName as string) : undefined,\n }));\n }\n\n clearCache(): void {\n this.cache?.clear();\n }\n\n getCacheStats(): CacheStats {\n if (!this.cache) {\n return { size: 0, maxSize: 0, hits: 0, misses: 0 };\n }\n return this.cache.getStats();\n }\n}\n\n/**\n * Create a public read client for blockchain queries\n *\n * @example\n * ```typescript\n * // Using Lumia mainnet defaults\n * const client = getPublicClient({ chainId: 994873017 });\n *\n * // Using custom RPC with fallbacks\n * const client = getPublicClient({\n * chainId: 1,\n * rpcUrls: ['https://primary.rpc', 'https://fallback.rpc'],\n * });\n * ```\n */\nexport function getPublicClient(config: PublicReadClientConfig): PublicReadClient {\n const {\n chainId,\n rpcUrls,\n multicall3Address,\n cacheTtl = DEFAULT_CACHE_TTL,\n cacheMaxSize = DEFAULT_CACHE_MAX_SIZE,\n disableCache = false,\n } = config;\n\n // Get RPC URLs\n const urls = resolveRpcUrls(chainId, rpcUrls);\n\n // Create chain object for viem\n const chainConfig = getChainConfig(chainId);\n const chain: Chain = {\n id: chainId,\n name: chainConfig?.name ?? `Chain ${chainId}`,\n nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },\n rpcUrls: {\n default: { http: urls },\n },\n };\n\n // Create viem client with fallback support\n let viemClient: ViemPublicClient;\n if (urls.length === 1) {\n viemClient = createPublicClient({\n chain,\n transport: http(urls[0]),\n });\n } else {\n viemClient = createFallbackClient(chain, { urls });\n }\n\n // Create cache if enabled\n const cache = disableCache\n ? null\n : new LRUCache({ maxSize: cacheMaxSize, ttl: cacheTtl });\n\n // Determine multicall3 address\n const resolvedMulticall3 =\n multicall3Address ?? chainConfig?.multicall3 ?? MULTICALL3_ADDRESS;\n\n return new PublicReadClientImpl(chainId, viemClient, cache, resolvedMulticall3);\n}\n\n/**\n * Resolve RPC URLs from config or chain defaults\n */\nfunction resolveRpcUrls(\n chainId: number,\n rpcUrls?: string | string[],\n): string[] {\n // If URLs provided, use them\n if (rpcUrls) {\n return Array.isArray(rpcUrls) ? rpcUrls : [rpcUrls];\n }\n\n // Try to get from chain config\n const chainConfig = getChainConfig(chainId);\n if (chainConfig) {\n return chainConfig.rpcUrls;\n }\n\n // Chain not supported and no URLs provided\n throw new ChainNotSupportedError(chainId);\n}\n\n/**\n * Normalize block tag for viem\n */\nfunction normalizeBlockTag(\n blockTag: BlockTag | bigint,\n): 'latest' | 'pending' | 'safe' | 'finalized' | 'earliest' | bigint {\n if (typeof blockTag === 'bigint') {\n return blockTag;\n }\n return blockTag;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/read/cache.ts","../../src/read/rpc-fallback.ts","../../src/read/constants.ts","../../src/read/errors.ts","../../src/read/public-client.ts"],"names":["createPublicClient","http","fallback"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * LRU Cache implementation for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport type { CacheConfig, CacheStats, BlockTag } from './types';\nimport type { Address } from 'viem';\n\n/**\n * Internal cache entry structure\n */\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\n/**\n * Default cache configuration\n */\nexport const DEFAULT_CACHE_CONFIG: CacheConfig = {\n maxSize: 1000,\n ttl: 12000, // 12 seconds (~1 block)\n};\n\n/**\n * LRU Cache with TTL support for blockchain read operations\n */\nexport class LRUCache<T = unknown> {\n private cache: Map<string, CacheEntry<T>>;\n private readonly maxSize: number;\n private readonly ttl: number;\n private hits = 0;\n private misses = 0;\n\n constructor(config: Partial<CacheConfig> = {}) {\n this.maxSize = config.maxSize ?? DEFAULT_CACHE_CONFIG.maxSize;\n this.ttl = config.ttl ?? DEFAULT_CACHE_CONFIG.ttl;\n this.cache = new Map();\n }\n\n /**\n * Get a value from cache\n * Returns undefined if not found or expired\n */\n get(key: string): T | undefined {\n const entry = this.cache.get(key);\n\n if (!entry) {\n this.misses++;\n return undefined;\n }\n\n // Check if expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n this.misses++;\n return undefined;\n }\n\n // Move to end (most recently used) by deleting and re-adding\n this.cache.delete(key);\n this.cache.set(key, entry);\n this.hits++;\n\n return entry.value;\n }\n\n /**\n * Set a value in cache with optional custom TTL\n */\n set(key: string, value: T, customTtl?: number): void {\n // If key exists, delete it first to update position\n if (this.cache.has(key)) {\n this.cache.delete(key);\n }\n\n // Evict oldest entries if at capacity\n while (this.cache.size >= this.maxSize) {\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey !== undefined) {\n this.cache.delete(oldestKey);\n }\n }\n\n const ttlToUse = customTtl ?? this.ttl;\n this.cache.set(key, {\n value,\n expiresAt: Date.now() + ttlToUse,\n });\n }\n\n /**\n * Check if key exists and is not expired\n */\n has(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) return false;\n\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return false;\n }\n\n return true;\n }\n\n /**\n * Delete a specific key\n */\n delete(key: string): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.cache.clear();\n this.hits = 0;\n this.misses = 0;\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n // Clean expired entries before reporting\n this.cleanExpired();\n\n return {\n size: this.cache.size,\n maxSize: this.maxSize,\n hits: this.hits,\n misses: this.misses,\n };\n }\n\n /**\n * Remove expired entries\n */\n private cleanExpired(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n\n/**\n * Generate a deterministic cache key for contract reads\n */\nexport function generateCacheKey(params: {\n chainId: number;\n address: Address;\n functionName: string;\n args: readonly unknown[];\n blockTag: BlockTag;\n from?: Address;\n}): string {\n const keyParts = {\n c: params.chainId,\n a: params.address.toLowerCase(),\n f: params.functionName,\n r: params.args,\n b: serializeBlockTag(params.blockTag),\n s: params.from?.toLowerCase(),\n };\n\n return JSON.stringify(keyParts);\n}\n\n/**\n * Serialize block tag for cache key\n */\nfunction serializeBlockTag(blockTag: BlockTag): string {\n if (typeof blockTag === 'bigint') {\n return `n:${blockTag.toString()}`;\n }\n return blockTag;\n}\n","/**\n * RPC Fallback Transport for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport {\n createPublicClient,\n fallback,\n http,\n type Chain,\n type PublicClient,\n} from 'viem';\n\n/**\n * Configuration for fallback transport\n */\nexport interface FallbackTransportConfig {\n /**\n * RPC URLs in priority order\n */\n urls: string[];\n\n /**\n * Number of retries per endpoint before failover\n * @default 1\n */\n retriesPerEndpoint?: number;\n\n /**\n * Request timeout in ms\n * @default 10000\n */\n timeout?: number;\n}\n\n/**\n * Default configuration\n */\nconst DEFAULT_CONFIG = {\n retriesPerEndpoint: 1,\n timeout: 10000,\n};\n\n/**\n * Create a viem public client with fallback RPC support\n */\nexport function createFallbackClient(\n chain: Chain,\n config: FallbackTransportConfig,\n): PublicClient {\n const {\n urls,\n retriesPerEndpoint = DEFAULT_CONFIG.retriesPerEndpoint,\n timeout = DEFAULT_CONFIG.timeout,\n } = config;\n\n if (urls.length === 0) {\n throw new Error('At least one RPC URL is required');\n }\n\n // For single URL, use simple http transport\n if (urls.length === 1) {\n return createPublicClient({\n chain,\n transport: http(urls[0], { timeout }),\n }) as PublicClient;\n }\n\n // For multiple URLs, use viem's built-in fallback transport\n const transports = urls.map((url) =>\n http(url, {\n timeout,\n retryCount: retriesPerEndpoint,\n retryDelay: 150,\n }),\n );\n\n return createPublicClient({\n chain,\n transport: fallback(transports, {\n rank: true, // Automatically rank transports by latency\n retryCount: 1,\n }),\n }) as PublicClient;\n}\n\n/**\n * Check if an error is recoverable (worth retrying)\n */\nexport function isRecoverableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n\n // Network errors are recoverable\n if (\n message.includes('network') ||\n message.includes('timeout') ||\n message.includes('econnrefused') ||\n message.includes('econnreset') ||\n message.includes('socket')\n ) {\n return true;\n }\n\n // Server errors are recoverable\n if (\n message.includes('500') ||\n message.includes('502') ||\n message.includes('503') ||\n message.includes('504')\n ) {\n return true;\n }\n\n // Rate limits are recoverable with backoff\n if (isRateLimitError(error)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if error is a rate limit error\n */\nfunction isRateLimitError(error: Error): boolean {\n const message = error.message.toLowerCase();\n return (\n message.includes('rate limit') ||\n message.includes('too many requests') ||\n message.includes('429') ||\n message.includes('throttle')\n );\n}\n","/**\n * Blockchain Read Layer - Constants and Chain Configurations\n * @module @lumiapassport/core/read\n */\n\nimport type { Address } from 'viem';\nimport type { ChainConfig } from './types';\n\n/**\n * Well-known Multicall3 contract address\n * Deployed at the same address on most EVM chains\n */\nexport const MULTICALL3_ADDRESS: Address = '0xcA11bde05977b3631167028862bE2a173976CA11';\n\n/**\n * Lumia Mainnet chain ID\n */\nexport const LUMIA_MAINNET_CHAIN_ID = 994873017;\n\n/**\n * Lumia Testnet chain ID\n */\nexport const LUMIA_TESTNET_CHAIN_ID = 1952959480;\n\n/**\n * Lumia Mainnet configuration\n */\nexport const LUMIA_MAINNET: ChainConfig = {\n id: LUMIA_MAINNET_CHAIN_ID,\n name: 'Lumia',\n rpcUrls: ['https://rpc.lumia.org'],\n multicall3: MULTICALL3_ADDRESS,\n blockTime: 2, // ~2 seconds per block\n};\n\n/**\n * Lumia Testnet configuration\n */\nexport const LUMIA_TESTNET: ChainConfig = {\n id: LUMIA_TESTNET_CHAIN_ID,\n name: 'Lumia Testnet',\n rpcUrls: ['https://testnet-rpc.lumia.org'],\n multicall3: MULTICALL3_ADDRESS,\n blockTime: 2,\n};\n\n/**\n * All supported chains with built-in configurations\n */\nexport const SUPPORTED_CHAINS: Map<number, ChainConfig> = new Map([\n [LUMIA_MAINNET_CHAIN_ID, LUMIA_MAINNET],\n [LUMIA_TESTNET_CHAIN_ID, LUMIA_TESTNET],\n]);\n\n/**\n * Get chain configuration by chain ID\n * Returns undefined for unsupported chains\n */\nexport function getChainConfig(chainId: number): ChainConfig | undefined {\n return SUPPORTED_CHAINS.get(chainId);\n}\n\n/**\n * Check if a chain is supported with built-in configuration\n */\nexport function isChainSupported(chainId: number): boolean {\n return SUPPORTED_CHAINS.has(chainId);\n}\n\n/**\n * Default cache TTL in milliseconds (12 seconds, ~1 block)\n */\nexport const DEFAULT_CACHE_TTL = 12000;\n\n/**\n * Default maximum cache entries\n */\nexport const DEFAULT_CACHE_MAX_SIZE = 1000;\n\n/**\n * Default maximum calls per multicall batch\n */\nexport const DEFAULT_MULTICALL_BATCH_SIZE = 100;\n\n/**\n * Default block range for getLogs queries (to avoid RPC limits)\n */\nexport const DEFAULT_LOGS_BLOCK_RANGE = 2000n;\n\n/**\n * Maximum block range for a single getLogs query\n */\nexport const MAX_LOGS_BLOCK_RANGE = 10000n;\n","/**\n * Blockchain Read Layer - Error Classes\n * @module @lumiapassport/core/read\n */\n\nimport type { Address } from 'viem';\n\n/**\n * Base error class for read layer errors\n */\nexport class ReadLayerError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n ) {\n super(message);\n this.name = 'ReadLayerError';\n }\n}\n\n/**\n * Contract does not exist at the specified address\n */\nexport class ContractNotFoundError extends ReadLayerError {\n constructor(\n public readonly address: Address,\n public readonly chainId: number,\n ) {\n super(\n `Contract not found at ${address} on chain ${chainId}`,\n 'CONTRACT_NOT_FOUND',\n );\n this.name = 'ContractNotFoundError';\n }\n}\n\n/**\n * Contract call reverted with a reason\n */\nexport class ContractRevertError extends ReadLayerError {\n constructor(\n public readonly address: Address,\n public readonly functionName: string,\n public readonly reason: string,\n ) {\n super(\n `Contract call to ${functionName} at ${address} reverted: ${reason}`,\n 'CONTRACT_REVERTED',\n );\n this.name = 'ContractRevertError';\n }\n}\n\n/**\n * Failed to connect to RPC endpoint\n */\nexport class RpcConnectionError extends ReadLayerError {\n constructor(\n public readonly url: string,\n public readonly cause?: Error,\n ) {\n super(`Failed to connect to RPC: ${url}`, 'RPC_CONNECTION_FAILED');\n this.name = 'RpcConnectionError';\n }\n}\n\n/**\n * All configured RPC endpoints failed\n */\nexport class AllRpcsFailedError extends ReadLayerError {\n constructor(\n public readonly urls: string[],\n public readonly errors: Error[],\n ) {\n super(\n `All ${urls.length} RPC endpoint(s) failed`,\n 'ALL_RPCS_FAILED',\n );\n this.name = 'AllRpcsFailedError';\n }\n}\n\n/**\n * RPC returned rate limit response\n */\nexport class RateLimitedError extends ReadLayerError {\n constructor(\n public readonly url: string,\n public readonly retryAfter?: number,\n ) {\n super(\n `Rate limited by RPC: ${url}${retryAfter ? `, retry after ${retryAfter}s` : ''}`,\n 'RATE_LIMITED',\n );\n this.name = 'RateLimitedError';\n }\n}\n\n/**\n * Requested block has been pruned from RPC node\n */\nexport class BlockPrunedError extends ReadLayerError {\n constructor(public readonly blockNumber: bigint) {\n super(\n `Block ${blockNumber} has been pruned and is not available`,\n 'BLOCK_PRUNED',\n );\n this.name = 'BlockPrunedError';\n }\n}\n\n/**\n * Invalid ABI provided - function not found\n */\nexport class InvalidAbiError extends ReadLayerError {\n constructor(\n public readonly functionName: string,\n public readonly address: Address,\n ) {\n super(\n `Function '${functionName}' not found in ABI for contract at ${address}`,\n 'INVALID_ABI',\n );\n this.name = 'InvalidAbiError';\n }\n}\n\n/**\n * Chain configuration not found\n */\nexport class ChainNotSupportedError extends ReadLayerError {\n constructor(public readonly chainId: number) {\n super(\n `Chain ${chainId} is not supported. Please provide an RPC URL.`,\n 'CHAIN_NOT_SUPPORTED',\n );\n this.name = 'ChainNotSupportedError';\n }\n}\n\n/**\n * Transaction receipt not found within timeout period\n */\nexport class TransactionReceiptTimeoutError extends ReadLayerError {\n constructor(\n public readonly hash: string,\n public readonly timeout: number,\n ) {\n super(\n `Transaction receipt not found within ${timeout}ms: ${hash}`,\n 'TRANSACTION_RECEIPT_TIMEOUT',\n );\n this.name = 'TransactionReceiptTimeoutError';\n }\n}\n","/**\n * Public Client Factory for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport {\n createPublicClient,\n http,\n type Chain,\n type PublicClient as ViemPublicClient,\n type BlockTag as ViemBlockTag,\n} from 'viem';\nimport { LRUCache, generateCacheKey } from './cache';\nimport { createFallbackClient } from './rpc-fallback';\nimport {\n getChainConfig,\n DEFAULT_CACHE_TTL,\n DEFAULT_CACHE_MAX_SIZE,\n MULTICALL3_ADDRESS,\n} from './constants';\nimport { ChainNotSupportedError, TransactionReceiptTimeoutError } from './errors';\nimport type {\n PublicReadClientConfig,\n PublicReadClient,\n ReadContractParams,\n MulticallParams,\n MulticallResult,\n GetLogsParams,\n LogEntry,\n CacheStats,\n ContractCall,\n BlockTag,\n GetTransactionReceiptParams,\n WaitForTransactionReceiptParams,\n TransactionReceipt,\n ReplacedTransactionResponse,\n} from './types';\nimport type { Abi, Address } from 'viem';\n\n/**\n * Internal client implementation\n */\nclass PublicReadClientImpl implements PublicReadClient {\n readonly chainId: number;\n private readonly viemClient: ViemPublicClient;\n private readonly cache: LRUCache | null;\n private readonly multicall3Address: Address | null;\n\n constructor(\n chainId: number,\n viemClient: ViemPublicClient,\n cache: LRUCache | null,\n multicall3Address: Address | null,\n ) {\n this.chainId = chainId;\n this.viemClient = viemClient;\n this.cache = cache;\n this.multicall3Address = multicall3Address;\n }\n\n async readContract<TAbi extends Abi, TFunctionName extends string>(\n params: ReadContractParams<TAbi, TFunctionName>,\n ): Promise<unknown> {\n const {\n address,\n abi,\n functionName,\n args = [],\n blockTag = 'latest',\n from,\n forceRefresh = false,\n } = params;\n\n // Check cache first (unless forceRefresh)\n if (this.cache && !forceRefresh) {\n const cacheKey = generateCacheKey({\n chainId: this.chainId,\n address,\n functionName,\n args,\n blockTag,\n from,\n });\n\n const cached = this.cache.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n }\n\n // Make the RPC call\n const result = await this.viemClient.readContract({\n address,\n abi,\n functionName,\n args: args as unknown[],\n blockTag: normalizeBlockTag(blockTag),\n account: from,\n } as Parameters<typeof this.viemClient.readContract>[0]);\n\n // Store in cache\n if (this.cache) {\n const cacheKey = generateCacheKey({\n chainId: this.chainId,\n address,\n functionName,\n args,\n blockTag,\n from,\n });\n this.cache.set(cacheKey, result);\n }\n\n return result;\n }\n\n async multicall<TContracts extends readonly ContractCall[]>(\n params: MulticallParams<TContracts>,\n ): Promise<MulticallResult[]> {\n const {\n contracts,\n allowFailure = true,\n blockTag = 'latest',\n batchSize = 100,\n } = params;\n\n // If no multicall3 or only one contract, use sequential calls\n if (!this.multicall3Address || contracts.length === 1) {\n return this.sequentialMulticall(contracts, allowFailure, blockTag);\n }\n\n // Chunk large batches\n const results: MulticallResult[] = [];\n for (let i = 0; i < contracts.length; i += batchSize) {\n const chunk = contracts.slice(i, i + batchSize);\n const chunkResults = await this.executeMulticallBatch(\n chunk,\n allowFailure,\n blockTag,\n );\n results.push(...chunkResults);\n }\n\n return results;\n }\n\n private async executeMulticallBatch(\n contracts: readonly ContractCall[],\n allowFailure: boolean,\n blockTag: BlockTag,\n ): Promise<MulticallResult[]> {\n try {\n const results = await this.viemClient.multicall({\n contracts: contracts.map((c) => ({\n address: c.address,\n abi: c.abi,\n functionName: c.functionName,\n args: c.args as unknown[],\n })),\n allowFailure,\n blockTag: blockTag as ViemBlockTag,\n multicallAddress: this.multicall3Address!,\n });\n\n // Cast results to known shape - viem returns either success or failure objects\n const typedResults = results as Array<\n { status: 'success'; result: unknown } | { status: 'failure'; error: Error }\n >;\n\n return typedResults.map((r) => {\n if (r.status === 'success') {\n return { status: 'success' as const, result: r.result };\n } else {\n return { status: 'failure' as const, error: r.error };\n }\n });\n } catch (error) {\n // If multicall fails entirely, fall back to sequential\n return this.sequentialMulticall(contracts, allowFailure, blockTag);\n }\n }\n\n private async sequentialMulticall(\n contracts: readonly ContractCall[],\n allowFailure: boolean,\n blockTag: BlockTag,\n ): Promise<MulticallResult[]> {\n const results: MulticallResult[] = [];\n\n for (const contract of contracts) {\n try {\n const result = await this.readContract({\n address: contract.address,\n abi: contract.abi,\n functionName: contract.functionName,\n args: contract.args,\n blockTag,\n });\n results.push({ status: 'success', result });\n } catch (error) {\n if (allowFailure) {\n results.push({\n status: 'failure',\n error: error instanceof Error ? error : new Error(String(error)),\n });\n } else {\n throw error;\n }\n }\n }\n\n return results;\n }\n\n async getLogs(params: GetLogsParams): Promise<LogEntry[]> {\n const { address, event, args, fromBlock, toBlock, blockHash } = params;\n\n // Build parameters conditionally based on what's provided\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const logsParams: any = {};\n\n if (address !== undefined) {\n logsParams.address = address;\n }\n\n if (event !== undefined) {\n logsParams.event = event;\n }\n\n if (args !== undefined) {\n logsParams.args = args;\n }\n\n if (blockHash !== undefined) {\n logsParams.blockHash = blockHash;\n } else {\n if (fromBlock !== undefined) {\n logsParams.fromBlock = normalizeBlockTag(fromBlock);\n }\n if (toBlock !== undefined) {\n logsParams.toBlock = normalizeBlockTag(toBlock);\n }\n }\n\n const logs = await this.viemClient.getLogs(logsParams);\n\n return logs.map((log) => ({\n address: log.address,\n topics: log.topics as [Address, ...Address[]] | [],\n data: log.data,\n blockNumber: log.blockNumber,\n blockHash: log.blockHash,\n transactionHash: log.transactionHash,\n transactionIndex: log.transactionIndex,\n logIndex: log.logIndex,\n removed: log.removed,\n // These properties only exist when an event ABI is provided\n args: 'args' in log ? (log.args as Record<string, unknown>) : undefined,\n eventName: 'eventName' in log ? (log.eventName as string) : undefined,\n }));\n }\n\n async getTransactionReceipt(\n params: GetTransactionReceiptParams,\n ): Promise<TransactionReceipt | null> {\n const { hash } = params;\n\n try {\n const receipt = await this.viemClient.getTransactionReceipt({ hash });\n return this.mapReceipt(receipt);\n } catch (error) {\n // Transaction not found or pending\n if (\n error instanceof Error &&\n (error.message.includes('could not be found') ||\n error.message.includes('not found'))\n ) {\n return null;\n }\n throw error;\n }\n }\n\n async waitForTransactionReceipt(\n params: WaitForTransactionReceiptParams,\n ): Promise<TransactionReceipt> {\n const {\n hash,\n confirmations = 1,\n pollingInterval = 4000,\n timeout = 60000,\n onReplaced,\n } = params;\n\n try {\n const receipt = await this.viemClient.waitForTransactionReceipt({\n hash,\n confirmations,\n pollingInterval,\n timeout,\n onReplaced: onReplaced\n ? (response) => {\n onReplaced({\n reason: response.reason,\n replacedTransaction: { hash: response.replacedTransaction.hash },\n transaction: { hash: response.transaction.hash },\n transactionReceipt: this.mapReceipt(response.transactionReceipt),\n } as ReplacedTransactionResponse);\n }\n : undefined,\n });\n return this.mapReceipt(receipt);\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('timed out')\n ) {\n throw new TransactionReceiptTimeoutError(hash, timeout);\n }\n throw error;\n }\n }\n\n private mapReceipt(\n receipt: Awaited<ReturnType<typeof this.viemClient.getTransactionReceipt>>,\n ): TransactionReceipt {\n return {\n blockHash: receipt.blockHash,\n blockNumber: receipt.blockNumber,\n contractAddress: receipt.contractAddress,\n cumulativeGasUsed: receipt.cumulativeGasUsed,\n effectiveGasPrice: receipt.effectiveGasPrice,\n from: receipt.from,\n gasUsed: receipt.gasUsed,\n logs: receipt.logs.map((log) => ({\n address: log.address,\n topics: log.topics as [Address, ...Address[]] | [],\n data: log.data,\n blockNumber: log.blockNumber,\n blockHash: log.blockHash,\n transactionHash: log.transactionHash,\n transactionIndex: log.transactionIndex,\n logIndex: log.logIndex,\n removed: log.removed,\n })),\n logsBloom: receipt.logsBloom,\n status: receipt.status,\n to: receipt.to,\n transactionHash: receipt.transactionHash,\n transactionIndex: receipt.transactionIndex,\n type: receipt.type,\n };\n }\n\n clearCache(): void {\n this.cache?.clear();\n }\n\n getCacheStats(): CacheStats {\n if (!this.cache) {\n return { size: 0, maxSize: 0, hits: 0, misses: 0 };\n }\n return this.cache.getStats();\n }\n}\n\n/**\n * Create a public read client for blockchain queries\n *\n * @example\n * ```typescript\n * // Using Lumia mainnet defaults\n * const client = getPublicClient({ chainId: 994873017 });\n *\n * // Using custom RPC with fallbacks\n * const client = getPublicClient({\n * chainId: 1,\n * rpcUrls: ['https://primary.rpc', 'https://fallback.rpc'],\n * });\n * ```\n */\nexport function getPublicClient(config: PublicReadClientConfig): PublicReadClient {\n const {\n chainId,\n rpcUrls,\n multicall3Address,\n cacheTtl = DEFAULT_CACHE_TTL,\n cacheMaxSize = DEFAULT_CACHE_MAX_SIZE,\n disableCache = false,\n } = config;\n\n // Get RPC URLs\n const urls = resolveRpcUrls(chainId, rpcUrls);\n\n // Create chain object for viem\n const chainConfig = getChainConfig(chainId);\n const chain: Chain = {\n id: chainId,\n name: chainConfig?.name ?? `Chain ${chainId}`,\n nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },\n rpcUrls: {\n default: { http: urls },\n },\n };\n\n // Create viem client with fallback support\n let viemClient: ViemPublicClient;\n if (urls.length === 1) {\n viemClient = createPublicClient({\n chain,\n transport: http(urls[0]),\n });\n } else {\n viemClient = createFallbackClient(chain, { urls });\n }\n\n // Create cache if enabled\n const cache = disableCache\n ? null\n : new LRUCache({ maxSize: cacheMaxSize, ttl: cacheTtl });\n\n // Determine multicall3 address\n const resolvedMulticall3 =\n multicall3Address ?? chainConfig?.multicall3 ?? MULTICALL3_ADDRESS;\n\n return new PublicReadClientImpl(chainId, viemClient, cache, resolvedMulticall3);\n}\n\n/**\n * Resolve RPC URLs from config or chain defaults\n */\nfunction resolveRpcUrls(\n chainId: number,\n rpcUrls?: string | string[],\n): string[] {\n // If URLs provided, use them\n if (rpcUrls) {\n return Array.isArray(rpcUrls) ? rpcUrls : [rpcUrls];\n }\n\n // Try to get from chain config\n const chainConfig = getChainConfig(chainId);\n if (chainConfig) {\n return chainConfig.rpcUrls;\n }\n\n // Chain not supported and no URLs provided\n throw new ChainNotSupportedError(chainId);\n}\n\n/**\n * Normalize block tag for viem\n */\nfunction normalizeBlockTag(\n blockTag: BlockTag | bigint,\n): 'latest' | 'pending' | 'safe' | 'finalized' | 'earliest' | bigint {\n if (typeof blockTag === 'bigint') {\n return blockTag;\n }\n return blockTag;\n}\n"]}
|
package/dist/read/index.d.cts
CHANGED
|
@@ -229,6 +229,79 @@ interface CacheConfig {
|
|
|
229
229
|
*/
|
|
230
230
|
ttl: number;
|
|
231
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Parameters for getting a transaction receipt
|
|
234
|
+
*/
|
|
235
|
+
interface GetTransactionReceiptParams {
|
|
236
|
+
/**
|
|
237
|
+
* Transaction hash to get receipt for
|
|
238
|
+
*/
|
|
239
|
+
hash: Hash;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Parameters for waiting for a transaction receipt
|
|
243
|
+
*/
|
|
244
|
+
interface WaitForTransactionReceiptParams {
|
|
245
|
+
/**
|
|
246
|
+
* Transaction hash to wait for
|
|
247
|
+
*/
|
|
248
|
+
hash: Hash;
|
|
249
|
+
/**
|
|
250
|
+
* Number of block confirmations to wait for
|
|
251
|
+
* @default 1
|
|
252
|
+
*/
|
|
253
|
+
confirmations?: number;
|
|
254
|
+
/**
|
|
255
|
+
* Polling interval in milliseconds
|
|
256
|
+
* @default 4000
|
|
257
|
+
*/
|
|
258
|
+
pollingInterval?: number;
|
|
259
|
+
/**
|
|
260
|
+
* Timeout in milliseconds
|
|
261
|
+
* @default 60000
|
|
262
|
+
*/
|
|
263
|
+
timeout?: number;
|
|
264
|
+
/**
|
|
265
|
+
* Callback when transaction is replaced (speed-up or cancelled)
|
|
266
|
+
*/
|
|
267
|
+
onReplaced?: (response: ReplacedTransactionResponse) => void;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Transaction type
|
|
271
|
+
*/
|
|
272
|
+
type TransactionType = 'legacy' | 'eip2930' | 'eip1559' | 'eip4844' | 'eip7702' | (string & {});
|
|
273
|
+
/**
|
|
274
|
+
* Transaction receipt
|
|
275
|
+
*/
|
|
276
|
+
interface TransactionReceipt {
|
|
277
|
+
blockHash: Hash;
|
|
278
|
+
blockNumber: bigint;
|
|
279
|
+
contractAddress: Address | null | undefined;
|
|
280
|
+
cumulativeGasUsed: bigint;
|
|
281
|
+
effectiveGasPrice: bigint;
|
|
282
|
+
from: Address;
|
|
283
|
+
gasUsed: bigint;
|
|
284
|
+
logs: LogEntry[];
|
|
285
|
+
logsBloom: Hex;
|
|
286
|
+
status: 'success' | 'reverted';
|
|
287
|
+
to: Address | null;
|
|
288
|
+
transactionHash: Hash;
|
|
289
|
+
transactionIndex: number;
|
|
290
|
+
type: TransactionType;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Response when a transaction is replaced (speed-up or cancelled)
|
|
294
|
+
*/
|
|
295
|
+
interface ReplacedTransactionResponse {
|
|
296
|
+
reason: 'replaced' | 'repriced' | 'cancelled';
|
|
297
|
+
replacedTransaction: {
|
|
298
|
+
hash: Hash;
|
|
299
|
+
};
|
|
300
|
+
transaction: {
|
|
301
|
+
hash: Hash;
|
|
302
|
+
};
|
|
303
|
+
transactionReceipt: TransactionReceipt;
|
|
304
|
+
}
|
|
232
305
|
/**
|
|
233
306
|
* Public read client interface - the main API surface
|
|
234
307
|
*/
|
|
@@ -249,6 +322,16 @@ interface PublicReadClient {
|
|
|
249
322
|
* Query historical event logs
|
|
250
323
|
*/
|
|
251
324
|
getLogs(params: GetLogsParams): Promise<LogEntry[]>;
|
|
325
|
+
/**
|
|
326
|
+
* Get transaction receipt by hash
|
|
327
|
+
* Returns null if transaction is pending or not found
|
|
328
|
+
*/
|
|
329
|
+
getTransactionReceipt(params: GetTransactionReceiptParams): Promise<TransactionReceipt | null>;
|
|
330
|
+
/**
|
|
331
|
+
* Wait for transaction to be mined and return receipt
|
|
332
|
+
* Throws TransactionReceiptTimeoutError if timeout exceeded
|
|
333
|
+
*/
|
|
334
|
+
waitForTransactionReceipt(params: WaitForTransactionReceiptParams): Promise<TransactionReceipt>;
|
|
252
335
|
/**
|
|
253
336
|
* Clear all cached entries
|
|
254
337
|
*/
|
|
@@ -356,6 +439,14 @@ declare class ChainNotSupportedError extends ReadLayerError {
|
|
|
356
439
|
readonly chainId: number;
|
|
357
440
|
constructor(chainId: number);
|
|
358
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* Transaction receipt not found within timeout period
|
|
444
|
+
*/
|
|
445
|
+
declare class TransactionReceiptTimeoutError extends ReadLayerError {
|
|
446
|
+
readonly hash: string;
|
|
447
|
+
readonly timeout: number;
|
|
448
|
+
constructor(hash: string, timeout: number);
|
|
449
|
+
}
|
|
359
450
|
|
|
360
451
|
/**
|
|
361
452
|
* Blockchain Read Layer - Constants and Chain Configurations
|
|
@@ -466,4 +557,4 @@ declare function generateCacheKey(params: {
|
|
|
466
557
|
from?: Address;
|
|
467
558
|
}): string;
|
|
468
559
|
|
|
469
|
-
export { type AbiEventDefinition, AllRpcsFailedError, BlockPrunedError, type BlockTag, type CacheConfig, type CacheStats, type ChainConfig, ChainNotSupportedError, type ContractCall, ContractNotFoundError, ContractRevertError, DEFAULT_CACHE_CONFIG, DEFAULT_CACHE_MAX_SIZE, DEFAULT_CACHE_TTL, DEFAULT_MULTICALL_BATCH_SIZE, type EventArgs, type GetLogsParams, InvalidAbiError, LRUCache, LUMIA_MAINNET, LUMIA_MAINNET_CHAIN_ID, LUMIA_TESTNET, LUMIA_TESTNET_CHAIN_ID, type LogEntry, MULTICALL3_ADDRESS, type MulticallFailure, type MulticallParams, type MulticallResult, type MulticallSuccess, type PublicReadClient, type PublicReadClientConfig, RateLimitedError, type ReadContractParams, ReadLayerError, RpcConnectionError, generateCacheKey, getChainConfig, getPublicClient, isChainSupported };
|
|
560
|
+
export { type AbiEventDefinition, AllRpcsFailedError, BlockPrunedError, type BlockTag, type CacheConfig, type CacheStats, type ChainConfig, ChainNotSupportedError, type ContractCall, ContractNotFoundError, ContractRevertError, DEFAULT_CACHE_CONFIG, DEFAULT_CACHE_MAX_SIZE, DEFAULT_CACHE_TTL, DEFAULT_MULTICALL_BATCH_SIZE, type EventArgs, type GetLogsParams, type GetTransactionReceiptParams, InvalidAbiError, LRUCache, LUMIA_MAINNET, LUMIA_MAINNET_CHAIN_ID, LUMIA_TESTNET, LUMIA_TESTNET_CHAIN_ID, type LogEntry, MULTICALL3_ADDRESS, type MulticallFailure, type MulticallParams, type MulticallResult, type MulticallSuccess, type PublicReadClient, type PublicReadClientConfig, RateLimitedError, type ReadContractParams, ReadLayerError, type ReplacedTransactionResponse, RpcConnectionError, type TransactionReceipt, TransactionReceiptTimeoutError, type TransactionType, type WaitForTransactionReceiptParams, generateCacheKey, getChainConfig, getPublicClient, isChainSupported };
|
package/dist/read/index.d.ts
CHANGED
|
@@ -229,6 +229,79 @@ interface CacheConfig {
|
|
|
229
229
|
*/
|
|
230
230
|
ttl: number;
|
|
231
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Parameters for getting a transaction receipt
|
|
234
|
+
*/
|
|
235
|
+
interface GetTransactionReceiptParams {
|
|
236
|
+
/**
|
|
237
|
+
* Transaction hash to get receipt for
|
|
238
|
+
*/
|
|
239
|
+
hash: Hash;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Parameters for waiting for a transaction receipt
|
|
243
|
+
*/
|
|
244
|
+
interface WaitForTransactionReceiptParams {
|
|
245
|
+
/**
|
|
246
|
+
* Transaction hash to wait for
|
|
247
|
+
*/
|
|
248
|
+
hash: Hash;
|
|
249
|
+
/**
|
|
250
|
+
* Number of block confirmations to wait for
|
|
251
|
+
* @default 1
|
|
252
|
+
*/
|
|
253
|
+
confirmations?: number;
|
|
254
|
+
/**
|
|
255
|
+
* Polling interval in milliseconds
|
|
256
|
+
* @default 4000
|
|
257
|
+
*/
|
|
258
|
+
pollingInterval?: number;
|
|
259
|
+
/**
|
|
260
|
+
* Timeout in milliseconds
|
|
261
|
+
* @default 60000
|
|
262
|
+
*/
|
|
263
|
+
timeout?: number;
|
|
264
|
+
/**
|
|
265
|
+
* Callback when transaction is replaced (speed-up or cancelled)
|
|
266
|
+
*/
|
|
267
|
+
onReplaced?: (response: ReplacedTransactionResponse) => void;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Transaction type
|
|
271
|
+
*/
|
|
272
|
+
type TransactionType = 'legacy' | 'eip2930' | 'eip1559' | 'eip4844' | 'eip7702' | (string & {});
|
|
273
|
+
/**
|
|
274
|
+
* Transaction receipt
|
|
275
|
+
*/
|
|
276
|
+
interface TransactionReceipt {
|
|
277
|
+
blockHash: Hash;
|
|
278
|
+
blockNumber: bigint;
|
|
279
|
+
contractAddress: Address | null | undefined;
|
|
280
|
+
cumulativeGasUsed: bigint;
|
|
281
|
+
effectiveGasPrice: bigint;
|
|
282
|
+
from: Address;
|
|
283
|
+
gasUsed: bigint;
|
|
284
|
+
logs: LogEntry[];
|
|
285
|
+
logsBloom: Hex;
|
|
286
|
+
status: 'success' | 'reverted';
|
|
287
|
+
to: Address | null;
|
|
288
|
+
transactionHash: Hash;
|
|
289
|
+
transactionIndex: number;
|
|
290
|
+
type: TransactionType;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Response when a transaction is replaced (speed-up or cancelled)
|
|
294
|
+
*/
|
|
295
|
+
interface ReplacedTransactionResponse {
|
|
296
|
+
reason: 'replaced' | 'repriced' | 'cancelled';
|
|
297
|
+
replacedTransaction: {
|
|
298
|
+
hash: Hash;
|
|
299
|
+
};
|
|
300
|
+
transaction: {
|
|
301
|
+
hash: Hash;
|
|
302
|
+
};
|
|
303
|
+
transactionReceipt: TransactionReceipt;
|
|
304
|
+
}
|
|
232
305
|
/**
|
|
233
306
|
* Public read client interface - the main API surface
|
|
234
307
|
*/
|
|
@@ -249,6 +322,16 @@ interface PublicReadClient {
|
|
|
249
322
|
* Query historical event logs
|
|
250
323
|
*/
|
|
251
324
|
getLogs(params: GetLogsParams): Promise<LogEntry[]>;
|
|
325
|
+
/**
|
|
326
|
+
* Get transaction receipt by hash
|
|
327
|
+
* Returns null if transaction is pending or not found
|
|
328
|
+
*/
|
|
329
|
+
getTransactionReceipt(params: GetTransactionReceiptParams): Promise<TransactionReceipt | null>;
|
|
330
|
+
/**
|
|
331
|
+
* Wait for transaction to be mined and return receipt
|
|
332
|
+
* Throws TransactionReceiptTimeoutError if timeout exceeded
|
|
333
|
+
*/
|
|
334
|
+
waitForTransactionReceipt(params: WaitForTransactionReceiptParams): Promise<TransactionReceipt>;
|
|
252
335
|
/**
|
|
253
336
|
* Clear all cached entries
|
|
254
337
|
*/
|
|
@@ -356,6 +439,14 @@ declare class ChainNotSupportedError extends ReadLayerError {
|
|
|
356
439
|
readonly chainId: number;
|
|
357
440
|
constructor(chainId: number);
|
|
358
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* Transaction receipt not found within timeout period
|
|
444
|
+
*/
|
|
445
|
+
declare class TransactionReceiptTimeoutError extends ReadLayerError {
|
|
446
|
+
readonly hash: string;
|
|
447
|
+
readonly timeout: number;
|
|
448
|
+
constructor(hash: string, timeout: number);
|
|
449
|
+
}
|
|
359
450
|
|
|
360
451
|
/**
|
|
361
452
|
* Blockchain Read Layer - Constants and Chain Configurations
|
|
@@ -466,4 +557,4 @@ declare function generateCacheKey(params: {
|
|
|
466
557
|
from?: Address;
|
|
467
558
|
}): string;
|
|
468
559
|
|
|
469
|
-
export { type AbiEventDefinition, AllRpcsFailedError, BlockPrunedError, type BlockTag, type CacheConfig, type CacheStats, type ChainConfig, ChainNotSupportedError, type ContractCall, ContractNotFoundError, ContractRevertError, DEFAULT_CACHE_CONFIG, DEFAULT_CACHE_MAX_SIZE, DEFAULT_CACHE_TTL, DEFAULT_MULTICALL_BATCH_SIZE, type EventArgs, type GetLogsParams, InvalidAbiError, LRUCache, LUMIA_MAINNET, LUMIA_MAINNET_CHAIN_ID, LUMIA_TESTNET, LUMIA_TESTNET_CHAIN_ID, type LogEntry, MULTICALL3_ADDRESS, type MulticallFailure, type MulticallParams, type MulticallResult, type MulticallSuccess, type PublicReadClient, type PublicReadClientConfig, RateLimitedError, type ReadContractParams, ReadLayerError, RpcConnectionError, generateCacheKey, getChainConfig, getPublicClient, isChainSupported };
|
|
560
|
+
export { type AbiEventDefinition, AllRpcsFailedError, BlockPrunedError, type BlockTag, type CacheConfig, type CacheStats, type ChainConfig, ChainNotSupportedError, type ContractCall, ContractNotFoundError, ContractRevertError, DEFAULT_CACHE_CONFIG, DEFAULT_CACHE_MAX_SIZE, DEFAULT_CACHE_TTL, DEFAULT_MULTICALL_BATCH_SIZE, type EventArgs, type GetLogsParams, type GetTransactionReceiptParams, InvalidAbiError, LRUCache, LUMIA_MAINNET, LUMIA_MAINNET_CHAIN_ID, LUMIA_TESTNET, LUMIA_TESTNET_CHAIN_ID, type LogEntry, MULTICALL3_ADDRESS, type MulticallFailure, type MulticallParams, type MulticallResult, type MulticallSuccess, type PublicReadClient, type PublicReadClientConfig, RateLimitedError, type ReadContractParams, ReadLayerError, type ReplacedTransactionResponse, RpcConnectionError, type TransactionReceipt, TransactionReceiptTimeoutError, type TransactionType, type WaitForTransactionReceiptParams, generateCacheKey, getChainConfig, getPublicClient, isChainSupported };
|
package/dist/read/index.js
CHANGED
|
@@ -286,6 +286,17 @@ var ChainNotSupportedError = class extends ReadLayerError {
|
|
|
286
286
|
this.name = "ChainNotSupportedError";
|
|
287
287
|
}
|
|
288
288
|
};
|
|
289
|
+
var TransactionReceiptTimeoutError = class extends ReadLayerError {
|
|
290
|
+
constructor(hash, timeout) {
|
|
291
|
+
super(
|
|
292
|
+
`Transaction receipt not found within ${timeout}ms: ${hash}`,
|
|
293
|
+
"TRANSACTION_RECEIPT_TIMEOUT"
|
|
294
|
+
);
|
|
295
|
+
this.hash = hash;
|
|
296
|
+
this.timeout = timeout;
|
|
297
|
+
this.name = "TransactionReceiptTimeoutError";
|
|
298
|
+
}
|
|
299
|
+
};
|
|
289
300
|
|
|
290
301
|
// src/read/public-client.ts
|
|
291
302
|
var PublicReadClientImpl = class {
|
|
@@ -454,6 +465,77 @@ var PublicReadClientImpl = class {
|
|
|
454
465
|
eventName: "eventName" in log ? log.eventName : void 0
|
|
455
466
|
}));
|
|
456
467
|
}
|
|
468
|
+
async getTransactionReceipt(params) {
|
|
469
|
+
const { hash } = params;
|
|
470
|
+
try {
|
|
471
|
+
const receipt = await this.viemClient.getTransactionReceipt({ hash });
|
|
472
|
+
return this.mapReceipt(receipt);
|
|
473
|
+
} catch (error) {
|
|
474
|
+
if (error instanceof Error && (error.message.includes("could not be found") || error.message.includes("not found"))) {
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
throw error;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
async waitForTransactionReceipt(params) {
|
|
481
|
+
const {
|
|
482
|
+
hash,
|
|
483
|
+
confirmations = 1,
|
|
484
|
+
pollingInterval = 4e3,
|
|
485
|
+
timeout = 6e4,
|
|
486
|
+
onReplaced
|
|
487
|
+
} = params;
|
|
488
|
+
try {
|
|
489
|
+
const receipt = await this.viemClient.waitForTransactionReceipt({
|
|
490
|
+
hash,
|
|
491
|
+
confirmations,
|
|
492
|
+
pollingInterval,
|
|
493
|
+
timeout,
|
|
494
|
+
onReplaced: onReplaced ? (response) => {
|
|
495
|
+
onReplaced({
|
|
496
|
+
reason: response.reason,
|
|
497
|
+
replacedTransaction: { hash: response.replacedTransaction.hash },
|
|
498
|
+
transaction: { hash: response.transaction.hash },
|
|
499
|
+
transactionReceipt: this.mapReceipt(response.transactionReceipt)
|
|
500
|
+
});
|
|
501
|
+
} : void 0
|
|
502
|
+
});
|
|
503
|
+
return this.mapReceipt(receipt);
|
|
504
|
+
} catch (error) {
|
|
505
|
+
if (error instanceof Error && error.message.includes("timed out")) {
|
|
506
|
+
throw new TransactionReceiptTimeoutError(hash, timeout);
|
|
507
|
+
}
|
|
508
|
+
throw error;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
mapReceipt(receipt) {
|
|
512
|
+
return {
|
|
513
|
+
blockHash: receipt.blockHash,
|
|
514
|
+
blockNumber: receipt.blockNumber,
|
|
515
|
+
contractAddress: receipt.contractAddress,
|
|
516
|
+
cumulativeGasUsed: receipt.cumulativeGasUsed,
|
|
517
|
+
effectiveGasPrice: receipt.effectiveGasPrice,
|
|
518
|
+
from: receipt.from,
|
|
519
|
+
gasUsed: receipt.gasUsed,
|
|
520
|
+
logs: receipt.logs.map((log) => ({
|
|
521
|
+
address: log.address,
|
|
522
|
+
topics: log.topics,
|
|
523
|
+
data: log.data,
|
|
524
|
+
blockNumber: log.blockNumber,
|
|
525
|
+
blockHash: log.blockHash,
|
|
526
|
+
transactionHash: log.transactionHash,
|
|
527
|
+
transactionIndex: log.transactionIndex,
|
|
528
|
+
logIndex: log.logIndex,
|
|
529
|
+
removed: log.removed
|
|
530
|
+
})),
|
|
531
|
+
logsBloom: receipt.logsBloom,
|
|
532
|
+
status: receipt.status,
|
|
533
|
+
to: receipt.to,
|
|
534
|
+
transactionHash: receipt.transactionHash,
|
|
535
|
+
transactionIndex: receipt.transactionIndex,
|
|
536
|
+
type: receipt.type
|
|
537
|
+
};
|
|
538
|
+
}
|
|
457
539
|
clearCache() {
|
|
458
540
|
this.cache?.clear();
|
|
459
541
|
}
|
|
@@ -513,6 +595,6 @@ function normalizeBlockTag(blockTag) {
|
|
|
513
595
|
return blockTag;
|
|
514
596
|
}
|
|
515
597
|
|
|
516
|
-
export { AllRpcsFailedError, BlockPrunedError, ChainNotSupportedError, ContractNotFoundError, ContractRevertError, DEFAULT_CACHE_CONFIG, DEFAULT_CACHE_MAX_SIZE, DEFAULT_CACHE_TTL, DEFAULT_MULTICALL_BATCH_SIZE, InvalidAbiError, LRUCache, LUMIA_MAINNET, LUMIA_MAINNET_CHAIN_ID, LUMIA_TESTNET, LUMIA_TESTNET_CHAIN_ID, MULTICALL3_ADDRESS, RateLimitedError, ReadLayerError, RpcConnectionError, generateCacheKey, getChainConfig, getPublicClient, isChainSupported };
|
|
598
|
+
export { AllRpcsFailedError, BlockPrunedError, ChainNotSupportedError, ContractNotFoundError, ContractRevertError, DEFAULT_CACHE_CONFIG, DEFAULT_CACHE_MAX_SIZE, DEFAULT_CACHE_TTL, DEFAULT_MULTICALL_BATCH_SIZE, InvalidAbiError, LRUCache, LUMIA_MAINNET, LUMIA_MAINNET_CHAIN_ID, LUMIA_TESTNET, LUMIA_TESTNET_CHAIN_ID, MULTICALL3_ADDRESS, RateLimitedError, ReadLayerError, RpcConnectionError, TransactionReceiptTimeoutError, generateCacheKey, getChainConfig, getPublicClient, isChainSupported };
|
|
517
599
|
//# sourceMappingURL=index.js.map
|
|
518
600
|
//# sourceMappingURL=index.js.map
|
package/dist/read/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/read/cache.ts","../../src/read/rpc-fallback.ts","../../src/read/constants.ts","../../src/read/errors.ts","../../src/read/public-client.ts"],"names":["createPublicClient","http"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * LRU Cache implementation for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport type { CacheConfig, CacheStats, BlockTag } from './types';\nimport type { Address } from 'viem';\n\n/**\n * Internal cache entry structure\n */\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\n/**\n * Default cache configuration\n */\nexport const DEFAULT_CACHE_CONFIG: CacheConfig = {\n maxSize: 1000,\n ttl: 12000, // 12 seconds (~1 block)\n};\n\n/**\n * LRU Cache with TTL support for blockchain read operations\n */\nexport class LRUCache<T = unknown> {\n private cache: Map<string, CacheEntry<T>>;\n private readonly maxSize: number;\n private readonly ttl: number;\n private hits = 0;\n private misses = 0;\n\n constructor(config: Partial<CacheConfig> = {}) {\n this.maxSize = config.maxSize ?? DEFAULT_CACHE_CONFIG.maxSize;\n this.ttl = config.ttl ?? DEFAULT_CACHE_CONFIG.ttl;\n this.cache = new Map();\n }\n\n /**\n * Get a value from cache\n * Returns undefined if not found or expired\n */\n get(key: string): T | undefined {\n const entry = this.cache.get(key);\n\n if (!entry) {\n this.misses++;\n return undefined;\n }\n\n // Check if expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n this.misses++;\n return undefined;\n }\n\n // Move to end (most recently used) by deleting and re-adding\n this.cache.delete(key);\n this.cache.set(key, entry);\n this.hits++;\n\n return entry.value;\n }\n\n /**\n * Set a value in cache with optional custom TTL\n */\n set(key: string, value: T, customTtl?: number): void {\n // If key exists, delete it first to update position\n if (this.cache.has(key)) {\n this.cache.delete(key);\n }\n\n // Evict oldest entries if at capacity\n while (this.cache.size >= this.maxSize) {\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey !== undefined) {\n this.cache.delete(oldestKey);\n }\n }\n\n const ttlToUse = customTtl ?? this.ttl;\n this.cache.set(key, {\n value,\n expiresAt: Date.now() + ttlToUse,\n });\n }\n\n /**\n * Check if key exists and is not expired\n */\n has(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) return false;\n\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return false;\n }\n\n return true;\n }\n\n /**\n * Delete a specific key\n */\n delete(key: string): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.cache.clear();\n this.hits = 0;\n this.misses = 0;\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n // Clean expired entries before reporting\n this.cleanExpired();\n\n return {\n size: this.cache.size,\n maxSize: this.maxSize,\n hits: this.hits,\n misses: this.misses,\n };\n }\n\n /**\n * Remove expired entries\n */\n private cleanExpired(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n\n/**\n * Generate a deterministic cache key for contract reads\n */\nexport function generateCacheKey(params: {\n chainId: number;\n address: Address;\n functionName: string;\n args: readonly unknown[];\n blockTag: BlockTag;\n from?: Address;\n}): string {\n const keyParts = {\n c: params.chainId,\n a: params.address.toLowerCase(),\n f: params.functionName,\n r: params.args,\n b: serializeBlockTag(params.blockTag),\n s: params.from?.toLowerCase(),\n };\n\n return JSON.stringify(keyParts);\n}\n\n/**\n * Serialize block tag for cache key\n */\nfunction serializeBlockTag(blockTag: BlockTag): string {\n if (typeof blockTag === 'bigint') {\n return `n:${blockTag.toString()}`;\n }\n return blockTag;\n}\n","/**\n * RPC Fallback Transport for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport {\n createPublicClient,\n fallback,\n http,\n type Chain,\n type PublicClient,\n} from 'viem';\n\n/**\n * Configuration for fallback transport\n */\nexport interface FallbackTransportConfig {\n /**\n * RPC URLs in priority order\n */\n urls: string[];\n\n /**\n * Number of retries per endpoint before failover\n * @default 1\n */\n retriesPerEndpoint?: number;\n\n /**\n * Request timeout in ms\n * @default 10000\n */\n timeout?: number;\n}\n\n/**\n * Default configuration\n */\nconst DEFAULT_CONFIG = {\n retriesPerEndpoint: 1,\n timeout: 10000,\n};\n\n/**\n * Create a viem public client with fallback RPC support\n */\nexport function createFallbackClient(\n chain: Chain,\n config: FallbackTransportConfig,\n): PublicClient {\n const {\n urls,\n retriesPerEndpoint = DEFAULT_CONFIG.retriesPerEndpoint,\n timeout = DEFAULT_CONFIG.timeout,\n } = config;\n\n if (urls.length === 0) {\n throw new Error('At least one RPC URL is required');\n }\n\n // For single URL, use simple http transport\n if (urls.length === 1) {\n return createPublicClient({\n chain,\n transport: http(urls[0], { timeout }),\n }) as PublicClient;\n }\n\n // For multiple URLs, use viem's built-in fallback transport\n const transports = urls.map((url) =>\n http(url, {\n timeout,\n retryCount: retriesPerEndpoint,\n retryDelay: 150,\n }),\n );\n\n return createPublicClient({\n chain,\n transport: fallback(transports, {\n rank: true, // Automatically rank transports by latency\n retryCount: 1,\n }),\n }) as PublicClient;\n}\n\n/**\n * Check if an error is recoverable (worth retrying)\n */\nexport function isRecoverableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n\n // Network errors are recoverable\n if (\n message.includes('network') ||\n message.includes('timeout') ||\n message.includes('econnrefused') ||\n message.includes('econnreset') ||\n message.includes('socket')\n ) {\n return true;\n }\n\n // Server errors are recoverable\n if (\n message.includes('500') ||\n message.includes('502') ||\n message.includes('503') ||\n message.includes('504')\n ) {\n return true;\n }\n\n // Rate limits are recoverable with backoff\n if (isRateLimitError(error)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if error is a rate limit error\n */\nfunction isRateLimitError(error: Error): boolean {\n const message = error.message.toLowerCase();\n return (\n message.includes('rate limit') ||\n message.includes('too many requests') ||\n message.includes('429') ||\n message.includes('throttle')\n );\n}\n","/**\n * Blockchain Read Layer - Constants and Chain Configurations\n * @module @lumiapassport/core/read\n */\n\nimport type { Address } from 'viem';\nimport type { ChainConfig } from './types';\n\n/**\n * Well-known Multicall3 contract address\n * Deployed at the same address on most EVM chains\n */\nexport const MULTICALL3_ADDRESS: Address = '0xcA11bde05977b3631167028862bE2a173976CA11';\n\n/**\n * Lumia Mainnet chain ID\n */\nexport const LUMIA_MAINNET_CHAIN_ID = 994873017;\n\n/**\n * Lumia Testnet chain ID\n */\nexport const LUMIA_TESTNET_CHAIN_ID = 1952959480;\n\n/**\n * Lumia Mainnet configuration\n */\nexport const LUMIA_MAINNET: ChainConfig = {\n id: LUMIA_MAINNET_CHAIN_ID,\n name: 'Lumia',\n rpcUrls: ['https://rpc.lumia.org'],\n multicall3: MULTICALL3_ADDRESS,\n blockTime: 2, // ~2 seconds per block\n};\n\n/**\n * Lumia Testnet configuration\n */\nexport const LUMIA_TESTNET: ChainConfig = {\n id: LUMIA_TESTNET_CHAIN_ID,\n name: 'Lumia Testnet',\n rpcUrls: ['https://testnet-rpc.lumia.org'],\n multicall3: MULTICALL3_ADDRESS,\n blockTime: 2,\n};\n\n/**\n * All supported chains with built-in configurations\n */\nexport const SUPPORTED_CHAINS: Map<number, ChainConfig> = new Map([\n [LUMIA_MAINNET_CHAIN_ID, LUMIA_MAINNET],\n [LUMIA_TESTNET_CHAIN_ID, LUMIA_TESTNET],\n]);\n\n/**\n * Get chain configuration by chain ID\n * Returns undefined for unsupported chains\n */\nexport function getChainConfig(chainId: number): ChainConfig | undefined {\n return SUPPORTED_CHAINS.get(chainId);\n}\n\n/**\n * Check if a chain is supported with built-in configuration\n */\nexport function isChainSupported(chainId: number): boolean {\n return SUPPORTED_CHAINS.has(chainId);\n}\n\n/**\n * Default cache TTL in milliseconds (12 seconds, ~1 block)\n */\nexport const DEFAULT_CACHE_TTL = 12000;\n\n/**\n * Default maximum cache entries\n */\nexport const DEFAULT_CACHE_MAX_SIZE = 1000;\n\n/**\n * Default maximum calls per multicall batch\n */\nexport const DEFAULT_MULTICALL_BATCH_SIZE = 100;\n\n/**\n * Default block range for getLogs queries (to avoid RPC limits)\n */\nexport const DEFAULT_LOGS_BLOCK_RANGE = 2000n;\n\n/**\n * Maximum block range for a single getLogs query\n */\nexport const MAX_LOGS_BLOCK_RANGE = 10000n;\n","/**\n * Blockchain Read Layer - Error Classes\n * @module @lumiapassport/core/read\n */\n\nimport type { Address } from 'viem';\n\n/**\n * Base error class for read layer errors\n */\nexport class ReadLayerError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n ) {\n super(message);\n this.name = 'ReadLayerError';\n }\n}\n\n/**\n * Contract does not exist at the specified address\n */\nexport class ContractNotFoundError extends ReadLayerError {\n constructor(\n public readonly address: Address,\n public readonly chainId: number,\n ) {\n super(\n `Contract not found at ${address} on chain ${chainId}`,\n 'CONTRACT_NOT_FOUND',\n );\n this.name = 'ContractNotFoundError';\n }\n}\n\n/**\n * Contract call reverted with a reason\n */\nexport class ContractRevertError extends ReadLayerError {\n constructor(\n public readonly address: Address,\n public readonly functionName: string,\n public readonly reason: string,\n ) {\n super(\n `Contract call to ${functionName} at ${address} reverted: ${reason}`,\n 'CONTRACT_REVERTED',\n );\n this.name = 'ContractRevertError';\n }\n}\n\n/**\n * Failed to connect to RPC endpoint\n */\nexport class RpcConnectionError extends ReadLayerError {\n constructor(\n public readonly url: string,\n public readonly cause?: Error,\n ) {\n super(`Failed to connect to RPC: ${url}`, 'RPC_CONNECTION_FAILED');\n this.name = 'RpcConnectionError';\n }\n}\n\n/**\n * All configured RPC endpoints failed\n */\nexport class AllRpcsFailedError extends ReadLayerError {\n constructor(\n public readonly urls: string[],\n public readonly errors: Error[],\n ) {\n super(\n `All ${urls.length} RPC endpoint(s) failed`,\n 'ALL_RPCS_FAILED',\n );\n this.name = 'AllRpcsFailedError';\n }\n}\n\n/**\n * RPC returned rate limit response\n */\nexport class RateLimitedError extends ReadLayerError {\n constructor(\n public readonly url: string,\n public readonly retryAfter?: number,\n ) {\n super(\n `Rate limited by RPC: ${url}${retryAfter ? `, retry after ${retryAfter}s` : ''}`,\n 'RATE_LIMITED',\n );\n this.name = 'RateLimitedError';\n }\n}\n\n/**\n * Requested block has been pruned from RPC node\n */\nexport class BlockPrunedError extends ReadLayerError {\n constructor(public readonly blockNumber: bigint) {\n super(\n `Block ${blockNumber} has been pruned and is not available`,\n 'BLOCK_PRUNED',\n );\n this.name = 'BlockPrunedError';\n }\n}\n\n/**\n * Invalid ABI provided - function not found\n */\nexport class InvalidAbiError extends ReadLayerError {\n constructor(\n public readonly functionName: string,\n public readonly address: Address,\n ) {\n super(\n `Function '${functionName}' not found in ABI for contract at ${address}`,\n 'INVALID_ABI',\n );\n this.name = 'InvalidAbiError';\n }\n}\n\n/**\n * Chain configuration not found\n */\nexport class ChainNotSupportedError extends ReadLayerError {\n constructor(public readonly chainId: number) {\n super(\n `Chain ${chainId} is not supported. Please provide an RPC URL.`,\n 'CHAIN_NOT_SUPPORTED',\n );\n this.name = 'ChainNotSupportedError';\n }\n}\n","/**\n * Public Client Factory for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport {\n createPublicClient,\n http,\n type Chain,\n type PublicClient as ViemPublicClient,\n type BlockTag as ViemBlockTag,\n} from 'viem';\nimport { LRUCache, generateCacheKey } from './cache';\nimport { createFallbackClient } from './rpc-fallback';\nimport {\n getChainConfig,\n DEFAULT_CACHE_TTL,\n DEFAULT_CACHE_MAX_SIZE,\n MULTICALL3_ADDRESS,\n} from './constants';\nimport { ChainNotSupportedError } from './errors';\nimport type {\n PublicReadClientConfig,\n PublicReadClient,\n ReadContractParams,\n MulticallParams,\n MulticallResult,\n GetLogsParams,\n LogEntry,\n CacheStats,\n ContractCall,\n BlockTag,\n} from './types';\nimport type { Abi, Address } from 'viem';\n\n/**\n * Internal client implementation\n */\nclass PublicReadClientImpl implements PublicReadClient {\n readonly chainId: number;\n private readonly viemClient: ViemPublicClient;\n private readonly cache: LRUCache | null;\n private readonly multicall3Address: Address | null;\n\n constructor(\n chainId: number,\n viemClient: ViemPublicClient,\n cache: LRUCache | null,\n multicall3Address: Address | null,\n ) {\n this.chainId = chainId;\n this.viemClient = viemClient;\n this.cache = cache;\n this.multicall3Address = multicall3Address;\n }\n\n async readContract<TAbi extends Abi, TFunctionName extends string>(\n params: ReadContractParams<TAbi, TFunctionName>,\n ): Promise<unknown> {\n const {\n address,\n abi,\n functionName,\n args = [],\n blockTag = 'latest',\n from,\n forceRefresh = false,\n } = params;\n\n // Check cache first (unless forceRefresh)\n if (this.cache && !forceRefresh) {\n const cacheKey = generateCacheKey({\n chainId: this.chainId,\n address,\n functionName,\n args,\n blockTag,\n from,\n });\n\n const cached = this.cache.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n }\n\n // Make the RPC call\n const result = await this.viemClient.readContract({\n address,\n abi,\n functionName,\n args: args as unknown[],\n blockTag: normalizeBlockTag(blockTag),\n account: from,\n } as Parameters<typeof this.viemClient.readContract>[0]);\n\n // Store in cache\n if (this.cache) {\n const cacheKey = generateCacheKey({\n chainId: this.chainId,\n address,\n functionName,\n args,\n blockTag,\n from,\n });\n this.cache.set(cacheKey, result);\n }\n\n return result;\n }\n\n async multicall<TContracts extends readonly ContractCall[]>(\n params: MulticallParams<TContracts>,\n ): Promise<MulticallResult[]> {\n const {\n contracts,\n allowFailure = true,\n blockTag = 'latest',\n batchSize = 100,\n } = params;\n\n // If no multicall3 or only one contract, use sequential calls\n if (!this.multicall3Address || contracts.length === 1) {\n return this.sequentialMulticall(contracts, allowFailure, blockTag);\n }\n\n // Chunk large batches\n const results: MulticallResult[] = [];\n for (let i = 0; i < contracts.length; i += batchSize) {\n const chunk = contracts.slice(i, i + batchSize);\n const chunkResults = await this.executeMulticallBatch(\n chunk,\n allowFailure,\n blockTag,\n );\n results.push(...chunkResults);\n }\n\n return results;\n }\n\n private async executeMulticallBatch(\n contracts: readonly ContractCall[],\n allowFailure: boolean,\n blockTag: BlockTag,\n ): Promise<MulticallResult[]> {\n try {\n const results = await this.viemClient.multicall({\n contracts: contracts.map((c) => ({\n address: c.address,\n abi: c.abi,\n functionName: c.functionName,\n args: c.args as unknown[],\n })),\n allowFailure,\n blockTag: blockTag as ViemBlockTag,\n multicallAddress: this.multicall3Address!,\n });\n\n // Cast results to known shape - viem returns either success or failure objects\n const typedResults = results as Array<\n { status: 'success'; result: unknown } | { status: 'failure'; error: Error }\n >;\n\n return typedResults.map((r) => {\n if (r.status === 'success') {\n return { status: 'success' as const, result: r.result };\n } else {\n return { status: 'failure' as const, error: r.error };\n }\n });\n } catch (error) {\n // If multicall fails entirely, fall back to sequential\n return this.sequentialMulticall(contracts, allowFailure, blockTag);\n }\n }\n\n private async sequentialMulticall(\n contracts: readonly ContractCall[],\n allowFailure: boolean,\n blockTag: BlockTag,\n ): Promise<MulticallResult[]> {\n const results: MulticallResult[] = [];\n\n for (const contract of contracts) {\n try {\n const result = await this.readContract({\n address: contract.address,\n abi: contract.abi,\n functionName: contract.functionName,\n args: contract.args,\n blockTag,\n });\n results.push({ status: 'success', result });\n } catch (error) {\n if (allowFailure) {\n results.push({\n status: 'failure',\n error: error instanceof Error ? error : new Error(String(error)),\n });\n } else {\n throw error;\n }\n }\n }\n\n return results;\n }\n\n async getLogs(params: GetLogsParams): Promise<LogEntry[]> {\n const { address, event, args, fromBlock, toBlock, blockHash } = params;\n\n // Build parameters conditionally based on what's provided\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const logsParams: any = {};\n\n if (address !== undefined) {\n logsParams.address = address;\n }\n\n if (event !== undefined) {\n logsParams.event = event;\n }\n\n if (args !== undefined) {\n logsParams.args = args;\n }\n\n if (blockHash !== undefined) {\n logsParams.blockHash = blockHash;\n } else {\n if (fromBlock !== undefined) {\n logsParams.fromBlock = normalizeBlockTag(fromBlock);\n }\n if (toBlock !== undefined) {\n logsParams.toBlock = normalizeBlockTag(toBlock);\n }\n }\n\n const logs = await this.viemClient.getLogs(logsParams);\n\n return logs.map((log) => ({\n address: log.address,\n topics: log.topics as [Address, ...Address[]] | [],\n data: log.data,\n blockNumber: log.blockNumber,\n blockHash: log.blockHash,\n transactionHash: log.transactionHash,\n transactionIndex: log.transactionIndex,\n logIndex: log.logIndex,\n removed: log.removed,\n // These properties only exist when an event ABI is provided\n args: 'args' in log ? (log.args as Record<string, unknown>) : undefined,\n eventName: 'eventName' in log ? (log.eventName as string) : undefined,\n }));\n }\n\n clearCache(): void {\n this.cache?.clear();\n }\n\n getCacheStats(): CacheStats {\n if (!this.cache) {\n return { size: 0, maxSize: 0, hits: 0, misses: 0 };\n }\n return this.cache.getStats();\n }\n}\n\n/**\n * Create a public read client for blockchain queries\n *\n * @example\n * ```typescript\n * // Using Lumia mainnet defaults\n * const client = getPublicClient({ chainId: 994873017 });\n *\n * // Using custom RPC with fallbacks\n * const client = getPublicClient({\n * chainId: 1,\n * rpcUrls: ['https://primary.rpc', 'https://fallback.rpc'],\n * });\n * ```\n */\nexport function getPublicClient(config: PublicReadClientConfig): PublicReadClient {\n const {\n chainId,\n rpcUrls,\n multicall3Address,\n cacheTtl = DEFAULT_CACHE_TTL,\n cacheMaxSize = DEFAULT_CACHE_MAX_SIZE,\n disableCache = false,\n } = config;\n\n // Get RPC URLs\n const urls = resolveRpcUrls(chainId, rpcUrls);\n\n // Create chain object for viem\n const chainConfig = getChainConfig(chainId);\n const chain: Chain = {\n id: chainId,\n name: chainConfig?.name ?? `Chain ${chainId}`,\n nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },\n rpcUrls: {\n default: { http: urls },\n },\n };\n\n // Create viem client with fallback support\n let viemClient: ViemPublicClient;\n if (urls.length === 1) {\n viemClient = createPublicClient({\n chain,\n transport: http(urls[0]),\n });\n } else {\n viemClient = createFallbackClient(chain, { urls });\n }\n\n // Create cache if enabled\n const cache = disableCache\n ? null\n : new LRUCache({ maxSize: cacheMaxSize, ttl: cacheTtl });\n\n // Determine multicall3 address\n const resolvedMulticall3 =\n multicall3Address ?? chainConfig?.multicall3 ?? MULTICALL3_ADDRESS;\n\n return new PublicReadClientImpl(chainId, viemClient, cache, resolvedMulticall3);\n}\n\n/**\n * Resolve RPC URLs from config or chain defaults\n */\nfunction resolveRpcUrls(\n chainId: number,\n rpcUrls?: string | string[],\n): string[] {\n // If URLs provided, use them\n if (rpcUrls) {\n return Array.isArray(rpcUrls) ? rpcUrls : [rpcUrls];\n }\n\n // Try to get from chain config\n const chainConfig = getChainConfig(chainId);\n if (chainConfig) {\n return chainConfig.rpcUrls;\n }\n\n // Chain not supported and no URLs provided\n throw new ChainNotSupportedError(chainId);\n}\n\n/**\n * Normalize block tag for viem\n */\nfunction normalizeBlockTag(\n blockTag: BlockTag | bigint,\n): 'latest' | 'pending' | 'safe' | 'finalized' | 'earliest' | bigint {\n if (typeof blockTag === 'bigint') {\n return blockTag;\n }\n return blockTag;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/read/cache.ts","../../src/read/rpc-fallback.ts","../../src/read/constants.ts","../../src/read/errors.ts","../../src/read/public-client.ts"],"names":["createPublicClient","http"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * LRU Cache implementation for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport type { CacheConfig, CacheStats, BlockTag } from './types';\nimport type { Address } from 'viem';\n\n/**\n * Internal cache entry structure\n */\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\n/**\n * Default cache configuration\n */\nexport const DEFAULT_CACHE_CONFIG: CacheConfig = {\n maxSize: 1000,\n ttl: 12000, // 12 seconds (~1 block)\n};\n\n/**\n * LRU Cache with TTL support for blockchain read operations\n */\nexport class LRUCache<T = unknown> {\n private cache: Map<string, CacheEntry<T>>;\n private readonly maxSize: number;\n private readonly ttl: number;\n private hits = 0;\n private misses = 0;\n\n constructor(config: Partial<CacheConfig> = {}) {\n this.maxSize = config.maxSize ?? DEFAULT_CACHE_CONFIG.maxSize;\n this.ttl = config.ttl ?? DEFAULT_CACHE_CONFIG.ttl;\n this.cache = new Map();\n }\n\n /**\n * Get a value from cache\n * Returns undefined if not found or expired\n */\n get(key: string): T | undefined {\n const entry = this.cache.get(key);\n\n if (!entry) {\n this.misses++;\n return undefined;\n }\n\n // Check if expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n this.misses++;\n return undefined;\n }\n\n // Move to end (most recently used) by deleting and re-adding\n this.cache.delete(key);\n this.cache.set(key, entry);\n this.hits++;\n\n return entry.value;\n }\n\n /**\n * Set a value in cache with optional custom TTL\n */\n set(key: string, value: T, customTtl?: number): void {\n // If key exists, delete it first to update position\n if (this.cache.has(key)) {\n this.cache.delete(key);\n }\n\n // Evict oldest entries if at capacity\n while (this.cache.size >= this.maxSize) {\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey !== undefined) {\n this.cache.delete(oldestKey);\n }\n }\n\n const ttlToUse = customTtl ?? this.ttl;\n this.cache.set(key, {\n value,\n expiresAt: Date.now() + ttlToUse,\n });\n }\n\n /**\n * Check if key exists and is not expired\n */\n has(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) return false;\n\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return false;\n }\n\n return true;\n }\n\n /**\n * Delete a specific key\n */\n delete(key: string): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.cache.clear();\n this.hits = 0;\n this.misses = 0;\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n // Clean expired entries before reporting\n this.cleanExpired();\n\n return {\n size: this.cache.size,\n maxSize: this.maxSize,\n hits: this.hits,\n misses: this.misses,\n };\n }\n\n /**\n * Remove expired entries\n */\n private cleanExpired(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n\n/**\n * Generate a deterministic cache key for contract reads\n */\nexport function generateCacheKey(params: {\n chainId: number;\n address: Address;\n functionName: string;\n args: readonly unknown[];\n blockTag: BlockTag;\n from?: Address;\n}): string {\n const keyParts = {\n c: params.chainId,\n a: params.address.toLowerCase(),\n f: params.functionName,\n r: params.args,\n b: serializeBlockTag(params.blockTag),\n s: params.from?.toLowerCase(),\n };\n\n return JSON.stringify(keyParts);\n}\n\n/**\n * Serialize block tag for cache key\n */\nfunction serializeBlockTag(blockTag: BlockTag): string {\n if (typeof blockTag === 'bigint') {\n return `n:${blockTag.toString()}`;\n }\n return blockTag;\n}\n","/**\n * RPC Fallback Transport for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport {\n createPublicClient,\n fallback,\n http,\n type Chain,\n type PublicClient,\n} from 'viem';\n\n/**\n * Configuration for fallback transport\n */\nexport interface FallbackTransportConfig {\n /**\n * RPC URLs in priority order\n */\n urls: string[];\n\n /**\n * Number of retries per endpoint before failover\n * @default 1\n */\n retriesPerEndpoint?: number;\n\n /**\n * Request timeout in ms\n * @default 10000\n */\n timeout?: number;\n}\n\n/**\n * Default configuration\n */\nconst DEFAULT_CONFIG = {\n retriesPerEndpoint: 1,\n timeout: 10000,\n};\n\n/**\n * Create a viem public client with fallback RPC support\n */\nexport function createFallbackClient(\n chain: Chain,\n config: FallbackTransportConfig,\n): PublicClient {\n const {\n urls,\n retriesPerEndpoint = DEFAULT_CONFIG.retriesPerEndpoint,\n timeout = DEFAULT_CONFIG.timeout,\n } = config;\n\n if (urls.length === 0) {\n throw new Error('At least one RPC URL is required');\n }\n\n // For single URL, use simple http transport\n if (urls.length === 1) {\n return createPublicClient({\n chain,\n transport: http(urls[0], { timeout }),\n }) as PublicClient;\n }\n\n // For multiple URLs, use viem's built-in fallback transport\n const transports = urls.map((url) =>\n http(url, {\n timeout,\n retryCount: retriesPerEndpoint,\n retryDelay: 150,\n }),\n );\n\n return createPublicClient({\n chain,\n transport: fallback(transports, {\n rank: true, // Automatically rank transports by latency\n retryCount: 1,\n }),\n }) as PublicClient;\n}\n\n/**\n * Check if an error is recoverable (worth retrying)\n */\nexport function isRecoverableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n\n // Network errors are recoverable\n if (\n message.includes('network') ||\n message.includes('timeout') ||\n message.includes('econnrefused') ||\n message.includes('econnreset') ||\n message.includes('socket')\n ) {\n return true;\n }\n\n // Server errors are recoverable\n if (\n message.includes('500') ||\n message.includes('502') ||\n message.includes('503') ||\n message.includes('504')\n ) {\n return true;\n }\n\n // Rate limits are recoverable with backoff\n if (isRateLimitError(error)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if error is a rate limit error\n */\nfunction isRateLimitError(error: Error): boolean {\n const message = error.message.toLowerCase();\n return (\n message.includes('rate limit') ||\n message.includes('too many requests') ||\n message.includes('429') ||\n message.includes('throttle')\n );\n}\n","/**\n * Blockchain Read Layer - Constants and Chain Configurations\n * @module @lumiapassport/core/read\n */\n\nimport type { Address } from 'viem';\nimport type { ChainConfig } from './types';\n\n/**\n * Well-known Multicall3 contract address\n * Deployed at the same address on most EVM chains\n */\nexport const MULTICALL3_ADDRESS: Address = '0xcA11bde05977b3631167028862bE2a173976CA11';\n\n/**\n * Lumia Mainnet chain ID\n */\nexport const LUMIA_MAINNET_CHAIN_ID = 994873017;\n\n/**\n * Lumia Testnet chain ID\n */\nexport const LUMIA_TESTNET_CHAIN_ID = 1952959480;\n\n/**\n * Lumia Mainnet configuration\n */\nexport const LUMIA_MAINNET: ChainConfig = {\n id: LUMIA_MAINNET_CHAIN_ID,\n name: 'Lumia',\n rpcUrls: ['https://rpc.lumia.org'],\n multicall3: MULTICALL3_ADDRESS,\n blockTime: 2, // ~2 seconds per block\n};\n\n/**\n * Lumia Testnet configuration\n */\nexport const LUMIA_TESTNET: ChainConfig = {\n id: LUMIA_TESTNET_CHAIN_ID,\n name: 'Lumia Testnet',\n rpcUrls: ['https://testnet-rpc.lumia.org'],\n multicall3: MULTICALL3_ADDRESS,\n blockTime: 2,\n};\n\n/**\n * All supported chains with built-in configurations\n */\nexport const SUPPORTED_CHAINS: Map<number, ChainConfig> = new Map([\n [LUMIA_MAINNET_CHAIN_ID, LUMIA_MAINNET],\n [LUMIA_TESTNET_CHAIN_ID, LUMIA_TESTNET],\n]);\n\n/**\n * Get chain configuration by chain ID\n * Returns undefined for unsupported chains\n */\nexport function getChainConfig(chainId: number): ChainConfig | undefined {\n return SUPPORTED_CHAINS.get(chainId);\n}\n\n/**\n * Check if a chain is supported with built-in configuration\n */\nexport function isChainSupported(chainId: number): boolean {\n return SUPPORTED_CHAINS.has(chainId);\n}\n\n/**\n * Default cache TTL in milliseconds (12 seconds, ~1 block)\n */\nexport const DEFAULT_CACHE_TTL = 12000;\n\n/**\n * Default maximum cache entries\n */\nexport const DEFAULT_CACHE_MAX_SIZE = 1000;\n\n/**\n * Default maximum calls per multicall batch\n */\nexport const DEFAULT_MULTICALL_BATCH_SIZE = 100;\n\n/**\n * Default block range for getLogs queries (to avoid RPC limits)\n */\nexport const DEFAULT_LOGS_BLOCK_RANGE = 2000n;\n\n/**\n * Maximum block range for a single getLogs query\n */\nexport const MAX_LOGS_BLOCK_RANGE = 10000n;\n","/**\n * Blockchain Read Layer - Error Classes\n * @module @lumiapassport/core/read\n */\n\nimport type { Address } from 'viem';\n\n/**\n * Base error class for read layer errors\n */\nexport class ReadLayerError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n ) {\n super(message);\n this.name = 'ReadLayerError';\n }\n}\n\n/**\n * Contract does not exist at the specified address\n */\nexport class ContractNotFoundError extends ReadLayerError {\n constructor(\n public readonly address: Address,\n public readonly chainId: number,\n ) {\n super(\n `Contract not found at ${address} on chain ${chainId}`,\n 'CONTRACT_NOT_FOUND',\n );\n this.name = 'ContractNotFoundError';\n }\n}\n\n/**\n * Contract call reverted with a reason\n */\nexport class ContractRevertError extends ReadLayerError {\n constructor(\n public readonly address: Address,\n public readonly functionName: string,\n public readonly reason: string,\n ) {\n super(\n `Contract call to ${functionName} at ${address} reverted: ${reason}`,\n 'CONTRACT_REVERTED',\n );\n this.name = 'ContractRevertError';\n }\n}\n\n/**\n * Failed to connect to RPC endpoint\n */\nexport class RpcConnectionError extends ReadLayerError {\n constructor(\n public readonly url: string,\n public readonly cause?: Error,\n ) {\n super(`Failed to connect to RPC: ${url}`, 'RPC_CONNECTION_FAILED');\n this.name = 'RpcConnectionError';\n }\n}\n\n/**\n * All configured RPC endpoints failed\n */\nexport class AllRpcsFailedError extends ReadLayerError {\n constructor(\n public readonly urls: string[],\n public readonly errors: Error[],\n ) {\n super(\n `All ${urls.length} RPC endpoint(s) failed`,\n 'ALL_RPCS_FAILED',\n );\n this.name = 'AllRpcsFailedError';\n }\n}\n\n/**\n * RPC returned rate limit response\n */\nexport class RateLimitedError extends ReadLayerError {\n constructor(\n public readonly url: string,\n public readonly retryAfter?: number,\n ) {\n super(\n `Rate limited by RPC: ${url}${retryAfter ? `, retry after ${retryAfter}s` : ''}`,\n 'RATE_LIMITED',\n );\n this.name = 'RateLimitedError';\n }\n}\n\n/**\n * Requested block has been pruned from RPC node\n */\nexport class BlockPrunedError extends ReadLayerError {\n constructor(public readonly blockNumber: bigint) {\n super(\n `Block ${blockNumber} has been pruned and is not available`,\n 'BLOCK_PRUNED',\n );\n this.name = 'BlockPrunedError';\n }\n}\n\n/**\n * Invalid ABI provided - function not found\n */\nexport class InvalidAbiError extends ReadLayerError {\n constructor(\n public readonly functionName: string,\n public readonly address: Address,\n ) {\n super(\n `Function '${functionName}' not found in ABI for contract at ${address}`,\n 'INVALID_ABI',\n );\n this.name = 'InvalidAbiError';\n }\n}\n\n/**\n * Chain configuration not found\n */\nexport class ChainNotSupportedError extends ReadLayerError {\n constructor(public readonly chainId: number) {\n super(\n `Chain ${chainId} is not supported. Please provide an RPC URL.`,\n 'CHAIN_NOT_SUPPORTED',\n );\n this.name = 'ChainNotSupportedError';\n }\n}\n\n/**\n * Transaction receipt not found within timeout period\n */\nexport class TransactionReceiptTimeoutError extends ReadLayerError {\n constructor(\n public readonly hash: string,\n public readonly timeout: number,\n ) {\n super(\n `Transaction receipt not found within ${timeout}ms: ${hash}`,\n 'TRANSACTION_RECEIPT_TIMEOUT',\n );\n this.name = 'TransactionReceiptTimeoutError';\n }\n}\n","/**\n * Public Client Factory for blockchain read operations\n * @module @lumiapassport/core/read\n */\n\nimport {\n createPublicClient,\n http,\n type Chain,\n type PublicClient as ViemPublicClient,\n type BlockTag as ViemBlockTag,\n} from 'viem';\nimport { LRUCache, generateCacheKey } from './cache';\nimport { createFallbackClient } from './rpc-fallback';\nimport {\n getChainConfig,\n DEFAULT_CACHE_TTL,\n DEFAULT_CACHE_MAX_SIZE,\n MULTICALL3_ADDRESS,\n} from './constants';\nimport { ChainNotSupportedError, TransactionReceiptTimeoutError } from './errors';\nimport type {\n PublicReadClientConfig,\n PublicReadClient,\n ReadContractParams,\n MulticallParams,\n MulticallResult,\n GetLogsParams,\n LogEntry,\n CacheStats,\n ContractCall,\n BlockTag,\n GetTransactionReceiptParams,\n WaitForTransactionReceiptParams,\n TransactionReceipt,\n ReplacedTransactionResponse,\n} from './types';\nimport type { Abi, Address } from 'viem';\n\n/**\n * Internal client implementation\n */\nclass PublicReadClientImpl implements PublicReadClient {\n readonly chainId: number;\n private readonly viemClient: ViemPublicClient;\n private readonly cache: LRUCache | null;\n private readonly multicall3Address: Address | null;\n\n constructor(\n chainId: number,\n viemClient: ViemPublicClient,\n cache: LRUCache | null,\n multicall3Address: Address | null,\n ) {\n this.chainId = chainId;\n this.viemClient = viemClient;\n this.cache = cache;\n this.multicall3Address = multicall3Address;\n }\n\n async readContract<TAbi extends Abi, TFunctionName extends string>(\n params: ReadContractParams<TAbi, TFunctionName>,\n ): Promise<unknown> {\n const {\n address,\n abi,\n functionName,\n args = [],\n blockTag = 'latest',\n from,\n forceRefresh = false,\n } = params;\n\n // Check cache first (unless forceRefresh)\n if (this.cache && !forceRefresh) {\n const cacheKey = generateCacheKey({\n chainId: this.chainId,\n address,\n functionName,\n args,\n blockTag,\n from,\n });\n\n const cached = this.cache.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n }\n\n // Make the RPC call\n const result = await this.viemClient.readContract({\n address,\n abi,\n functionName,\n args: args as unknown[],\n blockTag: normalizeBlockTag(blockTag),\n account: from,\n } as Parameters<typeof this.viemClient.readContract>[0]);\n\n // Store in cache\n if (this.cache) {\n const cacheKey = generateCacheKey({\n chainId: this.chainId,\n address,\n functionName,\n args,\n blockTag,\n from,\n });\n this.cache.set(cacheKey, result);\n }\n\n return result;\n }\n\n async multicall<TContracts extends readonly ContractCall[]>(\n params: MulticallParams<TContracts>,\n ): Promise<MulticallResult[]> {\n const {\n contracts,\n allowFailure = true,\n blockTag = 'latest',\n batchSize = 100,\n } = params;\n\n // If no multicall3 or only one contract, use sequential calls\n if (!this.multicall3Address || contracts.length === 1) {\n return this.sequentialMulticall(contracts, allowFailure, blockTag);\n }\n\n // Chunk large batches\n const results: MulticallResult[] = [];\n for (let i = 0; i < contracts.length; i += batchSize) {\n const chunk = contracts.slice(i, i + batchSize);\n const chunkResults = await this.executeMulticallBatch(\n chunk,\n allowFailure,\n blockTag,\n );\n results.push(...chunkResults);\n }\n\n return results;\n }\n\n private async executeMulticallBatch(\n contracts: readonly ContractCall[],\n allowFailure: boolean,\n blockTag: BlockTag,\n ): Promise<MulticallResult[]> {\n try {\n const results = await this.viemClient.multicall({\n contracts: contracts.map((c) => ({\n address: c.address,\n abi: c.abi,\n functionName: c.functionName,\n args: c.args as unknown[],\n })),\n allowFailure,\n blockTag: blockTag as ViemBlockTag,\n multicallAddress: this.multicall3Address!,\n });\n\n // Cast results to known shape - viem returns either success or failure objects\n const typedResults = results as Array<\n { status: 'success'; result: unknown } | { status: 'failure'; error: Error }\n >;\n\n return typedResults.map((r) => {\n if (r.status === 'success') {\n return { status: 'success' as const, result: r.result };\n } else {\n return { status: 'failure' as const, error: r.error };\n }\n });\n } catch (error) {\n // If multicall fails entirely, fall back to sequential\n return this.sequentialMulticall(contracts, allowFailure, blockTag);\n }\n }\n\n private async sequentialMulticall(\n contracts: readonly ContractCall[],\n allowFailure: boolean,\n blockTag: BlockTag,\n ): Promise<MulticallResult[]> {\n const results: MulticallResult[] = [];\n\n for (const contract of contracts) {\n try {\n const result = await this.readContract({\n address: contract.address,\n abi: contract.abi,\n functionName: contract.functionName,\n args: contract.args,\n blockTag,\n });\n results.push({ status: 'success', result });\n } catch (error) {\n if (allowFailure) {\n results.push({\n status: 'failure',\n error: error instanceof Error ? error : new Error(String(error)),\n });\n } else {\n throw error;\n }\n }\n }\n\n return results;\n }\n\n async getLogs(params: GetLogsParams): Promise<LogEntry[]> {\n const { address, event, args, fromBlock, toBlock, blockHash } = params;\n\n // Build parameters conditionally based on what's provided\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const logsParams: any = {};\n\n if (address !== undefined) {\n logsParams.address = address;\n }\n\n if (event !== undefined) {\n logsParams.event = event;\n }\n\n if (args !== undefined) {\n logsParams.args = args;\n }\n\n if (blockHash !== undefined) {\n logsParams.blockHash = blockHash;\n } else {\n if (fromBlock !== undefined) {\n logsParams.fromBlock = normalizeBlockTag(fromBlock);\n }\n if (toBlock !== undefined) {\n logsParams.toBlock = normalizeBlockTag(toBlock);\n }\n }\n\n const logs = await this.viemClient.getLogs(logsParams);\n\n return logs.map((log) => ({\n address: log.address,\n topics: log.topics as [Address, ...Address[]] | [],\n data: log.data,\n blockNumber: log.blockNumber,\n blockHash: log.blockHash,\n transactionHash: log.transactionHash,\n transactionIndex: log.transactionIndex,\n logIndex: log.logIndex,\n removed: log.removed,\n // These properties only exist when an event ABI is provided\n args: 'args' in log ? (log.args as Record<string, unknown>) : undefined,\n eventName: 'eventName' in log ? (log.eventName as string) : undefined,\n }));\n }\n\n async getTransactionReceipt(\n params: GetTransactionReceiptParams,\n ): Promise<TransactionReceipt | null> {\n const { hash } = params;\n\n try {\n const receipt = await this.viemClient.getTransactionReceipt({ hash });\n return this.mapReceipt(receipt);\n } catch (error) {\n // Transaction not found or pending\n if (\n error instanceof Error &&\n (error.message.includes('could not be found') ||\n error.message.includes('not found'))\n ) {\n return null;\n }\n throw error;\n }\n }\n\n async waitForTransactionReceipt(\n params: WaitForTransactionReceiptParams,\n ): Promise<TransactionReceipt> {\n const {\n hash,\n confirmations = 1,\n pollingInterval = 4000,\n timeout = 60000,\n onReplaced,\n } = params;\n\n try {\n const receipt = await this.viemClient.waitForTransactionReceipt({\n hash,\n confirmations,\n pollingInterval,\n timeout,\n onReplaced: onReplaced\n ? (response) => {\n onReplaced({\n reason: response.reason,\n replacedTransaction: { hash: response.replacedTransaction.hash },\n transaction: { hash: response.transaction.hash },\n transactionReceipt: this.mapReceipt(response.transactionReceipt),\n } as ReplacedTransactionResponse);\n }\n : undefined,\n });\n return this.mapReceipt(receipt);\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('timed out')\n ) {\n throw new TransactionReceiptTimeoutError(hash, timeout);\n }\n throw error;\n }\n }\n\n private mapReceipt(\n receipt: Awaited<ReturnType<typeof this.viemClient.getTransactionReceipt>>,\n ): TransactionReceipt {\n return {\n blockHash: receipt.blockHash,\n blockNumber: receipt.blockNumber,\n contractAddress: receipt.contractAddress,\n cumulativeGasUsed: receipt.cumulativeGasUsed,\n effectiveGasPrice: receipt.effectiveGasPrice,\n from: receipt.from,\n gasUsed: receipt.gasUsed,\n logs: receipt.logs.map((log) => ({\n address: log.address,\n topics: log.topics as [Address, ...Address[]] | [],\n data: log.data,\n blockNumber: log.blockNumber,\n blockHash: log.blockHash,\n transactionHash: log.transactionHash,\n transactionIndex: log.transactionIndex,\n logIndex: log.logIndex,\n removed: log.removed,\n })),\n logsBloom: receipt.logsBloom,\n status: receipt.status,\n to: receipt.to,\n transactionHash: receipt.transactionHash,\n transactionIndex: receipt.transactionIndex,\n type: receipt.type,\n };\n }\n\n clearCache(): void {\n this.cache?.clear();\n }\n\n getCacheStats(): CacheStats {\n if (!this.cache) {\n return { size: 0, maxSize: 0, hits: 0, misses: 0 };\n }\n return this.cache.getStats();\n }\n}\n\n/**\n * Create a public read client for blockchain queries\n *\n * @example\n * ```typescript\n * // Using Lumia mainnet defaults\n * const client = getPublicClient({ chainId: 994873017 });\n *\n * // Using custom RPC with fallbacks\n * const client = getPublicClient({\n * chainId: 1,\n * rpcUrls: ['https://primary.rpc', 'https://fallback.rpc'],\n * });\n * ```\n */\nexport function getPublicClient(config: PublicReadClientConfig): PublicReadClient {\n const {\n chainId,\n rpcUrls,\n multicall3Address,\n cacheTtl = DEFAULT_CACHE_TTL,\n cacheMaxSize = DEFAULT_CACHE_MAX_SIZE,\n disableCache = false,\n } = config;\n\n // Get RPC URLs\n const urls = resolveRpcUrls(chainId, rpcUrls);\n\n // Create chain object for viem\n const chainConfig = getChainConfig(chainId);\n const chain: Chain = {\n id: chainId,\n name: chainConfig?.name ?? `Chain ${chainId}`,\n nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },\n rpcUrls: {\n default: { http: urls },\n },\n };\n\n // Create viem client with fallback support\n let viemClient: ViemPublicClient;\n if (urls.length === 1) {\n viemClient = createPublicClient({\n chain,\n transport: http(urls[0]),\n });\n } else {\n viemClient = createFallbackClient(chain, { urls });\n }\n\n // Create cache if enabled\n const cache = disableCache\n ? null\n : new LRUCache({ maxSize: cacheMaxSize, ttl: cacheTtl });\n\n // Determine multicall3 address\n const resolvedMulticall3 =\n multicall3Address ?? chainConfig?.multicall3 ?? MULTICALL3_ADDRESS;\n\n return new PublicReadClientImpl(chainId, viemClient, cache, resolvedMulticall3);\n}\n\n/**\n * Resolve RPC URLs from config or chain defaults\n */\nfunction resolveRpcUrls(\n chainId: number,\n rpcUrls?: string | string[],\n): string[] {\n // If URLs provided, use them\n if (rpcUrls) {\n return Array.isArray(rpcUrls) ? rpcUrls : [rpcUrls];\n }\n\n // Try to get from chain config\n const chainConfig = getChainConfig(chainId);\n if (chainConfig) {\n return chainConfig.rpcUrls;\n }\n\n // Chain not supported and no URLs provided\n throw new ChainNotSupportedError(chainId);\n}\n\n/**\n * Normalize block tag for viem\n */\nfunction normalizeBlockTag(\n blockTag: BlockTag | bigint,\n): 'latest' | 'pending' | 'safe' | 'finalized' | 'earliest' | bigint {\n if (typeof blockTag === 'bigint') {\n return blockTag;\n }\n return blockTag;\n}\n"]}
|