Skip to content

Commit 0bde625

Browse files
Merge pull request #5372 from BitGo/WIN-4290
feat: adding overrides for coredao for non-bitgo recovery support through wrw
2 parents 5bc43e7 + 0905dc6 commit 0bde625

File tree

4 files changed

+132
-5
lines changed

4 files changed

+132
-5
lines changed

modules/sdk-coin-coredao/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@
4343
"@bitgo/abstract-eth": "^22.4.13",
4444
"@bitgo/sdk-core": "^28.22.0",
4545
"@bitgo/statics": "^50.22.0",
46-
"@ethereumjs/common": "^2.6.5"
46+
"@ethereumjs/common": "^2.6.5",
47+
"@ethereumjs/tx": "^3.3.0",
48+
"bn.js": "^5.2.1"
4749
},
4850
"devDependencies": {
4951
"@bitgo/sdk-api": "^1.58.5",

modules/sdk-coin-coredao/src/coredao.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { BaseCoin, BitGoBase, common, MPCAlgorithm } from '@bitgo/sdk-core';
22
import { BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
3-
import { AbstractEthLikeNewCoins, recoveryBlockchainExplorerQuery } from '@bitgo/abstract-eth';
3+
import { AbstractEthLikeNewCoins, optionalDeps, recoveryBlockchainExplorerQuery } from '@bitgo/abstract-eth';
44
import { TransactionBuilder } from './lib';
5+
import BN from 'bn.js';
56

67
export class Coredao extends AbstractEthLikeNewCoins {
78
protected constructor(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>) {
@@ -31,4 +32,42 @@ export class Coredao extends AbstractEthLikeNewCoins {
3132
const explorerUrl = common.Environments[this.bitgo.getEnv()].coredaoExplorerBaseUrl;
3233
return await recoveryBlockchainExplorerQuery(query, explorerUrl as string, apiToken);
3334
}
35+
36+
/** @inheritDoc */
37+
async queryAddressBalance(address: string): Promise<BN> {
38+
const result = await this.recoveryBlockchainExplorerQuery({
39+
module: 'account',
40+
action: 'balance',
41+
address: address,
42+
});
43+
// throw if the result does not exist or the result is not a valid number
44+
if (!result || !result.result || isNaN(Number(result.result))) {
45+
throw new Error(`Could not obtain address balance for ${address} from the explorer, got: ${result.result}`);
46+
}
47+
result.result = result.result.toString();
48+
49+
return new optionalDeps.ethUtil.BN(result.result, 10);
50+
}
51+
52+
/** @inheritDoc */
53+
async getAddressNonce(address: string): Promise<number> {
54+
// Get nonce for backup key
55+
let nonce = 0;
56+
57+
const result = await this.recoveryBlockchainExplorerQuery({
58+
module: 'account',
59+
action: 'txlist',
60+
sort: 'desc',
61+
address: address,
62+
});
63+
if (!result || !Array.isArray(result.result)) {
64+
throw new Error('Unable to find next nonce from the explorer, got: ' + JSON.stringify(result));
65+
}
66+
const backupKeyTxList = result.result;
67+
if (backupKeyTxList.length > 0) {
68+
// Calculate last nonce used
69+
nonce = Math.max(...backupKeyTxList.filter((tx) => tx.from === address).map((tx) => tx.nonce as number)) + 1;
70+
}
71+
return nonce;
72+
}
3473
}

modules/sdk-coin-coredao/test/unit/coredao.ts

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
import 'should';
1+
import * as should from 'should';
22

33
import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test';
44
import { BitGoAPI } from '@bitgo/sdk-api';
55

66
import { Coredao, Tcoredao } from '../../src/index';
7+
import nock from 'nock';
8+
9+
import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx';
10+
import { stripHexPrefix } from '@ethereumjs/util';
711

812
const bitgo: TestBitGoAPI = TestBitGo.decorate(BitGoAPI, { env: 'test' });
913

@@ -39,4 +43,86 @@ describe('Coredao', function () {
3943
tcoredao.allowsAccountConsolidations().should.equal(false);
4044
});
4145
});
46+
47+
describe('Build Recover Transaction', function () {
48+
const bitgo = TestBitGo.decorate(BitGoAPI, { env: 'test' });
49+
const getTxListRequest: Record<string, string> = {
50+
module: 'account',
51+
action: 'txlist',
52+
sort: 'desc',
53+
address: '0x594886d686261172b95fae7401841843504f156b',
54+
};
55+
56+
const getTxListResponse: Record<string, unknown> = {
57+
status: '1',
58+
result: [
59+
{
60+
hash: '0xede855d43d70ea1bb75db63d4f75113dae0845f0d4bdb0b2d8bda55249c70812',
61+
nonce: '23',
62+
from: '0x594886d686261172b95fae7401841843504f156b',
63+
},
64+
],
65+
message: 'OK',
66+
};
67+
68+
const getBalanceRequest: Record<string, string> = {
69+
module: 'account',
70+
action: 'balance',
71+
address: '0x594886d686261172b95fae7401841843504f156b',
72+
};
73+
74+
const getBalanceResponse: Record<string, unknown> = {
75+
status: '1',
76+
result: 100000000000000000,
77+
message: 'OK',
78+
};
79+
80+
const mockData = {
81+
recoveryDestination: '0x224056675da79dac836c330704e9b091a7fc2e1c',
82+
userKeyData:
83+
'{"iv":"1j/pXswlTT5JEkqmopflwA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"yA1ls3UYGwk=","ct":"DWf+iaYWSig20VhHWiNYurPyONJO4rAMC0Erxp06SUlLVdLAiD4bHsjNhh3t8OeuVQLlAkfqDBOufVV6DGFcRaBK5KE/mjON2XSIVk+GW8K/ZbdxYpvyFX2zKQtONUP4OXhSrKghgJb7nHCTWtHFPuP734IIKTA1s+iPp4Ojafd7nwXh9uKV5lfD8hSKKt6oWcAqGIeyTk2EUl948wbKdxECgXA3noGHGeDEd4i17VnR44gu9A7A2YB2hQamrn5u1T6uAbNJomYcvD2szzo3bqEi9vFA8WMrX6MYvmTlH21NM5KsxZPPSIHaBlBL/w1bnwgrC6qLEQChnWOIinVepUmWj+NQWkRADbyz9gJLQZtYIcOO1YOoNMKr96a/0zKoktjOrL4d6e617RSWyeOC+OMCtIwBw/LHaQyFzCtuwdtSaG6xoDJIkT0mW7AFX6veu6xK6DM2S2/dNrFlF2cT8a0KO+L4uiA5QcsznPiYv7uUmC2SbX2nskBd2xe6+TpF9VcMMYNk6P01YXj+w9zVUtZRNRv9ke8rMq0Tg8LdorfDqCS15TB86P5iSEOgjP4xXzw5s+5QVhO1Y+4RQuDFW7tDRto0XWZlY7jFg/ NJ7PXOipNPasFjBKHROhM9gq5V4sT5opjbetUHqFGaJC4sRY4HvO9Y+oxFk7khJkK40EFlQzvDCkmDOTjVv/fb5N2kJjq7IGeZTsEeFA90fogUM2DGvwnBB0icggHLS2px40/RHlK2jz3V1XQp5ecddhLzc38/lik9MUsmtTlK3VB5WjGfDRSLBZqy1hjsvKlvKTbpVkg937X/Wun62c4kquYzSJIHd0UanAKd5D7O+oIoUZR7FgpbDQoutRhVflDTyYpOq7tSJOrYbjA1qEJVWJqeFIKdfQ9ZboT9aFq3aGQxuk7mz9CyrKVRQfPBrjzEbW8mKCqpJLUshKXkcETnlNzSBbOuPokIRz+nM3rlYFevk4oiA418QdH3rK+gPQv4NkKHGcZlb3Vzro85seOZVqzgITXadXUznBG0/mYmY+Iqe1zHI1nDDGrxCqzpK4v31M2e7xyPu/kMHZYKNvM0k2jy"}',
84+
backupKeyData:
85+
'{"iv":"LYD8I6UEfqMEmFgwC/YR+w==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"IxVKifwPPWU=","ct":"qw+MmwAoinYPgyAbVKGbKDKFaNv+tyj9W1ird+MdVrLBurYoccf1wESdBpLVIIEaljXHZD/uxXSxOHtIjM4tUpnwajI5fSG0pYa2p048uN4K54tBtCJqj1W1jPyDVdaGEi6TheI5jGjKPEnI3J4ZPbQ7BfeT0WceIX3S9dT+VETug6vAf4axU8phIejCRuHgnvtErx/xiKH3zSDnc3oOSjHfoz0ujR/ZLtb4FRPaXujgRDISqoR4CtN7io3myq2NArzNsYi6PluD/jp80My+1jImIrmDqY+DVgGTDBAOz97eL9lXS2uiw3VuoPUSsQCdCrIjnhsq0BtL/W53eZbrXH565Bykm6L6DqJLJeVOrIMUAG/An1X9iUSqmHDFr7SW2z6NCy624vC3ulBRUcji44XHcmm4eVU1SgZDlzB00wBTNxHObIVJwWX8ZP33bYjeav3WBClXrC3b0CqEVzY7F3nLT8I6q1bb0WrRzB3blX7Avf0FylnUN0QbN1mQLUA01LZYof3+gPFCfDEzT/qX8EpgcxLpGgd8T4sj7RKjv0rHBZ462l1yh4lN2PqmZW/10UkyTYYqr0Jw3neYFHQTLoS2FqBNkftyBYkO8eiVXvbeaHuCugiDBB963cNR3nE1a6UqHH1Ime1K6chAoUZlq5arfT3OPR4lPpWXXwigznNcUMMJVQhGVJI1siEOXR1b78fe12VTD1PKhRQC5J9UvE3nBRoXoEWkj1b3/UQfUF6ITQQYDg8lZYKdRYyOlrQDS56oVI1HF8uR0+IQSbtshWSw4OrN6FPHf6ZuhcwX3PSvZwXpNVndxKII8pgFAn0SyQAFsWVY/4OKCO/O+PJkg7ODcJo/S9BAqcxmInBWgnaLMEhCGl77xVELW/B8wVOEVC3ApGtQsjg1CQg/PWsJY5EDkVykejiRTZyim9C84hZSL6bSpDCGOWnEEkI1U9gQlE0kkj1ZBQpe7xxOJ7jhWqNC800orDNsSIdOlDvD/SXX1zHf88aby9VNkUUwb6D9cUItuVkL4gllk/7aTnt0UIoiy8X6Z3w3z3tQi4i9pEZNeM3kG0nlQX12Q7788YNR"}',
86+
walletRootAddress: '0x594886d686261172b95fae7401841843504f156b',
87+
walletPassphrase: 'test_1234_test',
88+
explorerUrl: 'https://app.test.btcs.network',
89+
getTxListRequest: getTxListRequest,
90+
getTxListResponse: getTxListResponse,
91+
getBalanceRequest: getBalanceRequest,
92+
getBalanceResponse: getBalanceResponse,
93+
};
94+
95+
it('should generate a signed non-bitgo recovery tx', async () => {
96+
nock(mockData.explorerUrl)
97+
.get('/api')
98+
.twice()
99+
.query(mockData.getTxListRequest)
100+
.reply(200, mockData.getTxListResponse);
101+
nock(mockData.explorerUrl).get('/api').query(mockData.getBalanceRequest).reply(200, mockData.getBalanceResponse);
102+
103+
const baseCoin: any = bitgo.coin('tcoredao');
104+
const transaction = await baseCoin.recover({
105+
userKey: mockData.userKeyData,
106+
backupKey: mockData.backupKeyData,
107+
walletContractAddress: mockData.walletRootAddress,
108+
walletPassphrase: mockData.walletPassphrase,
109+
recoveryDestination: mockData.recoveryDestination,
110+
isTss: true,
111+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
112+
gasLimit: 500000,
113+
replayProtectionOptions: {
114+
chain: 1115,
115+
hardfork: 'london',
116+
},
117+
});
118+
should.exist(transaction);
119+
transaction.should.have.property('id');
120+
transaction.should.have.property('tx');
121+
const tx = FeeMarketEIP1559Transaction.fromSerializedTx(Buffer.from(stripHexPrefix(transaction.tx), 'hex'));
122+
tx.getSenderAddress().toString().should.equal(mockData.walletRootAddress);
123+
const jsonTx = tx.toJSON();
124+
jsonTx.chainId?.should.equal('0x45b');
125+
jsonTx.to?.should.equal(mockData.recoveryDestination);
126+
});
127+
});
42128
});

modules/sdk-core/src/bitgo/environments.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ const mainnetBase: EnvironmentTemplate = {
164164
hmacVerificationEnforced: true,
165165
suiNodeUrl: 'https://fullnode.mainnet.sui.io',
166166
etcNodeUrl: 'https://etc.blockscout.com',
167-
coredaoExplorerBaseUrl: 'https://scan.coredao.org/',
167+
coredaoExplorerBaseUrl: 'https://app.coredao.org/',
168168
oasExplorerBaseUrl: 'https://explorer.oasys.games',
169169
rosettaNodeURL: 'http://localhost:8081', //TODO(WIN-4242): update when rosetta node is available
170170
};
@@ -220,7 +220,7 @@ const testnetBase: EnvironmentTemplate = {
220220
hmacVerificationEnforced: false,
221221
suiNodeUrl: 'https://fullnode.testnet.sui.io',
222222
etcNodeUrl: 'https://etc-mordor.blockscout.com',
223-
coredaoExplorerBaseUrl: 'https://scan.test.btcs.network',
223+
coredaoExplorerBaseUrl: 'https://app.test.btcs.network',
224224
oasExplorerBaseUrl: 'https://explorer.testnet.oasys.games',
225225
rosettaNodeURL: 'http://localhost:8081', //TODO(WIN-4242): update when rosetta node is available
226226
};

0 commit comments

Comments
 (0)