Skip to content

Commit f97a2ae

Browse files
authored
feat(AE): Allow to spend % of balance. (#371)
#336
1 parent 5909161 commit f97a2ae

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

es/ae/index.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ import stampit from '@stamp/it'
2626
import Tx from '../tx'
2727
import Chain from '../chain'
2828
import Account from '../account'
29+
import TxBuilder from '../tx/builder'
2930
import * as R from 'ramda'
31+
import { BigNumber } from 'bignumber.js'
3032

3133
/**
3234
* Sign and post a transaction to the chain
@@ -60,6 +62,38 @@ async function spend (amount, recipientId, options = {}) {
6062
return this.send(spendTx, opt)
6163
}
6264

65+
/**
66+
* Send a percentage of funds to another account
67+
* @instance
68+
* @category async
69+
* @rtype (percentage: Number|String, recipientId: String, options?: Object) => Promise[String]
70+
* @param {Number|String} percentage - Percentage of amount to spend
71+
* @param {String} recipientId - Address of recipient account
72+
* @param {Object} options - Options
73+
* @return {String|String} Transaction or transaction hash
74+
*/
75+
async function transferFunds (percentage, recipientId, options = { excludeFee: false }) {
76+
if (percentage < 0 || percentage > 1) throw new Error(`Percentage should be a number between 0 and 1, got ${percentage}`)
77+
const opt = R.merge(this.Ae.defaults, options)
78+
79+
const requestTransferAmount = BigNumber(await this.balance(await this.address())).times(percentage)
80+
let spendTx = await this.spendTx(R.merge(opt, { senderId: await this.address(), recipientId, amount: requestTransferAmount }))
81+
82+
const { tx: txObject } = TxBuilder.unpackTx(spendTx)
83+
// If the requestTransferAmount should include the fee keep calculating the fee
84+
let amount = requestTransferAmount
85+
if (!options.excludeFee) {
86+
while (amount.plus(txObject.fee).gt(requestTransferAmount)) {
87+
amount = requestTransferAmount.minus(txObject.fee)
88+
}
89+
}
90+
91+
// Rebuild tx
92+
spendTx = await this.spendTx(R.merge(opt, { senderId: await this.address(), recipientId, amount }))
93+
94+
return this.send(spendTx, opt)
95+
}
96+
6397
/**
6498
* Remove all listeners for RPC
6599
* @instance
@@ -90,7 +124,7 @@ function destroyInstance () {
90124
* @return {Object} Ae instance
91125
*/
92126
const Ae = stampit(Tx, Account, Chain, {
93-
methods: { send, spend, destroyInstance }
127+
methods: { send, spend, transferFunds, destroyInstance }
94128
})
95129

96130
export default Ae

test/integration/accounts.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ describe('Accounts', function () {
5252
return wallet.balance(await wallet.address()).should.eventually.be.a('string')
5353
})
5454

55+
it('Spend 50% of balance', async () => {
56+
const balance = await wallet.balance(await wallet.address())
57+
58+
await wallet.transferFunds(0.5, 'ak_DMNCzsVoZnpV5fe8FTQnNsTfQ48YM5C3WbHPsJyHjAuTXebFi')
59+
const balanceAfter = await wallet.balance(await wallet.address())
60+
BigNumber(balance).div(balanceAfter).toNumber().should.be.equal(2)
61+
})
62+
5563
it('spends tokens', async () => {
5664
const ret = await wallet.spend(1, receiver)
5765
ret.should.have.property('tx')

0 commit comments

Comments
 (0)