abstract-solana 0.0.0.1__tar.gz

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,26 @@
1
+ Metadata-Version: 2.1
2
+ Name: abstract_solana
3
+ Version: 0.0.0.1
4
+ Home-page: https://github.com/AbstractEndeavors/abstract_solana
5
+ Author: putkoff
6
+ Author-email: partners@abstractendeavors.com
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Topic :: Software Development :: Libraries
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.6
13
+ Classifier: Programming Language :: Python :: 3.7
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.6
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: solders
22
+ Requires-Dist: abstract_utilities
23
+
24
+ ## Abstract Solana
25
+
26
+
@@ -0,0 +1,3 @@
1
+ ## Abstract Solana
2
+
3
+
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,34 @@
1
+ from time import time
2
+ import setuptools
3
+ with open("README.md", "r", encoding="utf-8") as fh:
4
+ long_description = fh.read()
5
+ setuptools.setup(
6
+ name='abstract_solana',
7
+ version='0.0.0.01',
8
+ author='putkoff',
9
+ author_email='partners@abstractendeavors.com',
10
+ description="",
11
+ long_description=long_description,
12
+ long_description_content_type='text/markdown',
13
+ url='https://github.com/AbstractEndeavors/abstract_solana',
14
+ classifiers=[
15
+ 'Development Status :: 3 - Alpha',
16
+ 'Intended Audience :: Developers',
17
+ 'Topic :: Software Development :: Libraries',
18
+ 'License :: OSI Approved :: MIT License',
19
+ 'Programming Language :: Python :: 3',
20
+ 'Programming Language :: Python :: 3.6',
21
+ 'Programming Language :: Python :: 3.7',
22
+ 'Programming Language :: Python :: 3.8',
23
+ 'Programming Language :: Python :: 3.9',
24
+ 'Programming Language :: Python :: 3.10',
25
+ 'Programming Language :: Python :: 3.11',
26
+ 'Programming Language :: Python :: 3.12',
27
+ ],
28
+ install_requires=['solders','abstract_utilities'],
29
+ package_dir={"": "src"},
30
+ packages=setuptools.find_packages(where="src"),
31
+ python_requires=">=3.6",
32
+ # Add this line to include wheel format in your distribution
33
+ setup_requires=['wheel'],
34
+ )
@@ -0,0 +1,8 @@
1
+ from .account_key_utils import *
2
+ from .genesis_functions import *
3
+ from .index_utils import *
4
+ from .price_utils import *
5
+ from .pubkey_utils import *
6
+ from .signature_data_parse import *
7
+ from .utils import *
8
+ from .log_message_functions import *
@@ -0,0 +1,20 @@
1
+ from .signature_data_parse import get_account_keys_from_txn,get_read_only_addresses_from_txn,get_writable_addresses_from_txn
2
+ from .pubkey_utils import get_pubkey
3
+ from abstract_utilities import is_number
4
+
5
+ def get_all_account_keys(txnData):
6
+ accountKeys=[]
7
+ accountKeys += get_account_keys_from_txn(txnData)
8
+ accountKeys += get_read_only_addresses_from_txn(txnData)
9
+ accountKeys += get_writable_addresses_from_txn(txnData)
10
+ return accountKeys
11
+
12
+ def get_account_key(index,txnData):
13
+ accountKeys = get_all_account_keys(txnData)
14
+ if index is not None and accountKeys is not None and is_number(index) and len(accountKeys)>int(index):
15
+ return accountKeys[int(index)]
16
+
17
+ def get_account_index(accountIndex,txnData):
18
+ for i,account in enumerate(get_all_account_keys(txnData)):
19
+ if get_pubkey(str(account)) == get_pubkey(str(accountIndex)):
20
+ return i
@@ -0,0 +1,14 @@
1
+ from .signature_data_parse import get_error_message_from_txn,get_block_time_from_txn
2
+ def get_errorless_txn_from_signature_array(signatureArray):
3
+ return [sig for sig in signatureArray if get_error_message_from_txn(sig) == None]
4
+ def return_oldest_from_signature_array(signatureArray,errorless=False):
5
+ if errorless:
6
+ signatureArray = get_errorless_txn_from_signature_array(signatureArray)
7
+ if signatureArray and isinstance(signatureArray,list):
8
+ if get_block_time_from_txn(signatureArray[0])<get_block_time_from_txn(signatureArray[-1]):
9
+ return signatureArray[0].get('signature')
10
+ return signatureArray[-1].get('signature')
11
+ def return_oldest_last_and_original_length_from_signature_array(signatureArray):
12
+ return {"oldest":return_oldest_from_signature_array(signatureArray),
13
+ "oldestValid":return_oldest_from_signature_array(signatureArray,errorless=True),
14
+ "length":len(signatureArray)}
@@ -0,0 +1,43 @@
1
+ from typing import List, Dict, Any, Optional, Union
2
+ from .pubkey_utils import try_pubkey
3
+ from .account_key_utils import get_all_account_keys
4
+
5
+ def search_for_index(data,index_number,key):
6
+ for index_data in data:
7
+ if str(index_data.get(key)) == str(index_number):
8
+ return index_data
9
+
10
+ def search_for_account_index(data,index_number):
11
+ return search_for_index(data,index_number,'accountIndex')
12
+
13
+ def find_log_entry(needle: str, log_entries: List[str]) -> Optional[str]:
14
+ for log_entry in log_entries:
15
+ if needle in log_entry:
16
+ return log_entry
17
+ return None
18
+
19
+ def extract_lp_initialization_log_entry_info_from_log_entry(lp_log_entry: str) -> Dict[str, Union[int, float]]:
20
+ lp_initialization_log_entry_info_start = lp_log_entry.find('{')
21
+ return json.loads(fix_relaxed_json_in_lp_log_entry(lp_log_entry[lp_initialization_log_entry_info_start:]))
22
+
23
+ def fix_relaxed_json_in_lp_log_entry(relaxed_json: str) -> str:
24
+ return relaxed_json.replace(r'([{,])\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:', r'\1"\2":')
25
+
26
+ def get_associations(event, txnData):
27
+ accountKeys = get_all_account_keys(txnData)
28
+ key_properties = {'associatedAccounts': ['accountIndex', 'accounts'], 'programId': ['programIdIndex']}
29
+ new_accounts = {k: None for k in key_properties}
30
+ for key, values in key_properties.items():
31
+ for value in values:
32
+ subjects = event.get(value)
33
+ if value in event and subjects is not None:
34
+ subjects = event.get(value)
35
+ if isinstance(subjects, list):
36
+ event[key] = [convert_subject(sub, accountKeys) for sub in subjects]
37
+ else:
38
+ event[key] = convert_subject(subjects, accountKeys)
39
+
40
+ return event
41
+
42
+ def convert_subject(sub, accountKeys):
43
+ return sub if try_pubkey(sub) else accountKeys[int(sub)]
@@ -0,0 +1,89 @@
1
+ from abstract_utilities import make_list
2
+ import json,pprint
3
+ from .signature_data_parse import get_log_messages_from_txn,get_instructions_from_txn,get_inner_instructions_from_txn
4
+ from .account_key_utils import get_all_account_keys
5
+ def ifListGetSection(list_obj,i=0):
6
+ if list_obj and isinstance(list_obj,list) and len(list_obj)>i:
7
+ list_obj = list_obj[i]
8
+ return list_obj
9
+ def get_logs_from_index(txnData,index=None):
10
+ if index is not None:
11
+ allLogs = get_log_messages_from_txn(txnData)
12
+ endLog = get_end_log_index(txnData,index)
13
+ return allLogs[index:endLog]
14
+ def get_program_ids(txnData):
15
+ allLogs = get_log_messages_from_txn(txnData)
16
+ return [log.split(' ')[1] for log in allLogs if 'invoke' in log]
17
+ def get_program_id_from_log(logs):
18
+ for log in make_list(logs):
19
+ if 'invoke' in log.lower():
20
+ return log.split(' ')[1]
21
+ def get_stack_height_from_logs(logs):
22
+ for log in make_list(logs):
23
+ if 'invoke' in log.lower():
24
+ return int(log.split(' ')[-1][1:-1])
25
+ def get_end_log_index(txnData,index):
26
+ allLogs = get_log_messages_from_txn(txnData)
27
+ i=0
28
+ for i,log in enumerate(allLogs[index+1:]):
29
+ if 'invoke' in log.lower():
30
+ return index+1+i
31
+ return len(allLogs)
32
+ def get_for_program_ids_info(txnData):
33
+ allLogs = get_log_messages_from_txn(txnData)
34
+ return [{"programId":get_program_id_from_log(allLogs[i]),
35
+ "start":i,
36
+ "end":get_end_log_index(txnData,i),
37
+ 'stackHeight':get_stack_height_from_logs(allLogs[i]),
38
+ 'events':[event.split(':')[0] for event in get_log_events(get_logs_from_index(txnData,index=i))],
39
+ 'logs':get_logs_from_index(txnData,index=i)
40
+ } for i in range(len(allLogs)) if 'invoke' in allLogs[i].lower()]
41
+ def split_log_for_instruction(log):
42
+ return log.split('log:')[-1].split('Instruction:')[-1]
43
+ def clean_split_string(string,delim=' '):
44
+ return delim.join([spl for spl in string.split(' ') if spl])
45
+ def get_log_events(logs=None,index=None):
46
+ return [clean_split_string(split_log_for_instruction(log)) for log in logs if 'log:' in log.lower() or 'instruction:' in log.lower()]
47
+ def get_instruction_accounts(instruction,txnData):
48
+ accounts = get_all_account_keys(txnData)
49
+ return [accounts[index] for index in instruction.get('accounts',[]) if index < len(accounts)]
50
+ def get_instruction_info(instruction,txnData,instruction_index=0):
51
+
52
+ stack_height = instruction.get('stackHeight') or 1
53
+ accounts = instruction.get('accounts',[])
54
+ associatedAccounts = get_instruction_accounts(instruction,txnData)
55
+ instruction_info = {'instruction_index':instruction_index,'accounts':accounts,'associatedAccounts':associatedAccounts,'instructionStackHeight':stack_height}
56
+
57
+ instruction_info.update(get_for_program_ids_info(txnData)[instruction_index])
58
+ return instruction_info
59
+ def process_instructions(instructions,txnData,start_index=1):
60
+ catalog = []
61
+ for i, inst in enumerate(instructions):
62
+ instruction_index = start_index-1 + i
63
+ instruction_info = get_instruction_info(inst,txnData,instruction_index)
64
+ catalog.append(instruction_info)
65
+ return catalog
66
+ def get_instructions_catalog(txnData,printIt=False,saveIt=False):
67
+ instructions = get_instructions_from_txn(txnData)
68
+ outer_instructions_catalog = process_instructions(instructions,txnData)
69
+ inner_instructions = get_inner_instructions_from_txn(txnData)
70
+ if inner_instructions:
71
+ inner_instructions_catalog = process_instructions(inner_instructions,txnData,start_index=len(instructions))
72
+ complete_catalog = outer_instructions_catalog+inner_instructions_catalog
73
+ if printIt:
74
+ pprint.pprint(complete_catalog)
75
+ if saveIt:
76
+ with open(saveIt, 'w') as f:
77
+ json.dump(complete_catalog, f, indent=4)
78
+ return complete_catalog
79
+
80
+ def find_in_catalog(string,txnData,programId=None):
81
+ complete_catalog = get_instructions_catalog(txnData)
82
+ return [txn for txn in complete_catalog if [event for event in txn['events'] if string.lower() in event.lower()]]
83
+ def findKeyValueIdInCatalog(key,value,txnData,programId=None):
84
+ complete_catalog = get_instructions_catalog(txnData)
85
+ if programId:
86
+ complete_catalog = findKeyValueIdInCatalog('programId',programId,txnData)
87
+ return [txn for txn in make_list(complete_catalog) if txn.get(key) == value]
88
+ def find_account_in_catalog(account,catalog):
89
+ return ifListGetSection([txn for txn in make_list(catalog) if account in txn.get('associatedAccounts')])
@@ -0,0 +1,77 @@
1
+ from .signature_data_parse import get_account_keys_from_txn,get_post_balances_from_txn,get_pre_balances_from_txn,get_post_token_balances_from_txn,get_pre_token_balances_from_txn
2
+ from .account_key_utils import get_all_account_keys
3
+ from abstract_utilities import exponential,get_any_value,update_dict_value,get_value_from_path,find_paths_to_key
4
+ from abstract_solcatcher import *
5
+ def get_amount_dict(amount,decimals=9):
6
+ if amount!= None:
7
+ if isinstance(amount,dict):
8
+ amount_dict = get_any_value(amount,'uiTokenAmount')
9
+ amount = get_any_value(amount_dict,'amount')
10
+ decimals = get_any_value(amount_dict,'decimals')
11
+ return exponential(amount,decimals,-1)
12
+ def create_token_txns(txnData):
13
+ preBalances = get_pre_balances_from_txn(txnData)
14
+ postBalances = get_post_balances_from_txn(txnData)
15
+ account_keys = get_all_account_keys(txnData)
16
+ pre_post_balances = {"preTokenBalances":preTokenBalances,"postTokenBalances":postTokenBalances}
17
+ dont_use = []
18
+ all_txns = {"accounts":[],"owner":[],'Balance Before':[],"Balance After":[],"Change":[],"mint":[],"balanceIndexs":[]}
19
+ for key,tokenBalances in pre_post_balances.items():
20
+ for i,tokenBalance in enumerate(tokenBalances):
21
+ index = tokenBalance.get('accountIndex')
22
+ if index not in dont_use:
23
+ dont_use.append(index)
24
+ after = get_amount_dict(get_acct_index(postTokenBalances,index))
25
+ change = get_amount_dict(tokenBalance)
26
+ if after!=None and change !=None:
27
+ before = after-change
28
+ if i == 0:
29
+ pre_change = change
30
+ change = before
31
+ before = pre_change
32
+ all_txns["accounts"].append(account_keys[index])
33
+ all_txns["owner"].append(tokenBalance.get('owner'))
34
+ all_txns['Balance Before'].append(before)
35
+ all_txns["Balance After"].append(after)
36
+ all_txns["Change"].append(change)
37
+ all_txns["mint"].append(tokenBalance.get('mint'))
38
+ all_txns["balanceIndexs"].append(find_paths_to_key(signature_data, key)[0]+[i])
39
+ return all_txns
40
+ def get_solana_balances(txnData):
41
+ balance = []
42
+ preBalances = get_pre_balances_from_txn(txnData)
43
+ postBalances = get_post_balances_from_txn(txnData)
44
+ account_keys = get_all_account_keys(txnData)
45
+ all_txns = {"accounts":[],'Balance Before':[],"Balance After":[],"Change":[]}
46
+ for i, amt in enumerate(preBalances):
47
+ before = exponential(amt, 9,-1)
48
+ after = exponential(postBalances[i], 9,-1)
49
+ address = account_keys[i]
50
+ change = after - before
51
+ all_txns['accounts'].append(address)
52
+ all_txns['Balance Before'].append(before)
53
+ all_txns['Balance After'].append(after)
54
+ all_txns['Change'].append(change)
55
+ return all_txns
56
+ def get_balances(txnData):
57
+ balances = {"solana":{},"tokens":{}}
58
+ solanaTxns = get_solana_balances(txnData)
59
+ tokenTxns = create_token_txns(txnData)
60
+ for i,address in enumerate(solanaTxns["accounts"]):
61
+ balances["solana"][address]={"Balance Before":solanaTxns["Balance Before"][i],"Balance After":solanaTxns["Balance After"][i],"Change":solanaTxns["Change"][i]}
62
+ for i,address in enumerate(tokenTxns["accounts"]):
63
+ before = tokenTxns["Balance Before"][i]
64
+ after = tokenTxns["Balance After"][i]
65
+ change = after - before
66
+ balances["tokens"][address]={"Balance Before":before,"Balance After":after,"Change":change,"mint":tokenTxns["mint"][i],"owner":tokenTxns["owner"][i],"balanceIndex":tokenTxns["balanceIndexs"][i]}
67
+ return balances
68
+ def update_balance_data(txnData):
69
+ balances = get_balances(txnData)
70
+ all_txns = create_token_txns(txnData)
71
+ for key,values in balances["tokens"].items():
72
+ path =values.get("balanceIndex")
73
+ tokenBalance = get_value_from_path(txnData,path)
74
+ tokenBalance.update({key:values.get(key) for key in ["Balance Before","Balance After","Change"]})
75
+ signature_data = update_dict_value(txnData, path, tokenBalance)
76
+ txnData['meta']['balances']=balances
77
+ return txnData
@@ -0,0 +1,59 @@
1
+ from solders.pubkey import Pubkey
2
+ from solders.signature import Signature
3
+ def get_pubString(obj):
4
+ return Pubkey.from_string(str(obj))
5
+
6
+ def get_sigString(obj):
7
+ return Signature.from_string(str(obj))
8
+
9
+ def is_sigkey(obj):
10
+ return isinstance(obj,Signature)
11
+
12
+ def is_pubkey(obj):
13
+ return isinstance(obj,Pubkey)
14
+
15
+ def get_pubBytes(obj):
16
+ return Pubkey.from_bytes(obj)
17
+
18
+ def get_sigBytes(obj):
19
+ return Signature.from_bytes(obj)
20
+
21
+ def try_pubkey(obj):
22
+ return is_pubkey(get_pubkey(obj))
23
+
24
+ def try_sigkey(obj):
25
+ return is_sigkey(get_sigkey(obj))
26
+
27
+ def get_pubkey(obj):
28
+ if is_pubkey(obj):
29
+ return obj
30
+ address = obj
31
+ if isinstance(obj,bytes):
32
+ pubkey = get_pubBytes(address)
33
+ if is_pubkey(pubkey):
34
+ return pubkey
35
+ if isinstance(obj,str):
36
+ try:
37
+ pubkey= get_pubString(obj)
38
+ except:
39
+ pubkey = obj
40
+ if is_pubkey(pubkey):
41
+ return pubkey
42
+ return obj
43
+
44
+ def get_sigkey(obj):
45
+ if is_sigkey(obj):
46
+ return obj
47
+ signature = obj
48
+ if isinstance(signature,bytes):
49
+ sigKey = get_sigBytes(signature)
50
+ if is_sigkey(sigKey):
51
+ return sigKey
52
+ if isinstance(signature,str):
53
+ try:
54
+ sigKey= get_sigString(signature)
55
+ except:
56
+ sigKey = signature
57
+ if is_sigkey(sigKey):
58
+ return sigKey
59
+ return obj
@@ -0,0 +1,57 @@
1
+ from abstract_utilities import make_list,get_any_value
2
+ def get_block_time_from_txn(txnData):
3
+ return int(get_any_value(txnData,'blockTime') or 0)
4
+
5
+ def get_meta_from_txn(txnData):
6
+ return txnData.get('meta',{})
7
+
8
+ def get_transaction_from_txn(txnData):
9
+ return txnData.get('transaction', {})
10
+
11
+ def get_message_from_txn(txnData):
12
+ return get_transaction_from_txn(txnData).get('message', {})
13
+
14
+ def get_addres_lookup_table_from_txn(txnData):
15
+ return get_message_from_txn(txnData).get('addressTableLookups', [])
16
+
17
+ def get_account_keys_from_txn(txnData):
18
+ return get_message_from_txn(txnData).get('accountKeys', [])
19
+
20
+ def get_loaded_addresses_from_txn(txnData):
21
+ return get_meta_from_txn(txnData).get('loadedAddresses',{})
22
+
23
+ def get_read_only_addresses_from_txn(txnData):
24
+ return get_any_value(txnData,'readonly') or []
25
+
26
+ def get_writable_addresses_from_txn(txnData):
27
+ return get_any_value(txnData,'writable') or []
28
+
29
+ def get_log_messages_from_txn(txnData):
30
+ return get_meta_from_txn(txnData).get('logMessages',[])
31
+
32
+ def get_error_message_from_txn(txnData):
33
+ return make_list(get_any_value(txnData,'err'))[0]
34
+
35
+ def get_instructions_from_txn(txnData):
36
+ return get_message_from_txn(txnData).get('instructions',[])
37
+
38
+ def get_inner_instructions_raw(txnData):
39
+ return get_meta_from_txn(txnData).get('innerInstructions',[{}])
40
+
41
+ def get_inner_instructions_from_txn(txnData):
42
+ return get_inner_instructions_raw(txnData)[0].get('instructions',[])
43
+
44
+ def get_post_token_balances_from_txn(txnData):
45
+ return get_meta_from_txn(txnData).get('postTokenBalances', [])
46
+
47
+ def get_pre_token_balances_from_txn(txnData):
48
+ return get_meta_from_txn(txnData).get('preTokenBalances', [])
49
+
50
+ def get_post_balances_from_txn(txnData):
51
+ return get_meta_from_txn(txnData).get('postBalances', [])
52
+
53
+ def get_pre_balances_from_txn(txnData):
54
+ return get_meta_from_txn(txnData).get('preBalances', [])
55
+
56
+ def get_signatures_from_txn(txnData):
57
+ return txnData.get('signatures',{})
@@ -0,0 +1,12 @@
1
+ def ifListGetSection(listObj,section=0):
2
+ if isinstance(listObj,list):
3
+ if len(listObj)>section:
4
+ return listObj[section]
5
+ return listObj
6
+ def if_list_get_Part(obj,i=0):
7
+ if obj and isinstance(obj,list) and len(obj)>i:
8
+ obj = obj[i]
9
+ return obj
10
+ def updateData(data,**kwargs):
11
+ data.update(kwargs)
12
+ return data
@@ -0,0 +1,26 @@
1
+ Metadata-Version: 2.1
2
+ Name: abstract_solana
3
+ Version: 0.0.0.1
4
+ Home-page: https://github.com/AbstractEndeavors/abstract_solana
5
+ Author: putkoff
6
+ Author-email: partners@abstractendeavors.com
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Topic :: Software Development :: Libraries
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.6
13
+ Classifier: Programming Language :: Python :: 3.7
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.6
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: solders
22
+ Requires-Dist: abstract_utilities
23
+
24
+ ## Abstract Solana
25
+
26
+
@@ -0,0 +1,17 @@
1
+ README.md
2
+ setup.py
3
+ src/abstract_solana/__init__.py
4
+ src/abstract_solana/account_key_utils.py
5
+ src/abstract_solana/genesis_functions.py
6
+ src/abstract_solana/index_utils.py
7
+ src/abstract_solana/log_message_functions.py
8
+ src/abstract_solana/price_utils.py
9
+ src/abstract_solana/pubkey_utils.py
10
+ src/abstract_solana/signature_data_parse.py
11
+ src/abstract_solana/utils.py
12
+ src/abstract_solana.egg-info/PKG-INFO
13
+ src/abstract_solana.egg-info/SOURCES.txt
14
+ src/abstract_solana.egg-info/dependency_links.txt
15
+ src/abstract_solana.egg-info/requires.txt
16
+ src/abstract_solana.egg-info/top_level.txt
17
+ test/test_abstract_solana.py
@@ -0,0 +1,2 @@
1
+ solders
2
+ abstract_utilities
@@ -0,0 +1 @@
1
+ abstract_solana
@@ -0,0 +1,111 @@
1
+ from abstract_solana import *
2
+ from spl.token.instructions import create_associated_token_account, get_associated_token_address
3
+ from solders_rpc import *
4
+ PUMP_FUN_PROGRAM = get_pubkey("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P")
5
+
6
+ PUMP_FUN_ASSOC_TOKEN_ACC_PROG = get_pubkey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL")
7
+ from abstract_solcatcher import *
8
+ def get_solcatcher_api(endpoint,*args,**kwargs):
9
+ return get_async_response(get_solcatcher_endpoint,endpoint=endpoint,*args,**kwargs)
10
+ def derive_associated_bonding_curve(mint):
11
+ return get_associated_token_address(derive_bonding_curve(mint)[0], get_pubkey(mint))
12
+ def derive_bonding_curve(mint):
13
+ return Pubkey.find_program_address(["bonding-curve".encode(), bytes(get_pubkey(mint))],PUMP_FUN_PROGRAM)
14
+
15
+ def get_balance_info(balanceInfo, programId, authority):
16
+ return next((bal for bal in balanceInfo if programId == bal.get("programId") and authority == bal.get("owner")), {})
17
+ def get_balance_from_instruction(transfer_instruction, txnData):
18
+ preBalance = txnData["meta"].get("preTokenBalances", [])
19
+ postBalance = txnData["meta"].get("postTokenBalances", [])
20
+
21
+ # Update transfer_instruction with source, destination, and authority
22
+ accounts = transfer_instruction.get("accounts", [])
23
+ transfer_instruction.update({
24
+ key: accounts[i] for i, key in enumerate(["source", "destination", "authority"])
25
+ })
26
+
27
+ preBalanceInfo = get_balance_info(preBalance, transfer_instruction['programId'], transfer_instruction['authority'])
28
+ postBalanceInfo = get_balance_info(postBalance, transfer_instruction['programId'], transfer_instruction['authority'])
29
+
30
+ amount = preBalanceInfo.get('uiTokenAmount', {}).get('amount', 0) - postBalanceInfo.get('uiTokenAmount', {}).get('amount', 0)
31
+ transfer_instruction['amount'] = amount
32
+
33
+ return transfer_instruction
34
+ def get_transfer_info(transfer_instructions, txnData):
35
+ for transfer_instruction in transfer_instructions:
36
+ updated_instruction = get_balance_from_instruction(transfer_instruction, txnData)
37
+ transfer_instruction.update(updated_instruction)
38
+
39
+ return transfer_instructions
40
+ async def async_getSignaturesForAddress(account: Pubkey,
41
+ before: Optional[Signature] = None,
42
+ until: Optional[Signature] = None,
43
+ limit: Optional[int] = None,
44
+ commitment: Optional[Commitment] = None,
45
+ errorProof=False):
46
+ """Returns confirmed signatures for transactions involving an address.
47
+
48
+ Signatures are returned backwards in time from the provided signature or
49
+ most recent confirmed block.
50
+
51
+ Args:
52
+ account: Account to be queried.
53
+ before: (optional) Start searching backwards from this transaction signature.
54
+ If not provided the search starts from the top of the highest max confirmed block.
55
+ until: (optional) Search until this transaction signature, if found before limit reached.
56
+ limit: (optional) Maximum transaction signatures to return (between 1 and 1,000, default: 1,000).
57
+ commitment: (optional) Bank state to query. It can be either "finalized", "confirmed" or "processed".
58
+
59
+ Example:
60
+ >>> solana_client = Client("http://localhost:8899")
61
+ >>> from solders.pubkey import Pubkey
62
+ >>> pubkey = Pubkey.from_string("Vote111111111111111111111111111111111111111")
63
+ >>> solana_client.get_signatures_for_address(pubkey, limit=1).value[0].signature # doctest: +SKIP
64
+ Signature(
65
+ 1111111111111111111111111111111111111111111111111111111111111111,
66
+ )
67
+ """
68
+ account=get_pubkey(account)
69
+ before=get_sigkey(before)
70
+ until=until
71
+ limit=limit or 1000
72
+ commitment=commitment
73
+ response = json.loads(str(Client().get_signatures_for_address(account=account,before=before,until=until,limit=limit,commitment=commitment)))
74
+ signatureArray= await makeLimitedCall(response.get('method'),response.get('params'))
75
+ if errorProof:
76
+ signatureArray = [signatureData for signatureData in signatureArray if signatureData.get('err') == None]
77
+ return signatureArray
78
+ def getsignaturesforaddress(account,before=None,until=None,limit=None,commitment=None,errorProof=None):
79
+ return get_async_response(async_getSignaturesForAddress,account=account,before=before,until=until,limit=limit,commitment=commitment,errorProof=errorProof)
80
+
81
+ def get_transfer_instructions(txnData,programId=None):
82
+ programId = programId or PUMP_FUN_ASSOC_TOKEN_ACC_PROG
83
+ return get_transfer_info(find_in_catalog('transfer',txnData,programId=programId),txnData)
84
+ async def async_getGenesisSignature(account,before=None,limit=1000,commitment=None):
85
+ method = "getGenesisSignature"
86
+ limit=1000
87
+
88
+ genesisSignature=None
89
+ if genesisSignature == None:
90
+ before = before or None
91
+ genesisSignature = None # This will store the last seen valid signature
92
+ while True:
93
+ signatureArray = await getsignaturesforaddress(account=account,before=before,limit=limit,commitment=commitment)
94
+ signatureArrayInfo = return_oldest_last_and_original_length_from_signature_array(signatureArray)
95
+ genesisSignature = signatureArrayInfo.get("oldestValid") or genesisSignature
96
+
97
+ if before == signatureArrayInfo.get("oldest") or signatureArrayInfo.get("length") < limit:
98
+ #insert_Db(method.lower(), str(account), (str(account), str(genesisSignature)))
99
+ return genesisSignature
100
+ before = signatureArrayInfo.get("oldest")
101
+ return genesisSignature
102
+
103
+ def getgenesissignature(account,before=None,limit=None,commitment=None):
104
+ return get_async_response(async_getGenesisSignature,account=account,before=before,limit=limit,commitment=commitment)
105
+
106
+ mint = "911eA3wRZ85ZiSTpmCH1hksPGLGgzyVpfMXtJ4zSzVJ5"
107
+ bondingCurve = str(derive_bonding_curve(mint))
108
+ #input(getsignaturesforaddress(str(derive_bonding_curve(mint)[0])))
109
+ input(getgenesissignature(str(derive_bonding_curve(mint)[0])))
110
+ parsed_txn = get_solcatcher_api("getParsedTransaction",signature="2pQRuCawe8it1X4bvKZnmSZZfcLUXd3q1ki8z1kMBCKm52eU2obQxGSkpRR1tX88nquy5iNiycebit3BFsQaDPcx")
111
+ input(get_transfer_instructions(parsed_txn,programId=PUMP_FUN_ASSOC_TOKEN_ACC_PROG))