abstract-solana 0.0.0.17__tar.gz → 0.0.0.18__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.
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/PKG-INFO +1 -1
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/setup.py +1 -1
- abstract_solana-0.0.0.18/src/abstract_solana/log_message_functions.py +154 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/pubkey_utils.py +2 -1
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana.egg-info/PKG-INFO +1 -1
- abstract_solana-0.0.0.18/test/test_abstract_solana.py +197 -0
- abstract_solana-0.0.0.17/src/abstract_solana/log_message_functions.py +0 -90
- abstract_solana-0.0.0.17/test/test_abstract_solana.py +0 -29
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/README.md +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/setup.cfg +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/__init__.py +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/account_key_utils.py +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/constants.py +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/genesis_functions.py +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/index_utils.py +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/price_utils.py +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/signature_data_parse.py +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/utils.py +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana.egg-info/SOURCES.txt +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana.egg-info/dependency_links.txt +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana.egg-info/requires.txt +0 -0
- {abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,154 @@
|
|
|
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
|
+
from .constants import TOKEN_PROGRAM_ID
|
|
6
|
+
def ifListGetSection(list_obj,i=0):
|
|
7
|
+
if list_obj and isinstance(list_obj,list) and len(list_obj)>i:
|
|
8
|
+
list_obj = list_obj[i]
|
|
9
|
+
return list_obj
|
|
10
|
+
def get_logs_from_index(txnData,index=None):
|
|
11
|
+
if index is not None:
|
|
12
|
+
allLogs = get_log_messages_from_txn(txnData)
|
|
13
|
+
endLog = get_end_log_index(txnData,index)
|
|
14
|
+
return allLogs[index:endLog]
|
|
15
|
+
def get_program_ids(txnData):
|
|
16
|
+
allLogs = get_log_messages_from_txn(txnData)
|
|
17
|
+
return [log.split(' ')[1] for log in allLogs if 'invoke' in log]
|
|
18
|
+
def get_program_id_from_log(logs):
|
|
19
|
+
for log in make_list(logs):
|
|
20
|
+
if 'invoke' in log.lower():
|
|
21
|
+
return log.split(' ')[1]
|
|
22
|
+
def get_stack_height_from_logs(logs):
|
|
23
|
+
for log in make_list(logs):
|
|
24
|
+
if 'invoke' in log.lower():
|
|
25
|
+
return int(log.split(' ')[-1][1:-1])
|
|
26
|
+
def get_end_log_index(txnData,index):
|
|
27
|
+
allLogs = get_log_messages_from_txn(txnData)
|
|
28
|
+
i=0
|
|
29
|
+
for i,log in enumerate(allLogs[index+1:]):
|
|
30
|
+
if 'invoke' in log.lower():
|
|
31
|
+
return index+1+i
|
|
32
|
+
return len(allLogs)
|
|
33
|
+
def get_stack_height_from_logs(logs):
|
|
34
|
+
for log in make_list(logs):
|
|
35
|
+
if 'invoke' in log.lower():
|
|
36
|
+
return int(log.split(' ')[-1][1:-1])
|
|
37
|
+
def get_program_id_from_log(logs):
|
|
38
|
+
for log in make_list(logs):
|
|
39
|
+
if 'invoke' in log.lower():
|
|
40
|
+
return log.split(' ')[1]
|
|
41
|
+
|
|
42
|
+
def get_all_logs(txnData):
|
|
43
|
+
logits = []
|
|
44
|
+
allLogs = get_log_messages_from_txn(txnData)
|
|
45
|
+
for i,log in enumerate(allLogs):
|
|
46
|
+
if 'invoke' in log.lower():
|
|
47
|
+
logits.append([])
|
|
48
|
+
logits[-1].append(log)
|
|
49
|
+
start = 0
|
|
50
|
+
for i,log in enumerate(logits):
|
|
51
|
+
length = len(log)
|
|
52
|
+
end = start+length
|
|
53
|
+
logits[i]={"programId":get_program_id_from_log(log[0]),
|
|
54
|
+
"start":start,
|
|
55
|
+
"end":end-1,
|
|
56
|
+
'stackHeight':get_stack_height_from_logs(log[0]) or 1,
|
|
57
|
+
'events':[event.split(':')[-1] or 'unknown' for event in get_log_events(log)],
|
|
58
|
+
'vars':[event.split(':')[1:] or 'unknown' for event in get_log_events(log)],
|
|
59
|
+
'logs':log}
|
|
60
|
+
start = end
|
|
61
|
+
return logits
|
|
62
|
+
def split_log_for_instruction(log):
|
|
63
|
+
return log.split('log:')[-1].split('Instruction:')[-1]
|
|
64
|
+
def clean_split_string(string,delim=' '):
|
|
65
|
+
return delim.join([spl for spl in string.split(' ') if spl])
|
|
66
|
+
def get_log_events(logs=None,index=None):
|
|
67
|
+
return [clean_split_string(split_log_for_instruction(log)) for log in logs if 'log:' in log.lower() or 'instruction:' in log.lower()]
|
|
68
|
+
def get_instruction_accounts(instruction,txnData):
|
|
69
|
+
accounts = get_all_account_keys(txnData)
|
|
70
|
+
return [accounts[index] for index in instruction.get('accounts',[]) if index < len(accounts)]
|
|
71
|
+
def get_instruction_info(instruction,txnData,instruction_index=0):
|
|
72
|
+
|
|
73
|
+
stack_height = instruction.get('stackHeight') or 1
|
|
74
|
+
accounts = instruction.get('accounts',[])
|
|
75
|
+
associatedAccounts = get_instruction_accounts(instruction,txnData)
|
|
76
|
+
instruction_info = {'instruction_index':instruction_index,'accounts':accounts,'associatedAccounts':associatedAccounts,'instructionStackHeight':stack_height}
|
|
77
|
+
|
|
78
|
+
instruction_info.update(get_for_program_ids_info(txnData)[instruction_index])
|
|
79
|
+
return instruction_info
|
|
80
|
+
def process_instructions(instructions,txnData,start_index=1):
|
|
81
|
+
catalog = []
|
|
82
|
+
for i, inst in enumerate(instructions):
|
|
83
|
+
instruction_index = start_index-1 + i
|
|
84
|
+
instruction_info = get_instruction_info(inst,txnData,instruction_index)
|
|
85
|
+
catalog.append(instruction_info)
|
|
86
|
+
return catalog
|
|
87
|
+
def get_instructions_catalog(txnData,printIt=False,saveIt=False):
|
|
88
|
+
instructions = get_instructions_from_txn(txnData)
|
|
89
|
+
outer_instructions_catalog = process_instructions(instructions,txnData)
|
|
90
|
+
inner_instructions = get_inner_instructions_from_txn(txnData)
|
|
91
|
+
if inner_instructions:
|
|
92
|
+
inner_instructions_catalog = process_instructions(inner_instructions,txnData,start_index=len(instructions))
|
|
93
|
+
complete_catalog = outer_instructions_catalog+inner_instructions_catalog
|
|
94
|
+
if printIt:
|
|
95
|
+
pprint.pprint(complete_catalog)
|
|
96
|
+
if saveIt:
|
|
97
|
+
with open(saveIt, 'w') as f:
|
|
98
|
+
json.dump(complete_catalog, f, indent=4)
|
|
99
|
+
return complete_catalog
|
|
100
|
+
|
|
101
|
+
def find_in_catalog(string,txnData,programId=None):
|
|
102
|
+
complete_catalog = get_instructions_catalog(txnData)
|
|
103
|
+
return [txn for txn in complete_catalog if [event for event in txn['events'] if string.lower() in event.lower()]]
|
|
104
|
+
def findKeyValueIdInCatalog(key,value,txnData,programId=None):
|
|
105
|
+
complete_catalog = get_instructions_catalog(txnData)
|
|
106
|
+
if programId:
|
|
107
|
+
complete_catalog = findKeyValueIdInCatalog('programId',programId,txnData)
|
|
108
|
+
return [txn for txn in make_list(complete_catalog) if txn.get(key) == value]
|
|
109
|
+
def find_account_in_catalog(account,catalog):
|
|
110
|
+
return ifListGetSection([txn for txn in make_list(catalog) if account in txn.get('associatedAccounts')])
|
|
111
|
+
def associate_logs_with_instructions(txnData):
|
|
112
|
+
accountKeys = get_all_account_keys(txnData)
|
|
113
|
+
instructions = txnData['transaction']['message']['instructions']
|
|
114
|
+
innerInstructions = txnData['meta']['innerInstructions'][0]['instructions']
|
|
115
|
+
allLogs = txnData['meta']['logMessages']
|
|
116
|
+
for logIndex,log in enumerate(allLogs):
|
|
117
|
+
log_programId = log['programId']
|
|
118
|
+
log_stackHeight = log.get('stackHeight') # Default to 0 if stackHeight is missing
|
|
119
|
+
# Search for matching instructions by programId and stackHeight
|
|
120
|
+
for instIndex,allInstruction in enumerate([instructions,innerInstructions]):
|
|
121
|
+
for i,instruction in enumerate(allInstruction):
|
|
122
|
+
program_id_index = instruction.get('programIdIndex')
|
|
123
|
+
if program_id_index is not None:
|
|
124
|
+
instruction_program_id = accountKeys[program_id_index]
|
|
125
|
+
instruction_stack_height = instruction.get('stackHeight', 1)
|
|
126
|
+
if instruction_program_id == log_programId and instruction_stack_height == log_stackHeight:
|
|
127
|
+
# Add log data to the matching instruction
|
|
128
|
+
instruction['logs'] = log['logs']
|
|
129
|
+
instruction['event'] = None if log['events'] == [] else log['events'][0]
|
|
130
|
+
instruction['start'] = log['start']
|
|
131
|
+
instruction['end'] = log['end']
|
|
132
|
+
instruction['stackHeight'] = instruction_stack_height
|
|
133
|
+
instruction['programId'] = instruction_program_id
|
|
134
|
+
instruction['associatedAccounts'] = [accountKeys[index] for index in instruction['accounts']]
|
|
135
|
+
if instIndex == 0:
|
|
136
|
+
instructions[i] = instruction
|
|
137
|
+
else:
|
|
138
|
+
innerInstructions[i] = instruction
|
|
139
|
+
allLogs[logIndex].update(instruction)
|
|
140
|
+
txnData['transaction']['message']['instructions'] = instructions
|
|
141
|
+
txnData['meta']['innerInstructions'][0]['instructions'] = innerInstructions
|
|
142
|
+
txnData['meta']['logMessages'] = allLogs
|
|
143
|
+
return txnData
|
|
144
|
+
def update_initial_txnData(txnData):
|
|
145
|
+
accountKeys = get_all_account_keys(txnData)
|
|
146
|
+
txnData = update_balance_data(txnData)
|
|
147
|
+
txnData['transaction']['message']['instructions'] = [{**inst,"instructionIndex":instIndex,"programId":accountKeys[inst.get('programIdIndex')],"stackHeight":inst.get('stackHeight', 1),"associatedAccounts":[accountKeys[index] for index in inst['accounts']]} for instIndex,inst in enumerate(txnData['transaction']['message']['instructions'])]
|
|
148
|
+
txnData['meta']['innerInstructions'][0]['instructions'] = [{**inst,"instructionIndex":instIndex+len(txnData['transaction']['message']['instructions']),"programId":accountKeys[inst.get('programIdIndex')],"stackHeight":inst.get('stackHeight', 1),"associatedAccounts":[accountKeys[index] for index in inst['accounts']]} for instIndex,inst in enumerate(txnData['meta']['innerInstructions'][0]['instructions'])]
|
|
149
|
+
txnData['meta']['logMessages'] = get_all_logs(txnData)
|
|
150
|
+
return txnData
|
|
151
|
+
def get_for_program_ids_info(txnData):
|
|
152
|
+
txnData = update_initial_txnData(txnData)
|
|
153
|
+
txnData = associate_logs_with_instructions(txnData)
|
|
154
|
+
return txnData
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from solders.pubkey import Pubkey
|
|
2
2
|
from solders.signature import Signature
|
|
3
3
|
from spl.token.instructions import get_associated_token_address
|
|
4
|
+
TOKEN_PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
|
|
4
5
|
|
|
5
6
|
def pubkey_find_program_address(string,address,programId):
|
|
6
7
|
return Pubkey.find_program_address([str(string).encode(), bytes(get_pubkey(address))],get_pubkey(programId))
|
|
@@ -67,5 +68,5 @@ def derive_associated_bonding_curve(mint,programId=None):
|
|
|
67
68
|
return get_associated_token_address(derive_bonding_curve(mint,programId)[0], get_pubkey(mint))
|
|
68
69
|
|
|
69
70
|
def derive_bonding_curve(mint,programId=None):
|
|
70
|
-
programId = programId or
|
|
71
|
+
programId = programId or TOKEN_PROGRAM_ID
|
|
71
72
|
return pubkey_find_program_address("bonding-curve",mint,programId)
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
from abstract_solana import *
|
|
2
|
+
from spl.token.instructions import create_associated_token_account, get_associated_token_address
|
|
3
|
+
from price_functions import *
|
|
4
|
+
from abstract_solcatcher import *
|
|
5
|
+
from abstract_utilities import make_list
|
|
6
|
+
import json,pprint
|
|
7
|
+
from abstract_utilities import make_list
|
|
8
|
+
from abstract_solana import *
|
|
9
|
+
from abstract_solana.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
|
|
10
|
+
from abstract_solana.account_key_utils import get_all_account_keys
|
|
11
|
+
from abstract_solana.index_utils import search_for_account_index
|
|
12
|
+
from abstract_utilities import exponential,get_any_value,update_dict_value,get_value_from_path,find_paths_to_key
|
|
13
|
+
import base64
|
|
14
|
+
import struct
|
|
15
|
+
import base58
|
|
16
|
+
from construct import Struct, Int8ul, Int16ul, Int32ul, Int64ul, PaddedString, Flag, Padding
|
|
17
|
+
from abstract_solana.signature_data_parse import get_log_messages_from_txn,get_instructions_from_txn,get_inner_instructions_from_txn
|
|
18
|
+
from abstract_solana.account_key_utils import get_all_account_keys
|
|
19
|
+
TOKEN_PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
|
|
20
|
+
def ifListGetSection(list_obj,i=0):
|
|
21
|
+
if list_obj and isinstance(list_obj,list) and len(list_obj)>i:
|
|
22
|
+
list_obj = list_obj[i]
|
|
23
|
+
return list_obj
|
|
24
|
+
def get_logs_from_index(txnData,index=None):
|
|
25
|
+
if index is not None:
|
|
26
|
+
allLogs = get_log_messages_from_txn(txnData)
|
|
27
|
+
endLog = get_end_log_index(txnData,index)
|
|
28
|
+
return allLogs[index:endLog]
|
|
29
|
+
def get_program_ids(txnData):
|
|
30
|
+
allLogs = get_log_messages_from_txn(txnData)
|
|
31
|
+
return [log.split(' ')[1] for log in allLogs if 'invoke' in log]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def get_end_log_index(txnData,index):
|
|
35
|
+
allLogs = get_log_messages_from_txn(txnData)
|
|
36
|
+
i=0
|
|
37
|
+
for i,log in enumerate(allLogs[index+1:]):
|
|
38
|
+
if 'invoke' in log.lower():
|
|
39
|
+
return index+1+i
|
|
40
|
+
return len(allLogs)
|
|
41
|
+
def searchForProgramIdEvent(allLogs,programId):
|
|
42
|
+
for i,allLog in enumerate(allLogs):
|
|
43
|
+
if programId == allLog.get('programId'):
|
|
44
|
+
return i
|
|
45
|
+
def searchEvent(events,search_event):
|
|
46
|
+
for i,event in enumerate(events):
|
|
47
|
+
if event.get('event') == search_event:
|
|
48
|
+
return i
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_stack_height_from_logs(logs):
|
|
52
|
+
for log in make_list(logs):
|
|
53
|
+
if 'invoke' in log.lower():
|
|
54
|
+
return int(log.split(' ')[-1][1:-1])
|
|
55
|
+
def get_program_id_from_log(logs):
|
|
56
|
+
for log in make_list(logs):
|
|
57
|
+
if 'invoke' in log.lower():
|
|
58
|
+
return log.split(' ')[1]
|
|
59
|
+
def get_all_logs(txnData):
|
|
60
|
+
logits = []
|
|
61
|
+
allLogs = get_log_messages_from_txn(txnData)
|
|
62
|
+
for i,log in enumerate(allLogs):
|
|
63
|
+
if 'invoke' in log.lower():
|
|
64
|
+
logits.append([])
|
|
65
|
+
logits[-1].append(log)
|
|
66
|
+
start = 0
|
|
67
|
+
for i,log in enumerate(logits):
|
|
68
|
+
length = len(log)
|
|
69
|
+
end = start+length
|
|
70
|
+
logits[i]={"programId":get_program_id_from_log(log[0]),
|
|
71
|
+
"start":start,
|
|
72
|
+
"end":end-1,
|
|
73
|
+
'stackHeight':get_stack_height_from_logs(log[0]) or 1,
|
|
74
|
+
'events':[event.split(':')[-1] or 'unknown' for event in get_log_events(log)],
|
|
75
|
+
'vars':[event.split(':')[1:] or 'unknown' for event in get_log_events(log)],
|
|
76
|
+
'logs':log}
|
|
77
|
+
start = end
|
|
78
|
+
return logits
|
|
79
|
+
def get_programId(txnData,programId,stackHeight,event=None):
|
|
80
|
+
instructions = txnData['transaction']['message']['instructions']
|
|
81
|
+
inner_instructions = txnData['meta']['innerInstructions'][0]['instructions']
|
|
82
|
+
return [all_instruction for all_instruction in instructions+inner_instructions if all_instruction.get("programId") == programId and all_instruction.get('stackHeight') == stackHeight]
|
|
83
|
+
def associate_logs_with_instructions(txnData):
|
|
84
|
+
accountKeys = get_all_account_keys(txnData)
|
|
85
|
+
instructions = txnData['transaction']['message']['instructions']
|
|
86
|
+
innerInstructions = txnData['meta']['innerInstructions'][0]['instructions']
|
|
87
|
+
allLogs = txnData['meta']['logMessages']
|
|
88
|
+
for logIndex,log in enumerate(allLogs):
|
|
89
|
+
log_programId = log['programId']
|
|
90
|
+
log_stackHeight = log.get('stackHeight') # Default to 0 if stackHeight is missing
|
|
91
|
+
# Search for matching instructions by programId and stackHeight
|
|
92
|
+
for instIndex,allInstruction in enumerate([instructions,innerInstructions]):
|
|
93
|
+
for i,instruction in enumerate(allInstruction):
|
|
94
|
+
program_id_index = instruction.get('programIdIndex')
|
|
95
|
+
if program_id_index is not None:
|
|
96
|
+
instruction_program_id = accountKeys[program_id_index]
|
|
97
|
+
instruction_stack_height = instruction.get('stackHeight', 1)
|
|
98
|
+
if instruction_program_id == log_programId and instruction_stack_height == log_stackHeight:
|
|
99
|
+
# Add log data to the matching instruction
|
|
100
|
+
instruction['logs'] = log['logs']
|
|
101
|
+
instruction['event'] = None if log['events'] == [] else log['events'][0]
|
|
102
|
+
instruction['start'] = log['start']
|
|
103
|
+
instruction['end'] = log['end']
|
|
104
|
+
instruction['stackHeight'] = instruction_stack_height
|
|
105
|
+
instruction['programId'] = instruction_program_id
|
|
106
|
+
instruction['associatedAccounts'] = [accountKeys[index] for index in instruction['accounts']]
|
|
107
|
+
if instIndex == 0:
|
|
108
|
+
instructions[i] = instruction
|
|
109
|
+
else:
|
|
110
|
+
innerInstructions[i] = instruction
|
|
111
|
+
allLogs[logIndex].update(instruction)
|
|
112
|
+
txnData['transaction']['message']['instructions'] = instructions
|
|
113
|
+
txnData['meta']['innerInstructions'][0]['instructions'] = innerInstructions
|
|
114
|
+
txnData['meta']['logMessages'] = allLogs
|
|
115
|
+
return txnData
|
|
116
|
+
def update_initial_txnData(txnData):
|
|
117
|
+
accountKeys = get_all_account_keys(txnData)
|
|
118
|
+
txnData = update_balance_data(txnData)
|
|
119
|
+
txnData['transaction']['message']['instructions'] = [{**inst,"instructionIndex":instIndex,"programId":accountKeys[inst.get('programIdIndex')],"stackHeight":inst.get('stackHeight', 1),"associatedAccounts":[accountKeys[index] for index in inst['accounts']]} for instIndex,inst in enumerate(txnData['transaction']['message']['instructions'])]
|
|
120
|
+
txnData['meta']['innerInstructions'][0]['instructions'] = [{**inst,"instructionIndex":instIndex+len(txnData['transaction']['message']['instructions']),"programId":accountKeys[inst.get('programIdIndex')],"stackHeight":inst.get('stackHeight', 1),"associatedAccounts":[accountKeys[index] for index in inst['accounts']]} for instIndex,inst in enumerate(txnData['meta']['innerInstructions'][0]['instructions'])]
|
|
121
|
+
txnData['meta']['logMessages'] = get_all_logs(txnData)
|
|
122
|
+
return txnData
|
|
123
|
+
def get_for_program_ids_info(txnData):
|
|
124
|
+
txnData = update_initial_txnData(txnData)
|
|
125
|
+
txnData = associate_logs_with_instructions(txnData)
|
|
126
|
+
return txnData
|
|
127
|
+
|
|
128
|
+
def get_instruction_accounts(instruction,txnData):
|
|
129
|
+
accounts = get_all_account_keys(txnData)
|
|
130
|
+
return [accounts[index] for index in instruction.get('accounts',[]) if index < len(accounts)]
|
|
131
|
+
def get_instruction_info(instruction,txnData,instruction_index=0):
|
|
132
|
+
|
|
133
|
+
stack_height = instruction.get('stackHeight') or 1
|
|
134
|
+
accounts = instruction.get('accounts',[])
|
|
135
|
+
associatedAccounts = get_instruction_accounts(instruction,txnData)
|
|
136
|
+
instruction_info = {'instruction_index':instruction_index,'accounts':accounts,'associatedAccounts':associatedAccounts,'instructionStackHeight':stack_height}
|
|
137
|
+
|
|
138
|
+
instruction_info.update(get_for_program_ids_info(txnData)[instruction_index])
|
|
139
|
+
return instruction_info
|
|
140
|
+
def process_instructions(instructions,txnData,start_index=1):
|
|
141
|
+
catalog = []
|
|
142
|
+
for i, inst in enumerate(instructions):
|
|
143
|
+
instruction_index = start_index + i
|
|
144
|
+
instruction_info = get_instruction_info(inst,txnData,instruction_index)
|
|
145
|
+
catalog.append(instruction_info)
|
|
146
|
+
return catalog
|
|
147
|
+
def get_instructions_catalog(txnData,printIt=False,saveIt=False):
|
|
148
|
+
instructions = get_instructions_from_txn(txnData)
|
|
149
|
+
outer_instructions_catalog = process_instructions(instructions,txnData)
|
|
150
|
+
inner_instructions = get_inner_instructions_from_txn(txnData)
|
|
151
|
+
if inner_instructions:
|
|
152
|
+
inner_instructions_catalog = process_instructions(inner_instructions,txnData,start_index=len(instructions))
|
|
153
|
+
complete_catalog = outer_instructions_catalog+inner_instructions_catalog
|
|
154
|
+
if printIt:
|
|
155
|
+
pprint.pprint(complete_catalog)
|
|
156
|
+
if saveIt:
|
|
157
|
+
with open(saveIt, 'w') as f:
|
|
158
|
+
json.dump(complete_catalog, f, indent=4)
|
|
159
|
+
return complete_catalog
|
|
160
|
+
|
|
161
|
+
def find_in_catalog(string,txnData,programId=None):
|
|
162
|
+
complete_catalog = get_instructions_catalog(txnData)
|
|
163
|
+
return [txn for txn in complete_catalog if [event for event in txn['events'] if string.lower() in event.lower()]]
|
|
164
|
+
def findKeyValueIdInCatalog(key,value,txnData,programId=None):
|
|
165
|
+
complete_catalog = get_instructions_catalog(txnData)
|
|
166
|
+
if programId:
|
|
167
|
+
complete_catalog = findKeyValueIdInCatalog('programId',programId,txnData)
|
|
168
|
+
return [txn for txn in make_list(complete_catalog) if txn.get(key) == value]
|
|
169
|
+
def find_account_in_catalog(account,catalog):
|
|
170
|
+
return ifListGetSection([txn for txn in make_list(catalog) if account in txn.get('associatedAccounts')])
|
|
171
|
+
|
|
172
|
+
def get_solcatcher_api(endpoint,*args,**kwargs):
|
|
173
|
+
return get_async_response(get_solcatcher_endpoint,endpoint=endpoint,*args,**kwargs)
|
|
174
|
+
def get_balance_info(balanceInfo, programId, authority):
|
|
175
|
+
return next((bal for bal in balanceInfo if programId == bal.get("programId") and authority == bal.get("owner")), {})
|
|
176
|
+
|
|
177
|
+
def get_transfer_info(transfer_instructions, txnData):
|
|
178
|
+
for transfer_instruction in transfer_instructions:
|
|
179
|
+
updated_instruction = get_balance_from_instruction(transfer_instruction, txnData)
|
|
180
|
+
transfer_instruction.update(updated_instruction)
|
|
181
|
+
return transfer_instructions
|
|
182
|
+
|
|
183
|
+
def get_transfer_instructions(txnData,programId=None):
|
|
184
|
+
programId = programId or PUMP_FUN_PROGRAM
|
|
185
|
+
return get_transfer_info(find_in_catalog('Transfer',txnData,programId=programId),txnData)
|
|
186
|
+
|
|
187
|
+
mint = "911eA3wRZ85ZiSTpmCH1hksPGLGgzyVpfMXtJ4zSzVJ5"
|
|
188
|
+
bonding_curve = str(derive_bonding_curve(mint)[0])
|
|
189
|
+
bonding_curve_signature = get_solcatcher_api("getGenesisSignature",account=str(bonding_curve))
|
|
190
|
+
transfers = []
|
|
191
|
+
txnData = get_solcatcher_api("getTransaction",tx_sig=str(bonding_curve_signature))
|
|
192
|
+
txnData = get_transfer_instructions(txnData)
|
|
193
|
+
input(txnData)
|
|
194
|
+
txnData = get_for_program_ids_info(txnData)
|
|
195
|
+
input(txnData)
|
|
196
|
+
|
|
197
|
+
|
|
@@ -1,90 +0,0 @@
|
|
|
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
|
-
from .constants import TOKEN_PROGRAM_ID
|
|
6
|
-
def ifListGetSection(list_obj,i=0):
|
|
7
|
-
if list_obj and isinstance(list_obj,list) and len(list_obj)>i:
|
|
8
|
-
list_obj = list_obj[i]
|
|
9
|
-
return list_obj
|
|
10
|
-
def get_logs_from_index(txnData,index=None):
|
|
11
|
-
if index is not None:
|
|
12
|
-
allLogs = get_log_messages_from_txn(txnData)
|
|
13
|
-
endLog = get_end_log_index(txnData,index)
|
|
14
|
-
return allLogs[index:endLog]
|
|
15
|
-
def get_program_ids(txnData):
|
|
16
|
-
allLogs = get_log_messages_from_txn(txnData)
|
|
17
|
-
return [log.split(' ')[1] for log in allLogs if 'invoke' in log]
|
|
18
|
-
def get_program_id_from_log(logs):
|
|
19
|
-
for log in make_list(logs):
|
|
20
|
-
if 'invoke' in log.lower():
|
|
21
|
-
return log.split(' ')[1]
|
|
22
|
-
def get_stack_height_from_logs(logs):
|
|
23
|
-
for log in make_list(logs):
|
|
24
|
-
if 'invoke' in log.lower():
|
|
25
|
-
return int(log.split(' ')[-1][1:-1])
|
|
26
|
-
def get_end_log_index(txnData,index):
|
|
27
|
-
allLogs = get_log_messages_from_txn(txnData)
|
|
28
|
-
i=0
|
|
29
|
-
for i,log in enumerate(allLogs[index+1:]):
|
|
30
|
-
if 'invoke' in log.lower():
|
|
31
|
-
return index+1+i
|
|
32
|
-
return len(allLogs)
|
|
33
|
-
def get_for_program_ids_info(txnData):
|
|
34
|
-
allLogs = get_log_messages_from_txn(txnData)
|
|
35
|
-
return [{"programId":get_program_id_from_log(allLogs[i]),
|
|
36
|
-
"start":i,
|
|
37
|
-
"end":get_end_log_index(txnData,i),
|
|
38
|
-
'stackHeight':get_stack_height_from_logs(allLogs[i]),
|
|
39
|
-
'events':[event.split(':')[0] for event in get_log_events(get_logs_from_index(txnData,index=i))],
|
|
40
|
-
'logs':get_logs_from_index(txnData,index=i)
|
|
41
|
-
} for i in range(len(allLogs)) if 'invoke' in allLogs[i].lower()]
|
|
42
|
-
def split_log_for_instruction(log):
|
|
43
|
-
return log.split('log:')[-1].split('Instruction:')[-1]
|
|
44
|
-
def clean_split_string(string,delim=' '):
|
|
45
|
-
return delim.join([spl for spl in string.split(' ') if spl])
|
|
46
|
-
def get_log_events(logs=None,index=None):
|
|
47
|
-
return [clean_split_string(split_log_for_instruction(log)) for log in logs if 'log:' in log.lower() or 'instruction:' in log.lower()]
|
|
48
|
-
def get_instruction_accounts(instruction,txnData):
|
|
49
|
-
accounts = get_all_account_keys(txnData)
|
|
50
|
-
return [accounts[index] for index in instruction.get('accounts',[]) if index < len(accounts)]
|
|
51
|
-
def get_instruction_info(instruction,txnData,instruction_index=0):
|
|
52
|
-
|
|
53
|
-
stack_height = instruction.get('stackHeight') or 1
|
|
54
|
-
accounts = instruction.get('accounts',[])
|
|
55
|
-
associatedAccounts = get_instruction_accounts(instruction,txnData)
|
|
56
|
-
instruction_info = {'instruction_index':instruction_index,'accounts':accounts,'associatedAccounts':associatedAccounts,'instructionStackHeight':stack_height}
|
|
57
|
-
|
|
58
|
-
instruction_info.update(get_for_program_ids_info(txnData)[instruction_index])
|
|
59
|
-
return instruction_info
|
|
60
|
-
def process_instructions(instructions,txnData,start_index=1):
|
|
61
|
-
catalog = []
|
|
62
|
-
for i, inst in enumerate(instructions):
|
|
63
|
-
instruction_index = start_index-1 + i
|
|
64
|
-
instruction_info = get_instruction_info(inst,txnData,instruction_index)
|
|
65
|
-
catalog.append(instruction_info)
|
|
66
|
-
return catalog
|
|
67
|
-
def get_instructions_catalog(txnData,printIt=False,saveIt=False):
|
|
68
|
-
instructions = get_instructions_from_txn(txnData)
|
|
69
|
-
outer_instructions_catalog = process_instructions(instructions,txnData)
|
|
70
|
-
inner_instructions = get_inner_instructions_from_txn(txnData)
|
|
71
|
-
if inner_instructions:
|
|
72
|
-
inner_instructions_catalog = process_instructions(inner_instructions,txnData,start_index=len(instructions))
|
|
73
|
-
complete_catalog = outer_instructions_catalog+inner_instructions_catalog
|
|
74
|
-
if printIt:
|
|
75
|
-
pprint.pprint(complete_catalog)
|
|
76
|
-
if saveIt:
|
|
77
|
-
with open(saveIt, 'w') as f:
|
|
78
|
-
json.dump(complete_catalog, f, indent=4)
|
|
79
|
-
return complete_catalog
|
|
80
|
-
|
|
81
|
-
def find_in_catalog(string,txnData,programId=None):
|
|
82
|
-
complete_catalog = get_instructions_catalog(txnData)
|
|
83
|
-
return [txn for txn in complete_catalog if [event for event in txn['events'] if string.lower() in event.lower()]]
|
|
84
|
-
def findKeyValueIdInCatalog(key,value,txnData,programId=None):
|
|
85
|
-
complete_catalog = get_instructions_catalog(txnData)
|
|
86
|
-
if programId:
|
|
87
|
-
complete_catalog = findKeyValueIdInCatalog('programId',programId,txnData)
|
|
88
|
-
return [txn for txn in make_list(complete_catalog) if txn.get(key) == value]
|
|
89
|
-
def find_account_in_catalog(account,catalog):
|
|
90
|
-
return ifListGetSection([txn for txn in make_list(catalog) if account in txn.get('associatedAccounts')])
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from abstract_solana import *
|
|
2
|
-
from spl.token.instructions import create_associated_token_account, get_associated_token_address
|
|
3
|
-
from price_functions import *
|
|
4
|
-
from abstract_solcatcher import *
|
|
5
|
-
def get_solcatcher_api(endpoint,*args,**kwargs):
|
|
6
|
-
return get_async_response(get_solcatcher_endpoint,endpoint=endpoint,*args,**kwargs)
|
|
7
|
-
def get_balance_info(balanceInfo, programId, authority):
|
|
8
|
-
return next((bal for bal in balanceInfo if programId == bal.get("programId") and authority == bal.get("owner")), {})
|
|
9
|
-
|
|
10
|
-
def get_transfer_info(transfer_instructions, txnData):
|
|
11
|
-
for transfer_instruction in transfer_instructions:
|
|
12
|
-
updated_instruction = get_balance_from_instruction(transfer_instruction, txnData)
|
|
13
|
-
transfer_instruction.update(updated_instruction)
|
|
14
|
-
return transfer_instructions
|
|
15
|
-
|
|
16
|
-
def get_transfer_instructions(txnData,programId=None):
|
|
17
|
-
programId = programId or PUMP_FUN_ASSOC_TOKEN_ACC_PROG
|
|
18
|
-
return get_transfer_info(find_in_catalog('transfer',txnData,programId=programId),txnData)
|
|
19
|
-
|
|
20
|
-
mint = "911eA3wRZ85ZiSTpmCH1hksPGLGgzyVpfMXtJ4zSzVJ5"
|
|
21
|
-
bondingCurve = str(derive_bonding_curve(mint))
|
|
22
|
-
#input(getsignaturesforaddress(str(derive_bonding_curve(mint)[0])))
|
|
23
|
-
signature = get_solcatcher_api("getGenesisSignature",account=str(derive_associated_bonding_curve(mint,PUMP_FUN_PROGRAM)[0]))
|
|
24
|
-
txnData = get_solcatcher_api("getTransaction",tx_sig=str(signature))
|
|
25
|
-
input(get_all_account_keys(txnData))
|
|
26
|
-
parsed_txnData=parse_instruction_and_token_balances(txnData)
|
|
27
|
-
input(parsed_txnData)
|
|
28
|
-
input(find_in_catalog('Transfer',parsed_txnData,programId=PUMP_FUN_PROGRAM))
|
|
29
|
-
input(get_transfer_instructions(txnData))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/account_key_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
{abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/genesis_functions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana/signature_data_parse.py
RENAMED
|
File without changes
|
|
File without changes
|
{abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana.egg-info/requires.txt
RENAMED
|
File without changes
|
{abstract_solana-0.0.0.17 → abstract_solana-0.0.0.18}/src/abstract_solana.egg-info/top_level.txt
RENAMED
|
File without changes
|