Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
Adspromoter
ExtLibJ
Commits
79374c4d
Commit
79374c4d
authored
Apr 25, 2020
by
zeroleak
Browse files
httpObservable
parent
3b983295
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
155 additions
and
58 deletions
+155
-58
java/com/samourai/wallet/api/backend/BackendApi.java
java/com/samourai/wallet/api/backend/BackendApi.java
+90
-52
java/com/samourai/wallet/api/backend/IBackendClient.java
java/com/samourai/wallet/api/backend/IBackendClient.java
+4
-2
java/com/samourai/wallet/util/oauth/OAuthApi.java
java/com/samourai/wallet/util/oauth/OAuthApi.java
+3
-2
java/com/samourai/wallet/util/oauth/OAuthManager.java
java/com/samourai/wallet/util/oauth/OAuthManager.java
+53
-2
pom.xml
pom.xml
+5
-0
No files found.
java/com/samourai/wallet/api/backend/BackendApi.java
View file @
79374c4d
...
...
@@ -6,6 +6,10 @@ import com.samourai.wallet.api.backend.beans.RefreshTokenResponse;
import
com.samourai.wallet.api.backend.beans.UnspentResponse
;
import
com.samourai.wallet.util.oauth.OAuthApi
;
import
com.samourai.wallet.util.oauth.OAuthManager
;
import
io.reactivex.Completable
;
import
io.reactivex.Observable
;
import
io.reactivex.functions.Action
;
import
io.reactivex.functions.Function
;
import
java8.util.Optional
;
import
org.apache.commons.lang3.StringUtils
;
import
org.slf4j.Logger
;
...
...
@@ -38,52 +42,70 @@ public class BackendApi implements OAuthApi {
}
}
public
List
<
UnspentResponse
.
UnspentOutput
>
fetchUtxos
(
String
zpub
)
throws
Exception
{
public
Observable
<
List
<
UnspentResponse
.
UnspentOutput
>
>
fetchUtxos
(
String
zpub
)
throws
Exception
{
String
url
=
computeAuthUrl
(
urlBackend
+
URL_UNSPENT
+
zpub
);
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"fetchUtxos: "
+
url
);
}
Map
<
String
,
String
>
headers
=
computeHeaders
();
UnspentResponse
unspentResponse
=
httpClient
.
getJson
(
url
,
UnspentResponse
.
class
,
headers
);
List
<
UnspentResponse
.
UnspentOutput
>
unspentOutputs
=
new
ArrayList
<
UnspentResponse
.
UnspentOutput
>();
if
(
unspentResponse
.
unspent_outputs
!=
null
)
{
unspentOutputs
=
Arrays
.
asList
(
unspentResponse
.
unspent_outputs
);
}
return
unspentOutputs
;
Observable
<
Optional
<
UnspentResponse
>>
observable
=
httpClient
.
getJson
(
url
,
UnspentResponse
.
class
,
headers
);
return
observable
.
map
(
new
Function
<
Optional
<
UnspentResponse
>,
List
<
UnspentResponse
.
UnspentOutput
>>()
{
@Override
public
List
<
UnspentResponse
.
UnspentOutput
>
apply
(
Optional
<
UnspentResponse
>
unspentResponseOptional
)
throws
Exception
{
List
<
UnspentResponse
.
UnspentOutput
>
unspentOutputs
=
new
ArrayList
<
UnspentResponse
.
UnspentOutput
>();
UnspentResponse
unspentResponse
=
unspentResponseOptional
.
get
();
if
(
unspentResponse
.
unspent_outputs
!=
null
)
{
unspentOutputs
=
Arrays
.
asList
(
unspentResponse
.
unspent_outputs
);
}
return
unspentOutputs
;
}
});
}
public
List
<
MultiAddrResponse
.
Address
>
fetchAddresses
(
String
zpub
)
throws
Exception
{
public
Observable
<
List
<
MultiAddrResponse
.
Address
>
>
fetchAddresses
(
String
zpub
)
throws
Exception
{
String
url
=
computeAuthUrl
(
urlBackend
+
URL_MULTIADDR
+
zpub
);
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"fetchAddress: "
+
url
);
}
Map
<
String
,
String
>
headers
=
computeHeaders
();
MultiAddrResponse
multiAddrResponse
=
httpClient
.
getJson
(
url
,
MultiAddrResponse
.
class
,
headers
);
List
<
MultiAddrResponse
.
Address
>
addresses
=
new
ArrayList
<
MultiAddrResponse
.
Address
>();
if
(
multiAddrResponse
.
addresses
!=
null
)
{
addresses
=
Arrays
.
asList
(
multiAddrResponse
.
addresses
);
}
return
addresses
;
Observable
<
Optional
<
MultiAddrResponse
>>
observable
=
httpClient
.
getJson
(
url
,
MultiAddrResponse
.
class
,
headers
);
return
observable
.
map
(
new
Function
<
Optional
<
MultiAddrResponse
>,
List
<
MultiAddrResponse
.
Address
>>()
{
@Override
public
List
<
MultiAddrResponse
.
Address
>
apply
(
Optional
<
MultiAddrResponse
>
multiAddrResponseOptional
)
throws
Exception
{
List
<
MultiAddrResponse
.
Address
>
addresses
=
new
ArrayList
<
MultiAddrResponse
.
Address
>();
MultiAddrResponse
multiAddrResponse
=
multiAddrResponseOptional
.
get
();
if
(
multiAddrResponse
.
addresses
!=
null
)
{
addresses
=
Arrays
.
asList
(
multiAddrResponse
.
addresses
);
}
return
addresses
;
}
});
}
public
MultiAddrResponse
.
Address
fetchAddress
(
String
zpub
)
throws
Exception
{
List
<
MultiAddrResponse
.
Address
>
addresses
=
fetchAddresses
(
zpub
);
if
(
addresses
.
size
()
!=
1
)
{
throw
new
Exception
(
"Address count="
+
addresses
.
size
());
}
MultiAddrResponse
.
Address
address
=
addresses
.
get
(
0
);
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"fetchAddress "
+
zpub
+
": account_index="
+
address
.
account_index
+
", change_index="
+
address
.
change_index
);
}
return
address
;
public
Observable
<
MultiAddrResponse
.
Address
>
fetchAddress
(
final
String
zpub
)
throws
Exception
{
Observable
<
List
<
MultiAddrResponse
.
Address
>>
observable
=
fetchAddresses
(
zpub
);
return
observable
.
map
(
new
Function
<
List
<
MultiAddrResponse
.
Address
>,
MultiAddrResponse
.
Address
>()
{
@Override
public
MultiAddrResponse
.
Address
apply
(
List
<
MultiAddrResponse
.
Address
>
addresses
)
throws
Exception
{
if
(
addresses
.
size
()
!=
1
)
{
throw
new
Exception
(
"Address count="
+
addresses
.
size
());
}
MultiAddrResponse
.
Address
address
=
addresses
.
get
(
0
);
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"fetchAddress "
+
zpub
+
": account_index="
+
address
.
account_index
+
", change_index="
+
address
.
change_index
);
}
return
address
;
}
});
}
public
void
initBip84
(
String
zpub
)
throws
Exception
{
...
...
@@ -99,14 +121,20 @@ public class BackendApi implements OAuthApi {
httpClient
.
postUrlEncoded
(
url
,
Void
.
class
,
headers
,
postBody
);
}
public
MinerFee
fetchMinerFee
()
throws
Exception
{
public
Observable
<
MinerFee
>
fetchMinerFee
()
throws
Exception
{
String
url
=
computeAuthUrl
(
urlBackend
+
URL_MINER_FEES
);
Map
<
String
,
String
>
headers
=
computeHeaders
();
Map
<
String
,
Integer
>
feeResponse
=
httpClient
.
getJson
(
url
,
Map
.
class
,
headers
);
if
(
feeResponse
==
null
)
{
throw
new
Exception
(
"Invalid miner fee response from server"
);
}
return
new
MinerFee
(
feeResponse
);
Observable
<
Optional
<
Map
>>
observable
=
httpClient
.
getJson
(
url
,
Map
.
class
,
headers
);
return
observable
.
map
(
new
Function
<
Optional
<
Map
>,
MinerFee
>()
{
@Override
public
MinerFee
apply
(
Optional
<
Map
>
feeResponseOptional
)
throws
Exception
{
Map
<
String
,
Integer
>
feeResponse
=
feeResponseOptional
.
get
();
if
(
feeResponse
==
null
)
{
throw
new
Exception
(
"Invalid miner fee response from server"
);
}
return
new
MinerFee
(
feeResponse
);
}
});
}
public
void
pushTx
(
String
txHex
)
throws
Exception
{
...
...
@@ -172,36 +200,46 @@ public class BackendApi implements OAuthApi {
// OAuthAPI
@Override
public
RefreshTokenResponse
.
Authorization
oAuthAuthenticate
(
String
apiKey
)
throws
Exception
{
public
Observable
<
RefreshTokenResponse
.
Authorization
>
oAuthAuthenticate
(
String
apiKey
)
throws
Exception
{
String
url
=
getUrlBackend
()
+
URL_GET_AUTH_LOGIN
;
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"tokenAuthenticate"
);
}
Map
<
String
,
String
>
postBody
=
new
HashMap
<
String
,
String
>();
postBody
.
put
(
"apikey"
,
apiKey
);
RefreshTokenResponse
respons
e
=
Observable
<
Optional
<
RefreshTokenResponse
>>
observabl
e
=
getHttpClient
().
postUrlEncoded
(
url
,
RefreshTokenResponse
.
class
,
null
,
postBody
);
if
(
response
.
authorizations
==
null
||
StringUtils
.
isEmpty
(
response
.
authorizations
.
access_token
))
{
throw
new
Exception
(
"Authorization refused. Invalid apiKey?"
);
}
return
response
.
authorizations
;
return
observable
.
map
(
new
Function
<
Optional
<
RefreshTokenResponse
>,
RefreshTokenResponse
.
Authorization
>()
{
@Override
public
RefreshTokenResponse
.
Authorization
apply
(
Optional
<
RefreshTokenResponse
>
refreshTokenResponseOptional
)
throws
Exception
{
RefreshTokenResponse
response
=
refreshTokenResponseOptional
.
get
();
if
(
response
.
authorizations
==
null
||
StringUtils
.
isEmpty
(
response
.
authorizations
.
access_token
))
{
throw
new
Exception
(
"Authorization refused. Invalid apiKey?"
);
}
return
response
.
authorizations
;
}
});
}
@Override
public
String
oAuthRefresh
(
String
refreshTokenStr
)
throws
Exception
{
public
Observable
<
String
>
oAuthRefresh
(
String
refreshTokenStr
)
throws
Exception
{
String
url
=
getUrlBackend
()
+
URL_GET_AUTH_REFRESH
;
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"tokenRefresh"
);
}
Map
<
String
,
String
>
postBody
=
new
HashMap
<
String
,
String
>();
postBody
.
put
(
"rt"
,
refreshTokenStr
);
RefreshTokenResponse
respons
e
=
Observable
<
Optional
<
RefreshTokenResponse
>>
observabl
e
=
getHttpClient
().
postUrlEncoded
(
url
,
RefreshTokenResponse
.
class
,
null
,
postBody
);
if
(
response
.
authorizations
==
null
||
StringUtils
.
isEmpty
(
response
.
authorizations
.
access_token
))
{
throw
new
Exception
(
"Authorization refused. Invalid apiKey?"
);
}
return
response
.
authorizations
.
access_token
;
return
observable
.
map
(
new
Function
<
Optional
<
RefreshTokenResponse
>,
String
>()
{
@Override
public
String
apply
(
Optional
<
RefreshTokenResponse
>
refreshTokenResponseOptional
)
throws
Exception
{
RefreshTokenResponse
response
=
refreshTokenResponseOptional
.
get
();
if
(
response
.
authorizations
==
null
||
StringUtils
.
isEmpty
(
response
.
authorizations
.
access_token
))
{
throw
new
Exception
(
"Authorization refused. Invalid apiKey?"
);
}
return
response
.
authorizations
.
access_token
;
}
});
}
}
java/com/samourai/wallet/api/backend/IBackendClient.java
View file @
79374c4d
package
com.samourai.wallet.api.backend
;
import
com.samourai.wallet.api.backend.beans.HttpException
;
import
io.reactivex.Observable
;
import
java8.util.Optional
;
import
java.util.Map
;
public
interface
IBackendClient
{
<
T
>
T
getJson
(
String
url
,
Class
<
T
>
responseType
,
Map
<
String
,
String
>
headers
)
throws
HttpException
;
<
T
>
Observable
<
Optional
<
T
>>
getJson
(
String
url
,
Class
<
T
>
responseType
,
Map
<
String
,
String
>
headers
)
throws
HttpException
;
<
T
>
T
postUrlEncoded
(
String
url
,
Class
<
T
>
responseType
,
Map
<
String
,
String
>
headers
,
Map
<
String
,
String
>
body
)
throws
HttpException
;
<
T
>
Observable
<
Optional
<
T
>>
postUrlEncoded
(
String
url
,
Class
<
T
>
responseType
,
Map
<
String
,
String
>
headers
,
Map
<
String
,
String
>
body
)
throws
HttpException
;
}
java/com/samourai/wallet/util/oauth/OAuthApi.java
View file @
79374c4d
package
com.samourai.wallet.util.oauth
;
import
com.samourai.wallet.api.backend.beans.RefreshTokenResponse
;
import
io.reactivex.Observable
;
public
interface
OAuthApi
{
String
oAuthRefresh
(
String
refreshTokenStr
)
throws
Exception
;
RefreshTokenResponse
.
Authorization
oAuthAuthenticate
(
String
apiKey
)
throws
Exception
;
Observable
<
String
>
oAuthRefresh
(
String
refreshTokenStr
)
throws
Exception
;
Observable
<
RefreshTokenResponse
.
Authorization
>
oAuthAuthenticate
(
String
apiKey
)
throws
Exception
;
}
java/com/samourai/wallet/util/oauth/OAuthManager.java
View file @
79374c4d
package
com.samourai.wallet.util.oauth
;
public
interface
OAuthManager
{
import
com.auth0.jwt.interfaces.DecodedJWT
;
import
com.samourai.wallet.api.backend.beans.RefreshTokenResponse
;
import
io.reactivex.Observable
;
import
io.reactivex.functions.Function
;
String
getOAuthAccessToken
(
OAuthApi
oAuthApi
)
throws
Exception
;
public
class
OAuthManager
{
private
OAuthImpl
oAuthImpl
;
private
String
apiKey
;
private
DecodedJWT
accessToken
;
private
DecodedJWT
refreshToken
;
public
OAuthManager
(
String
apiKey
)
{
this
.
oAuthImpl
=
new
OAuthImpl
();
this
.
apiKey
=
apiKey
;
}
public
Observable
<
String
>
computeAccessToken
(
OAuthApi
oAuthApi
)
throws
Exception
{
if
(
accessToken
!=
null
)
{
boolean
valid
=
oAuthImpl
.
validate
(
accessToken
);
if
(
valid
)
{
// accessToken is valid
return
Observable
.
fromArray
(
oAuthImpl
.
tokenToString
(
accessToken
));
}
}
return
newAccessToken
(
oAuthApi
);
}
public
Observable
<
String
>
newAccessToken
(
OAuthApi
oAuthApi
)
throws
Exception
{
if
(
refreshToken
!=
null
)
{
boolean
valid
=
oAuthImpl
.
validate
(
refreshToken
);
if
(
valid
)
{
// refreshToken is valid => refresh
Observable
<
String
>
observable
=
oAuthApi
.
oAuthRefresh
(
oAuthImpl
.
tokenToString
(
refreshToken
));
return
observable
.
map
(
new
Function
<
String
,
String
>()
{
@Override
public
String
apply
(
String
accessTokenStr
)
{
accessToken
=
oAuthImpl
.
decode
(
accessTokenStr
);
return
oAuthImpl
.
tokenToString
(
accessToken
);
}
});
}
}
// no refreshToken => authenticate
Observable
<
RefreshTokenResponse
.
Authorization
>
observable
=
oAuthApi
.
oAuthAuthenticate
(
apiKey
);
return
observable
.
map
(
new
Function
<
RefreshTokenResponse
.
Authorization
,
String
>()
{
@Override
public
String
apply
(
RefreshTokenResponse
.
Authorization
auth
)
throws
Exception
{
accessToken
=
oAuthImpl
.
decode
(
auth
.
access_token
);
refreshToken
=
oAuthImpl
.
decode
(
auth
.
refresh_token
);
return
oAuthImpl
.
tokenToString
(
accessToken
);
}
});
}
}
pom.xml
View file @
79374c4d
...
...
@@ -51,6 +51,11 @@
<artifactId>
streamsupport
</artifactId>
<version>
1.7.0
</version>
</dependency>
<dependency>
<groupId>
io.reactivex.rxjava2
</groupId>
<artifactId>
rxjava
</artifactId>
<version>
2.2.15
</version>
</dependency>
<dependency>
<groupId>
org.junit.platform
</groupId>
<artifactId>
junit-platform-launcher
</artifactId>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment