Skip to content

Commit 8d85ef6

Browse files
authored
Tck implement ScheduleCreateTransaction (#2478)
Signed-off-by: emiliyank <e.kadiyski@gmail.com>
1 parent 6b0d1a6 commit 8d85ef6

10 files changed

Lines changed: 1642 additions & 881 deletions

File tree

sdk/src/main/java/com/hedera/hashgraph/sdk/ScheduleCreateTransaction.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ public final class ScheduleCreateTransaction extends Transaction<ScheduleCreateT
101101
@Nullable
102102
private Instant expirationTime = null;
103103

104+
@Nullable
105+
private java.time.Duration expirationTimeDuration = null;
106+
104107
private boolean waitForExpiry = false;
105108

106109
/**
@@ -145,7 +148,24 @@ public Instant getExpirationTime() {
145148
* @return {@code this}
146149
*/
147150
public ScheduleCreateTransaction setExpirationTime(Instant expirationTime) {
151+
Objects.requireNonNull(expirationTime);
152+
requireNotFrozen();
148153
this.expirationTime = expirationTime;
154+
this.expirationTimeDuration = null;
155+
return this;
156+
}
157+
158+
/**
159+
* Overload: set the expiration time using a Duration value.
160+
*
161+
* @param expirationTime The duration to be used as expiration time
162+
* @return {@code this}
163+
*/
164+
public ScheduleCreateTransaction setExpirationTime(java.time.Duration expirationTime) {
165+
Objects.requireNonNull(expirationTime);
166+
requireNotFrozen();
167+
this.expirationTime = null;
168+
this.expirationTimeDuration = expirationTime;
149169
return this;
150170
}
151171

@@ -312,6 +332,8 @@ ScheduleCreateTransactionBody.Builder build() {
312332
}
313333
if (expirationTime != null) {
314334
builder.setExpirationTime(InstantConverter.toProtobuf(expirationTime));
335+
} else if (expirationTimeDuration != null) {
336+
builder.setExpirationTime(InstantConverter.toProtobuf(expirationTimeDuration));
315337
}
316338
builder.setMemo(scheduleMemo).setWaitForExpiry(waitForExpiry);
317339
return builder;

sdk/src/test/java/com/hedera/hashgraph/sdk/ScheduleCreateTransactionTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
package com.hedera.hashgraph.sdk;
33

44
import static org.assertj.core.api.Assertions.assertThat;
5+
import static org.junit.jupiter.api.Assertions.assertThrows;
56

67
import io.github.jsonSnapshot.SnapshotMatcher;
8+
import java.time.Duration;
79
import java.time.Instant;
810
import java.util.Arrays;
911
import org.junit.jupiter.api.AfterAll;
@@ -61,4 +63,41 @@ void shouldBytesNoSetters() throws Exception {
6163
var tx2 = Transaction.fromBytes(tx.toBytes());
6264
assertThat(tx2.toString()).isEqualTo(tx.toString());
6365
}
66+
67+
@Test
68+
void shouldSupportExpirationTimeDurationBytesRoundTrip() throws Exception {
69+
var transferTransaction = new TransferTransaction()
70+
.addHbarTransfer(AccountId.fromString("0.0.555"), new Hbar(-10))
71+
.addHbarTransfer(AccountId.fromString("0.0.333"), new Hbar(10));
72+
73+
var tx = transferTransaction
74+
.schedule()
75+
.setNodeAccountIds(Arrays.asList(AccountId.fromString("0.0.5005"), AccountId.fromString("0.0.5006")))
76+
.setTransactionId(TransactionId.withValidStart(AccountId.fromString("0.0.5006"), validStart))
77+
.setAdminKey(unusedPrivateKey)
78+
.setPayerAccountId(AccountId.fromString("0.0.222"))
79+
.setScheduleMemo("with-duration")
80+
.setMaxTransactionFee(new Hbar(1))
81+
.setExpirationTime(Duration.ofSeconds(1234));
82+
83+
// When expiration is set via Duration, Instant getter should be null
84+
assertThat(tx.getExpirationTime()).isNull();
85+
86+
var tx2 = (ScheduleCreateTransaction) Transaction.fromBytes(tx.toBytes());
87+
assertThat(tx2.toString()).isEqualTo(tx.toString());
88+
assertThat(tx2.getExpirationTime()).isEqualTo(Instant.ofEpochSecond(1234));
89+
}
90+
91+
@Test
92+
void setExpirationTimeDurationOnFrozenTransactionShouldThrow() {
93+
var tx = spawnTestTransaction();
94+
assertThrows(IllegalStateException.class, () -> tx.setExpirationTime(Duration.ofSeconds(1)));
95+
}
96+
97+
@Test
98+
void getSetExpirationTimeInstant() {
99+
var instant = Instant.ofEpochSecond(1_234_567L);
100+
var tx = new ScheduleCreateTransaction().setExpirationTime(instant);
101+
assertThat(tx.getExpirationTime()).isEqualTo(instant);
102+
}
64103
}
Lines changed: 12 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// SPDX-License-Identifier: Apache-2.0
22
package com.hedera.hashgraph.tck.methods.sdk;
33

4-
import com.google.protobuf.InvalidProtocolBufferException;
54
import com.hedera.hashgraph.sdk.*;
65
import com.hedera.hashgraph.tck.annotation.JSONRPC2Method;
76
import com.hedera.hashgraph.tck.annotation.JSONRPC2Service;
@@ -10,10 +9,8 @@
109
import com.hedera.hashgraph.tck.methods.sdk.param.transfer.*;
1110
import com.hedera.hashgraph.tck.methods.sdk.response.AccountAllowanceResponse;
1211
import com.hedera.hashgraph.tck.methods.sdk.response.AccountResponse;
13-
import com.hedera.hashgraph.tck.util.KeyUtils;
14-
import java.time.Duration;
12+
import com.hedera.hashgraph.tck.util.TransactionBuilders;
1513
import java.util.Map;
16-
import java.util.Optional;
1714

1815
/**
1916
* AccountService for account related methods
@@ -28,41 +25,7 @@ public AccountService(SdkService sdkService) {
2825

2926
@JSONRPC2Method("createAccount")
3027
public AccountResponse createAccount(final AccountCreateParams params) throws Exception {
31-
AccountCreateTransaction accountCreateTransaction = new AccountCreateTransaction();
32-
params.getKey().ifPresent(key -> {
33-
try {
34-
accountCreateTransaction.setKeyWithoutAlias(KeyUtils.getKeyFromString(key));
35-
} catch (InvalidProtocolBufferException e) {
36-
throw new IllegalArgumentException(e);
37-
}
38-
});
39-
40-
params.getInitialBalance()
41-
.ifPresent(initialBalanceTinybars -> accountCreateTransaction.setInitialBalance(
42-
Hbar.from(Long.parseLong(initialBalanceTinybars), HbarUnit.TINYBAR)));
43-
44-
params.getReceiverSignatureRequired().ifPresent(accountCreateTransaction::setReceiverSignatureRequired);
45-
46-
params.getAutoRenewPeriod()
47-
.ifPresent(autoRenewPeriodSeconds -> accountCreateTransaction.setAutoRenewPeriod(
48-
Duration.ofSeconds(Long.parseLong(autoRenewPeriodSeconds))));
49-
50-
params.getMemo().ifPresent(accountCreateTransaction::setAccountMemo);
51-
52-
params.getMaxAutoTokenAssociations()
53-
.ifPresent(autoAssociations ->
54-
accountCreateTransaction.setMaxAutomaticTokenAssociations(autoAssociations.intValue()));
55-
56-
params.getStakedAccountId()
57-
.ifPresent(stakedAccountId ->
58-
accountCreateTransaction.setStakedAccountId(AccountId.fromString(stakedAccountId)));
59-
60-
params.getStakedNodeId()
61-
.ifPresent(stakedNodeId -> accountCreateTransaction.setStakedNodeId(Long.parseLong(stakedNodeId)));
62-
63-
params.getDeclineStakingReward().ifPresent(accountCreateTransaction::setDeclineStakingReward);
64-
65-
params.getAlias().ifPresent(accountCreateTransaction::setAlias);
28+
AccountCreateTransaction accountCreateTransaction = TransactionBuilders.AccountBuilder.buildCreate(params);
6629

6730
params.getCommonTransactionParams()
6831
.ifPresent(commonTransactionParams ->
@@ -81,43 +44,7 @@ public AccountResponse createAccount(final AccountCreateParams params) throws Ex
8144

8245
@JSONRPC2Method("updateAccount")
8346
public AccountResponse updateAccount(final AccountUpdateParams params) throws Exception {
84-
AccountUpdateTransaction accountUpdateTransaction = new AccountUpdateTransaction();
85-
86-
params.getAccountId()
87-
.ifPresent(accountId -> accountUpdateTransaction.setAccountId(AccountId.fromString(accountId)));
88-
89-
params.getKey().ifPresent(key -> {
90-
try {
91-
accountUpdateTransaction.setKey(KeyUtils.getKeyFromString(key));
92-
} catch (InvalidProtocolBufferException e) {
93-
throw new IllegalArgumentException(e);
94-
}
95-
});
96-
97-
params.getReceiverSignatureRequired().ifPresent(accountUpdateTransaction::setReceiverSignatureRequired);
98-
99-
params.getAutoRenewPeriod()
100-
.ifPresent(autoRenewPeriodSeconds -> accountUpdateTransaction.setAutoRenewPeriod(
101-
Duration.ofSeconds(Long.parseLong(autoRenewPeriodSeconds))));
102-
103-
params.getMemo().ifPresent(accountUpdateTransaction::setAccountMemo);
104-
105-
params.getExpirationTime()
106-
.ifPresent(expirationTime ->
107-
accountUpdateTransaction.setExpirationTime(Duration.ofSeconds(Long.parseLong(expirationTime))));
108-
109-
params.getMaxAutoTokenAssociations()
110-
.ifPresent(autoAssociations ->
111-
accountUpdateTransaction.setMaxAutomaticTokenAssociations(autoAssociations.intValue()));
112-
113-
params.getStakedAccountId()
114-
.ifPresent(stakedAccountId ->
115-
accountUpdateTransaction.setStakedAccountId(AccountId.fromString(stakedAccountId)));
116-
117-
params.getStakedNodeId()
118-
.ifPresent(stakedNodeId -> accountUpdateTransaction.setStakedNodeId(Long.parseLong(stakedNodeId)));
119-
120-
params.getDeclineStakingReward().ifPresent(accountUpdateTransaction::setDeclineStakingReward);
47+
AccountUpdateTransaction accountUpdateTransaction = TransactionBuilders.AccountBuilder.buildUpdate(params);
12148

12249
params.getCommonTransactionParams()
12350
.ifPresent(commonTransactionParams ->
@@ -131,13 +58,7 @@ public AccountResponse updateAccount(final AccountUpdateParams params) throws Ex
13158

13259
@JSONRPC2Method("deleteAccount")
13360
public AccountResponse deleteAccount(final AccountDeleteParams params) throws Exception {
134-
AccountDeleteTransaction accountDeleteTransaction = new AccountDeleteTransaction();
135-
136-
params.getDeleteAccountId()
137-
.ifPresent(accountId -> accountDeleteTransaction.setAccountId(AccountId.fromString(accountId)));
138-
139-
params.getTransferAccountId()
140-
.ifPresent(accountId -> accountDeleteTransaction.setTransferAccountId(AccountId.fromString(accountId)));
61+
AccountDeleteTransaction accountDeleteTransaction = TransactionBuilders.AccountBuilder.buildDelete(params);
14162

14263
params.getCommonTransactionParams()
14364
.ifPresent(commonTransactionParams ->
@@ -151,9 +72,7 @@ public AccountResponse deleteAccount(final AccountDeleteParams params) throws Ex
15172

15273
@JSONRPC2Method("approveAllowance")
15374
public AccountAllowanceResponse approveAllowance(final AccountAllowanceParams params) throws Exception {
154-
AccountAllowanceApproveTransaction tx = new AccountAllowanceApproveTransaction();
155-
156-
params.getAllowances().ifPresent(allowances -> allowances.forEach(allowance -> approve(tx, allowance)));
75+
AccountAllowanceApproveTransaction tx = TransactionBuilders.AccountBuilder.buildApproveAllowance(params);
15776

15877
params.getCommonTransactionParams()
15978
.ifPresent(commonParams -> commonParams.fillOutTransaction(tx, sdkService.getClient()));
@@ -165,9 +84,7 @@ public AccountAllowanceResponse approveAllowance(final AccountAllowanceParams pa
16584

16685
@JSONRPC2Method("deleteAllowance")
16786
public AccountAllowanceResponse deleteAllowance(final AccountAllowanceParams params) throws Exception {
168-
AccountAllowanceDeleteTransaction tx = new AccountAllowanceDeleteTransaction();
169-
170-
params.getAllowances().ifPresent(allowances -> allowances.forEach(allowance -> delete(tx, allowance)));
87+
AccountAllowanceDeleteTransaction tx = TransactionBuilders.AccountBuilder.buildDeleteAllowance(params);
17188

17289
params.getCommonTransactionParams()
17390
.ifPresent(commonParams -> commonParams.fillOutTransaction(tx, sdkService.getClient()));
@@ -186,10 +103,7 @@ public AccountAllowanceResponse deleteAllowance(final AccountAllowanceParams par
186103
*/
187104
@JSONRPC2Method("transferCrypto")
188105
public Map<String, String> transferCrypto(final TransferCryptoParams params) throws Exception {
189-
TransferTransaction transferTransaction = new TransferTransaction();
190-
191-
params.getTransfers()
192-
.ifPresent(transfers -> transfers.forEach(txParams -> processTransfer(transferTransaction, txParams)));
106+
TransferTransaction transferTransaction = TransactionBuilders.TransferBuilder.buildTransfer(params);
193107

194108
params.getCommonTransactionParams()
195109
.ifPresent(
@@ -204,7 +118,7 @@ public Map<String, String> transferCrypto(final TransferCryptoParams params) thr
204118
/**
205119
* Process an individual transfer based on its type (Hbar, Token, or NFT)
206120
*/
207-
private void processTransfer(TransferTransaction tx, TransferParams txParams) {
121+
public static void processTransfer(TransferTransaction tx, TransferParams txParams) {
208122
boolean approved = txParams.getApproved().orElse(false);
209123

210124
txParams.getHbar().ifPresent(hbarParams -> processHbarTransfer(tx, hbarParams, approved));
@@ -215,7 +129,7 @@ private void processTransfer(TransferTransaction tx, TransferParams txParams) {
215129
/**
216130
* Process an Hbar transfer
217131
*/
218-
private void processHbarTransfer(TransferTransaction tx, HbarTransferParams hbarParams, boolean approved) {
132+
private static void processHbarTransfer(TransferTransaction tx, HbarTransferParams hbarParams, boolean approved) {
219133
hbarParams.getAmount().ifPresent(amountStr -> {
220134
Hbar amount = Hbar.fromTinybars(Long.parseLong(amountStr));
221135

@@ -242,7 +156,8 @@ private void processHbarTransfer(TransferTransaction tx, HbarTransferParams hbar
242156
/**
243157
* Process a token transfer
244158
*/
245-
private void processTokenTransfer(TransferTransaction tx, TokenTransferParams tokenParams, boolean approved) {
159+
private static void processTokenTransfer(
160+
TransferTransaction tx, TokenTransferParams tokenParams, boolean approved) {
246161
tokenParams.getAccountId().ifPresent(accountIdStr -> {
247162
tokenParams.getTokenId().ifPresent(tokenIdStr -> {
248163
tokenParams.getAmount().ifPresent(amountStr -> {
@@ -272,7 +187,7 @@ private void processTokenTransfer(TransferTransaction tx, TokenTransferParams to
272187
/**
273188
* Process an NFT transfer
274189
*/
275-
private void processNftTransfer(TransferTransaction tx, NftTransferParams nftParams, boolean approved) {
190+
private static void processNftTransfer(TransferTransaction tx, NftTransferParams nftParams, boolean approved) {
276191
nftParams.getSenderAccountId().ifPresent(senderIdStr -> {
277192
nftParams.getReceiverAccountId().ifPresent(receiverIdStr -> {
278193
nftParams.getTokenId().ifPresent(tokenIdStr -> {
@@ -293,55 +208,4 @@ private void processNftTransfer(TransferTransaction tx, NftTransferParams nftPar
293208
});
294209
});
295210
}
296-
297-
private void approve(AccountAllowanceApproveTransaction tx, AllowanceParams allowance) {
298-
AccountId owner = AccountId.fromString(allowance.getOwnerAccountId().orElseThrow());
299-
AccountId spender = AccountId.fromString(allowance.getSpenderAccountId().orElseThrow());
300-
301-
allowance
302-
.getHbar()
303-
.ifPresent(hbar ->
304-
tx.approveHbarAllowance(owner, spender, Hbar.fromTinybars(Long.parseLong(hbar.getAmount()))));
305-
306-
allowance
307-
.getToken()
308-
.ifPresent(token -> tx.approveTokenAllowance(
309-
TokenId.fromString(token.getTokenId()), owner, spender, token.getAmount()));
310-
311-
allowance.getNft().ifPresent(nft -> approveNFT(tx, owner, spender, nft));
312-
}
313-
314-
private void delete(AccountAllowanceDeleteTransaction tx, AllowanceParams allowance) {
315-
var owner = AccountId.fromString(allowance.getOwnerAccountId().orElseThrow());
316-
var tokenId = allowance.getTokenId().orElseThrow();
317-
318-
if (allowance.getSerialNumbers().isPresent()) {
319-
allowance.getSerialNumbers().get().forEach(serialNumber -> {
320-
var nftId = new NftId(TokenId.fromString(tokenId), Long.parseLong(serialNumber));
321-
tx.deleteAllTokenNftAllowances(nftId, owner);
322-
});
323-
}
324-
}
325-
326-
private void approveNFT(
327-
AccountAllowanceApproveTransaction tx,
328-
AccountId owner,
329-
AccountId spender,
330-
AllowanceParams.TokenNftAllowance nft) {
331-
TokenId tokenId = TokenId.fromString(nft.getTokenId());
332-
Optional<String> delegateSpender = Optional.ofNullable(nft.getDelegatingSpender());
333-
334-
if (!nft.getSerialNumbers().isEmpty()) {
335-
nft.getSerialNumbers().forEach(serial -> {
336-
NftId nftId = new NftId(tokenId, serial);
337-
delegateSpender.ifPresentOrElse(
338-
ds -> tx.approveTokenNftAllowance(nftId, owner, spender, AccountId.fromString(ds)),
339-
() -> tx.approveTokenNftAllowance(nftId, owner, spender));
340-
});
341-
} else if (nft.getAllSerials()) {
342-
tx.approveTokenNftAllowanceAllSerials(tokenId, owner, spender);
343-
} else {
344-
tx.deleteTokenNftAllowanceAllSerials(tokenId, owner, spender);
345-
}
346-
}
347211
}

0 commit comments

Comments
 (0)