Skip to content

Commit b772379

Browse files
authored
chore: add more test for append_payment_to_contract_op. (#1025)
1 parent a427e58 commit b772379

File tree

4 files changed

+121
-31
lines changed

4 files changed

+121
-31
lines changed

Diff for: stellar_sdk/contract/assembled_transaction.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def sign_and_submit(
116116
117117
A convenience method combining sign() and submit().
118118
119-
:param transaction_signer: transaction_signer: Optional keypair to sign with (overrides instance signer)
119+
:param transaction_signer: Optional keypair to sign with (overrides instance signer)
120120
:param force: Whether to sign and submit even if the transaction is a read call
121121
:return: The value returned by the invoked function, parsed if parse_result_xdr_fn was set, otherwise raw XDR
122122
"""

Diff for: stellar_sdk/transaction_builder.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1483,7 +1483,6 @@ def append_payment_to_contract_op(
14831483
and then use the :func:`append_payment_to_contract_op` method to send assets again.
14841484
14851485
You can find the example code in the `examples/send_asset_to_contract_without_rpc.py <https://github.com/StellarCN/py-stellar-base/blob/main/examples/>`__.
1486-
14871486
.. note::
14881487
1. This method should only be used to send assets to contract addresses (starting with 'C'). For sending assets to regular account addresses (starting with 'G'), please use the :func:`append_payment_op` method.
14891488
2. This method is suitable for sending assets to a contract account when you don't have access to a Stellar RPC server. If you have access to a Stellar RPC server, it is recommended to use the :class:`stellar_sdk.contract.ContractClient` to build transactions for sending tokens to contracts.
@@ -1550,6 +1549,7 @@ def append_payment_to_contract_op(
15501549
),
15511550
)
15521551
],
1552+
source=source,
15531553
)
15541554

15551555
contract_instance_ledger_key = stellar_xdr.LedgerKey(

Diff for: tests/integration_utils.py

+35-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import time
2+
13
import requests
24

35
from stellar_sdk import (
6+
Account,
47
Asset,
58
Keypair,
69
Network,
@@ -9,7 +12,7 @@
912
TransactionBuilder,
1013
scval,
1114
)
12-
from stellar_sdk.contract import ContractClient
15+
from stellar_sdk.contract import AssembledTransaction, ContractClient
1316
from stellar_sdk.contract.exceptions import SimulationFailedError
1417

1518
RPC_URL = "http://127.0.0.1:8000/soroban/rpc"
@@ -45,35 +48,50 @@ def get_balance_for_contract(contract_id: str, asset: Asset, source: str) -> int
4548
).result()
4649

4750

48-
def issue_asset(asset_code: str, issuer_kp: Keypair, receiver_kp: Keypair, amount: str):
49-
with Server(HORIZON_URL) as server:
50-
asset = Asset(asset_code, issuer_kp.public_key)
51-
# First, the receiving account must trust the asset
52-
trust_transaction = (
51+
def get_random_contract_id(source: Keypair):
52+
with SorobanServer(RPC_URL) as server:
53+
transaction_builder = (
5354
TransactionBuilder(
54-
source_account=server.load_account(receiver_kp.public_key),
55+
source_account=Account(source.public_key, 0),
5556
network_passphrase=NETWORK_PASSPHRASE,
5657
base_fee=100,
5758
)
58-
.append_change_trust_op(asset=asset)
59-
.set_timeout(30)
60-
.build()
59+
.append_create_stellar_asset_contract_from_address_op(source.public_key)
60+
.set_timeout(300)
6161
)
62+
contract_id = (
63+
AssembledTransaction(
64+
transaction_builder,
65+
server,
66+
source,
67+
lambda x: scval.from_address(x).address,
68+
)
69+
.simulate()
70+
.sign_and_submit()
71+
)
72+
time.sleep(1) # https://github.com/stellar/quickstart/issues/667
73+
return contract_id
6274

63-
trust_transaction.sign(receiver_kp)
64-
server.submit_transaction(trust_transaction)
6575

66-
payment_transaction = (
76+
def issue_asset(asset_code: str, issuer_kp: Keypair, receiver_kp: Keypair, amount: str):
77+
with Server(HORIZON_URL) as server:
78+
asset = Asset(asset_code, issuer_kp.public_key)
79+
transaction = (
6780
TransactionBuilder(
68-
source_account=server.load_account(issuer_kp.public_key),
81+
source_account=server.load_account(receiver_kp.public_key),
6982
network_passphrase=NETWORK_PASSPHRASE,
7083
base_fee=100,
7184
)
85+
.append_change_trust_op(asset=asset, source=receiver_kp.public_key)
7286
.append_payment_op(
73-
destination=receiver_kp.public_key, amount=amount, asset=asset
87+
destination=receiver_kp.public_key,
88+
amount=amount,
89+
asset=asset,
90+
source=issuer_kp.public_key,
7491
)
7592
.set_timeout(30)
7693
.build()
7794
)
78-
payment_transaction.sign(issuer_kp)
79-
server.submit_transaction(payment_transaction)
95+
transaction.sign(receiver_kp)
96+
transaction.sign(issuer_kp)
97+
server.submit_transaction(transaction)

Diff for: tests/test_transaction_builder.py

+84-12
Original file line numberDiff line numberDiff line change
@@ -1012,16 +1012,14 @@ def test_from_xdr_with_soroban_tx(self):
10121012
@pytest.mark.integration
10131013
def test_append_payment_to_contract_op_with_native_asset(self):
10141014
asset = Asset.native()
1015-
amount1 = "100.125"
1016-
amount2 = "120.7891"
1017-
destination = asset.contract_id(
1018-
integration_utils.NETWORK_PASSPHRASE
1019-
) # we use it as the destination, do need to create a new contract
1020-
10211015
kp = Keypair.random()
10221016
integration_utils.fund_account(kp.public_key)
10231017
integration_utils.create_asset_contract(asset, kp)
10241018
server = Server(horizon_url=integration_utils.HORIZON_URL)
1019+
amount1 = "100.125"
1020+
amount2 = "120.7891"
1021+
destination = integration_utils.get_random_contract_id(kp)
1022+
10251023
source = server.load_account(kp.public_key)
10261024
tx1 = (
10271025
TransactionBuilder(
@@ -1085,14 +1083,13 @@ def test_append_payment_to_contract_op_with_alphanum4_asset(self):
10851083
asset = Asset("CAT", issuer_kp.public_key)
10861084
amount1 = "100.125"
10871085
amount2 = "120.7891"
1088-
destination = asset.contract_id(
1089-
integration_utils.NETWORK_PASSPHRASE
1090-
) # we use it as the destination, do need to create a new contract
10911086

10921087
integration_utils.fund_account(issuer_kp.public_key)
10931088
integration_utils.fund_account(kp.public_key)
10941089
integration_utils.issue_asset(asset.code, issuer_kp, kp, "1000")
10951090
integration_utils.create_asset_contract(asset, kp)
1091+
destination = integration_utils.get_random_contract_id(kp)
1092+
10961093
server = Server(horizon_url=integration_utils.HORIZON_URL)
10971094
source = server.load_account(kp.public_key)
10981095
tx1 = (
@@ -1156,14 +1153,12 @@ def test_append_payment_to_contract_op_with_alphanum12_asset(self):
11561153
asset = Asset("BANANA", issuer_kp.public_key)
11571154
amount1 = "100.125"
11581155
amount2 = "120.7891"
1159-
destination = asset.contract_id(
1160-
integration_utils.NETWORK_PASSPHRASE
1161-
) # we use it as the destination, do need to create a new contract
11621156

11631157
integration_utils.fund_account(issuer_kp.public_key)
11641158
integration_utils.fund_account(kp.public_key)
11651159
integration_utils.issue_asset(asset.code, issuer_kp, kp, "1000")
11661160
integration_utils.create_asset_contract(asset, kp)
1161+
destination = integration_utils.get_random_contract_id(kp)
11671162
server = Server(horizon_url=integration_utils.HORIZON_URL)
11681163
source = server.load_account(kp.public_key)
11691164
tx1 = (
@@ -1219,6 +1214,83 @@ def test_append_payment_to_contract_op_with_alphanum12_asset(self):
12191214

12201215
server.close()
12211216

1217+
@pytest.mark.integration
1218+
def test_append_payment_to_contract_op_with_different_op_source(self):
1219+
asset = Asset.native()
1220+
kp = Keypair.random()
1221+
op_kp = Keypair.random()
1222+
integration_utils.fund_account(kp.public_key)
1223+
integration_utils.fund_account(op_kp.public_key)
1224+
integration_utils.create_asset_contract(asset, kp)
1225+
server = Server(horizon_url=integration_utils.HORIZON_URL)
1226+
amount1 = "100.125"
1227+
amount2 = "120.7891"
1228+
destination = integration_utils.get_random_contract_id(kp)
1229+
1230+
source = server.load_account(kp.public_key)
1231+
tx1 = (
1232+
TransactionBuilder(
1233+
source_account=source,
1234+
network_passphrase=integration_utils.NETWORK_PASSPHRASE,
1235+
base_fee=100,
1236+
)
1237+
.append_payment_to_contract_op(
1238+
destination, asset, amount1, source=op_kp.public_key
1239+
)
1240+
.set_timeout(30)
1241+
.build()
1242+
)
1243+
tx1.sign(kp)
1244+
tx1.sign(op_kp)
1245+
server.submit_transaction(tx1)
1246+
assert (
1247+
integration_utils.get_balance_for_contract(
1248+
destination, asset, kp.public_key
1249+
)
1250+
== 1001250000
1251+
)
1252+
1253+
tx2 = (
1254+
TransactionBuilder(
1255+
source_account=source,
1256+
network_passphrase=integration_utils.NETWORK_PASSPHRASE,
1257+
base_fee=100,
1258+
)
1259+
.append_payment_to_contract_op(
1260+
destination, asset, amount2, source=op_kp.public_key
1261+
)
1262+
.set_timeout(30)
1263+
.build()
1264+
)
1265+
tx2.sign(kp)
1266+
tx2.sign(op_kp)
1267+
server.submit_transaction(tx2)
1268+
assert (
1269+
integration_utils.get_balance_for_contract(
1270+
destination, asset, kp.public_key
1271+
)
1272+
== 2209141000
1273+
)
1274+
1275+
# In the e2e environment, it has not expired, but we still try to call it.
1276+
tx3 = (
1277+
TransactionBuilder(
1278+
source_account=source,
1279+
network_passphrase=integration_utils.NETWORK_PASSPHRASE,
1280+
base_fee=100,
1281+
)
1282+
.append_restore_asset_balance_entry_op(
1283+
destination, asset, source=op_kp.public_key
1284+
)
1285+
.set_timeout(30)
1286+
.build()
1287+
)
1288+
tx3.sign(kp)
1289+
tx3.sign(op_kp)
1290+
server.submit_transaction(tx3)
1291+
1292+
server.close()
1293+
12221294
def test_append_payment_to_stellar_address_raise(self):
12231295
kp = Keypair.random()
12241296
asset = Asset.native()

0 commit comments

Comments
 (0)