Skip to content

Commit

Permalink
chore(feat): Added DeleteTokenNftAllowanceAllSerials method (#1226)
Browse files Browse the repository at this point in the history
* feat: Added DeleteTokenNftAllowanceAllSerials method to account allowance approve transaction

Signed-off-by: ivaylogarnev-limechain <[email protected]>

* test: Added unit/integration tests for DeleteTokenNftAllowanceAllSerials method

Signed-off-by: ivaylogarnev-limechain <[email protected]>

---------

Signed-off-by: ivaylogarnev-limechain <[email protected]>
  • Loading branch information
ivaylogarnev-limechain authored Jan 21, 2025
1 parent 52f97bf commit da301d8
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 0 deletions.
28 changes: 28 additions & 0 deletions sdk/account_allowance_approve_transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,27 @@ func (tx *AccountAllowanceApproveTransaction) _ApproveTokenNftAllowanceAllSerial
return tx
}

func (tx *AccountAllowanceApproveTransaction) _DeleteTokenNftAllowanceAllSerials(tokenID TokenID, ownerAccountID *AccountID, spenderAccount AccountID) *AccountAllowanceApproveTransaction {
for _, t := range tx.nftAllowances {
if t.TokenID.String() == tokenID.String() {
if t.SpenderAccountID.String() == spenderAccount.String() {
t.SerialNumbers = []int64{}
t.AllSerials = true
return tx
}
}
}

tx.nftAllowances = append(tx.nftAllowances, &TokenNftAllowance{
TokenID: &tokenID,
SpenderAccountID: &spenderAccount,
SerialNumbers: []int64{},
AllSerials: false,
OwnerAccountID: ownerAccountID,
})
return tx
}

// AddAllTokenNftApproval
// Approve allowance of non-fungible token transfers for a spender.
// Spender has access to all of the owner's NFT units of type tokenId (currently
Expand All @@ -230,6 +251,13 @@ func (tx *AccountAllowanceApproveTransaction) ApproveTokenNftAllowanceAllSerials
return tx._ApproveTokenNftAllowanceAllSerials(tokenID, &ownerAccountID, spenderAccount)
}

// DeleteTokenNftAllowanceAllSerials
// Revokes an allowance that permits a spender to transfer all of the owner's non-fungible tokens (NFTs) of a specific type (tokenId).
// This action applies to both the NFTs currently owned by the owner and any future NFTs of the same type.
func (tx *AccountAllowanceApproveTransaction) DeleteTokenNftAllowanceAllSerials(tokenID TokenID, ownerAccountID AccountID, spenderAccount AccountID) *AccountAllowanceApproveTransaction {
return tx._DeleteTokenNftAllowanceAllSerials(tokenID, &ownerAccountID, spenderAccount)
}

// List of NFT allowance records
func (tx *AccountAllowanceApproveTransaction) GetTokenNftAllowances() []*TokenNftAllowance {
return tx.nftAllowances
Expand Down
38 changes: 38 additions & 0 deletions sdk/account_allowance_approve_transaction_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,41 @@ func TestUnitAllowanceApproveTransactionFromToBytes(t *testing.T) {

assert.Equal(t, tx.buildProtoBody(), txFromBytes.(AccountAllowanceApproveTransaction).buildProtoBody())
}

func TestUnitDeleteTokenNftAllowanceAllSerials(t *testing.T) {
t.Parallel()

transactionID := TransactionIDGenerate(AccountID{Account: 324})

transaction, err := NewAccountAllowanceApproveTransaction().
SetTransactionID(transactionID).
SetNodeAccountIDs(nodeAccountID).
DeleteTokenNftAllowanceAllSerials(tokenID2, owner, spenderAccountID1).
DeleteTokenNftAllowanceAllSerials(tokenID1, owner, spenderAccountID2).
Freeze()
require.NoError(t, err)

data := transaction.build()

switch d := data.Data.(type) {
case *services.TransactionBody_CryptoApproveAllowance:
require.Equal(t, d.CryptoApproveAllowance.NftAllowances, []*services.NftAllowance{
{
TokenId: tokenID2._ToProtobuf(),
Owner: owner._ToProtobuf(),
Spender: spenderAccountID1._ToProtobuf(),
SerialNumbers: []int64{},
ApprovedForAll: &wrapperspb.BoolValue{Value: false},
DelegatingSpender: nil,
},
{
TokenId: tokenID1._ToProtobuf(),
Owner: owner._ToProtobuf(),
Spender: spenderAccountID2._ToProtobuf(),
SerialNumbers: []int64{},
ApprovedForAll: &wrapperspb.BoolValue{Value: false},
DelegatingSpender: nil,
},
})
}
}
64 changes: 64 additions & 0 deletions sdk/token_nft_allowance_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,67 @@ func TestIntegrationAfterGivenAllowanceForAllSerialsCanGiveSingleSerialToOtherAc
require.NoError(t, err)
require.Equal(t, env.OperatorID, info2[0].AccountID)
}

func TestIntegrationCantSendIfTokenNftSerialsDeleted(t *testing.T) {
t.Parallel()
env := NewIntegrationTestEnv(t)
defer CloseIntegrationTestEnv(env, nil)
spenderKey, err := PrivateKeyGenerateEd25519()
require.NoError(t, err)

spenderCreate, err := NewAccountCreateTransaction().
SetKey(spenderKey.PublicKey()).
SetInitialBalance(NewHbar(2)).
Execute(env.Client)
require.NoError(t, err)
spenderAccountReceipt, err := spenderCreate.SetValidateStatus(true).GetReceipt(env.Client)
spenderAccountId := spenderAccountReceipt.AccountID

receiverKey, err := PrivateKeyGenerateEd25519()
require.NoError(t, err)
receiverCreate, err := NewAccountCreateTransaction().
SetKey(receiverKey.PublicKey()).
SetInitialBalance(NewHbar(2)).
Execute(env.Client)
require.NoError(t, err)
receiverAccountReceipt, err := receiverCreate.SetValidateStatus(true).GetReceipt(env.Client)
receiverAccountId := receiverAccountReceipt.AccountID

tokenID, err := createNft(&env)
require.NoError(t, err)

frozenTxn, err := NewTokenAssociateTransaction().SetTokenIDs(tokenID).SetAccountID(*spenderAccountId).FreezeWith(env.Client)
require.NoError(t, err)
_, err = frozenTxn.Sign(spenderKey).Execute(env.Client)
require.NoError(t, err)

frozenTxn, err = NewTokenAssociateTransaction().SetTokenIDs(tokenID).SetAccountID(*receiverAccountId).FreezeWith(env.Client)
require.NoError(t, err)
_, err = frozenTxn.Sign(receiverKey).Execute(env.Client)
require.NoError(t, err)

mint, err := NewTokenMintTransaction().SetTokenID(tokenID).SetMetadata([]byte{0x01}).SetMetadata([]byte{0x02}).Execute(env.Client)
require.NoError(t, err)
mintReceipt, err := mint.SetValidateStatus(true).GetReceipt(env.Client)
require.NoError(t, err)
serials := mintReceipt.SerialNumbers

nft1 := NftID{TokenID: tokenID, SerialNumber: serials[0]}
approveTx, err := NewAccountAllowanceApproveTransaction().ApproveTokenNftAllowanceAllSerials(nft1.TokenID, env.OperatorID, *spenderAccountId).Execute(env.Client)
require.NoError(t, err)
_, err = approveTx.SetValidateStatus(true).GetReceipt(env.Client)
require.NoError(t, err)

resp, err := NewAccountAllowanceApproveTransaction().DeleteTokenNftAllowanceAllSerials(nft1.TokenID, env.OperatorID, *spenderAccountId).Execute(env.Client)
require.NoError(t, err)

onBehalfOfTxId := TransactionIDGenerate(*spenderAccountId)

frozenTransfer, err := NewTransferTransaction().AddApprovedNftTransfer(nft1, env.OperatorID, *receiverAccountId, true).SetTransactionID(onBehalfOfTxId).FreezeWith(env.Client)
require.NoError(t, err)

resp, err = frozenTransfer.Sign(spenderKey).Execute(env.Client)
_, err = resp.SetValidateStatus(true).GetReceipt(env.Client)
require.Error(t, err)
require.Equal(t, "exceptional receipt status: SPENDER_DOES_NOT_HAVE_ALLOWANCE", err.Error())
}

0 comments on commit da301d8

Please sign in to comment.