Mint TIP-3 Tokens
In previous section we have learned to deploy a token root and wallet using the our custom contract.
In this section we will learn the how to mint TIP-3 tokens for a deployed token wallet, it's pretty easy and straight forward, you just need to pay attention to a few small points.
TIP
- Notice that the owner of the deployed Token Wallet is the
MultiWalletTIP3
contract that we deployed earlier. - the
notify
parameter is always true inMultiWalletTIP3
in order to receive callback function from the token root and update the state of theMultiWalletTIP3
contract. - We send the
mint
transaction to thetoken root
contract, so how do we update theMultiWalletTIP3
contract state ?
There is a callback function namedonAcceptTokensMint
which will be called on theMultiWalletTIP-3
by the token wallet and updates its state when the tokens are minted if we set the parameternotify
to true !
Step 1: Write Minting Script
We can mint TIP-3 tokens for the target Token Wallet, as shown in the code samples below using the locklift tool.
We use the previously written script stats from the deploy token wallet section for the following script.
INFO
- Before we start to write our scripts we need to make sure that there is a file named
05-mint-tip3.ts
in thescript
folder in the project root.
Minting TIP-3 tokens using everscale-inpage-provider is pretty easy as well:
INFO
- You may find the following code sample a bit complex, that's because we want to get familiar with the multi wallet functionalities and how to use them.
/* Minting TIP-3 tokens using multi wallet contract */
// Defining the parameters for minting tip-3 tokens
const mintAmount: number =
50 * 10 ** deployRootFromDeployerParams.decimals;
console.log(
'balance before mint:',
(
await getWalletData(
aliceMultiWalletContract,
tokenRootContract.address
)
).balance /
10 ** deployRootFromDeployerParams.decimals
);
// Minting tokens for receiver
await tokenRootContract.methods
.mint({
amount: mintAmount,
recipient: aliceMultiWalletContract.address, // the owner of the token wallet is the MW contract
deployWalletValue: 0,
notify: true, // To update the Multi Wallet contract
payload: '',
remainingGasTo: aliceAccount.address,
})
.send({
from: aliceAccount.address,
amount: locklift.utils.toNano(5),
});
// confirming that its minted
console.log(
'balance after mint:',
(
await getWalletData(
aliceMultiWalletContract,
tokenRootContract.address
)
).balance /
10 ** deployRootFromDeployerParams.decimals
);
import {
ProviderRpcClient,
Address,
Transaction,
Contract,
} from 'everscale-inpage-provider';
import * as tip3Artifacts from 'tip3-docs-artifacts';
import { provider, providerAddress } from './useProvider';
// We use the getWalletData function to extract the token wallet data from the multi wallet contract
async function getWalletData(
MWContract: Contract<
tip3Artifacts.FactorySource['MultiWalletTIP3']
>,
tokenRootAddress: Address
): Promise<{ tokenWallet: Address; balance: number }> {
// Returned value of the wallets mapping on the multi wallet tip-3 contract
const walletData = (
await MWContract.methods.wallets().call()
).wallets.map(item => {
if (item[0].toString() == tokenRootAddress.toString()) {
return item[1];
}
});
let balance: number = 0;
let tokenWallet: Address = tip3Artifacts.zeroAddress;
if (walletData.length != 0) {
balance = Number(walletData[0]!.balance);
tokenWallet = walletData[0]!.tokenWallet;
}
return { tokenWallet: tokenWallet, balance: balance };
}
async function main() {
// Required contracts addresses
const tokenRootAddress: Address = new Address(
'<YOUR_TOKEN_ROOT_ADDRESS>'
);
const multiWalletAddress: Address = new Address(
'<YOUR_MULTI_WALLET_ADDRESS>'
);
try {
// creating an instance of the required contracts
const tokenRootContract: Contract<
tip3Artifacts.FactorySource['TokenRoot']
> = new provider.Contract(
tip3Artifacts.factorySource['TokenRoot'],
tokenRootAddress
);
const MultiWalletContract: Contract<
tip3Artifacts.FactorySource['MultiWalletTIP3']
> = new provider.Contract(
tip3Artifacts.factorySource['MultiWalletTIP3'],
multiWalletAddress
);
// Fetching the decimals and symbol
const [decimals, symbol] = await Promise.all([
Number(
(
await tokenRootContract.methods
.decimals({ answerId: 0 })
.call()
).value0
),
(await tokenRootContract.methods.symbol({ answerId: 0 }).call())
.value0,
]);
// Defining the mint amount
const mintAmount: number = 50 * 10 ** decimals;
// Checking if the user already has a token wallet associated with the token root
let tokenWalletData = await getWalletData(
MultiWalletContract,
tokenRootContract.address
);
// Defining the deployWalletValue
let deployWalletValue: number = 0;
// Fetching the balance before minting tokens
const oldBal: number =
Number(tokenWalletData.balance) / 10 ** decimals;
// Checking the if the user already has an token wallet of the target token root and accordingly setting the deployWalletValue to deploy onw for the user if doesn't have any
if (
tokenWalletData.tokenWallet.toString() ==
tip3Artifacts.zeroAddress.toString()
) {
deployWalletValue = 2 * 10 ** 9;
}
// Defining the transaction fee
const txFee: string = String(2 * 10 ** 9 + deployWalletValue);
// Minting tokens fo the receiver
const mintRes: Transaction = await tokenRootContract.methods
.mint({
amount: mintAmount,
deployWalletValue: deployWalletValue,
remainingGasTo: providerAddress,
recipient: multiWalletAddress,
notify: true, /// @dev it's very important to update the MW contract state
payload: '',
})
.send({
from: providerAddress,
amount: txFee,
bounce: true,
});
// Throwing an error if the transaction was aborted
if (mintRes.aborted) {
throw new Error(
`Transaction aborted ! ${
(mintRes.exitCode, mintRes.resultCode)
}`
);
}
// Fetching the wallet data and balance after the mint is done
tokenWalletData = await getWalletData(
MultiWalletContract,
tokenRootContract.address
);
const newBal: number =
Number(tokenWalletData.balance) / 10 ** decimals;
// Checking if the tokens are minted successfully for th receiver
if (newBal >= oldBal) {
console.log(`${mintAmount} ${symbol}'s minted successfully `);
return `Old balance: ${oldBal} \n New balance: ${newBal}`;
} else {
throw new Error(
`Failed ${(mintRes.exitCode, mintRes.resultCode)}`
);
}
} catch (e: any) {
throw new Error(`Failed ${e.message}`);
}
}
Step 2: Mint TIP-3 tokens
Use this command to mint TIP-3 tokens:
npx locklift run -s ./scripts/05-mint-tip3.ts -n local
Congratulations, you have successfully minted TIP-3 tokens for a token wallet deployed by a custom contract 🎉
Token Root address
Multi Wallet (recipient) address
Amount