Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
46 changes: 46 additions & 0 deletions antd-java/src/main/java/com/autonomi/antd/GrpcAntdClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@
import antd.v1.Chunks.PutChunkRequest;
import antd.v1.Chunks.PutChunkResponse;

import antd.v1.WalletServiceGrpc;
import antd.v1.Wallet.GetWalletAddressRequest;
import antd.v1.Wallet.GetWalletAddressResponse;
import antd.v1.Wallet.GetWalletBalanceRequest;
import antd.v1.Wallet.GetWalletBalanceResponse;
import antd.v1.Wallet.WalletApproveRequest;
import antd.v1.Wallet.WalletApproveResponse;

import antd.v1.FileServiceGrpc;
import antd.v1.Files.PutFileRequest;
import antd.v1.Files.PutFileResponse;
Expand Down Expand Up @@ -74,6 +82,7 @@ public class GrpcAntdClient implements AutoCloseable {
private final DataServiceGrpc.DataServiceBlockingStub dataStub;
private final ChunkServiceGrpc.ChunkServiceBlockingStub chunkStub;
private final FileServiceGrpc.FileServiceBlockingStub fileStub;
private final WalletServiceGrpc.WalletServiceBlockingStub walletStub;
private final UploadServiceGrpc.UploadServiceBlockingStub uploadStub;

public static GrpcAntdClient autoDiscover() {
Expand All @@ -98,6 +107,7 @@ public GrpcAntdClient(ManagedChannel channel) {
this.dataStub = DataServiceGrpc.newBlockingStub(channel);
this.chunkStub = ChunkServiceGrpc.newBlockingStub(channel);
this.fileStub = FileServiceGrpc.newBlockingStub(channel);
this.walletStub = WalletServiceGrpc.newBlockingStub(channel);
this.uploadStub = UploadServiceGrpc.newBlockingStub(channel);
}

Expand Down Expand Up @@ -348,6 +358,42 @@ public UploadCostEstimate fileCost(String path, boolean isPublic) {
return fileCost(path, isPublic, PaymentMode.AUTO);
}

// Wallet — V2-286 parity with REST AntdClient.walletAddress/Balance/Approve.
// A missing daemon wallet emits gRPC FailedPrecondition which mapException
// surfaces as PaymentException (the established FailedPrecondition→Payment
// convention across all SDKs; semantic is a bit off vs REST's 503 but
// matches every other SDK).

public WalletAddress walletAddress() {
try {
GetWalletAddressResponse resp = walletStub.getAddress(
GetWalletAddressRequest.getDefaultInstance());
return new WalletAddress(resp.getAddress());
} catch (StatusRuntimeException e) {
throw mapException(e);
}
}

public WalletBalance walletBalance() {
try {
GetWalletBalanceResponse resp = walletStub.getBalance(
GetWalletBalanceRequest.getDefaultInstance());
return new WalletBalance(resp.getBalance(), resp.getGasBalance());
} catch (StatusRuntimeException e) {
throw mapException(e);
}
}

public boolean walletApprove() {
try {
WalletApproveResponse resp = walletStub.approve(
WalletApproveRequest.getDefaultInstance());
return resp.getApproved();
} catch (StatusRuntimeException e) {
throw mapException(e);
}
}

// External Signer (Upload + Chunks prepare/finalize)

/**
Expand Down
87 changes: 87 additions & 0 deletions antd-java/src/test/java/com/autonomi/antd/GrpcAntdClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ void setUp() throws Exception {
.addService(new MockDataService())
.addService(new MockChunkService())
.addService(new MockFileService())
.addService(new MockWalletService())
.addService(new MockUploadService())
.build()
.start();
Expand Down Expand Up @@ -775,4 +776,90 @@ void testFinalizeChunkUploadReturnsAddressAndForwardsBody() {
String addr = client.finalizeChunkUpload("upid_chunk_42", tx);
assertEquals("addr_for_upid_chunk_42", addr);
}
// =========================================================================
// V2-286 MockWalletService + tests
// =========================================================================

static class MockWalletService extends antd.v1.WalletServiceGrpc.WalletServiceImplBase {
@Override
public void getAddress(antd.v1.Wallet.GetWalletAddressRequest req,
io.grpc.stub.StreamObserver<antd.v1.Wallet.GetWalletAddressResponse> resp) {
resp.onNext(antd.v1.Wallet.GetWalletAddressResponse.newBuilder()
.setAddress("0xabc1234567890abcdef1234567890abcdef123456")
.build());
resp.onCompleted();
}

@Override
public void getBalance(antd.v1.Wallet.GetWalletBalanceRequest req,
io.grpc.stub.StreamObserver<antd.v1.Wallet.GetWalletBalanceResponse> resp) {
resp.onNext(antd.v1.Wallet.GetWalletBalanceResponse.newBuilder()
.setBalance("1000000000000000000")
.setGasBalance("500000000000000000")
.build());
resp.onCompleted();
}

@Override
public void approve(antd.v1.Wallet.WalletApproveRequest req,
io.grpc.stub.StreamObserver<antd.v1.Wallet.WalletApproveResponse> resp) {
resp.onNext(antd.v1.Wallet.WalletApproveResponse.newBuilder()
.setApproved(true)
.build());
resp.onCompleted();
}
}

@Test
void walletAddressReturnsAddress() {
com.autonomi.antd.models.WalletAddress r = client.walletAddress();
assertEquals("0xabc1234567890abcdef1234567890abcdef123456", r.address());
}

@Test
void walletBalanceReturnsBalances() {
com.autonomi.antd.models.WalletBalance r = client.walletBalance();
assertEquals("1000000000000000000", r.balance());
assertEquals("500000000000000000", r.gasBalance());
}

@Test
void walletApproveReturnsTrue() {
assertTrue(client.walletApprove());
}

/**
* Daemon emits gRPC FailedPrecondition for "wallet not configured"; the
* established mapping in GrpcAntdClient.mapException surfaces this as
* PaymentException. (Semantic is a bit off vs REST's 503 but matches every
* SDK.)
*/
@Test
void walletAddressUnconfiguredReturnsPaymentException() throws Exception {
String serverName = InProcessServerBuilder.generateName();
Server errServer = InProcessServerBuilder.forName(serverName)
.directExecutor()
.addService(new antd.v1.WalletServiceGrpc.WalletServiceImplBase() {
@Override
public void getAddress(antd.v1.Wallet.GetWalletAddressRequest req,
io.grpc.stub.StreamObserver<antd.v1.Wallet.GetWalletAddressResponse> resp) {
resp.onError(io.grpc.Status.FAILED_PRECONDITION
.withDescription("wallet not configured — set AUTONOMI_WALLET_KEY")
.asRuntimeException());
}
})
.build()
.start();
ManagedChannel ch = InProcessChannelBuilder.forName(serverName).directExecutor().build();
try (GrpcAntdClient c = new GrpcAntdClient(ch)) {
com.autonomi.antd.errors.PaymentException ex = assertThrows(
com.autonomi.antd.errors.PaymentException.class,
c::walletAddress);
assertTrue(ex.getMessage().contains("wallet not configured"));
} finally {
ch.shutdownNow();
errServer.shutdownNow();
}
}

}