|
| 1 | +"""A script that sends loyalty rewards (based on certain rules) to a pool's delegators in one transaction""" |
| 2 | + |
| 3 | +from blockfrost import BlockFrostApi, ApiUrls |
| 4 | + |
| 5 | +from pycardano import * |
| 6 | + |
| 7 | +# ======= Modify variables below ======== |
| 8 | + |
| 9 | +network = Network.MAINNET |
| 10 | + |
| 11 | +BLOCK_FROST_PROJECT_ID = "your_project_id" |
| 12 | + |
| 13 | +POOL_ID = "your_pool_id" |
| 14 | + |
| 15 | +POOL_TICKER = "your_pool_ticker" |
| 16 | + |
| 17 | +# An address where any changes will be returned to |
| 18 | +CHANGE_ADDRESS = "your_change_address" |
| 19 | + |
| 20 | +# If you want to exclude any address (e.g. your own address), include those in the variable below |
| 21 | +EXCLUDE_ADDRESSES = [] |
| 22 | + |
| 23 | +# The payment key used to generate sender address |
| 24 | +PAYMENT_KEY_PATH = "payment.skey" |
| 25 | + |
| 26 | +# ======= Modify variables above ======== |
| 27 | + |
| 28 | + |
| 29 | +# Read keys to memory |
| 30 | +# Assume there is a payment.skey file sitting in current directory |
| 31 | +psk = PaymentSigningKey.load(PAYMENT_KEY_PATH) |
| 32 | +pvk = PaymentVerificationKey.from_signing_key(psk) |
| 33 | + |
| 34 | +# Derive an address from payment verification key |
| 35 | +input_address = Address(pvk.hash(), network=network) |
| 36 | +print(f"ADA will be distributed from this address: {input_address}, make sure there are enough ADA in it.") |
| 37 | + |
| 38 | +# Create a BlockFrost chain context |
| 39 | +context = BlockFrostChainContext(BLOCK_FROST_PROJECT_ID, network) |
| 40 | + |
| 41 | +api = BlockFrostApi(BLOCK_FROST_PROJECT_ID, ApiUrls.mainnet.value) |
| 42 | + |
| 43 | +delegators = api.pool_delegators(POOL_ID, gather_pages=True) |
| 44 | + |
| 45 | +to_send_50 = [] |
| 46 | +to_send_10 = [] |
| 47 | + |
| 48 | +for delegator in delegators: |
| 49 | + if delegator.address not in EXCLUDE_ADDRESSES: |
| 50 | + if int(delegator.live_stake) >= 100000000000: |
| 51 | + to_send_50.append(delegator) |
| 52 | + elif int(delegator.live_stake) >= 10000000000: |
| 53 | + to_send_10.append(delegator) |
| 54 | + |
| 55 | +builder = TransactionBuilder(context) |
| 56 | + |
| 57 | +builder.add_input_address(input_address) |
| 58 | + |
| 59 | +# ======= Business logic starts ======== |
| 60 | + |
| 61 | +# Send 50 ADA to delegators with 100K+ ADA |
| 62 | +for d in to_send_50: |
| 63 | + to_send_addr = api.account_addresses(d.address)[0].address |
| 64 | + builder.add_output(TransactionOutput.from_primitive([to_send_addr, 50000000])) |
| 65 | + |
| 66 | +# Send 10 ADA to delegators with 10K+ ADA |
| 67 | +for d in to_send_10: |
| 68 | + to_send_addr = api.account_addresses(d.address)[0].address |
| 69 | + builder.add_output(TransactionOutput.from_primitive([to_send_addr, 10000000])) |
| 70 | + |
| 71 | +# ======= Business logic ends ======== |
| 72 | + |
| 73 | +auxiliary_data = AuxiliaryData(AlonzoMetadata(metadata=Metadata({ |
| 74 | + 674: { |
| 75 | + "Title": f"Loyalty rewards for stake pool [{POOL_TICKER}] delegators", |
| 76 | + "Rules": { |
| 77 | + "100K+": "50 ADA", |
| 78 | + "10K+": "10 ADA" |
| 79 | + }, |
| 80 | + "Notes": "Created with https://github.com/cffls/pycardano." |
| 81 | + } |
| 82 | +}))) |
| 83 | + |
| 84 | +builder.auxiliary_data = auxiliary_data |
| 85 | + |
| 86 | +tx_body = builder.build(change_address=Address.from_primitive(CHANGE_ADDRESS)) |
| 87 | + |
| 88 | +# Sign the transaction body hash using the payment signing key |
| 89 | +signature = psk.sign(tx_body.hash()) |
| 90 | + |
| 91 | +# Add verification key and the signature to the witness set |
| 92 | +vk_witnesses = [VerificationKeyWitness(pvk, signature)] |
| 93 | + |
| 94 | +# Create final signed transaction |
| 95 | +signed_tx = Transaction(tx_body, TransactionWitnessSet(vkey_witnesses=vk_witnesses), |
| 96 | + auxiliary_data=auxiliary_data) |
| 97 | + |
| 98 | +# Submit signed transaction to the network |
| 99 | +print(signed_tx) |
| 100 | + |
| 101 | +print("#### Transaction id ####") |
| 102 | +print(tx_body.hash().hex()) |
| 103 | +context.submit_tx(signed_tx.to_cbor()) |
| 104 | +print("Transaction successfully submitted!") |
0 commit comments