Skip to content

Instantly share code, notes, and snippets.

@ElliotFriend
Last active February 13, 2024 19:36
Show Gist options
  • Save ElliotFriend/06d1e93e796845709c245d0a911f6fcd to your computer and use it in GitHub Desktop.
Save ElliotFriend/06d1e93e796845709c245d0a911f6fcd to your computer and use it in GitHub Desktop.
Restore and Extend TTL for all Cakewalk Ledger Entries
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