diff --git a/README.md b/README.md index da8ee00..e958b37 100644 --- a/README.md +++ b/README.md @@ -110,8 +110,8 @@ https://github.com/CryptoLions/SimpleAssets/blob/master/include/SimpleAssets.hpp canceloffer (owner, [assetid1,..,assetidn]) claim (claimer, [assetid1,..,assetidn]) - delegate (owner, to, [assetid1,..,assetidn], period, memo) - undelegate (owner, from, [assetid1,..,assetidn]) + delegate (owner, to, [assetid1,..,assetidn], period, redelegate, memo) + undelegate (owner, [assetid1,..,assetidn]) delegatemore (owner, assetid, period) attach (owner, assetidc, [assetid1,..,assetidn]) @@ -214,13 +214,14 @@ authors { ## Delegates ``` delegates{ - uint64_t assetid; // asset id offered for claim; - name owner; // asset owner; - name delegatedto; // who can claim this asset; - uint64_t cdate; // offer create date; - uint64_t period; // Time in seconds that the asset will be lent. Lender cannot undelegate until - // the period expires, however the receiver can transfer back at any time. - string memo; // memo from action parameters. Max 64 length. + uint64_t assetid; // asset id offered for claim; + name owner; // asset owner; + name delegatedto; // who can claim this asset; + uint64_t cdate; // offer create date; + uint64_t period; // Time in seconds that the asset will be lent. Lender cannot undelegate until + // the period expires, however the receiver can transfer back at any time. + bool redelegate; // redelegate is allow more redelegate for to account or not. + string memo; // memo from action parameters. Max 64 length. } ``` @@ -517,6 +518,16 @@ saRes1.send(); ----------------- # Change Logs +## Change Log v1.4.0 +- re-delegate assets. (lender of assets can allow them to be re-lent) +- New parameter `bool redelegate` added in delegate action, which allows asset re-delegation. +- New field `bool redelegate` added in table `delegates` => require migration in case of self- deployed contract !!! +- In `undelegate` action parameter `from` was removed. (identity of borrower is available in the delegates table) +- Fixed transfer of empty assets array +- Error messages improved for clarity +- Code refactoring + + ## Change Log v1.3.0 - Upgrade work with latest Contract Development Toolkit (CDT v1.6.3). (Resolves this compilation [issue](https://github.com/EOSIO/eosio.cdt/issues/527)) diff --git a/build/SimpleAssets/SimpleAssets.abi b/build/SimpleAssets/SimpleAssets.abi index 950522f..a16ce0c 100644 --- a/build/SimpleAssets/SimpleAssets.abi +++ b/build/SimpleAssets/SimpleAssets.abi @@ -169,6 +169,32 @@ } ] }, + { + "name": "changeauthor", + "base": "", + "fields": [ + { + "name": "author", + "type": "name" + }, + { + "name": "newauthor", + "type": "name" + }, + { + "name": "owner", + "type": "name" + }, + { + "name": "assetids", + "type": "uint64[]" + }, + { + "name": "memo", + "type": "string" + } + ] + }, { "name": "claim", "base": "", @@ -429,6 +455,10 @@ "name": "period", "type": "uint64" }, + { + "name": "redelegate", + "type": "bool" + }, { "name": "memo", "type": "string" @@ -713,6 +743,10 @@ "name": "period", "type": "uint64" }, + { + "name": "redelegate", + "type": "bool" + }, { "name": "memo", "type": "string" @@ -893,10 +927,6 @@ "name": "owner", "type": "name" }, - { - "name": "from", - "type": "name" - }, { "name": "assetids", "type": "uint64[]" @@ -1017,6 +1047,11 @@ "type": "cancelofferf", "ricardian_contract": "---\nspec_version: 0.0.2\ntitle: Cancels offer of FTs\nsummary: Cancels offer of FTs \nicon: https://cryptolions.io/assets/images/sa-icons-256/cancelofferf.png#9c35f488e2c53464f430e0e31e5a4b3bd2e914fe3b6db126722166a8a408fa83\n---\n\nInput parameters:\n`owner` - riginal owner of the FT\n`ftofferids` - id of the FT offer\n\nTERM\nThis Contract expires at the conclusion of code execution.\nby CryptoLions [ https://cryptolions.io ]" }, + { + "name": "changeauthor", + "type": "changeauthor", + "ricardian_contract": "---\nspec_version: 0.0.2\ntitle: Change author of assets\nsummary: Change author of assets\nicon: https://cryptolions.io/assets/images/sa-icons-256/regauthor.png#c6a539be8e7dfd1a4c466ba9cabfd13571cd77d5c988c652d2e8f87096f3548e\n---\t\n\nInput parameters:\n`author` - asset's author, who will able to change author name asset's;\n`newauthor` - asset's new author name;\n`owner` - assets owner;\n`assetids` - array of assetid's\n\nTERM\nThis Contract expires at the conclusion of code execution.\nby CryptoLions [ https://cryptolions.io ]" + }, { "name": "claim", "type": "claim", diff --git a/build/SimpleAssets/SimpleAssets.wasm b/build/SimpleAssets/SimpleAssets.wasm index 4e8cf8c..3358fd0 100755 Binary files a/build/SimpleAssets/SimpleAssets.wasm and b/build/SimpleAssets/SimpleAssets.wasm differ diff --git a/external_test/unit_tests.sh b/external_test/unit_tests.sh index 60dd088..3293960 100755 --- a/external_test/unit_tests.sh +++ b/external_test/unit_tests.sh @@ -1,5 +1,5 @@ #sudo apt-get install bc -#./unit_tests.sh alexnag12345 alexnag1tran PW5KUxSPhXY1YSH9risb7CVpTXzwH7DEVK84wQBugoy1uqBjo5Twm +#./unit_tests.sh simpleasset5 alexnag1tran PW5KUxSPhXY1YSH9risb7CVpTXzwH7DEVK84wQBugoy1uqBjo5Twm echo "Test account where deployed SimpleAsset: " $1 echo "Account second to test transfer: " $2 @@ -292,6 +292,7 @@ function READ_ONE_ASSET sleep $WAIT_TIME size=$(./cleos.sh get table $ACC $SCOPE sassets | jq -r '.rows | length') asset_ids=$(./cleos.sh get table $ACC $SCOPE sassets | jq -r '.rows[].id') + asset_author=$(./cleos.sh get table $ACC $SCOPE sassets | jq -r '.rows[].author') if (( size > 1 )) then @@ -1142,8 +1143,51 @@ function TEST_CREATENTT_CLAIMNTT_BURNNTT CLEAN_NTTASSETS_TABLE ${ACC_TO} } +function PUSH_CHANGEAUTHOR +{ + sleep $WAIT_TIME + echo "changeauthor action" + + output=$(./cleos.sh push action ${ACC} changeauthor '{ "author":"'${ACC}'", "newauthor":"'${ACC_TO}'", "owner":"'${ACC}'" ,"assetids":['${result_asset_id}'],"memo":"mdata"}' -p $ACC@active 2>&1) + + if [[ $output =~ "${ACC} <= ${ACC}" ]] + then + echo "Success" + else + echo "Error" + echo "Output: " $output + exit 1 + fi +} + +function TEST_CHANGEAUTHOR +{ + echo "----------------------------------- TEST_CHANGEAUTHOR ----------------------------------------------------------------" + CLEAN_ASSETS_TABLE + + PUSH_CREATE_ASSET + + READ_ONE_ASSET + + PUSH_CHANGEAUTHOR + + READ_ONE_ASSET + + if [ "$asset_author" = "$ACC_TO" ] + then + echo "Success. changeauthor ACTION test was successfully passed" + else + echo "asset_author: " $asset_author + echo "Error. Author was not changed" + exit 1 + fi +} + unlock_wallet +# 2019-11-01 This test created after adding changeauthor action +TEST_CHANGEAUTHOR + # 2019-10-02 This test created after adding createntt claimntt burnntt actions TEST_CREATENTT_CLAIMNTT_BURNNTT diff --git a/include/SimpleAssets.hpp b/include/SimpleAssets.hpp index 5e67d79..5f89965 100644 --- a/include/SimpleAssets.hpp +++ b/include/SimpleAssets.hpp @@ -30,7 +30,7 @@ #include using namespace eosio; -using std::string; +using namespace std; CONTRACT SimpleAssets : public contract{ public: @@ -40,7 +40,7 @@ CONTRACT SimpleAssets : public contract{ * Update version. * * This action updates the version string of this SimpleAssets deployment for 3rd party wallets, - * marketplaces, etc. + * marketplaces, etc. * * @param version is version number of SimpleAssetst deployment. * @return no return value. @@ -52,8 +52,8 @@ CONTRACT SimpleAssets : public contract{ * New Author registration. * * This action registers a new new author account. It is not mandatory. Markets *may* choose to use - * information here to display information about the author, and to follow specifications expressed - * here for displaying asset fields. + * information here to display information about the author, and to follow specifications expressed + * here for displaying asset fields. * * @param author is author's account who will create assets. * @param data is stringified JSON. Recommendations to include: game, company, logo, url, desc. @@ -83,7 +83,7 @@ CONTRACT SimpleAssets : public contract{ * Authors info update. * * This action updates author's information and the asset display recommendations. This action replaces - * the fields data, stemplate, and imgpriority. + * the fields data, stemplate, and imgpriority. * To remove author entry, call this action with null strings for data, stemplate, and imgpriority. * * (See regauthor action for parameter info.) @@ -93,6 +93,17 @@ CONTRACT SimpleAssets : public contract{ ACTION authorupdate( name author, string data, string stemplate, string imgpriority ); using authorupdate_action = action_wrapper< "authorupdate"_n, &SimpleAssets::authorupdate >; + /* + * Change author. + * + * This action change author. This action replaces author name + * + * @return no return value. + */ + + ACTION changeauthor( name author, name newauthor, name owner, vector& assetids, string memo ); + using changeauthor_action = action_wrapper< "changeauthor"_n, &SimpleAssets::changeauthor >; + /* * Create a new asset. * @@ -104,9 +115,9 @@ CONTRACT SimpleAssets : public contract{ * @param idata is stringified JSON or sha256 string with immutable asset data. * @param mdata is stringified JSON or sha256 string with mutable asset data. It can be changed only by author. * @param requireclaim is true or false. If set to "false", the newly created asset will be transferred to the - * owner (but author's RAM will be used until the asset is transferred again). If set to - * "true", the author will remain to be the owner, but an offer will be created for the - * account specified in the owner field to claim the asset using the owner's RAM. + * owner (but author's RAM will be used until the asset is transferred again). If set to + * "true", the author will remain to be the owner, but an offer will be created for the + * account specified in the owner field to claim the asset using the owner's RAM. * @return no return value. */ ACTION create( name author, name category, name owner, string idata, string mdata, bool requireclaim ); @@ -125,13 +136,12 @@ CONTRACT SimpleAssets : public contract{ * @param idata is stringified JSON or sha256 string with immutable asset data. * @param mdata is stringified JSON or sha256 string with mutable asset data. It can be changed only by author. * @param requireclaim is true or false. If set to "false", the newly created asset will be transferred to the - * owner (but author's RAM will be used until the asset is transferred again). If set to - * "true", the author will remain to be the owner, but an offer will be created for the - * account specified in the owner field to claim the asset using the owner's RAM. + * owner (but author's RAM will be used until the asset is transferred again). If set to + * "true", the author will remain to be the owner, but an offer will be created for the + * account specified in the owner field to claim the asset using the owner's RAM. * @return no return value. */ - ACTION createlog( name author, name category, name owner, string idata, string mdata, uint64_t assetid, - bool requireclaim ); + ACTION createlog( name author, name category, name owner, string idata, string mdata, uint64_t assetid, bool requireclaim ); using createlog_action = action_wrapper< "createlog"_n, &SimpleAssets::createlog >; /* @@ -143,7 +153,7 @@ CONTRACT SimpleAssets : public contract{ * @param assetids is array of asset id's to claim. * @return no return value. */ - ACTION claim( name claimer, std::vector< uint64_t >& assetids ); + ACTION claim( name claimer, vector< uint64_t >& assetids ); using claim_action = action_wrapper< "claim"_n, &SimpleAssets::claim >; /* @@ -159,7 +169,7 @@ CONTRACT SimpleAssets : public contract{ * @param memo is transfers comment. * @return no return value. */ - ACTION transfer( name from, name to, std::vector< uint64_t >& assetids, string memo ); + ACTION transfer( name from, name to, vector< uint64_t >& assetids, string memo ); using transfer_action = action_wrapper< "transfer"_n, &SimpleAssets::transfer >; /* @@ -190,7 +200,7 @@ CONTRACT SimpleAssets : public contract{ * @param memo is memo for offer action. * @return no return value. */ - ACTION offer( name owner, name newowner, std::vector< uint64_t >& assetids, string memo ); + ACTION offer( name owner, name newowner, vector< uint64_t >& assetids, string memo ); using offer_action = action_wrapper< "offer"_n, &SimpleAssets::offer >; /* @@ -202,29 +212,29 @@ CONTRACT SimpleAssets : public contract{ * @param assetids - array of asset id's to cancel from offer. * @return no return value. */ - ACTION canceloffer( name owner, std::vector& assetids ); + ACTION canceloffer( name owner, vector& assetids ); using canceloffer_action = action_wrapper< "canceloffer"_n, &SimpleAssets::canceloffer >; /* * Burn asset. * * This action wil ldestroy the assets specified in {{assetids}}. This action is only available for the asset - * owner. After executing, the asset will disappear forever, and RAM used for asset will be released. All - * attached fungible and non-fungible assets will be destroyed too. + * owner. After executing, the asset will disappear forever, and RAM used for asset will be released. All + * attached fungible and non-fungible assets will be destroyed too. * * @param owner is current asset owner account. * @param assetids is array of asset id's to burn. * @param memo is memo for burn action. * @return no return value. */ - ACTION burn( name owner, std::vector< uint64_t >& assetids, string memo ); + ACTION burn( name owner, vector< uint64_t >& assetids, string memo ); using burn_action = action_wrapper< "burn"_n, &SimpleAssets::burn >; /* * Delegate assets. * * This action delegates asset to {{to}} account. This action changes the asset owner by calling the transfer - * action. It also adds a record in the delegates table to record the asset as borrowed. This blocks + * action. It also adds a record in the delegates table to record the asset as borrowed. This blocks * the asset from all owner actions (transfers, offers, burning by borrower). * * @param owner is current asset owner account. @@ -232,24 +242,24 @@ CONTRACT SimpleAssets : public contract{ * @param assetids is array of asset id's to delegate. * @param period is time in seconds that the asset will be lent for. The lender cannot undelegate until * the period expires, however the receiver can transfer back at any time. + * @param redelegate is allow more redelegate for to account or not. * @param memo is memo for delegate action. * @return no return value. */ - ACTION delegate( name owner, name to, std::vector< uint64_t >& assetids, uint64_t period, string memo ); + ACTION delegate( name owner, name to, vector< uint64_t >& assetids, uint64_t period, bool redelegate, string memo ); using delegate_action = action_wrapper< "delegate"_n, &SimpleAssets::delegate >; /* * Undelegate assets. * * This action undelegates assets from {{from}} account. Executing action by real owner will return asset - * immediately, and the entry in the delegates table recording the borrowing will be erased. + * immediately, and the entry in the delegates table recording the borrowing will be erased. * * @param owner is the account of real owner of the assets. - * @param from is current account owner (borrower). * @param assetids is array of asset id's to undelegate. * @return no return value. */ - ACTION undelegate( name owner, name from, std::vector< uint64_t >& assetids ); + ACTION undelegate( name owner, vector< uint64_t >& assetids ); using undelegate_action = action_wrapper< "undelegate"_n, &SimpleAssets::undelegate >; /* @@ -265,21 +275,21 @@ CONTRACT SimpleAssets : public contract{ * @param assetids is array of asset id's to attach. * @return no return value. */ - ACTION attach( name owner, uint64_t assetidc, std::vector< uint64_t >& assetids ); + ACTION attach( name owner, uint64_t assetidc, vector< uint64_t >& assetids ); using attach_action = action_wrapper< "attach"_n, &SimpleAssets::attach >; /* * Detach non-fungible token. * * This action detaches NFTs from the specified NFT. Only the owner of the container asset is - * allowed to execute this action. + * allowed to execute this action. * * @param owner is owner of NFTs. * @param assetidc is the id of the NFT from which we are detaching. * @param assetids is the array of id's of the NFTS to be detached. * @return no return value. */ - ACTION detach( name owner, uint64_t assetidc, std::vector< uint64_t >& assetids ); + ACTION detach( name owner, uint64_t assetidc, vector< uint64_t >& assetids ); using detach_t_action = action_wrapper< "detach"_n, &SimpleAssets::detach >; /* @@ -330,13 +340,13 @@ CONTRACT SimpleAssets : public contract{ * Creates fungible token. * * This action creates a fungible token with specified maximum supply. Maximum supply and author control - * cannot be modified after the token is created. + * cannot be modified after the token is created. * * @param author is fungible token author; * @param maximum_supply is maximum token supply, example "10000000.0000 GOLD", "10000000 SEED", - * "100000000.00 WOOD". The amount must specify the exact precision. + * "100000000.00 WOOD". The amount must specify the exact precision. * @param authorctrl is IMPORTANT! If true(1) allows token author (and not just owner) to burnf and transferf. - * Cannot be changed after creation! + * Cannot be changed after creation! * @param data is stringified JSON (recommend including keys `img` and `name` for better displaying by markets). * @return no return value. */ @@ -413,7 +423,7 @@ CONTRACT SimpleAssets : public contract{ * @param ftofferids is ID of the FT offer. * @return no return value. */ - ACTION cancelofferf( name owner, std::vector< uint64_t >& ftofferids ); + ACTION cancelofferf( name owner, vector< uint64_t >& ftofferids ); using cancelofferf_action = action_wrapper< "cancelofferf"_n, &SimpleAssets::cancelofferf >; /* @@ -425,15 +435,15 @@ CONTRACT SimpleAssets : public contract{ * @param ftofferids is array of FT offer id's. * @return no return value. */ - ACTION claimf( name claimer, std::vector< uint64_t >& ftofferids ); + ACTION claimf( name claimer, vector< uint64_t >& ftofferids ); using claimf_action = action_wrapper< "claimf"_n, &SimpleAssets::claimf >; /* * Burn fungible tokens * * This action burns a fungible token. This action is available for the token owner and author. - * After executing,accounts balance and supply in stats table for this token will reduce by the - * specified quantity. + * After executing,accounts balance and supply in stats table for this token will reduce by the + * specified quantity. * * @param from is account that burns the token. * @param author is account of fungible token author. @@ -545,7 +555,7 @@ CONTRACT SimpleAssets : public contract{ * @param assetids is array of NTT assetid's to claim. * @return no return value. */ - ACTION claimntt( name claimer, std::vector< uint64_t >& assetids ); + ACTION claimntt( name claimer, vector< uint64_t >& assetids ); using claimntt_action = action_wrapper< "claimntt"_n, &SimpleAssets::claimntt >; /* @@ -573,7 +583,7 @@ CONTRACT SimpleAssets : public contract{ * @param memo is memo for burn action. * @return no return value. */ - ACTION burnntt( name owner, std::vector< uint64_t >& assetids, string memo ); + ACTION burnntt( name owner, vector< uint64_t >& assetids, string memo ); using burnntt_action = action_wrapper< "burnntt"_n, &SimpleAssets::burnntt >; private: @@ -600,9 +610,11 @@ CONTRACT SimpleAssets : public contract{ void attachdeatch( name owner, name author, asset quantity, uint64_t assetidc, bool attach ); void sub_balancef( name owner, name author, asset value ); void add_balancef( name owner, name author, asset value, name ram_payer ); + void check_empty_vector( vector< uint64_t >& vector_ids, string vector_name = "assetids" ); + std::string timeToWait(uint64_t time_in_seconds); template - void sendEvent( name author, name rampayer, name seaction, const std::tuple &tup ); + void sendEvent( name author, name rampayer, name seaction, const tuple &tup ); /* * Authors table. Can be used by asset markets, asset explorers, or wallets for correct asset @@ -668,8 +680,8 @@ CONTRACT SimpleAssets : public contract{ name category; string idata; // immutable data string mdata; // mutable data - std::vector container; - std::vector containerf; + vector container; + vector containerf; auto primary_key() const { return id; @@ -793,6 +805,7 @@ CONTRACT SimpleAssets : public contract{ name delegatedto; uint64_t cdate; uint64_t period; + bool redelegate; string memo; auto primary_key() const { @@ -835,7 +848,7 @@ CONTRACT SimpleAssets : public contract{ */ TABLE tokenconfigs { name standard; - std::string version; + string version; }; typedef singleton< "tokenconfigs"_n, tokenconfigs > Configs; }; diff --git a/ricardian/SimpleAssets.contracts.md b/ricardian/SimpleAssets.contracts.md index 81bb79c..60fe334 100644 --- a/ricardian/SimpleAssets.contracts.md +++ b/ricardian/SimpleAssets.contracts.md @@ -67,6 +67,25 @@ TERM This Contract expires at the conclusion of code execution. by CryptoLions [ https://cryptolions.io ] +

changeauthor

+ +--- +spec_version: 0.0.2 +title: Change author of assets +summary: Change author of assets +icon: https://cryptolions.io/assets/images/sa-icons-256/regauthor.png#c6a539be8e7dfd1a4c466ba9cabfd13571cd77d5c988c652d2e8f87096f3548e +--- + +Input parameters: +`author` - asset's author, who will able to change author name asset's; +`newauthor` - asset's new author name; +`owner` - assets owner; +`assetids` - array of assetid's + +TERM +This Contract expires at the conclusion of code execution. +by CryptoLions [ https://cryptolions.io ] +

create

--- @@ -242,8 +261,8 @@ Input parameters: `assetids` - array of assetid's to delegate; `period` - time in seconds that the asset will be lent. Lender cannot undelegate until the period expires, however the receiver can transfer back at any time; +`redelegate`- allow more redelegate or not; `memo` - memo for delegate action; -`autoreturn`- automatic return for delegated action; TERM This Contract expires at the conclusion of code execution. @@ -262,7 +281,6 @@ Executing action by real owner will return asset immediately, and the entry in t Input parameters: `owner` - real asset owner account; -`from` - current account owner (borrower); `assetids` - array of assetid's to undelegate; TERM diff --git a/ricardian/SimpleAssets.contracts.md.in b/ricardian/SimpleAssets.contracts.md.in index e4fa4ab..bf3a067 100644 --- a/ricardian/SimpleAssets.contracts.md.in +++ b/ricardian/SimpleAssets.contracts.md.in @@ -67,6 +67,25 @@ TERM This Contract expires at the conclusion of code execution. by CryptoLions [ https://cryptolions.io ] +

changeauthor

+ +--- +spec_version: 0.0.2 +title: Change author of assets +summary: Change author of assets +icon: @ICON_BASE_URL@/@REGAUTHOR_ICON_URI@ +--- + +Input parameters: +`author` - asset's author, who will able to change author name asset's; +`newauthor` - asset's new author name; +`owner` - assets owner; +`assetids` - array of assetid's + +TERM +This Contract expires at the conclusion of code execution. +by CryptoLions [ https://cryptolions.io ] +

create

--- diff --git a/src/SimpleAssets.cpp b/src/SimpleAssets.cpp index 7000981..a493d49 100644 --- a/src/SimpleAssets.cpp +++ b/src/SimpleAssets.cpp @@ -7,6 +7,41 @@ ACTION SimpleAssets::updatever( string version ) { configs.set( tokenconfigs{ "simpleassets"_n, version }, _self ); } +ACTION SimpleAssets::changeauthor( name author, name newauthor, name owner, vector& assetids, string memo ) { + + require_auth( author ); + require_recipient( author ); + check_empty_vector( assetids ); + + sassets assets_f( _self, owner.value ); + offers offert( _self, _self.value ); + delegates delegatet( _self, _self.value ); + + map< name, map< uint64_t, name > > uniqauthor; + + for ( auto i = 0; i < assetids.size(); ++i ) { + + const auto itr = assets_f.require_find( assetids[i], string("asset id: " + to_string(assetids[i]) +" was not found").c_str() ); + + check( offert.find( assetids[i] ) == offert.end(), "At least one of the assets is already offered for claim. Asset id:" + to_string( assetids[i] ) ); + check( delegatet.find( assetids[i] ) == delegatet.end(), "At least one of the assets is delegated and cannot be offered. Asset id: " + to_string( assetids[i] ) ); + check( itr->author == author, "Only author can update asset." ); + check( !( itr->container.size() != 0 ), "Asset has items in non-fungible container" ); + check( !( itr->containerf.size() != 0 ), "Asset has items in funible container" ); + + assets_f.modify( itr, author, [&]( auto& a ) { + a.author = newauthor; + }); + uniqauthor[itr->author][assetids[i]] = itr->owner; + } + + // Send Event as deferred + for ( auto uniqauthorIt = uniqauthor.begin(); uniqauthorIt != uniqauthor.end(); ++uniqauthorIt ) { + name keyauthor = move( uniqauthorIt->first ); + sendEvent( keyauthor, author, "saechauthor"_n, make_tuple( author, newauthor, owner, uniqauthor[keyauthor], memo ) ); + } +} + ACTION SimpleAssets::regauthor( name author, string data, string stemplate, string imgpriority ) { require_auth( author ); @@ -32,8 +67,8 @@ ACTION SimpleAssets::authorupdate( name author, string data, string stemplate, s require_auth( author ); require_recipient( author ); authors author_( _self, _self.value ); - auto itr = author_.find( author.value ); - check( itr != author_.end(), "author not registered" ); + + auto itr = author_.require_find( author.value, string("author " + author.to_string() + " not registered").c_str() ); if ( data.empty() && stemplate.empty() ) { itr = author_.erase( itr ); @@ -79,7 +114,7 @@ ACTION SimpleAssets::create( name author, name category, name owner, string idat }); //Events - sendEvent( author, author, "saecreate"_n, std::make_tuple( owner, newID ) ); + sendEvent( author, author, "saecreate"_n, make_tuple( owner, newID ) ); SEND_INLINE_ACTION( *this, createlog, { {_self, "active"_n} }, { author, category, owner, idata, mdata, newID, requireclaim } ); } @@ -88,23 +123,28 @@ ACTION SimpleAssets::createlog( name author, name category, name owner, string i require_auth(get_self()); } -ACTION SimpleAssets::claim( name claimer, std::vector& assetids ) { +ACTION SimpleAssets::claim( name claimer, vector& assetids ) { require_auth( claimer ); require_recipient( claimer ); + + check_empty_vector( assetids ); + offers offert( _self, _self.value ); sassets assets_t( _self, claimer.value ); - std::map< name, std::map< uint64_t, name > > uniqauthor; + map< name, map< uint64_t, name > > uniqauthor; for ( auto i = 0; i < assetids.size(); ++i ) { - auto itrc = offert.find( assetids[i] ); - check( itrc != offert.end(), "Cannot find at least one of the assets you're attempting to claim." ); - check( claimer == itrc->offeredto, "At least one of the assets has not been offerred to you." ); + + auto itrc = offert.require_find( assetids[i], string("Cannot find offer for asset id: " + to_string(assetids[i]) + " that you're attempting to claim.").c_str() ); + + check( claimer == itrc->offeredto, "Asset id: " + to_string(assetids[i]) + " has not been offerred to you. It offered to " + itrc->offeredto.to_string() ); sassets assets_f( _self, itrc->owner.value ); - auto itr = assets_f.find( assetids[i] ); - check( itr != assets_f.end(), "Cannot find at least one of the assets you're attempting to claim." ); - check( itrc->owner.value == itr->owner.value, "Owner was changed for at least one of the items!?" ); + + auto itr = assets_f.require_find(assetids[i], string("Cannot find asset id: " + to_string(assetids[i]) + " that you're attempting to claim at scope: " + itrc->owner.to_string()).c_str()); + + check( itrc->owner.value == itr->owner.value, "Owner was changed for asset id:" + to_string(assetids[i]) + " .Owner at offers:" + itrc->owner.to_string() + " . Owner at assets: " + itr->owner.to_string() ); assets_t.emplace( claimer, [&]( auto& s ) { s.id = itr->id; @@ -125,17 +165,23 @@ ACTION SimpleAssets::claim( name claimer, std::vector& assetids ) { } for ( auto uniqauthorIt = uniqauthor.begin(); uniqauthorIt != uniqauthor.end(); ++uniqauthorIt ) { - name keyauthor = std::move( uniqauthorIt->first ); - sendEvent( keyauthor, claimer, "saeclaim"_n, std::make_tuple( claimer, uniqauthor[keyauthor] ) ); + name keyauthor = move( uniqauthorIt->first ); + sendEvent( keyauthor, claimer, "saeclaim"_n, make_tuple( claimer, uniqauthor[keyauthor] ) ); } } -ACTION SimpleAssets::transfer( name from, name to, std::vector& assetids, string memo ) { +void SimpleAssets::check_empty_vector( vector& vector_ids, string vector_name ) { + + check( !(vector_ids.size() == 0), "Please add values to parameter: " + move(vector_name) ); +} + +ACTION SimpleAssets::transfer( name from, name to, vector& assetids, string memo ) { check( from != to, "cannot transfer to yourself" ); check( is_account( to ), "TO account does not exist" ); check( memo.size() <= 256, "memo has more than 256 bytes" ); - + check_empty_vector( assetids ); + require_recipient( from ); require_recipient( to ); @@ -149,7 +195,7 @@ ACTION SimpleAssets::transfer( name from, name to, std::vector& asseti bool isDelegeting = false; - std::map< name, std::vector > uniqauthor; + map< name, vector > uniqauthor; for ( auto i = 0; i < assetids.size(); ++i ) { auto itrd = delegatet.find( assetids[i] ); @@ -162,7 +208,7 @@ ACTION SimpleAssets::transfer( name from, name to, std::vector& asseti } } else { - check( false, "At least one of the assets cannot be transferred because it is delegated" ); + check( false, "Asset id: " + to_string(assetids[i]) + " cannot be transferred because it is delegated to " + itrd->delegatedto.to_string() ); } } @@ -173,10 +219,10 @@ ACTION SimpleAssets::transfer( name from, name to, std::vector& asseti require_auth( from ); } - auto itr = assets_f.find( assetids[i] ); - check( itr != assets_f.end(), "At least one of the assets cannot be found (check ids?)" ); - check( from.value == itr->owner.value, "At least one of the assets is not yours to transfer." ); - check( offert.find( assetids[i] ) == offert.end(), "At least one of the assets has been offered for a claim and cannot be transferred. Cancel offer?" ); + const auto itr = assets_f.require_find( assetids[i], string("Asset id: " + to_string(assetids[i]) + " cannot be found (check ids?)").c_str() ); + + check( from.value == itr->owner.value, "Asset id: " + to_string(assetids[i]) + " is not yours to transfer. Owner: " + itr->owner.to_string() ); + check( offert.find( assetids[i] ) == offert.end(), "Asset id: " + to_string(assetids[i]) + " offered for a claim and cannot be transferred. Cancel offer?" ); assets_t.emplace( rampayer, [&]( auto& s ) { s.id = itr->id; @@ -197,8 +243,8 @@ ACTION SimpleAssets::transfer( name from, name to, std::vector& asseti //Send Event as deferred for ( auto uniqauthorIt = uniqauthor.begin(); uniqauthorIt != uniqauthor.end(); ++uniqauthorIt ) { - name keyauthor = std::move( uniqauthorIt->first ); - sendEvent( keyauthor, rampayer, "saetransfer"_n, std::make_tuple( from, to, uniqauthor[keyauthor], memo ) ); + name keyauthor = move( uniqauthorIt->first ); + sendEvent( keyauthor, rampayer, "saetransfer"_n, make_tuple( from, to, uniqauthor[keyauthor], memo ) ); } } @@ -206,31 +252,33 @@ ACTION SimpleAssets::update( name author, name owner, uint64_t assetid, string m require_auth( author ); sassets assets_f( _self, owner.value ); - const auto itr = assets_f.find( assetid ); - check( itr != assets_f.end(), "asset not found" ); - check( itr->author == author, "Only author can update asset." ); + const auto itr = assets_f.require_find( assetid, string("asset id: " + to_string(assetid) + " not found").c_str() ); + + check( itr->author == author, "Only for author allowed to update asset. Asset id: " + to_string(assetid) + " has author: " + itr->author.to_string() + " ,you entered author: " + author.to_string() ); assets_f.modify( itr, author, [&]( auto& a ) { a.mdata = mdata; }); } -ACTION SimpleAssets::offer( name owner, name newowner, std::vector& assetids, string memo ) { +ACTION SimpleAssets::offer( name owner, name newowner, vector& assetids, string memo ) { check( owner != newowner, "cannot offer to yourself" ); + check_empty_vector( assetids ); + require_auth( owner ); require_recipient( owner ); require_recipient( newowner ); - check( is_account( newowner ), "newowner account does not exist" ); + check( is_account( newowner ), "newowner account: " + newowner.to_string() + " does not exist" ); sassets assets_f( _self, owner.value ); offers offert( _self, _self.value ); delegates delegatet( _self, _self.value ); for ( auto i = 0; i < assetids.size(); ++i ) { - check( assets_f.find( assetids[i] ) != assets_f.end(), "At least one of the assets was not found." ); - check( offert.find( assetids[i] ) == offert.end(), "At least one of the assets is already offered for claim." ); - check( delegatet.find( assetids[i] ) == delegatet.end(), "At least one of the assets is delegated and cannot be offered." ); + check( assets_f.find ( assetids[i] ) != assets_f.end(), "Asset id: " + to_string(assetids[i]) + " was not found." ); + check( offert.find ( assetids[i] ) == offert.end(), "Asset id: " + to_string(assetids[i]) + " is already offered for claim." ); + check( delegatet.find( assetids[i] ) == delegatet.end(), "Asset id: " + to_string(assetids[i]) + " is delegated and cannot be offered." ); offert.emplace( owner, [&]( auto& s ) { s.assetid = assetids[i]; @@ -241,35 +289,41 @@ ACTION SimpleAssets::offer( name owner, name newowner, std::vector& as } } -ACTION SimpleAssets::canceloffer( name owner, std::vector& assetids ) { +ACTION SimpleAssets::canceloffer( name owner, vector& assetids ) { + + check_empty_vector( assetids ); require_auth( owner ); require_recipient( owner ); offers offert( _self, _self.value ); for ( auto i = 0; i < assetids.size(); ++i ) { - auto itr = offert.find( assetids[i] ); - check( itr != offert.end(), "The offer for at least one of the assets was not found." ); - check( owner.value == itr->owner.value, "You're not the owner of at least one of the assets whose offers you're attempting to cancel." ); + + auto itr = offert.require_find( assetids[i], string("The offer for asset id: " + to_string(assetids[i]) + " was not found.").c_str() ); + + check( owner.value == itr->owner.value, "You're not the owner of asset id: " + to_string(assetids[i]) + " whose offers you're attempting to cancel. Owner is " + itr->owner.to_string()); offert.erase( itr ); } } -ACTION SimpleAssets::burn( name owner, std::vector& assetids, string memo ) { +ACTION SimpleAssets::burn( name owner, vector& assetids, string memo ) { + + check_empty_vector( assetids ); require_auth( owner ); sassets assets_f( _self, owner.value ); offers offert( _self, _self.value ); delegates delegatet( _self, _self.value ); - std::map< name, std::vector > uniqauthor; + map< name, vector > uniqauthor; for ( auto i = 0; i < assetids.size(); ++i ) { - auto itr = assets_f.find( assetids[i] ); - check( itr != assets_f.end(), "At least one of the assets was not found." ); - check( owner.value == itr->owner.value, "At least one of the assets you're attempting to burn is not yours." ); - check( offert.find( assetids[i] ) == offert.end(), "At least one of the assets has an open offer and cannot be burned." ); - check( delegatet.find( assetids[i] ) == delegatet.end(), "At least one of assets is delegated and cannot be burned." ); + + auto itr = assets_f.require_find( assetids[i], string("Asset id: " + to_string(assetids[i]) + " was not found.").c_str() ); + + check( owner.value == itr->owner.value, "Asset id: " + to_string(assetids[i]) + " you're attempting to burn is not yours. Owner is " + itr->owner.to_string() + ", you entered owner " + owner.to_string()); + check( offert.find( assetids[i] ) == offert.end(), "Asset id: " + to_string(assetids[i]) + " has an open offer and cannot be burned." ); + check( delegatet.find( assetids[i] ) == delegatet.end(), "Asset id: " + to_string(assetids[i]) + " is delegated and cannot be burned." ); //Events uniqauthor[itr->author].push_back( assetids[i] ); @@ -278,15 +332,18 @@ ACTION SimpleAssets::burn( name owner, std::vector& assetids, string m //Send Event as deferred for ( auto uniqauthorIt = uniqauthor.begin(); uniqauthorIt != uniqauthor.end(); ++uniqauthorIt ) { - name keyauthor = std::move( uniqauthorIt->first ); - sendEvent( keyauthor, owner, "saeburn"_n, std::make_tuple( owner, uniqauthor[keyauthor], memo ) ); + name keyauthor = move( uniqauthorIt->first ); + sendEvent( keyauthor, owner, "saeburn"_n, make_tuple( owner, uniqauthor[keyauthor], memo ) ); } } -ACTION SimpleAssets::delegate( name owner, name to, std::vector& assetids, uint64_t period, string memo ) { +ACTION SimpleAssets::delegate( name owner, name to, vector& assetids, uint64_t period, bool redelegate, string memo ) { - check(memo.size() <= 64, "Error. Size of memo cannot be bigger 64"); + check( memo.size() <= 64, "Size of memo cannot be bigger 64" ); check( owner != to, "cannot delegate to yourself" ); + + check_empty_vector( assetids ); + require_auth( owner ); require_recipient( owner ); check( is_account( to ), "TO account does not exist" ); @@ -296,18 +353,30 @@ ACTION SimpleAssets::delegate( name owner, name to, std::vector& asset offers offert( _self, _self.value ); for ( auto i = 0; i < assetids.size(); ++i ) { - check( assets_f.find( assetids[i] ) != assets_f.end(), "At least one of the assets cannot be found." ); - check( delegatet.find( assetids[i] ) == delegatet.end(), "At least one of the assets is already delegated." ); - check( offert.find( assetids[i] ) == offert.end(), "At least one of the assets has an open offer and cannot be delegated." ); - - delegatet.emplace( owner, [&]( auto& s ) { - s.assetid = assetids[i]; - s.owner = owner; - s.delegatedto = to; - s.cdate = current_time_point().sec_since_epoch(); - s.period = period; - s.memo = memo; - }); + check( assets_f.find( assetids[i] ) != assets_f.end(), "Asset id: " + to_string( assetids[i] ) + " cannot be found at scope " + owner.to_string() ); + check( offert.find( assetids[i] ) == offert.end(), "Asset id: " + to_string( assetids[i] ) + " has an open offer and cannot be delegated." ); + + if ( auto itr_delegated = delegatet.find( assetids[i] ); itr_delegated != delegatet.end() ) + { + check( !( itr_delegated->redelegate == false ), "For asset id:" + to_string( assetids[i] ) + " .Terms of delegation forbid re-delegation." ); + check( !( itr_delegated->owner == to ), "For asset id:" + to_string( assetids[i] ) + " .Not allowed re-delegate to original owner of asset" ); + + delegatet.modify(itr_delegated, owner, [&](auto& s) { + s.delegatedto = to; + s.redelegate = redelegate; + }); + } + else { + delegatet.emplace(owner, [&](auto& s) { + s.assetid = assetids[i]; + s.owner = owner; + s.delegatedto = to; + s.cdate = current_time_point().sec_since_epoch(); + s.period = period; + s.redelegate = redelegate; + s.memo = memo; + }); + } } transfer( owner, to, assetids, "Delegate memo: " + memo ); @@ -319,63 +388,75 @@ ACTION SimpleAssets::delegatemore( name owner, uint64_t assetidc, uint64_t perio require_recipient( owner ); delegates delegatet( _self, _self.value ); - const auto itrc = delegatet.find( assetidc ); - check( itrc != delegatet.end(), "Assets assetidc is not delegated." ); - check( owner == itrc->owner, "You are not the owner of this asset." ); + + const auto itrc = delegatet.require_find( assetidc, string("Assets id: " + to_string( assetidc ) + " is not delegated.").c_str() ); + + check( owner == itrc->owner, "You are not the owner of asset id: " + to_string(assetidc) + ". Owner is: " + itrc->owner.to_string() + " , you entered: " + owner.to_string() ); delegatet.modify( itrc, owner, [&]( auto& s ) { s.period = itrc->period + period; }); } -ACTION SimpleAssets::undelegate( name owner, name from, std::vector& assetids ) { - +ACTION SimpleAssets::undelegate( name owner, vector& assetids ) { + require_auth( owner ); require_recipient( owner ); - check( is_account( from ), "to account does not exist" ); + check_empty_vector( assetids ); - sassets assets_f( _self, from.value ); delegates delegatet( _self, _self.value ); + const auto itrc = delegatet.require_find( assetids[0], string( "Asset id: " + to_string( assetids[0] ) + " is not delegated" ).c_str() ); + name from = itrc->delegatedto; + + sassets assets_f( _self, from.value ); string assetidsmemo; for ( auto i = 0; i < assetids.size(); ++i ) { - auto itr = assets_f.find( assetids[i] ); - check( itr != assets_f.end(), "At least one of the assets cannot be found." ); - auto itrc = delegatet.find( assetids[i] ); - check( itrc != delegatet.end(), "At least one of the assets is not delegated." ); - check( owner == itrc->owner, "You are not the owner of at least one of these assets." ); - check( from == itrc->delegatedto, "FROM does not match DELEGATEDTO for at least one of the assets." ); - check( itr->owner == itrc->delegatedto, "FROM does not match DELEGATEDTO for at least one of the assets." ); - check( ( itrc->cdate + itrc->period ) < current_time_point().sec_since_epoch(), "Cannot undelegate until the PERIOD expires." ); + + const auto itrc = delegatet.require_find( assetids[i], string( "Asset id: " + to_string( assetids[i] ) + " is not delegated").c_str() ); + check( owner == itrc->owner, "You are not the owner of asset id: " + to_string( assetids[i]) + ". Owner is: " + itrc->owner.to_string() + " , you entered: " + owner.to_string() ); + check( !(from != itrc->delegatedto), "All delegated assets in assetids must be delegated to one account. For asset id: " + to_string( assetids[i] ) + " delegatedto = " + itrc->delegatedto.to_string() + " but it must be same with first asset which has delegatedto = " + from.to_string()); + + const auto itr = assets_f.require_find(assetids[i], string("Asset id: " + to_string(assetids[i]) + " cannot be found in scope " + from.to_string()).c_str()); + check( itr->owner == itrc->delegatedto, "Owner does not match DELEGATEDTO for asset id: " + to_string( assetids[i] ) + " .Owner = " + itr->owner.to_string() + " but it must be " + itrc->delegatedto.to_string() + " for this asset"); + + check((itrc->cdate + itrc->period) < current_time_point().sec_since_epoch(), + "Cannot undelegate until the PERIOD expires. " + timeToWait(abs((int)((uint64_t)(itrc->cdate + itrc->period) - (uint64_t)current_time_point().sec_since_epoch())))); if ( i != 0 ) { assetidsmemo += ", "; } - assetidsmemo += std::to_string( assetids[i] ); + assetidsmemo += to_string( assetids[i] ); } transfer( from, owner, assetids, "undelegate assetid: " + assetidsmemo ); } -ACTION SimpleAssets::attach( name owner, uint64_t assetidc, std::vector& assetids ) { +ACTION SimpleAssets::attach( name owner, uint64_t assetidc, vector& assetids ) { + + check_empty_vector( assetids ); sassets assets_f( _self, owner.value ); delegates delegatet( _self, _self.value ); offers offert( _self, _self.value ); require_recipient( owner ); - const auto ac_ = assets_f.find( assetidc ); - check( ac_ != assets_f.end(), "Asset cannot be found." ); + + const auto ac_ = assets_f.require_find( assetidc, string("assetidc : " + to_string( assetidc ) + " cannot be found").c_str() ); + require_auth( ac_->author ); for ( auto i = 0; i < assetids.size(); ++i ) { - auto itr = assets_f.find( assetids[i] ); - check( itr != assets_f.end(), "At least one of the assets cannot be found." ); - check( assetidc != assetids[i], "Cannot attcach to self." ); - check( itr->author == ac_->author, "Different authors." ); - check( delegatet.find( assetids[i] ) == delegatet.end(), "At least one of the assets is delegated." ); - check( offert.find( assetids[i] ) == offert.end(), "At least one of the assets has an open offer and cannot be delegated." ); + + auto itr = assets_f.require_find( assetids[i], string("assetids asset id: " + to_string( assetidc ) + " cannot be found").c_str() ); + + check( assetidc != assetids[i], "Cannot attcach to self" ); + check( itr->author == ac_->author, + "Different authors. For asset id: " + to_string( assetids[i] ) + " author is " + itr->author.to_string() + " but for assetidc : " + to_string( assetidc ) + " author is " + ac_->author.to_string() ); + + check( delegatet.find( assetids[i] ) == delegatet.end(), "Asset id: " + to_string(assetids[i]) + " is delegated." ); + check( offert.find( assetids[i] ) == offert.end(), "Asset id " + to_string(assetids[i]) + " has an open offer and cannot be delegated." ); assets_f.modify( ac_, ac_->author, [&]( auto& a ) { a.container.push_back( *itr ); @@ -384,20 +465,22 @@ ACTION SimpleAssets::attach( name owner, uint64_t assetidc, std::vector& assetids ) { +ACTION SimpleAssets::detach( name owner, uint64_t assetidc, vector& assetids ) { + + check_empty_vector( assetids ); require_auth( owner ); require_recipient( owner ); sassets assets_f( _self, owner.value ); - const auto ac_ = assets_f.find( assetidc ); - check( ac_ != assets_f.end(), "Asset cannot be found." ); + const auto ac_ = assets_f.require_find( assetidc, string("assetidc: " + to_string(assetidc) + " cannot be found").c_str() ); delegates delegatet( _self, _self.value ); - check( delegatet.find( assetidc ) == delegatet.end(), "Cannot detach from delegated. assetidc is delegated." ); + const auto itr = delegatet.find( assetidc ); + check( itr == delegatet.end(), "Cannot detach from delegated. assetidc " + to_string(assetidc) + " is delegated." ); for ( auto i = 0; i < assetids.size(); ++i ) { - std::vector newcontainer; + vector newcontainer; for ( auto j = 0; j < ac_->container.size(); ++j ) { auto acc = ac_->container[j]; @@ -476,8 +559,7 @@ ACTION SimpleAssets::issuef( name to, name author, asset quantity, string memo ) check( memo.size() <= 256, "memo has more than 256 bytes" ); stats statstable( _self, author.value ); - const auto existing = statstable.find( sym.code().raw() ); - check( existing != statstable.end(), "token with symbol does not exist, create token before issue" ); + const auto existing = statstable.require_find( sym.code().raw(), "token with symbol does not exist, create token before issue" ); require_auth( existing->issuer ); check( quantity.is_valid(), "invalid quantity" ); @@ -531,15 +613,14 @@ ACTION SimpleAssets::offerf( name owner, name newowner, name author, asset quant require_auth( owner ); require_recipient( owner ); require_recipient( newowner ); - check( is_account( newowner ), "newowner account does not exist" ); + check( is_account( newowner ), "newowner account " + newowner.to_string() +" does not exist" ); check( owner != newowner, "cannot offer to yourself" ); const auto sym = quantity.symbol; check( sym.is_valid(), "invalid symbol name" ); check( memo.size() <= 256, "memo has more than 256 bytes" ); stats statstable( _self, author.value ); - const auto existing = statstable.find( sym.code().raw() ); - check( existing != statstable.end(), "token with symbol does not exist" ); + const auto existing = statstable.require_find( sym.code().raw(), "token with symbol does not exist" ); check( quantity.is_valid(), "invalid quantity" ); check( quantity.amount > 0, "must retire positive quantity" ); check( quantity.symbol == existing->supply.symbol, "symbol precision mismatch" ); @@ -572,32 +653,36 @@ ACTION SimpleAssets::offerf( name owner, name newowner, name author, asset quant sub_balancef( owner, author, quantity ); } -ACTION SimpleAssets::cancelofferf( name owner, std::vector& ftofferids ) { +ACTION SimpleAssets::cancelofferf( name owner, vector& ftofferids ) { + + check_empty_vector( ftofferids, "ftofferids" ); require_auth( owner ); require_recipient( owner ); offerfs offert( _self, _self.value ); for ( auto i = 0; i < ftofferids.size(); ++i ) { - auto itr = offert.find( ftofferids[i] ); - check( itr != offert.end(), "The offer for at least one of the FT was not found." ); - check( owner.value == itr->owner.value, "You're not the owner of at least one of those FTs." ); + const auto itr = offert.require_find( ftofferids[i], string("The offer id " + to_string( ftofferids[i] ) + " was not found").c_str() ); + + check( owner.value == itr->owner.value, "Owner was changed for asset id:" + to_string( ftofferids[i]) + " .Owner is" + itr->owner.to_string() + " , you entered " + owner.to_string() ); + add_balancef( owner, itr->author, itr->quantity, owner ); offert.erase( itr ); } } -ACTION SimpleAssets::claimf( name claimer, std::vector& ftofferids ) { +ACTION SimpleAssets::claimf( name claimer, vector& ftofferids ) { + + check_empty_vector( ftofferids, "ftofferids" ); require_auth( claimer ); require_recipient( claimer ); offerfs offert( _self, _self.value ); - std::map< name, std::vector< uint64_t > > uniqauthor; + map< name, vector< uint64_t > > uniqauthor; for ( auto i = 0; i < ftofferids.size(); ++i ) { - auto itrc = offert.find( ftofferids[i] ); - check( itrc != offert.end(), "Cannot find at least one of the FT you're attempting to claim." ); - check( claimer == itrc->offeredto, "At least one of the FTs has not been offerred to you." ); + auto itrc = offert.require_find( ftofferids[i], string("Cannot find offer for asset id: " + to_string(ftofferids[i]) + " attempting to claim.").c_str() ); + check( claimer == itrc->offeredto, "Asset id: " + to_string(ftofferids[i]) + " has not been offerred to you. It offered to " + itrc->offeredto.to_string() ); add_balancef( claimer, itrc->author, itrc->quantity, claimer ); offert.erase( itrc ); } @@ -610,8 +695,8 @@ ACTION SimpleAssets::burnf( name from, name author, asset quantity, string memo check( memo.size() <= 256, "memo has more than 256 bytes" ); stats statstable( _self, author.value ); - const auto existing = statstable.find( sym.code().raw() ); - check( existing != statstable.end(), "token with symbol does not exist" ); + const auto existing = statstable.require_find( sym.code().raw(), "token with symbol does not exist" ); + require_auth( existing->authorctrl && has_auth( existing->issuer ) ? existing->issuer : from ); check( quantity.is_valid(), "invalid quantity" ); @@ -646,8 +731,7 @@ ACTION SimpleAssets::closef( name owner, name author, const symbol& symbol ) { require_auth( owner ); accounts acnts( _self, owner.value ); - auto it = acnts.find( getFTIndex( author, symbol ) ); - check( it != acnts.end(), "Balance row already deleted or never existed. Action won't have any effect." ); + auto it = acnts.require_find( getFTIndex( author, symbol ), "Balance row already deleted or never existed. Action won't have any effect" ); check( it->balance.amount == 0, "Cannot close because the balance is not zero." ); offerfs offert( _self, _self.value ); @@ -682,9 +766,7 @@ uint64_t SimpleAssets::getid( bool defer ) { uint64_t SimpleAssets::getFTIndex( name author, symbol symbol ) { stats statstable( _self, author.value ); - const auto existing = statstable.find( symbol.code().raw() ); - check( existing != statstable.end(), "token with symbol does not exist." ); - return existing->id; + return statstable.require_find(symbol.code().raw(), "token with symbol does not exist")->id; } void SimpleAssets::attachdeatch( name owner, name author, asset quantity, uint64_t assetidc, bool attach ) { @@ -700,7 +782,7 @@ void SimpleAssets::attachdeatch( name owner, name author, asset quantity, uint64 check( quantity.is_valid(), "invalid quantity" ); check( quantity.amount > 0, "must transfer positive quantity" ); check( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); - check( st.issuer == author, "Different authors" ); + check( st.issuer == author, "Different authors. For asset " + quantity.to_string() + " issuer is " + st.issuer.to_string() + " you entered author = " + author.to_string() ); if ( attach ) { require_auth( author ); //attach @@ -709,13 +791,17 @@ void SimpleAssets::attachdeatch( name owner, name author, asset quantity, uint64 require_auth( owner ); //deatach } - const auto itr = assets_f.find( assetidc ); - check( itr != assets_f.end(), "assetid cannot be found." ); - check( itr->author == author, "Different authors." ); - check( delegatet.find(assetidc) == delegatet.end(), "Asset is delegated." ); - check( offert.find(assetidc) == offert.end(), "Assets has an open offer and cannot be delegated." ); + const auto itr = assets_f.require_find( assetidc, string("assetid " + to_string( assetidc ) + " cannot be found").c_str() ); + + check( itr->author == author, "Different authors. For asset id: " + to_string( assetidc ) + " author is " + itr->author.to_string() + " you entered author = " + author.to_string() ); + + const auto itr_delegeted = delegatet.find( assetidc ); + check( itr_delegeted == delegatet.end(), "Asset id: " + to_string( assetidc ) + " is delegated to " + itr_delegeted->delegatedto.to_string() ); + + const auto itr_offered = offert.find( assetidc ); + check( itr_offered == offert.end(), "Asset id: " + to_string( assetidc ) + " has an open offer to " + itr_offered->offeredto.to_string() + "and cannot be delegated." ); - std::vector newcontainerf; + vector newcontainerf; bool found = false; for ( auto j = 0; j < itr->containerf.size(); j++ ) { @@ -793,7 +879,7 @@ void SimpleAssets::add_balancef( name owner, name author, asset value, name ram_ ACTION SimpleAssets::createntt( name author, name category, name owner, string idata, string mdata, bool requireclaim ) { require_auth( author ); - check( is_account( owner ), "owner account does not exist" ); + check( is_account( owner ), "owner account " + owner.to_string() + " does not exist" ); require_recipient( owner ); const auto newID = getid(); name assetOwner = owner; @@ -833,32 +919,37 @@ ACTION SimpleAssets::updatentt( name author, name owner, uint64_t assetid, strin require_auth(author); snttassets assets_f(_self, owner.value); - const auto itr = assets_f.find(assetid); - check(itr != assets_f.end(), "asset not found"); - check(itr->author == author, "Only author can update asset."); + + const auto itr = assets_f.require_find( assetid, string("asset id: " + to_string(assetid) + " not found").c_str() ); + + check( itr->author == author, "Only for author allowed to update asset. Asset id: " + to_string( assetid ) + " has author: " + itr->author.to_string() + " ,you entered author: " + author.to_string() ); assets_f.modify(itr, author, [&](auto& a) { a.mdata = mdata; }); } -ACTION SimpleAssets::claimntt( name claimer, std::vector& assetids ) { +ACTION SimpleAssets::claimntt( name claimer, vector& assetids ) { + + check_empty_vector( assetids ); require_auth( claimer ); require_recipient( claimer ); nttoffers nttoffert( _self, _self.value ); snttassets assets_claimer( _self, claimer.value ); - std::map< name, std::map< uint64_t, name > > uniqauthor; + map< name, map< uint64_t, name > > uniqauthor; for ( auto i = 0; i < assetids.size(); ++i ) { - auto itrc = nttoffert.find( assetids[i] ); - check( !( itrc == nttoffert.end() ), "Cannot find at least one of the offers you're attempting to claim." ); - check( claimer == itrc->offeredto, "At least one of the assets has not been offerred to you." ); + + auto itrc = nttoffert.require_find( assetids[i], string("Cannot find offer for asset id: " + to_string( assetids[i] ) + " that you're attempting to claim.").c_str()); + + check( claimer == itrc->offeredto, "Asset id: " + to_string(assetids[i]) + " has not been offerred to you. It offered to " + itrc->offeredto.to_string() ); snttassets assets_owner( _self, itrc->owner.value ); - auto itr = assets_owner.find( assetids[i] ); - check( !(itr == assets_owner.end() ), "Cannot find at least one of the assets you're attempting to claim." ); - check( itrc->owner.value == itr->owner.value, "Owner was changed for at least one of the items!?" ); + + auto itr = assets_owner.require_find( assetids[i], string("Cannot find asset id: " + to_string( assetids[i] ) + " that you're attempting to claim at scope: " + itrc->owner.to_string()).c_str() ); + + check( itrc->owner.value == itr->owner.value, "Owner was changed for asset id:" + to_string(assetids[i]) + " .Owner at offers:" + itrc->owner.to_string() + " . Owner at assets: " + itr->owner.to_string() ); assets_claimer.emplace( claimer, [&](auto& s) { s.id = itr->id; @@ -877,12 +968,12 @@ ACTION SimpleAssets::claimntt( name claimer, std::vector& assetids ) { } //for ( auto uniqauthorIt = uniqauthor.begin(); uniqauthorIt != uniqauthor.end(); ++uniqauthorIt ) { - // name keyauthor = std::move( uniqauthorIt->first ); - // sendEvent( keyauthor, claimer, "saeclaim"_n, std::make_tuple( claimer, uniqauthor[keyauthor] ) ); + // name keyauthor = move( uniqauthorIt->first ); + // sendEvent( keyauthor, claimer, "saeclaim"_n, make_tuple( claimer, uniqauthor[keyauthor] ) ); //} } -ACTION SimpleAssets::burnntt( name owner, std::vector& assetids, string memo ) { +ACTION SimpleAssets::burnntt( name owner, vector& assetids, string memo ) { require_auth( owner ); require_recipient( owner ); @@ -891,13 +982,13 @@ ACTION SimpleAssets::burnntt( name owner, std::vector& assetids, strin nttoffers nttoffert( _self, _self.value ); for ( auto i = 0; i < assetids.size(); ++i ) { - auto itr_asset = assets_ntt.find( assetids[i] ); - check( itr_asset != assets_ntt.end(), "At least one of the assets was not found." ); + + auto itr_asset = assets_ntt.require_find( assetids[i], string("Asset id: " + to_string(assetids[i]) + " was not found." ).c_str()); auto itroffer = nttoffert.find( assetids[i] ); if ( itroffer != nttoffert.end() ) { - check( owner.value == itroffer->owner.value, "You're not the owner of at least one of the assets whose offers you're attempting to cancel." ); + check(owner.value == itroffer->owner.value, "You're not the owner of Asset id: " + to_string(assetids[i]) + " you're attempting to burn. Owner at offer is " + itroffer->owner.to_string() + ", you entered owner " + owner.to_string()); nttoffert.erase( itroffer ); } @@ -906,14 +997,14 @@ ACTION SimpleAssets::burnntt( name owner, std::vector& assetids, strin //Send Event as deferred //for ( auto uniqauthorIt = uniqauthor.begin(); uniqauthorIt != uniqauthor.end(); ++uniqauthorIt ) { - // name keyauthor = std::move( uniqauthorIt->first ); - // sendEvent( keyauthor, owner, "saeburn"_n, std::make_tuple( owner, uniqauthor[keyauthor], memo ) ); + // name keyauthor = move( uniqauthorIt->first ); + // sendEvent( keyauthor, owner, "saeburn"_n, make_tuple( owner, uniqauthor[keyauthor], memo ) ); //} } template -void SimpleAssets::sendEvent( name author, name rampayer, name seaction, const std::tuple &adata ) { - +void SimpleAssets::sendEvent( name author, name rampayer, name seaction, const tuple &adata ) +{ transaction sevent{}; sevent.actions.emplace_back( permission_level{ _self, "active"_n }, author, seaction, adata ); sevent.delay_sec = 0; @@ -921,16 +1012,26 @@ void SimpleAssets::sendEvent( name author, name rampayer, name seaction, const s } asset SimpleAssets::get_supply( name token_contract_account, name author, symbol_code sym_code ) { + stats statstable( token_contract_account, author.value ); return statstable.get( sym_code.raw() ).supply; } asset SimpleAssets::get_balance( name token_contract_account, name owner, name author, symbol_code sym_code ) { + stats statstable( token_contract_account, author.value ); accounts accountstable( token_contract_account, owner.value ); return accountstable.get( statstable.get( sym_code.raw() ).id ).balance; } +std::string SimpleAssets::timeToWait( uint64_t time_in_seconds ){ + + uint64_t s, h, m = 0; + m = time_in_seconds / 60; + h = m / 60; + return "Time to wait " + std::to_string(int(h)) + " hours " + std::to_string(int(m % 60)) + " minutes " + std::to_string(int(time_in_seconds % 60)) + " seconds"; +} + EOSIO_DISPATCH( SimpleAssets, ( create )( createlog )( transfer )( burn )( update ) ( offer )( canceloffer )( claim ) ( regauthor )( authorupdate ) @@ -938,7 +1039,7 @@ EOSIO_DISPATCH( SimpleAssets, ( create )( createlog )( transfer )( burn )( updat ( createf )( updatef )( issuef )( transferf )( burnf ) ( offerf )( cancelofferf )( claimf ) ( attachf )( detachf )( openf )( closef ) -( updatever ) ( createntt ) ( burnntt ) ( createnttlog ) ( claimntt ) ( updatentt ) ) +( updatever ) ( createntt ) ( burnntt ) ( createnttlog ) ( claimntt ) ( updatentt ) ( changeauthor ) ) //============================================================================================================