1
- import { IAgentRuntime , Memory , Provider , State } from "@ai16z/eliza" ;
1
+ import {
2
+ IAgentRuntime ,
3
+ ICacheManager ,
4
+ Memory ,
5
+ Provider ,
6
+ State ,
7
+ } from "@ai16z/eliza" ;
2
8
import {
3
9
Account ,
4
10
Aptos ,
@@ -10,6 +16,8 @@ import {
10
16
} from "@aptos-labs/ts-sdk" ;
11
17
import BigNumber from "bignumber.js" ;
12
18
import NodeCache from "node-cache" ;
19
+ import * as path from "path" ;
20
+ import { APT_DECIMALS } from "../constants" ;
13
21
14
22
// Provider configuration
15
23
const PROVIDER_CONFIG = {
@@ -19,7 +27,7 @@ const PROVIDER_CONFIG = {
19
27
20
28
interface WalletPortfolio {
21
29
totalUsd : string ;
22
- totalApt ? : string ;
30
+ totalApt : string ;
23
31
}
24
32
25
33
interface Prices {
@@ -28,15 +36,56 @@ interface Prices {
28
36
29
37
export class WalletProvider {
30
38
private cache : NodeCache ;
39
+ private cacheKey : string = "aptos/wallet" ;
31
40
32
41
constructor (
33
42
private aptosClient : Aptos ,
34
- private address : string
43
+ private address : string ,
44
+ private cacheManager : ICacheManager
35
45
) {
36
46
this . cache = new NodeCache ( { stdTTL : 300 } ) ; // Cache TTL set to 5 minutes
37
47
}
38
48
39
- private async fetchAptPriceWithRetry ( ) {
49
+ private async readFromCache < T > ( key : string ) : Promise < T | null > {
50
+ const cached = await this . cacheManager . get < T > (
51
+ path . join ( this . cacheKey , key )
52
+ ) ;
53
+ return cached ;
54
+ }
55
+
56
+ private async writeToCache < T > ( key : string , data : T ) : Promise < void > {
57
+ await this . cacheManager . set ( path . join ( this . cacheKey , key ) , data , {
58
+ expires : Date . now ( ) + 5 * 60 * 1000 ,
59
+ } ) ;
60
+ }
61
+
62
+ private async getCachedData < T > ( key : string ) : Promise < T | null > {
63
+ // Check in-memory cache first
64
+ const cachedData = this . cache . get < T > ( key ) ;
65
+ if ( cachedData ) {
66
+ return cachedData ;
67
+ }
68
+
69
+ // Check file-based cache
70
+ const fileCachedData = await this . readFromCache < T > ( key ) ;
71
+ if ( fileCachedData ) {
72
+ // Populate in-memory cache
73
+ this . cache . set ( key , fileCachedData ) ;
74
+ return fileCachedData ;
75
+ }
76
+
77
+ return null ;
78
+ }
79
+
80
+ private async setCachedData < T > ( cacheKey : string , data : T ) : Promise < void > {
81
+ // Set in-memory cache
82
+ this . cache . set ( cacheKey , data ) ;
83
+
84
+ // Write to file-based cache
85
+ await this . writeToCache ( cacheKey , data ) ;
86
+ }
87
+
88
+ private async fetchPricesWithRetry ( ) {
40
89
let lastError : Error ;
41
90
42
91
for ( let i = 0 ; i < PROVIDER_CONFIG . MAX_RETRIES ; i ++ ) {
@@ -77,19 +126,20 @@ export class WalletProvider {
77
126
async fetchPortfolioValue ( ) : Promise < WalletPortfolio > {
78
127
try {
79
128
const cacheKey = `portfolio-${ this . address } ` ;
80
- const cachedValue = this . cache . get < WalletPortfolio > ( cacheKey ) ;
129
+ const cachedValue =
130
+ await this . getCachedData < WalletPortfolio > ( cacheKey ) ;
81
131
82
132
if ( cachedValue ) {
83
- console . log ( "Cache hit for fetchPortfolioValue" ) ;
133
+ console . log ( "Cache hit for fetchPortfolioValue" , cachedValue ) ;
84
134
return cachedValue ;
85
135
}
86
136
console . log ( "Cache miss for fetchPortfolioValue" ) ;
87
137
88
- const aptPrice = await this . fetchAptPrice ( ) . catch ( ( error ) => {
138
+ const prices = await this . fetchPrices ( ) . catch ( ( error ) => {
89
139
console . error ( "Error fetching APT price:" , error ) ;
90
140
throw error ;
91
141
} ) ;
92
- const aptAmount = await this . aptosClient
142
+ const aptAmountOnChain = await this . aptosClient
93
143
. getAccountAPTAmount ( {
94
144
accountAddress : this . address ,
95
145
} )
@@ -98,32 +148,36 @@ export class WalletProvider {
98
148
throw error ;
99
149
} ) ;
100
150
101
- const totalUsd = new BigNumber ( aptAmount ) . times ( aptPrice . apt . usd ) ;
151
+ const aptAmount = new BigNumber ( aptAmountOnChain ) . div (
152
+ new BigNumber ( 10 ) . pow ( APT_DECIMALS )
153
+ ) ;
154
+ const totalUsd = new BigNumber ( aptAmount ) . times ( prices . apt . usd ) ;
102
155
103
156
const portfolio = {
104
157
totalUsd : totalUsd . toString ( ) ,
105
158
totalApt : aptAmount . toString ( ) ,
106
159
} ;
107
- this . cache . set ( cacheKey , portfolio ) ;
160
+ this . setCachedData ( cacheKey , portfolio ) ;
161
+ console . log ( "Fetched portfolio:" , portfolio ) ;
108
162
return portfolio ;
109
163
} catch ( error ) {
110
164
console . error ( "Error fetching portfolio:" , error ) ;
111
165
throw error ;
112
166
}
113
167
}
114
168
115
- async fetchAptPrice ( ) : Promise < Prices > {
169
+ async fetchPrices ( ) : Promise < Prices > {
116
170
try {
117
171
const cacheKey = "prices" ;
118
- const cachedValue = this . cache . get < Prices > ( cacheKey ) ;
172
+ const cachedValue = await this . getCachedData < Prices > ( cacheKey ) ;
119
173
120
174
if ( cachedValue ) {
121
175
console . log ( "Cache hit for fetchPrices" ) ;
122
176
return cachedValue ;
123
177
}
124
178
console . log ( "Cache miss for fetchPrices" ) ;
125
179
126
- const aptPriceData = await this . fetchAptPriceWithRetry ( ) . catch (
180
+ const aptPriceData = await this . fetchPricesWithRetry ( ) . catch (
127
181
( error ) => {
128
182
console . error ( "Error fetching APT price:" , error ) ;
129
183
throw error ;
@@ -132,7 +186,7 @@ export class WalletProvider {
132
186
const prices : Prices = {
133
187
apt : { usd : aptPriceData . pair . priceUsd } ,
134
188
} ;
135
- this . cache . set ( cacheKey , prices ) ;
189
+ this . setCachedData ( cacheKey , prices ) ;
136
190
return prices ;
137
191
} catch ( error ) {
138
192
console . error ( "Error fetching prices:" , error ) ;
@@ -141,13 +195,13 @@ export class WalletProvider {
141
195
}
142
196
143
197
formatPortfolio ( runtime , portfolio : WalletPortfolio ) : string {
144
- let output = `${ runtime . character . description } \n` ;
145
- output += `Wallet Address: ${ this . address } \n\n ` ;
198
+ let output = `${ runtime . character . name } \n` ;
199
+ output += `Wallet Address: ${ this . address } \n` ;
146
200
147
201
const totalUsdFormatted = new BigNumber ( portfolio . totalUsd ) . toFixed ( 2 ) ;
148
- const totalAptFormatted = portfolio . totalApt ;
202
+ const totalAptFormatted = new BigNumber ( portfolio . totalApt ) . toFixed ( 4 ) ;
149
203
150
- output += `Total Value: $${ totalUsdFormatted } (${ totalAptFormatted } APT)\n\n ` ;
204
+ output += `Total Value: $${ totalUsdFormatted } (${ totalAptFormatted } APT)\n` ;
151
205
152
206
return output ;
153
207
}
@@ -188,7 +242,8 @@ const walletProvider: Provider = {
188
242
) ;
189
243
const provider = new WalletProvider (
190
244
aptosClient ,
191
- aptosAccount . accountAddress . toStringLong ( )
245
+ aptosAccount . accountAddress . toStringLong ( ) ,
246
+ runtime . cacheManager
192
247
) ;
193
248
return await provider . getFormattedPortfolio ( runtime ) ;
194
249
} catch ( error ) {
0 commit comments