Created
November 19, 2019 17:00
-
-
Save sudoaza/1803abb81ba54492852e540f1e70b718 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
const { | |
BaseTransaction, | |
TransactionError, | |
utils | |
} = require('@liskhq/lisk-transactions'); | |
/** | |
* Send tokens to multiple recipients. | |
*/ | |
class MultiSendTransaction extends BaseTransaction { | |
static get TYPE () { | |
return 42; | |
} | |
static get FEE () { | |
return `${2*10**6}`; | |
}; | |
async prepare(store) { | |
let accounts = [{ address: this.senderId }]; | |
accounts.push(...this.asset.recipients); | |
await store.account.cache(accounts); | |
} | |
validateAsset() { | |
const errors = []; | |
// Check we have necesary parameters | |
if (!this.asset.recipients || !this.asset.recipients.length || !this.asset.amounts || !this.asset.amounts.length) { | |
errors.push( | |
new TransactionError( | |
'A valid transaction should have a list of recipients and a list of amounts', | |
this.id, | |
'.recipients', | |
this.asset.recipients, | |
'.amounts', | |
this.asset.amounts | |
) | |
); | |
return errors; | |
} | |
// Check recipient count is valid | |
if (this.asset.recipients.length < 2 || this.asset.recipients.length > 10) { | |
errors.push( | |
new TransactionError( | |
'Recipients should have between 2 and 10 entries', | |
this.id, | |
'.recipients', | |
this.asset.recipients | |
) | |
); | |
} | |
// Check no duplicate recipient | |
if ((new Set(this.asset.recipients)).size != this.asset.recipients.length) { | |
errors.push( | |
new TransactionError( | |
'Recipients cannot have duplicate entries', | |
this.id, | |
'.recipients', | |
this.asset.recipients | |
) | |
); | |
} | |
// Check sender not in recipients list | |
if (this.asset.recipients.includes(this.senderId)) { | |
errors.push( | |
new TransactionError( | |
'Sender cannot be among recipients', | |
this.id, | |
'.recipients', | |
this.asset.recipients | |
) | |
); | |
} | |
// Check amounts count is valid | |
if (this.asset.amounts.length < 2 || this.asset.amounts.length > 10) { | |
errors.push( | |
new TransactionError( | |
'Amounts should have between 2 and 10 entries', | |
this.id, | |
'.amounts', | |
this.asset.amounts | |
) | |
); | |
} | |
// Check same amount of balances as recipients | |
if (this.asset.recipients.length != this.asset.amounts.length) { | |
errors.push( | |
new TransactionError( | |
'Recipients length doesn\'t match amounts length', | |
this.id, | |
'.recipients', | |
this.asset.recipients | |
) | |
); | |
} | |
// All recipientId should be string | |
this.asset.recipients.forEach((recipientId, idx) => { | |
if (!recipientId || typeof recipientId !== 'string') { | |
errors.push( | |
new TransactionError( | |
'Invalid "recipientId" defined on transaction', | |
this.id, | |
'.recipients[]', | |
recipientId | |
) | |
); | |
} | |
}); | |
// All amounts should be numeric and above 0 | |
this.asset.amounts.forEach((amount, idx) => { | |
if (!amount || typeof amount !== 'number' || new utils.BigNum(amount) <= 0) { | |
errors.push( | |
new TransactionError( | |
'Invalid "amount" defined on transaction, should be numeric and greater than 0', | |
this.id, | |
'.amounts[]', | |
amount | |
) | |
); | |
} | |
}); | |
return errors; | |
} | |
applyAsset(store) { | |
const errors = []; | |
const balance = new utils.BigNum(sender.balance); | |
const sentAmount = this.asset.amounts.reduce((accumulator, currValue) =>{ | |
return accumulator.add(new utils.BigNum(currValue)); | |
}, new utils.BigNum(0)); | |
const updatedSenderBalance = balance.sub(sentAmount); | |
if (updatedSenderBalance < 0) { | |
errors.push( | |
new TransactionError( | |
'Not enough funds for transaction', | |
this.id, | |
'total amount', | |
sent_amount | |
) | |
); | |
return errors; | |
} | |
// Update sender balance | |
const sender = store.account.get(this.senderId); | |
const updatedSender = { | |
...sender, | |
balance: updatedSenderBalance.toString(), | |
}; | |
store.account.set(sender.address, updatedSender); | |
// Update recipients balances | |
this.asset.amounts.forEach((amount, idx) => { | |
this.sendTokens(recipients[idx], amount); | |
}); | |
return errors; | |
} | |
undoAsset(store) { | |
const errors = []; | |
return errors; | |
} | |
sendTokens(recipientId, amount) { | |
const recipient = store.account.get(recipientId); | |
const updatedRecipientBalance = new utils.BigNum(recipient.balance).add(new utils.BigNum(amount)); | |
const updatedRecipient = { | |
...recipient, | |
balance: updatedRecipientBalance.toString(), | |
}; | |
store.account.set(recipient.address, updatedRecipient); | |
} | |
} | |
module.exports = MultiSendTransaction; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment