Last active
February 13, 2024 19:36
-
-
Save ElliotFriend/06d1e93e796845709c245d0a911f6fcd to your computer and use it in GitHub Desktop.
Restore and Extend TTL for all Cakewalk Ledger Entries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
import math | |
from stellar_sdk import xdr, scval, Address, Network, Keypair, SorobanDataBuilder, SorobanServer, TransactionBuilder | |
from stellar_sdk.soroban_rpc import SendTransactionStatus | |
# switch this to True if you want all entries to be bumped (the user-submitted stuff). | |
# otherwise, we'll just bump the contract instance, code, etc. | |
BUMP_EVERYTHING: bool = False | |
cakewalk_contract = 'CB4W5563H62YDM27BK5AVBYVPTFXHRPPMCYIMYHT3CWITCZSY34IO2RJ' | |
server = SorobanServer('https://rpc-futurenet.stellar.org') | |
def divide_list(ops_list: list, n: int): | |
for i in range(0, len(ops_list), n): | |
yield ops_list[i:i + n] | |
# 0. start a list to collect the ledger keys | |
ledger_keys_list: list[xdr.LedgerKey] = [] | |
# 1. get the authors entry | |
authors_ledger_key = xdr.LedgerKey( | |
type=xdr.LedgerEntryType.CONTRACT_DATA, | |
contract_data=xdr.LedgerKeyContractData( | |
contract=Address(cakewalk_contract).to_xdr_sc_address(), | |
key=scval.to_vec([scval.to_symbol('Authors')]), | |
durability=xdr.ContractDataDurability.PERSISTENT | |
) | |
) | |
authors_ledger_entry = xdr.LedgerEntryData.from_xdr(server.get_ledger_entries([ | |
authors_ledger_key, | |
]).entries[0].xdr) | |
# 2. for each author: | |
for author in authors_ledger_entry.contract_data.val.map.sc_map: | |
author_key = author.key.u32.uint32 | |
author_val = author.val.str.sc_string.decode() | |
# 2a. create the Key::Picture(picture.number) entry | |
ledger_keys_list.append(xdr.LedgerKey( | |
type=xdr.LedgerEntryType.CONTRACT_DATA, | |
contract_data=xdr.LedgerKeyContractData( | |
contract=Address(cakewalk_contract).to_xdr_sc_address(), | |
key=scval.to_vec([ | |
scval.to_symbol('Picture'), | |
scval.to_uint32(author_key), | |
]), | |
durability=xdr.ContractDataDurability.PERSISTENT | |
) | |
)) | |
# 2b. create the Key::Owner(picture.number) entry | |
ledger_keys_list.append(xdr.LedgerKey( | |
type=xdr.LedgerEntryType.CONTRACT_DATA, | |
contract_data=xdr.LedgerKeyContractData( | |
contract=Address(cakewalk_contract).to_xdr_sc_address(), | |
key=scval.to_vec([ | |
scval.to_symbol('Owner'), | |
scval.to_uint32(author_key), | |
]), | |
durability=xdr.ContractDataDurability.PERSISTENT | |
) | |
)) | |
# 2c. create the Key::Author(picture.author.clone()) entry | |
ledger_keys_list.append(xdr.LedgerKey( | |
type=xdr.LedgerEntryType.CONTRACT_DATA, | |
contract_data=xdr.LedgerKeyContractData( | |
contract=Address(cakewalk_contract).to_xdr_sc_address(), | |
key=scval.to_vec([ | |
scval.to_symbol('Author'), | |
scval.to_string(author_val), | |
]), | |
durability=xdr.ContractDataDurability.PERSISTENT | |
) | |
)) | |
# 3. build a restore footprint tx | |
# Public Key: GDNLBT7EG7ZULV7HHSLBFYBGBIJ5ZWLQDBZWADTFTE6FLPGTB673X5KK | |
kp = Keypair.from_secret('SC45LMFHDV2HTFMN5SXR75ERK24K4ZZD5CVUIUPSA7C6EOWWWW6X5A57') | |
account = server.load_account(kp.public_key) | |
if BUMP_EVERYTHING: | |
print(f"attempting to restore {len(ledger_keys_list)} ledger entries (20 at a time) = {math.ceil(len(ledger_keys_list) / 20)} transactions") | |
for keys_list in divide_list(ledger_keys_list, 20): | |
restore_tx = ( | |
TransactionBuilder( | |
source_account=account, | |
network_passphrase=Network.FUTURENET_NETWORK_PASSPHRASE, | |
base_fee=10000, | |
) | |
.append_restore_footprint_op() | |
.set_soroban_data( | |
SorobanDataBuilder() | |
.set_read_write(keys_list) | |
.build() | |
) | |
.set_timeout(300) | |
.build() | |
) | |
# simulate, sign, and send the transaction | |
prepped_tx = server.prepare_transaction(restore_tx) | |
prepped_tx.sign(kp) | |
resp = server.send_transaction(prepped_tx) | |
print(resp) | |
# simple loop to account for if the response is `TRY_AGAIN_LATER` | |
while resp.status != SendTransactionStatus.PENDING: | |
resp = server.send_transaction(prepped_tx) | |
print(resp) | |
time.sleep(10) | |
# wait a few seconds so the transaction can settle | |
time.sleep(10) | |
# 4. build an extend ttl tx | |
print(f"attempting to extend_ttl on {len(ledger_keys_list)} ledger entries (40 at a time) = {math.ceil(len(ledger_keys_list) / 40)} transactions") | |
for keys_list in divide_list(ledger_keys_list, 40): | |
extend_tx = ( | |
TransactionBuilder( | |
source_account=account, | |
network_passphrase=Network.FUTURENET_NETWORK_PASSPHRASE, | |
base_fee=10000, | |
) | |
.append_extend_footprint_ttl_op( | |
extend_to=3110399 | |
) | |
.set_soroban_data( | |
SorobanDataBuilder() | |
.set_read_only(keys_list) | |
.build() | |
) | |
.set_timeout(300) | |
.build() | |
) | |
# simulate, sign, and send the transaction | |
prepped_tx = server.prepare_transaction(extend_tx) | |
prepped_tx.sign(kp) | |
resp = server.send_transaction(prepped_tx) | |
print(resp) | |
# simple loop to account for if the response is `TRY_AGAIN_LATER` | |
while resp.status != SendTransactionStatus.PENDING: | |
resp = server.send_transaction(prepped_tx) | |
print(resp) | |
time.sleep(10) | |
# wait a few seconds so the transaction can settle | |
time.sleep(10) | |
# 5. we may as well extend the contract instance and code while we're here | |
# 5a. create the contract instance ledger key | |
contract_instance_ledger_key = xdr.LedgerKey( | |
type=xdr.LedgerEntryType.CONTRACT_DATA, | |
contract_data=xdr.LedgerKeyContractData( | |
contract=Address(cakewalk_contract).to_xdr_sc_address(), | |
key=xdr.SCVal(type=xdr.SCValType.SCV_LEDGER_KEY_CONTRACT_INSTANCE), | |
durability=xdr.ContractDataDurability.PERSISTENT, | |
) | |
) | |
# 5b. use the instance entry to create the code ledger key | |
contract_instance_ledger_entry = server.get_ledger_entries([ | |
contract_instance_ledger_key, | |
]) | |
# print(contract_instance_ledger_entry.entries[0].xdr) | |
contract_code_wasm_hash = xdr.LedgerEntryData.from_xdr( | |
contract_instance_ledger_entry.entries[0].xdr | |
).contract_data.val.instance.executable.wasm_hash | |
contract_code_ledger_key = xdr.LedgerKey( | |
type=xdr.LedgerEntryType.CONTRACT_CODE, | |
contract_code=xdr.LedgerKeyContractCode( | |
hash=contract_code_wasm_hash | |
) | |
) | |
# 5c. add both the instance and code keys to a transaction to extend the ttl | |
instance_extend_tx = ( | |
TransactionBuilder( | |
source_account=account, | |
network_passphrase=Network.FUTURENET_NETWORK_PASSPHRASE, | |
base_fee=10000, | |
) | |
.append_extend_footprint_ttl_op( | |
extend_to=3110399 | |
) | |
.set_soroban_data( | |
SorobanDataBuilder() | |
.set_read_only([ | |
contract_instance_ledger_key, | |
contract_code_ledger_key, | |
authors_ledger_key, | |
]) | |
.build() | |
) | |
.set_timeout(300) | |
.build() | |
) | |
# simulate, sign, and send the transaction | |
prepped_tx = server.prepare_transaction(instance_extend_tx) | |
prepped_tx.sign(kp) | |
resp = server.send_transaction(prepped_tx) | |
print(resp) | |
# simple loop to account for if the response is `TRY_AGAIN_LATER` | |
while resp.status != SendTransactionStatus.PENDING: | |
resp = server.send_transaction(prepped_tx) | |
print(resp) | |
time.sleep(10) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment