Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example/hip 573 #1292

Merged
merged 4 commits into from
Oct 14, 2022
Merged
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
280 changes: 280 additions & 0 deletions examples/exempt-custom-fees.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
import {
AccountId,
PrivateKey,
TokenCreateTransaction,
TokenType,
TransferTransaction,
CustomFractionalFee,
Hbar,
AccountCreateTransaction,
LocalProvider,
Wallet,
AccountBalanceQuery
} from "@hashgraph/sdk";


import dotenv from "dotenv";

dotenv.config();


/*
Example for HIP-573: Blanket exemptions for custom fee collectors

1. Create accounts A, B, and C
2. Create a fungible token that has three fractional fees
Fee #1 sends 1/100 of the transferred value to collector 0.0.A.
Fee #2 sends 2/100 of the transferred value to collector 0.0.B.
Fee #3 sends 3/100 of the transferred value to collector 0.0.C.
3. Collector 0.0.B sends 10_000 units of the token to 0.0.A.
4. Get the transaction fee for that transfer transaction
5. Show that the fee collector accounts in the custom fee list of the token
that was created was not charged a custom fee in the transfer

*/

async function main() {

// Configure accounts and client, and generate needed keys
const operatorId = AccountId.fromString(process.env.OPERATOR_ID);
const operatorKey = PrivateKey.fromString(process.env.OPERATOR_KEY);


// If we weren't able to get them, we should throw a new error
if (operatorId == null || operatorKey == null ) {
throw new Error("Could not fetch 'operatorId' and 'operatorKey' properly");
}


const wallet = new Wallet(
operatorId,
operatorKey,
new LocalProvider()
);

/** Example 1
*
* Step 1
*
* Create accounts A, B, and C
*/


let firstAccountPrivateKey = PrivateKey.generateED25519();
let firstAccountPublicKey = firstAccountPrivateKey.publicKey;

let createAccountAtx = await new AccountCreateTransaction()
.setKey(firstAccountPublicKey)
.setInitialBalance(Hbar.fromString("1000"))
.freezeWithSigner(wallet);
createAccountAtx = await createAccountAtx.signWithSigner(wallet);

let firstResponse = await createAccountAtx.executeWithSigner(wallet);
const firstAccountId = (await firstResponse.getReceiptWithSigner(wallet)).accountId;

const firstAccountWallet = new Wallet(
firstAccountId,
firstAccountPrivateKey,
new LocalProvider()
);

let secondAccountPrivateKey = PrivateKey.generateED25519();
let secondAccountPublicKey = secondAccountPrivateKey.publicKey;

let createAccountBtx = await new AccountCreateTransaction()
.setKey(secondAccountPublicKey)
.setInitialBalance(Hbar.fromString("1000"))
.freezeWithSigner(wallet);
createAccountBtx = await createAccountBtx.signWithSigner(wallet);

let secondResponse = await createAccountBtx.executeWithSigner(wallet);
const secondAccountId = (await secondResponse.getReceiptWithSigner(wallet)).accountId;

const secondAccountWallet = new Wallet(
secondAccountId,
secondAccountPrivateKey,
new LocalProvider()
);


let thirdAccountPrivateKey = PrivateKey.generateED25519();
let thirdAccountPublicKey = thirdAccountPrivateKey.publicKey;

let createAccountCtx = await new AccountCreateTransaction()
.setKey(thirdAccountPublicKey)
.setInitialBalance(Hbar.fromString("1000"))
.freezeWithSigner(wallet);
createAccountCtx = await createAccountCtx.signWithSigner(wallet);

let thirdResponse = await createAccountCtx.executeWithSigner(wallet);
const thirdAccountId = (await thirdResponse.getReceiptWithSigner(wallet)).accountId;

const thirdAccountWallet = new Wallet(
thirdAccountId,
thirdAccountPrivateKey,
new LocalProvider()
);


let firstAccountBalanceBefore = (
await new AccountBalanceQuery()
.setAccountId(firstAccountId)
.executeWithSigner(wallet)
)
.hbars.toString();

let secondAccountBalanceBefore = (
await new AccountBalanceQuery()
.setAccountId(secondAccountId)
.executeWithSigner(wallet)
)
.hbars.toString();

let thirdAccountBalanceBefore = (
await new AccountBalanceQuery()
.setAccountId(thirdAccountId)
.executeWithSigner(wallet)
)
.hbars.toString();

console.log(`First account balance before TransferTransaction: ${firstAccountBalanceBefore}`);
console.log(`Second account balance before TransferTransaction: ${secondAccountBalanceBefore}`);
console.log(`Third account balance before TransferTransaction: ${thirdAccountBalanceBefore}`);


/**
* Step 2
*
* 2. Create a fungible token that has three fractional fees
* Fee #1 sends 1/100 of the transferred value to collector 0.0.A.
* Fee #2 sends 2/100 of the transferred value to collector 0.0.B.
* Fee #3 sends 3/100 of the transferred value to collector 0.0.C.
*/

const fee = new CustomFractionalFee()
.setFeeCollectorAccountId(firstAccountId)
.setNumerator(1)
.setDenominator(100);

const fee2 = new CustomFractionalFee()
.setFeeCollectorAccountId(secondAccountId)
.setNumerator(2)
.setDenominator(100);

const fee3 = new CustomFractionalFee()
.setFeeCollectorAccountId(thirdAccountId)
.setNumerator(3)
.setDenominator(100);


let tokenCreateTx = await new TokenCreateTransaction()
.setTokenName("HIP-573 Token")
.setTokenSymbol("H573")
.setTokenType(TokenType.FungibleCommon)
.setTreasuryAccountId(secondAccountWallet.getAccountId())
.setAutoRenewAccountId(wallet.getAccountId())
.setAdminKey(wallet.getAccountKey())
.setFreezeKey(wallet.getAccountKey())
.setWipeKey(wallet.getAccountKey())
.setInitialSupply(100000000) // Total supply = 100000000 / 10 ^ 2
.setDecimals(2)
.setCustomFees([fee, fee2, fee3])
.freezeWithSigner(wallet);


// TokenCreateTransaction should be also signed with all of the fee collector wallets
// in the custom fee list of the token before executing the transaction
tokenCreateTx = await tokenCreateTx.signWithSigner(wallet);
tokenCreateTx = await tokenCreateTx.signWithSigner(firstAccountWallet);
tokenCreateTx = await tokenCreateTx.signWithSigner(secondAccountWallet);
tokenCreateTx = await tokenCreateTx.signWithSigner(thirdAccountWallet);

// Submit the transaction to the Hedera network
let tokenCreateSubmit = await tokenCreateTx.executeWithSigner(wallet);
console.log(`response`);
console.log(tokenCreateSubmit);
console.log(tokenCreateTx);


// Get transaction receipt information
let tokenCreateRx = await tokenCreateSubmit.getReceiptWithSigner(wallet);
let tokenId = tokenCreateRx.tokenId;
console.log(`Created token with token id: ${tokenId.toString()} \n`);


/**
* Step 3
*
* Collector 0.0.B sends 10_000 units of the token to 0.0.A.
*/

let tokenTransferTx = await new TransferTransaction()
.addTokenTransfer(tokenId, secondAccountId, -10000)
.addTokenTransfer(tokenId, firstAccountId, 10000)
.freezeWithSigner(wallet);


// Sign the transaction also with the wallet of the sender
tokenTransferTx = await tokenTransferTx.signWithSigner(wallet);
tokenTransferTx = await tokenTransferTx.signWithSigner(secondAccountWallet);

// Submit the transaction to the Hedera network
let tokenTransferSubmit = await tokenTransferTx.executeWithSigner(wallet);


/**
* Step 4
*
* Get the transaction fee for that transfer transaction
*/

// Get transaction record information
let transactionFee = (await tokenTransferSubmit.getRecordWithSigner(wallet)).transactionFee;

console.log(`Transaction fee: ${transactionFee}`);


/**
* Step 5
*
* Show that the fee collector accounts in the custom fee list
* of the token that was created was not charged a custom fee in the transfer
*/


let firstAccountBalanceAfter = (
await new AccountBalanceQuery()
.setAccountId(firstAccountId)
.executeWithSigner(wallet)
)
.hbars.toString();

let secondAccountBalanceAfter = (
await new AccountBalanceQuery()
.setAccountId(secondAccountId)
.executeWithSigner(wallet)
)
.hbars.toString();

let thirdAccountBalanceAfter = (
await new AccountBalanceQuery()
.setAccountId(thirdAccountId)
.executeWithSigner(wallet)
)
.hbars.toString();

console.log(`First account balance after TransferTransaction: ${firstAccountBalanceAfter}`);
console.log(`Second account balance after TransferTransaction: ${secondAccountBalanceAfter}`);
console.log(`Third account balance after TransferTransaction: ${thirdAccountBalanceAfter}`);


if (firstAccountBalanceBefore === firstAccountBalanceAfter
&& secondAccountBalanceBefore === secondAccountBalanceAfter
&& thirdAccountBalanceBefore === thirdAccountBalanceAfter) {

console.log(`Fee collector accounts were not charged after transfer transaction`);
}

}

void main();