PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-etc/test/unit
Просмотр файла: etc.ts
import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test';
import { BitGoAPI } from '@bitgo/sdk-api';
import { Etc, Tetc, TransactionBuilder } from '../../src';
import sinon from 'sinon';
import { OfflineVaultTxInfo, SignTransactionOptions } from '@bitgo/abstract-eth';
import { BN } from 'ethereumjs-util';
import { getBuilder } from './getBuilder';
import { FullySignedTransaction } from '@bitgo/sdk-core';
import * as should from 'should';
describe('Ethereum Classic', function () {
let bitgo: TestBitGoAPI;
before(function () {
bitgo = TestBitGo.decorate(BitGoAPI, { env: 'mock' });
bitgo.initializeTestVars();
bitgo.safeRegister('etc', Etc.createInstance);
bitgo.safeRegister('tetc', Tetc.createInstance);
});
it('should instantiate the coin', function () {
let localBasecoin = bitgo.coin('tetc');
localBasecoin.should.be.an.instanceof(Tetc);
localBasecoin = bitgo.coin('etc');
localBasecoin.should.be.an.instanceof(Etc);
});
});
describe('Wallet Recovery Wizard', function () {
let sandbox;
let bitgo: TestBitGoAPI;
let tetcCoin: Tetc;
const sourceRootAddress = '0x321cbe223ff1c3d0c03b73b8c648ef2d91e4aaa1';
const backupKeyAddress = '0x921f162bfd472424d6065b919c3f6e3bf13fe3d7';
const destinationWalletAddress = '0x76e2dcc49618f3b9769fc8a80b6991388570b3ae';
const walletPassPhrase = 'Z@oOQ6fkpzjkJXxM<bN1';
beforeEach(function () {
sandbox = sinon.createSandbox();
const callBack = sandbox.stub(Etc.prototype, 'queryAddressBalance' as keyof Etc);
callBack.withArgs(sourceRootAddress).resolves(new BN('2190000000000000000'));
callBack.withArgs(backupKeyAddress).resolves(new BN('190000000000000000'));
callBack.withArgs('0x5273e0d869226ccf579a81b6d291fb3702ba9dec').resolves(new BN('0'));
callBack.withArgs('0x1b9af47cc3048fe1d31ad72299611d3df3926755').resolves(new BN('190000000000000000'));
callBack.withArgs('0x7fcf95a9106a0ed3bd09e653c8ea3d5e489bfb23').resolves(new BN('2190000000000000000'));
});
afterEach(function () {
sandbox.restore();
});
before(function () {
bitgo = TestBitGo.decorate(BitGoAPI, { env: 'test' });
bitgo.safeRegister('tetc', Tetc.createInstance);
bitgo.initializeTestVars();
});
describe('Non-BitGo Recovery', function () {
beforeEach(function () {
tetcCoin = bitgo.coin('tetc') as Tetc;
});
it('should build a recovery transaction for non-bitgo recovery', async function () {
const walletContractAddress = sourceRootAddress;
const recovery = (await tetcCoin.recover({
userKey:
'{"iv":"rP+aJBBP5VkYiGmc0KPz4A==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"/B4OU/PQ1Eg=","ct":"HvCzOA23n6WxgFcBdH3ZqrLnZl5NckPPUyC/UDSv/KO8ZPBb1xZVTTY2ZY6/JBG8dHp/ApvAlRFm1SC+MjZ/OF9LC6Zjz8vsoLiS0BHB+z8Z6qB/16aWJbEIRzEmgEkWRn10l9m646GS00qGNHKG1VBURvUOYN4="}',
backupKey:
'{"iv":"rDHtZUUKxaCQaIzGMB0b0w==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"0bmqSuxoVlA=","ct":"LyKRuUNVcRzhY5LUF15jKdKOpP04nUHs88FYPK1ZB9yuBSEGduQPjJs+xO62NCDh3pyiX1YeHBe9N6Gsm5Va0jSCk8XQ5pCwNuiO1RXvESAhfrXCivJMfRLVmCgaM79YMWapL7syUa//6mhu/1l4tPBBoZoBYc8="}',
walletContractAddress,
walletPassphrase: walletPassPhrase,
recoveryDestination: destinationWalletAddress,
})) as OfflineVaultTxInfo;
recovery.should.not.be.undefined();
recovery.should.have.property('id');
recovery.should.have.property('tx');
const txBuilder = getBuilder('tetc') as TransactionBuilder;
txBuilder.from(recovery.tx);
const tx = await txBuilder.build();
tx.toBroadcastFormat().should.not.be.empty();
});
it('should error when the backup key is unfunded (cannot pay gas)', async function () {
await tetcCoin
.recover({
userKey:
'{"iv":"RI3d7nXJnnMTJFEKE5U6CA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"qZtZ8FXlr5I=","ct":"F49E7Pi3duSQ9v1iauXuQ6q6SqmGHLPQ9RNJTmfJp0AH2mwNe1bl/pMpwsaT12Ay3x3roLsi5+WFzePK8q1z43xwKfMWjTdsxj0yHpwa+8kOyckEnKyZ5J/AUw0nS7ujegTelaKR/wT2D+mvpJejQ+NRs9Lvyrg="}\n',
backupKey:
'{"iv":"XJPzySPeTTAbLVol9fsQUA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"6LzbWSvK9Wo=","ct":"8fBnXkAX38ZtoHjN9MBUSkJ3dGgR8FuAmOo1sO7XfOu6Pan23YVpy468dKgl0C+UkzBQbnepNQ0UOf3kEudTYqt3/HgtvUcDdkkD3YDfEF1gVN7ndiBabF2C3SwnMNxUkuD0n5YWaRmaBPo+A2AGj4VrQ0wzFZs="}',
walletContractAddress: destinationWalletAddress,
walletPassphrase: walletPassPhrase,
recoveryDestination: sourceRootAddress,
})
.should.be.rejectedWith(
'Backup key address 0x5273e0d869226ccf579a81b6d291fb3702ba9dec has balance 0 Gwei.This address must have a balance of at least 10000000 Gwei to perform recoveries. Try sending some funds to this address then retry.'
);
});
it('should get the next sequence id for an address', async function () {
const baseCoin = bitgo.coin('tetc') as Tetc;
const walletContractAddress = '0x2E0b5638Bf3F774AF116029b09415AA9FDD812d5';
const sequenceId = await baseCoin.querySequenceId(walletContractAddress);
sequenceId.should.not.be.undefined();
});
});
describe('Unsigned sweep for cold wallet', function () {
const userXprv =
'xprv9s21ZrQH143K38Cfd5PyKGajVbA1sZYwAKQif8qvJMfMmSY85spqTnd4taexRHc9F92QCgBzHosCauYcnJWT9eWxfFKvSjAKoSgQkf74DoM';
const userXpub =
'xpub661MyMwAqRbcFcH8j6vygQXU3czWH2GnXYLKTXFXrhCLeEsGdR961awYjr3yC8eUj9rqhgFWHVbQJWqZS7kXpLBDzvoCKDLaBujsCH12Zfj';
const backupXprv =
'xprv9s21ZrQH143K3WkGc7rUw4NU5ZZTPczbMk9GajGxpJYhJXtfnYUL4j1x6vAGcxUg9XFzEHpQWPy3aYyJZcuGnYbc2eNzrsyNn3SRNdQa1PC';
const backupXpub =
'xpub661MyMwAqRbcGYaF52itktGhGDfiL9CBBTh4TSXV6QqGgXRbhSS5DAaTbdCPJA425XwkvwyCKtTmoxcUTAUgKUf7Qr5Ks9gJP9DTfiV2PhU';
const walletContractAddress = '0x7fcf95a9106a0ed3bd09e653c8ea3d5e489bfb23';
// tetc wallet 1 receiveAddress 4
const recoveryDestination = '0x321cbe223ff1c3d0c03b73b8c648ef2d91e4aaa1';
const gasPrice = 25000000000;
beforeEach(function () {
tetcCoin = bitgo.coin('tetc') as Tetc;
});
afterEach(function () {
sandbox.restore();
});
it('should generate an ETH unsigned sweep', async function () {
const transaction: OfflineVaultTxInfo = (await tetcCoin.recover({
userKey: userXpub,
backupKey: backupXpub,
walletContractAddress,
recoveryDestination,
gasPrice,
})) as OfflineVaultTxInfo;
should.exist(transaction);
transaction.should.have.property('txHex');
transaction.should.have.property('userKey');
transaction.should.have.property('backupKey');
transaction.should.have.property('gasLimit');
transaction.gasLimit.should.equal('500000');
transaction.should.have.property('gasPrice');
transaction.gasPrice.should.equal('25000000000');
transaction.should.have.property('walletContractAddress');
transaction.walletContractAddress.should.equal('0x7fcf95a9106a0ed3bd09e653c8ea3d5e489bfb23');
transaction.should.have.property('recipient');
});
it('should add a second signature', async function () {
const transaction = (await tetcCoin.recover({
userKey: userXpub,
backupKey: backupXpub,
walletContractAddress,
recoveryDestination,
gasPrice,
})) as OfflineVaultTxInfo;
const txPrebuild = {
txHex: transaction.txHex,
};
const params = {
txPrebuild,
prv: userXprv,
};
// sign transaction once
const halfSigned = await tetcCoin.signTransaction(params as SignTransactionOptions);
const halfSignedParams = {
txPrebuild: halfSigned,
isLastSignature: true,
walletContractAddress: walletContractAddress,
prv: backupXprv,
};
// sign transaction twice with the "isLastSignature" flag
const finalSignedTx = (await tetcCoin.signTransaction(
halfSignedParams as SignTransactionOptions
)) as FullySignedTransaction;
finalSignedTx.should.have.property('txHex');
const txBuilder = tetcCoin.getTransactionBuilder() as TransactionBuilder;
txBuilder.from(finalSignedTx.txHex);
const rebuiltTx = await txBuilder.build();
rebuiltTx.signature.length.should.equal(2);
rebuiltTx.outputs.length.should.equal(1);
});
});
});
Выполнить команду
Для локальной разработки. Не используйте в интернете!