-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from SCMusson/minting_tests
Minting tests (WIP)
- Loading branch information
Showing
6 changed files
with
226 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from opshin.prelude import * | ||
|
||
|
||
def assert_minting_purpose(context: ScriptContext) -> None: | ||
purpose = context.purpose | ||
if isinstance(purpose, Minting): | ||
is_minting = True | ||
else: | ||
is_minting = False | ||
assert is_minting, "not minting purpose" | ||
|
||
|
||
def assert_signed(pkh: PubKeyHash, context: ScriptContext) -> None: | ||
assert pkh in context.tx_info.signatories, "missing signature" | ||
|
||
|
||
def validator(pkh: PubKeyHash, redeemer: None, context: ScriptContext) -> None: | ||
assert_minting_purpose(context) | ||
assert_signed(pkh, context) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import pathlib | ||
from opshin import build | ||
import cbor2 | ||
import pycardano | ||
from pycardano import ChainContext | ||
from plutus_bench.tool import load_contract, ScriptType, address_from_script | ||
|
||
own_path = pathlib.Path(__file__) | ||
|
||
|
||
def mint_coin_with_contract( | ||
token_name: str, | ||
amount: int, | ||
issuer_signing_key: pycardano.PaymentSigningKey, | ||
required_key: pycardano.PaymentVerificationKey, | ||
context: ChainContext, | ||
): | ||
network = context.network | ||
|
||
tn_bytes = bytes(token_name, encoding="utf-8") | ||
|
||
VerificationKey = pycardano.PaymentVerificationKey.from_signing_key( | ||
issuer_signing_key | ||
) | ||
payment_address = pycardano.Address( | ||
payment_part=VerificationKey.hash(), network=network | ||
) | ||
|
||
# get input utxo | ||
utxo_to_spend_or_burn = None | ||
if amount > 0: | ||
for utxo in context.utxos(payment_address): | ||
if utxo.output.amount.coin > 3_000_000: | ||
utxo_to_spend_or_burn = utxo | ||
break | ||
else: | ||
|
||
def f(pi: pycardano.ScriptHash, an: pycardano.AssetName, a: int) -> bool: | ||
return pi == script_hash and an.payload == tn_bytes and a >= -amount | ||
|
||
for utxo in context.utxos(payment_address): | ||
if utxo.output.amount.multi_asset.count(f): | ||
utxo_to_spend_or_burn = utxo | ||
assert utxo_to_spend_or_burn is not None, "UTxO not found to spend!" | ||
|
||
# Build script | ||
mint_script_path = own_path.parent / "contracts" / "signed_mint.py" | ||
pkh = required_key.hash() | ||
plutus_script = build(mint_script_path, pkh) | ||
|
||
script_hash = pycardano.plutus_script_hash(plutus_script) | ||
|
||
# Build the transaction | ||
builder = pycardano.TransactionBuilder(context) | ||
builder.add_minting_script(script=plutus_script, redeemer=pycardano.Redeemer(0)) | ||
builder.mint = pycardano.MultiAsset.from_primitive( | ||
{bytes(script_hash): {tn_bytes: amount}} | ||
) | ||
builder.add_input(utxo_to_spend_or_burn) | ||
if amount > 0: | ||
# if not burning | ||
builder.add_output( | ||
pycardano.TransactionOutput( | ||
payment_address, | ||
amount=pycardano.Value(coin=amount, multi_asset=builder.mint), | ||
) | ||
) | ||
# builder.required_signers = [VerificationKey,] | ||
|
||
# sign the transation | ||
signed_tx = builder.build_and_sign( | ||
signing_keys=[ | ||
issuer_signing_key, | ||
], | ||
change_address=payment_address, | ||
auto_required_signers=True, | ||
) | ||
|
||
context.submit_tx(signed_tx) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import pathlib | ||
|
||
import pycardano | ||
import pytest | ||
from pycardano import TransactionFailedException | ||
|
||
from plutus_bench import MockChainContext, MockUser | ||
from plutus_bench.mock import MockFrostApi | ||
|
||
from tests.mint import mint_coin_with_contract | ||
from plutus_bench.tool import address_from_script, load_contract, ScriptType | ||
|
||
own_path = pathlib.Path(__file__) | ||
|
||
|
||
def test_mint_contract(): | ||
api = MockFrostApi() | ||
context = MockChainContext(api=api) | ||
minting_user = MockUser(api) | ||
minting_user.fund(100_000_000) | ||
|
||
mint_coin_with_contract( | ||
"My_token", | ||
100, | ||
minting_user.signing_key, | ||
minting_user.verification_key, | ||
context, | ||
) | ||
|
||
|
||
def test_wrong_signature_mint_contract(): | ||
api = MockFrostApi() | ||
context = MockChainContext(api=api) | ||
minting_user = MockUser(api) | ||
minting_user.fund(100_000_000) | ||
|
||
other_user = MockUser(api) | ||
pytest.raises( | ||
TransactionFailedException, | ||
mint_coin_with_contract, | ||
"My_token", | ||
100, | ||
minting_user.signing_key, | ||
other_user.verification_key, | ||
context, | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
test_mint_contract() | ||
test_wrong_signature_mint_contract() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import pathlib | ||
from multiprocessing import Process | ||
from time import sleep | ||
|
||
import pycardano | ||
import pytest | ||
import uvicorn | ||
from pycardano import TransactionFailedException | ||
from starlette.testclient import TestClient | ||
|
||
from plutus_bench import MockChainContext, MockUser | ||
from plutus_bench.mock import MockFrostApi | ||
|
||
from tests.mint import mint_coin_with_contract | ||
from plutus_bench.tool import address_from_script, load_contract, ScriptType | ||
from plutus_bench.mockfrost.client import MockFrostClient, MockFrostUser | ||
from plutus_bench.mockfrost.server import app | ||
|
||
own_path = pathlib.Path(__file__) | ||
|
||
|
||
def run_server(): | ||
uvicorn.run(app, port=8000) | ||
|
||
|
||
@pytest.fixture | ||
def server(): | ||
proc = Process(target=run_server, args=(), daemon=True) | ||
proc.start() | ||
sleep(1) # Wait for server to start | ||
yield | ||
proc.kill() # Cleanup after test | ||
|
||
|
||
def test_mint_contract(server): | ||
client = MockFrostClient(base_url="http://127.0.0.1:8000") | ||
session = client.create_session() | ||
context = session.chain_context() | ||
minting_user = MockFrostUser(session) | ||
minting_user.fund(100_000_000) | ||
|
||
mint_coin_with_contract( | ||
"My_token", | ||
100, | ||
minting_user.signing_key, | ||
minting_user.verification_key, | ||
context, | ||
) | ||
|
||
|
||
def test_wrong_signature_mint_contract(server): | ||
client = MockFrostClient(base_url="http://127.0.0.1:8000") | ||
session = client.create_session() | ||
context = session.chain_context() | ||
minting_user = MockFrostUser(session) | ||
minting_user.fund(100_000_000) | ||
|
||
other_user = MockFrostUser(session) | ||
|
||
pytest.raises( | ||
TransactionFailedException, | ||
mint_coin_with_contract, | ||
"My_token", | ||
100, | ||
minting_user.signing_key, | ||
other_user.verification_key, | ||
context, | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
test_mint_contract() | ||
# test_spend_from_gift_contract() | ||
# test_other_user_spend_from_gift_contract() |