0
# Account Management
1
2
Account data fetching, parsing, and validation with support for various encoding formats and specialized account types.
3
4
## Capabilities
5
6
### Account Data Structures
7
8
Core account information and data representations.
9
10
```typescript { .api }
11
/**
12
* Base account information returned by RPC
13
*/
14
interface BaseAccount {
15
/** Account balance in lamports */
16
lamports: Lamports;
17
/** Program that owns this account */
18
programId: Address;
19
/** Whether this account contains executable code */
20
executable: boolean;
21
/** Rent epoch for rent collection */
22
rentEpoch?: bigint;
23
}
24
25
/**
26
* Complete account with address and decoded data
27
*/
28
interface Account<TData, TAddress = Address> extends BaseAccount {
29
/** Account address */
30
address: TAddress;
31
/** Decoded account data */
32
data: TData;
33
}
34
35
/**
36
* Account with raw encoded data
37
*/
38
interface EncodedAccount<TAddress = Address> extends BaseAccount {
39
/** Account address */
40
address: TAddress;
41
/** Raw account data as Uint8Array */
42
data: Uint8Array;
43
}
44
45
/**
46
* Account that may or may not exist
47
*/
48
type MaybeAccount<TData, TAddress = Address> = Account<TData, TAddress> | null;
49
50
/**
51
* Encoded account that may or may not exist
52
*/
53
type MaybeEncodedAccount<TAddress = Address> = EncodedAccount<TAddress> | null;
54
```
55
56
### Account Fetching
57
58
Retrieve account data from the blockchain with various encoding options.
59
60
```typescript { .api }
61
/**
62
* Fetch account with base64-encoded data
63
* @param rpc - RPC client instance
64
* @param address - Account address to fetch
65
* @param config - Optional fetch configuration
66
* @returns Promise resolving to account with Uint8Array data or null
67
*/
68
function fetchEncodedAccount<TAddress extends Address>(
69
rpc: Rpc<GetAccountInfoApi>,
70
address: TAddress,
71
config?: FetchAccountConfig
72
): Promise<MaybeEncodedAccount<TAddress>>;
73
74
/**
75
* Fetch account with JSON-parsed data
76
* @param rpc - RPC client instance
77
* @param address - Account address to fetch
78
* @param config - Optional fetch configuration
79
* @returns Promise resolving to account with parsed data or null
80
*/
81
function fetchJsonParsedAccount<TData, TAddress extends Address = Address>(
82
rpc: Rpc<GetAccountInfoApi>,
83
address: TAddress,
84
config?: FetchAccountConfig
85
): Promise<MaybeAccount<TData, TAddress>>;
86
87
/**
88
* Fetch multiple accounts with encoded data
89
* @param rpc - RPC client instance
90
* @param addresses - Array of addresses to fetch
91
* @param config - Optional fetch configuration
92
* @returns Promise resolving to array of accounts or null values
93
*/
94
function fetchEncodedAccounts<TAddress extends Address>(
95
rpc: Rpc<GetMultipleAccountsApi>,
96
addresses: TAddress[],
97
config?: FetchAccountsConfig
98
): Promise<MaybeEncodedAccount<TAddress>[]>;
99
100
/**
101
* Fetch multiple accounts with JSON-parsed data
102
* @param rpc - RPC client instance
103
* @param addresses - Array of addresses to fetch
104
* @param config - Optional fetch configuration
105
* @returns Promise resolving to array of accounts with parsed data
106
*/
107
function fetchJsonParsedAccounts<TData, TAddress extends Address = Address>(
108
rpc: Rpc<GetMultipleAccountsApi>,
109
addresses: TAddress[],
110
config?: FetchAccountsConfig
111
): Promise<MaybeAccount<TData, TAddress>[]>;
112
```
113
114
**Usage Examples:**
115
116
```typescript
117
import {
118
fetchEncodedAccount,
119
fetchJsonParsedAccount,
120
createSolanaRpc,
121
address
122
} from "@solana/web3.js";
123
124
const rpc = createSolanaRpc("https://api.devnet.solana.com");
125
126
// Fetch encoded account data
127
const encodedAccount = await fetchEncodedAccount(
128
rpc,
129
address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
130
);
131
132
if (encodedAccount) {
133
console.log("Account data:", encodedAccount.data);
134
console.log("Lamports:", encodedAccount.lamports);
135
}
136
137
// Fetch JSON-parsed token account
138
interface TokenAccount {
139
mint: string;
140
owner: string;
141
amount: string;
142
delegate?: string;
143
state: "initialized" | "uninitialized" | "frozen";
144
}
145
146
const tokenAccount = await fetchJsonParsedAccount<TokenAccount>(
147
rpc,
148
address("your-token-account-address"),
149
{ encoding: "jsonParsed" }
150
);
151
152
if (tokenAccount) {
153
console.log("Token mint:", tokenAccount.data.mint);
154
console.log("Owner:", tokenAccount.data.owner);
155
}
156
```
157
158
### Account Decoding
159
160
Convert raw account data to typed structures using codecs.
161
162
```typescript { .api }
163
/**
164
* Decode account data using a provided codec
165
* @param encodedAccount - Account with raw data
166
* @param decoder - Codec decoder for the data type
167
* @returns Account with decoded data
168
*/
169
function decodeAccount<TData, TAddress extends Address>(
170
encodedAccount: EncodedAccount<TAddress>,
171
decoder: Decoder<Uint8Array, TData>
172
): Account<TData, TAddress>;
173
```
174
175
**Usage Examples:**
176
177
```typescript
178
import {
179
fetchEncodedAccount,
180
decodeAccount,
181
getStructCodec,
182
getU64Codec,
183
address
184
} from "@solana/web3.js";
185
186
// Define account data structure
187
interface MyAccountData {
188
value: bigint;
189
owner: Address;
190
}
191
192
// Create decoder
193
const accountDecoder = getStructCodec({
194
value: getU64Codec(),
195
owner: getAddressCodec()
196
});
197
198
// Fetch and decode
199
const encodedAccount = await fetchEncodedAccount(rpc, myAddress);
200
if (encodedAccount) {
201
const decodedAccount = decodeAccount(encodedAccount, accountDecoder);
202
console.log("Decoded value:", decodedAccount.data.value);
203
}
204
```
205
206
### Account Validation
207
208
Validate and assert account states and data integrity.
209
210
```typescript { .api }
211
/**
212
* Assert that an account has been decoded (not raw bytes)
213
* @param account - Account to check
214
* @throws SolanaError if account data is not decoded
215
*/
216
function assertAccountDecoded<TData>(
217
account: Account<TData> | EncodedAccount
218
): asserts account is Account<TData>;
219
220
/**
221
* Assert that all accounts in array have been decoded
222
* @param accounts - Array of accounts to check
223
* @throws SolanaError if any account data is not decoded
224
*/
225
function assertAccountsDecoded<TData>(
226
accounts: (Account<TData> | EncodedAccount)[]
227
): asserts accounts is Account<TData>[];
228
229
/**
230
* Assert that a maybe account exists (is not null)
231
* @param account - Maybe account to check
232
* @throws SolanaError if account is null
233
*/
234
function assertAccountExists<TData, TAddress>(
235
account: MaybeAccount<TData, TAddress>
236
): asserts account is Account<TData, TAddress>;
237
238
/**
239
* Assert that all maybe accounts exist
240
* @param accounts - Array of maybe accounts to check
241
* @throws SolanaError if any account is null
242
*/
243
function assertAccountsExist<TData, TAddress>(
244
accounts: MaybeAccount<TData, TAddress>[]
245
): asserts accounts is Account<TData, TAddress>[];
246
```
247
248
### RPC Response Parsing
249
250
Parse raw RPC responses into structured account data.
251
252
```typescript { .api }
253
/**
254
* Parse RPC account response with base64 encoding
255
* @param rpcAccount - Raw RPC account response
256
* @returns Parsed account with Uint8Array data
257
*/
258
function parseBase64RpcAccount<TAddress extends Address>(
259
rpcAccount: RpcAccount,
260
address: TAddress
261
): EncodedAccount<TAddress>;
262
263
/**
264
* Parse RPC account response with base58 encoding
265
* @param rpcAccount - Raw RPC account response
266
* @returns Parsed account with Uint8Array data
267
*/
268
function parseBase58RpcAccount<TAddress extends Address>(
269
rpcAccount: RpcAccount,
270
address: TAddress
271
): EncodedAccount<TAddress>;
272
273
/**
274
* Parse RPC account response with JSON encoding
275
* @param rpcAccount - Raw RPC account response
276
* @returns Parsed account with structured data
277
*/
278
function parseJsonRpcAccount<TData, TAddress extends Address>(
279
rpcAccount: RpcAccount,
280
address: TAddress
281
): Account<TData, TAddress>;
282
```
283
284
### Specialized Account Types
285
286
Pre-defined parsers for common Solana account types.
287
288
```typescript { .api }
289
/**
290
* Address lookup table account data
291
*/
292
interface AddressLookupTableAccount {
293
addresses: Address[];
294
authority?: Address;
295
deactivationSlot: Slot;
296
}
297
298
/**
299
* Token account data structure
300
*/
301
interface TokenAccount {
302
mint: Address;
303
owner: Address;
304
amount: bigint;
305
delegate?: Address;
306
state: "initialized" | "uninitialized" | "frozen";
307
isNative?: bigint;
308
delegatedAmount: bigint;
309
closeAuthority?: Address;
310
}
311
312
/**
313
* Token mint account data
314
*/
315
interface MintAccount {
316
mintAuthority?: Address;
317
supply: bigint;
318
decimals: number;
319
isInitialized: boolean;
320
freezeAuthority?: Address;
321
}
322
323
/**
324
* Stake account data
325
*/
326
interface StakeAccount {
327
meta: {
328
rentExemptReserve: Lamports;
329
authorized: {
330
staker: Address;
331
withdrawer: Address;
332
};
333
lockup: {
334
unixTimestamp: UnixTimestamp;
335
epoch: bigint;
336
custodian: Address;
337
};
338
};
339
stake?: {
340
delegation: {
341
voterPubkey: Address;
342
stake: Lamports;
343
activationEpoch: bigint;
344
deactivationEpoch: bigint;
345
};
346
creditsObserved: bigint;
347
};
348
}
349
```
350
351
## Configuration and Options
352
353
```typescript { .api }
354
/**
355
* Configuration for fetching single accounts
356
*/
357
interface FetchAccountConfig {
358
/** Commitment level for the request */
359
commitment?: Commitment;
360
/** Minimum context slot for the request */
361
minContextSlot?: Slot;
362
/** Data encoding format */
363
encoding?: "base58" | "base64" | "jsonParsed";
364
/** Data slice to retrieve */
365
dataSlice?: {
366
offset: number;
367
length: number;
368
};
369
}
370
371
/**
372
* Configuration for fetching multiple accounts
373
*/
374
interface FetchAccountsConfig extends FetchAccountConfig {
375
/** Maximum number of accounts per request */
376
batchSize?: number;
377
}
378
379
/**
380
* RPC account response structure
381
*/
382
interface RpcAccount {
383
/** Account balance in lamports */
384
lamports: number;
385
/** Base64 or base58 encoded data */
386
data: [string, string] | string;
387
/** Program owner */
388
owner: string;
389
/** Whether account is executable */
390
executable: boolean;
391
/** Rent epoch */
392
rentEpoch: number;
393
}
394
395
/**
396
* Account size constant
397
*/
398
const BASE_ACCOUNT_SIZE = 128;
399
```
400
401
**Advanced Usage Examples:**
402
403
```typescript
404
import {
405
fetchEncodedAccounts,
406
assertAccountsExist,
407
assertAccountsDecoded,
408
createSolanaRpc
409
} from "@solana/web3.js";
410
411
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
412
413
// Batch fetch with validation
414
const addresses = [
415
address("account1..."),
416
address("account2..."),
417
address("account3...")
418
];
419
420
const accounts = await fetchEncodedAccounts(rpc, addresses, {
421
commitment: "confirmed",
422
batchSize: 100
423
});
424
425
// Validate all accounts exist
426
assertAccountsExist(accounts);
427
428
// Now accounts is typed as Account<Uint8Array>[] (no nulls)
429
console.log("All accounts loaded:", accounts.length);
430
431
// Process accounts with error handling
432
for (const account of accounts) {
433
try {
434
// Decode account data here
435
console.log(`Account ${account.address} has ${account.lamports} lamports`);
436
} catch (error) {
437
console.error(`Failed to process account ${account.address}:`, error);
438
}
439
}
440
```