ergoplatform / ergoplatform/ergo-appkit

Calling WalletApi.walletBoxesCollect throws an exception

Open
#183 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
44
Forks
34
PR merge metrics
No merged PRs in 30d

Description

I am trying to use the new `WalletApi` to get some boxes from my wallet.

I created the wallet service like this
```scala
// 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
```scala
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_.
![image](https://user-images.githubusercontent.com/33580723/179362540-495f1676-4e9f-4bfb-95b0-d3d511e35df7.png)

However, I noticed that [the appkit method](https://github.com/ergoplatform/ergo-appkit/blob/develop/java-client-generated/src/main/java/org/ergoplatform/restapi/client/WalletApi.java#L152) that queries that endpoint has a `@GET` annotation for it
![image](https://user-images.githubusercontent.com/33580723/179362578-4a699636-3c2d-46b0-ba4d-d01bbc9d16d1.png)

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,
```java
public interface NewWalletApi {
@Headers({
"Content-Type:application/json"
})
@POST("wallet/boxes/collect")
Call> walletBoxesCollect(
@retrofit2.http.Body BoxesRequestHolder body
);
}
```

updated the wallet service creation to use the interface,
```scala
val walletService = apiClient.createService(classOf[NewWalletApi])
```

and tried executing a request again.
```scala
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.

![image](https://user-images.githubusercontent.com/33580723/179363932-227051d0-44cf-4b7a-84d8-6b37a853fc75.png)

1. `targetAssets` is required and cannot be `null`.
1. In the Swagger example, `targetAssets` is shown as a List of Lists (the `BoxesRequestHolder` Java model [reflects this](https://github.com/ergoplatform/ergo-appkit/blob/315c6d36955756e0f78da63e214a12d4221568b2/java-client-generated/src/main/java/org/ergoplatform/restapi/client/BoxesRequestHolder.java#L31)).
1. Sending a request, via the Swagger page, following this suggested structure _results in a **400 - Bad Request**_.

I tried out a few combinations
```json
// 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!
```json
{
// empty object/map
"targetAssets": {}
...
}
```

![image](https://user-images.githubusercontent.com/33580723/179364789-0f883244-d107-4109-979b-fbb3945b4df8.png)

So, it looks like
1. `targetAssets` cannot be `null` but it _can_ be empty.
1. 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`, 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

```java
public class NewBoxesRequestHolder {
@SerializedName("targetAssets")
private java.util.HashMap targetAssets = new HashMap<>();

@SerializedName("targetBalance")
private Long targetBalance = null;

public NewBoxesRequestHolder targetAssets(java.util.HashMap targetAssets) {
this.targetAssets = targetAssets;
return this;
}

public NewBoxesRequestHolder targetBalance(Long targetBalance) {
this.targetBalance = targetBalance;
return this;
}

public java.util.HashMap getTargetAssets() {
return targetAssets;
}

public void setTargetAssets(java.util.HashMap 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!

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.