Skip to content

Commit

Permalink
Example/hip 573 (hashgraph#1292)
Browse files Browse the repository at this point in the history
* init exempt custom fees example

* creating accounts properly

* minor refactoring

* added check if the balances match after execution
  • Loading branch information
petreze authored Oct 14, 2022
1 parent d09919d commit fb4cd6a
Showing 1 changed file with 280 additions and 0 deletions.
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();

0 comments on commit fb4cd6a

Please sign in to comment.