Delete more CCs #381
This commit is contained in:
@@ -46,23 +46,5 @@ int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmppr
|
||||
int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid);
|
||||
bool AssetCalcAmounts(struct CCcontract_info *cpAssets, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid);
|
||||
|
||||
// CCassetstx
|
||||
//int64_t GetAssetBalance(CPubKey pk,uint256 tokenid); // --> GetTokenBalance()
|
||||
int64_t AddAssetInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 assetid, int64_t total, int32_t maxinputs);
|
||||
|
||||
UniValue AssetOrders(uint256 tokenid, CPubKey pubkey, uint8_t additionalEvalCode);
|
||||
//UniValue AssetInfo(uint256 tokenid);
|
||||
//UniValue AssetList();
|
||||
//std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description);
|
||||
//std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> destpubkey,int64_t total);
|
||||
//std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector<uint8_t> destpubkey,int64_t total,int32_t evalcode);
|
||||
|
||||
std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64_t pricetotal);
|
||||
std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid);
|
||||
std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t fillamount);
|
||||
std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t pricetotal);
|
||||
std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal);
|
||||
std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid);
|
||||
std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 asktxid,int64_t fillamount);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,765 +19,3 @@
|
||||
#include "CCassets.h"
|
||||
#include "CCtokens.h"
|
||||
|
||||
|
||||
UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t additionalEvalCode)
|
||||
{
|
||||
UniValue result(UniValue::VARR);
|
||||
|
||||
struct CCcontract_info *cpAssets, assetsC;
|
||||
struct CCcontract_info *cpTokens, tokensC;
|
||||
|
||||
cpAssets = CCinit(&assetsC, EVAL_ASSETS);
|
||||
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
|
||||
|
||||
auto addOrders = [&](struct CCcontract_info *cp, std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it)
|
||||
{
|
||||
uint256 txid, hashBlock, assetid, assetid2;
|
||||
int64_t price;
|
||||
std::vector<uint8_t> origpubkey;
|
||||
CTransaction ordertx;
|
||||
uint8_t funcid, evalCode;
|
||||
char numstr[32], funcidstr[16], origaddr[64], origtokenaddr[64];
|
||||
|
||||
txid = it->first.txhash;
|
||||
LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() checking txid=" << txid.GetHex() << std::endl);
|
||||
if ( myGetTransaction(txid, ordertx, hashBlock) != 0 )
|
||||
{
|
||||
// for logging: funcid = DecodeAssetOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey);
|
||||
if (ordertx.vout.size() > 0 && (funcid = DecodeAssetTokenOpRet(ordertx.vout[ordertx.vout.size()-1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey)) != 0)
|
||||
{
|
||||
LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() checking ordertx.vout.size()=" << ordertx.vout.size() << " funcid=" << (char)(funcid ? funcid : ' ') << " assetid=" << assetid.GetHex() << std::endl);
|
||||
|
||||
if (pk == CPubKey() && (refassetid == zeroid || assetid == refassetid) // tokenorders
|
||||
|| pk != CPubKey() && pk == pubkey2pk(origpubkey) && (funcid == 'S' || funcid == 's')) // mytokenorders, returns only asks (is this correct?)
|
||||
{
|
||||
|
||||
LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() it->first.index=" << it->first.index << " ordertx.vout[it->first.index].nValue=" << ordertx.vout[it->first.index].nValue << std::endl);
|
||||
if (ordertx.vout[it->first.index].nValue == 0) {
|
||||
LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() order with value=0 skipped" << std::endl);
|
||||
return;
|
||||
}
|
||||
|
||||
UniValue item(UniValue::VOBJ);
|
||||
|
||||
funcidstr[0] = funcid;
|
||||
funcidstr[1] = 0;
|
||||
item.push_back(Pair("funcid", funcidstr));
|
||||
item.push_back(Pair("txid", txid.GetHex()));
|
||||
item.push_back(Pair("vout", (int64_t)it->first.index));
|
||||
if (funcid == 'b' || funcid == 'B')
|
||||
{
|
||||
sprintf(numstr, "%.8f", (double)ordertx.vout[it->first.index].nValue / COIN);
|
||||
item.push_back(Pair("amount", numstr));
|
||||
sprintf(numstr, "%.8f", (double)ordertx.vout[0].nValue / COIN);
|
||||
item.push_back(Pair("bidamount", numstr));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(numstr, "%llu", (long long)ordertx.vout[it->first.index].nValue);
|
||||
item.push_back(Pair("amount", numstr));
|
||||
sprintf(numstr, "%llu", (long long)ordertx.vout[0].nValue);
|
||||
item.push_back(Pair("askamount", numstr));
|
||||
}
|
||||
if (origpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE)
|
||||
{
|
||||
GetCCaddress(cp, origaddr, pubkey2pk(origpubkey));
|
||||
item.push_back(Pair("origaddress", origaddr));
|
||||
GetTokensCCaddress(cpTokens, origtokenaddr, pubkey2pk(origpubkey));
|
||||
item.push_back(Pair("origtokenaddress", origtokenaddr));
|
||||
}
|
||||
if (assetid != zeroid)
|
||||
item.push_back(Pair("tokenid", assetid.GetHex()));
|
||||
if (assetid2 != zeroid)
|
||||
item.push_back(Pair("otherid", assetid2.GetHex()));
|
||||
if (price > 0)
|
||||
{
|
||||
if (funcid == 's' || funcid == 'S' || funcid == 'e' || funcid == 'e')
|
||||
{
|
||||
sprintf(numstr, "%.8f", (double)price / COIN);
|
||||
item.push_back(Pair("totalrequired", numstr));
|
||||
sprintf(numstr, "%.8f", (double)price / (COIN * ordertx.vout[0].nValue));
|
||||
item.push_back(Pair("price", numstr));
|
||||
}
|
||||
else
|
||||
{
|
||||
item.push_back(Pair("totalrequired", (int64_t)price));
|
||||
sprintf(numstr, "%.8f", (double)ordertx.vout[0].nValue / (price * COIN));
|
||||
item.push_back(Pair("price", numstr));
|
||||
}
|
||||
}
|
||||
result.push_back(item);
|
||||
LOGSTREAM("ccassets", CCLOG_DEBUG1, stream << "addOrders() added order funcId=" << (char)(funcid ? funcid : ' ') << " it->first.index=" << it->first.index << " ordertx.vout[it->first.index].nValue=" << ordertx.vout[it->first.index].nValue << " tokenid=" << assetid.GetHex() << std::endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputsTokens, unspentOutputsDualEvalTokens, unspentOutputsCoins;
|
||||
|
||||
char assetsUnspendableAddr[64];
|
||||
GetCCaddress(cpAssets, assetsUnspendableAddr, GetUnspendable(cpAssets, NULL));
|
||||
SetCCunspents(unspentOutputsCoins, assetsUnspendableAddr,true);
|
||||
|
||||
char assetsTokensUnspendableAddr[64];
|
||||
std::vector<uint8_t> vopretNonfungible;
|
||||
if (refassetid != zeroid) {
|
||||
GetNonfungibleData(refassetid, vopretNonfungible);
|
||||
if (vopretNonfungible.size() > 0)
|
||||
cpAssets->additionalTokensEvalcode2 = vopretNonfungible.begin()[0];
|
||||
}
|
||||
GetTokensCCaddress(cpAssets, assetsTokensUnspendableAddr, GetUnspendable(cpAssets, NULL));
|
||||
SetCCunspents(unspentOutputsTokens, assetsTokensUnspendableAddr,true);
|
||||
|
||||
// tokenbids:
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator itCoins = unspentOutputsCoins.begin();
|
||||
itCoins != unspentOutputsCoins.end();
|
||||
itCoins++)
|
||||
addOrders(cpAssets, itCoins);
|
||||
|
||||
// tokenasks:
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator itTokens = unspentOutputsTokens.begin();
|
||||
itTokens != unspentOutputsTokens.end();
|
||||
itTokens++)
|
||||
addOrders(cpAssets, itTokens);
|
||||
|
||||
if (additionalEvalCode != 0) { //this would be mytokenorders
|
||||
char assetsDualEvalTokensUnspendableAddr[64];
|
||||
|
||||
// try also dual eval tokenasks (and we do not need bids):
|
||||
cpAssets->additionalTokensEvalcode2 = additionalEvalCode;
|
||||
GetTokensCCaddress(cpAssets, assetsDualEvalTokensUnspendableAddr, GetUnspendable(cpAssets, NULL));
|
||||
SetCCunspents(unspentOutputsDualEvalTokens, assetsDualEvalTokensUnspendableAddr,true);
|
||||
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator itDualEvalTokens = unspentOutputsDualEvalTokens.begin();
|
||||
itDualEvalTokens != unspentOutputsDualEvalTokens.end();
|
||||
itDualEvalTokens++)
|
||||
addOrders(cpAssets, itDualEvalTokens);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// not used (use TokenCreate instead)
|
||||
/* std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk; struct CCcontract_info *cp,C;
|
||||
if ( assetsupply < 0 )
|
||||
{
|
||||
fprintf(stderr,"negative assetsupply %lld\n",(long long)assetsupply);
|
||||
return("");
|
||||
}
|
||||
cp = CCinit(&C,EVAL_ASSETS);
|
||||
if ( name.size() > 32 || description.size() > 4096 )
|
||||
{
|
||||
fprintf(stderr,"name.%d or description.%d is too big\n",(int32_t)name.size(),(int32_t)description.size());
|
||||
return("");
|
||||
}
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
if ( AddNormalinputs(mtx,mypk,assetsupply+2*txfee,64) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,assetsupply,mypk));
|
||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(cp->CChexstr) << OP_CHECKSIG));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetCreateOpRet('c',Mypubkey(),name,description)));
|
||||
}
|
||||
return("");
|
||||
} */
|
||||
|
||||
// not used (use TokenTransfer instead)
|
||||
/* std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> destpubkey,int64_t total)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk; uint64_t mask; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C;
|
||||
if ( total < 0 )
|
||||
{
|
||||
fprintf(stderr,"negative total %lld\n",(long long)total);
|
||||
return("");
|
||||
}
|
||||
cp = CCinit(&C,EVAL_ASSETS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 )
|
||||
{
|
||||
//n = outputs.size();
|
||||
//if ( n == amounts.size() )
|
||||
//{
|
||||
// for (i=0; i<n; i++)
|
||||
// total += amounts[i];
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 )
|
||||
{
|
||||
|
||||
if (inputs < total) { //added dimxy
|
||||
std::cerr << "AssetTransfer(): insufficient funds" << std::endl;
|
||||
return ("");
|
||||
}
|
||||
if ( inputs > total )
|
||||
CCchange = (inputs - total);
|
||||
//for (i=0; i<n; i++)
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,total,pubkey2pk(destpubkey)));
|
||||
if ( CCchange != 0 )
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
|
||||
return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey())));
|
||||
} else fprintf(stderr,"not enough CC asset inputs for %.8f\n",(double)total/COIN);
|
||||
//} else fprintf(stderr,"numoutputs.%d != numamounts.%d\n",n,(int32_t)amounts.size());
|
||||
}
|
||||
return("");
|
||||
} */
|
||||
|
||||
// deprecated
|
||||
/* std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector<uint8_t> destpubkey,int64_t total,int32_t evalcode)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C;
|
||||
if ( total < 0 )
|
||||
{
|
||||
fprintf(stderr,"negative total %lld\n",(long long)total);
|
||||
return("");
|
||||
}
|
||||
cp = CCinit(&C,EVAL_ASSETS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 )
|
||||
{
|
||||
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 )
|
||||
{
|
||||
if ( inputs > total )
|
||||
CCchange = (inputs - total);
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
|
||||
mtx.vout.push_back(MakeCC1vout(evalcode,total,pubkey2pk(destpubkey)));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey())));
|
||||
} else fprintf(stderr,"not enough CC asset inputs for %.8f\n",(double)total/COIN);
|
||||
}
|
||||
return("");
|
||||
} */
|
||||
|
||||
// rpc tokenbid implementation, locks 'bidamount' coins for the 'pricetotal' of tokens
|
||||
std::string CreateBuyOffer(int64_t txfee, int64_t bidamount, uint256 assetid, int64_t pricetotal)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk;
|
||||
struct CCcontract_info *cpAssets, C;
|
||||
uint256 hashBlock;
|
||||
CTransaction vintx;
|
||||
std::vector<uint8_t> origpubkey;
|
||||
std::string name,description;
|
||||
int64_t inputs;
|
||||
|
||||
std::cerr << "CreateBuyOffer() bidamount=" << bidamount << " numtokens(pricetotal)=" << pricetotal << std::endl;
|
||||
|
||||
if (bidamount < 0 || pricetotal < 0)
|
||||
{
|
||||
fprintf(stderr,"negative bidamount %lld, pricetotal %lld\n", (long long)bidamount, (long long)pricetotal);
|
||||
return("");
|
||||
}
|
||||
if (myGetTransaction(assetid, vintx, hashBlock) == 0)
|
||||
{
|
||||
fprintf(stderr,"cant find assetid\n");
|
||||
return("");
|
||||
}
|
||||
if (vintx.vout.size() > 0 && DecodeTokenCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey, origpubkey, name, description) == 0)
|
||||
{
|
||||
fprintf(stderr,"assetid isnt assetcreation txid\n");
|
||||
return("");
|
||||
}
|
||||
|
||||
cpAssets = CCinit(&C,EVAL_ASSETS); // NOTE: assets here!
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
|
||||
if ((inputs = AddNormalinputs(mtx, mypk, bidamount+(2*txfee), 64)) > 0)
|
||||
{
|
||||
std::cerr << "CreateBuyOffer() inputs=" << inputs << std::endl;
|
||||
if (inputs < bidamount+txfee) {
|
||||
std::cerr << "CreateBuyOffer(): insufficient coins to make buy offer" << std::endl;
|
||||
CCerror = strprintf("insufficient coins to make buy offer");
|
||||
return ("");
|
||||
}
|
||||
|
||||
CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, 0);
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount, unspendableAssetsPubkey));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk));
|
||||
std::vector<CPubKey> voutTokenPubkeys; // should be empty - no token vouts
|
||||
|
||||
return FinalizeCCTx(0, cpAssets, mtx, mypk, txfee,
|
||||
EncodeTokenOpRet(assetid, voutTokenPubkeys, // TODO: actually this tx is not 'tokens', maybe it is better not to have token opret here but only asset opret.
|
||||
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('b', zeroid, pricetotal, Mypubkey())))); // But still such token opret should not make problems because no token eval in these vouts
|
||||
}
|
||||
CCerror = strprintf("no coins found to make buy offer");
|
||||
return("");
|
||||
}
|
||||
|
||||
// rpc tokenask implementation, locks 'askamount' tokens for the 'pricetotal'
|
||||
std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t pricetotal)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk;
|
||||
uint64_t mask;
|
||||
int64_t inputs, CCchange;
|
||||
struct CCcontract_info *cpAssets, assetsC;
|
||||
struct CCcontract_info *cpTokens, tokensC;
|
||||
|
||||
//std::cerr << "CreateSell() askamount=" << askamount << " pricetotal=" << pricetotal << std::endl;
|
||||
|
||||
if (askamount < 0 || pricetotal < 0) {
|
||||
fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount);
|
||||
return("");
|
||||
}
|
||||
|
||||
cpAssets = CCinit(&assetsC, EVAL_ASSETS); // NOTE: for signing
|
||||
|
||||
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0)
|
||||
{
|
||||
std::vector<uint8_t> vopretNonfungible;
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
// add single-eval tokens (or non-fungible tokens):
|
||||
cpTokens = CCinit(&tokensC, EVAL_TOKENS); // NOTE: adding inputs only from EVAL_TOKENS cc
|
||||
if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, askamount, 60, vopretNonfungible)) > 0)
|
||||
{
|
||||
if (inputs < askamount) {
|
||||
//was: askamount = inputs;
|
||||
std::cerr << "CreateSell(): insufficient tokens for ask" << std::endl;
|
||||
CCerror = strprintf("insufficient tokens for ask");
|
||||
return ("");
|
||||
}
|
||||
|
||||
// if this is non-fungible tokens:
|
||||
if( !vopretNonfungible.empty() )
|
||||
// set its evalcode
|
||||
cpAssets->additionalTokensEvalcode2 = vopretNonfungible.begin()[0];
|
||||
|
||||
CPubKey unspendableAssetsPubkey = GetUnspendable(cpAssets, NULL);
|
||||
mtx.vout.push_back(MakeTokensCC1vout(EVAL_ASSETS, cpAssets->additionalTokensEvalcode2, askamount, unspendableAssetsPubkey));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk)); //marker (seems, it is not for tokenorders)
|
||||
if (inputs > askamount)
|
||||
CCchange = (inputs - askamount);
|
||||
if (CCchange != 0)
|
||||
// change to single-eval or non-fungible token vout (although for non-fungible token change currently is not possible)
|
||||
mtx.vout.push_back(MakeTokensCC1vout((cpAssets->additionalTokensEvalcode2) ? cpAssets->additionalTokensEvalcode2 : EVAL_TOKENS, CCchange, mypk));
|
||||
|
||||
std::vector<CPubKey> voutTokenPubkeys;
|
||||
voutTokenPubkeys.push_back(unspendableAssetsPubkey);
|
||||
|
||||
return FinalizeCCTx(mask, cpTokens, mtx, mypk, txfee,
|
||||
EncodeTokenOpRet(assetid, voutTokenPubkeys,
|
||||
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('s', zeroid, pricetotal, Mypubkey()))));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "need some tokens to place ask\n");
|
||||
}
|
||||
}
|
||||
else { // dimxy added 'else', because it was misleading message before
|
||||
fprintf(stderr, "need some native coins to place ask\n");
|
||||
}
|
||||
return("");
|
||||
}
|
||||
|
||||
////////////////////////// NOT IMPLEMENTED YET/////////////////////////////////
|
||||
std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C;
|
||||
|
||||
////////////////////////// NOT IMPLEMENTED YET/////////////////////////////////
|
||||
fprintf(stderr,"asset swaps disabled\n");
|
||||
return("");
|
||||
////////////////////////// NOT IMPLEMENTED YET/////////////////////////////////
|
||||
|
||||
if ( askamount < 0 || pricetotal < 0 )
|
||||
{
|
||||
fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount);
|
||||
return("");
|
||||
}
|
||||
cp = CCinit(&C, EVAL_ASSETS);
|
||||
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
////////////////////////// NOT IMPLEMENTED YET/////////////////////////////////
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
|
||||
if (AddNormalinputs(mtx, mypk, txfee, 3) > 0)
|
||||
{
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
/*if ((inputs = AddAssetInputs(cp, mtx, mypk, assetid, askamount, 60)) > 0)
|
||||
{
|
||||
////////////////////////// NOT IMPLEMENTED YET/////////////////////////////////
|
||||
if (inputs < askamount) {
|
||||
//was: askamount = inputs;
|
||||
std::cerr << "CreateSwap(): insufficient tokens for ask" << std::endl;
|
||||
CCerror = strprintf("insufficient tokens for ask");
|
||||
return ("");
|
||||
}
|
||||
////////////////////////// NOT IMPLEMENTED YET/////////////////////////////////
|
||||
CPubKey unspendablePubkey = GetUnspendable(cp, 0);
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, askamount, unspendablePubkey));
|
||||
|
||||
if (inputs > askamount)
|
||||
CCchange = (inputs - askamount);
|
||||
if (CCchange != 0)
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk));
|
||||
|
||||
////////////////////////// NOT IMPLEMENTED YET/////////////////////////////////
|
||||
std::vector<CPubKey> voutTokenPubkeys; // should be empty - no token vouts
|
||||
|
||||
if (assetid2 == zeroid) {
|
||||
opret = EncodeTokenOpRet(assetid, voutTokenPubkeys,
|
||||
EncodeAssetOpRet('s', zeroid, pricetotal, Mypubkey()));
|
||||
}
|
||||
else {
|
||||
opret = EncodeTokenOpRet(assetid, voutTokenPubkeys,
|
||||
EncodeAssetOpRet('e', assetid2, pricetotal, Mypubkey()));
|
||||
}
|
||||
////////////////////////// NOT IMPLEMENTED YET/////////////////////////////////
|
||||
return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "need some assets to place ask\n");
|
||||
} */
|
||||
}
|
||||
else { // dimxy added 'else', because it was misleading message before
|
||||
fprintf(stderr,"need some native coins to place ask\n");
|
||||
}
|
||||
|
||||
return("");
|
||||
} ////////////////////////// NOT IMPLEMENTED YET/////////////////////////////////
|
||||
|
||||
// unlocks coins
|
||||
std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CTransaction vintx; uint64_t mask;
|
||||
uint256 hashBlock; int64_t bidamount;
|
||||
CPubKey mypk; struct CCcontract_info *cpAssets, C;
|
||||
uint8_t funcid,dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector<uint8_t> dummyOrigpubkey;
|
||||
|
||||
cpAssets = CCinit(&C, EVAL_ASSETS);
|
||||
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
|
||||
if (AddNormalinputs(mtx, mypk, txfee, 3) > 0)
|
||||
{
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
if (myGetTransaction(bidtxid, vintx, hashBlock) != 0)
|
||||
{
|
||||
std::vector<uint8_t> vopretNonfungible;
|
||||
GetNonfungibleData(assetid, vopretNonfungible);
|
||||
|
||||
bidamount = vintx.vout[0].nValue;
|
||||
mtx.vin.push_back(CTxIn(bidtxid, 0, CScript())); // coins in Assets
|
||||
|
||||
if((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0)
|
||||
{
|
||||
if (funcid == 's') mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b'
|
||||
else if (funcid=='S') mtx.vin.push_back(CTxIn(bidtxid, 3, CScript())); // spend marker if funcid='B'
|
||||
}
|
||||
|
||||
mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
|
||||
std::vector<CPubKey> voutTokenPubkeys; // should be empty, no token vouts
|
||||
|
||||
return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee,
|
||||
EncodeTokenOpRet(assetid, voutTokenPubkeys,
|
||||
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('o', zeroid, 0, Mypubkey())))));
|
||||
}
|
||||
}
|
||||
return("");
|
||||
}
|
||||
|
||||
//unlocks tokens
|
||||
std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CTransaction vintx; uint64_t mask;
|
||||
uint256 hashBlock; int64_t askamount;
|
||||
CPubKey mypk;
|
||||
struct CCcontract_info *cpTokens, *cpAssets, tokensC, assetsC;
|
||||
uint8_t funcid, dummyEvalCode;
|
||||
uint256 dummyAssetid, dummyAssetid2;
|
||||
int64_t dummyPrice;
|
||||
std::vector<uint8_t> dummyOrigpubkey;
|
||||
|
||||
cpAssets = CCinit(&assetsC, EVAL_ASSETS);
|
||||
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
|
||||
if (AddNormalinputs(mtx, mypk, txfee, 3) > 0)
|
||||
{
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
if (myGetTransaction(asktxid, vintx, hashBlock) != 0)
|
||||
{
|
||||
std::vector<uint8_t> vopretNonfungible;
|
||||
GetNonfungibleData(assetid, vopretNonfungible);
|
||||
|
||||
askamount = vintx.vout[0].nValue;
|
||||
mtx.vin.push_back(CTxIn(asktxid, 0, CScript()));
|
||||
|
||||
if ((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0)
|
||||
{
|
||||
if (funcid == 's')
|
||||
mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // marker if funcid='s'
|
||||
else if (funcid=='S')
|
||||
mtx.vin.push_back(CTxIn(asktxid, 3, CScript())); // marker if funcid='S'
|
||||
}
|
||||
|
||||
if (vopretNonfungible.size() > 0)
|
||||
cpAssets->additionalTokensEvalcode2 = vopretNonfungible.begin()[0];
|
||||
|
||||
mtx.vout.push_back(MakeTokensCC1vout(cpAssets->additionalTokensEvalcode2 == 0 ? EVAL_TOKENS : cpAssets->additionalTokensEvalcode2, askamount, mypk)); // one-eval token vout
|
||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
|
||||
std::vector<CPubKey> voutTokenPubkeys;
|
||||
voutTokenPubkeys.push_back(mypk);
|
||||
|
||||
// this is only for unspendable addresses:
|
||||
//CCaddr2set(cpTokens, EVAL_ASSETS, mypk, myPrivkey, myCCaddr); //do we need this? Seems FinalizeCCTx can attach to any evalcode cc addr by calling Getscriptaddress
|
||||
|
||||
uint8_t unspendableAssetsPrivkey[32];
|
||||
char unspendableAssetsAddr[64];
|
||||
// init assets 'unspendable' privkey and pubkey
|
||||
CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey);
|
||||
GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk);
|
||||
|
||||
// add additional eval-tokens unspendable assets privkey:
|
||||
CCaddr2set(cpAssets, EVAL_TOKENS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr);
|
||||
|
||||
return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee,
|
||||
EncodeTokenOpRet(assetid, voutTokenPubkeys,
|
||||
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('x', zeroid, 0, Mypubkey())))));
|
||||
}
|
||||
}
|
||||
return("");
|
||||
}
|
||||
|
||||
//send tokens, receive coins:
|
||||
std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t fillamount)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CTransaction vintx;
|
||||
uint256 hashBlock;
|
||||
CPubKey mypk;
|
||||
std::vector<uint8_t> origpubkey;
|
||||
int32_t bidvout=0;
|
||||
uint64_t mask;
|
||||
int64_t origprice, bidamount, paid_amount, remaining_required, inputs, CCchange=0;
|
||||
struct CCcontract_info *cpTokens, tokensC;
|
||||
struct CCcontract_info *cpAssets, assetsC;
|
||||
|
||||
if (fillamount < 0)
|
||||
{
|
||||
fprintf(stderr,"negative fillamount %lld\n", (long long)fillamount);
|
||||
return("");
|
||||
}
|
||||
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
|
||||
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
|
||||
if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0)
|
||||
{
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
if (myGetTransaction(bidtxid, vintx, hashBlock) != 0)
|
||||
{
|
||||
bidamount = vintx.vout[bidvout].nValue;
|
||||
SetAssetOrigpubkey(origpubkey, origprice, vintx);
|
||||
|
||||
mtx.vin.push_back(CTxIn(bidtxid, bidvout, CScript())); // Coins on Assets unspendable
|
||||
|
||||
std::vector<uint8_t> vopretNonfungible;
|
||||
if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, fillamount, 60, vopretNonfungible)) > 0)
|
||||
{
|
||||
if (inputs < fillamount) {
|
||||
std::cerr << "FillBuyOffer(): insufficient tokens to fill buy offer" << std::endl;
|
||||
CCerror = strprintf("insufficient tokens to fill buy offer");
|
||||
return ("");
|
||||
}
|
||||
|
||||
SetBidFillamounts(paid_amount, remaining_required, bidamount, fillamount, origprice);
|
||||
|
||||
uint8_t additionalTokensEvalcode2 = 0;
|
||||
if (vopretNonfungible.size() > 0)
|
||||
additionalTokensEvalcode2 = vopretNonfungible.begin()[0];
|
||||
|
||||
if (inputs > fillamount)
|
||||
CCchange = (inputs - fillamount);
|
||||
|
||||
uint8_t unspendableAssetsPrivkey[32];
|
||||
cpAssets = CCinit(&assetsC, EVAL_ASSETS);
|
||||
CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey);
|
||||
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder
|
||||
mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to normal
|
||||
mtx.vout.push_back(MakeTokensCC1vout(additionalTokensEvalcode2 == 0 ? EVAL_TOKENS : additionalTokensEvalcode2, fillamount, pubkey2pk(origpubkey))); // vout2 single-eval tokens sent to the originator
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, origpubkey)); // vout3 marker to origpubkey
|
||||
|
||||
if (CCchange != 0)
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); // vout4 change in single-eval tokens
|
||||
|
||||
fprintf(stderr,"FillBuyOffer() remaining %llu -> origpubkey\n", (long long)remaining_required);
|
||||
|
||||
char unspendableAssetsAddr[64];
|
||||
cpAssets = CCinit(&assetsC, EVAL_ASSETS);
|
||||
GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk);
|
||||
|
||||
// add additional unspendable addr from Assets:
|
||||
CCaddr2set(cpTokens, EVAL_ASSETS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr);
|
||||
|
||||
// token vout verification pubkeys:
|
||||
std::vector<CPubKey> voutTokenPubkeys;
|
||||
voutTokenPubkeys.push_back(pubkey2pk(origpubkey));
|
||||
|
||||
return(FinalizeCCTx(mask, cpTokens, mtx, mypk, txfee,
|
||||
EncodeTokenOpRet(assetid, voutTokenPubkeys,
|
||||
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('B', zeroid, remaining_required, origpubkey)))));
|
||||
} else return("dont have any assets to fill bid");
|
||||
}
|
||||
}
|
||||
return("no normal coins left");
|
||||
}
|
||||
|
||||
|
||||
// send coins, receive tokens
|
||||
std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 asktxid, int64_t fillunits)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CTransaction vintx,filltx;
|
||||
uint256 hashBlock;
|
||||
CPubKey mypk;
|
||||
std::vector<uint8_t> origpubkey;
|
||||
double dprice;
|
||||
uint64_t mask = 0;
|
||||
int32_t askvout = 0;
|
||||
int64_t received_assetoshis, total_nValue, orig_assetoshis, paid_nValue, remaining_nValue, inputs, CCchange=0;
|
||||
//struct CCcontract_info *cpTokens, tokensC;
|
||||
struct CCcontract_info *cpAssets, assetsC;
|
||||
|
||||
if (fillunits < 0)
|
||||
{
|
||||
CCerror = strprintf("negative fillunits %lld\n",(long long)fillunits);
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
if (assetid2 != zeroid)
|
||||
{
|
||||
CCerror = "asset swaps disabled";
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
|
||||
std::vector<uint8_t> vopretNonfungible;
|
||||
uint8_t additionalTokensEvalcode2 = 0;
|
||||
GetNonfungibleData(assetid, vopretNonfungible);
|
||||
if (vopretNonfungible.size() > 0)
|
||||
additionalTokensEvalcode2 = vopretNonfungible.begin()[0];
|
||||
|
||||
cpAssets = CCinit(&assetsC, EVAL_ASSETS);
|
||||
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
//if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0)
|
||||
//{
|
||||
//mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
if (myGetTransaction(asktxid, vintx, hashBlock) != 0)
|
||||
{
|
||||
orig_assetoshis = vintx.vout[askvout].nValue;
|
||||
SetAssetOrigpubkey(origpubkey, total_nValue, vintx);
|
||||
dprice = (double)total_nValue / orig_assetoshis;
|
||||
paid_nValue = dprice * fillunits;
|
||||
|
||||
if (assetid2 != zeroid) {
|
||||
inputs = 0; // = AddAssetInputs(cpAssets, mtx, mypk, assetid2, paid_nValue, 60); // not implemented yet
|
||||
}
|
||||
else
|
||||
{
|
||||
inputs = AddNormalinputs(mtx, mypk, 2 * txfee + paid_nValue, 60); // Better to use single AddNormalinputs() to allow payment if user has only single utxo with normal funds
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
}
|
||||
if (inputs > 0)
|
||||
{
|
||||
if (inputs < paid_nValue) {
|
||||
std::cerr << "FillSell(): insufficient coins to fill sell" << std::endl;
|
||||
CCerror = strprintf("insufficient coins to fill sell");
|
||||
return ("");
|
||||
}
|
||||
|
||||
// cc vin should be after normal vin
|
||||
mtx.vin.push_back(CTxIn(asktxid, askvout, CScript()));
|
||||
|
||||
if (assetid2 != zeroid)
|
||||
SetSwapFillamounts(received_assetoshis, remaining_nValue, orig_assetoshis, paid_nValue, total_nValue); //not implemented correctly yet
|
||||
else
|
||||
SetAskFillamounts(received_assetoshis, remaining_nValue, orig_assetoshis, paid_nValue, total_nValue);
|
||||
|
||||
if (assetid2 != zeroid && inputs > paid_nValue)
|
||||
CCchange = (inputs - paid_nValue);
|
||||
|
||||
// vout.0 tokens remainder to unspendable cc addr:
|
||||
mtx.vout.push_back(MakeTokensCC1vout(EVAL_ASSETS, additionalTokensEvalcode2, orig_assetoshis - received_assetoshis, GetUnspendable(cpAssets, NULL)));
|
||||
//vout.1 purchased tokens to self token single-eval or dual-eval token+nonfungible cc addr:
|
||||
mtx.vout.push_back(MakeTokensCC1vout(additionalTokensEvalcode2 == 0 ? EVAL_TOKENS : additionalTokensEvalcode2, received_assetoshis, mypk));
|
||||
|
||||
if (assetid2 != zeroid) {
|
||||
std::cerr << "FillSell() WARNING: asset swap not implemented yet! (paid_nValue)" << std::endl;
|
||||
// TODO: change MakeCC1vout appropriately when implementing:
|
||||
//mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, paid_nValue, origpubkey)); //vout.2 tokens... (swap is not implemented yet)
|
||||
}
|
||||
else {
|
||||
//std::cerr << "FillSell() paid_value=" << paid_nValue << " origpubkey=" << HexStr(pubkey2pk(origpubkey)) << std::endl;
|
||||
mtx.vout.push_back(CTxOut(paid_nValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to tokens seller's normal addr
|
||||
}
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,txfee,origpubkey)); //vout.3 marker to origpubkey
|
||||
|
||||
// not implemented
|
||||
if (CCchange != 0) {
|
||||
std::cerr << "FillSell() WARNING: asset swap not implemented yet! (CCchange)" << std::endl;
|
||||
// TODO: change MakeCC1vout appropriately when implementing:
|
||||
//mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk)); //vout.3 coins in Assets cc addr (swap not implemented)
|
||||
}
|
||||
|
||||
uint8_t unspendableAssetsPrivkey[32];
|
||||
char unspendableAssetsAddr[64];
|
||||
// init assets 'unspendable' privkey and pubkey
|
||||
CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey);
|
||||
GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk);
|
||||
|
||||
// add additional eval-tokens unspendable assets privkey:
|
||||
CCaddr2set(cpAssets, EVAL_TOKENS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr);
|
||||
|
||||
// vout verification pubkeys:
|
||||
std::vector<CPubKey> voutTokenPubkeys;
|
||||
voutTokenPubkeys.push_back(mypk);
|
||||
|
||||
cpAssets->additionalTokensEvalcode2 = additionalTokensEvalcode2;
|
||||
|
||||
return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee,
|
||||
EncodeTokenOpRet(assetid, voutTokenPubkeys,
|
||||
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet(assetid2 != zeroid ? 'E' : 'S', assetid2, remaining_nValue, origpubkey)))));
|
||||
} else {
|
||||
CCerror = strprintf("filltx not enough utxos");
|
||||
fprintf(stderr,"%s\n", CCerror.c_str());
|
||||
}
|
||||
}
|
||||
//}
|
||||
return("");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user