use of com.hederahashgraph.api.proto.java.TokenTransferList in project hedera-mirror-node by hashgraph.
the class TokenUpdateTransactionHandler method updateTreasury.
private void updateTreasury(RecordItem recordItem) {
var payerAccountId = EntityId.of(recordItem.getTransactionBody().getTransactionID().getAccountID()).getId();
for (TokenTransferList tokenTransferList : recordItem.getRecord().getTokenTransferListsList()) {
for (NftTransfer nftTransfer : tokenTransferList.getNftTransfersList()) {
if (nftTransfer.getSerialNumber() == NftTransferId.WILDCARD_SERIAL_NUMBER) {
EntityId newTreasury = EntityId.of(nftTransfer.getReceiverAccountID());
EntityId previousTreasury = EntityId.of(nftTransfer.getSenderAccountID());
EntityId tokenId = EntityId.of(tokenTransferList.getToken());
nftRepository.updateTreasury(tokenId.getId(), previousTreasury.getId(), newTreasury.getId(), recordItem.getConsensusTimestamp(), payerAccountId, nftTransfer.getIsApproval());
}
}
}
}
use of com.hederahashgraph.api.proto.java.TokenTransferList in project hedera-mirror-node by hashgraph.
the class TokenUpdateTransactionHandlerTest method updateTreasury.
@Test
void updateTreasury() {
AbstractEntity entity = getExpectedUpdatedEntity();
AccountID previousAccountId = AccountID.newBuilder().setAccountNum(1L).build();
AccountID newAccountId = AccountID.newBuilder().setAccountNum(2L).build();
TokenID tokenID = TokenID.newBuilder().setTokenNum(3L).build();
long consensusTimestamp = DomainUtils.timestampInNanosMax(MODIFIED_TIMESTAMP);
TokenTransferList tokenTransferList = TokenTransferList.newBuilder().setToken(tokenID).addNftTransfers(NftTransfer.newBuilder().setReceiverAccountID(newAccountId).setSenderAccountID(previousAccountId).setSerialNumber(NftTransferId.WILDCARD_SERIAL_NUMBER).build()).build();
TransactionRecord record = getDefaultTransactionRecord().addTokenTransferLists(tokenTransferList).build();
RecordItem recordItem = getRecordItem(getDefaultTransactionBody().build(), record);
when(entityIdService.lookup(AccountID.newBuilder().setAccountNum(DEFAULT_AUTO_RENEW_ACCOUNT_NUM).build())).thenReturn(EntityIdEndec.decode(DEFAULT_AUTO_RENEW_ACCOUNT_NUM, EntityType.ACCOUNT));
Transaction transaction = new Transaction();
transaction.setEntityId(entity.toEntityId());
transactionHandler.updateTransaction(transaction, recordItem);
TransactionBody body = recordItem.getTransactionBody();
var payerAccount = EntityId.of(body.getTransactionID().getAccountID()).toEntity().getId();
verify(nftRepository).updateTreasury(tokenID.getTokenNum(), previousAccountId.getAccountNum(), newAccountId.getAccountNum(), consensusTimestamp, payerAccount, false);
}
use of com.hederahashgraph.api.proto.java.TokenTransferList in project hedera-services by hashgraph.
the class SigRequirements method cryptoTransfer.
private <T> SigningOrderResult<T> cryptoTransfer(final AccountID payer, final CryptoTransferTransactionBody op, final SigningOrderResultFactory<T> factory, @Nullable final LinkedRefs linkedRefs) {
List<JKey> required = new ArrayList<>();
KeyOrderingFailure failure;
for (TokenTransferList xfers : op.getTokenTransfersList()) {
for (AccountAmount adjust : xfers.getTransfersList()) {
if ((failure = includeIfNecessary(payer, adjust, required, false, linkedRefs)) != NONE) {
return accountFailure(failure, factory);
}
}
final var token = xfers.getToken();
for (NftTransfer adjust : xfers.getNftTransfersList()) {
final var sender = adjust.getSenderAccountID();
if ((failure = nftIncludeIfNecessary(payer, sender, null, adjust.getIsApproval(), required, token, op, linkedRefs)) != NONE) {
return accountFailure(failure, factory);
}
final var receiver = adjust.getReceiverAccountID();
if ((failure = nftIncludeIfNecessary(payer, receiver, sender, false, required, token, op, linkedRefs)) != NONE) {
return (failure == MISSING_TOKEN) ? factory.forMissingToken() : accountFailure(failure, factory);
}
}
}
for (AccountAmount adjust : op.getTransfers().getAccountAmountsList()) {
if ((failure = includeIfNecessary(payer, adjust, required, true, linkedRefs)) != NONE) {
return accountFailure(failure, factory);
}
}
return factory.forValidOrder(required);
}
use of com.hederahashgraph.api.proto.java.TokenTransferList in project hedera-services by hashgraph.
the class TokenAssociationSpecs method dissociationFromExpiredTokensAsExpected.
public HapiApiSpec dissociationFromExpiredTokensAsExpected() {
final String treasury = "accountA";
final String frozenAccount = "frozen";
final String unfrozenAccount = "unfrozen";
final String expiringToken = "expiringToken";
long lifetimeSecs = 10;
AtomicLong now = new AtomicLong();
return defaultHapiSpec("DissociationFromExpiredTokensAsExpected").given(newKeyNamed("freezeKey"), cryptoCreate(treasury), cryptoCreate(frozenAccount).via("creation"), cryptoCreate(unfrozenAccount).via("creation"), withOpContext((spec, opLog) -> {
var subOp = getTxnRecord("creation");
allRunFor(spec, subOp);
var record = subOp.getResponseRecord();
now.set(record.getConsensusTimestamp().getSeconds());
}), sourcing(() -> tokenCreate(expiringToken).freezeKey("freezeKey").freezeDefault(true).treasury(treasury).initialSupply(1000L).expiry(now.get() + lifetimeSecs))).when(tokenAssociate(unfrozenAccount, expiringToken), tokenAssociate(frozenAccount, expiringToken), tokenUnfreeze(expiringToken, unfrozenAccount), cryptoTransfer(moving(100L, expiringToken).between(treasury, unfrozenAccount))).then(getAccountBalance(treasury).hasTokenBalance(expiringToken, 900L), sleepFor(lifetimeSecs * 1_000L), tokenDissociate(treasury, expiringToken).hasKnownStatus(ACCOUNT_IS_TREASURY), tokenDissociate(unfrozenAccount, expiringToken).via("dissociateTxn"), getTxnRecord("dissociateTxn").hasPriority(recordWith().tokenTransfers(new BaseErroringAssertsProvider<>() {
@Override
public ErroringAsserts<List<TokenTransferList>> assertsFor(HapiApiSpec spec) {
return tokenXfers -> {
try {
assertEquals(1, tokenXfers.size(), "Wrong number of tokens transferred!");
TokenTransferList xfers = tokenXfers.get(0);
assertEquals(spec.registry().getTokenID(expiringToken), xfers.getToken(), "Wrong token transferred!");
AccountAmount toTreasury = xfers.getTransfers(0);
assertEquals(spec.registry().getAccountID(treasury), toTreasury.getAccountID(), "Treasury should come first!");
assertEquals(100L, toTreasury.getAmount(), "Treasury should get 100 tokens back!");
AccountAmount fromAccount = xfers.getTransfers(1);
assertEquals(spec.registry().getAccountID(unfrozenAccount), fromAccount.getAccountID(), "Account should come second!");
assertEquals(-100L, fromAccount.getAmount(), "Account should send 100 tokens back!");
} catch (Throwable error) {
return List.of(error);
}
return Collections.emptyList();
};
}
})), getAccountBalance(treasury).hasTokenBalance(expiringToken, 1000L), getAccountInfo(frozenAccount).hasToken(relationshipWith(expiringToken).freeze(Frozen)), tokenDissociate(frozenAccount, expiringToken).hasKnownStatus(ACCOUNT_FROZEN_FOR_TOKEN));
}
use of com.hederahashgraph.api.proto.java.TokenTransferList in project hedera-mirror-node by hashgraph.
the class EntityRecordItemListenerTokenTest method tokenWipeNft.
@Test
void tokenWipeNft() {
createAndAssociateToken(TOKEN_ID, NON_FUNGIBLE_UNIQUE, SYMBOL, CREATE_TIMESTAMP, ASSOCIATE_TIMESTAMP, PAYER2, false, false, false, 0);
long mintTimestamp = 10L;
TokenTransferList mintTransfer = nftTransfer(TOKEN_ID, PAYER, DEFAULT_ACCOUNT_ID, SERIAL_NUMBER_LIST);
Transaction mintTransaction = tokenSupplyTransaction(TOKEN_ID, NON_FUNGIBLE_UNIQUE, true, 0, SERIAL_NUMBER_LIST);
insertAndParseTransaction(mintTimestamp, mintTransaction, builder -> {
builder.getReceiptBuilder().setNewTotalSupply(2L).addAllSerialNumbers(SERIAL_NUMBER_LIST);
builder.addTokenTransferLists(mintTransfer);
});
// approve allowance for nft 1
long approveAllowanceTimestamp = 12L;
var cryptoApproveAllowanceTransaction = buildTransaction(b -> b.getCryptoApproveAllowanceBuilder().addNftAllowances(NftAllowance.newBuilder().setOwner(PAYER).setTokenId(TOKEN_ID).addSerialNumbers(SERIAL_NUMBER_1).setSpender(SPENDER)));
insertAndParseTransaction(approveAllowanceTimestamp, cryptoApproveAllowanceTransaction);
var expectedNft1 = Nft.builder().id(new NftId(SERIAL_NUMBER_1, EntityId.of(TOKEN_ID))).accountId(EntityId.of(PAYER)).createdTimestamp(mintTimestamp).deleted(false).metadata(METADATA.getBytes()).modifiedTimestamp(approveAllowanceTimestamp).spender(EntityId.of(SPENDER)).build();
assertThat(nftRepository.findById(expectedNft1.getId())).get().isEqualTo(expectedNft1);
long wipeTimestamp = 15L;
TokenTransferList wipeTransfer = nftTransfer(TOKEN_ID, DEFAULT_ACCOUNT_ID, PAYER, List.of(SERIAL_NUMBER_1));
Transaction transaction = tokenWipeTransaction(TOKEN_ID, NON_FUNGIBLE_UNIQUE, 0, List.of(SERIAL_NUMBER_1));
insertAndParseTransaction(wipeTimestamp, transaction, builder -> {
builder.getReceiptBuilder().setNewTotalSupply(1L);
builder.addTokenTransferLists(wipeTransfer);
});
expectedNft1.setAccountId(null);
expectedNft1.setDeleted(true);
expectedNft1.setModifiedTimestamp(wipeTimestamp);
expectedNft1.setSpender(null);
var expectedNft2 = Nft.builder().id(new NftId(SERIAL_NUMBER_2, EntityId.of(TOKEN_ID))).accountId(EntityId.of(PAYER)).createdTimestamp(mintTimestamp).deleted(false).metadata(METADATA.getBytes()).modifiedTimestamp(mintTimestamp).build();
// Verify
assertThat(nftTransferRepository.count()).isEqualTo(3L);
assertNftTransferInRepository(mintTimestamp, SERIAL_NUMBER_1, TOKEN_ID, PAYER, null);
assertNftTransferInRepository(mintTimestamp, SERIAL_NUMBER_2, TOKEN_ID, PAYER, null);
assertNftTransferInRepository(wipeTimestamp, SERIAL_NUMBER_1, TOKEN_ID, null, PAYER);
assertTokenInRepository(TOKEN_ID, true, CREATE_TIMESTAMP, wipeTimestamp, SYMBOL, 1);
assertThat(nftRepository.findAll()).containsExactlyInAnyOrder(expectedNft1, expectedNft2);
}
Aggregations