Skip to content

Instantly share code, notes, and snippets.

@FrankC01
Created August 23, 2025 09:47
Show Gist options
  • Select an option

  • Save FrankC01/8ccf532db795fe161635e1a3d0a45595 to your computer and use it in GitHub Desktop.

Select an option

Save FrankC01/8ccf532db795fe161635e1a3d0a45595 to your computer and use it in GitHub Desktop.
Hayes 402 General
#
"""."""
import dataclasses
from enum import IntEnum
from typing import Any
from pysui import SyncClient, SuiAddress, SuiRpcResult, SuiConfig
from pysui.sui.sui_txn import SyncTransaction
from pysui.sui.sui_builders.get_builders import GetCoins
from pysui.sui.sui_bcs.bcs import Argument
from pysui.sui.sui_txresults.single_tx import SuiCoinObject
class Schemes:
a = 1
b = 2
c = 3
@dataclasses.dataclass
class PaymentRequirements:
scheme: Schemes | None = None
max_amount_required: int | None = None
resource: str | None = None
description: str | None = None
asset: str | None = None
pay_to: str
network: str | None = None
def get_non_sui_coin(
txer: SyncTransaction, *, sender: SuiAddress, coin_type: str, amount_required: int
) -> SuiCoinObject:
"""."""
# Fetch the type coins
coin_data: list[SuiCoinObject] = []
# Using paging
q_res = txer.client.execute(GetCoins(owner=sender, coin_type=coin_type))
while q_res.is_ok() and q_res.result_data.data:
coin_data.extend(q_res.result_data.data)
if q_res.result_data.next_cursor:
q_res = txer.client.execute(
GetCoins(
owner=sender,
coin_type=coin_type,
cursor=q_res.result_data.next_cursor,
)
)
else:
break
if not coin_data:
raise Exception(f"No coins of type {coin_type} found for address {sender}")
# Check with coins we achieve amount_required
total_balance = sum(int(coin.balance) for coin in coin_data)
if total_balance < amount_required:
raise Exception(
f"Insufficient balance. Required: {amount_required}, Available: {total_balance}"
)
main_coin: Argument | SuiCoinObject
# First see if there is one coin that satisfies
if main_coin := next(
filter(lambda x: int(x.balance) >= amount_required, coin_data),
None,
):
pass
# Else merge and split
else:
# We know there is not a singular yet the total meets criteria
# so marge the list
target_coin: SuiCoinObject = coin_data[0]
txer.merge_coins(merge_to=main_coin, merge_from=coin_data[1:])
main_coin = txer.split_coin(coin=target_coin, amounts=[amount_required])
return main_coin
def create_transfer_transaction(
client: SyncClient,
*,
requirements: PaymentRequirements,
sender: SuiAddress | None = None,
) -> SyncTransaction:
"""."""
sender = sender or client.config.active_address
txer: SyncTransaction = client.transaction(initial_sender=sender)
coin_to_send: Argument | SuiCoinObject = None
if requirements.asset.endswith("SUI"):
coin_to_send = txer.split_coin(
coin=txer.gas, amounts=[requirements.max_amount_required]
)
else:
coin_to_send = get_non_sui_coin(
client,
coin_type=requirements.asset,
sender=sender,
amount_required=requirements.max_amount_required,
)
txer.transfer_objects(transfers=[coin_to_send], recipient=requirements.pay_to)
def create_and_sign_payment(
client: SyncClient, *, sender: SuiAddress, requirements: PaymentRequirements
) -> tuple[str, str]:
"""."""
txer = create_transfer_transaction(client, requirements=requirements, sender=sender)
base64_txn_str = txer.deferred_execution()
signature = (
txer.signer_block.get_signatures(client=client, tx_bytes=base64_txn_str)
.array[0]
.signature
)
return base64_txn_str, signature
def main():
"""."""
faux_requirements = PaymentRequirements()
wallet_config = SuiConfig.default_config()
tx_bytes, signature = create_and_sign_payment(
SyncClient(config=wallet_config),
sender=wallet_config.active_address,
requirements=faux_requirements,
)
print(f"Base64 tx_bytes: {tx_bytes}\nSignature: {signature}")
if __name__ == "__main__":
try:
main()
except Exception as ve:
print(ve)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment