Skip to content

Bump java-stellar-sdk to v1.0.0 #1575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies {

implementation(libs.apache.commons.lang3)
implementation(libs.bcastle)
implementation(libs.bcutil)
implementation(libs.commons.beanutils)
implementation(libs.commons.codec)
implementation(libs.commons.io)
Expand Down
14 changes: 5 additions & 9 deletions core/src/main/java/org/stellar/anchor/auth/Sep10Jwt.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.stellar.sdk.AccountConverter;
import org.stellar.sdk.KeyPair;
import org.stellar.sdk.xdr.MuxedAccount;
import org.stellar.sdk.MuxedAccount;

@Getter
@Setter
Expand Down Expand Up @@ -111,13 +109,11 @@ void updateAccountAndMemo() {
this.accountMemo = null;

try {
MuxedAccount maybeMuxedAccount = AccountConverter.enableMuxed().encode(sub);
MuxedAccount.MuxedAccountMed25519 muxedAccount = maybeMuxedAccount.getMed25519();
if (muxedAccount != null) {
MuxedAccount maybeMuxedAccount = new MuxedAccount(sub);
if (maybeMuxedAccount.getMuxedId() != null) {
this.muxedAccount = sub;
byte[] pubKeyBytes = muxedAccount.getEd25519().getUint256();
this.account = KeyPair.fromPublicKey(pubKeyBytes).getAccountId();
this.muxedAccountId = muxedAccount.getId().getUint64().getNumber().longValue();
this.account = maybeMuxedAccount.getAccountId();
this.muxedAccountId = maybeMuxedAccount.getMuxedId().longValue();
}
} catch (Exception ignored) {
}
Expand Down
27 changes: 19 additions & 8 deletions core/src/main/java/org/stellar/anchor/horizon/Horizon.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

import static org.stellar.anchor.api.asset.AssetInfo.NATIVE_ASSET_CODE;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import lombok.Getter;
import org.stellar.anchor.config.AppConfig;
import org.stellar.anchor.util.AssetHelper;
import org.stellar.sdk.AssetTypeCreditAlphaNum;
import org.stellar.sdk.Server;
import org.stellar.sdk.TrustLineAsset;
import org.stellar.sdk.exception.NetworkException;
import org.stellar.sdk.requests.PaymentsRequestBuilder;
import org.stellar.sdk.responses.AccountResponse;
import org.stellar.sdk.responses.operations.OperationResponse;
import org.stellar.sdk.xdr.AssetType;

/** The horizon-server. */
public class Horizon {
Expand All @@ -30,29 +32,38 @@ public Server getServer() {
return this.horizonServer;
}

public boolean isTrustlineConfigured(String account, String asset) throws IOException {
public boolean isTrustlineConfigured(String account, String asset) throws NetworkException {
String assetCode = AssetHelper.getAssetCode(asset);
if (NATIVE_ASSET_CODE.equals(assetCode)) {
return true;
}
String assetIssuer = AssetHelper.getAssetIssuer(asset);

AccountResponse accountResponse = getServer().accounts().account(account);
return Arrays.stream(accountResponse.getBalances())
return accountResponse.getBalances().stream()
.anyMatch(
balance -> {
if (balance.getAssetType().equals("credit_alphanum4")
|| balance.getAssetType().equals("credit_alphanum12")) {
TrustLineAsset trustLineAsset = balance.getTrustLineAsset();
if (trustLineAsset.getAssetType() == AssetType.ASSET_TYPE_CREDIT_ALPHANUM4
|| trustLineAsset.getAssetType() == AssetType.ASSET_TYPE_CREDIT_ALPHANUM12) {
AssetTypeCreditAlphaNum creditAsset =
(AssetTypeCreditAlphaNum) balance.getAsset().get();
(AssetTypeCreditAlphaNum) trustLineAsset.getAsset();
assert creditAsset != null;
return creditAsset.getCode().equals(assetCode)
&& creditAsset.getIssuer().equals(assetIssuer);
}
return false;
});
}

public List<OperationResponse> getStellarTxnOperations(String stellarTxnId) throws IOException {
/**
* Get payment operations for a transaction.
*
* @param stellarTxnId the transaction id
* @return the operations
* @throws NetworkException request failed, see {@link PaymentsRequestBuilder#execute()}
*/
public List<OperationResponse> getStellarTxnOperations(String stellarTxnId) {
return getServer()
.payments()
.includeTransactions(true)
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/stellar/anchor/sep10/Sep10Helper.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import org.stellar.anchor.api.exception.InvalidConfigException;
import org.stellar.anchor.api.exception.SepException;
import org.stellar.anchor.util.Sep1Helper;
import org.stellar.sdk.FormatException;
import org.stellar.sdk.KeyPair;
import org.stellar.sdk.exception.StrKeyException;

public class Sep10Helper {

Expand Down Expand Up @@ -39,7 +39,7 @@ public static String fetchSigningKeyFromClientDomain(String clientDomain, boolea
debugF("Validating client_domain signing key: {}", clientSigningKey);
KeyPair.fromAccountId(clientSigningKey);
return clientSigningKey;
} catch (IllegalArgumentException | FormatException e) {
} catch (IllegalArgumentException | StrKeyException e) {
infoF("SIGNING_KEY {} is not a valid Stellar account Id.", clientSigningKey);
throw new SepException(
String.format("SIGNING_KEY %s is not a valid Stellar account Id.", clientSigningKey));
Expand Down
46 changes: 23 additions & 23 deletions core/src/main/java/org/stellar/anchor/sep10/Sep10Service.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import io.jsonwebtoken.Jws;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Metrics;
import java.io.IOException;
import java.time.Instant;
import java.util.Arrays;
import java.util.HashSet;
Expand All @@ -36,7 +35,10 @@
import org.stellar.anchor.util.Log;
import org.stellar.sdk.*;
import org.stellar.sdk.Sep10Challenge.ChallengeTransaction;
import org.stellar.sdk.requests.ErrorResponse;
import org.stellar.sdk.exception.InvalidSep10ChallengeException;
import org.stellar.sdk.exception.NetworkException;
import org.stellar.sdk.operations.ManageDataOperation;
import org.stellar.sdk.operations.Operation;
import org.stellar.sdk.responses.AccountResponse;

/** The Sep-10 protocol service. */
Expand Down Expand Up @@ -114,7 +116,7 @@ public ChallengeResponse createChallenge(
}

public ValidationResponse validateChallenge(ValidationRequest request)
throws IOException, InvalidSep10ChallengeException, SepValidationException {
throws SepValidationException {
info("Validating SEP-10 challenge.");

ChallengeTransaction challenge = parseChallenge(request);
Expand Down Expand Up @@ -176,8 +178,7 @@ public ChallengeResponse createChallengeResponse(
}
}

Transaction newChallenge(ChallengeRequest request, String clientSigningKey, Memo memo)
throws InvalidSep10ChallengeException {
Transaction newChallenge(ChallengeRequest request, String clientSigningKey, Memo memo) {

KeyPair signer = KeyPair.fromSecretSeed(secretConfig.getSep10SigningSeed());
long now = Instant.now().getEpochSecond();
Expand Down Expand Up @@ -388,7 +389,7 @@ void validateAccountFormat(ChallengeRequest request) throws SepException {

void validateChallengeRequest(
ValidationRequest request, AccountResponse account, String clientDomain)
throws InvalidSep10ChallengeException, IOException, SepValidationException {
throws SepValidationException {
// fetch the signers from the transaction
Set<Sep10Challenge.Signer> signers = fetchSigners(account);
// the signatures must be greater than the medium threshold of the account.
Expand All @@ -415,15 +416,15 @@ void validateChallengeRequest(

Set<Sep10Challenge.Signer> fetchSigners(AccountResponse account) {
// Find the signers of the client account.
return Arrays.stream(account.getSigners())
return account.getSigners().stream()
.filter(as -> as.getType().equals("ed25519_public_key"))
.map(as -> new Sep10Challenge.Signer(as.getKey(), as.getWeight()))
.collect(Collectors.toSet());
}

AccountResponse fetchAccount(
ValidationRequest request, ChallengeTransaction challenge, String clientDomain)
throws InvalidSep10ChallengeException, IOException, SepValidationException {
throws SepValidationException {
// Check the client's account
AccountResponse account;
try {
Expand All @@ -432,7 +433,7 @@ AccountResponse fetchAccount(
traceF("challenge account: {}", account);
sep10ChallengeValidatedCounter.increment();
return account;
} catch (ErrorResponse | IOException ex) {
} catch (NetworkException ex) {
infoF("Account {} does not exist in the Stellar Network");
// account not found
// The client account does not exist, using the client's master key to verify.
Expand Down Expand Up @@ -494,8 +495,7 @@ String fetchClientDomain(ChallengeTransaction challenge) {
return clientDomain;
}

ChallengeTransaction parseChallenge(ValidationRequest request)
throws IOException, InvalidSep10ChallengeException, SepValidationException {
ChallengeTransaction parseChallenge(ValidationRequest request) throws SepValidationException {

if (request == null || request.getTransaction() == null) {
throw new SepValidationException("{transaction} is required.");
Expand Down Expand Up @@ -554,13 +554,17 @@ private String authUrl() {
* @param network The network to connect to for verifying and retrieving.
* @return The extracted home domain from the Manage Data operation within the SEP-10 challenge
* transaction.
* @throws IOException If read XDR string fails, the exception will be thrown.
* @throws SepValidationException If the transaction is not a valid SEP-10 challenge transaction.
*/
String extractHomeDomainFromChallengeXdr(String challengeXdr, Network network)
throws IOException, SepValidationException {
AbstractTransaction parsed =
Transaction.fromEnvelopeXdr(AccountConverter.enableMuxed(), challengeXdr, network);
throws SepValidationException {
AbstractTransaction parsed;
try {
parsed = Transaction.fromEnvelopeXdr(challengeXdr, network);
} catch (IllegalArgumentException e) {
throw new SepValidationException("Invalid challenge transaction.");
}

if (!(parsed instanceof Transaction)) {
throw new SepValidationException("Transaction cannot be a fee bump transaction");
}
Expand Down Expand Up @@ -603,8 +607,7 @@ public synchronized Transaction newChallenge(
TimeBounds timebounds,
String clientDomain,
String clientSigningKey,
Memo memo)
throws InvalidSep10ChallengeException {
Memo memo) {
return Sep10Challenge.newChallenge(
signer,
network,
Expand All @@ -622,8 +625,7 @@ public synchronized ChallengeTransaction readChallengeTransaction(
String serverAccountId,
Network network,
String domainName,
String webAuthDomain)
throws InvalidSep10ChallengeException, IOException {
String webAuthDomain) {
return Sep10Challenge.readChallengeTransaction(
challengeXdr, serverAccountId, network, domainName, webAuthDomain);
}
Expand All @@ -634,8 +636,7 @@ public synchronized void verifyChallengeTransactionSigners(
Network network,
String domainName,
String webAuthDomain,
Set<String> signers)
throws InvalidSep10ChallengeException, IOException {
Set<String> signers) {
Sep10Challenge.verifyChallengeTransactionSigners(
challengeXdr, serverAccountId, network, domainName, webAuthDomain, signers);
}
Expand All @@ -647,8 +648,7 @@ public synchronized void verifyChallengeTransactionThreshold(
String domainName,
String webAuthDomain,
int threshold,
Set<Sep10Challenge.Signer> signers)
throws InvalidSep10ChallengeException, IOException {
Set<Sep10Challenge.Signer> signers) {
Sep10Challenge.verifyChallengeTransactionThreshold(
challengeXdr, serverAccountId, network, domainName, webAuthDomain, threshold, signers);
}
Expand Down
12 changes: 3 additions & 9 deletions core/src/main/java/org/stellar/anchor/util/SepHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import org.stellar.anchor.api.exception.BadRequestException;
import org.stellar.anchor.api.exception.InvalidStellarAccountException;
import org.stellar.anchor.api.sep.SepTransactionStatus;
import org.stellar.sdk.AccountConverter;
import org.stellar.sdk.KeyPair;
import org.stellar.sdk.xdr.*;
import org.stellar.sdk.MuxedAccount;
import org.stellar.sdk.xdr.MemoType;

public class SepHelper {
/**
Expand Down Expand Up @@ -59,14 +59,8 @@ public static String getAccountMemo(String strAccount) throws InvalidStellarAcco
String[] tokens = strAccount.split(":");
switch (tokens.length) {
case 1:
AccountConverter accountConverter;
if (tokens[0].startsWith("G")) {
accountConverter = AccountConverter.disableMuxed();
} else {
accountConverter = AccountConverter.enableMuxed();
}
// Check if the account is a valid G... or M...
accountConverter.encode(tokens[0]);
new MuxedAccount(tokens[0]);
return null;
case 2:
KeyPair.fromAccountId(tokens[0]);
Expand Down
54 changes: 28 additions & 26 deletions core/src/test/kotlin/org/stellar/anchor/horizon/HorizonTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ package org.stellar.anchor.horizon

import io.mockk.every
import io.mockk.mockk
import java.util.*
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.stellar.anchor.config.AppConfig
import org.stellar.sdk.Asset
import org.stellar.sdk.AssetTypeCreditAlphaNum
import org.stellar.sdk.Server
import org.stellar.sdk.TrustLineAsset
import org.stellar.sdk.requests.AccountsRequestBuilder
import org.stellar.sdk.responses.AccountResponse
import org.stellar.sdk.responses.AccountResponse.Balance
Expand Down Expand Up @@ -84,20 +85,21 @@ internal class HorizonTest {
every { appConfig.stellarNetworkPassphrase } returns TEST_HORIZON_PASSPHRASE
every { server.accounts() } returns accountsRequestBuilder
every { accountsRequestBuilder.account(account) } returns accountResponse
every { balance1.getAssetType() } returns "credit_alphanum4"
every { balance1.getAsset() } returns Optional.of(asset1)
every { balance2.getAssetType() } returns "credit_alphanum12"
every { balance2.getAsset() } returns Optional.of(asset2)
every { asset1.getCode() } returns "USDC"
every { asset1.getIssuer() } returns "issuerAccount1"
every { asset2.getCode() } returns "USDC"
every { asset2.getIssuer() } returns "issuerAccount2"
every { accountResponse.getBalances() } returns arrayOf(balance1, balance2)

every { asset1.code } returns "USDC"
every { asset1.issuer } returns "issuerAccount1"
every { asset2.code } returns "USDC"
every { asset2.issuer } returns "issuerAccount2"

every { balance1.trustLineAsset } returns
TrustLineAsset(Asset.createNonNativeAsset(asset1.code, asset1.issuer))
every { balance2.trustLineAsset } returns
TrustLineAsset(Asset.createNonNativeAsset(asset2.code, asset2.issuer))
every { accountResponse.balances } returns listOf(balance1, balance2)

val horizon = mockk<Horizon>()
every { horizon.server } returns server
every { horizon.isTrustlineConfigured(account, asset) } answers { callOriginal() }

assertTrue(horizon.isTrustlineConfigured(account, asset))
}

Expand All @@ -112,32 +114,32 @@ internal class HorizonTest {
val balance1: Balance = mockk()
val balance2: Balance = mockk()
val balance3: Balance = mockk()
val asset1: AssetTypeCreditAlphaNum = mockk()
// val asset1: AssetTypeNative = mockk()
val asset2: AssetTypeCreditAlphaNum = mockk()
val asset3: AssetTypeCreditAlphaNum = mockk()
every { server.accounts() } returns accountsRequestBuilder
every { accountsRequestBuilder.account(account) } returns accountResponse
every { balance1.getAssetType() } returns "credit_alphanum8"
every { balance1.getAsset() } returns Optional.of(asset1)
every { balance2.getAssetType() } returns "credit_alphanum4"
every { balance2.getAsset() } returns Optional.of(asset2)
every { balance3.getAssetType() } returns "credit_alphanum4"
every { balance3.getAsset() } returns Optional.of(asset3)
every { asset1.getCode() } returns "USDC"
every { asset1.getIssuer() } returns "issuerAccount1"
every { asset2.getCode() } returns "SRT"
every { asset2.getIssuer() } returns "issuerAccount1"
every { asset3.getCode() } returns "USDC"
every { asset3.getIssuer() } returns "issuerAccount2"
every { accountResponse.getBalances() } returns arrayOf(balance1, balance2, balance3)

// asset 1 is native asset
every { asset2.code } returns "SRT"
every { asset2.issuer } returns "issuerAccount1"
every { asset3.code } returns "USDC"
every { asset3.issuer } returns "issuerAccount2"

every { balance1.trustLineAsset } returns TrustLineAsset(Asset.createNativeAsset())
every { balance2.trustLineAsset } returns
TrustLineAsset(Asset.createNonNativeAsset(asset2.code, asset2.issuer))
every { balance3.trustLineAsset } returns
TrustLineAsset(Asset.createNonNativeAsset(asset3.code, asset3.issuer))

every { accountResponse.balances } returns listOf(balance1, balance2, balance3)

every { appConfig.horizonUrl } returns TEST_HORIZON_URI
every { appConfig.stellarNetworkPassphrase } returns TEST_HORIZON_PASSPHRASE

val horizon = mockk<Horizon>()
every { horizon.server } returns server
every { horizon.isTrustlineConfigured(account, asset) } answers { callOriginal() }

assertFalse(horizon.isTrustlineConfigured(account, asset))
}
}
Loading
Loading