Overview
This tutorial application allows token owners to issue their security token to whitelisted investors. You may also burn tokens, if needed. You should be able to:
Import and Export CSV with investor addresses and balances.
Mint tokens to investors.
The CSV that represents issuance has the following format:
Copy address, balance
0x0439...8fj4 1200
0xjf73...hf73 400
Copy // Processes imported text into tokenholder objects, then sends blockchain transaction to
// issue tokens to uploaded tokenholders.
const importData = (data) => {
// Split file content into lines
data = data.split('\r\n')
// Trim lines
.map(record => record.trim())
// Remove empty lines
.filter(record => record.length)
// Convert string amounts to BigNumber.
.map(record => {
let [address, amount] = record.split(',')
return {address, amount: new BigNumber(amount)}
})
asyncAction(dispatch, () => issueTokens(data), 'Issuing tokens')
}
To issue tokens, simply call the SDK's token.issuance.issue
method.
Copy const issueTokens = async (records) => {
const q = await token.issuance.issue({issuanceData: records})
await q.run()
await new Promise(resolve => setTimeout(resolve, 1000))
dispatch({type: 'RELOAD_TOKENHOLDERS'})
}
You will have the data needed in state store (i.e., records
). You simply need to concatenate that data into a CSV file.
Copy const exportData = () => {
const csvContent = records.map(({address, balance}) => {
return [address, balance].join(',')
}).join('\r\n')
console.log('csvContent', csvContent)
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8' })
FileSaver.saveAs(blob, 'whitelist.csv')
}
Burning tokens is as intuitive as specifying the amount
, address
, and reason
for burning in each call.
Copy // Async action
const burnTokens = async (amount, from, reason = '') => {
asyncAction(
dispatch,
() => controllerRedeem(amount, from, reason),
`Burning ${amount} tokens from ${from}`
)
}
const controllerRedeem = async (amount, from, reason) => {
reason = web3Utils.numberToHex(reason)
amount = new BigNumber(amount)
while (true) {
// Try to redeem tokens...
try {
const q = await token.controller.redeem({ amount, from, reason })
await q.run()
dispatch({type: 'RELOAD_TOKENHOLDERS'})
return
}
// ...unless current user is not a controller. In that case, add them as a controller first.
catch (error) {
if (error.message.includes('You must be the controller')) {
console.log(`Add ${walletAddress} as controller`)
const addControllerQ = await token.controller.modifyController({controller: walletAddress})
await addControllerQ.run()
}
else {
dispatch({type: 'ERROR', error: error.message})
return
}
}
}
}