or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

account-management.mdcore-primitives.mdcryptography.mdencoding-codecs.mderror-handling.mdhigh-level-utilities.mdindex.mdinstructions-programs.mdrpc-communication.mdsigning-authentication.mdtransaction-building.md

account-management.mddocs/

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

```