Skip to content

Commit

Permalink
add async
Browse files Browse the repository at this point in the history
  • Loading branch information
dangell7 committed Feb 2, 2024
1 parent e5c8420 commit ce81044
Show file tree
Hide file tree
Showing 14 changed files with 1,266 additions and 2 deletions.
103 changes: 103 additions & 0 deletions hooks_toolkit/asyncio_set_hook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env python
# coding: utf-8

from typing import List, Dict, Any

from xrpl.clients.sync_client import SyncClient
from xrpl.wallet import Wallet
from xrpl.models.transactions import SetHook
from xrpl.models.transactions.set_hook import Hook
from xrpl.utils import calculate_hook_on
from xrpl.models.transactions import SetHookFlag

from hooks_toolkit.libs.asyncio.xrpl_helpers.transaction import (
get_transaction_fee,
app_transaction,
)
from hooks_toolkit.utils import hex_namespace, read_hook_binary_hex_from_ns
from hooks_toolkit.types import SetHookParams


def create_hook_payload(
params: SetHookParams,
) -> Hook:
kwargs: Dict[str, Any] = {
"hook_api_version": params.version,
"hook_namespace": hex_namespace(params.namespace),
}

if params.create_file is not None:
kwargs["create_code"] = read_hook_binary_hex_from_ns(params.create_file)

if params.hook_on_array is not None:
kwargs["hook_on"] = calculate_hook_on(params.hook_on_array)

if params.hook_hash is not None:
kwargs["hook_hash"] = params.hook_hash

if params.flags is not None:
kwargs["flags"] = params.flags

if params.hook_parameters is not None:
kwargs["hook_parameters"] = params.hook_parameters

if params.hook_grants is not None:
kwargs["hook_grants"] = params.hook_grants

return Hook(**kwargs)


async def set_hooks_v3(client: SyncClient, seed: str, hooks: List[Hook]):
HOOK_ACCOUNT = Wallet(seed, 0)
_tx = SetHook(
account=HOOK_ACCOUNT.classic_address,
hooks=hooks,
)
tx = SetHook(
account=HOOK_ACCOUNT.classic_address,
hooks=hooks,
fee=await get_transaction_fee(client, _tx),
)

await app_transaction(
client, tx, HOOK_ACCOUNT, hard_fail=True, count=2, delay_ms=1000
)


async def clear_all_hooks_v3(client: SyncClient, seed: str):
HOOK_ACCOUNT = Wallet(seed, 0)
hook = Hook(
**{
"create_code": "",
"flags": [SetHookFlag.HSF_OVERRIDE, SetHookFlag.HSF_NS_DELETE],
}
)
_tx = SetHook(
account=HOOK_ACCOUNT.classic_address,
hooks=[hook, hook, hook, hook, hook, hook, hook, hook, hook, hook],
)
tx = SetHook(
account=HOOK_ACCOUNT.classic_address,
hooks=[hook, hook, hook, hook, hook, hook, hook, hook, hook, hook],
fee=await get_transaction_fee(client, _tx),
)

await app_transaction(
client, tx, HOOK_ACCOUNT, hard_fail=True, count=2, delay_ms=1000
)


async def clear_hook_state_v3(client: SyncClient, seed: str, hooks: List[Hook]):
HOOK_ACCOUNT = Wallet(seed, 0)
_tx = SetHook(
account=HOOK_ACCOUNT.classic_address,
hooks=hooks,
)
tx = SetHook(
account=HOOK_ACCOUNT.classic_address,
hooks=hooks,
fee=await get_transaction_fee(client, _tx),
)
await app_transaction(
client, tx, HOOK_ACCOUNT, hard_fail=True, count=2, delay_ms=1000
)
32 changes: 32 additions & 0 deletions hooks_toolkit/asyncio_xrpld.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python
# coding: utf-8

from typing import Any
from xrpl.clients import Client

from hooks_toolkit.libs.asyncio.xrpl_helpers.transaction import app_transaction

from hooks_toolkit.types import SmartContractParams
from hooks_toolkit.libs.keylet_utils import ExecutionUtility


class Xrpld:
@staticmethod
async def submit(client: Client, params: SmartContractParams) -> Any:
# validate(built_tx)
tx_response = await app_transaction(
client,
params.tx,
params.wallet,
hard_fail=True,
count=1,
delay_ms=1000,
)
tx_result = tx_response.result.get("meta")["TransactionResult"]
if tx_result == "tecHOOK_REJECTED":
hook_executions = ExecutionUtility.get_hook_executions_from_meta(
client,
tx_response.result.get("meta"),
)
raise ValueError(hook_executions.executions[0].HookReturnString)
return tx_response.result
11 changes: 11 additions & 0 deletions hooks_toolkit/libs/asyncio/keylet_utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from hooks_toolkit.libs.keylet_utils.execution_utility import (
ExecutionUtility,
)
from hooks_toolkit.libs.keylet_utils.state_utility import (
StateUtility,
)

__all__ = [
"ExecutionUtility",
"StateUtility",
]
78 changes: 78 additions & 0 deletions hooks_toolkit/libs/asyncio/keylet_utils/execution_utility.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env python
# coding: utf-8

from typing import List

from xrpl.asyncio.clients import AsyncWebsocketClient
from xrpl.models import TransactionMetadata
from xrpl.models.transactions.metadata import (
HookExecution,
HookExecutionFields,
HookEmission,
HookEmissionFields,
)
from xrpl.models.requests import Tx
from xrpl.utils.str_conversions import hex_to_str


class iHookExecution:
def __init__(self, hook_execution: HookExecutionFields):
self.HookAccount = hook_execution["HookAccount"]
self.HookEmitCount = hook_execution["HookEmitCount"]
self.HookExecutionIndex = hook_execution["HookExecutionIndex"]
self.HookHash = hook_execution["HookHash"]
self.HookInstructionCount = hook_execution["HookInstructionCount"]
self.HookResult = hook_execution["HookResult"]
self.HookReturnCode = hook_execution["HookReturnCode"]
self.HookReturnString = hex_to_str(hook_execution["HookReturnString"]).replace(
"\x00", ""
)
self.HookStateChangeCount = hook_execution["HookStateChangeCount"]
self.Flags = hook_execution["Flags"]


class iHookEmission:
def __init__(self, hook_emission: HookEmissionFields):
self.EmittedTxnID = hook_emission["EmittedTxnID"]
self.HookAccount = hook_emission["HookAccount"]
self.HookHash = hook_emission["HookHash"]
self.EmitNonce = hook_emission["EmitNonce"]


class iHookExecutions:
def __init__(self, results: List[HookExecution]):
self.executions = [iHookExecution(entry["HookExecution"]) for entry in results]


class iHookEmissions:
def __init__(self, results: List[HookEmission]):
self.txs = [iHookEmission(entry["HookEmission"]) for entry in results]


class ExecutionUtility:
@staticmethod
async def get_hook_executions_from_meta(meta: TransactionMetadata):
if not meta["HookExecutions"]:
raise Exception("No HookExecutions found")

return iHookExecutions(meta["HookExecutions"])

@staticmethod
async def get_hook_executions_from_tx(client: AsyncWebsocketClient, hash: str):
if not client.is_open():
raise Exception("xrpl Client is not connected")

tx_response = await client.request(Tx(transaction=hash))

hook_executions = tx_response.result.get("meta", {}).get("HookExecutions")
if not hook_executions:
raise Exception("No HookExecutions found")

return iHookExecutions(hook_executions)

@staticmethod
async def get_hook_emitted_txs_from_meta(meta: TransactionMetadata):
if not meta["HookEmissions"]:
raise Exception("No HookEmissions found")

return iHookEmissions(meta["HookEmissions"])
57 changes: 57 additions & 0 deletions hooks_toolkit/libs/asyncio/keylet_utils/state_utility.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from xrpl.asyncio.clients import AsyncWebsocketClient
from xrpl.models.requests import LedgerEntry
from xrpl.models.requests.ledger_entry import Hook, HookDefinition, HookState
from xrpl.models.requests.account_namespace import AccountNamespace


class StateUtility:
@staticmethod
async def get_hook(client: AsyncWebsocketClient, account: str) -> Hook:
if not client.is_open():
raise Exception("xrpl Client is not connected")
hook_req = LedgerEntry(
hook={
"account": account,
},
)
hook_res = await client.request(hook_req)
return hook_res.result["node"]

@staticmethod
async def get_hook_definition(
client: AsyncWebsocketClient, hash: str
) -> HookDefinition:
if not client.is_open():
raise Exception("xrpl Client is not connected")
hook_def_request = LedgerEntry(
hook_definition=hash,
)
hook_def_res = await client.request(hook_def_request)
return hook_def_res.result["node"]

@staticmethod
async def get_hook_state_dir(
client: AsyncWebsocketClient, account: str, namespace: str
):
if not client.is_open():
raise Exception("xrpl Client is not connected")
response = await client.request(
AccountNamespace(account=account, namespace_id=namespace)
)
return response.result["namespace_entries"]

@staticmethod
async def get_hook_state(
client: AsyncWebsocketClient, account: str, key: str, namespace: str
) -> HookState:
if not client.is_open():
raise Exception("xrpl Client is not connected")
hook_state_req = LedgerEntry(
hook_state={
"account": account,
"key": key,
"namespace_id": namespace,
},
)
hook_state_resp = await client.request(hook_state_req)
return hook_state_resp.result["node"]
Empty file.
81 changes: 81 additions & 0 deletions hooks_toolkit/libs/asyncio/xrpl_helpers/fund_system.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env python
# coding: utf-8

from typing import List

from xrpl.asyncio.clients import Client
from xrpl.wallet import Wallet
from xrpl.models.amounts import IssuedCurrencyAmount

from hooks_toolkit.libs.asyncio.xrpl_helpers.tools import (
Account,
ICXRP,
balance,
fund,
account_set,
limit,
trust,
pay,
)


async def fund_system(
client: Client,
wallet: Wallet,
ic: IssuedCurrencyAmount,
native_balance: int,
ic_limit: int,
ic_balance: int,
) -> None:
user_accounts = [
"alice",
"bob",
"carol",
"dave",
"elsa",
"frank",
"grace",
"heidi",
"ivan",
"judy",
]
user_wallets: List[Account] = [Account(acct) for acct in user_accounts]
hook_accounts = [
"hook1",
"hook2",
"hook3",
"hook4",
"hook5",
]
hook_wallets: List[Account] = [Account(hacct) for hacct in hook_accounts]

USD = ic

gw: Account = Account("gw")
if await balance(client, gw.wallet.classic_address) == 0:
await fund(client, wallet, ICXRP(native_balance), gw.wallet.classic_address)
await account_set(client, gw.wallet)

needs_funding = []
needs_lines = []
needs_ic = []

for acct in user_wallets:
if await balance(client, acct.wallet.classic_address) < (native_balance / 2):
needs_funding.append(acct.wallet.classic_address)
if await limit(client, acct.wallet.classic_address, USD) < (ic_limit / 2):
needs_lines.append(acct.wallet)
if await balance(client, acct.wallet.classic_address, USD) < (ic_balance / 2):
needs_ic.append(acct.wallet.classic_address)

for hacct in hook_wallets:
if await balance(client, hacct.wallet.classic_address) < (native_balance / 2):
needs_funding.append(hacct.wallet.classic_address)

print(f"FUNDING: {len(needs_funding)}")
print(f"TRUSTING: {len(needs_lines)}")
print(f"PAYING: {len(needs_ic)}")

await fund(client, wallet, ICXRP(native_balance), *needs_funding)
await trust(client, USD.set(ic_limit), *needs_lines)
await pay(client, USD.set(ic_balance), gw.wallet, *needs_ic)
Loading

0 comments on commit ce81044

Please sign in to comment.