Skip to content

Commit

Permalink
Merge branch '0.8.3' of https://github.com/mvs-org/metaverse into 0.8.3
Browse files Browse the repository at this point in the history
  • Loading branch information
luozhaohui committed Aug 16, 2018
2 parents 9cb03a0 + f776794 commit a9c1538
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 61 deletions.
22 changes: 15 additions & 7 deletions include/metaverse/explorer/extensions/commands/swaptoken.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ class swaptoken: public command_extension
return get_argument_metadata()
.add("ACCOUNTNAME", 1)
.add("ACCOUNTAUTH", 1)
.add("TO_", 1)
.add("SYMBOL", 1)
.add("AMOUNT", 1)
.add("MESSAGE", 1);
.add("FOREIGN_ADDR", 1);
}

void load_fallbacks (std::istream& input,
Expand All @@ -56,9 +57,10 @@ class swaptoken: public command_extension
const auto raw = requires_raw_input();
load_input(auth_.name, "ACCOUNTNAME", variables, input, raw);
load_input(auth_.auth, "ACCOUNTAUTH", variables, input, raw);
load_input(argument_.to, "TO_", variables, input, raw);
load_input(argument_.symbol, "SYMBOL", variables, input, raw);
load_input(argument_.amount, "AMOUNT", variables, input, raw);
load_input(argument_.message, "MESSAGE", variables, input, raw);
load_input(argument_.foreign_addr, "FOREIGN_ADDR", variables, input, raw);
}

options_metadata& load_options() override
Expand All @@ -81,20 +83,25 @@ class swaptoken: public command_extension
value<std::string>(&auth_.auth)->required(),
BX_ACCOUNT_AUTH
)
(
"TO_",
value<std::string>(&argument_.to)->required(),
"To this did/address the specific asset will be sent. expect to be \"crosschain\"."
)
(
"SYMBOL",
value<std::string>(&argument_.symbol)->required(),
"The asset will be burned."
"Asset symbol"
)
(
"AMOUNT",
value<uint64_t>(&argument_.amount)->required(),
"Asset integer bits. see asset <decimal_number>."
)
(
"MESSAGE",
value<std::string>(&argument_.message)->required(),
"Message in json format which indicates the destination chain(by 'type') and address(by 'address') to swap."
"FOREIGN_ADDR",
value<std::string>(&argument_.foreign_addr)->required(),
"To this address of the destination chain to swap the asset."
)
(
"change,c",
Expand Down Expand Up @@ -130,9 +137,10 @@ class swaptoken: public command_extension

struct argument
{
std::string to;
std::string symbol;
uint64_t amount;
std::string message;
std::string foreign_addr;
} argument_;

struct option
Expand Down
32 changes: 14 additions & 18 deletions src/lib/explorer/extensions/commands/swaptoken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,17 @@ console_result swaptoken::invoke(Json::Value& jv_output,
blockchain.uppercase_symbol(argument_.symbol);

// check message
if (argument_.message.empty() || argument_.message.size() >= 255) {
if (argument_.foreign_addr.empty() || argument_.foreign_addr.size() >= 255) {
throw argument_size_invalid_exception{"message length out of bounds."};
}

{
Json::Reader reader;
Json::Value file_root;
if (!reader.parse(argument_.message, file_root)) {
throw argument_legality_exception{"message format parse error."};
}
if (file_root["type"] != "ETH") {
throw argument_legality_exception{"value of [type] not expect in message."};
}
// check ETH address
static const regex regular("^0x[0-9a-f]{40}+$");

const std::string address = file_root["address"].asString();
sregex_iterator it(address.begin(), address.end(), regular), end;
sregex_iterator it(argument_.foreign_addr.begin(), argument_.foreign_addr.end(), regular), end;
if (it == end) {
throw argument_legality_exception{"value of [address] not expect in message."};
throw argument_legality_exception{argument_.foreign_addr + " is not a valid ETH address."};
}
}

Expand All @@ -68,14 +60,15 @@ console_result swaptoken::invoke(Json::Value& jv_output,
throw argument_legality_exception{"Only support assets prefixed by 'ERC.'"};
}

attachment attach;
const std::string&& to_address = get_address("crosschain", attach, false, blockchain);
attachment attach_asset, attach_fee;
const std::string&& to_address = get_address(argument_.to, attach_asset, false, blockchain);
const std::string&& swapfee_address = bc::get_developer_community_address(
blockchain.chain_settings().use_testnet_rules);

std::string from_address("");
if (!option_.from.empty()) {
from_address = get_address(option_.from, attach, true, blockchain);
from_address = get_address(option_.from, attach_asset, true, blockchain);
get_address(option_.from, attach_fee, true, blockchain);
}

std::string change_address = get_address(option_.change, blockchain);
Expand All @@ -88,16 +81,19 @@ console_result swaptoken::invoke(Json::Value& jv_output,
}

std::vector<receiver_record> receiver{
{to_address, argument_.symbol, 0, argument_.amount, utxo_attach_type::asset_transfer, attach},
{swapfee_address, "", option_.swapfee, 0, utxo_attach_type::etp, attachment()},
{to_address, argument_.symbol, 0, argument_.amount, utxo_attach_type::asset_transfer, attach_asset},
{swapfee_address, "", option_.swapfee, 0, utxo_attach_type::etp, attach_fee},
};

std::string message("{\"type\":\"ETH\",\"address\":\""+ argument_.foreign_addr + "\"}");

auto send_helper = sending_asset(
*this, blockchain,
std::move(auth_.name), std::move(auth_.auth),
std::move(from_address), std::move(argument_.symbol),
"",
std::move(receiver), option_.fee,
std::move(argument_.message), std::move(change_address));
std::move(message), std::move(change_address));

send_helper.exec();

Expand Down
73 changes: 40 additions & 33 deletions test/test-rpc-v3/TestCase/Asset/test_swaptoken.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@

# This asset is expected to be enough to be spend for 1 month
AssetName = 'ERC.TSTCASE.' + time.strftime("%04Y%02m", time.localtime())
crosschain_addr = 'MLixg7rxKmtPj9DT9wPKSy6WkJkoUDWUSv'


class TestSwapToken(MVSTestCaseBase):
#class TestSwapToken(MVSTestCaseBase):
class TestSwapToken:
need_mine = False
@classmethod
def setUpClass(cls):
Expand All @@ -23,39 +24,39 @@ def setUpClass(cls):
ec, message = Alice.create_asset_with_symbol(AssetName)
assert (ec == 0)
Alice.mining()
# TODO: need to bind did [crosschain] to Alice's address [MLixg7rxKmtPj9DT9wPKSy6WkJkoUDWUSv]

@classmethod
def tearDownClass(cls):
Alice.mining()
MVSTestCaseBase.tearDownClass()

def test_0_check_positional_args(self):
ec, message = mvs_rpc.swap_token(Alice.name, Alice.password, Alice.asset_symbol, 100, "{}")
self.assertEqual(message, 'value of [type] not expect in message.')
self.assertEqual(message, '{} is not a valid ETH address.')

ec, message = mvs_rpc.swap_token(Alice.name, Alice.password, Alice.asset_symbol, 100, '{"type":"ETHX"}')
self.assertEqual(message, 'value of [type] not expect in message.')
self.assertEqual(message, '{"type":"ETHX"} is not a valid ETH address.')

ec, message = mvs_rpc.swap_token(Alice.name, Alice.password, Alice.asset_symbol, 100, '{"type":"ETH", "address":"xxx"}')
self.assertEqual(message, 'value of [address] not expect in message.')
self.assertEqual(message, '{"type":"ETH", "address":"xxx"} is not a valid ETH address.')

ec, message = mvs_rpc.swap_token(Alice.name, Alice.password, Alice.asset_symbol, 100,
'{"type":"ETH", "address":"0x000000000000000000000000000000000000000g"}')
self.assertEqual(message, 'value of [address] not expect in message.')
ec, message = mvs_rpc.swap_token(Alice.name, Alice.password, Alice.asset_symbol, 100,
'{"type":"ETH", "address":"0x000000000000000000000000000000000000000"}')
self.assertEqual(message, 'value of [address] not expect in message.')
"0x000000000000000000000000000000000000000g")
self.assertEqual(message, '0x000000000000000000000000000000000000000g is not a valid ETH address.')

ec, message = mvs_rpc.swap_token(Alice.name, Alice.password, Alice.asset_symbol, 100,
'{"type":"ETH", "address":"0x0000000000000000000000000000000000000000"}')
# address length error
ec, message = mvs_rpc.swap_token(Alice.name, Alice.password, Alice.asset_symbol, 100, "0x000000000000000000000000000000000000000")
self.assertEqual(message, '0x000000000000000000000000000000000000000 is not a valid ETH address.')

ec, message = mvs_rpc.swap_token(Alice.name, Alice.password, Alice.asset_symbol, 100, "0x0000000000000000000000000000000000000000")
self.assertEqual(message, "Only support assets prefixed by 'ERC.'")

ec, message = mvs_rpc.swap_token(Alice.name, Alice.password, "ERC.ABC", 100,
'{"type":"ETH", "address":"0x0000000000000000000000000000000000000000"}')
ec, message = mvs_rpc.swap_token(Alice.name, Alice.password, "ERC.ABC", 100, "0x0000000000000000000000000000000000000000")
self.assertEqual(message, 'not enough asset amount, unspent = 0, payment = 100')

def test_1_check_optional_args(self):
func = lambda change, from_, fee, swapfee: mvs_rpc.swap_token(Alice.name, Alice.password, "ERC.ABC", 100,
'{"type":"ETH", "address":"0x0000000000000000000000000000000000000000"}',
func = lambda change, from_, fee, swapfee: mvs_rpc.swap_token(Alice.name, Alice.password, "ERC.ABC", 100, "0x0000000000000000000000000000000000000000", \
change, from_, fee, swapfee)
ec, message = func(None, None, 10000 -1, None)
self.assertEqual(ec, 5005, 'check fee')
Expand All @@ -67,44 +68,48 @@ def test_1_check_optional_args(self):
self.assertEqual(message, 'not enough asset amount, unspent = 0, payment = 100')

def test_2_default(self):
global AssetName
message = '{"type":"ETH", "address":"0x0000000000000000000000000000000000000000"}'
ec, result = mvs_rpc.swap_token(Alice.name, Alice.password, AssetName, 1, message)
global AssetName, crosschain_addr
foreign_addr = "0x0000000000000000000000000000000000000000"
message = '{"type":"ETH","address":"%s"}' % foreign_addr
ec, result = mvs_rpc.swap_token(Alice.name, Alice.password, AssetName, 1, foreign_addr)
self.assertEqual(ec, 0)

#result = result['transaction']
actual_output0 = copy.copy(result['outputs'][0])
actual_output0.pop('script')
expect_output0= {u'index': 0, u'value': 0, u'attachment': {u'symbol': AssetName, u'type': u'asset-transfer', u'quantity': 1}, u'address': u'MAwLwVGwJyFsTBfNj2j5nCUrQXGVRvHzPh', u'locked_height_range': 0}
expect_output0= {u'index': 0, u'value': 0, u'attachment': {u'from_did': u'', u'to_did': u'crosschain', u'symbol': AssetName, u'type': u'asset-transfer', u'quantity': 1}, u'address': crosschain_addr, u'locked_height_range': 0}
self.assertEqual(actual_output0, expect_output0)

actual_output1 = copy.copy(result['outputs'][1])
actual_output1.pop('script')
expect_output1 = {u'index': 1, u'value': 100000000, u'attachment': {u'type': u'etp'}, u'address': u'MAwLwVGwJyFsTBfNj2j5nCUrQXGVRvHzPh', u'locked_height_range': 0}
self.assertEqual(actual_output1, expect_output1)

actual_output4 = copy.copy(result['outputs'][4])
actual_output4 = copy.copy(result['outputs'][-1])
actual_output4.pop('script')
actual_output4.pop('address')
expect_output4 = {u'index': 4, u'value': 0, u'attachment': {u'content': message, u'type': u'message'}, u'locked_height_range': 0}
actual_output4.pop('index')
expect_output4 = {u'value': 0, u'attachment': {u'content': message, u'type': u'message'}, u'locked_height_range': 0}
self.assertEqual(actual_output4, expect_output4)
Alice.mining()

def test_3_fromdid(self):
global AssetName
message = '{"type":"ETH", "address":"0x0000000000000000000000000000000000000001"}'
ec, result = mvs_rpc.swap_token(Alice.name, Alice.password, AssetName, 1, message, from_=Alice.did_symbol)
global AssetName, crosschain_addr
foreign_addr = "0x0000000000000000000000000000000000000001"
message = '{"type":"ETH","address":"%s"}' % foreign_addr
ec, result = mvs_rpc.swap_token(Alice.name, Alice.password, AssetName, 1, foreign_addr, from_=Alice.did_symbol)
self.assertEqual(ec, 0)
#result = result['transaction']

actual_output0 = copy.copy(result['outputs'][0])
actual_output0.pop('script')
expect_output0 = {u'index': 0, u'value': 0, u'attachment': {u'from_did': Alice.did_symbol, u'to_did': u'', u'type': u'asset-transfer', u'symbol': AssetName, u'quantity': 1}, u'address': u'MAwLwVGwJyFsTBfNj2j5nCUrQXGVRvHzPh', u'locked_height_range': 0}
expect_output0 = {u'index': 0, u'value': 0, u'attachment': {u'from_did': Alice.did_symbol, u'to_did': u'crosschain', u'type': u'asset-transfer', u'symbol': AssetName, u'quantity': 1}, u'address': u'MLixg7rxKmtPj9DT9wPKSy6WkJkoUDWUSv', u'locked_height_range': 0}
self.assertEqual(actual_output0, expect_output0)

actual_output1 = copy.copy(result['outputs'][1])
actual_output1.pop('script')
expect_output1 = {u'index': 1, u'value': 100000000, u'attachment': {u'from_did': Alice.did_symbol, u'to_did': u'', u'type': u'etp'}, u'address': u'MAwLwVGwJyFsTBfNj2j5nCUrQXGVRvHzPh', u'locked_height_range': 0}
expect_output1 = {u'index': 1, u'value': 100000000, u'attachment': {u'from_did': Alice.did_symbol, u'to_did': u'', u'type': u'etp'}, u'address': "MAwLwVGwJyFsTBfNj2j5nCUrQXGVRvHzPh", u'locked_height_range': 0}

self.assertEqual(actual_output1, expect_output1)
Alice.mining()

Expand All @@ -113,8 +118,9 @@ def test_4_fromaddress(self):

def test_5_change(self):
global AssetName
message = '{"type":"ETH", "address":"0x0000000000000000000000000000000000000002"}'
ec, result = mvs_rpc.swap_token(Alice.name, Alice.password, AssetName, 1, message, change=Alice.addresslist[1])
foreign_addr = "0x0000000000000000000000000000000000000002"
message = '{"type":"ETH","address":"%s"}' % foreign_addr
ec, result = mvs_rpc.swap_token(Alice.name, Alice.password, AssetName, 1, foreign_addr, from_=Alice.mainaddress(), change=Alice.addresslist[1])
self.assertEqual(ec, 0)
#result = result['transaction']

Expand All @@ -132,14 +138,15 @@ def test_5_change(self):
Alice.mining()

def test_6_swapfee(self):
global AssetName
message = '{"type":"ETH", "address":"0x0000000000000000000000000000000000000002"}'
ec, result = mvs_rpc.swap_token(Alice.name, Alice.password, AssetName, 1, message, swapfee=10**8 + 123456)
global AssetName, crosschain_addr
foreign_addr = "0x0000000000000000000000000000000000000003"
message = '{"type":"ETH","address":"%s"}' % foreign_addr
ec, result = mvs_rpc.swap_token(Alice.name, Alice.password, AssetName, 1, foreign_addr, swapfee=10**8 + 123456)
self.assertEqual(ec, 0)
#result = result['transaction']

actual_output1 = copy.copy(result['outputs'][1])
actual_output1.pop('script')
expect_output1 = {u'index': 1, u'value': 100123456, u'attachment': {u'type': u'etp'}, u'address': u'MAwLwVGwJyFsTBfNj2j5nCUrQXGVRvHzPh', u'locked_height_range': 0}
expect_output1 = {u'index': 1, u'value': 100123456, u'attachment': {u'type': u'etp'}, u'address': "MAwLwVGwJyFsTBfNj2j5nCUrQXGVRvHzPh", u'locked_height_range': 0}
self.assertEqual(actual_output1, expect_output1)
Alice.mining()
6 changes: 3 additions & 3 deletions test/test-rpc-v3/utils/mvs_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -814,14 +814,14 @@ def pop_block(height):
return "popblock", [height], {}, None

@mvs_api
def swap_token(account, password, symbol, amount, message, change=None, from_=None, fee=None, swapfee=None):
def swap_token(account, password, symbol, amount, foreign_addr, change=None, from_=None, fee=None, swapfee=None):
optional = {
'--change': change,
'--From': from_,
'--from': from_,
'--fee': fee,
'--swapfee': swapfee
}
return "swaptoken", [account, password, symbol, amount, message], optional, None
return "swaptoken", [account, password, "crosschain", symbol, amount, foreign_addr], optional, None

if __name__ == "__main__":
rc = RemoteCtrl("10.10.10.35")
Expand Down

0 comments on commit a9c1538

Please sign in to comment.