func getUxOutByID(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { wh.Error405(w, "") return } uxid := r.FormValue("uxid") if uxid == "" { wh.Error400(w, "uxid is empty") return } id, err := cipher.SHA256FromHex(uxid) if err != nil { wh.Error400(w, err.Error()) return } uxout, err := gateway.GetUxOutByID(id) if err != nil { wh.Error400(w, err.Error()) return } if uxout == nil { wh.Error404(w, "not found") return } wh.SendOr404(w, uxout) } }
func getAddrUxOuts(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { wh.Error405(w, "") return } addr := r.FormValue("address") if addr == "" { wh.Error400(w, "address is empty") return } cipherAddr, err := cipher.DecodeBase58Address(addr) if err != nil { wh.Error400(w, err.Error()) return } uxs, err := gateway.GetAddrUxOuts(cipherAddr) if err != nil { wh.Error400(w, err.Error()) return } wh.SendOr404(w, uxs) } }
func getTransactionByID(gate *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { wh.Error405(w, "") return } txid := r.FormValue("txid") if txid == "" { wh.Error400(w, "txid is empty") return } h, err := cipher.SHA256FromHex(txid) if err != nil { wh.Error400(w, err.Error()) return } tx, err := gate.V.GetTransaction(h) if err != nil { wh.Error400(w, err.Error()) return } if tx == nil { wh.Error404(w, "not found") return } resTx := visor.TransactionResult{ Transaction: visor.NewReadableTransaction(tx), Status: tx.Status, } wh.SendOr404(w, &resTx) } }
func getRawTx(gate *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { wh.Error405(w, "") return } txid := r.FormValue("txid") if txid == "" { wh.Error400(w, "txid is empty") return } h, err := cipher.SHA256FromHex(txid) if err != nil { wh.Error400(w, err.Error()) return } tx, err := gate.V.GetTransaction(h) if err != nil { wh.Error400(w, err.Error()) return } d := tx.Txn.Serialize() wh.SendOr404(w, hex.EncodeToString(d)) return } }
// Update wallet label func walletUpdateHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // Update wallet id := r.FormValue("id") if id == "" { wh.Error400(w, "wallet id is empty") return } label := r.FormValue("label") if label == "" { wh.Error400(w, "label is empty") return } wlt := Wg.GetWallet(id) if wlt == nil { wh.Error404(w, fmt.Sprintf("wallet of id: %v does not exist", id)) return } wlt.SetLabel(label) if err := Wg.SaveWallet(wlt.GetID()); err != nil { m := "Failed to save wallet: %v" logger.Critical(m, "Failed to update label of wallet %v", id) wh.Error500(w, "Update wallet failed") return } wh.SendOr404(w, "success") } }
// Returns all loaded wallets func walletsHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { //ret := wallet.Wallets.ToPublicReadable() ret := Wg.GetWalletsReadable() wh.SendOr404(w, ret) } }
func walletNewAddresses(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { wh.Error405(w, "") return } wltID := r.FormValue("id") if wltID == "" { wh.Error400(w, "wallet id not set") return } addrs, err := Wg.NewAddresses(wltID, 1) if err != nil { wh.Error400(w, err.Error()) return } if err := Wg.SaveWallet(wltID); err != nil { wh.Error500(w, "") return } var rlt = struct { Address string `json:"address"` }{ addrs[0].String(), } wh.SendOr404(w, rlt) return } }
func getBalanceHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { addrsParam := r.URL.Query().Get("addrs") addrsStr := strings.Split(addrsParam, ",") addrs := make([]cipher.Address, len(addrsStr)) addrSet := make(map[cipher.Address]byte) for i, addr := range addrsStr { addrs[i] = cipher.MustDecodeBase58Address(addr) addrSet[addrs[i]] = byte(1) } v := gateway.D.Visor.Visor auxs := v.Blockchain.GetUnspent().AllForAddresses(addrs) unspent := v.Blockchain.GetUnspent() puxs := v.Unconfirmed.SpendsForAddresses(unspent, addrSet) coins1, hours1 := v.AddressBalance(auxs) coins2, hours2 := v.AddressBalance(auxs.Sub(puxs)) confirmed := wallet.Balance{coins1, hours1} predicted := wallet.Balance{coins2, hours2} bal := struct { Confirmed wallet.Balance `json:"confirmed"` Predicted wallet.Balance `json:"predicted"` }{ Confirmed: confirmed, Predicted: predicted, } wh.SendOr404(w, bal) } } }
// Returns a wallet by ID if GET. Creates or updates a wallet if POST. func walletGet(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { ret := Wg.GetWallet(r.FormValue("id")) wh.SendOr404(w, ret) } } }
// Creates and broadcasts a transaction sending money from one of our wallets // to destination address. func walletSpendHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { //log.Printf("Spend1") if r.FormValue("id") == "" { wh.Error400(w, "Missing wallet_id") return } walletId := r.FormValue("id") if walletId == "" { wh.Error400(w, "Invalid Wallet Id") return } sdst := r.FormValue("dst") if sdst == "" { wh.Error400(w, "Missing destination address \"dst\"") return } dst, err := cipher.DecodeBase58Address(sdst) if err != nil { //Error400(w, "Invalid destination address: %v", err) wh.Error400(w, "Invalid destination address: %v", err.Error()) return } //set fee automatically for now /* sfee := r.FormValue("fee") fee, err := strconv.ParseUint(sfee, 10, 64) if err != nil { Error400(w, "Invalid \"fee\" value") return } */ //var fee uint64 = 0 scoins := r.FormValue("coins") //shours := r.FormValue("hours") coins, err := strconv.ParseUint(scoins, 10, 64) if err != nil { wh.Error400(w, "Invalid \"coins\" value") return } var hours uint64 = 0 var fee uint64 = 0 //doesnt work/do anything right now //MOVE THIS INTO HERE ret := Spend(gateway.D, gateway.D.Visor, Wg, walletId, wallet.NewBalance(coins, hours), fee, dst) if ret.Error != "" { wh.Error400(w, "Spend Failed: %s", ret.Error) } wh.SendOr404(w, ret) } }
func connectionHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if addr := r.FormValue("addr"); addr == "" { wh.Error404(w) } else { wh.SendOr404(w, gateway.GetConnection(addr)) } } }
// Returns JSON of unconfirmed transactions for user's wallet func walletTransactionsHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { wallet := Wg.GetWallet(r.FormValue("id")) addresses := wallet.GetAddresses() ret := gateway.Visor.GetUnconfirmedTxns(gateway.V, addresses) wh.SendOr404(w, ret) } } }
// get block by hash or seq // method: GET // url: /block?hash=[:hash] or /block?seq[:seq] // params: hash or seq, should only specify one filter. func getBlock(gate *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { wh.Error405(w, "") return } hash := r.FormValue("hash") seq := r.FormValue("seq") var b *coin.Block switch { case hash == "" && seq == "": wh.Error400(w, "should specify one filter, hash or seq") return case hash != "" && seq != "": wh.Error400(w, "should only specify one filter, hash or seq") return case hash != "": h, err := cipher.SHA256FromHex(hash) if err != nil { wh.Error400(w, err.Error()) return } b = gate.V.GetBlockByHash(h) case seq != "": uSeq, err := strconv.ParseUint(seq, 10, 64) if err != nil { wh.Error400(w, err.Error()) return } b = gate.V.GetBlockBySeq(uSeq) } if b == nil { wh.SendOr404(w, nil) return } wh.SendOr404(w, visor.NewReadableBlock(b)) } }
// Generating secret key, address, public key by given // GET/POST // bc - bool - is bitcoin type (optional) - default: true // n - int - Generation count (optional) - default: 1 // s - bool - is hide secret key (optional) - default: false // seed - string - seed hash func apiCreateAddressHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var seed string = r.FormValue("seed") var err error if seed == "" { wh.Error400(w, "Empty seed") return } isBitcoin, err = strconv.ParseBool(r.FormValue("bc")) if err != nil { isBitcoin = true } genCount, err := strconv.Atoi(r.FormValue("n")) if err != nil { genCount = 1 } hideSecKey, err = strconv.ParseBool(r.FormValue("s")) if err != nil { hideSecKey = false } wallet := Wallet{ Meta: make(map[string]string), //map[string]string Entries: make([]KeyEntry, genCount), } if isBitcoin == false { wallet.Meta = map[string]string{"coin": "skycoin"} } else { wallet.Meta = map[string]string{"coin": "bitcoin"} } wallet.Meta["seed"] = seed seckeys := cipher.GenerateDeterministicKeyPairs([]byte(seed), genCount) for i, sec := range seckeys { pub := cipher.PubKeyFromSecKey(sec) wallet.Entries[i] = getKeyEntry(pub, sec) } ret := wallet wh.SendOr404(w, ret) } }
// Returns pending transactions func getPendingTxs(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { wh.Error405(w, "") return } V := gateway.V ret := make([]*visor.ReadableUnconfirmedTxn, 0, len(V.Unconfirmed.Txns)) for _, unconfirmedTxn := range V.Unconfirmed.Txns { readable := visor.NewReadableUnconfirmedTxn(&unconfirmedTxn) ret = append(ret, &readable) } wh.SendOr404(w, &ret) } }
func (rh *rpcHandler) Handler(w http.ResponseWriter, r *http.Request) { var ( req Request res Response ) for { // only support post. if r.Method != "POST" { res = makeErrorResponse(errCodeInvalidRequest, errMsgNotPost) break } // deocder request. if err := json.NewDecoder(r.Body).Decode(&req); err != nil { res = makeErrorResponse(errCodeParseError, errMsgParseError) break } if req.Jsonrpc != jsonRPC { res = makeErrorResponse(errCodeInvalidParams, errMsgInvalidJsonrpc) break } resC := make(chan Response) rh.ops <- func(rpc *rpcHandler) { defer func() { if r := recover(); r != nil { logger.Critical(fmt.Sprintf("%v", r)) resC <- makeErrorResponse(errCodeInternalError, errMsgInternalError) } }() if handler, ok := rpc.handlers[req.Method]; ok { logger.Info("method: %v", req.Method) resC <- handler(req, rpc.gateway) return } resC <- makeErrorResponse(errCodeMethodNotFound, errMsgMethodNotFound) } res = <-resC break } wh.SendOr404(w, &res) }
// Returns the wallet's balance, both confirmed and predicted. The predicted // balance is the confirmed balance minus the pending spends. func walletBalanceHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id := r.FormValue("id") //addr := r.FormValue("addr") //r.ParseForm() //r.ParseMultipartForm() //log.Println(r.Form) //r.URL.String() r.ParseForm() b, err := Wg.GetWalletBalance(gateway.D.Visor.Visor, id) if err != nil { _ = err } //log.Printf("%v, %v, %v \n", r.URL.String(), r.RequestURI, r.Form) wh.SendOr404(w, b) } }
//Implement func injectTransaction(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { wh.Error405(w, "") return } // get the rawtransaction v := struct { Rawtx string `json:"rawtx"` }{} if err := json.NewDecoder(r.Body).Decode(&v); err != nil { logger.Error("bad request: %v", err) wh.Error400(w, err.Error()) return } b, err := hex.DecodeString(v.Rawtx) if err != nil { logger.Error("%v", err) wh.Error400(w, err.Error()) return } txn := coin.TransactionDeserialize(b) if err := visor.VerifyTransactionFee(gateway.D.Visor.Visor.Blockchain, &txn); err != nil { wh.Error400(w, err.Error()) return } t, err := gateway.D.Visor.InjectTransaction(txn, gateway.D.Pool) if err != nil { wh.Error400(w, fmt.Sprintf("inject tx failed:%v", err)) return } wh.SendOr404(w, t.Hash().Hex()) } }
func getBlocks(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { wh.Error405(w, "") return } sstart := r.FormValue("start") start, err := strconv.ParseUint(sstart, 10, 64) if err != nil { wh.Error400(w, fmt.Sprintf("Invalid start value \"%s\"", sstart)) return } send := r.FormValue("end") end, err := strconv.ParseUint(send, 10, 64) if err != nil { wh.Error400(w, fmt.Sprintf("Invalid end value \"%s\"", send)) return } wh.SendOr404(w, gateway.GetBlocks(start, end)) } }
// get last N blocks func getLastBlocks(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { wh.Error405(w, "") return } num := r.FormValue("num") if num == "" { wh.Error400(w, "Param: num is empty") return } n, err := strconv.ParseUint(num, 10, 64) if err != nil { wh.Error400(w, err.Error()) return } wh.SendOr404(w, gateway.GetLastBlocks(n)) } }
// getOutputsHandler get utxos base on the filters in url params. // mode: GET // url: /outputs?addrs=[:addrs]&hashes=[:hashes] // if addrs and hashes are not specificed, return all unspent outputs. // if both addrs and hashes are specificed, then both those filters are need to be matched. // if only specify one filter, then return outputs match the filter. func getOutputsHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { var addrs []string var hashes []string trimSpace := func(vs []string) []string { for i := range vs { vs[i] = strings.TrimSpace(vs[i]) } return vs } addrStr := r.FormValue("addrs") if addrStr != "" { addrs = trimSpace(strings.Split(addrStr, ",")) } hashStr := r.FormValue("hashes") if hashStr != "" { hashes = trimSpace(strings.Split(hashStr, ",")) } filters := []daemon.OutputsFilter{} if len(addrs) > 0 { filters = append(filters, daemon.FbyAddresses(addrs)) } if len(hashes) > 0 { filters = append(filters, daemon.FbyHashes(hashes)) } outs := gateway.GetUnspentOutputs(filters...) wh.SendOr404(w, outs) } } }
// getLastTxs get the last confirmed txs. func getLastTxs(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { wh.Error405(w, "") return } txs, err := gateway.V.GetLastTxs() if err != nil { wh.Error500(w, err.Error()) return } resTxs := make([]visor.TransactionResult, len(txs)) for i, tx := range txs { resTxs[i] = visor.TransactionResult{ Transaction: visor.NewReadableTransaction(tx), Status: tx.Status, } } wh.SendOr404(w, &resTxs) } }
func newWalletSeed(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { entropy, err := bip39.NewEntropy(128) if err != nil { wh.Error500(w) return } mnemonic, err := bip39.NewMnemonic(entropy) if err != nil { wh.Error500(w) return } var rlt = struct { Seed string `json:"seed"` }{ mnemonic, } wh.SendOr404(w, rlt) } }
func defaultConnectionsHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { wh.SendOr404(w, gateway.GetDefaultConnections()) } }
func blockchainProgressHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { wh.SendOr404(w, gateway.GetBlockchainProgress()) } }