feat(common & core & legacy): Stellar, add support for StellarPathPaymentStrictSendOp.

pull/1896/head
Jun Luo 3 years ago committed by matejcik
parent 1dcb8e4913
commit d064aae3f9

@ -75,6 +75,7 @@ message StellarSignTx {
* @next StellarPaymentOp
* @next StellarCreateAccountOp
* @next StellarPathPaymentStrictReceiveOp
* @next StellarPathPaymentStrictSendOp
* @next StellarManageSellOfferOp
* @next StellarManageBuyOfferOp
* @next StellarCreatePassiveOfferOp
@ -117,13 +118,28 @@ message StellarCreateAccountOp {
* @next StellarSignedTx
*/
message StellarPathPaymentStrictReceiveOp {
optional string source_account = 1; // (optional) source address
required StellarAsset send_asset = 2;
required sint64 send_max = 3;
required string destination_account = 4;
required StellarAsset destination_asset = 5;
required sint64 destination_amount = 6;
repeated StellarAsset paths = 7;
optional string source_account = 1; // (optional) source address
required StellarAsset send_asset = 2; // asset we pay with
required sint64 send_max = 3; // the maximum amount of sendAsset to send (excluding fees)
required string destination_account = 4; // recipient of the payment
required StellarAsset destination_asset = 5; // what they end up with
required sint64 destination_amount = 6; // amount they end up with
repeated StellarAsset paths = 7; // additional hops it must go through to get there
}
/**
* Request: ask device to confirm this operation type
* @next StellarTxOpRequest
* @next StellarSignedTx
*/
message StellarPathPaymentStrictSendOp {
optional string source_account = 1; // (optional) source address
required StellarAsset send_asset = 2; // asset we pay with
required sint64 send_amount = 3; // amount of sendAsset to send (excluding fees)
required string destination_account = 4; // recipient of the payment
required StellarAsset destination_asset = 5; // what they end up with
required sint64 destination_min = 6; // the minimum amount of dest asset to be received
repeated StellarAsset paths = 7; //additional hops it must go through to get there
}
/**

@ -240,6 +240,7 @@ enum MessageType {
MessageType_StellarManageDataOp = 220 [(wire_in) = true];
MessageType_StellarBumpSequenceOp = 221 [(wire_in) = true];
MessageType_StellarManageBuyOfferOp = 222 [(wire_in) = true];
MessageType_StellarPathPaymentStrictSendOp = 223 [(wire_in) = true];
MessageType_StellarSignedTx = 230 [(wire_out) = true];
// Cardano

@ -451,6 +451,56 @@
"signature": "A/ccrRMTEy3GXaZ7Lo5frX3ME5fy3bDMrmYaZ8oPtpPk+cnRStbcSAgdTKnRq/dPGRLfh2btvPJD9ETMe1ajDA=="
}
},
{
"name": "StellarPathPaymentStrictSendOp",
"parameters": {
"xdr": "AAAAAgAAAAAvIrnGLwi3dPPr5t1ufbk8PsLL3gJ5Vho9nFIluMMikgAAAGQAAAAAAAAD6AAAAAEAAAAAG4J3zQAAAABd5CqEAAAAAAAAAAEAAAAAAAAADQAAAAFYAAAAAAAAAHCLqjFfflwWbYS0ZL+zj9YleP460nIn52zLt6F5xFEhAAAAAB3PFpgAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAACQUJDREVGR0hJSktMAAAAACmElgLCDlg2XxI8Eth6HKRVDRDNIbCuDhjUTj5W/WoVAAAAAAAB4kAAAAACAAAAAUpQWQAAAAAA/Pr8d4Jv8Bq3LDTJiXMR/LjsnkO0R2sDyP5fodnIhB4AAAACQkFOQU5BAAAAAAAAAAAAAL5FO387ZKhuvo51/hHfkV1gShE677dHpUZV6jK+Wgg7AAAAAAAAAAA=",
"address_n": "m/44'/148'/0'",
"network_passphrase": "Test SDF Network ; September 2015",
"tx": {
"source_account": "GAXSFOOGF4ELO5HT5PTN23T5XE6D5QWL3YBHSVQ2HWOFEJNYYMRJENBV",
"fee": 100,
"sequence_number": 1000,
"timebounds_start": 461535181,
"timebounds_end": 1575234180,
"memo_type": "NONE"
},
"operations": [
{
"_message_type": "StellarPathPaymentStrictSendOp",
"send_asset": {
"type": "ALPHANUM4",
"code": "X",
"issuer": "GBYIXKRRL57FYFTNQS2GJP5TR7LCK6H6HLJHEJ7HNTF3PILZYRISDLNQ"
},
"send_amount": 500111000,
"destination_account": "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V",
"destination_asset": {
"type": "ALPHANUM12",
"code": "ABCDEFGHIJKL",
"issuer": "GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC"
},
"destination_min": 123456,
"paths": [
{
"type": "ALPHANUM4",
"code": "JPY",
"issuer": "GD6PV7DXQJX7AGVXFQ2MTCLTCH6LR3E6IO2EO2YDZD7F7IOZZCCB5DSQ"
},
{
"type": "ALPHANUM12",
"code": "BANANA",
"issuer": "GC7EKO37HNSKQ3V6RZ274EO7SFOWASQRHLX3OR5FIZK6UMV6LIEDXHGZ"
}
]
}
]
},
"result": {
"public_key": "2f22b9c62f08b774f3ebe6dd6e7db93c3ec2cbde0279561a3d9c5225b8c32292",
"signature": "ZoJRiq9zQsbv/w5CA4IOqRPsPY46kzrQ0uMgY+Y9Ec6kKk/0ktFt2icEKNvVAKZUYmfEEigKhki/Rt9meN43CQ=="
}
},
{
"name": "StellarManageDataOp",
"parameters": {

@ -1 +1 @@
Stellar: add support for StellarManageBuyOfferOp.
Stellar: add support for StellarManageBuyOfferOp and StellarPathPaymentStrictSendOp.

@ -28,6 +28,7 @@ Stellar transaction is composed of one or more operations. We support all [opera
- Manage Buy Offer
- Manage Sell Offer
- Path Payment Strict Receive
- Path Payment Strict Send
- Payment
- Set Options

@ -17,6 +17,7 @@ if False:
StellarManageBuyOfferOp,
StellarManageSellOfferOp,
StellarPathPaymentStrictReceiveOp,
StellarPathPaymentStrictSendOp,
StellarPaymentOp,
StellarSetOptionsOp,
)
@ -32,6 +33,7 @@ if False:
StellarManageBuyOfferOp,
StellarManageSellOfferOp,
StellarPathPaymentStrictReceiveOp,
StellarPathPaymentStrictSendOp,
StellarPaymentOp,
StellarSetOptionsOp,
]
@ -52,6 +54,7 @@ op_codes: dict[int, int] = {
MessageType.StellarManageBuyOfferOp: 12,
MessageType.StellarManageSellOfferOp: 3,
MessageType.StellarPathPaymentStrictReceiveOp: 2,
MessageType.StellarPathPaymentStrictSendOp: 13,
MessageType.StellarPaymentOp: 1,
MessageType.StellarSetOptionsOp: 5,
}
@ -67,6 +70,7 @@ op_wire_types = [
MessageType.StellarManageBuyOfferOp,
MessageType.StellarManageSellOfferOp,
MessageType.StellarPathPaymentStrictReceiveOp,
MessageType.StellarPathPaymentStrictSendOp,
MessageType.StellarPaymentOp,
MessageType.StellarSetOptionsOp,
]

@ -43,6 +43,9 @@ async def process_operation(
elif serialize.StellarPathPaymentStrictReceiveOp.is_type_of(op):
await layout.confirm_path_payment_strict_receive_op(ctx, op)
serialize.write_path_payment_strict_receive_op(w, op)
elif serialize.StellarPathPaymentStrictSendOp.is_type_of(op):
await layout.confirm_path_payment_strict_send_op(ctx, op)
serialize.write_path_payment_strict_send_op(w, op)
elif serialize.StellarPaymentOp.is_type_of(op):
await layout.confirm_payment_op(ctx, op)
serialize.write_payment_op(w, op)

@ -11,6 +11,7 @@ from trezor.messages import (
StellarManageDataOp,
StellarManageSellOfferOp,
StellarPathPaymentStrictReceiveOp,
StellarPathPaymentStrictSendOp,
StellarPaymentOp,
StellarSetOptionsOp,
)
@ -213,6 +214,27 @@ async def confirm_path_payment_strict_receive_op(
await confirm_asset_issuer(ctx, op.send_asset)
async def confirm_path_payment_strict_send_op(
ctx: Context, op: StellarPathPaymentStrictSendOp
) -> None:
await confirm_output(
ctx,
address=op.destination_account,
amount=format_amount(op.destination_min, op.destination_asset),
title="Path Pay at least",
)
await confirm_asset_issuer(ctx, op.destination_asset)
# confirm what the sender is using to pay
await confirm_amount(
ctx,
title="Debited amount",
amount=format_amount(op.send_amount, op.send_asset),
description="Pay:",
br_type="op_path_payment_strict_send",
)
await confirm_asset_issuer(ctx, op.send_asset)
async def confirm_payment_op(ctx: Context, op: StellarPaymentOp) -> None:
await confirm_output(
ctx,

@ -11,6 +11,7 @@ from trezor.messages import (
StellarManageDataOp,
StellarManageSellOfferOp,
StellarPathPaymentStrictReceiveOp,
StellarPathPaymentStrictSendOp,
StellarPaymentOp,
StellarSetOptionsOp,
)
@ -99,6 +100,20 @@ def write_path_payment_strict_receive_op(
_write_asset(w, p)
def write_path_payment_strict_send_op(
w: Writer, msg: StellarPathPaymentStrictSendOp
) -> None:
_write_asset(w, msg.send_asset)
writers.write_uint64(w, msg.send_amount)
writers.write_pubkey(w, msg.destination_account)
_write_asset(w, msg.destination_asset)
writers.write_uint64(w, msg.destination_min)
writers.write_uint32(w, len(msg.paths))
for p in msg.paths:
_write_asset(w, p)
def write_payment_op(w: Writer, msg: StellarPaymentOp) -> None:
writers.write_pubkey(w, msg.destination_account)
_write_asset(w, msg.asset)

@ -131,6 +131,7 @@ if not utils.BITCOIN_ONLY:
StellarManageDataOp = 220
StellarBumpSequenceOp = 221
StellarManageBuyOfferOp = 222
StellarPathPaymentStrictSendOp = 223
StellarSignedTx = 230
CardanoSignTx = 303
CardanoGetPublicKey = 305

@ -136,6 +136,7 @@ if TYPE_CHECKING:
StellarManageDataOp = 220
StellarBumpSequenceOp = 221
StellarManageBuyOfferOp = 222
StellarPathPaymentStrictSendOp = 223
StellarSignedTx = 230
CardanoSignTx = 303
CardanoGetPublicKey = 305

@ -4798,6 +4798,32 @@ if TYPE_CHECKING:
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["StellarPathPaymentStrictReceiveOp"]:
return isinstance(msg, cls)
class StellarPathPaymentStrictSendOp(protobuf.MessageType):
source_account: "str | None"
send_asset: "StellarAsset"
send_amount: "int"
destination_account: "str"
destination_asset: "StellarAsset"
destination_min: "int"
paths: "list[StellarAsset]"
def __init__(
self,
*,
send_asset: "StellarAsset",
send_amount: "int",
destination_account: "str",
destination_asset: "StellarAsset",
destination_min: "int",
paths: "list[StellarAsset] | None" = None,
source_account: "str | None" = None,
) -> None:
pass
@classmethod
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["StellarPathPaymentStrictSendOp"]:
return isinstance(msg, cls)
class StellarManageSellOfferOp(protobuf.MessageType):
source_account: "str | None"
selling_asset: "StellarAsset"

@ -1 +1 @@
Stellar: add support for StellarManageBuyOfferOp.
Stellar: add support for StellarManageBuyOfferOp and StellarPathPaymentStrictSendOp.

@ -120,6 +120,8 @@ void fsm_msgStellarPaymentOp(const StellarPaymentOp *msg);
void fsm_msgStellarCreateAccountOp(const StellarCreateAccountOp *msg);
void fsm_msgStellarPathPaymentStrictReceiveOp(
const StellarPathPaymentStrictReceiveOp *msg);
void fsm_msgStellarPathPaymentStrictSendOp(
const StellarPathPaymentStrictSendOp *msg);
void fsm_msgStellarManageBuyOfferOp(const StellarManageBuyOfferOp *msg);
void fsm_msgStellarManageSellOfferOp(const StellarManageSellOfferOp *msg);
void fsm_msgStellarCreatePassiveOfferOp(const StellarCreatePassiveOfferOp *msg);

@ -128,6 +128,25 @@ void fsm_msgStellarPathPaymentStrictReceiveOp(
}
}
void fsm_msgStellarPathPaymentStrictSendOp(
const StellarPathPaymentStrictSendOp *msg) {
if (!stellar_confirmPathPaymentStrictSendOp(msg)) return;
if (stellar_allOperationsConfirmed()) {
RESP_INIT(StellarSignedTx);
stellar_fillSignedTx(resp);
msg_write(MessageType_MessageType_StellarSignedTx, resp);
layoutHome();
}
// Request the next operation to sign
else {
RESP_INIT(StellarTxOpRequest);
msg_write(MessageType_MessageType_StellarTxOpRequest, resp);
}
}
void fsm_msgStellarManageBuyOfferOp(const StellarManageBuyOfferOp *msg) {
if (!stellar_confirmManageBuyOfferOp(msg)) return;

@ -21,6 +21,10 @@ StellarPathPaymentStrictReceiveOp.source_account max_size:57
StellarPathPaymentStrictReceiveOp.destination_account max_size:57
StellarPathPaymentStrictReceiveOp.paths max_count:5
StellarPathPaymentStrictSendOp.source_account max_size:57
StellarPathPaymentStrictSendOp.destination_account max_size:57
StellarPathPaymentStrictSendOp.paths max_count:5
StellarManageBuyOfferOp.source_account max_size:57
StellarManageSellOfferOp.source_account max_size:57

@ -356,9 +356,9 @@ bool stellar_confirmPathPaymentStrictReceiveOp(
strlcpy(str_source_amount, _("Pay Using "), sizeof(str_source_amount));
strlcat(str_source_amount, str_source_number, sizeof(str_source_amount));
stellar_layoutTransactionDialog(str_source_amount, str_send_asset, NULL,
_("This is the amount debited"),
_("from your account."));
stellar_layoutTransactionDialog(str_source_amount, str_send_asset,
_("This is the max"),
_("amount debited from your"), _("account."));
if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
stellar_signingAbort(_("User canceled"));
return false;
@ -388,6 +388,104 @@ bool stellar_confirmPathPaymentStrictReceiveOp(
return true;
}
bool stellar_confirmPathPaymentStrictSendOp(
const StellarPathPaymentStrictSendOp *msg) {
if (!stellar_signing) return false;
if (!stellar_confirmSourceAccount(msg->has_source_account,
msg->source_account)) {
stellar_signingAbort(_("Source account error"));
return false;
}
// Hash: operation type
stellar_hashupdate_uint32(13);
// Validate destination account and convert to bytes
uint8_t destination_account_bytes[STELLAR_KEY_SIZE] = {0};
if (!stellar_getAddressBytes(msg->destination_account,
destination_account_bytes)) {
stellar_signingAbort(_("Invalid destination account"));
return false;
}
const char **str_dest_rows =
stellar_lineBreakAddress(destination_account_bytes);
// To: G...
char str_to[32] = {0};
strlcpy(str_to, _("To: "), sizeof(str_to));
strlcat(str_to, str_dest_rows[0], sizeof(str_to));
char str_send_asset[32] = {0};
char str_dest_asset[32] = {0};
stellar_format_asset(&(msg->send_asset), str_send_asset,
sizeof(str_send_asset));
stellar_format_asset(&(msg->destination_asset), str_dest_asset,
sizeof(str_dest_asset));
char str_pay_amount[32] = {0};
char str_amount[32] = {0};
stellar_format_stroops(msg->destination_min, str_amount, sizeof(str_amount));
strlcat(str_pay_amount, str_amount, sizeof(str_pay_amount));
// Confirm what the receiver will get
/*
Path Pay at least
100.0000000
JPY (G1234ABCDEF)
To: G....
....
....
*/
stellar_layoutTransactionDialog(_("Path Pay at least"), str_pay_amount,
str_dest_asset, str_to, str_dest_rows[1]);
if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
stellar_signingAbort(_("User canceled"));
return false;
}
// Confirm what the sender is using to pay
char str_source_amount[32] = {0};
char str_source_number[32] = {0};
stellar_format_stroops(msg->send_amount, str_source_number,
sizeof(str_source_number));
strlcpy(str_source_amount, _("Pay Using "), sizeof(str_source_amount));
strlcat(str_source_amount, str_source_number, sizeof(str_source_amount));
stellar_layoutTransactionDialog(
str_dest_rows[2], str_source_amount, str_send_asset,
_("This is the amount debited"), _("from your account."));
if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
stellar_signingAbort(_("User canceled"));
return false;
}
// Note: no confirmation for intermediate steps since they don't impact the
// user
// Hash send asset
stellar_hashupdate_asset(&(msg->send_asset));
// send amount (signed vs. unsigned doesn't matter wrt hashing)
stellar_hashupdate_uint64(msg->send_amount);
// destination account
stellar_hashupdate_address(destination_account_bytes);
// destination asset
stellar_hashupdate_asset(&(msg->destination_asset));
// destination amount
stellar_hashupdate_uint64(msg->destination_min);
// paths are stored as an array so hash the number of elements as a uint32
stellar_hashupdate_uint32(msg->paths_count);
for (uint8_t i = 0; i < msg->paths_count; i++) {
stellar_hashupdate_asset(&(msg->paths[i]));
}
// At this point, the operation is confirmed
stellar_activeTx.confirmed_operations++;
return true;
}
bool stellar_confirmManageBuyOfferOp(const StellarManageBuyOfferOp *msg) {
if (!stellar_signing) return false;

@ -61,6 +61,8 @@ bool stellar_confirmCreateAccountOp(const StellarCreateAccountOp *msg);
bool stellar_confirmPaymentOp(const StellarPaymentOp *msg);
bool stellar_confirmPathPaymentStrictReceiveOp(
const StellarPathPaymentStrictReceiveOp *msg);
bool stellar_confirmPathPaymentStrictSendOp(
const StellarPathPaymentStrictSendOp *msg);
bool stellar_confirmManageBuyOfferOp(const StellarManageBuyOfferOp *msg);
bool stellar_confirmManageSellOfferOp(const StellarManageSellOfferOp *msg);
bool stellar_confirmCreatePassiveOfferOp(

@ -157,6 +157,7 @@ class MessageType(IntEnum):
StellarManageDataOp = 220
StellarBumpSequenceOp = 221
StellarManageBuyOfferOp = 222
StellarPathPaymentStrictSendOp = 223
StellarSignedTx = 230
CardanoSignTx = 303
CardanoGetPublicKey = 305
@ -6357,6 +6358,38 @@ class StellarPathPaymentStrictReceiveOp(protobuf.MessageType):
self.source_account = source_account
class StellarPathPaymentStrictSendOp(protobuf.MessageType):
MESSAGE_WIRE_TYPE = 223
FIELDS = {
1: protobuf.Field("source_account", "string", repeated=False, required=False),
2: protobuf.Field("send_asset", "StellarAsset", repeated=False, required=True),
3: protobuf.Field("send_amount", "sint64", repeated=False, required=True),
4: protobuf.Field("destination_account", "string", repeated=False, required=True),
5: protobuf.Field("destination_asset", "StellarAsset", repeated=False, required=True),
6: protobuf.Field("destination_min", "sint64", repeated=False, required=True),
7: protobuf.Field("paths", "StellarAsset", repeated=True, required=False),
}
def __init__(
self,
*,
send_asset: "StellarAsset",
send_amount: "int",
destination_account: "str",
destination_asset: "StellarAsset",
destination_min: "int",
paths: Optional[List["StellarAsset"]] = None,
source_account: Optional["str"] = None,
) -> None:
self.paths = paths if paths is not None else []
self.send_asset = send_asset
self.send_amount = send_amount
self.destination_account = destination_account
self.destination_asset = destination_asset
self.destination_min = destination_min
self.source_account = source_account
class StellarManageSellOfferOp(protobuf.MessageType):
MESSAGE_WIRE_TYPE = 213
FIELDS = {

@ -35,6 +35,7 @@ try:
NoneMemo,
Operation,
PathPaymentStrictReceive,
PathPaymentStrictSend,
Payment,
ReturnHashMemo,
SetOptions,
@ -237,6 +238,17 @@ def _read_operation(op: "Operation"):
price_d=price.d,
offer_id=op.offer_id,
)
if isinstance(op, PathPaymentStrictSend):
operation = messages.StellarPathPaymentStrictSendOp(
source_account=source_account,
send_asset=_read_asset(op.send_asset),
send_amount=_read_amount(op.send_amount),
destination_account=op.destination.account_id,
destination_asset=_read_asset(op.dest_asset),
destination_min=_read_amount(op.dest_min),
paths=[_read_asset(asset) for asset in op.path],
)
return operation
raise ValueError(f"Unknown operation type: {op.__class__.__name__}")

@ -330,6 +330,7 @@ def test_path_payment_strict_receive():
assert operations[0].destination_account == destination
assert operations[0].send_asset.type == messages.StellarAssetType.NATIVE
assert operations[0].send_max == 500111000
assert operations[0].destination_amount == 1000000000
assert operations[0].destination_asset.type == messages.StellarAssetType.ALPHANUM4
assert operations[0].destination_asset.code == dest_code
assert operations[0].destination_asset.issuer == dest_issuer
@ -782,3 +783,57 @@ def test_manage_buy_offer_update_offer():
assert operations[0].price_n == 1
assert operations[0].price_d == 2
assert operations[0].offer_id == offer_id
def test_path_payment_strict_send():
tx = make_default_tx()
destination = "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6"
send_amount = "50.0112"
dest_min = "120"
send_code = "XLM"
send_issuer = None
dest_code = "USD"
dest_issuer = "GCSJ7MFIIGIRMAS4R3VT5FIFIAOXNMGDI5HPYTWS5X7HH74FSJ6STSGF"
operation_source = "GAEB4MRKRCONK4J7MVQXAHTNDPAECUCCCNE7YC5CKM34U3OJ673A4D6V"
path_asset1 = Asset(
"JPY", "GD6PV7DXQJX7AGVXFQ2MTCLTCH6LR3E6IO2EO2YDZD7F7IOZZCCB5DSQ"
)
path_asset2 = Asset(
"BANANA", "GC7EKO37HNSKQ3V6RZ274EO7SFOWASQRHLX3OR5FIZK6UMV6LIEDXHGZ"
)
envelope = (
tx
.append_path_payment_strict_send_op(
destination=destination,
send_code=send_code,
send_issuer=send_issuer,
send_amount=send_amount,
dest_code=dest_code,
dest_issuer=dest_issuer,
dest_min=dest_min,
path=[path_asset1, path_asset2],
source=operation_source,
)
.build()
)
tx, operations = stellar.from_envelope(envelope)
assert len(operations) == 1
assert isinstance(operations[0], messages.StellarPathPaymentStrictSendOp)
assert operations[0].source_account == operation_source
assert operations[0].destination_account == destination
assert operations[0].send_asset.type == messages.StellarAssetType.NATIVE
assert operations[0].send_amount == 500112000
assert operations[0].destination_min == 1200000000
assert operations[0].destination_asset.type == messages.StellarAssetType.ALPHANUM4
assert operations[0].destination_asset.code == dest_code
assert operations[0].destination_asset.issuer == dest_issuer
assert len(operations[0].paths) == 2
assert operations[0].paths[0].type == messages.StellarAssetType.ALPHANUM4
assert operations[0].paths[0].code == path_asset1.code
assert operations[0].paths[0].issuer == path_asset1.issuer
assert operations[0].paths[1].type == messages.StellarAssetType.ALPHANUM12
assert operations[0].paths[1].code == path_asset2.code
assert operations[0].paths[1].issuer == path_asset2.issuer

@ -849,6 +849,7 @@
"test_stellar.py::test_sign_tx[StellarManageBuyOfferOp]": "fc57e1ca8b65588aa16cc3524d6dc0f01e094ad5d16a6f7e739a69c101b554bc",
"test_stellar.py::test_sign_tx[StellarManageSellOfferOp]": "6ed84765b2ed46711be0ed1219d91c27e927119d352f37b2baf8c6501186bbce",
"test_stellar.py::test_sign_tx[StellarPathPaymentStrictReceiveOp]": "58f3bfaece0706bc172d6e6564b728ec0b7f8e2629d8c64dc60672786586076d",
"test_stellar.py::test_sign_tx[StellarPathPaymentStrictSendOp]": "fdd36a59520317d514e03f535dfeb93339af0f7ea5ee07c556bee3c8784c94ed",
"test_stellar.py::test_sign_tx[StellarPaymentOp-asset12]": "1d8e9d5d65420a259f7e2deef1efaf0ce5be966a0f1e5b8e95b832f176f00de2",
"test_stellar.py::test_sign_tx[StellarPaymentOp-asset4]": "0de0b815dad5d348a3b9d06e37da94800363e5de8e6ca9cd0f84e5070f7e1b22",
"test_stellar.py::test_sign_tx[StellarPaymentOp-native_asset]": "b2015b9e0f9ff60e2ea4fca2942e97b70a320386c2043fb36acde4a830272098",

Loading…
Cancel
Save