bitcoinmain.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. package bitcoin
  2. import (
  3. "encoding/json"
  4. //"errors"
  5. "fmt"
  6. "strconv"
  7. "sync"
  8. . "template"
  9. "time"
  10. simplejson "github.com/go-simplejson"
  11. btc "github.com/piotrnar/gocoin/lib/btc"
  12. tml "github.com/toml-master"
  13. )
  14. var (
  15. Config config
  16. CoinApi BitCoinApi
  17. m_unspent []map[string]interface{}
  18. m_mutUnspent sync.Mutex
  19. )
  20. type BitCoin struct {
  21. walletstatus bool
  22. }
  23. const (
  24. NameCoin = "BTC"
  25. )
  26. const BACKUPPUBKEYINDEX = "backuppubkeyindex"
  27. // PubKey
  28. var PubKey string = ""
  29. //bitcoin PubKey Child index
  30. var StartCount uint32 = 0
  31. var EndCount uint32 = 0
  32. func (m BitCoin) InitDriver(parm interface{}) bool {
  33. if m.initconfig() == false {
  34. return false
  35. }
  36. go m.getwalletinfo()
  37. //缓存当前未花费的
  38. go AsyncRoutine()
  39. return true
  40. }
  41. //get the server's total available balance
  42. func (m BitCoin) CoinBalance(parm interface{}) ([]byte, error) {
  43. confirmedBalance, err := CoinApi.WalleGetBalance("*")
  44. if err != nil {
  45. LOG("ERROR", " GetBalance err:%v", err.Error())
  46. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETBALANCE_ERR, getErrMsg(GETBALANCE_ERR, nil))
  47. }
  48. UnconfirmedBalance, err := CoinApi.WalleGetUnconfirmedBalance("")
  49. if err != nil {
  50. LOG("ERROR", " GetUnconfirmedBalance err:%s", err.Error())
  51. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETUNCONFIRMEDBALANCE_ERR, getErrMsg(GETUNCONFIRMEDBALANCE_ERR, nil))
  52. }
  53. var jbuf []byte
  54. resp := make(map[string]interface{})
  55. resp["confirmedbalance"] = confirmedBalance
  56. resp["unconfirmed"] = UnconfirmedBalance
  57. resp["errcode"] = 0
  58. resp["exact"] = 0
  59. if jbuf, err = json.Marshal(resp); err != nil {
  60. LOG("ERROR", " inner json error:%v", err.Error())
  61. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  62. }
  63. return jbuf, nil
  64. }
  65. //Returns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.
  66. func (m BitCoin) TransInfo(parm interface{}) ([]byte, error) {
  67. pjs := parm.(*simplejson.Json)
  68. startH := pjs.Get("starth").MustUint64()
  69. endH := pjs.Get("endh").MustUint64()
  70. if startH < 1 {
  71. LOG("DEBUG", " input para err:%v", startH)
  72. startH = 1
  73. }
  74. //get longest block count
  75. blockcount, err := CoinApi.WalleGetBlockCount()
  76. if err != nil {
  77. LOG("ERROR", " WalleGetBlockCount err:%v", err.Error())
  78. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETCLOCKCOUNT_ERR, getErrMsg(GETCLOCKCOUNT_ERR, nil))
  79. }
  80. //get startblock hash by height
  81. if startH > blockcount {
  82. LOG("DEBUG", " startheight:%v > blockcount:%v", startH, blockcount)
  83. startH = blockcount
  84. }
  85. startblockhash, err := CoinApi.WalletGetBlockHash(uint64(startH - 1))
  86. if err != nil {
  87. LOG("ERROR", " WalletGetBlockHash startH:%v err:%v", startH, err.Error())
  88. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETBLOCKINFO_ERR, getErrMsg(GETBLOCKINFO_ERR, nil))
  89. }
  90. //get endblock time by height
  91. if endH > blockcount {
  92. LOG("DEBUG", " endheight:%v > blockcount:%v", endH, blockcount)
  93. endH = blockcount
  94. }
  95. endblockhash, err := CoinApi.WalletGetBlockHash(uint64(endH))
  96. if err != nil {
  97. LOG("ERROR", " WalletGetBlockHash startH:%v err:%v", startH, err.Error())
  98. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETBLOCKINFO_ERR, getErrMsg(GETBLOCKINFO_ERR, nil))
  99. }
  100. endblocktime, err := CoinApi.WalletGetBlockTime(endblockhash)
  101. if err != nil {
  102. LOG("ERROR", " WalletGetBlockTime endH:%v err:%v", endH, err.Error())
  103. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETBLOCKINFO_ERR, getErrMsg(GETBLOCKINFO_ERR, nil))
  104. }
  105. //Get all transactions in blocks since block [blockhash]
  106. resp, err := CoinApi.WalleListSinceBlock(startblockhash)
  107. if err != nil {
  108. LOG("ERROR", " WalleListSinceBlock err:%v", err.Error())
  109. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, TRANSINFO_ERR, getErrMsg(TRANSINFO_ERR, nil))
  110. }
  111. var litelisttransactionsinfo []Listtransactions
  112. if err = json.Unmarshal([]byte(resp), &litelisttransactionsinfo); err != nil {
  113. LOG("ERROR", " inner json error:%v", err.Error())
  114. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  115. }
  116. outputsArr := make([]map[string]interface{}, 0)
  117. for _, listtransaction := range litelisttransactionsinfo {
  118. // get all transactions from block startHright to endHeight
  119. if listtransaction.Blocktime <= endblocktime {
  120. requestData := make(map[string]interface{})
  121. if listtransaction.Amount < 0 {
  122. LOG("DEBUG", "listtransaction.Address:%v,value:%v,txid:%v", listtransaction.Address, listtransaction.Amount, listtransaction.Txid)
  123. continue
  124. }
  125. confirmationheight, err := CoinApi.WalletGetBlockHeight(listtransaction.Blockhash)
  126. if err != nil {
  127. LOG("ERROR", "WalletGetBlockHeight error:%v", err.Error())
  128. continue
  129. }
  130. requestData["confirmationheight"] = confirmationheight
  131. requestData["address"] = listtransaction.Address
  132. requestData["confirmationtimestamp"] = listtransaction.Timereceived
  133. requestData["value"] = listtransaction.Amount
  134. requestData["transactionid"] = listtransaction.Txid
  135. requestData["confirmations"] = listtransaction.Confirmations
  136. requestData["walletaddress"] = true
  137. requestData["vout"] = listtransaction.Vout
  138. outputsArr = append(outputsArr, requestData)
  139. }
  140. }
  141. var jbuf []byte
  142. resptmp := make(map[string]interface{})
  143. resptmp["errcode"] = 0
  144. resptmp["cointype"] = "BTC"
  145. resptmp["outputs"] = outputsArr
  146. if jbuf, err = json.Marshal(resptmp); err != nil {
  147. LOG("ERROR", " inner json error:%v", err.Error())
  148. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  149. }
  150. return jbuf, nil
  151. }
  152. //Sent an amount from an account to a lite address.
  153. func (m BitCoin) TransferAccounts(parm interface{}) ([]byte, error) {
  154. pjs := parm.(*simplejson.Json)
  155. amountTmp := pjs.Get("amount").MustString()
  156. destination := pjs.Get("address").MustString()
  157. if len(amountTmp) == 0 {
  158. LOG("ERROR", " amount illeagal")
  159. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, AMOUNT_ERR, getErrMsg(AMOUNT_ERR, nil))
  160. }
  161. f, err := strconv.ParseFloat(amountTmp, 64)
  162. if err != nil {
  163. LOG("ERROR", " inner json error:%v", err.Error())
  164. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  165. }
  166. amount := float64(f)
  167. transactionid, err := CoinApi.WalleSendFrom("", destination, amount, 1, "", "")
  168. if err != nil {
  169. LOG("ERROR", " Send coin error:%v", err.Error())
  170. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, SENDCOINS_ERR, getErrMsg(SENDCOINS_ERR, nil))
  171. }
  172. if len(transactionid) != 0 {
  173. var jbuf []byte
  174. resp := make(map[string]interface{})
  175. resp["transcationids"] = []string{transactionid}
  176. resp["errcode"] = 0
  177. resp["msg"] = "ok"
  178. if jbuf, err = json.Marshal(resp); err != nil {
  179. LOG("ERROR", " inner json error:%v", err.Error())
  180. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  181. }
  182. return jbuf, nil
  183. }
  184. LOG("ERROR", " transactionid is null error:%v", err.Error())
  185. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  186. }
  187. //create a new address&key for receiving payments
  188. func (m BitCoin) CreateAddress(parm interface{}) ([]byte, error) {
  189. // Create Address From HdWallet
  190. result, err := m.CreateAddressFromHdWallet()
  191. return result, err
  192. }
  193. //Create Address From HdWallet address&key for receiving payments
  194. func (m BitCoin) CreateAddressFromHdWallet() ([]byte, error) {
  195. if len(PubKey) == 0 {
  196. LOG("ERROR", " CreateAddressFromHdWallet PubKey is null!")
  197. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  198. }
  199. var backupindex uint32
  200. //get BACKUPPUBKEYINDEX from bitcoindb
  201. backuppubkeyindex, err := bitcoindb.Get([]byte(BACKUPPUBKEYINDEX))
  202. if err != nil {
  203. LOG("ERROR", " bitcoindb.Get erroe!")
  204. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  205. }
  206. if len(string(backuppubkeyindex)) == 0 {
  207. backupindex = 0
  208. } else {
  209. if err := json.Unmarshal([]byte(backuppubkeyindex), &backupindex); err != nil {
  210. fmt.Println("Unmarshal err :", err.Error())
  211. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  212. }
  213. }
  214. LOG("DEBUG", "litedb.Get BACKUPPUBKEYINDEX:%v", backupindex)
  215. //check pubkey child start index
  216. if backupindex < StartCount {
  217. LOG("ERROR", " backupindex:%v < StartCount:%v!", backupindex, StartCount)
  218. backupindex = StartCount
  219. }
  220. //check pubkey child end index
  221. if EndCount != 0 && backupindex > EndCount {
  222. LOG("ERROR", " backupindex:%v > EndCount:%v!", backupindex, EndCount)
  223. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  224. }
  225. index := backupindex + 1
  226. pubkey := btc.StringChild(PubKey, index)
  227. addr, err := btc.StringAddress(pubkey)
  228. if err != nil {
  229. LOG("ERROR", " StringAddress error!Pub:%v,index:%v", PubKey, index)
  230. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  231. }
  232. var jbuf []byte
  233. resp := make(map[string]interface{})
  234. resp["address"] = addr
  235. resp["privkey"] = ""
  236. resp["errcode"] = 0
  237. if jbuf, err = json.Marshal(resp); err != nil {
  238. LOG("ERROR", " inner json error:%v", err.Error())
  239. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  240. }
  241. // back up index in db
  242. var pubkeyindex []byte
  243. if pubkeyindex, err = json.Marshal(index); err != nil {
  244. fmt.Println("Marshal err :", err.Error())
  245. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  246. }
  247. bitcoindb.Put([]byte(BACKUPPUBKEYINDEX), pubkeyindex)
  248. //Import the Address in Wallet watche only cannot be used to spend
  249. _, err = CoinApi.WalletImportAddress(addr, false)
  250. if err != nil {
  251. LOG("ERROR", "WalletImportAddress:%v, error:%v", addr, err.Error())
  252. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  253. }
  254. return jbuf, nil
  255. }
  256. //create a new address&key for receiving payments
  257. func (m BitCoin) CreateAddressFromWallet() ([]byte, error) {
  258. addr, err := CoinApi.WalletNewAddr()
  259. if err != nil {
  260. LOG("ERROR", " get new address error:%v", err.Error())
  261. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETNEWADDRESS_ERR, getErrMsg(GETNEWADDRESS_ERR, nil))
  262. }
  263. if len(addr) != 0 {
  264. //get key by the address
  265. key, err := CoinApi.WalletDumpPrivKey(addr)
  266. if err != nil {
  267. LOG("ERROR", " dump private key error:%v", err.Error())
  268. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, DUMPPRIVKEY_ERR, getErrMsg(DUMPPRIVKEY_ERR, nil))
  269. }
  270. if len(key) != 0 {
  271. var jbuf []byte
  272. resp := make(map[string]interface{})
  273. resp["address"] = addr
  274. resp["privkey"] = key
  275. resp["errcode"] = 0
  276. if jbuf, err = json.Marshal(resp); err != nil {
  277. LOG("ERROR", " inner json error:%v", err.Error())
  278. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  279. }
  280. return jbuf, nil
  281. }
  282. LOG("ERROR", " privkey is null error:%v")
  283. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  284. }
  285. LOG("ERROR", " address is null error:%v")
  286. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  287. }
  288. func (m BitCoin) getwalletinfo() bool {
  289. fmt.Println("WalletInfo:")
  290. m.walletstatus = false
  291. for {
  292. if m.walletstatus == false {
  293. resp, err := CoinApi.WalletInfo()
  294. if err != nil {
  295. LOG("ERROR", "WalletInfo error:%v", err.Error())
  296. time.Sleep(time.Second * 1)
  297. continue
  298. }
  299. LOG("DEBUG", "WalletInfo resp:%v", string(resp))
  300. m.walletstatus = true
  301. }
  302. time.Sleep(time.Second)
  303. }
  304. }
  305. //config rpc from lite.toml
  306. func (m BitCoin) initconfig() bool {
  307. if _, err := tml.DecodeFile("./src/bitcoin/bitcoin.toml", &Config); err != nil {
  308. fmt.Println(err)
  309. return false
  310. }
  311. fmt.Printf("%+v\n", Config)
  312. User := Config.Rpc.Rpcuser
  313. Password := Config.Rpc.Rpcpassword
  314. Host := Config.Rpc.Rpchost
  315. Port := Config.Rpc.Rpcport
  316. CoinApi.InitRpcConf(User, Password, Host, Port)
  317. initLiteErr()
  318. //init bitcoin db
  319. bitcoindb.InitGoleveldb()
  320. PubKey = Config.Pubkey.Pubkeystr
  321. LOG("DEBUG", "PubKey:%v", PubKey)
  322. StartCount = Config.Count.Startcount
  323. EndCount = Config.Count.Endcount
  324. LOG("DEBUG", "StartCount:%v,EndCount%v", StartCount, EndCount)
  325. f, err := strconv.ParseFloat(Config.Limit.Fee, 64)
  326. if err != nil {
  327. LOG("ERROR", "inner json error:%v", err.Error())
  328. return false
  329. }
  330. fee := float64(f)
  331. CoinApi.WalletSetTxFee(fee)
  332. return true
  333. }
  334. func (m BitCoin) ChainHeight(parm interface{}) ([]byte, error) {
  335. blockcount, err := CoinApi.WalleGetBlockCount()
  336. if err != nil {
  337. LOG("ERROR", " get current block count error:%v", err.Error())
  338. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, GETCLOCKCOUNT_ERR, getErrMsg(GETCLOCKCOUNT_ERR, nil))
  339. }
  340. sendstr := fmt.Sprintf(`{"errcode":%v,"height":%v}`, OK, blockcount)
  341. return []byte(sendstr), nil
  342. }
  343. func (m BitCoin) ListUnspent(parm interface{}) ([]byte, error) {
  344. i_unspent := make([]map[string]interface{}, 0)
  345. pjs := parm.(*simplejson.Json)
  346. Issync, err := pjs.Get("Sync").Bool()
  347. if !Issync {
  348. fmt.Println("The listunspent data Asynchrony!!!!")
  349. i_unspent = m_unspent
  350. } else {
  351. address, err := pjs.Get("address").StringArray()
  352. if err != nil {
  353. LOG("ERROR", " input parm error:%v", err.Error())
  354. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
  355. }
  356. unspent, err := CoinApi.Listunspent(address)
  357. if err != nil {
  358. LOG("ERROR", " get listunspent:%v", err.Error())
  359. //return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
  360. }
  361. i_unspent = unspent
  362. }
  363. var jbuf []byte
  364. resptmp := make(map[string]interface{})
  365. resptmp["errcode"] = 0
  366. resptmp["cointype"] = "BTC"
  367. resptmp["unspents"] = i_unspent
  368. if jbuf, err = json.Marshal(resptmp); err != nil {
  369. LOG("ERROR", " inner json error:%v", err.Error())
  370. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  371. }
  372. return jbuf, nil
  373. }
  374. func (m BitCoin) SendRawTransaction(parm interface{}) ([]byte, error) {
  375. pjs := parm.(*simplejson.Json)
  376. transdata := pjs.Get("data").MustString()
  377. if len(transdata) == 0 {
  378. return nil, fmt.Errorf(`{"cointype":"BTC","errcode":%v,"msg":"%v"}`, PARM_ERR, getErrMsg(PARM_ERR, []byte("hexstring is null")))
  379. }
  380. transactionhex, err := CoinApi.SendRawTransaction(transdata)
  381. if err != nil {
  382. LOG("ERROR", " SendRawTransaction err:%s", err.Error())
  383. return nil, fmt.Errorf(`{"cointype":"BTC","errcode":%v,"msg":"%s"}`, SEND_RAW_TRANSACTION_ERR, getErrMsg(SEND_RAW_TRANSACTION_ERR, nil))
  384. }
  385. var jbuf []byte
  386. resp := make(map[string]interface{})
  387. resp["cointype"] = "BTC"
  388. resp["transactionids"] = transactionhex
  389. resp["errcode"] = 0
  390. resp["msg"] = "OK"
  391. if jbuf, err = json.Marshal(resp); err != nil {
  392. LOG("ERROR", "inner json error:%v", err.Error())
  393. return nil, fmt.Errorf(`{"cointype":"BTC","errcode":%v,"msg":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  394. }
  395. return jbuf, nil
  396. }
  397. func (m BitCoin) SumcoinBalance(parm interface{}) ([]byte, error) {
  398. return nil, nil
  399. }
  400. func (m BitCoin) AccountsBalance(parm interface{}) (jbuf []byte, err error) {
  401. var balancestotal, offlinebalancetotal float64
  402. ilistunspent := m_unspent
  403. accountbalance := make([]map[string]interface{}, 0)
  404. offlinebalance := make([]map[string]interface{}, 0)
  405. for _, value := range ilistunspent {
  406. if value["spendable"] == true {
  407. balancestotal += value["Amount"].(float64)
  408. accountbalance = append(accountbalance, value)
  409. } else {
  410. offlinebalancetotal += value["Amount"].(float64)
  411. offlinebalance = append(offlinebalance, value)
  412. }
  413. }
  414. resptmp := make(map[string]interface{})
  415. resptmp["errcode"] = 0
  416. resptmp["cointype"] = "BTC"
  417. resptmp["accountbalance"] = accountbalance
  418. resptmp["balancestotal"] = balancestotal
  419. resptmp["offlinebalance"] = offlinebalance
  420. resptmp["offlinebalancetotal"] = offlinebalancetotal
  421. if jbuf, err = json.Marshal(resptmp); err != nil {
  422. LOG("ERROR", " inner json error:%v", err.Error())
  423. return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
  424. }
  425. return jbuf, nil
  426. }
  427. func AsyncRoutine() {
  428. CachelistunspentTicker := time.NewTicker(120 * time.Second)
  429. for {
  430. select {
  431. case _ = <-CachelistunspentTicker.C:
  432. Cachelistunspent()
  433. }
  434. }
  435. }
  436. func Cachelistunspent() {
  437. fmt.Println("cachelistunspent time:", time.Now().Format("2006-01-02 15:04:05"))
  438. var address []string
  439. m_unspent = make([]map[string]interface{}, 0)
  440. unspent, err := CoinApi.Listunspent(address)
  441. if err != nil {
  442. LOG("ERROR", " get listunspent:%v", err.Error())
  443. //return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
  444. }
  445. m_mutUnspent.Lock()
  446. m_unspent = unspent
  447. m_mutUnspent.Unlock()
  448. }
  449. func init() {
  450. Register(NameCoin, &BitCoin{})
  451. }