-
Notifications
You must be signed in to change notification settings - Fork 3
Implement GetBalance client call and server endpoint #217
Changes from all commits
5894279
0dba7c2
f21cdf0
35aa08d
a1d2f91
09f4762
494156b
6a57244
6b74577
7a0ae63
18dd13f
ceadf77
0ce5957
da2aafe
15d18d3
8a31cda
61a1446
393e9eb
1fad2ed
01d6a12
9f90c3c
0e8d498
c67f00a
43bf4c8
f500e35
c71048d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ import tbdex.sdk.httpclient.models.GetExchangesFilter | |
import tbdex.sdk.httpclient.models.GetOfferingsFilter | ||
import tbdex.sdk.httpclient.models.TbdexResponseException | ||
import tbdex.sdk.protocol.Validator | ||
import tbdex.sdk.protocol.models.Balance | ||
import tbdex.sdk.protocol.models.Close | ||
import tbdex.sdk.protocol.models.Message | ||
import tbdex.sdk.protocol.models.Offering | ||
|
@@ -29,6 +30,8 @@ import web5.sdk.dids.did.BearerDid | |
*/ | ||
object TbdexHttpClient { | ||
private val client = OkHttpClient() | ||
private const val CONTENT_TYPE = "Content-Type" | ||
private const val AUTHORIZATION = "Authorization" | ||
private val jsonMediaType = "application/json; charset=utf-8".toMediaType() | ||
private const val JSON_HEADER = "application/json" | ||
|
||
|
@@ -41,6 +44,7 @@ object TbdexHttpClient { | |
* @return A list of [Offering] matching the request. | ||
* @throws TbdexResponseException for request or response errors. | ||
*/ | ||
@Suppress("SwallowedException") | ||
fun getOfferings(pfiDid: String, filter: GetOfferingsFilter? = null): List<Offering> { | ||
val pfiServiceEndpoint = getPfiServiceEndpoint(pfiDid) | ||
val baseUrl = "$pfiServiceEndpoint/offerings/" | ||
|
@@ -64,7 +68,70 @@ object TbdexHttpClient { | |
val jsonNode = jsonMapper.readTree(responseString) | ||
return jsonNode.get("data").elements() | ||
.asSequence() | ||
.map { Offering.parse(it.toString()) } | ||
.map { | ||
try { | ||
Offering.parse(it.toString()) | ||
} catch (e: Exception) { | ||
throw TbdexResponseException( | ||
"response status: ${response.code}", | ||
errors = listOf( | ||
ErrorDetail( | ||
detail = "Failed to parse offering ${e.message}" | ||
) | ||
) | ||
) | ||
} | ||
} | ||
.toList() | ||
} | ||
|
||
else -> throw buildResponseException(response) | ||
} | ||
} | ||
|
||
/** | ||
* Fetches balances from a PFI. | ||
* | ||
* @param pfiDid The decentralized identifier of the PFI. | ||
* @param requesterDid The decentralized identifier of the entity requesting the balances. | ||
* @return A list of [Balance] matching the request. | ||
* @throws TbdexResponseException for request or response errors. | ||
*/ | ||
@Suppress("SwallowedException") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what exception gets swallowed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the exception thrown if Balance.parse(it.toString()) fails in the try/catch, line 123. it gets re-thrown as TbdexResponseException as implemented per this suggestion |
||
fun getBalances(pfiDid: String, requesterDid: BearerDid): List<Balance> { | ||
val pfiServiceEndpoint = getPfiServiceEndpoint(pfiDid) | ||
val baseUrl = "$pfiServiceEndpoint/balances/" | ||
val requestToken = RequestToken.generate(requesterDid, pfiDid) | ||
|
||
val request = Request.Builder() | ||
.url(baseUrl) | ||
.addHeader(CONTENT_TYPE, JSON_HEADER) | ||
.addHeader(AUTHORIZATION, "Bearer $requestToken") | ||
.get() | ||
.build() | ||
|
||
val response: Response = client.newCall(request).execute() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah does this throw an exception if the request fails? e.g. timeout, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. correct. from the docs:
|
||
when { | ||
response.isSuccessful -> { | ||
val responseString = response.body?.string() | ||
// response body is an object with a data field | ||
val jsonNode = jsonMapper.readTree(responseString) | ||
return jsonNode.get("data").elements() | ||
.asSequence() | ||
.map { | ||
try { | ||
Balance.parse(it.toString()) | ||
} catch (e: Exception) { | ||
throw TbdexResponseException( | ||
"response status: ${response.code}", | ||
errors = listOf( | ||
ErrorDetail( | ||
detail = "Failed to parse balance ${e.message}" | ||
) | ||
) | ||
) | ||
} | ||
} | ||
.toList() | ||
} | ||
|
||
|
@@ -115,7 +182,7 @@ object TbdexHttpClient { | |
|
||
val request = Request.Builder() | ||
.url(url) | ||
.addHeader("Content-Type", JSON_HEADER) | ||
.addHeader(CONTENT_TYPE, JSON_HEADER) | ||
.post(requestBody) | ||
.build() | ||
|
||
|
@@ -170,7 +237,7 @@ object TbdexHttpClient { | |
|
||
val request = Request.Builder() | ||
.url(url) | ||
.addHeader("Content-Type", JSON_HEADER) | ||
.addHeader(CONTENT_TYPE, JSON_HEADER) | ||
.put(requestBody) | ||
.build() | ||
|
||
|
@@ -195,8 +262,8 @@ object TbdexHttpClient { | |
|
||
val request = Request.Builder() | ||
.url(baseUrl) | ||
.addHeader("Content-Type", JSON_HEADER) | ||
.addHeader("Authorization", "Bearer $requestToken") | ||
.addHeader(CONTENT_TYPE, JSON_HEADER) | ||
.addHeader(AUTHORIZATION, "Bearer $requestToken") | ||
.get() | ||
.build() | ||
|
||
|
@@ -237,8 +304,8 @@ object TbdexHttpClient { | |
|
||
val request = Request.Builder() | ||
.url(httpUrlBuilder.build()) | ||
.addHeader("Content-Type", JSON_HEADER) | ||
.addHeader("Authorization", "Bearer $requestToken") | ||
.addHeader(CONTENT_TYPE, JSON_HEADER) | ||
.addHeader(AUTHORIZATION, "Bearer $requestToken") | ||
.get() | ||
.build() | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking out loud: in tbdex-js, we have both
TbdexRequestError
andTbdexResponseError
, representing errors that happen before and after the client call respectively. It's a slight misnomer to throw a RequestException for both request and response errors, so I'm making a mental note that in my next tidy-up PR, I may explore introducing aTbdexRequestException
class. In any case, it's relatively low priority and outside the scope of this PR.