I am trying to use the new WalletApi to get some boxes from my wallet.
I created the wallet service like this
// conf is of type ErgoToolConfig
val apiClient = new ApiClient(conf.getNode.getNodeApi.getApiUrl, "ApiKeyAuth", conf.getNode.getNodeApi.getApiKey)
val walletService = apiClient.createService(classOf[WalletApi])
Then I'm using it like this to get some amount of ERG from my wallet
val getWalletBoxesRequest = new BoxesRequestHolder().targetBalance(Parameters.OneErg)
val response = walletService.walletBoxesCollect(getWalletBoxesRequest).execute()
But that call throws the following error:
Exception in thread "main" java.lang.IllegalArgumentException: Non-body HTTP method cannot contain @Body.
After a little digging, I found that WalletApi.walletBoxesCollect queries /wallet/boxes/collect in the node's API, which is a POST endpoint.

However, I noticed that the appkit method that queries that endpoint has a @GET annotation for it

It seemed like the fix was as simple as changing the annotation from @GET to @POST, so I tried it locally. For simplicity's sake, I created a Java interface in my codebase,
public interface NewWalletApi {
@Headers({
"Content-Type:application/json"
})
@POST("wallet/boxes/collect")
Call<List<WalletBox>> walletBoxesCollect(
@retrofit2.http.Body BoxesRequestHolder body
);
}
updated the wallet service creation to use the interface,
val walletService = apiClient.createService(classOf[NewWalletApi])
and tried executing a request again.
val getWalletBoxesRequest = new BoxesRequestHolder().targetBalance(Parameters.OneErg)
val response = walletService.walletBoxesCollect(getWalletBoxesRequest).execute()
This time, I just got a Bad Request back from the node, no further details.
So I went to the node's Swagger page to inspect that endpoint further (POST /wallet/boxes/collect), and soon learned some things about the expected request body.

targetAssets is required and cannot be null.
- In the Swagger example,
targetAssets is shown as a List of Lists (the BoxesRequestHolder Java model reflects this).
- Sending a request, via the Swagger page, following this suggested structure results in a 400 - Bad Request.
I tried out a few combinations
// empty list
{
"targetAssets": []
...
}
// empty list with empty list
{
"targetAssets": [[]]
...
}
// list of lists with "dummy" values
{
"targetAssets": [["", 0]]
...
}
None worked. Until finally I tried this, and it worked!
{
// empty object/map
"targetAssets": {}
...
}

So, it looks like
targetAssets cannot be null but it can be empty.
- Despite the Swagger example,
targetAssets needs to be an object/map (where each key/value pair represent asset_id/amount), NOT a list of lists (array of arrays).
So, I tried updating the targetAssets property in the BoxesRequestHolder model to a HashMap<String, Long>, executed another request from my code using appkit, but then I got this error:
Note: to facilitate and speed up local testing of this, I created a new model NewBoxesRequestHolder, updated targetAssets as needed, and used it to build a request body instead of BoxesRequestHolder
Click to expand
public class NewBoxesRequestHolder {
@SerializedName("targetAssets")
private java.util.HashMap<String, Long> targetAssets = new HashMap<>();
@SerializedName("targetBalance")
private Long targetBalance = null;
public NewBoxesRequestHolder targetAssets(java.util.HashMap<String, Long> targetAssets) {
this.targetAssets = targetAssets;
return this;
}
public NewBoxesRequestHolder targetBalance(Long targetBalance) {
this.targetBalance = targetBalance;
return this;
}
public java.util.HashMap<String, Long> getTargetAssets() {
return targetAssets;
}
public void setTargetAssets(java.util.HashMap<String, Long> targetAssets) {
this.targetAssets = targetAssets;
}
public Long getTargetBalance() {
return targetBalance;
}
public void setTargetBalance(Long targetBalance) {
this.targetBalance = targetBalance;
}
}
Exception in thread "main" java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:39) at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27) at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225) at retrofit2.OkHttpCall.execute(OkHttpCall.java:188)
While I've figrued out how to send a valid request to POST /wallet/boxes/collect via the node's Swagger page, I have not yet managed to get it to work via appkit.
I'm still into it but this is as far as I've made it. If anyone has any useful insights into how to potentially resolve this issue, they'd be greatly appreciated!
I am trying to use the new
WalletApito get some boxes from my wallet.I created the wallet service like this
Then I'm using it like this to get some amount of ERG from my wallet
But that call throws the following error:
After a little digging, I found that

WalletApi.walletBoxesCollectqueries/wallet/boxes/collectin the node's API, which is a POST endpoint.However, I noticed that the appkit method that queries that endpoint has a

@GETannotation for itIt seemed like the fix was as simple as changing the annotation from
@GETto@POST, so I tried it locally. For simplicity's sake, I created a Java interface in my codebase,updated the wallet service creation to use the interface,
and tried executing a request again.
This time, I just got a
Bad Requestback from the node, no further details.So I went to the node's Swagger page to inspect that endpoint further (
POST /wallet/boxes/collect), and soon learned some things about the expected request body.targetAssetsis required and cannot benull.targetAssetsis shown as a List of Lists (theBoxesRequestHolderJava model reflects this).I tried out a few combinations
None worked. Until finally I tried this, and it worked!
{ // empty object/map "targetAssets": {} ... }So, it looks like
targetAssetscannot benullbut it can be empty.targetAssetsneeds to be an object/map (where each key/value pair represent asset_id/amount), NOT a list of lists (array of arrays).So, I tried updating the
targetAssetsproperty in theBoxesRequestHoldermodel to aHashMap<String, Long>, executed another request from my code using appkit, but then I got this error:Note: to facilitate and speed up local testing of this, I created a new model
NewBoxesRequestHolder, updatedtargetAssetsas needed, and used it to build a request body instead ofBoxesRequestHolderClick to expand
While I've figrued out how to send a valid request to
POST /wallet/boxes/collectvia the node's Swagger page, I have not yet managed to get it to work via appkit.I'm still into it but this is as far as I've made it. If anyone has any useful insights into how to potentially resolve this issue, they'd be greatly appreciated!