|
@@ -0,0 +1,368 @@
|
|
|
+package dcrcash
|
|
|
+
|
|
|
+import (
|
|
|
+ "encoding/json"
|
|
|
+ "fmt"
|
|
|
+ "strconv"
|
|
|
+ . "template"
|
|
|
+ "time"
|
|
|
+
|
|
|
+ simplejson "github.com/go-simplejson"
|
|
|
+ tml "github.com/toml-master"
|
|
|
+)
|
|
|
+
|
|
|
+var (
|
|
|
+ Config config
|
|
|
+ CoinApi DcrCashApi
|
|
|
+ //Walletpass string
|
|
|
+)
|
|
|
+
|
|
|
+type DcrCash struct {
|
|
|
+ walletstatus bool
|
|
|
+}
|
|
|
+
|
|
|
+const (
|
|
|
+ NameCoin = "DCR"
|
|
|
+ SendToError = "-32603"
|
|
|
+)
|
|
|
+
|
|
|
+func (m DcrCash) InitDriver(param interface{}) bool {
|
|
|
+ if m.initconfig() == false {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ go m.getwalletinfo()
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+func (m DcrCash) initconfig() bool {
|
|
|
+ if _, err := tml.DecodeFile("./src/dcrcash/dcrcash.toml", &Config); err != nil {
|
|
|
+ fmt.Println(err)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ fmt.Printf("%+v\n", Config)
|
|
|
+ User := Config.Rpc.Rpcuser
|
|
|
+ Password := Config.Rpc.Rpcpassword
|
|
|
+ Host := Config.Rpc.Rpchost
|
|
|
+ Port := Config.Rpc.Rpcport
|
|
|
+ //Walletpass = Config.WalletInfo.Pripassphrase
|
|
|
+
|
|
|
+ CoinApi.InitRpcConf(User, Password, Host, Port)
|
|
|
+
|
|
|
+ initDcrError()
|
|
|
+
|
|
|
+ f, err := strconv.ParseFloat(Config.Limit.Fee, 64)
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", "init json error:%v", err.Error())
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ fee := float64(f)
|
|
|
+ CoinApi.WalletSetTxFee(fee) //
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+func (m DcrCash) getwalletinfo() bool {
|
|
|
+ fmt.Println("Walletinfo:")
|
|
|
+ m.walletstatus = false
|
|
|
+
|
|
|
+ for {
|
|
|
+ if m.walletstatus == false {
|
|
|
+ resp, err := CoinApi.WalletInfo()
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", "WalletInfo error:%v", err.Error())
|
|
|
+ time.Sleep(time.Second * 1)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ LOG("DEBUG", "walletInfo resp:%v", string(resp))
|
|
|
+ m.walletstatus = true
|
|
|
+ }
|
|
|
+
|
|
|
+ time.Sleep(time.Second)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (m DcrCash) CoinBalance(parm interface{}) ([]byte, error) {
|
|
|
+ confirmedBalance, err := CoinApi.WalleGetBalance("*")
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " GetBalance err:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETBALANCE_ERR, getErrMsg(GETBALANCE_ERR, nil))
|
|
|
+ }
|
|
|
+ var balance []account
|
|
|
+ if err = json.Unmarshal(confirmedBalance, &balance); err != nil {
|
|
|
+ LOG("ERROR", " inner json error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+ }
|
|
|
+ var totalConfirbalance float64
|
|
|
+ var totalUnconfirbalance float64
|
|
|
+ for _, vbalance := range balance {
|
|
|
+ if vbalance.Spendable != 0 {
|
|
|
+ totalConfirbalance += vbalance.Spendable
|
|
|
+ }
|
|
|
+ if vbalance.Unconfirmed != 0 {
|
|
|
+ totalUnconfirbalance += vbalance.Unconfirmed
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ var jbuf []byte
|
|
|
+ resp := make(map[string]interface{})
|
|
|
+ resp["confirmedbalance"] = totalConfirbalance
|
|
|
+ resp["unconfirmed"] = totalUnconfirbalance
|
|
|
+ resp["errcode"] = 0
|
|
|
+ resp["exact"] = 0
|
|
|
+ if jbuf, err = json.Marshal(resp); err != nil {
|
|
|
+ LOG("ERROR", "lite inner json error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ return jbuf, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (m DcrCash) CreateAddress(parm interface{}) ([]byte, error) {
|
|
|
+ addr, err := CoinApi.WalletNewAddr()
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " get new address error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETNEWADDRESS_ERR, getErrMsg(GETNEWADDRESS_ERR, nil))
|
|
|
+ }
|
|
|
+ if len(addr) != 0 {
|
|
|
+ //get key by the address
|
|
|
+ key, err := CoinApi.WalletDumpPrivKey(addr)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " dump private key error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, DUMPPRIVKEY_ERR, getErrMsg(DUMPPRIVKEY_ERR, nil))
|
|
|
+ }
|
|
|
+ if len(key) != 0 {
|
|
|
+
|
|
|
+ var jbuf []byte
|
|
|
+ resp := make(map[string]interface{})
|
|
|
+ resp["address"] = addr
|
|
|
+ resp["privkey"] = key
|
|
|
+ resp["errcode"] = 0
|
|
|
+
|
|
|
+ if jbuf, err = json.Marshal(resp); err != nil {
|
|
|
+ LOG("ERROR", " inner json error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+ }
|
|
|
+ return jbuf, nil
|
|
|
+ }
|
|
|
+ LOG("ERROR", " privkey is null error:%v")
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+ }
|
|
|
+ LOG("ERROR", " address is null error:%v")
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+}
|
|
|
+
|
|
|
+func (m DcrCash) TransferAccounts(parm interface{}) ([]byte, error) {
|
|
|
+ pjs := parm.(*simplejson.Json)
|
|
|
+ amountTmp := pjs.Get("amount").MustString()
|
|
|
+ destination := pjs.Get("address").MustString()
|
|
|
+
|
|
|
+ if len(amountTmp) == 0 {
|
|
|
+ LOG("ERROR", " amount illeagal")
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, AMOUNT_ERR, getErrMsg(AMOUNT_ERR, nil))
|
|
|
+ }
|
|
|
+ f, err := strconv.ParseFloat(amountTmp, 64)
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " inner json error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ amount := float64(f)
|
|
|
+
|
|
|
+ transactionid, err := CoinApi.WalleSendTo(destination, amount, "", "")
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " Send coin error:%v", err.Error())
|
|
|
+ fmt.Println(transactionid)
|
|
|
+ if transactionid == SendToError {
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INSUFFICIENT_FUNDS_TRANSACTION_ERR, getErrMsg(INSUFFICIENT_FUNDS_TRANSACTION_ERR, nil))
|
|
|
+ }
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, SENDCOINS_ERR, getErrMsg(SENDCOINS_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(transactionid) != 0 {
|
|
|
+ var jbuf []byte
|
|
|
+ resp := make(map[string]interface{})
|
|
|
+ resp["transcationids"] = []string{transactionid}
|
|
|
+ resp["errcode"] = 0
|
|
|
+ resp["msg"] = "ok"
|
|
|
+
|
|
|
+ if jbuf, err = json.Marshal(resp); err != nil {
|
|
|
+ LOG("ERROR", " inner json error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+ }
|
|
|
+ return jbuf, nil
|
|
|
+ }
|
|
|
+ LOG("ERROR", " transactionid is null error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+}
|
|
|
+
|
|
|
+func (m DcrCash) TransInfo(parm interface{}) ([]byte, error) {
|
|
|
+ pjs := parm.(*simplejson.Json)
|
|
|
+ startH := pjs.Get("starth").MustUint64()
|
|
|
+ endH := pjs.Get("endh").MustUint64()
|
|
|
+
|
|
|
+ if startH < 1 {
|
|
|
+ LOG("DEBUG", " input para err:%v", startH)
|
|
|
+ startH = 1
|
|
|
+ }
|
|
|
+
|
|
|
+ //get longest block count
|
|
|
+ blockcount, err := CoinApi.WalleGetBlockCount()
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " WalleGetBlockCount err:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETCLOCKCOUNT_ERR, getErrMsg(GETCLOCKCOUNT_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ //get startblock hash by height
|
|
|
+
|
|
|
+ if startH > blockcount {
|
|
|
+ LOG("DEBUG", " startheight:%v > blockcount:%v", startH, blockcount)
|
|
|
+ startH = blockcount
|
|
|
+ }
|
|
|
+
|
|
|
+ startblockhash, err := CoinApi.WalletGetBlockHash(uint64(startH - 1))
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " WalletGetBlockHash startH:%v err:%v", startH, err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETBLOCKINFO_ERR, getErrMsg(GETBLOCKINFO_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ //get endblock time by height
|
|
|
+ if endH > blockcount {
|
|
|
+ LOG("DEBUG", " endheight:%v > blockcount:%v", endH, blockcount)
|
|
|
+ endH = blockcount
|
|
|
+ }
|
|
|
+
|
|
|
+ endblockhash, err := CoinApi.WalletGetBlockHash(uint64(endH))
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " WalletGetBlockHash startH:%v err:%v", startH, err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETBLOCKINFO_ERR, getErrMsg(GETBLOCKINFO_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ endblocktime, err := CoinApi.WalletGetBlockTime(endblockhash)
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " WalletGetBlockTime endH:%v err:%v", endH, err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETBLOCKINFO_ERR, getErrMsg(GETBLOCKINFO_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ //Get all transactions in blocks since block [blockhash]
|
|
|
+ resp, err := CoinApi.WalleListSinceBlock(startblockhash)
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " WalleListSinceBlock err:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, TRANSINFO_ERR, getErrMsg(TRANSINFO_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ var litelisttransactionsinfo []Listtransactions
|
|
|
+
|
|
|
+ if err = json.Unmarshal([]byte(resp), &litelisttransactionsinfo); err != nil {
|
|
|
+ LOG("ERROR", " inner json error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ outputsArr := make([]map[string]interface{}, 0)
|
|
|
+ fmt.Println("WalleListSinceBlock_num:", len(litelisttransactionsinfo))
|
|
|
+ for index, listtransaction := range litelisttransactionsinfo {
|
|
|
+
|
|
|
+ // get all transactions from block startHright to endHeight
|
|
|
+ fmt.Println("BLockTime,Endblocktime", listtransaction.Blocktime, endblocktime, index)
|
|
|
+ if listtransaction.Blocktime <= endblocktime {
|
|
|
+ requestData := make(map[string]interface{})
|
|
|
+ confirmationheight, err := CoinApi.WalletGetBlockHeight(listtransaction.Blockhash)
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", "WalletGetBlockHeight error:%v", err.Error())
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ requestData["confirmationheight"] = confirmationheight
|
|
|
+ requestData["address"] = listtransaction.Address
|
|
|
+ requestData["confirmationtimestamp"] = listtransaction.Timereceived
|
|
|
+ requestData["value"] = listtransaction.Amount
|
|
|
+ requestData["transactionid"] = listtransaction.Txid
|
|
|
+ requestData["confirmations"] = listtransaction.Confirmations
|
|
|
+ requestData["walletaddress"] = true
|
|
|
+ requestData["vout"] = listtransaction.Vout
|
|
|
+ outputsArr = append(outputsArr, requestData)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var jbuf []byte
|
|
|
+ resptmp := make(map[string]interface{})
|
|
|
+ resptmp["errcode"] = 0
|
|
|
+ resptmp["cointype"] = "DCR"
|
|
|
+ resptmp["outputs"] = outputsArr
|
|
|
+
|
|
|
+ if jbuf, err = json.Marshal(resptmp); err != nil {
|
|
|
+ LOG("ERROR", " inner json error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+ }
|
|
|
+ return jbuf, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (m DcrCash) ListUnspent(parm interface{}) ([]byte, error) {
|
|
|
+ pjs := parm.(*simplejson.Json)
|
|
|
+ address, err := pjs.Get("address").StringArray()
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " input parm error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
|
|
|
+ }
|
|
|
+ unspent, err := CoinApi.Listunspent(address)
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " get listunspent:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ var jbuf []byte
|
|
|
+ resptmp := make(map[string]interface{})
|
|
|
+ resptmp["errcode"] = 0
|
|
|
+ resptmp["cointype"] = "DCR"
|
|
|
+ resptmp["unspents"] = unspent
|
|
|
+
|
|
|
+ if jbuf, err = json.Marshal(resptmp); err != nil {
|
|
|
+ LOG("ERROR", " inner json error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+ }
|
|
|
+ return jbuf, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (m DcrCash) SendRawTransaction(parm interface{}) ([]byte, error) {
|
|
|
+ pjs := parm.(*simplejson.Json)
|
|
|
+ transdata := pjs.Get("data").MustString()
|
|
|
+
|
|
|
+ if len(transdata) == 0 {
|
|
|
+ return nil, fmt.Errorf(`{"cointype":"DCR","errcode":%v,"msg":"%v"}`, PARM_ERR, getErrMsg(PARM_ERR, []byte("hexstring is null")))
|
|
|
+ }
|
|
|
+ transactionhex, err := CoinApi.SendRawTransaction(transdata)
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " SendRawTransaction err:%s", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"cointype":"DCR","errcode":%v,"msg":"%s"}`, SEND_RAW_TRANSACTION_ERR, getErrMsg(SEND_RAW_TRANSACTION_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ var jbuf []byte
|
|
|
+ resp := make(map[string]interface{})
|
|
|
+ resp["cointype"] = "DCR"
|
|
|
+ resp["transactionids"] = transactionhex
|
|
|
+ resp["errcode"] = 0
|
|
|
+ resp["msg"] = "OK"
|
|
|
+
|
|
|
+ if jbuf, err = json.Marshal(resp); err != nil {
|
|
|
+ LOG("ERROR", "inner json error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"cointype":"DCR","errcode":%v,"msg":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
|
|
|
+ }
|
|
|
+ return jbuf, nil
|
|
|
+}
|
|
|
+func (m DcrCash) ChainHeight(parm interface{}) ([]byte, error) {
|
|
|
+
|
|
|
+ blockcount, err := CoinApi.WalleGetBlockCount()
|
|
|
+ if err != nil {
|
|
|
+ LOG("ERROR", " get current block count error:%v", err.Error())
|
|
|
+ return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETCLOCKCOUNT_ERR, getErrMsg(GETCLOCKCOUNT_ERR, nil))
|
|
|
+ }
|
|
|
+
|
|
|
+ sendstr := fmt.Sprintf(`{"errcode":%v,"height":%v}`, OK, blockcount)
|
|
|
+ return []byte(sendstr), nil
|
|
|
+}
|
|
|
+
|
|
|
+func init() {
|
|
|
+
|
|
|
+ Register(NameCoin, &DcrCash{})
|
|
|
+}
|