Skip to content

Commit 0a8849e

Browse files
committed
Add getSacBalance to SorobanServer
1 parent 42733cc commit 0a8849e

File tree

4 files changed

+133
-31
lines changed

4 files changed

+133
-31
lines changed

src/main/java/org/stellar/sdk/SorobanServer.java

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,7 @@
55
import java.io.Closeable;
66
import java.io.IOException;
77
import java.net.SocketTimeoutException;
8-
import java.util.ArrayList;
9-
import java.util.Collection;
10-
import java.util.Collections;
11-
import java.util.List;
12-
import java.util.Optional;
13-
import java.util.UUID;
8+
import java.util.*;
149
import java.util.concurrent.TimeUnit;
1510
import okhttp3.HttpUrl;
1611
import okhttp3.MediaType;
@@ -36,19 +31,8 @@
3631
import org.stellar.sdk.requests.sorobanrpc.SendTransactionRequest;
3732
import org.stellar.sdk.requests.sorobanrpc.SimulateTransactionRequest;
3833
import org.stellar.sdk.requests.sorobanrpc.SorobanRpcRequest;
39-
import org.stellar.sdk.responses.sorobanrpc.GetEventsResponse;
40-
import org.stellar.sdk.responses.sorobanrpc.GetFeeStatsResponse;
41-
import org.stellar.sdk.responses.sorobanrpc.GetHealthResponse;
42-
import org.stellar.sdk.responses.sorobanrpc.GetLatestLedgerResponse;
43-
import org.stellar.sdk.responses.sorobanrpc.GetLedgerEntriesResponse;
44-
import org.stellar.sdk.responses.sorobanrpc.GetLedgersResponse;
45-
import org.stellar.sdk.responses.sorobanrpc.GetNetworkResponse;
46-
import org.stellar.sdk.responses.sorobanrpc.GetTransactionResponse;
47-
import org.stellar.sdk.responses.sorobanrpc.GetTransactionsResponse;
48-
import org.stellar.sdk.responses.sorobanrpc.GetVersionInfoResponse;
49-
import org.stellar.sdk.responses.sorobanrpc.SendTransactionResponse;
50-
import org.stellar.sdk.responses.sorobanrpc.SimulateTransactionResponse;
51-
import org.stellar.sdk.responses.sorobanrpc.SorobanRpcResponse;
34+
import org.stellar.sdk.responses.sorobanrpc.*;
35+
import org.stellar.sdk.scval.Scv;
5236
import org.stellar.sdk.xdr.ContractDataDurability;
5337
import org.stellar.sdk.xdr.LedgerEntry;
5438
import org.stellar.sdk.xdr.LedgerEntryType;
@@ -560,6 +544,52 @@ public SendTransactionResponse sendTransaction(Transaction transaction) {
560544
"sendTransaction", params, new TypeToken<SorobanRpcResponse<SendTransactionResponse>>() {});
561545
}
562546

547+
public GetSacBalanceResponse getSacBalance(String contractId, Asset asset, Network network)
548+
throws IOException {
549+
550+
if (!StrKey.isValidContract(contractId)) {
551+
throw new IllegalArgumentException("expected contract ID, got " + contractId);
552+
}
553+
554+
LedgerKey ledgerKey =
555+
LedgerKey.builder()
556+
.discriminant(LedgerEntryType.CONTRACT_DATA)
557+
.contractData(
558+
LedgerKey.LedgerKeyContractData.builder()
559+
.contract(Scv.toAddress(asset.getContractId(network)).getAddress())
560+
.key(
561+
Scv.toVec(
562+
Arrays.asList(Scv.toSymbol("Balance"), Scv.toAddress(contractId))))
563+
.durability(ContractDataDurability.PERSISTENT)
564+
.build())
565+
.build();
566+
567+
GetLedgerEntriesResponse response = this.getLedgerEntries(Collections.singleton(ledgerKey));
568+
569+
List<GetLedgerEntriesResponse.LedgerEntryResult> entries = response.getEntries();
570+
if (entries == null || entries.isEmpty()) {
571+
return null;
572+
}
573+
574+
GetLedgerEntriesResponse.LedgerEntryResult entry = entries.get(0);
575+
LedgerEntry.LedgerEntryData ledgerEntryData =
576+
LedgerEntry.LedgerEntryData.fromXdrBase64(entry.getXdr());
577+
LinkedHashMap<SCVal, SCVal> balanceMap =
578+
Scv.fromMap(ledgerEntryData.getContractData().getVal());
579+
580+
return GetSacBalanceResponse.builder()
581+
.latestLedger(response.getLatestLedger())
582+
.balanceEntry(
583+
GetSacBalanceResponse.BalanceEntry.builder()
584+
.liveUntilLedgerSeq(entry.getLiveUntilLedger())
585+
.lastModifiedLedgerSeq(entry.getLastModifiedLedger())
586+
.amount(Scv.fromInt128(balanceMap.get(Scv.toSymbol("amount"))).toString())
587+
.authorized(Scv.fromBoolean(balanceMap.get(Scv.toSymbol("authorized"))))
588+
.clawback(Scv.fromBoolean(balanceMap.get(Scv.toSymbol("clawback"))))
589+
.build())
590+
.build();
591+
}
592+
563593
public static Transaction assembleTransaction(
564594
Transaction transaction, SimulateTransactionResponse simulateTransactionResponse) {
565595
if (!transaction.isSorobanTransaction()) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.stellar.sdk.responses.sorobanrpc;
2+
3+
import lombok.Builder;
4+
import lombok.Value;
5+
6+
@Builder
7+
@Value
8+
public class GetSacBalanceResponse {
9+
long latestLedger;
10+
BalanceEntry balanceEntry;
11+
12+
@Value
13+
@Builder
14+
public static class BalanceEntry {
15+
Long liveUntilLedgerSeq;
16+
Long lastModifiedLedgerSeq;
17+
String amount;
18+
Boolean authorized;
19+
Boolean clawback;
20+
}
21+
}

src/test/java/org/stellar/sdk/SorobanServerTest.java

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,7 @@
3939
import org.stellar.sdk.requests.sorobanrpc.SendTransactionRequest;
4040
import org.stellar.sdk.requests.sorobanrpc.SimulateTransactionRequest;
4141
import org.stellar.sdk.requests.sorobanrpc.SorobanRpcRequest;
42-
import org.stellar.sdk.responses.sorobanrpc.GetEventsResponse;
43-
import org.stellar.sdk.responses.sorobanrpc.GetFeeStatsResponse;
44-
import org.stellar.sdk.responses.sorobanrpc.GetHealthResponse;
45-
import org.stellar.sdk.responses.sorobanrpc.GetLatestLedgerResponse;
46-
import org.stellar.sdk.responses.sorobanrpc.GetLedgerEntriesResponse;
47-
import org.stellar.sdk.responses.sorobanrpc.GetLedgersResponse;
48-
import org.stellar.sdk.responses.sorobanrpc.GetNetworkResponse;
49-
import org.stellar.sdk.responses.sorobanrpc.GetTransactionResponse;
50-
import org.stellar.sdk.responses.sorobanrpc.GetTransactionsResponse;
51-
import org.stellar.sdk.responses.sorobanrpc.GetVersionInfoResponse;
52-
import org.stellar.sdk.responses.sorobanrpc.SendTransactionResponse;
53-
import org.stellar.sdk.responses.sorobanrpc.SimulateTransactionResponse;
42+
import org.stellar.sdk.responses.sorobanrpc.*;
5443
import org.stellar.sdk.xdr.ContractDataDurability;
5544
import org.stellar.sdk.xdr.ContractExecutable;
5645
import org.stellar.sdk.xdr.ContractExecutableType;
@@ -1354,6 +1343,53 @@ public MockResponse dispatch(@NotNull RecordedRequest recordedRequest)
13541343
mockWebServer.close();
13551344
}
13561345

1346+
@Test
1347+
public void testGetSacBalance() throws IOException {
1348+
String filePath = "src/test/resources/soroban_server/get_sac_balance.json";
1349+
String json = new String(Files.readAllBytes(Paths.get(filePath)));
1350+
MockWebServer mockWebServer = new MockWebServer();
1351+
Dispatcher dispatcher =
1352+
new Dispatcher() {
1353+
@NotNull
1354+
@Override
1355+
public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) {
1356+
SorobanRpcRequest<GetLedgerEntriesRequest> sorobanRpcRequest =
1357+
gson.fromJson(
1358+
recordedRequest.getBody().readUtf8(),
1359+
new TypeToken<SorobanRpcRequest<GetLedgerEntriesRequest>>() {}.getType());
1360+
if ("POST".equals(recordedRequest.getMethod())
1361+
&& sorobanRpcRequest.getMethod().equals("getLedgerEntries")
1362+
&& "AAAABgAAAAHXkotywnA8z+r365/0701QSlWouXn8m0UOoshCtNHOYQAAABAAAAABAAAAAgAAAA8AAAAHQmFsYW5jZQAAAAASAAAAATS6wvBZn2PXUHdI2oDWZqeECiy17cpcL6qrr1lqpqu6AAAAAQ=="
1363+
.equals(
1364+
sorobanRpcRequest.getParams().getKeys().stream()
1365+
.findFirst()
1366+
.orElse(null))) {
1367+
return new MockResponse().setResponseCode(200).setBody(json);
1368+
}
1369+
return new MockResponse().setResponseCode(404);
1370+
}
1371+
};
1372+
mockWebServer.setDispatcher(dispatcher);
1373+
mockWebServer.start();
1374+
1375+
HttpUrl baseUrl = mockWebServer.url("");
1376+
SorobanServer server = new SorobanServer(baseUrl.toString());
1377+
GetSacBalanceResponse balance =
1378+
server.getSacBalance(
1379+
"CA2LVQXQLGPWHV2QO5ENVAGWM2TYICRMWXW4UXBPVKV26WLKU2V3UTH5",
1380+
Asset.createNativeAsset(),
1381+
Network.TESTNET);
1382+
assertEquals(1104160, balance.getLatestLedger());
1383+
assertEquals((Long) 3163876L, balance.getBalanceEntry().getLiveUntilLedgerSeq());
1384+
assertEquals((Long) 1090887L, balance.getBalanceEntry().getLastModifiedLedgerSeq());
1385+
assertEquals("28", balance.getBalanceEntry().getAmount());
1386+
assertTrue(balance.getBalanceEntry().getAuthorized());
1387+
assertFalse(balance.getBalanceEntry().getClawback());
1388+
1389+
server.close();
1390+
mockWebServer.close();
1391+
}
1392+
13571393
@Test
13581394
public void testSorobanRpcErrorResponseThrows() throws IOException {
13591395
String filePath = "src/test/resources/soroban_server/soroban_rpc_error.json";
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"jsonrpc": "2.0",
3+
"id": "5715b491-e70c-483b-b000-315735c4129b",
4+
"result": {
5+
"entries": [
6+
{
7+
"key": "AAAABgAAAAHXkotywnA8z+r365/0701QSlWouXn8m0UOoshCtNHOYQAAABAAAAABAAAAAgAAAA8AAAAHQmFsYW5jZQAAAAASAAAAATS6wvBZn2PXUHdI2oDWZqeECiy17cpcL6qrr1lqpqu6AAAAAQ==",
8+
"xdr": "AAAABgAAAAAAAAAB15KLcsJwPM/q9+uf9O9NUEpVqLl5/JtFDqLIQrTRzmEAAAAQAAAAAQAAAAIAAAAPAAAAB0JhbGFuY2UAAAAAEgAAAAE0usLwWZ9j11B3SNqA1manhAoste3KXC+qq69ZaqarugAAAAEAAAARAAAAAQAAAAMAAAAPAAAABmFtb3VudAAAAAAACgAAAAAAAAAAAAAAAAAAABwAAAAPAAAACmF1dGhvcml6ZWQAAAAAAAAAAAABAAAADwAAAAhjbGF3YmFjawAAAAAAAAAA",
9+
"lastModifiedLedgerSeq": 1090887,
10+
"liveUntilLedgerSeq": 3163876
11+
}
12+
],
13+
"latestLedger": 1104160
14+
}
15+
}

0 commit comments

Comments
 (0)