kmd REST API Example

See Using the REST APIs for an overview on how Algorand's APIs are available using REST servers.

The REST API for the kmd process provides calls to make wallets, generate keys, export keys, delete keys, and sign unsigned transactions. This tutorial walks through using the REST API from a sample GO application. In this example, we use the wallet call to make a wallet. This example makes use of the go-swagger project to produce a REST client for the specific kmd swagger.json file. There are many ways to install go-swagger. In this example, we just install it from the source using the following command:

go get -u github.com/go-swagger/go-swagger/cmd/swagger

Create your go project in your desired folder. In this example we created a project called swagger-example and created a main.go. Before putting any code in the main file, the REST client needs to be generated. 

The /swagger.json REST endpoint for the kmd process will provide this file in the near future:

curl http://$(cat ~/node/data/kmd-version/kmd.net)/swagger.json > swagger.json

Note: The kmd process is currently not serving the swagger.json file. This will be enabled in the next TestNet uplift. To get the swagger file for kmd now just copy the contents from here.

The client can be generated using the following command, once go-swagger is installed.

swagger generate client -f swagger.json

This will generate client and models packages for using the REST API. These can be imported into your sample application.

Remember to update the algorand/swagger-example path to reflect your project's location.


package main

import (
	"encoding/json"
	"fmt"
	"log"

	httptransport "github.com/go-openapi/runtime/client"

	"github.com/algorand/go-algorand/swagger-example/kmd/client"
	"github.com/algorand/go-algorand/swagger-example/kmd/client/operations"
	"github.com/algorand/go-algorand/swagger-example/kmd/models"

)

The main configuration parameters that will be required to use the REST API are the servers listening address and port, and the specific API token that is needed to make REST calls. These can be retrieved from the kmd-version directory. In this example, we use a private network so the kmd-version folder will be in the data directory for any of the nodes within the private network. These files will be named kmd.net and kmd.token. The following code just sets up the configuration. The server address and token values may be different every install.


const (
	ServerAddress           = "localhost:8081"
	TokenRequestKey         = "X-KMD-API-Token"
	TokenRequestKeyLocation = "header"
)

// This code requires a swagger generated client. To generate a client:
//     `go get -u github.com/go-swagger/go-swagger/cmd/swagger`
//     `swagger generate client -f ./swagger.json`
func main() {

	cfg := client.DefaultTransportConfig().WithHost(ServerAddress)
	apiclient := client.NewHTTPClientWithConfig(nil, cfg)

	// You will need to add your own logic for fetching a token
	token := "90c4a46490baaef91597366d28e13829721a143df02d29dc5831fbbda186d9e7"
	apiKeyQueryAuth := httptransport.APIKeyAuth(TokenRequestKey, TokenRequestKeyLocation, token)

Next, we set up a call to create the wallet by defining the parameters that the call will need. these will be passed to the CreateWallet function. 



	wParams := operations.NewCreateWalletParams()
	var cWalletRequest models.APIV1POSTWalletRequest
	cWalletRequest.WalletDriverName = "sqlite"
	cWalletRequest.WalletName = "MyWallet10"
	cWalletRequest.WalletPassword = "TestPass"
	wParams.SetCreateWalletRequest(&cWalletRequest)
	statusResponse, err := apiclient.Operations.CreateWallet(wParams, apiKeyQueryAuth)
	if err != nil {
		log.Fatal(err)
	}

The CreateWallet function will return details on the wallet that is created. In this example, we just print them out.

 
	// unwrap the response
	walletResponse := *statusResponse.Payload
	if statusResponse.Payload == nil {
		log.Fatal(fmt.Errorf("KMD API returned empty wallet response"))
	}

	fmt.Printf("\n-----------------Wallet Information-------------------\n")
	walletJSON, err := json.MarshalIndent(walletResponse, "", "\t")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(walletJSON))

With main.go ready based on the above code, you should be able to run it using:

go run main.go

If that fails to build, ensure you updated the algorand/swagger-example path in the import statements.

You may also need to get the open-api libraries that swagger leverages:

go get -u github.com/open-api/...