This package is a hub of monero related tools for Go. At this time, only the Wallet RPC Client is available.
The go-monero/walletrpc
package is a RPC client with all the methods of the v0.11.0.0 release.
It does support digest authentication, however I don't recommend using it alone (without https). If there is a need to split the RPC client and server into separate instances, you could put a proxy on the instance that contains the RPC server and check the authenticity of the requests using https + X-API-KEY headers between the proxy and this RPC client (there is an example about this implementation below)
go get -u github.com/gabstv/go-monero/walletrpc
The simplest way to use walletrpc is if you have both the server (monero-wallet-rpc) and the client on the same machine.
monero-wallet-rpc --testnet --wallet-file ~/testnet/mywallet.bin --rpc-bind-port 18082 --disable-rpc-login
Go:
package main
import (
"fmt"
"os"
"github.com/gabstv/go-monero/walletrpc"
)
func main() {
// Start a wallet client instance
client := walletrpc.New(walletrpc.Config{
Address: "http://127.0.0.1:18082/json_rpc",
})
// check wallet balance
balance, unlocked, err := client.GetBalance()
// there are two types of error that can happen:
// connection errors
// monero wallet errors
// connection errors are pretty much unicorns if everything is on the
// same instance (unless your OS hit an open files limit or something)
if err != nil {
if iswerr, werr := walletrpc.GetWalletError(err); iswerr {
// it is a monero wallet error
fmt.Printf("Wallet error (id:%v) %v\n", werr.Code, werr.Message)
os.Exit(1)
}
fmt.Println("Error:", err.Error())
os.Exit(1)
}
fmt.Println("Balance:", walletrpc.XMRToDecimal(balance))
fmt.Println("Unlocked balance:", walletrpc.XMRToDecimal(unlocked))
// Make a transfer
res, err := client.Transfer(walletrpc.TransferRequest{
Destinations: []walletrpc.Destination{
{
Address: "45eoXYNHC4LcL2Hh42T9FMPTmZHyDEwDbgfBEuNj3RZUek8A4og4KiCfVL6ZmvHBfCALnggWtHH7QHF8426yRayLQq7MLf5",
Amount: 10000000000, // 0.01 XMR
},
},
Priority: walletrpc.PriorityUnimportant,
Mixin: 1,
})
if err != nil {
if iswerr, werr := walletrpc.GetWalletError(err); iswerr {
// insufficient funds return a monero wallet error
// walletrpc.ErrGenericTransferError
fmt.Printf("Wallet error (id:%v) %v\n", werr.Code, werr.Message)
os.Exit(1)
}
fmt.Println("Error:", err.Error())
os.Exit(1)
}
fmt.Println("Transfer success! Fee:", walletrpc.XMRToDecimal(res.Fee), "Hash:", res.TxHash)
}
monero-wallet-rpc --testnet --rpc-bind-ip 127.0.0.1 --rpc-bind-port 29567 --rpc-login john:doe --wallet-file ~/testnet/wallet_03.bin
package main
import (
"fmt"
"github.com/gabstv/go-monero/walletrpc"
"github.com/gabstv/httpdigest"
)
func main() {
// username: john
// password: doe
t := httpdigest.New("john", "doe")
client := walletrpc.New(walletrpc.Config{
Address: "http://127.0.0.1:29567/json_rpc",
Transport: t,
})
balance, unlocked, err := client.GetBalance()
if err != nil {
panic(err)
}
fmt.Println("balance", walletrpc.XMRToDecimal(balance))
fmt.Println("unlocked balance", walletrpc.XMRToDecimal(unlocked))
}
You can use a proxy to be in between this client and the monero RPC server. This way you can use a safe encryption tunnel around the network.
monero-wallet-rpc --testnet --wallet-file ~/testnet/mywallet.bin --rpc-bind-port 18082 --disable-rpc-login
This example uses sandpiper (github.com/gabstv/sandpiper/sandpiper
) but you could also use nginx or apache
sandpiper config.yml:
debug: true
#listen_addr: :8084
listen_addr_tls: :23456
fallback_domain: moneroproxy
routes:
-
domain: moneroproxy
out_conn_type: HTTP
out_addr: localhost:18082
auth_mode: apikey
auth_key: X-API-KEY
auth_value: 55c12fca1b994455d3ec1795bdc82cca
tls_cert_file: moneroproxy.cert.pem
tls_key_file: moneroproxy.key.pem
The Go program is similar, but it uses an API-KEY:
package main
import (
"fmt"
"os"
"net/http"
"crypto/tls"
"github.com/gabstv/go-monero/walletrpc"
)
func main() {
// Start a wallet client instance
client := walletrpc.New(walletrpc.Config{
Address: "http://127.0.0.1:23456/json_rpc",
CustomHeaders: map[string]string{
"X-API-KEY": "55c12fca1b994455d3ec1795bdc82cca", // we use the same key defined above
},
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, // WARNING: instead of this, you can
// provide (or install) a certificate to make it
// really secure with Certificates: []tls.Certificate{},
},
},
})
// check wallet balance
balance, unlocked, err := client.GetBalance()
// there are two types of error that can happen:
// connection errors
// monero wallet errors
// connection errors are pretty much unicorns if everything is on the
// same instance (unless your OS hit an open files limit or something)
if err != nil {
if iswerr, werr := walletrpc.GetWalletError(err); iswerr {
// it is a monero wallet error
fmt.Printf("Wallet error (id:%v) %v\n", werr.Code, werr.Message)
os.Exit(1)
}
fmt.Println("Error:", err.Error())
os.Exit(1)
}
fmt.Println("Balance:", walletrpc.XMRToDecimal(balance))
fmt.Println("Unlocked balance:", walletrpc.XMRToDecimal(unlocked))
}