diff --git a/es/ae/index.js b/es/ae/index.js index 04783f64ba..99f0fe60bf 100644 --- a/es/ae/index.js +++ b/es/ae/index.js @@ -26,7 +26,9 @@ import stampit from '@stamp/it' import Tx from '../tx' import Chain from '../chain' import Account from '../account' +import TxBuilder from '../tx/builder' import * as R from 'ramda' +import { BigNumber } from 'bignumber.js' /** * Sign and post a transaction to the chain @@ -60,6 +62,38 @@ async function spend (amount, recipientId, options = {}) { return this.send(spendTx, opt) } +/** + * Send a percentage of funds to another account + * @instance + * @category async + * @rtype (percentage: Number|String, recipientId: String, options?: Object) => Promise[String] + * @param {Number|String} percentage - Percentage of amount to spend + * @param {String} recipientId - Address of recipient account + * @param {Object} options - Options + * @return {String|String} Transaction or transaction hash + */ +async function transferFunds (percentage, recipientId, options = { excludeFee: false }) { + if (percentage < 0 || percentage > 1) throw new Error(`Percentage should be a number between 0 and 1, got ${percentage}`) + const opt = R.merge(this.Ae.defaults, options) + + const requestTransferAmount = BigNumber(await this.balance(await this.address())).times(percentage) + let spendTx = await this.spendTx(R.merge(opt, { senderId: await this.address(), recipientId, amount: requestTransferAmount })) + + const { tx: txObject } = TxBuilder.unpackTx(spendTx) + // If the requestTransferAmount should include the fee keep calculating the fee + let amount = requestTransferAmount + if (!options.excludeFee) { + while (amount.plus(txObject.fee).gt(requestTransferAmount)) { + amount = requestTransferAmount.minus(txObject.fee) + } + } + + // Rebuild tx + spendTx = await this.spendTx(R.merge(opt, { senderId: await this.address(), recipientId, amount })) + + return this.send(spendTx, opt) +} + /** * Remove all listeners for RPC * @instance @@ -90,7 +124,7 @@ function destroyInstance () { * @return {Object} Ae instance */ const Ae = stampit(Tx, Account, Chain, { - methods: { send, spend, destroyInstance } + methods: { send, spend, transferFunds, destroyInstance } }) export default Ae diff --git a/test/integration/accounts.js b/test/integration/accounts.js index c4cb79f3ca..2031429e9f 100644 --- a/test/integration/accounts.js +++ b/test/integration/accounts.js @@ -52,6 +52,14 @@ describe('Accounts', function () { return wallet.balance(await wallet.address()).should.eventually.be.a('string') }) + it('Spend 50% of balance', async () => { + const balance = await wallet.balance(await wallet.address()) + + await wallet.transferFunds(0.5, 'ak_DMNCzsVoZnpV5fe8FTQnNsTfQ48YM5C3WbHPsJyHjAuTXebFi') + const balanceAfter = await wallet.balance(await wallet.address()) + BigNumber(balance).div(balanceAfter).toNumber().should.be.equal(2) + }) + it('spends tokens', async () => { const ret = await wallet.spend(1, receiver) ret.should.have.property('tx')