sol-trade-sdk 0.1.0 → 0.1.2
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 +12 -5
- package/dist/cache/index.d.mts +70 -0
- package/dist/cache/index.d.ts +70 -0
- package/dist/cache/index.js +259 -0
- package/dist/cache/index.mjs +19 -0
- package/dist/chunk-64JY4YH6.mjs +227 -0
- package/dist/chunk-6BWS3CLP.mjs +16 -0
- package/dist/{chunk-NEZDFAYA.mjs → chunk-H4ZUMTTP.mjs} +864 -336
- package/dist/{chunk-MMQAMIKR.mjs → chunk-L6RZIXXN.mjs} +4 -11
- package/dist/{clients-VITWK7B6.mjs → chunk-V7QDWUXJ.mjs} +39 -39
- package/dist/clients-PSG35HN4.mjs +107 -0
- package/dist/index-hZh5hrGj.d.mts +3089 -0
- package/dist/index-yJ5AsNfm.d.ts +3089 -0
- package/dist/index.d.mts +2 -2658
- package/dist/index.d.ts +2 -2658
- package/dist/index.js +794 -278
- package/dist/index.mjs +21 -4
- package/dist/perf/index.mjs +2 -1
- package/dist/pool/index.d.mts +88 -0
- package/dist/pool/index.d.ts +88 -0
- package/dist/pool/index.js +262 -0
- package/dist/pool/index.mjs +233 -0
- package/dist/rpc/index.d.mts +77 -0
- package/dist/rpc/index.d.ts +77 -0
- package/dist/rpc/index.js +447 -0
- package/dist/rpc/index.mjs +223 -0
- package/dist/swqos/index.d.mts +416 -0
- package/dist/swqos/index.d.ts +416 -0
- package/dist/swqos/index.js +3450 -0
- package/dist/swqos/index.mjs +1375 -0
- package/dist/trading/index.d.mts +998 -0
- package/dist/trading/index.d.ts +998 -0
- package/dist/trading/index.js +4302 -0
- package/dist/trading/index.mjs +2097 -0
- package/package.json +5 -4
- package/src/__tests__/hotpath.test.ts +33 -0
- package/src/__tests__/parser-compat.test.ts +82 -0
- package/src/__tests__/protocol-parity.test.ts +242 -0
- package/src/__tests__/sdk.test.ts +16 -0
- package/src/cache/index.ts +1 -0
- package/src/hotpath/executor.ts +25 -18
- package/src/index.ts +330 -92
- package/src/instruction/meteora_damm_v2_builder.ts +88 -20
- package/src/instruction/pumpfun_builder.ts +133 -43
- package/src/instruction/raydium_amm_v4_builder.ts +244 -35
- package/src/instruction/raydium_cpmm_builder.ts +87 -69
- package/src/params/index.ts +38 -5
- package/src/pool/index.ts +1 -0
- package/src/rpc/index.ts +1 -0
- package/src/trading/factory.ts +10 -0
package/README.md
CHANGED
|
@@ -71,19 +71,26 @@ This SDK is available in multiple languages:
|
|
|
71
71
|
| **Python** | [sol-trade-sdk-python](https://github.com/0xfnzero/sol-trade-sdk-python) | Async/await native support |
|
|
72
72
|
| **Go** | [sol-trade-sdk-golang](https://github.com/0xfnzero/sol-trade-sdk-golang) | Concurrent-safe with goroutine support |
|
|
73
73
|
|
|
74
|
+
## 🔖 Current Release
|
|
75
|
+
|
|
76
|
+
**npm package:** `sol-trade-sdk@0.1.2`
|
|
77
|
+
|
|
78
|
+
This release refreshes PumpFun V2 and USDC quote-pool handling, keeps the default RPC submit lane active alongside SWQoS lanes, and aligns Raydium CPMM fixed-output swaps with the on-chain `swap_base_out` instruction. Trade execution requires a caller-supplied `recentBlockhash` or durable nonce; hot-path execution does not query RPC for blockhash, account, or balance data.
|
|
79
|
+
|
|
74
80
|
## ✨ Features
|
|
75
81
|
|
|
76
|
-
1. **PumpFun Trading**:
|
|
82
|
+
1. **PumpFun Trading**: Unified `buy`, `sell`, and `buy_exact_quote_in` flow with automatic legacy or V2 instruction selection for SOL and USDC quote pools
|
|
77
83
|
2. **PumpSwap Trading**: Support for PumpSwap pool trading operations
|
|
78
84
|
3. **Bonk Trading**: Support for Bonk trading operations
|
|
79
85
|
4. **Raydium CPMM Trading**: Support for Raydium CPMM (Concentrated Pool Market Maker) trading operations
|
|
80
86
|
5. **Raydium AMM V4 Trading**: Support for Raydium AMM V4 (Automated Market Maker) trading operations
|
|
81
87
|
6. **Meteora DAMM V2 Trading**: Support for Meteora DAMM V2 (Dynamic AMM) trading operations
|
|
82
88
|
7. **Multiple MEV Protection**: Support for Jito, Nextblock, ZeroSlot, Temporal, Bloxroute, FlashBlock, BlockRazor, Node1, Astralane and other services
|
|
83
|
-
8. **Concurrent Trading**:
|
|
89
|
+
8. **Concurrent Trading**: Submit through every configured SWQoS provider plus the default RPC lane; the first accepted result can return early while slower routes continue submitting
|
|
84
90
|
9. **Unified Trading Interface**: Use unified trading protocol types for trading operations
|
|
85
91
|
10. **Middleware System**: Support for custom instruction middleware to modify, add, or remove instructions before transaction execution
|
|
86
92
|
11. **Shared Infrastructure**: Share expensive RPC and SWQoS clients across multiple wallets for reduced resource usage
|
|
93
|
+
12. **Hot-Path RPC Boundary**: Trade execution uses caller-supplied blockhash or durable nonce and never queries RPC for blockhash, account, or balance data
|
|
87
94
|
|
|
88
95
|
## 📦 Installation
|
|
89
96
|
|
|
@@ -117,11 +124,11 @@ Add to your `package.json`:
|
|
|
117
124
|
### Use NPM
|
|
118
125
|
|
|
119
126
|
```bash
|
|
120
|
-
npm install sol-trade-sdk
|
|
127
|
+
npm install sol-trade-sdk@0.1.2
|
|
121
128
|
# or
|
|
122
|
-
yarn add sol-trade-sdk
|
|
129
|
+
yarn add sol-trade-sdk@0.1.2
|
|
123
130
|
# or
|
|
124
|
-
pnpm add sol-trade-sdk
|
|
131
|
+
pnpm add sol-trade-sdk@0.1.2
|
|
125
132
|
```
|
|
126
133
|
|
|
127
134
|
## 🛠️ Usage Examples
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-Performance Cache Implementation for Sol Trade SDK
|
|
3
|
+
* Provides LRU, TTL, and sharded caches for optimal performance.
|
|
4
|
+
*/
|
|
5
|
+
interface CacheStats {
|
|
6
|
+
hits: number;
|
|
7
|
+
misses: number;
|
|
8
|
+
evictions: number;
|
|
9
|
+
size: number;
|
|
10
|
+
hitRate: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Thread-safe LRU cache with TTL support.
|
|
14
|
+
* O(1) get and set operations.
|
|
15
|
+
*/
|
|
16
|
+
declare class LRUCache<K, V> {
|
|
17
|
+
private cache;
|
|
18
|
+
private maxSize;
|
|
19
|
+
private ttl;
|
|
20
|
+
private hits;
|
|
21
|
+
private misses;
|
|
22
|
+
private evictions;
|
|
23
|
+
constructor(maxSize?: number, ttl?: number);
|
|
24
|
+
get(key: K): V | undefined;
|
|
25
|
+
set(key: K, value: V): void;
|
|
26
|
+
delete(key: K): boolean;
|
|
27
|
+
clear(): void;
|
|
28
|
+
cleanup(): number;
|
|
29
|
+
getStats(): CacheStats;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Simple TTL cache with fast reads.
|
|
33
|
+
*/
|
|
34
|
+
declare class TTLCache<K, V> {
|
|
35
|
+
private cache;
|
|
36
|
+
private ttl;
|
|
37
|
+
private hits;
|
|
38
|
+
private misses;
|
|
39
|
+
constructor(ttl?: number);
|
|
40
|
+
get(key: K): V | undefined;
|
|
41
|
+
set(key: K, value: V): void;
|
|
42
|
+
delete(key: K): boolean;
|
|
43
|
+
cleanup(): number;
|
|
44
|
+
getStats(): CacheStats;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sharded cache for high concurrency scenarios.
|
|
48
|
+
* Distributes keys across multiple shards to reduce lock contention.
|
|
49
|
+
*/
|
|
50
|
+
declare class ShardedCache<K, V> {
|
|
51
|
+
private shards;
|
|
52
|
+
private shardMask;
|
|
53
|
+
constructor(shards?: number, maxSizePerShard?: number, ttl?: number);
|
|
54
|
+
private getShard;
|
|
55
|
+
private hashKey;
|
|
56
|
+
get(key: K): V | undefined;
|
|
57
|
+
set(key: K, value: V): void;
|
|
58
|
+
delete(key: K): boolean;
|
|
59
|
+
clear(): void;
|
|
60
|
+
getStats(): CacheStats;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Decorator for caching function results.
|
|
64
|
+
*/
|
|
65
|
+
declare function cached<K extends any[], R>(cache: LRUCache<string, R> | TTLCache<string, R>, keyFn?: (...args: K) => string): (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: K) => R>) => TypedPropertyDescriptor<(...args: K) => R>;
|
|
66
|
+
declare const blockhashCache: TTLCache<string, string>;
|
|
67
|
+
declare const accountCache: ShardedCache<string, Buffer<ArrayBufferLike>>;
|
|
68
|
+
declare const priceCache: TTLCache<string, number>;
|
|
69
|
+
|
|
70
|
+
export { LRUCache, ShardedCache, TTLCache, accountCache, blockhashCache, cached, priceCache };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-Performance Cache Implementation for Sol Trade SDK
|
|
3
|
+
* Provides LRU, TTL, and sharded caches for optimal performance.
|
|
4
|
+
*/
|
|
5
|
+
interface CacheStats {
|
|
6
|
+
hits: number;
|
|
7
|
+
misses: number;
|
|
8
|
+
evictions: number;
|
|
9
|
+
size: number;
|
|
10
|
+
hitRate: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Thread-safe LRU cache with TTL support.
|
|
14
|
+
* O(1) get and set operations.
|
|
15
|
+
*/
|
|
16
|
+
declare class LRUCache<K, V> {
|
|
17
|
+
private cache;
|
|
18
|
+
private maxSize;
|
|
19
|
+
private ttl;
|
|
20
|
+
private hits;
|
|
21
|
+
private misses;
|
|
22
|
+
private evictions;
|
|
23
|
+
constructor(maxSize?: number, ttl?: number);
|
|
24
|
+
get(key: K): V | undefined;
|
|
25
|
+
set(key: K, value: V): void;
|
|
26
|
+
delete(key: K): boolean;
|
|
27
|
+
clear(): void;
|
|
28
|
+
cleanup(): number;
|
|
29
|
+
getStats(): CacheStats;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Simple TTL cache with fast reads.
|
|
33
|
+
*/
|
|
34
|
+
declare class TTLCache<K, V> {
|
|
35
|
+
private cache;
|
|
36
|
+
private ttl;
|
|
37
|
+
private hits;
|
|
38
|
+
private misses;
|
|
39
|
+
constructor(ttl?: number);
|
|
40
|
+
get(key: K): V | undefined;
|
|
41
|
+
set(key: K, value: V): void;
|
|
42
|
+
delete(key: K): boolean;
|
|
43
|
+
cleanup(): number;
|
|
44
|
+
getStats(): CacheStats;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sharded cache for high concurrency scenarios.
|
|
48
|
+
* Distributes keys across multiple shards to reduce lock contention.
|
|
49
|
+
*/
|
|
50
|
+
declare class ShardedCache<K, V> {
|
|
51
|
+
private shards;
|
|
52
|
+
private shardMask;
|
|
53
|
+
constructor(shards?: number, maxSizePerShard?: number, ttl?: number);
|
|
54
|
+
private getShard;
|
|
55
|
+
private hashKey;
|
|
56
|
+
get(key: K): V | undefined;
|
|
57
|
+
set(key: K, value: V): void;
|
|
58
|
+
delete(key: K): boolean;
|
|
59
|
+
clear(): void;
|
|
60
|
+
getStats(): CacheStats;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Decorator for caching function results.
|
|
64
|
+
*/
|
|
65
|
+
declare function cached<K extends any[], R>(cache: LRUCache<string, R> | TTLCache<string, R>, keyFn?: (...args: K) => string): (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: K) => R>) => TypedPropertyDescriptor<(...args: K) => R>;
|
|
66
|
+
declare const blockhashCache: TTLCache<string, string>;
|
|
67
|
+
declare const accountCache: ShardedCache<string, Buffer<ArrayBufferLike>>;
|
|
68
|
+
declare const priceCache: TTLCache<string, number>;
|
|
69
|
+
|
|
70
|
+
export { LRUCache, ShardedCache, TTLCache, accountCache, blockhashCache, cached, priceCache };
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/cache/index.ts
|
|
21
|
+
var cache_exports = {};
|
|
22
|
+
__export(cache_exports, {
|
|
23
|
+
LRUCache: () => LRUCache,
|
|
24
|
+
ShardedCache: () => ShardedCache,
|
|
25
|
+
TTLCache: () => TTLCache,
|
|
26
|
+
accountCache: () => accountCache,
|
|
27
|
+
blockhashCache: () => blockhashCache,
|
|
28
|
+
cached: () => cached,
|
|
29
|
+
priceCache: () => priceCache
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(cache_exports);
|
|
32
|
+
|
|
33
|
+
// src/cache/cache.ts
|
|
34
|
+
var LRUCache = class {
|
|
35
|
+
cache = /* @__PURE__ */ new Map();
|
|
36
|
+
maxSize;
|
|
37
|
+
ttl;
|
|
38
|
+
hits = 0;
|
|
39
|
+
misses = 0;
|
|
40
|
+
evictions = 0;
|
|
41
|
+
constructor(maxSize = 1e3, ttl = 3e5) {
|
|
42
|
+
this.maxSize = maxSize;
|
|
43
|
+
this.ttl = ttl;
|
|
44
|
+
}
|
|
45
|
+
get(key) {
|
|
46
|
+
const entry = this.cache.get(key);
|
|
47
|
+
if (!entry) {
|
|
48
|
+
this.misses++;
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
if (Date.now() > entry.expiration) {
|
|
52
|
+
this.cache.delete(key);
|
|
53
|
+
this.misses++;
|
|
54
|
+
return void 0;
|
|
55
|
+
}
|
|
56
|
+
this.cache.delete(key);
|
|
57
|
+
this.cache.set(key, entry);
|
|
58
|
+
entry.accessCount++;
|
|
59
|
+
this.hits++;
|
|
60
|
+
return entry.value;
|
|
61
|
+
}
|
|
62
|
+
set(key, value) {
|
|
63
|
+
const expiration = Date.now() + this.ttl;
|
|
64
|
+
if (this.cache.has(key)) {
|
|
65
|
+
const entry = this.cache.get(key);
|
|
66
|
+
entry.value = value;
|
|
67
|
+
entry.expiration = expiration;
|
|
68
|
+
this.cache.delete(key);
|
|
69
|
+
this.cache.set(key, entry);
|
|
70
|
+
} else {
|
|
71
|
+
this.cache.set(key, {
|
|
72
|
+
value,
|
|
73
|
+
expiration,
|
|
74
|
+
accessCount: 0
|
|
75
|
+
});
|
|
76
|
+
while (this.cache.size > this.maxSize) {
|
|
77
|
+
const firstKey = this.cache.keys().next().value;
|
|
78
|
+
if (firstKey === void 0) {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
this.cache.delete(firstKey);
|
|
82
|
+
this.evictions++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
delete(key) {
|
|
87
|
+
return this.cache.delete(key);
|
|
88
|
+
}
|
|
89
|
+
clear() {
|
|
90
|
+
this.cache.clear();
|
|
91
|
+
this.hits = 0;
|
|
92
|
+
this.misses = 0;
|
|
93
|
+
this.evictions = 0;
|
|
94
|
+
}
|
|
95
|
+
cleanup() {
|
|
96
|
+
let removed = 0;
|
|
97
|
+
const now = Date.now();
|
|
98
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
99
|
+
if (now > entry.expiration) {
|
|
100
|
+
this.cache.delete(key);
|
|
101
|
+
this.evictions++;
|
|
102
|
+
removed++;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return removed;
|
|
106
|
+
}
|
|
107
|
+
getStats() {
|
|
108
|
+
const total = this.hits + this.misses;
|
|
109
|
+
return {
|
|
110
|
+
hits: this.hits,
|
|
111
|
+
misses: this.misses,
|
|
112
|
+
evictions: this.evictions,
|
|
113
|
+
size: this.cache.size,
|
|
114
|
+
hitRate: total > 0 ? this.hits / total : 0
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
var TTLCache = class {
|
|
119
|
+
cache = /* @__PURE__ */ new Map();
|
|
120
|
+
ttl;
|
|
121
|
+
hits = 0;
|
|
122
|
+
misses = 0;
|
|
123
|
+
constructor(ttl = 3e5) {
|
|
124
|
+
this.ttl = ttl;
|
|
125
|
+
}
|
|
126
|
+
get(key) {
|
|
127
|
+
const entry = this.cache.get(key);
|
|
128
|
+
if (!entry) {
|
|
129
|
+
this.misses++;
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
if (Date.now() > entry.expiration) {
|
|
133
|
+
this.cache.delete(key);
|
|
134
|
+
this.misses++;
|
|
135
|
+
return void 0;
|
|
136
|
+
}
|
|
137
|
+
this.hits++;
|
|
138
|
+
return entry.value;
|
|
139
|
+
}
|
|
140
|
+
set(key, value) {
|
|
141
|
+
this.cache.set(key, {
|
|
142
|
+
value,
|
|
143
|
+
expiration: Date.now() + this.ttl,
|
|
144
|
+
accessCount: 0
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
delete(key) {
|
|
148
|
+
return this.cache.delete(key);
|
|
149
|
+
}
|
|
150
|
+
cleanup() {
|
|
151
|
+
let removed = 0;
|
|
152
|
+
const now = Date.now();
|
|
153
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
154
|
+
if (now > entry.expiration) {
|
|
155
|
+
this.cache.delete(key);
|
|
156
|
+
removed++;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return removed;
|
|
160
|
+
}
|
|
161
|
+
getStats() {
|
|
162
|
+
const total = this.hits + this.misses;
|
|
163
|
+
return {
|
|
164
|
+
hits: this.hits,
|
|
165
|
+
misses: this.misses,
|
|
166
|
+
evictions: 0,
|
|
167
|
+
size: this.cache.size,
|
|
168
|
+
hitRate: total > 0 ? this.hits / total : 0
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
var ShardedCache = class {
|
|
173
|
+
shards;
|
|
174
|
+
shardMask;
|
|
175
|
+
constructor(shards = 16, maxSizePerShard = 1e3, ttl = 3e5) {
|
|
176
|
+
this.shards = [];
|
|
177
|
+
for (let i = 0; i < shards; i++) {
|
|
178
|
+
this.shards.push(new LRUCache(maxSizePerShard, ttl));
|
|
179
|
+
}
|
|
180
|
+
this.shardMask = shards - 1;
|
|
181
|
+
}
|
|
182
|
+
getShard(key) {
|
|
183
|
+
const hash = this.hashKey(key);
|
|
184
|
+
return this.shards[hash & this.shardMask];
|
|
185
|
+
}
|
|
186
|
+
hashKey(key) {
|
|
187
|
+
const str = String(key);
|
|
188
|
+
let hash = 0;
|
|
189
|
+
for (let i = 0; i < str.length; i++) {
|
|
190
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
191
|
+
hash = hash & hash;
|
|
192
|
+
}
|
|
193
|
+
return Math.abs(hash);
|
|
194
|
+
}
|
|
195
|
+
get(key) {
|
|
196
|
+
return this.getShard(key).get(key);
|
|
197
|
+
}
|
|
198
|
+
set(key, value) {
|
|
199
|
+
this.getShard(key).set(key, value);
|
|
200
|
+
}
|
|
201
|
+
delete(key) {
|
|
202
|
+
return this.getShard(key).delete(key);
|
|
203
|
+
}
|
|
204
|
+
clear() {
|
|
205
|
+
for (const shard of this.shards) {
|
|
206
|
+
shard.clear();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
getStats() {
|
|
210
|
+
let totalHits = 0;
|
|
211
|
+
let totalMisses = 0;
|
|
212
|
+
let totalEvictions = 0;
|
|
213
|
+
let totalSize = 0;
|
|
214
|
+
for (const shard of this.shards) {
|
|
215
|
+
const stats = shard.getStats();
|
|
216
|
+
totalHits += stats.hits;
|
|
217
|
+
totalMisses += stats.misses;
|
|
218
|
+
totalEvictions += stats.evictions;
|
|
219
|
+
totalSize += stats.size;
|
|
220
|
+
}
|
|
221
|
+
const total = totalHits + totalMisses;
|
|
222
|
+
return {
|
|
223
|
+
hits: totalHits,
|
|
224
|
+
misses: totalMisses,
|
|
225
|
+
evictions: totalEvictions,
|
|
226
|
+
size: totalSize,
|
|
227
|
+
hitRate: total > 0 ? totalHits / total : 0
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
function cached(cache, keyFn) {
|
|
232
|
+
return function(target, propertyKey, descriptor) {
|
|
233
|
+
const originalMethod = descriptor.value;
|
|
234
|
+
descriptor.value = function(...args) {
|
|
235
|
+
const key = keyFn ? keyFn(...args) : `${propertyKey}:${JSON.stringify(args)}`;
|
|
236
|
+
const cached2 = cache.get(key);
|
|
237
|
+
if (cached2 !== void 0) {
|
|
238
|
+
return cached2;
|
|
239
|
+
}
|
|
240
|
+
const result = originalMethod.apply(this, args);
|
|
241
|
+
cache.set(key, result);
|
|
242
|
+
return result;
|
|
243
|
+
};
|
|
244
|
+
return descriptor;
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
var blockhashCache = new TTLCache(2e3);
|
|
248
|
+
var accountCache = new ShardedCache(16, 500, 1e4);
|
|
249
|
+
var priceCache = new TTLCache(1e3);
|
|
250
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
251
|
+
0 && (module.exports = {
|
|
252
|
+
LRUCache,
|
|
253
|
+
ShardedCache,
|
|
254
|
+
TTLCache,
|
|
255
|
+
accountCache,
|
|
256
|
+
blockhashCache,
|
|
257
|
+
cached,
|
|
258
|
+
priceCache
|
|
259
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LRUCache,
|
|
3
|
+
ShardedCache,
|
|
4
|
+
TTLCache,
|
|
5
|
+
accountCache,
|
|
6
|
+
blockhashCache,
|
|
7
|
+
cached,
|
|
8
|
+
priceCache
|
|
9
|
+
} from "../chunk-64JY4YH6.mjs";
|
|
10
|
+
import "../chunk-6BWS3CLP.mjs";
|
|
11
|
+
export {
|
|
12
|
+
LRUCache,
|
|
13
|
+
ShardedCache,
|
|
14
|
+
TTLCache,
|
|
15
|
+
accountCache,
|
|
16
|
+
blockhashCache,
|
|
17
|
+
cached,
|
|
18
|
+
priceCache
|
|
19
|
+
};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// src/cache/cache.ts
|
|
2
|
+
var LRUCache = class {
|
|
3
|
+
cache = /* @__PURE__ */ new Map();
|
|
4
|
+
maxSize;
|
|
5
|
+
ttl;
|
|
6
|
+
hits = 0;
|
|
7
|
+
misses = 0;
|
|
8
|
+
evictions = 0;
|
|
9
|
+
constructor(maxSize = 1e3, ttl = 3e5) {
|
|
10
|
+
this.maxSize = maxSize;
|
|
11
|
+
this.ttl = ttl;
|
|
12
|
+
}
|
|
13
|
+
get(key) {
|
|
14
|
+
const entry = this.cache.get(key);
|
|
15
|
+
if (!entry) {
|
|
16
|
+
this.misses++;
|
|
17
|
+
return void 0;
|
|
18
|
+
}
|
|
19
|
+
if (Date.now() > entry.expiration) {
|
|
20
|
+
this.cache.delete(key);
|
|
21
|
+
this.misses++;
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
this.cache.delete(key);
|
|
25
|
+
this.cache.set(key, entry);
|
|
26
|
+
entry.accessCount++;
|
|
27
|
+
this.hits++;
|
|
28
|
+
return entry.value;
|
|
29
|
+
}
|
|
30
|
+
set(key, value) {
|
|
31
|
+
const expiration = Date.now() + this.ttl;
|
|
32
|
+
if (this.cache.has(key)) {
|
|
33
|
+
const entry = this.cache.get(key);
|
|
34
|
+
entry.value = value;
|
|
35
|
+
entry.expiration = expiration;
|
|
36
|
+
this.cache.delete(key);
|
|
37
|
+
this.cache.set(key, entry);
|
|
38
|
+
} else {
|
|
39
|
+
this.cache.set(key, {
|
|
40
|
+
value,
|
|
41
|
+
expiration,
|
|
42
|
+
accessCount: 0
|
|
43
|
+
});
|
|
44
|
+
while (this.cache.size > this.maxSize) {
|
|
45
|
+
const firstKey = this.cache.keys().next().value;
|
|
46
|
+
if (firstKey === void 0) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
this.cache.delete(firstKey);
|
|
50
|
+
this.evictions++;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
delete(key) {
|
|
55
|
+
return this.cache.delete(key);
|
|
56
|
+
}
|
|
57
|
+
clear() {
|
|
58
|
+
this.cache.clear();
|
|
59
|
+
this.hits = 0;
|
|
60
|
+
this.misses = 0;
|
|
61
|
+
this.evictions = 0;
|
|
62
|
+
}
|
|
63
|
+
cleanup() {
|
|
64
|
+
let removed = 0;
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
67
|
+
if (now > entry.expiration) {
|
|
68
|
+
this.cache.delete(key);
|
|
69
|
+
this.evictions++;
|
|
70
|
+
removed++;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return removed;
|
|
74
|
+
}
|
|
75
|
+
getStats() {
|
|
76
|
+
const total = this.hits + this.misses;
|
|
77
|
+
return {
|
|
78
|
+
hits: this.hits,
|
|
79
|
+
misses: this.misses,
|
|
80
|
+
evictions: this.evictions,
|
|
81
|
+
size: this.cache.size,
|
|
82
|
+
hitRate: total > 0 ? this.hits / total : 0
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var TTLCache = class {
|
|
87
|
+
cache = /* @__PURE__ */ new Map();
|
|
88
|
+
ttl;
|
|
89
|
+
hits = 0;
|
|
90
|
+
misses = 0;
|
|
91
|
+
constructor(ttl = 3e5) {
|
|
92
|
+
this.ttl = ttl;
|
|
93
|
+
}
|
|
94
|
+
get(key) {
|
|
95
|
+
const entry = this.cache.get(key);
|
|
96
|
+
if (!entry) {
|
|
97
|
+
this.misses++;
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
if (Date.now() > entry.expiration) {
|
|
101
|
+
this.cache.delete(key);
|
|
102
|
+
this.misses++;
|
|
103
|
+
return void 0;
|
|
104
|
+
}
|
|
105
|
+
this.hits++;
|
|
106
|
+
return entry.value;
|
|
107
|
+
}
|
|
108
|
+
set(key, value) {
|
|
109
|
+
this.cache.set(key, {
|
|
110
|
+
value,
|
|
111
|
+
expiration: Date.now() + this.ttl,
|
|
112
|
+
accessCount: 0
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
delete(key) {
|
|
116
|
+
return this.cache.delete(key);
|
|
117
|
+
}
|
|
118
|
+
cleanup() {
|
|
119
|
+
let removed = 0;
|
|
120
|
+
const now = Date.now();
|
|
121
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
122
|
+
if (now > entry.expiration) {
|
|
123
|
+
this.cache.delete(key);
|
|
124
|
+
removed++;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return removed;
|
|
128
|
+
}
|
|
129
|
+
getStats() {
|
|
130
|
+
const total = this.hits + this.misses;
|
|
131
|
+
return {
|
|
132
|
+
hits: this.hits,
|
|
133
|
+
misses: this.misses,
|
|
134
|
+
evictions: 0,
|
|
135
|
+
size: this.cache.size,
|
|
136
|
+
hitRate: total > 0 ? this.hits / total : 0
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var ShardedCache = class {
|
|
141
|
+
shards;
|
|
142
|
+
shardMask;
|
|
143
|
+
constructor(shards = 16, maxSizePerShard = 1e3, ttl = 3e5) {
|
|
144
|
+
this.shards = [];
|
|
145
|
+
for (let i = 0; i < shards; i++) {
|
|
146
|
+
this.shards.push(new LRUCache(maxSizePerShard, ttl));
|
|
147
|
+
}
|
|
148
|
+
this.shardMask = shards - 1;
|
|
149
|
+
}
|
|
150
|
+
getShard(key) {
|
|
151
|
+
const hash = this.hashKey(key);
|
|
152
|
+
return this.shards[hash & this.shardMask];
|
|
153
|
+
}
|
|
154
|
+
hashKey(key) {
|
|
155
|
+
const str = String(key);
|
|
156
|
+
let hash = 0;
|
|
157
|
+
for (let i = 0; i < str.length; i++) {
|
|
158
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
159
|
+
hash = hash & hash;
|
|
160
|
+
}
|
|
161
|
+
return Math.abs(hash);
|
|
162
|
+
}
|
|
163
|
+
get(key) {
|
|
164
|
+
return this.getShard(key).get(key);
|
|
165
|
+
}
|
|
166
|
+
set(key, value) {
|
|
167
|
+
this.getShard(key).set(key, value);
|
|
168
|
+
}
|
|
169
|
+
delete(key) {
|
|
170
|
+
return this.getShard(key).delete(key);
|
|
171
|
+
}
|
|
172
|
+
clear() {
|
|
173
|
+
for (const shard of this.shards) {
|
|
174
|
+
shard.clear();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
getStats() {
|
|
178
|
+
let totalHits = 0;
|
|
179
|
+
let totalMisses = 0;
|
|
180
|
+
let totalEvictions = 0;
|
|
181
|
+
let totalSize = 0;
|
|
182
|
+
for (const shard of this.shards) {
|
|
183
|
+
const stats = shard.getStats();
|
|
184
|
+
totalHits += stats.hits;
|
|
185
|
+
totalMisses += stats.misses;
|
|
186
|
+
totalEvictions += stats.evictions;
|
|
187
|
+
totalSize += stats.size;
|
|
188
|
+
}
|
|
189
|
+
const total = totalHits + totalMisses;
|
|
190
|
+
return {
|
|
191
|
+
hits: totalHits,
|
|
192
|
+
misses: totalMisses,
|
|
193
|
+
evictions: totalEvictions,
|
|
194
|
+
size: totalSize,
|
|
195
|
+
hitRate: total > 0 ? totalHits / total : 0
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
function cached(cache, keyFn) {
|
|
200
|
+
return function(target, propertyKey, descriptor) {
|
|
201
|
+
const originalMethod = descriptor.value;
|
|
202
|
+
descriptor.value = function(...args) {
|
|
203
|
+
const key = keyFn ? keyFn(...args) : `${propertyKey}:${JSON.stringify(args)}`;
|
|
204
|
+
const cached2 = cache.get(key);
|
|
205
|
+
if (cached2 !== void 0) {
|
|
206
|
+
return cached2;
|
|
207
|
+
}
|
|
208
|
+
const result = originalMethod.apply(this, args);
|
|
209
|
+
cache.set(key, result);
|
|
210
|
+
return result;
|
|
211
|
+
};
|
|
212
|
+
return descriptor;
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
var blockhashCache = new TTLCache(2e3);
|
|
216
|
+
var accountCache = new ShardedCache(16, 500, 1e4);
|
|
217
|
+
var priceCache = new TTLCache(1e3);
|
|
218
|
+
|
|
219
|
+
export {
|
|
220
|
+
LRUCache,
|
|
221
|
+
TTLCache,
|
|
222
|
+
ShardedCache,
|
|
223
|
+
cached,
|
|
224
|
+
blockhashCache,
|
|
225
|
+
accountCache,
|
|
226
|
+
priceCache
|
|
227
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
__require,
|
|
15
|
+
__export
|
|
16
|
+
};
|