-
Notifications
You must be signed in to change notification settings - Fork 148
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Implement TokenRejectTransaction (#2411)
* feat: TokenRejectTransaction js file Signed-off-by: Ivaylo Nikolov <[email protected]> * test: unit tests for TokenRejectTransaction Signed-off-by: Ivaylo Nikolov <[email protected]> * test: add integration tests for TokenRejectTransaction Signed-off-by: Ivaylo Nikolov <[email protected]> * feat: TokenRejectFlow Signed-off-by: Ivaylo Nikolov <[email protected]> * feat: TokenRejectFlow and TokenReject example Signed-off-by: Ivaylo Nikolov <[email protected]> * fix: circular dependency Signed-off-by: Ivaylo Nikolov <[email protected]> * chore: lint change Signed-off-by: Ivaylo Nikolov <[email protected]> * chore: remove client Signed-off-by: Ivaylo Nikolov <[email protected]> * refactor: use to string for status codes Signed-off-by: Ivaylo Nikolov <[email protected]> * refactor: use ? instead of | null Signed-off-by: Ivaylo Nikolov <[email protected]> * refactor: avoid usage of token identifier Signed-off-by: Ivaylo Nikolov <[email protected]> * refator: add PublicKey type for jsdocs in type definitions Signed-off-by: Ivaylo Nikolov <[email protected]> * fix: should not support strings conversion in token reject tx Signed-off-by: Ivaylo Nikolov <[email protected]> * fix(test): unit test should not expect token identifier property Signed-off-by: Ivaylo Nikolov <[email protected]> * fix: use proper PublicKey path Signed-off-by: Ivaylo Nikolov <[email protected]> * feat: better console logging when executing examples Signed-off-by: Ivaylo Nikolov <[email protected]> Signed-off-by: Alexander Gadzhalov <[email protected]> * refactor: avoid using magical number in example script Signed-off-by: Ivaylo Nikolov <[email protected]> * chore: remove unused imports Signed-off-by: Ivaylo Nikolov <[email protected]> * chore: improve comments naming Signed-off-by: Ivaylo Nikolov <[email protected]> * chore: improve token naming Signed-off-by: Ivaylo Nikolov <[email protected]> * chore: max automatic token assoc should be 100 for consistency between all sdk Signed-off-by: Ivaylo Nikolov <[email protected]> * fix: reconnect to working node (#2417) * chore: address initial pain points Signed-off-by: Ivan Ivanov <[email protected]> * chore: bump grpc-js version Signed-off-by: Ivan Ivanov <[email protected]> * fix Signed-off-by: svetoslav-nikol0v <[email protected]> * remove example Signed-off-by: svetoslav-nikol0v <[email protected]> * chore: formatting Signed-off-by: svetoslav-nikol0v <[email protected]> * fix Signed-off-by: svetoslav-nikol0v <[email protected]> * revert: grpc old version Signed-off-by: svetoslav-nikol0v <[email protected]> * revert: pnpm-lock file Signed-off-by: svetoslav-nikol0v <[email protected]> * revert: package-lock file Signed-off-by: svetoslav-nikol0v <[email protected]> --------- Signed-off-by: Ivan Ivanov <[email protected]> Signed-off-by: svetoslav-nikol0v <[email protected]> Co-authored-by: Ivan Ivanov <[email protected]> * test(fix): update token reject outdated test Signed-off-by: Ivaylo Nikolov <[email protected]> * chore: comments typo and improvement Signed-off-by: Ivaylo Nikolov <[email protected]> * test: temporary skip allowance tests for NFT and FT Signed-off-by: Ivaylo Nikolov <[email protected]> * test: ignore eslint warnings for skipped tests Signed-off-by: Ivaylo Nikolov <[email protected]> * chore: add id-token permission to pages.yml workflow (#2418) Signed-off-by: Iliya Savov <[email protected]> Co-authored-by: Iliya Savov <[email protected]> Co-authored-by: Svet <[email protected]> --------- Signed-off-by: Ivaylo Nikolov <[email protected]> Signed-off-by: Alexander Gadzhalov <[email protected]> Signed-off-by: Ivan Ivanov <[email protected]> Signed-off-by: svetoslav-nikol0v <[email protected]> Signed-off-by: Iliya Savov <[email protected]> Co-authored-by: Svet <[email protected]> Co-authored-by: Ivan Ivanov <[email protected]> Co-authored-by: Iliya Savov <[email protected]> Co-authored-by: Iliya Savov <[email protected]> Co-authored-by: Alexander Gadzhalov <[email protected]>
- Loading branch information
1 parent
81fb7d0
commit 8a22ce9
Showing
10 changed files
with
2,252 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
import { | ||
AccountCreateTransaction, | ||
PrivateKey, | ||
TokenCreateTransaction, | ||
TransferTransaction, | ||
AccountId, | ||
Client, | ||
TokenType, | ||
TokenMintTransaction, | ||
TokenRejectTransaction, | ||
TokenRejectFlow, | ||
NftId, | ||
AccountBalanceQuery, | ||
TokenSupplyType, | ||
} from "@hashgraph/sdk"; | ||
import dotenv from "dotenv"; | ||
|
||
dotenv.config(); | ||
|
||
async function main() { | ||
if ( | ||
process.env.OPERATOR_ID == null || | ||
process.env.OPERATOR_KEY == null || | ||
process.env.HEDERA_NETWORK == null | ||
) { | ||
throw new Error( | ||
"Environment variables OPERATOR_ID, HEDERA_NETWORK, and OPERATOR_KEY are required.", | ||
); | ||
} | ||
const CID = [ | ||
"QmNPCiNA3Dsu3K5FxDPMG5Q3fZRwVTg14EXA92uqEeSRXn", | ||
"QmZ4dgAgt8owvnULxnKxNe8YqpavtVCXmc1Lt2XajFpJs9", | ||
"QmPzY5GxevjyfMUF5vEAjtyRoigzWp47MiKAtLBduLMC1T", | ||
]; | ||
const operatorId = AccountId.fromString(process.env.OPERATOR_ID); | ||
const operatorKey = PrivateKey.fromStringED25519(process.env.OPERATOR_KEY); | ||
const network = process.env.HEDERA_NETWORK; | ||
const client = Client.forName(network).setOperator(operatorId, operatorKey); | ||
|
||
// create a treasury account | ||
const treasuryPrivateKey = PrivateKey.generateED25519(); | ||
const treasuryAccountId = ( | ||
await ( | ||
await new AccountCreateTransaction() | ||
.setKey(treasuryPrivateKey) | ||
.setMaxAutomaticTokenAssociations(100) | ||
.execute(client) | ||
).getReceipt(client) | ||
).accountId; | ||
|
||
// create a receiver account with unlimited max auto associations | ||
const receiverPrivateKey = PrivateKey.generateED25519(); | ||
const receiverAccountId = ( | ||
await ( | ||
await new AccountCreateTransaction() | ||
.setKey(receiverPrivateKey) | ||
.setMaxAutomaticTokenAssociations(-1) | ||
.execute(client) | ||
).getReceipt(client) | ||
).accountId; | ||
|
||
// create a nft collection | ||
const nftCreationTx = await ( | ||
await new TokenCreateTransaction() | ||
.setTokenType(TokenType.NonFungibleUnique) | ||
.setTokenName("Example Fungible Token") | ||
.setTokenSymbol("EFT") | ||
.setMaxSupply(CID.length) | ||
.setSupplyType(TokenSupplyType.Finite) | ||
.setSupplyKey(operatorKey) | ||
.setAdminKey(operatorKey) | ||
.setTreasuryAccountId(treasuryAccountId) | ||
.freezeWith(client) | ||
.sign(treasuryPrivateKey) | ||
).execute(client); | ||
|
||
const nftId = (await nftCreationTx.getReceipt(client)).tokenId; | ||
console.log("NFT ID: ", nftId.toString()); | ||
|
||
// create a fungible token | ||
const ftCreationTx = await ( | ||
await new TokenCreateTransaction() | ||
.setTokenName("Example Fungible Token") | ||
.setTokenSymbol("EFT") | ||
.setInitialSupply(100000000) | ||
.setSupplyKey(operatorKey) | ||
.setAdminKey(operatorKey) | ||
.setTreasuryAccountId(treasuryAccountId) | ||
.freezeWith(client) | ||
.sign(treasuryPrivateKey) | ||
).execute(client); | ||
|
||
const ftId = (await ftCreationTx.getReceipt(client)).tokenId; | ||
console.log("FT ID: ", ftId.toString()); | ||
|
||
// mint 3 NFTs to treasury | ||
const nftSerialIds = []; | ||
for (let i = 0; i < CID.length; i++) { | ||
const { serials } = await ( | ||
await new TokenMintTransaction() | ||
.setTokenId(nftId) | ||
.addMetadata(Buffer.from(CID[i])) | ||
.execute(client) | ||
).getReceipt(client); | ||
const [serial] = serials; | ||
nftSerialIds.push(new NftId(nftId, serial)); | ||
} | ||
|
||
// transfer nfts to receiver | ||
await ( | ||
await ( | ||
await new TransferTransaction() | ||
.addNftTransfer( | ||
nftSerialIds[0], | ||
treasuryAccountId, | ||
receiverAccountId, | ||
) | ||
.addNftTransfer( | ||
nftSerialIds[1], | ||
treasuryAccountId, | ||
receiverAccountId, | ||
) | ||
.addNftTransfer( | ||
nftSerialIds[2], | ||
treasuryAccountId, | ||
receiverAccountId, | ||
) | ||
.freezeWith(client) | ||
.sign(treasuryPrivateKey) | ||
).execute(client) | ||
).getReceipt(client); | ||
|
||
// transfer fungible tokens to receiver | ||
await ( | ||
await ( | ||
await new TransferTransaction() | ||
.addTokenTransfer(ftId, treasuryAccountId, -1) | ||
.addTokenTransfer(ftId, receiverAccountId, 1) | ||
.freezeWith(client) | ||
.sign(treasuryPrivateKey) | ||
).execute(client) | ||
).getReceipt(client); | ||
|
||
console.log("======================="); | ||
console.log("Before Token Reject"); | ||
console.log("======================="); | ||
const receiverFTBalanceBefore = ( | ||
await new AccountBalanceQuery() | ||
.setAccountId(receiverAccountId) | ||
.execute(client) | ||
).tokens.get(ftId); | ||
const treasuryFTBalanceBefore = ( | ||
await new AccountBalanceQuery() | ||
.setAccountId(treasuryAccountId) | ||
.execute(client) | ||
).tokens.get(ftId); | ||
const receiverNFTBalanceBefore = ( | ||
await new AccountBalanceQuery() | ||
.setAccountId(receiverAccountId) | ||
.execute(client) | ||
).tokens.get(nftId); | ||
const treasuryNFTBalanceBefore = ( | ||
await new AccountBalanceQuery() | ||
.setAccountId(treasuryAccountId) | ||
.execute(client) | ||
).tokens.get(nftId); | ||
console.log("Receiver FT balance: ", receiverFTBalanceBefore.toInt()); | ||
console.log("Treasury FT balance: ", treasuryFTBalanceBefore.toInt()); | ||
console.log( | ||
"Receiver NFT balance: ", | ||
receiverNFTBalanceBefore ? receiverNFTBalanceBefore.toInt() : 0, | ||
); | ||
console.log("Treasury NFT balance: ", treasuryNFTBalanceBefore.toInt()); | ||
|
||
// reject fungible tokens back to treasury | ||
const tokenRejectResponse = await ( | ||
await ( | ||
await new TokenRejectTransaction() | ||
.setOwnerId(receiverAccountId) | ||
.addTokenId(ftId) | ||
.freezeWith(client) | ||
.sign(receiverPrivateKey) | ||
).execute(client) | ||
).getReceipt(client); | ||
|
||
// reject NFTs back to treasury | ||
const rejectFlowResponse = await ( | ||
await ( | ||
await new TokenRejectFlow() | ||
.setOwnerId(receiverAccountId) | ||
.setNftIds(nftSerialIds) | ||
.freezeWith(client) | ||
.sign(receiverPrivateKey) | ||
).execute(client) | ||
).getReceipt(client); | ||
|
||
const tokenRejectStatus = tokenRejectResponse.status.toString(); | ||
const tokenRejectFlowStatus = rejectFlowResponse.status.toString(); | ||
|
||
console.log("======================="); | ||
console.log("After Token Reject Transaction and flow"); | ||
console.log("======================="); | ||
|
||
const receiverFTBalanceAfter = ( | ||
await new AccountBalanceQuery() | ||
.setAccountId(receiverAccountId) | ||
.execute(client) | ||
).tokens.get(ftId); | ||
|
||
const treasuryFTBalanceAfter = ( | ||
await new AccountBalanceQuery() | ||
.setAccountId(treasuryAccountId) | ||
.execute(client) | ||
).tokens.get(ftId); | ||
|
||
const receiverNFTBalanceAfter = ( | ||
await new AccountBalanceQuery() | ||
.setAccountId(receiverAccountId) | ||
.execute(client) | ||
).tokens.get(nftId); | ||
|
||
const treasuryNFTBalanceAfter = ( | ||
await new AccountBalanceQuery() | ||
.setAccountId(treasuryAccountId) | ||
.execute(client) | ||
).tokens.get(nftId); | ||
|
||
console.log("TokenReject response:", tokenRejectStatus); | ||
console.log("TokenRejectFlow response:", tokenRejectFlowStatus); | ||
console.log("Receiver FT balance: ", receiverFTBalanceAfter.toInt()); | ||
console.log("Treasury FT balance: ", treasuryFTBalanceAfter.toInt()); | ||
console.log( | ||
"Receiver NFT balance: ", | ||
receiverNFTBalanceAfter ? receiverNFTBalanceAfter.toInt() : 0, | ||
); | ||
console.log("Treasury NFT balance: ", treasuryNFTBalanceAfter.toInt()); | ||
|
||
client.close(); | ||
} | ||
|
||
void main(); |
Submodule proto
updated
21 files
+28 −5 | .github/CODEOWNERS | |
+341 −0 | platform/state/platform_state.proto | |
+1 −9 | services/address_book_service.proto | |
+83 −2 | services/basic_types.proto | |
+12 −0 | services/node_create.proto | |
+0 −214 | services/node_get_info.proto | |
+16 −3 | services/node_update.proto | |
+0 −15 | services/query.proto | |
+0 −10 | services/response.proto | |
+105 −46 | services/response_code.proto | |
+38 −0 | services/schedulable_transaction_body.proto | |
+9 −0 | services/state/addressbook/node.proto | |
+11 −0 | services/state/token/account.proto | |
+70 −0 | services/state/token/account_pending_airdrop.proto | |
+100 −0 | services/token_airdrop.proto | |
+60 −0 | services/token_cancel_airdrop.proto | |
+64 −0 | services/token_claim_airdrop.proto | |
+89 −0 | services/token_reject.proto | |
+59 −0 | services/token_service.proto | |
+38 −0 | services/transaction_body.proto | |
+33 −0 | services/transaction_record.proto |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import NftId from "./NftId.js"; | ||
import TokenId from "./TokenId.js"; | ||
|
||
/** | ||
* @namespace proto | ||
* @typedef {import("@hashgraph/proto").proto.TokenReference} HashgraphProto.proto.TokenReference | ||
*/ | ||
|
||
export default class TokenReference { | ||
constructor() { | ||
/** | ||
* @public | ||
* @type {?TokenId} | ||
*/ | ||
this.fungibleToken = null; | ||
/** | ||
* @public | ||
* @type {?NftId} | ||
*/ | ||
this.nft = null; | ||
} | ||
|
||
/** | ||
* @public | ||
* @param {HashgraphProto.proto.TokenReference} reference | ||
* @returns {TokenReference} | ||
*/ | ||
static _fromProtobuf(reference) { | ||
return { | ||
fungibleToken: | ||
reference.fungibleToken != undefined | ||
? TokenId._fromProtobuf(reference.fungibleToken) | ||
: null, | ||
nft: | ||
reference.nft != undefined | ||
? NftId._fromProtobuf(reference.nft) | ||
: null, | ||
}; | ||
} | ||
} |
Oops, something went wrong.