|
1 | 1 | import { BitGoAPI } from '@bitgo/sdk-api'; |
2 | 2 | import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test'; |
3 | | -import { NetworkType } from '@bitgo/statics'; |
| 3 | +import { coins, NetworkType } from '@bitgo/statics'; |
4 | 4 | import BigNumber from 'bignumber.js'; |
5 | 5 | import sinon from 'sinon'; |
6 | 6 | import { Rune, Trune } from '../../src'; |
7 | 7 | import { RuneUtils } from '../../src/lib/utils'; |
8 | 8 | import { mainnetAddress } from '../resources/rune'; |
9 | | -import { TEST_SEND_TX, TEST_TX_WITH_MEMO, testnetAddress } from '../resources/trune'; |
| 9 | +import { TEST_SEND_TX, TEST_TX_WITH_MEMO, testnetAddress, wrwUser } from '../resources/trune'; |
10 | 10 | const bech32 = require('bech32-buffer'); |
11 | 11 | import should = require('should'); |
| 12 | +import { beforeEach } from 'mocha'; |
| 13 | +import { CosmosTransaction, SendMessage } from '@bitgo/abstract-cosmos'; |
| 14 | +import { GAS_AMOUNT } from '../../src/lib/constants'; |
12 | 15 |
|
13 | 16 | describe('Rune', function () { |
14 | 17 | let bitgo: TestBitGoAPI; |
@@ -265,4 +268,121 @@ describe('Rune', function () { |
265 | 268 | stub.restore(); |
266 | 269 | }); |
267 | 270 | }); |
| 271 | + |
| 272 | + describe('Recover transaction: success path', () => { |
| 273 | + const sandBox = sinon.createSandbox(); |
| 274 | + const coin = coins.get('tthorchain:rune'); |
| 275 | + const testBalance = '1500000'; |
| 276 | + const testAccountNumber = '123'; |
| 277 | + const testSequenceNumber = '0'; |
| 278 | + const testChainId = 'thorchain-stagenet-2'; |
| 279 | + |
| 280 | + beforeEach(() => { |
| 281 | + const accountBalance = sandBox.stub(Trune.prototype, 'getAccountBalance' as keyof Trune); |
| 282 | + accountBalance.withArgs(wrwUser.senderAddress).resolves(testBalance); |
| 283 | + |
| 284 | + const accountDetails = sandBox.stub(Trune.prototype, 'getAccountDetails' as keyof Trune); |
| 285 | + accountDetails.withArgs(wrwUser.senderAddress).resolves([testAccountNumber, testSequenceNumber]); |
| 286 | + |
| 287 | + const chainId = sandBox.stub(Trune.prototype, 'getChainId' as keyof Trune); |
| 288 | + chainId.withArgs().resolves(testChainId); |
| 289 | + }); |
| 290 | + |
| 291 | + afterEach(() => { |
| 292 | + sandBox.restore(); |
| 293 | + sinon.restore(); |
| 294 | + }); |
| 295 | + |
| 296 | + it('should recover funds for non-bitgo recoveries', async function () { |
| 297 | + const res = await trune.recover({ |
| 298 | + userKey: wrwUser.userPrivateKey, |
| 299 | + backupKey: wrwUser.backupPrivateKey, |
| 300 | + bitgoKey: wrwUser.bitgoPublicKey, |
| 301 | + walletPassphrase: wrwUser.walletPassphrase, |
| 302 | + recoveryDestination: wrwUser.destinationAddress, |
| 303 | + }); |
| 304 | + res.should.not.be.empty(); |
| 305 | + res.should.hasOwnProperty('serializedTx'); |
| 306 | + sandBox.assert.calledOnce(trune.getAccountBalance); |
| 307 | + sandBox.assert.calledOnce(trune.getAccountDetails); |
| 308 | + sandBox.assert.calledOnce(trune.getChainId); |
| 309 | + |
| 310 | + const truneTxn = new CosmosTransaction(coin, testnetUtils); |
| 311 | + truneTxn.enrichTransactionDetailsFromRawTransaction(res.serializedTx); |
| 312 | + const truneTxnJson = truneTxn.toJson(); |
| 313 | + const sendMessage = truneTxnJson.sendMessages[0].value as SendMessage; |
| 314 | + const balance = new BigNumber(testBalance); |
| 315 | + const actualBalance = balance.minus(new BigNumber(GAS_AMOUNT)); |
| 316 | + should.equal(sendMessage.amount[0].amount, actualBalance.toFixed()); |
| 317 | + }); |
| 318 | + }); |
| 319 | + |
| 320 | + describe('Recover transaction: failure path', () => { |
| 321 | + const sandBox = sinon.createSandbox(); |
| 322 | + const testZeroBalance = '0'; |
| 323 | + const testAccountNumber = '123'; |
| 324 | + const testSequenceNumber = '0'; |
| 325 | + const testChainId = 'thorchain-stagenet-2'; |
| 326 | + |
| 327 | + beforeEach(() => { |
| 328 | + const accountBalance = sandBox.stub(Trune.prototype, 'getAccountBalance' as keyof Trune); |
| 329 | + accountBalance.withArgs(wrwUser.senderAddress).resolves(testZeroBalance); |
| 330 | + |
| 331 | + const accountDetails = sandBox.stub(Trune.prototype, 'getAccountDetails' as keyof Trune); |
| 332 | + accountDetails.withArgs(wrwUser.senderAddress).resolves([testAccountNumber, testSequenceNumber]); |
| 333 | + |
| 334 | + const chainId = sandBox.stub(Trune.prototype, 'getChainId' as keyof Trune); |
| 335 | + chainId.withArgs().resolves(testChainId); |
| 336 | + }); |
| 337 | + |
| 338 | + afterEach(() => { |
| 339 | + sandBox.restore(); |
| 340 | + sinon.restore(); |
| 341 | + }); |
| 342 | + |
| 343 | + it('should throw error if backupkey is not present', async function () { |
| 344 | + await trune |
| 345 | + .recover({ |
| 346 | + userKey: wrwUser.userPrivateKey, |
| 347 | + bitgoKey: wrwUser.bitgoPublicKey, |
| 348 | + walletPassphrase: wrwUser.walletPassphrase, |
| 349 | + recoveryDestination: wrwUser.destinationAddress, |
| 350 | + }) |
| 351 | + .should.rejectedWith('missing backupKey'); |
| 352 | + }); |
| 353 | + |
| 354 | + it('should throw error if userkey is not present', async function () { |
| 355 | + await trune |
| 356 | + .recover({ |
| 357 | + backupKey: wrwUser.backupPrivateKey, |
| 358 | + bitgoKey: wrwUser.bitgoPublicKey, |
| 359 | + walletPassphrase: wrwUser.walletPassphrase, |
| 360 | + recoveryDestination: wrwUser.destinationAddress, |
| 361 | + }) |
| 362 | + .should.rejectedWith('missing userKey'); |
| 363 | + }); |
| 364 | + |
| 365 | + it('should throw error if wallet passphrase is not present', async function () { |
| 366 | + await trune |
| 367 | + .recover({ |
| 368 | + userKey: wrwUser.userPrivateKey, |
| 369 | + backupKey: wrwUser.backupPrivateKey, |
| 370 | + bitgoKey: wrwUser.bitgoPublicKey, |
| 371 | + recoveryDestination: wrwUser.destinationAddress, |
| 372 | + }) |
| 373 | + .should.rejectedWith('missing wallet passphrase'); |
| 374 | + }); |
| 375 | + |
| 376 | + it('should throw error if there is no balance', async function () { |
| 377 | + await trune |
| 378 | + .recover({ |
| 379 | + userKey: wrwUser.userPrivateKey, |
| 380 | + backupKey: wrwUser.backupPrivateKey, |
| 381 | + bitgoKey: wrwUser.bitgoPublicKey, |
| 382 | + walletPassphrase: wrwUser.walletPassphrase, |
| 383 | + recoveryDestination: wrwUser.destinationAddress, |
| 384 | + }) |
| 385 | + .should.rejectedWith('Did not have enough funds to recover'); |
| 386 | + }); |
| 387 | + }); |
268 | 388 | }); |
0 commit comments