Skip to content

Instantly share code, notes, and snippets.

@Smephite
Last active February 12, 2022 05:59
Show Gist options
  • Save Smephite/03233213ce42d1352c83247426b72988 to your computer and use it in GitHub Desktop.
Save Smephite/03233213ce42d1352c83247426b72988 to your computer and use it in GitHub Desktop.
Use this script to claim all sellable tokens offered to you by claimable balances. Now uses ^6.0.0b
from stellar_sdk import Server, Keypair, TransactionBuilder, Network
import stellar_sdk
from stellar_sdk.asset import Asset
from stellar_sdk.operation.create_claimable_balance import ClaimPredicate
from stellar_sdk.operation.path_payment_strict_send import PathPaymentStrictSend
from stellar_sdk.signer import Signer
import datetime, decimal
print(f"Using stellar SDK v{stellar_sdk.__version__}")
keypair = Keypair.from_secret(input("Please enter your secret key: "))
server = Server('https://horizon.stellar.org')
base_fee = server.fetch_base_fee()
acc = server.load_account(keypair.public_key)
balances = server.claimable_balances().for_claimant(keypair.public_key).call()['_embedded']['records']
pending_assets = []
tx = TransactionBuilder(source_account=acc, network_passphrase=Network.PUBLIC_NETWORK_PASSPHRASE, base_fee=base_fee*10)
# base fee is bidding system, we most likely will not pay more then the {base_fee}
operations = 0
for balance in balances:
if operations > 96:
print("This iteration reached the maximum transaction size. Please run the script again to claim any tokens left.")
break
asset = balance['asset'].split(':')
asset = Asset(asset[0], asset[1])
amount = balance['amount']
id = balance['id']
pending_assets.append({'asset': asset, 'amount': amount, 'id': id})
claimants = balance['claimants']
predicate = next(filter(lambda x: x['destination'] == acc.universal_account_id, claimants))['predicate']
if 'unconditional' not in predicate or not predicate['unconditional']:
if 'abs_before' in predicate :
date = datetime.datetime.strptime(predicate['abs_before'], '%Y-%m-%dT%H:%M:%SZ')
if date < datetime.datetime.now():
print(f"{asset.code} was only claimable until {date}")
continue
asset_info = server.strict_send_paths(source_amount=amount, source_asset=asset, destination=[Asset.native()]).call()
available_paths = asset_info['_embedded']['records']
max_path = max(available_paths, key=lambda path: path['destination_amount'], default=None)
if max_path is None:
print(f"Could not find path for {asset.code}")
continue
native_amount = decimal.Decimal(max_path['destination_amount'])
tx_cost = decimal.Decimal(4*base_fee)/10000000
if native_amount < tx_cost:
print(f"The amount gained by this token ({native_amount}) is less then the base fee ({tx_cost}) required to claim it.")
continue
print(f"{max_path['source_asset_code']} -> {max_path['destination_asset_type']}: {max_path['source_amount']} :: {native_amount}")
if len(max_path['path']) != 0:
print(f"{max_path}")
max_path['path'] = list(map(lambda val: Asset(val.asset_code, val.asset_issuer), max_path['path']))
tx = tx.append_change_trust_op(asset)
tx = tx.append_claim_claimable_balance_op(balance_id=id)
tx = tx.append_operation(PathPaymentStrictSend(
destination=acc.universal_account_id,
send_asset=asset,
send_amount=amount,
dest_min=native_amount,
dest_asset=Asset.native(),
path=max_path['path']
))
tx = tx.append_change_trust_op(asset, "0")
operations += 4
if operations == 0:
print("No claimable token was found...")
exit()
tx = tx.build()
tx.sign(keypair)
print(tx.to_xdr())
if input("Enter `y` to execute this transaction on pubnet: ") == "y":
print(server.submit_transaction(tx))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment