1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | import { describe, it, before } from 'mocha'
|
19 | import { getSdk, BaseAe, networkId } from './'
|
20 | import { generateKeyPair } from '../../es/utils/crypto'
|
21 | import BigNumber from 'bignumber.js'
|
22 | import MemoryAccount from '../../es/account/memory'
|
23 | import { AE_AMOUNT_FORMATS } from '../../es/utils/amount-formatter'
|
24 |
|
25 | describe('Accounts', function () {
|
26 | let wallet
|
27 |
|
28 | before(async function () {
|
29 | wallet = await getSdk()
|
30 | })
|
31 |
|
32 | const receiverKey = generateKeyPair()
|
33 | const receiver = receiverKey.publicKey
|
34 |
|
35 | describe('fails on unknown keypairs', () => {
|
36 | let wallet
|
37 |
|
38 | before(async function () {
|
39 | wallet = await getSdk()
|
40 | await wallet.addAccount(MemoryAccount({ keypair: generateKeyPair() }), { select: true })
|
41 | })
|
42 |
|
43 | it('determining the balance using deprecated `balance` method', async () => {
|
44 | return wallet.balance(await wallet.address()).should.be.rejectedWith(Error)
|
45 | })
|
46 |
|
47 | it('determining the balance', async () => {
|
48 | return wallet.getBalance(await wallet.address()).should.eventually.be.equal('0')
|
49 | })
|
50 |
|
51 | it('spending tokens', async () => {
|
52 | return wallet.spend(1, receiver).should.be.rejectedWith(Error)
|
53 | })
|
54 |
|
55 | it('spending minus amount of tokens', async () => {
|
56 | try {
|
57 | await wallet.spend(-1, receiver)
|
58 | } catch (e) {
|
59 | e.message.should.be.equal('Transaction build error. {"amount":"-1 must be >= 0"}')
|
60 | }
|
61 | })
|
62 | })
|
63 |
|
64 | it('determines the balance using `balance`', async () => {
|
65 | return wallet.balance(await wallet.address()).should.eventually.be.a('string')
|
66 | })
|
67 |
|
68 | describe('transferFunds', async () => {
|
69 | const spend = async fraction => {
|
70 | const balanceBefore = new BigNumber(await wallet.balance(await wallet.address()))
|
71 | const { tx } = await wallet.transferFunds(fraction, receiver)
|
72 | const balanceAfter = new BigNumber(await wallet.balance(await wallet.address()))
|
73 | return {
|
74 | balanceBefore,
|
75 | balanceAfter,
|
76 | amount: new BigNumber(tx.amount),
|
77 | fee: new BigNumber(tx.fee)
|
78 | }
|
79 | }
|
80 |
|
81 | it('throws exception if fraction is out of range', () => wallet.transferFunds(-1, receiver)
|
82 | .should.be.rejectedWith(/Fraction should be a number between 0 and 1, got/))
|
83 |
|
84 | it('spends 0% of balance', async () => {
|
85 | const { balanceBefore, balanceAfter, amount } = await spend(0)
|
86 | balanceBefore.should.be.not.eql(balanceAfter)
|
87 | amount.isZero().should.be.equal(true)
|
88 | })
|
89 |
|
90 | it('spends 68.97% of balance', async () => {
|
91 | const { balanceBefore, balanceAfter, amount, fee } = await spend(0.6897)
|
92 | balanceBefore.times(0.6897).integerValue(BigNumber.ROUND_HALF_UP).should.be.eql(amount)
|
93 | balanceAfter.plus(amount).plus(fee).should.be.eql(balanceBefore)
|
94 | })
|
95 |
|
96 | it('spends 100% of balance', async () => {
|
97 | const { balanceBefore, balanceAfter, amount, fee } = await spend(1)
|
98 | amount.plus(fee).should.be.eql(balanceBefore)
|
99 | balanceAfter.isZero().should.be.equal(true)
|
100 | })
|
101 |
|
102 | it('accepts onAccount option', async () => {
|
103 | await wallet.transferFunds(1, await wallet.address(), { onAccount: receiverKey })
|
104 | new BigNumber(await wallet.balance(receiver)).isZero().should.be.equal(true)
|
105 | })
|
106 | })
|
107 |
|
108 | it('spends tokens', async () => {
|
109 | const ret = await wallet.spend(1, receiver)
|
110 | ret.should.have.property('tx')
|
111 | ret.tx.should.include({
|
112 | amount: 1, recipientId: receiver
|
113 | })
|
114 | })
|
115 |
|
116 | it('spends tokens in AE format', async () => {
|
117 | const ret = await wallet.spend(1, receiver, { denomination: AE_AMOUNT_FORMATS.AE })
|
118 | ret.should.have.property('tx')
|
119 | ret.tx.should.include({
|
120 | amount: `${1e18}`, recipientId: receiver
|
121 | })
|
122 | })
|
123 |
|
124 | it('spends big amount of tokens', async () => {
|
125 | const bigAmount = '10000000000000100000000000000000'
|
126 | const genesis = await BaseAe({ networkId })
|
127 | const receiverWallet = generateKeyPair()
|
128 | const ret = await genesis.spend(bigAmount, receiverWallet.publicKey)
|
129 |
|
130 | const balanceAfter = await wallet.balance(receiverWallet.publicKey)
|
131 | balanceAfter.should.be.equal(bigAmount)
|
132 | ret.should.have.property('tx')
|
133 | ret.tx.should.include({
|
134 | amount: bigAmount, recipientId: receiverWallet.publicKey
|
135 | })
|
136 | })
|
137 |
|
138 | it('Get Account by block height/hash', async () => {
|
139 | const h = await wallet.height()
|
140 | await wallet.awaitHeight(h + 3)
|
141 | const spend = await wallet.spend(123, 'ak_DMNCzsVoZnpV5fe8FTQnNsTfQ48YM5C3WbHPsJyHjAuTXebFi')
|
142 | await wallet.awaitHeight(spend.blockHeight + 2)
|
143 | const accountAfterSpend = await wallet.getAccount(await wallet.address())
|
144 | const accountBeforeSpendByHash = await wallet.getAccount(await wallet.address(), { height: spend.blockHeight - 1 })
|
145 | BigNumber(accountBeforeSpendByHash.balance)
|
146 | .minus(BigNumber(accountAfterSpend.balance))
|
147 | .toString()
|
148 | .should.be
|
149 | .equal(`${spend.tx.fee + spend.tx.amount}`)
|
150 | })
|
151 |
|
152 | describe('Make operation on specific account without changing of current account', () => {
|
153 | it('Can make spend on specific account', async () => {
|
154 | const current = await wallet.address()
|
155 | const accounts = wallet.addresses()
|
156 | const onAccount = accounts.find(acc => acc !== current)
|
157 |
|
158 | const { tx } = await wallet.spend(1, await wallet.address(), { onAccount })
|
159 | tx.senderId.should.be.equal(onAccount)
|
160 | current.should.be.equal(current)
|
161 | })
|
162 |
|
163 | it('Fail on invalid account', async () => {
|
164 |
|
165 | try {
|
166 | await wallet.spend(1, await wallet.address(), { onAccount: 1 })
|
167 | } catch (e) {
|
168 | e.message.should.be.equal('Invalid `onAccount` option: should be keyPair object or account address')
|
169 | }
|
170 | })
|
171 |
|
172 | it('Fail on non exist account', async () => {
|
173 |
|
174 | try {
|
175 | await wallet.spend(1, await wallet.address(), { onAccount: 'ak_q2HatMwDnwCBpdNtN9oXf5gpD9pGSgFxaa8i2Evcam6gjiggk' })
|
176 | } catch (e) {
|
177 | e.message.should.be.equal('Account for ak_q2HatMwDnwCBpdNtN9oXf5gpD9pGSgFxaa8i2Evcam6gjiggk not available')
|
178 | }
|
179 | })
|
180 | it('Invalid on account options', async () => {
|
181 | try {
|
182 | await wallet.sign('tx_Aasdasd', { onAccount: 123 })
|
183 | } catch (e) {
|
184 | e.message.should.be.equal('Invalid `onAccount` option: should be keyPair object or account address')
|
185 | }
|
186 | })
|
187 | it('Make operation on account using keyPair/MemoryAccount', async () => {
|
188 | const keypair = generateKeyPair()
|
189 | const memoryAccount = MemoryAccount({ keypair })
|
190 | const data = 'Hello'
|
191 | const signature = await memoryAccount.sign(data)
|
192 | const sigUsingKeypair = await wallet.sign(data, { onAccount: keypair })
|
193 | const sigUsingMemoryAccount = await wallet.sign(data, { onAccount: memoryAccount })
|
194 | signature.toString('hex').should.be.equal(sigUsingKeypair.toString('hex'))
|
195 | signature.toString('hex').should.be.equal(sigUsingMemoryAccount.toString('hex'))
|
196 |
|
197 | const addressFromKeypair = await wallet.address({ onAccount: keypair })
|
198 | const addressFrommemoryAccount = await wallet.address({ onAccount: memoryAccount })
|
199 | addressFromKeypair.should.be.equal(keypair.publicKey)
|
200 | addressFrommemoryAccount.should.be.equal(keypair.publicKey)
|
201 | })
|
202 | it('Make operation on account using keyPair: Invalid keypair', async () => {
|
203 | const keypair = generateKeyPair()
|
204 | keypair.publicKey = 'ak_bev1aPMdAeJTuUiCJ7mHbdQiAizrkRGgoV9FfxHYb6pAxo5WY'
|
205 | const data = 'Hello'
|
206 | try {
|
207 | await wallet.sign(data, { onAccount: keypair })
|
208 | } catch (e) {
|
209 | e.message.should.be.equal('Invalid \'onAccount\' option: Invalid Key Pair')
|
210 | }
|
211 | try {
|
212 | await wallet.address({ onAccount: keypair })
|
213 | } catch (e) {
|
214 | e.message.should.be.equal('Invalid \'onAccount\' option: Invalid Key Pair')
|
215 | }
|
216 | })
|
217 | })
|
218 |
|
219 | describe('can be configured to return th', () => {
|
220 | it('on creation', async () => {
|
221 | const wallet = await getSdk()
|
222 | const th = await wallet.spend(1, receiver)
|
223 | th.should.be.a('object')
|
224 | th.hash.slice(0, 3).should.equal('th_')
|
225 | })
|
226 |
|
227 | it('on call', async () => {
|
228 | const th = await wallet.spend(1, receiver)
|
229 | th.should.be.a('object')
|
230 | th.hash.slice(0, 3).should.equal('th_')
|
231 | })
|
232 | })
|
233 | })
|