abstract-solana 0.0.0.89__py3-none-any.whl → 0.0.0.92__py3-none-any.whl

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.

Potentially problematic release.


This version of abstract-solana might be problematic. Click here for more details.

@@ -0,0 +1,1179 @@
1
+ from __future__ import annotations
2
+ from time import sleep, time
3
+ from typing import Dict, List, Optional, Sequence, Union
4
+ from abstract_solana import get_pubkey,get_sigkey
5
+ from solders.hash import Hash as Blockhash
6
+ from solders.keypair import Keypair
7
+ from solders.message import VersionedMessage
8
+ from solders.pubkey import Pubkey
9
+ from solders.rpc.responses import (
10
+ GetAccountInfoMaybeJsonParsedResp,
11
+ GetAccountInfoResp,
12
+ GetBalanceResp,
13
+ GetBlockCommitmentResp,
14
+ GetBlockHeightResp,
15
+ GetBlockResp,
16
+ GetBlocksResp,
17
+ GetBlockTimeResp,
18
+ GetClusterNodesResp,
19
+ GetEpochInfoResp,
20
+ GetEpochScheduleResp,
21
+ GetFeeForMessageResp,
22
+ GetFirstAvailableBlockResp,
23
+ GetGenesisHashResp,
24
+ GetIdentityResp,
25
+ GetInflationGovernorResp,
26
+ GetInflationRateResp,
27
+ GetInflationRewardResp,
28
+ GetLargestAccountsResp,
29
+ GetLatestBlockhashResp,
30
+ GetLeaderScheduleResp,
31
+ GetMinimumBalanceForRentExemptionResp,
32
+ GetMultipleAccountsMaybeJsonParsedResp,
33
+ GetMultipleAccountsResp,
34
+ GetProgramAccountsMaybeJsonParsedResp,
35
+ GetProgramAccountsResp,
36
+ GetRecentPerformanceSamplesResp,
37
+ GetSignaturesForAddressResp,
38
+ GetSignatureStatusesResp,
39
+ GetSlotLeaderResp,
40
+ GetSlotResp,
41
+ GetStakeActivationResp,
42
+ GetSupplyResp,
43
+ GetTokenAccountBalanceResp,
44
+ GetTokenAccountsByDelegateJsonParsedResp,
45
+ GetTokenAccountsByDelegateResp,
46
+ GetTokenAccountsByOwnerJsonParsedResp,
47
+ GetTokenAccountsByOwnerResp,
48
+ GetTokenLargestAccountsResp,
49
+ GetTokenSupplyResp,
50
+ GetTransactionCountResp,
51
+ GetTransactionResp,
52
+ GetVersionResp,
53
+ GetVoteAccountsResp,
54
+ MinimumLedgerSlotResp,
55
+ RequestAirdropResp,
56
+ RPCError,
57
+ SendTransactionResp,
58
+ SimulateTransactionResp,
59
+ ValidatorExitResp,
60
+ )
61
+ import json
62
+ from solders.signature import Signature
63
+ from solders.transaction import VersionedTransaction
64
+
65
+ from solana.rpc import types
66
+ from solana.transaction import Transaction
67
+
68
+ from solana.rpc.commitment import Commitment, Finalized
69
+ from solana.rpc.core import (
70
+ _COMMITMENT_TO_SOLDERS,
71
+ RPCException,
72
+ TransactionExpiredBlockheightExceededError,
73
+ UnconfirmedTxError,
74
+ _ClientCore,
75
+ )
76
+ from sqlalchemy import create_engine, Column, String, Integer, JSON
77
+ from sqlalchemy.ext.declarative import declarative_base
78
+ from sqlalchemy.orm import sessionmaker
79
+ import psycopg2
80
+ import json
81
+
82
+
83
+ from solana.rpc.providers import http
84
+ from abstract_apis.make_request import *
85
+ from abstract_solcatcher import get_solcatcher_api
86
+
87
+ def makeRpcCall(*args,**kwargs):
88
+ return get_solcatcher_api('/api/v1/rpc_call',**kwargs)
89
+
90
+ class Client(_ClientCore): # pylint: disable=too-many-public-methods
91
+ """Client class.
92
+
93
+ Args:
94
+ endpoint: URL of the RPC endpoint.
95
+ commitment: Default bank state to query. It can be either "finalized", "confirmed" or "processed".
96
+ timeout: HTTP request timeout in seconds.
97
+ extra_headers: Extra headers to pass for HTTP request.
98
+
99
+ """
100
+
101
+ def __init__(
102
+ self,
103
+ endpoint: Optional[str] = None,
104
+ commitment: Optional[Commitment] = "confirmed",
105
+ timeout: float = 10,
106
+ extra_headers: Optional[Dict[str, str]] = None,
107
+ ):
108
+ """Init API client."""
109
+ super().__init__(commitment)
110
+ self._provider = get_solcatcher_api('/api/v1/rpc_call', timeout=timeout, extra_headers=extra_headers)
111
+
112
+ def is_connected(self) -> bool:
113
+ """Health check.
114
+
115
+ Example:
116
+ >>> solana_client = Client("http://localhost:8899")
117
+ >>> solana_client.is_connected() # doctest: +SKIP
118
+ True
119
+
120
+ Returns:
121
+ True if the client is connected.
122
+ """
123
+ body = json.loads(str(self._get_transaction_body(get_sigkey(signature), encoding, commitment, max_supported_transaction_version)))
124
+
125
+ return body
126
+
127
+ def get_balance(self, pubkey: Pubkey, commitment: Optional[Commitment] = "finalized") -> GetBalanceResp:
128
+ """Returns the balance of the account of provided Pubkey.
129
+
130
+ Args:
131
+ pubkey: Pubkey of account to query
132
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
133
+
134
+ Example:
135
+ >>> from solders.pubkey import Pubkey
136
+ >>> solana_client = Client("http://localhost:8899")
137
+ >>> solana_client.get_balance(Pubkey([0] * 31 + [1])).value # doctest: +SKIP
138
+ 4104230290
139
+ """
140
+ body = json.loads(str(self._get_balance_body(pubkey, commitment)))
141
+ return body
142
+
143
+ def get_account_info(
144
+ self,
145
+ pubkey: Pubkey,
146
+ commitment: Optional[Commitment] = "confirmed",
147
+ encoding: str = "base64",
148
+ data_slice: Optional[types.DataSliceOpts] = None,
149
+ ) -> GetAccountInfoResp:
150
+ """Returns all the account info for the specified public key, encoded in either base58 or base64.
151
+
152
+ Args:
153
+ pubkey: Pubkey of account to query.
154
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
155
+ encoding: (optional) Encoding for Account data, either "base58" (slow) or "base64".
156
+ Default is "base64".
157
+
158
+ - "base58" is limited to Account data of less than 128 bytes.
159
+ - "base64" will return body
160
+ data_slice: (optional) Option to limit the returned account data using the provided `offset`: <usize> and
161
+ `length`: <usize> fields; only available for "base58" or "base64" encoding.
162
+
163
+ Example:
164
+ >>> from solders.pubkey import Pubkey
165
+ >>> solana_client = Client("http://localhost:8899")
166
+ >>> solana_client.get_account_info(Pubkey([0] * 31 + [1])).value # doctest: +SKIP
167
+ Account(
168
+ Account {
169
+ lamports: 4104230290,
170
+ data.len: 0,
171
+ owner: 11111111111111111111111111111111,
172
+ executable: false,
173
+ rent_epoch: 371,
174
+ },
175
+ )))
176
+ """
177
+ body = json.loads(str(self._get_account_info_body(
178
+ pubkey=pubkey,
179
+ commitment=commitment,
180
+ encoding=encoding,
181
+ data_slice=data_slice,
182
+ )))
183
+ return body
184
+
185
+ def get_account_info_json_parsed(
186
+ self,
187
+ pubkey: Pubkey,
188
+ commitment: Optional[Commitment] = "confirmed",
189
+ ) -> GetAccountInfoMaybeJsonParsedResp:
190
+ """Returns all the account info for the specified public key in parsed JSON format.
191
+
192
+ If JSON formatting is not available for this account, base64 is returned.
193
+
194
+ Args:
195
+ pubkey: Pubkey of account to query.
196
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
197
+
198
+ Example:
199
+ >>> from solders.pubkey import Pubkey
200
+ >>> solana_client = Client("http://localhost:8899")
201
+ >>> solana_client.get_account_info_json_parsed(Pubkey([0] * 31 + [1])).value.owner # doctest: +SKIP
202
+ Pubkey(
203
+ 11111111111111111111111111111111,
204
+ )))
205
+ """
206
+ body = json.loads(str(self._get_account_info_body(pubkey=get_pubkey(pubkey), commitment=commitment, encoding="jsonParsed", data_slice=None)))
207
+ return body
208
+
209
+ def get_block_commitment(self, slot: int) -> GetBlockCommitmentResp:
210
+ """Fetch the commitment for particular block.
211
+
212
+ Args:
213
+ slot: Block, identified by Slot.
214
+
215
+ Example:
216
+ >>> solana_client = Client("http://localhost:8899")
217
+ >>> solana_client.get_block_commitment(0).total_stake # doctest: +SKIP
218
+ 497717120
219
+ """
220
+ body = json.loads(str(self._get_block_commitment_body(slot)))
221
+ return body
222
+
223
+ def get_block_time(self, slot: int) -> GetBlockTimeResp:
224
+ """Fetch the estimated production time of a block.
225
+
226
+ Args:
227
+ slot: Block, identified by Slot.
228
+
229
+ Example:
230
+ >>> solana_client = Client("http://localhost:8899")
231
+ >>> solana_client.get_block_time(5).value # doctest: +SKIP
232
+ 1598400007
233
+ """
234
+ body = json.loads(str(self._get_block_time_body(slot)))
235
+ return body
236
+
237
+ def get_cluster_nodes(self) -> GetClusterNodesResp:
238
+ """Returns information about all the nodes participating in the cluster.
239
+
240
+ Example:
241
+ >>> solana_client = Client("http://localhost:8899")
242
+ >>> solana_client.get_cluster_nodes().value[0].tpu # doctest: +SKIP
243
+ '139.178.65.155:8004'
244
+ """
245
+ return body
246
+
247
+ def get_block(
248
+ self,
249
+ slot: int,
250
+ encoding: str = "json",
251
+ max_supported_transaction_version: Union[int, None] = 0,
252
+ ) -> GetBlockResp:
253
+ """Returns identity and transaction information about a confirmed block in the ledger.
254
+
255
+ Args:
256
+ slot: Slot, as u64 integer.
257
+ encoding: (optional) Encoding for the returned Transaction, either "json", "jsonParsed",
258
+ "base58" (slow), or "base64". If parameter not provided, the default encoding is JSON.
259
+ max_supported_transaction_version: (optional) The max transaction version to return body
260
+ responses. If the requested transaction is a higher version, an error will be returned
261
+
262
+ Example:
263
+ >>> solana_client = Client("http://localhost:8899")
264
+ >>> solana_client.get_block(1).value.blockhash # doctest: +SKIP
265
+ Hash(
266
+ EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG,
267
+ )))
268
+ """
269
+ body = json.loads(str(self._get_block_body(int(slot), encoding, max_supported_transaction_version)))
270
+ return body
271
+
272
+ def get_recent_performance_samples(self, limit: Optional[int] = 1000) -> GetRecentPerformanceSamplesResp:
273
+ """Returns a list of recent performance samples, in reverse slot order.
274
+
275
+ Performance samples are taken every 60 seconds and include the number of transactions and slots that occur in a given time window.
276
+
277
+ Args:
278
+ limit: Limit (optional) number of samples to return body
279
+
280
+ Examples:
281
+ >>> solana_client = Client("http://localhost:8899")
282
+ >>> solana_client.get_recent_performance_samples(1).value[0] # doctest: +SKIP
283
+ RpcPerfSample(
284
+ RpcPerfSample {
285
+ slot: 168036172,
286
+ num_transactions: 7159,
287
+ num_slots: 158,
288
+ sample_period_secs: 60,
289
+ },
290
+ )))
291
+ """ # noqa: E501 # pylint: disable=line-too-long
292
+ body = json.loads(str(self._get_recent_performance_samples_body(limit)))
293
+ return body
294
+
295
+ def get_block_height(self, commitment: Optional[Commitment] = "finalized") -> GetBlockHeightResp:
296
+ """Returns the current block height of the node.
297
+
298
+ Args:
299
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
300
+
301
+ Example:
302
+ >>> solana_client = Client("http://localhost:8899")
303
+ >>> solana_client.get_block_height().value # doctest: +SKIP
304
+ 1233
305
+ """
306
+ body = json.loads(str(self._get_block_height_body(commitment)))
307
+ return body
308
+
309
+ def get_blocks(self, start_slot: int, end_slot: Optional[int] = None) -> GetBlocksResp:
310
+ """Returns a list of confirmed blocks.
311
+
312
+ Args:
313
+ start_slot: Start slot, as u64 integer.
314
+ end_slot: (optional) End slot, as u64 integer.
315
+
316
+ Example:
317
+ >>> solana_client = Client("http://localhost:8899")
318
+ >>> solana_client.get_blocks(5, 10).value # doctest: +SKIP
319
+ [5, 6, 7, 8, 9, 10]
320
+ """
321
+ body = json.loads(str(self._get_blocks_body(start_slot, end_slot)))
322
+ return body
323
+
324
+ def get_signatures_for_address(
325
+ self,
326
+ account: Pubkey,
327
+ before: Optional[Signature] = None,
328
+ until: Optional[Signature] = None,
329
+ limit: Optional[int] = 1000,
330
+ commitment: Optional[Commitment] = "confirmed",
331
+ ) -> GetSignaturesForAddressResp:
332
+ """Returns confirmed signatures for transactions involving an address.
333
+
334
+ Signatures are returned backwards in time from the provided signature or
335
+ most recent confirmed block.
336
+
337
+ Args:
338
+ account: Account to be queried.
339
+ before: (optional) Start searching backwards from this transaction signature.
340
+ If not provided the search starts from the top of the highest max confirmed block.
341
+ until: (optional) Search until this transaction signature, if found before limit reached.
342
+ limit: (optional) Maximum transaction signatures to return body
343
+ commitment: (optional) Bank state to query. It can be either "finalized", "confirmed" or "processed".
344
+
345
+ Example:
346
+ >>> solana_client = Client("http://localhost:8899")
347
+ >>> from solders.pubkey import Pubkey
348
+ >>> pubkey = Pubkey.from_string("Vote111111111111111111111111111111111111111")
349
+ >>> solana_client.get_signatures_for_address(pubkey, limit=1).value[0].signature # doctest: +SKIP
350
+ Signature(
351
+ 1111111111111111111111111111111111111111111111111111111111111111,
352
+ )))
353
+ """
354
+ body = json.loads(str(self._get_signatures_for_address_body(get_pubkey(account), get_sigkey(before), get_sigkey(until), limit, commitment)))
355
+ return body
356
+
357
+ def get_transaction(
358
+ self,
359
+ signature: Signature,
360
+ encoding: str = "json",
361
+ commitment: Optional[Commitment] = "confirmed",
362
+ max_supported_transaction_version: Optional[int] = 0,
363
+ ) -> GetTransactionResp:
364
+ """Returns transaction details for a confirmed transaction.
365
+
366
+ Args:
367
+ tx_sig: Transaction signature as base-58 encoded string N encoding attempts to use program-specific
368
+ instruction parsers to return body
369
+ `transaction.message.instructions` list.
370
+ encoding: (optional) Encoding for the returned Transaction, either "json", "jsonParsed",
371
+ "base58" (slow), or "base64". If parameter not provided, the default encoding is JSON.
372
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
373
+ max_supported_transaction_version: (optional) The max transaction version to return body
374
+ If the requested transaction is a higher version, an error will be returned
375
+
376
+ Example:
377
+ >>> solana_client = Client("http://localhost:8899")
378
+ >>> from solders.signature import Signature
379
+ >>> sig = Signature.from_string("3PtGYH77LhhQqTXP4SmDVJ85hmDieWsgXCUbn14v7gYyVYPjZzygUQhTk3bSTYnfA48vCM1rmWY7zWL3j1EVKmEy")
380
+ >>> solana_client.get_transaction(sig).value.block_time # doctest: +SKIP
381
+ 1234
382
+ """ # noqa: E501 # pylint: disable=line-too-long
383
+
384
+ body = json.loads(str(self._get_transaction_body(get_sigkey(signature), encoding, commitment, max_supported_transaction_version)))
385
+ return body
386
+
387
+ def get_epoch_info(self, commitment: Optional[Commitment] = "finalized") -> GetEpochInfoResp:
388
+ """Returns information about the current epoch.
389
+
390
+ Args:
391
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
392
+
393
+ Example:
394
+ >>> solana_client = Client("http://localhost:8899")
395
+ >>> solana_client.get_epoch_info().value.epoch # doctest: +SKIP
396
+ 0
397
+ """
398
+ body = json.loads(str(self._get_epoch_info_body(commitment)))
399
+ return body
400
+
401
+ def get_epoch_schedule(self) -> GetEpochScheduleResp:
402
+ """Returns epoch schedule information from this cluster's genesis config.
403
+
404
+ Example:
405
+ >>> solana_client = Client("http://localhost:8899")
406
+ >>> solana_client.get_epoch_schedule().value.slots_per_epoch # doctest: +SKIP
407
+ 8192
408
+ """
409
+ return body
410
+
411
+ def get_fee_for_message(
412
+ self, message: VersionedMessage, commitment: Optional[Commitment] = "finalized"
413
+ ) -> GetFeeForMessageResp:
414
+ """Returns the fee for a message.
415
+
416
+ Args:
417
+ message: Message that the fee is requested for.
418
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
419
+
420
+ Example:
421
+ >>> from solders.keypair import Keypair
422
+ >>> from solders.system_program import TransferParams, transfer
423
+ >>> from solana.transaction import Transaction
424
+ >>> leading_zeros = [0] * 31
425
+ >>> sender, receiver = Keypair.from_seed(leading_zeros + [1]), Keypair.from_seed(leading_zeros + [2])
426
+ >>> txn = Transaction().add(transfer(TransferParams(
427
+ ... from_pubkey=sender.pubkey(), to_pubkey=receiver.pubkey(), lamports=1000)))
428
+ >>> solana_client = Client("http://localhost:8899")
429
+ >>> solana_client.get_fee_for_message(txn.compile_message(.value # doctest: +SKIP
430
+ 5000
431
+ """
432
+ body = json.loads(str(self._get_fee_for_message_body(message, commitment)))
433
+ return body
434
+
435
+ def get_first_available_block(self) -> GetFirstAvailableBlockResp:
436
+ """Returns the slot of the lowest confirmed block that has not been purged from the ledger.
437
+
438
+ Example:
439
+ >>> solana_client = Client("http://localhost:8899")
440
+ >>> solana_client.get_first_available_block().value # doctest: +SKIP
441
+ 1
442
+ """
443
+ return body
444
+
445
+ def get_genesis_hash(self) -> GetGenesisHashResp:
446
+ """Returns the genesis hash.
447
+
448
+ Example:
449
+ >>> solana_client = Client("http://localhost:8899")
450
+ >>> solana_client.get_genesis_hash().value # doctest: +SKIP
451
+ Hash(
452
+ EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG,
453
+ )))
454
+ """
455
+ return body
456
+
457
+ def get_identity(self) -> GetIdentityResp:
458
+ """Returns the identity pubkey for the current node.
459
+
460
+ Example:
461
+ >>> solana_client = Client("http://localhost:8899")
462
+ >>> solana_client.get_identity().value.identity # doctest: +SKIP
463
+ Pubkey(
464
+ 2LVtX3Wq5bhqAYYaUYBRknWaYrsfYiXLQBHTxtHWD2mv,
465
+ )))
466
+ """
467
+ return body
468
+
469
+ def get_inflation_governor(self, commitment: Optional[Commitment] = "finalized") -> GetInflationGovernorResp:
470
+ """Returns the current inflation governor.
471
+
472
+ Args:
473
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
474
+
475
+ Example:
476
+ >>> solana_client = Client("http://localhost:8899")
477
+ >>> solana_client.get_inflation_governor().value.foundation # doctest: +SKIP
478
+ 0.05
479
+ """
480
+ body = json.loads(str(self._get_inflation_governor_body(commitment)))
481
+ return body
482
+
483
+ def get_inflation_rate(self) -> GetInflationRateResp:
484
+ """Returns the specific inflation values for the current epoch.
485
+
486
+ Example:
487
+ >>> solana_client = Client("http://localhost:8899")
488
+ >>> solana_client.get_inflation_rate().value.epoch # doctest: +SKIP
489
+ 1
490
+ """
491
+ return body
492
+
493
+ def get_inflation_reward(
494
+ self, pubkeys: List[Pubkey], epoch: Optional[int] = None, commitment: Optional[Commitment] = "finalized"
495
+ ) -> GetInflationRewardResp:
496
+ """Returns the inflation / staking reward for a list of addresses for an epoch.
497
+
498
+ Args:
499
+ pubkeys: An array of addresses to query, as base-58 encoded strings
500
+ epoch: (optional) An epoch for which the reward occurs. If omitted, the previous epoch will be used
501
+ commitment: Bank state to query. It can be either "finalized" or "confirmed".
502
+
503
+ Example:
504
+ >>> solana_client = Client("http://localhost:8899")
505
+ >>> solana_client.get_inflation_reward().value.amount # doctest: +SKIP
506
+ 2500
507
+ """
508
+ body = json.loads(str(self._get_inflation_reward_body(get_pubkey(pubkeys), epoch, commitment)))
509
+ return body
510
+
511
+ def get_largest_accounts(
512
+ self, filter_opt: Optional[str] = None, commitment: Optional[Commitment] = "finalized"
513
+ ) -> GetLargestAccountsResp:
514
+ """Returns the 20 largest accounts, by lamport balance.
515
+
516
+ Args:
517
+ filter_opt: Filter results by account type; currently supported: circulating|nonCirculating.
518
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
519
+
520
+ Example:
521
+ >>> solana_client = Client("http://localhost:8899")
522
+ >>> solana_client.get_largest_accounts().value[0].lamports # doctest: +SKIP
523
+ 500000000000000000
524
+ """
525
+ body = json.loads(str(self._get_largest_accounts_body(filter_opt, commitment)))
526
+ return body
527
+
528
+ def get_leader_schedule(
529
+ self, epoch: Optional[int] = None, commitment: Optional[Commitment] = "finalized"
530
+ ) -> GetLeaderScheduleResp:
531
+ """Returns the leader schedule for an epoch.
532
+
533
+ Args:
534
+ epoch: Fetch the leader schedule for the epoch that corresponds to the provided slot.
535
+ If unspecified, the leader schedule for the current epoch is fetched.
536
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
537
+
538
+ Example:
539
+ >>> solana_client = Client("http://localhost:8899")
540
+ >>> list(solana_client.get_leader_schedule().value.items([0] # doctest: +SKIP
541
+ (Pubkey(
542
+ HMU77m6WSL9Xew9YvVCgz1hLuhzamz74eD9avi4XPdr,
543
+ ))), [346448, 346449, 346450, 346451, 369140, 369141, 369142, 369143, 384204, 384205, 384206, 384207])
544
+ """
545
+ body = json.loads(str(self._get_leader_schedule_body(epoch, commitment)))
546
+ return body
547
+
548
+ def get_minimum_balance_for_rent_exemption(
549
+ self, usize: int, commitment: Optional[Commitment] = "finalized"
550
+ ) -> GetMinimumBalanceForRentExemptionResp:
551
+ """Returns minimum balance required to make account rent exempt.
552
+
553
+ Args:
554
+ usize: Account data length.
555
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
556
+
557
+ Example:
558
+ >>> solana_client = Client("http://localhost:8899")
559
+ >>> solana_client.get_minimum_balance_for_rent_exemption(50).value # doctest: +SKIP
560
+ 1238880
561
+ """
562
+ body = json.loads(str(self._get_minimum_balance_for_rent_exemption_body(usize, commitment)))
563
+ return body
564
+
565
+ def get_multiple_accounts(
566
+ self,
567
+ pubkeys: List[Pubkey],
568
+ commitment: Optional[Commitment] = "confirmed",
569
+ encoding: str = "base64",
570
+ data_slice: Optional[types.DataSliceOpts] = None,
571
+ ) -> GetMultipleAccountsResp:
572
+ """Returns all the account info for a list of public keys.
573
+
574
+ Args:
575
+ pubkeys: list of Pubkeys to query
576
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
577
+ encoding: (optional) Encoding for Account data, either "base58" (slow) or "base64". Default is "base64".
578
+
579
+ - "base58" is limited to Account data of less than 128 bytes.
580
+ - "base64" will return body
581
+ data_slice: (optional) Option to limit the returned account data using the provided `offset`: <usize> and
582
+ `length`: <usize> fields; only available for "base58" or "base64" encoding.
583
+
584
+ Example:
585
+ >>> from solders.pubkey import Pubkey
586
+ >>> solana_client = Client("http://localhost:8899")
587
+ >>> pubkeys = [Pubkey.from_string("6ZWcsUiWJ63awprYmbZgBQSreqYZ4s6opowP4b7boUdh"), Pubkey.from_string("HkcE9sqQAnjJtECiFsqGMNmUho3ptXkapUPAqgZQbBSY")]
588
+ >>> solana_client.get_multiple_accounts(pubkeys).value[0].lamports # doctest: +SKIP
589
+ 1
590
+ """ # noqa: E501 # pylint: disable=line-too-long
591
+ body = json.loads(str(self._get_multiple_accounts_body(
592
+ pubkeys=[get_pubkey(pub) for pub in pubkeys],
593
+ commitment=commitment,
594
+ encoding=encoding,
595
+ data_slice=data_slice,
596
+ )))
597
+ return body
598
+
599
+ def get_multiple_accounts_json_parsed(
600
+ self,
601
+ pubkeys: List[Pubkey],
602
+ commitment: Optional[Commitment] = "confirmed",
603
+ ) -> GetMultipleAccountsMaybeJsonParsedResp:
604
+ """Returns all the account info for a list of public keys, in jsonParsed format if possible.
605
+
606
+ If a parser cannot be found, the RPC server falls back to base64 encoding,
607
+
608
+ Args:
609
+ pubkeys: list of Pubkeys to query
610
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
611
+
612
+ Example:
613
+ >>> from solders.pubkey import Pubkey
614
+ >>> solana_client = Client("http://localhost:8899")
615
+ >>> pubkeys = [Pubkey.from_string("6ZWcsUiWJ63awprYmbZgBQSreqYZ4s6opowP4b7boUdh"), Pubkey.from_string("HkcE9sqQAnjJtECiFsqGMNmUho3ptXkapUPAqgZQbBSY")]
616
+ >>> solana_client.get_multiple_accounts_json_parsed(pubkeys).value[0].lamports # doctest: +SKIP
617
+ 1
618
+ """ # noqa: E501 # pylint: disable=line-too-long
619
+ body = json.loads(str(self._get_multiple_accounts_body(
620
+ pubkeys=[get_pubkey(pub) for pub in pubkeys],
621
+ commitment=commitment,
622
+ encoding="jsonParsed",
623
+ data_slice=None,
624
+ )))
625
+ return body
626
+
627
+ def get_program_accounts( # pylint: disable=too-many-arguments
628
+ self,
629
+ pubkey: Pubkey,
630
+ commitment: Optional[Commitment] = "confirmed",
631
+ encoding: str = "base64",
632
+ data_slice: Optional[types.DataSliceOpts] = None,
633
+ filters: Optional[Sequence[Union[int, types.MemcmpOpts]]] = None,
634
+ ) -> GetProgramAccountsResp:
635
+ """Returns all accounts owned by the provided program Pubkey.
636
+
637
+ Args:
638
+ pubkey: Pubkey of program
639
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
640
+ encoding: (optional) Encoding for the returned Transaction, either "base58" (slow) or "base64".
641
+ data_slice: (optional) Limit the returned account data using the provided `offset`: <usize> and
642
+ ` length`: <usize> fields; only available for "base58" or "base64" encoding.
643
+ filters: (optional) Options to compare a provided series of bytes with program account data at a particular offset.
644
+ Note: an int entry is converted to a `dataSize` filter.
645
+
646
+ Example:
647
+ >>> from solana.rpc.types import MemcmpOpts
648
+ >>> from typing import List, Union
649
+ >>> solana_client = Client("http://localhost:8899")
650
+ >>> memcmp_opts = MemcmpOpts(offset=4, bytes="3Mc6vR")
651
+ >>> pubkey = Pubkey.from_string("4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T")
652
+ >>> filters: List[Union[int, MemcmpOpts]] = [17, memcmp_opts]
653
+ >>> solana_client.get_program_accounts(pubkey, filters=filters).value[0].account.lamports # doctest: +SKIP
654
+ 1
655
+ """ # noqa: E501 # pylint: disable=line-too-long
656
+ body = json.loads(str(self._get_program_accounts_body(
657
+ pubkey=get_pubkey(pubkey),
658
+ commitment=commitment,
659
+ encoding=encoding,
660
+ data_slice=data_slice,
661
+ filters=filters,
662
+ )))
663
+ return body
664
+
665
+ def get_program_accounts_json_parsed( # pylint: disable=too-many-arguments
666
+ self,
667
+ pubkey: Pubkey,
668
+ commitment: Optional[Commitment] = "confirmed",
669
+ filters: Optional[Sequence[Union[int, types.MemcmpOpts]]] = None,
670
+ ) -> GetProgramAccountsMaybeJsonParsedResp:
671
+ """Returns all accounts owned by the provided program Pubkey.
672
+
673
+ Args:
674
+ pubkey: Pubkey of program
675
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
676
+ filters: (optional) Options to compare a provided series of bytes with program account data at a particular offset.
677
+ Note: an int entry is converted to a `dataSize` filter.
678
+
679
+ Example:
680
+ >>> from solana.rpc.types import MemcmpOpts
681
+ >>> from typing import List, Union
682
+ >>> solana_client = Client("http://localhost:8899")
683
+ >>> memcmp_opts = MemcmpOpts(offset=4, bytes="3Mc6vR")
684
+ >>> pubkey = Pubkey.from_string("4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T")
685
+ >>> filters: List[Union[int, MemcmpOpts]] = [17, memcmp_opts]
686
+ >>> solana_client.get_program_accounts(pubkey, filters=filters).value[0].account.lamports # doctest: +SKIP
687
+ 1
688
+ """ # noqa: E501 # pylint: disable=line-too-long
689
+ body = json.loads(str(self._get_program_accounts_body(
690
+ pubkey=get_pubkey(pubkey),
691
+ commitment=commitment,
692
+ encoding="jsonParsed",
693
+ data_slice=None,
694
+ filters=filters,
695
+ )))
696
+ return body
697
+
698
+ def get_latest_blockhash(self, commitment: Optional[Commitment] = "finalized") -> GetLatestBlockhashResp:
699
+ """Returns the latest block hash from the ledger.
700
+
701
+ Response also includes the last valid block height.
702
+
703
+ Args:
704
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
705
+
706
+ Example:
707
+ >>> solana_client = Client("http://localhost:8899")
708
+ >>> solana_client.get_latest_blockhash().value # doctest: +SKIP
709
+ RpcBlockhash {
710
+ blockhash: Hash(
711
+ 4TLzN2RAACFnd5TYpHcUi76pC3V1qkggRF29HWk2VLeT,
712
+ ))),
713
+ last_valid_block_height: 158286487,
714
+ }
715
+ """
716
+ body = json.loads(str(self._get_latest_blockhash_body(commitment)))
717
+ return body
718
+
719
+ def get_signature_statuses(
720
+ self, signatures: List[Signature], search_transaction_history: bool = False
721
+ ) -> GetSignatureStatusesResp:
722
+ """Returns the statuses of a list of signatures.
723
+
724
+ Unless the `search_transaction_history` configuration parameter is included, this method only
725
+ searches the recent status cache of signatures, which retains statuses for all active slots plus
726
+ `MAX_RECENT_BLOCKHASHES` rooted slots.
727
+
728
+ Args:
729
+ signatures: An array of transaction signatures to confirm.
730
+ search_transaction_history: If true, a Solana node will search its ledger cache for
731
+ any signatures not found in the recent status cache.
732
+
733
+ Example:
734
+ >>> solana_client = Client("http://localhost:8899")
735
+ >>> raw_sigs = [
736
+ ... "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW",
737
+ ... "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7"]
738
+ >>> sigs = [Signature.from_string(sig) for sig in raw_sigs]
739
+ >>> solana_client.get_signature_statuses(sigs).value[0].confirmations # doctest: +SKIP
740
+ 10
741
+ """
742
+ body = json.loads(str(self._get_signature_statuses_body([get_sigkey(sig) for sig in signatures], search_transaction_history)))
743
+ return body
744
+
745
+ def get_slot(self, commitment: Optional[Commitment] = "finalized") -> GetSlotResp:
746
+ """Returns the current slot the node is processing.
747
+
748
+ Args:
749
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
750
+
751
+ Example:
752
+ >>> solana_client = Client("http://localhost:8899")
753
+ >>> solana_client.get_slot().value # doctest: +SKIP
754
+ 7515
755
+ """
756
+ body = json.loads(str(self._get_slot_body(commitment)))
757
+ return body
758
+
759
+ def get_slot_leader(self, commitment: Optional[Commitment] = "finalized") -> GetSlotLeaderResp:
760
+ """Returns the current slot leader.
761
+
762
+ Args:
763
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
764
+
765
+ Example:
766
+ >>> solana_client = Client("http://localhost:8899")
767
+ >>> solana_client.get_slot_leader().value # doctest: +SKIP
768
+ Pubkey(
769
+ dv2eQHeP4RFrJZ6UeiZWoc3XTtmtZCUKxxCApCDcRNV,
770
+ )))
771
+ """
772
+ body = json.loads(str(self._get_slot_leader_body(commitment)))
773
+ return body
774
+
775
+ def get_stake_activation(
776
+ self,
777
+ pubkey: Pubkey,
778
+ epoch: Optional[int] = None,
779
+ commitment: Optional[Commitment] = "confirmed",
780
+ ) -> GetStakeActivationResp:
781
+ """Returns epoch activation information for a stake account.
782
+
783
+ Args:
784
+ pubkey: Pubkey of stake account to query
785
+ epoch: (optional) Epoch for which to calculate activation details. If parameter not provided,
786
+ defaults to current epoch.
787
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
788
+
789
+ Example:
790
+ >>> solana_client = Client("http://localhost:8899")
791
+ >>> solana_client.get_stake_activation().value.active # doctest: +SKIP
792
+ 124429280
793
+ """
794
+ body = json.loads(str(self._get_stake_activation_body(get_pubkey(pubkey), epoch, commitment)))
795
+ return body
796
+
797
+ def get_supply(self, commitment: Optional[Commitment] = "finalized") -> GetSupplyResp:
798
+ """Returns information about the current supply.
799
+
800
+ Args:
801
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
802
+
803
+ Example:
804
+ >>> solana_client = Client("http://localhost:8899")
805
+ >>> solana_client.get_supply().value.circulating # doctest: +SKIP
806
+ 683635192454157660
807
+ """
808
+ body = json.loads(str(self._get_supply_body(commitment)))
809
+ return body
810
+
811
+ def get_token_account_balance(
812
+ self, pubkey: Pubkey, commitment: Optional[Commitment] = "finalized"
813
+ ) -> GetTokenAccountBalanceResp:
814
+ """Returns the token balance of an SPL Token account (UNSTABLE).
815
+
816
+ Args:
817
+ pubkey: Pubkey of Token account to query
818
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
819
+
820
+ Example:
821
+ >>> solana_client = Client("http://localhost:8899")
822
+ >>> pubkey = Pubkey.from_string("7fUAJdStEuGbc3sM84cKRL6yYaaSstyLSU4ve5oovLS7")
823
+ >>> solana_client.get_token_account_balance(pubkey).value.amount # noqa: E501 # doctest: +SKIP
824
+ '9864'
825
+ """
826
+ body = json.loads(str(self._get_token_account_balance_body(pubkey, commitment)))
827
+ return body
828
+
829
+ def get_token_accounts_by_delegate(
830
+ self,
831
+ delegate: Pubkey,
832
+ opts: types.TokenAccountOpts,
833
+ commitment: Optional[Commitment] = "confirmed",
834
+ ) -> GetTokenAccountsByDelegateResp:
835
+ """Returns all SPL Token accounts by approved Delegate (UNSTABLE).
836
+
837
+ Args:
838
+ delegate: Public key of the delegate owner to query.
839
+ opts: Token account option specifying at least one of `mint` or `program_id`.
840
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
841
+ """
842
+ body = json.loads(str(self._get_token_accounts_by_delegate_body(get_pubkey(delegate), opts, commitment)))
843
+ return body
844
+
845
+ def get_token_accounts_by_delegate_json_parsed(
846
+ self,
847
+ delegate: Pubkey,
848
+ opts: types.TokenAccountOpts,
849
+ commitment: Optional[Commitment] = "confirmed",
850
+ ) -> GetTokenAccountsByDelegateJsonParsedResp:
851
+ """Returns all SPL Token accounts by approved delegate in JSON format (UNSTABLE).
852
+
853
+ Args:
854
+ delegate: Public key of the delegate owner to query.
855
+ opts: Token account option specifying at least one of `mint` or `program_id`.
856
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
857
+ """
858
+ body = json.loads(str(self._get_token_accounts_by_delegate_json_parsed_body(get_pubkey(delegate), opts, commitment)))
859
+ return body
860
+
861
+ def get_token_accounts_by_owner(
862
+ self,
863
+ owner: Pubkey,
864
+ opts: types.TokenAccountOpts,
865
+ commitment: Optional[Commitment] = "confirmed",
866
+ ) -> GetTokenAccountsByOwnerResp:
867
+ """Returns all SPL Token accounts by token owner (UNSTABLE).
868
+
869
+ Args:
870
+ owner: Public key of the account owner to query.
871
+ opts: Token account option specifying at least one of `mint` or `program_id`.
872
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
873
+ """
874
+ body = json.loads(str(self._get_token_accounts_by_owner_body(get_pubkey(owner), opts, commitment)))
875
+ return body
876
+
877
+ def get_token_accounts_by_owner_json_parsed(
878
+ self,
879
+ owner: Pubkey,
880
+ opts: types.TokenAccountOpts,
881
+ commitment: Optional[Commitment] = "confirmed",
882
+ ) -> GetTokenAccountsByOwnerJsonParsedResp:
883
+ """Returns all SPL Token accounts by token owner in JSON format (UNSTABLE).
884
+
885
+ Args:
886
+ owner: Public key of the account owner to query.
887
+ opts: Token account option specifying at least one of `mint` or `program_id`.
888
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
889
+ """
890
+ body = json.loads(str(self._get_token_accounts_by_owner_json_parsed_body(get_pubkey(owner), opts, commitment)))
891
+ return body
892
+
893
+ def get_token_largest_accounts(
894
+ self, pubkey: Pubkey, commitment: Optional[Commitment] = "finalized"
895
+ ) -> GetTokenLargestAccountsResp:
896
+ """Returns the 20 largest accounts of a particular SPL Token type."""
897
+ body = json.loads(str(self._get_token_largest_accounts_body(get_pubkey(pubkey), commitment)))
898
+ return body
899
+
900
+ def get_token_supply(self, pubkey: Pubkey, commitment: Optional[Commitment] = "finalized") -> GetTokenSupplyResp:
901
+ """Returns the total supply of an SPL Token type."""
902
+ body = json.loads(str(self._get_token_supply_body(get_pubkey(pubkey), commitment)))
903
+ return body
904
+
905
+ def get_transaction_count(self, commitment: Optional[Commitment] = "finalized") -> GetTransactionCountResp:
906
+ """Returns the current Transaction count from the ledger.
907
+
908
+ Args:
909
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
910
+
911
+ Example:
912
+ >>> solana_client = Client("http://localhost:8899")
913
+ >>> solana_client.get_transaction_count().value # doctest: +SKIP
914
+ 4554
915
+ """
916
+ body = json.loads(str(self._get_transaction_count_body(commitment)))
917
+ return body
918
+
919
+ def get_minimum_ledger_slot(self) -> MinimumLedgerSlotResp:
920
+ """Returns the lowest slot that the node has information about in its ledger.
921
+
922
+ This value may increase over time if the node is configured to purge older ledger data.
923
+
924
+ Example:
925
+ >>> solana_client = Client("http://localhost:8899")
926
+ >>> solana_client.get_minimum_ledger_slot().value # doctest: +SKIP
927
+ 1234
928
+ """
929
+ return body
930
+
931
+ def get_version(self) -> GetVersionResp:
932
+ """Returns the current solana versions running on the node.
933
+
934
+ Example:
935
+ >>> solana_client = Client("http://localhost:8899")
936
+ >>> solana_client.get_version().value.solana_core # doctest: +SKIP
937
+ '1.13.2'
938
+ """
939
+ return body
940
+
941
+ def get_vote_accounts(self, commitment: Optional[Commitment] = "finalized") -> GetVoteAccountsResp:
942
+ """Returns the account info and associated stake for all the voting accounts in the current bank.
943
+
944
+ Args:
945
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
946
+
947
+ Example:
948
+ >>> solana_client = Client("http://localhost:8899")
949
+ >>> solana_client.get_vote_accounts().value.current[0].commission # doctest: +SKIP
950
+ 100
951
+ """
952
+ body = json.loads(str(self._get_vote_accounts_body(commitment)))
953
+ return body
954
+
955
+ def request_airdrop(
956
+ self, pubkey: Pubkey, lamports: int, commitment: Optional[Commitment] = "finalized"
957
+ ) -> RequestAirdropResp:
958
+ """Requests an airdrop of lamports to a Pubkey.
959
+
960
+ Args:
961
+ pubkey: Pubkey of account to receive lamports, as base-58 encoded string or public key object.
962
+ lamports: Amout of lamports.
963
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
964
+
965
+ Example:
966
+ >>> from solders.pubkey import Pubkey
967
+ >>> solana_client = Client("http://localhost:8899")
968
+ >>> solana_client.request_airdrop(Pubkey([0] * 31 + [1]), 10000).value # doctest: +SKIP
969
+ Signature(
970
+ 1111111111111111111111111111111111111111111111111111111111111111,
971
+ )))
972
+ """
973
+ body = json.loads(str(self._request_airdrop_body(get_pubkey(pubkey), lamports, commitment)))
974
+ return body
975
+
976
+ def send_raw_transaction(self, txn: bytes, opts: Optional[types.TxOpts] = None) -> SendTransactionResp:
977
+ """Send a transaction that has already been signed and serialized into the wire format.
978
+
979
+ Args:
980
+ txn: Transaction bytes.
981
+ opts: (optional) Transaction options.
982
+
983
+ Before submitting, the following preflight checks are performed (unless disabled with the `skip_preflight` option):
984
+
985
+ - The transaction signatures are verified.
986
+
987
+ - The transaction is simulated against the latest max confirmed bank and on failure an error
988
+ will be returned. Preflight checks may be disabled if desired.
989
+
990
+ Example:
991
+ >>> solana_client = Client("http://localhost:8899")
992
+ >>> full_signed_tx_hex = (
993
+ ... '01b3795ccfaac3eee838bb05c3b8284122c18acedcd645c914fe8e178c3b62640d8616d061cc818b26cab8ecf3855ecc'
994
+ ... '72fa113f731ecbd0215e88edc0309d6f0a010001031398f62c6d1a457c51ba6a4b5f3dbd2f69fca93216218dc8997e41'
995
+ ... '6bd17d93ca68ab4677ffb1f2894dd0a6153c231d45ec436ae53ae60149dbe15f32e4b8703f0000000000000000000000'
996
+ ... '000000000000000000000000000000000000000000839618f701ba7e9ba27ae59825dd6d6bb66d14f6d5d0eae215161d7'
997
+ ... '1851a106901020200010c0200000040420f0000000000'
998
+ ... )
999
+ >>> solana_client.send_raw_transaction(bytes.fromhex(full_signed_tx_hex)).value # doctest: +SKIP
1000
+ Signature(
1001
+ 1111111111111111111111111111111111111111111111111111111111111111,
1002
+ )))
1003
+ """ # noqa: E501 # pylint: disable=line-too-long
1004
+ opts_to_use = types.TxOpts(preflight_commitment=self._commitment) if opts is None else opts
1005
+ body = json.loads(str(self._send_raw_transaction_body(txn, opts_to_use)))
1006
+ resp = self._provider.make_request(body, SendTransactionResp)
1007
+ if opts_to_use.skip_confirmation:
1008
+ return body
1009
+ post_send_args = self._send_raw_transaction_post_send_args(resp, opts_to_use)
1010
+ return body
1011
+
1012
+ def send_transaction(
1013
+ self,
1014
+ txn: Union[VersionedTransaction, Transaction],
1015
+ *signers: Keypair,
1016
+ opts: Optional[types.TxOpts] = None,
1017
+ recent_blockhash: Optional[Blockhash] = None,
1018
+ ) -> SendTransactionResp:
1019
+ """Send a transaction.
1020
+
1021
+ Args:
1022
+ txn: transaction object.
1023
+ signers: Signers to sign the transaction. Only supported for legacy Transaction.
1024
+ opts: (optional) Transaction options.
1025
+ recent_blockhash: (optional) Pass a valid recent blockhash here if you want to
1026
+ skip fetching the recent blockhash or relying on the cache.
1027
+ Only supported for legacy Transaction.
1028
+
1029
+ Example:
1030
+ >>> from solders.keypair import Keypair
1031
+ >>> from solders.pubkey import Pubkey
1032
+ >>> from solana.rpc.api import Client
1033
+ >>> from solders.system_program import TransferParams, transfer
1034
+ >>> from solana.transaction import Transaction
1035
+ >>> leading_zeros = [0] * 31
1036
+ >>> sender, receiver = Keypair.from_seed(leading_zeros + [1]), Keypair.from_seed(leading_zeros + [2])
1037
+ >>> txn = Transaction().add(transfer(TransferParams(
1038
+ ... from_pubkey=sender.pubkey(), to_pubkey=receiver.pubkey(), lamports=1000)))
1039
+ >>> solana_client = Client("http://localhost:8899")
1040
+ >>> solana_client.send_transaction(txn, sender).value # doctest: +SKIP
1041
+ Signature(
1042
+ 1111111111111111111111111111111111111111111111111111111111111111,
1043
+ )))
1044
+ """
1045
+ if isinstance(txn, VersionedTransaction):
1046
+ if signers:
1047
+ msg = "*signers args are not used when sending VersionedTransaction."
1048
+ raise ValueError(msg)
1049
+ if recent_blockhash is not None:
1050
+ msg = "recent_blockhash arg is not used when sending VersionedTransaction."
1051
+ raise ValueError(msg)
1052
+ versioned_tx_opts = types.TxOpts(preflight_commitment=self._commitment) if opts is None else opts
1053
+ return body
1054
+ last_valid_block_height = None
1055
+ if recent_blockhash is None:
1056
+ blockhash_resp = self.get_latest_blockhash(Finalized)
1057
+ recent_blockhash = self.parse_recent_blockhash(blockhash_resp)
1058
+ last_valid_block_height = blockhash_resp.value.last_valid_block_height
1059
+
1060
+ txn.recent_blockhash = recent_blockhash
1061
+
1062
+ txn.sign(*signers)
1063
+ opts_to_use = (
1064
+ types.TxOpts(
1065
+ preflight_commitment=self._commitment,
1066
+ last_valid_block_height=last_valid_block_height,
1067
+ )
1068
+ if opts is None
1069
+ else opts
1070
+ )
1071
+ txn_resp = self.send_raw_transaction(txn.serialize(), opts=opts_to_use)
1072
+ return body
1073
+
1074
+ def simulate_transaction(
1075
+ self,
1076
+ txn: Union[Transaction, VersionedTransaction],
1077
+ sig_verify: bool = False,
1078
+ commitment: Optional[Commitment] = "confirmed",
1079
+ ) -> SimulateTransactionResp:
1080
+ """Simulate sending a transaction.
1081
+
1082
+ Args:
1083
+ txn: A transaction object.
1084
+ The transaction must have a valid blockhash, but is not required to be signed.
1085
+ sig_verify: If true the transaction signatures will be verified (default: false).
1086
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
1087
+
1088
+ Example:
1089
+ >>> solana_client = Client("http://localhost:8899")
1090
+ >>> full_signed_tx_hex = (
1091
+ ... '01b3795ccfaac3eee838bb05c3b8284122c18acedcd645c914fe8e178c3b62640d8616d061cc818b26cab8ecf3855ecc'
1092
+ ... '72fa113f731ecbd0215e88edc0309d6f0a010001031398f62c6d1a457c51ba6a4b5f3dbd2f69fca93216218dc8997e41'
1093
+ ... '6bd17d93ca68ab4677ffb1f2894dd0a6153c231d45ec436ae53ae60149dbe15f32e4b8703f0000000000000000000000'
1094
+ ... '000000000000000000000000000000000000000000839618f701ba7e9ba27ae59825dd6d6bb66d14f6d5d0eae215161d7'
1095
+ ... '1851a106901020200010c0200000040420f0000000000'
1096
+ ... )
1097
+ >>> tx = Transaction.deserialize(bytes.fromhex(full_signed_tx_hex))
1098
+ >>> solana_client.simulate_transaction(tx).value.logs # doctest: +SKIP
1099
+ ['BPF program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success']
1100
+ """
1101
+ body = json.loads(str(self._simulate_transaction_body(txn, sig_verify, commitment)))
1102
+ return body
1103
+
1104
+ def validator_exit(self) -> ValidatorExitResp:
1105
+ """Request to have the validator exit.
1106
+
1107
+ Validator must have booted with RPC exit enabled (`--enable-rpc-exit` parameter).
1108
+
1109
+ Example:
1110
+ >>> solana_client = Client("http://localhost:8899")
1111
+ >>> solana_client.validator_exit().value # doctest: +SKIP
1112
+ True
1113
+ """
1114
+ return body
1115
+
1116
+ def __post_send_with_confirm(
1117
+ self,
1118
+ resp: SendTransactionResp,
1119
+ conf_comm: Commitment,
1120
+ last_valid_block_height: Optional[int],
1121
+ ) -> SendTransactionResp:
1122
+ resp = self._post_send(resp)
1123
+ sig = resp.value
1124
+ self._provider.logger.info("Transaction sent to %s. Signature %s: ", self._provider.endpoint_uri, sig)
1125
+ self.confirm_transaction(sig, conf_comm, last_valid_block_height=last_valid_block_height)
1126
+ return body
1127
+
1128
+ def confirm_transaction(
1129
+ self,
1130
+ tx_sig: Signature,
1131
+ commitment: Optional[Commitment] = "confirmed",
1132
+ sleep_seconds: float = 0.5,
1133
+ last_valid_block_height: Optional[int] = None,
1134
+ ) -> GetSignatureStatusesResp:
1135
+ """Confirm the transaction identified by the specified signature.
1136
+
1137
+ Args:
1138
+ tx_sig: the transaction signature to confirm.
1139
+ commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
1140
+ sleep_seconds: The number of seconds to sleep when polling the signature status.
1141
+ last_valid_block_height: The block height by which the transaction would become invalid.
1142
+ """
1143
+ timeout = time() + 90
1144
+ commitment_to_use = _COMMITMENT_TO_SOLDERS[commitment or self._commitment]
1145
+ commitment_rank = int(commitment_to_use)
1146
+ if last_valid_block_height:
1147
+ current_blockheight = (self.get_block_height(commitment)).value
1148
+ while current_blockheight <= last_valid_block_height:
1149
+ resp = self.get_signature_statuses([tx_sig])
1150
+ if isinstance(resp, RPCError.__args__): # type: ignore
1151
+ raise RPCException(resp)
1152
+ resp_value = resp.value[0]
1153
+ if resp_value is not None:
1154
+ confirmation_status = resp_value.confirmation_status
1155
+ if confirmation_status is not None:
1156
+ confirmation_rank = int(confirmation_status)
1157
+ if confirmation_rank >= commitment_rank:
1158
+ break
1159
+ current_blockheight = (self.get_block_height(commitment)).value
1160
+ sleep(sleep_seconds)
1161
+ else:
1162
+ if isinstance(resp, RPCError.__args__): # type: ignore
1163
+ raise RPCException(resp)
1164
+ raise TransactionExpiredBlockheightExceededError(f"{tx_sig} has expired: block height exceeded")
1165
+ return body
1166
+ else:
1167
+ while time() < timeout:
1168
+ resp = self.get_signature_statuses([tx_sig])
1169
+ resp_value = resp.value[0]
1170
+ if resp_value is not None:
1171
+ confirmation_status = resp_value.confirmation_status
1172
+ if confirmation_status is not None:
1173
+ confirmation_rank = int(confirmation_status)
1174
+ if confirmation_rank >= commitment_rank:
1175
+ break
1176
+ sleep(sleep_seconds)
1177
+ else:
1178
+ raise UnconfirmedTxError(f"Unable to confirm transaction {tx_sig}")
1179
+ return body