Skip to content

Commit 48129d3

Browse files
committed
feat(bsc): added support for mpcv2 in recovery
TICKET: WIN-4618
1 parent b6c1977 commit 48129d3

File tree

5 files changed

+324
-26
lines changed

5 files changed

+324
-26
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import { BaseCoin, BitGoBase, common, MPCAlgorithm, MultisigType, multisigTypes
22
import { BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
33
import { AbstractEthLikeNewCoins, recoveryBlockchainExplorerQuery } from '@bitgo/abstract-eth';
44
import { TransactionBuilder } from './lib';
5+
import {
6+
UnsignedSweepTxMPCv2,
7+
RecoverOptions,
8+
OfflineVaultTxInfo,
9+
} from '../../abstract-eth/src/abstractEthLikeNewCoins';
510

611
export class Bsc extends AbstractEthLikeNewCoins {
712
protected constructor(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>) {
@@ -12,6 +17,15 @@ export class Bsc extends AbstractEthLikeNewCoins {
1217
return new Bsc(bitgo, staticsCoin);
1318
}
1419

20+
/**
21+
* Builds an unsigned sweep transaction for TSS
22+
* @param params - Recovery options
23+
* @returns {Promise<OfflineVaultTxInfo | UnsignedSweepTxMPCv2>}
24+
*/
25+
protected async buildUnsignedSweepTxnTSS(params: RecoverOptions): Promise<OfflineVaultTxInfo | UnsignedSweepTxMPCv2> {
26+
return this.buildUnsignedSweepTxnMPCv2(params);
27+
}
28+
1529
protected getTransactionBuilder(): TransactionBuilder {
1630
return new TransactionBuilder(coins.get(this.getBaseChain()));
1731
}

modules/sdk-coin-bsc/src/lib/transactionBuilder.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { BaseCoin as CoinConfig } from '@bitgo/statics';
2-
import { BuildTransactionError, TransactionType } from '@bitgo/sdk-core';
2+
import { BuildTransactionError, PublicKey, TransactionType } from '@bitgo/sdk-core';
33
import { TransactionBuilder as AbstractTransactionBuilder, Transaction } from '@bitgo/abstract-eth';
44
import { getCommon } from './utils';
55
import { TransferBuilder } from './transferBuilder';
66

77
export class TransactionBuilder extends AbstractTransactionBuilder {
88
protected _transfer: TransferBuilder;
9+
private _signatures: { publicKey: string; signature: string }[] = [];
910

1011
constructor(_coinConfig: Readonly<CoinConfig>) {
1112
super(_coinConfig);
@@ -23,4 +24,13 @@ export class TransactionBuilder extends AbstractTransactionBuilder {
2324
}
2425
return this._transfer;
2526
}
27+
/**
28+
* Add a signature to the transaction
29+
* @param publicKey - The public key associated with the signature
30+
* @param signature - The signature to add
31+
*/
32+
addSignature(publicKey: PublicKey, signature: Buffer): void {
33+
// Method updated
34+
this._signatures.push({ publicKey: publicKey.toString(), signature: signature.toString('hex') });
35+
}
2636
}

modules/sdk-coin-bsc/test/fixtures/ecdsa.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,114 @@ export const keyShares = {
104104
},
105105
},
106106
};
107+
108+
// New mock data functions for recovery and sweep
109+
const TEST_POLYGON_WALLET_FIRST_ADDRESS = '0x4861ae0ac185c9b395df457e9d8c03ec14b558fe';
110+
const TEST_RECOVERY_PASSCODE = 'Bondiola1234#';
111+
112+
export function getNonBitGoRecoveryForHotWalletsMPCv2(intendedChain = 'tpolygon'): any {
113+
return {
114+
userKey:
115+
'{"iv":"xijOgJRivR4fTovtu+UyxA==","v":1,"iter":10000,"ks":256,"ts":64,"mode"\n' +
116+
':"ccm","adata":"","cipher":"aes","salt":"X3Y8Gq6SIww=","ct":"NLtQHqJx5dNCO5\n' +
117+
'h/qdqnrDVLTgxPkOVPbLgw0qvA28w2jU+E63DP1R45sXCeCJM1CyMq+aADBE8HAsqA91Pn21AvW\n' +
118+
'cR9B7ElL5uCSWplBgQhitQN58m6sDs0wkskjMTYTZlv6UuDsTr/ZxWUug/xxiWn6FT0O8OcSemI\n' +
119+
'CR0/VoEwiLKmO48Ay9FnfI+/5BPZGExuu9ej8rIQJr2LF+F+HZKDP/IDJU4yoBsK+a1MCnNWh4X\n' +
120+
'IIqg2dgW00rebJuO1wCBmQUBX9mNe1wu83YZjPd4Q1LtRyFyIvadVf+tiUXLuyYQddbyFrR5d9J\n' +
121+
'HOPHafMyMzhD6TZD9ejBwB/jnfxg6ksjC4KgfkvQFvPyJfuC9eXms6ZLkYLb8xQina0M1PhBzBM\n' +
122+
'kcPBIiat9IRkc0XwD0csRXRMUp9spp0g7Cs78oCazfwrtqMVhoUP1lLqNA/JhPCIfjQwaiIWHu3\n' +
123+
'xo+j0+MEr9ShpTa8GxGhnqTvE8yGAjjzvVHTftHtCfV6v8mP30c7nst9NMn8q/kp2r7DICVdWzl\n' +
124+
'ZSr+t676mO8VC/OZ5imxeNZRpD5HBjMw6sreSPZpcBCB2jnLcKzmmUdL+YUUaMpM46v3jCypOsb\n' +
125+
'geQ0Y8J1b7VGHwwdMpoWJFwYfPGPhFXKe/93HilfVc+0rKmDM3Sf+XHRdRbcnB0gd/f4e2Nz3nd\n' +
126+
'XpFgM+U3u4rPXx1KBAnySH2jQM6ewPqyNqiEtisCAe3/YJ9wXegvSP5EGDtE91tur36NWJ1/DEl\n' +
127+
'e17QnNh23IHg5zn37pqnf+E2CYI77Db4TrVdFW/8Mw9Cc+qy1Nqk1Z4nzw7KF1r1AuJtOOLWnAo\n' +
128+
'AF43cG92JfpW8degO1xUu4LRMgPc/kqAsB+BK33zabHk4R8mBzrRTD9mdtlVz+4fAwrcM9KIwr/\n' +
129+
'xAf7jb/96juw02v0juDKmM/gFv+Wa8aCLyT0liW/cJm4h3ZyJTpFrZWRH06FEiPf4skaOpBVQov\n' +
130+
'HmTAXpRWVNtNB3XKkE7AtsYOd+2F2txx/PrOPZjvMP18RqwIjY4KZKYGamEnU/AjCk3LphNmKP+\n' +
131+
'V7cNpyP+zr5HxMDlCqYuYKbObDQCrTwVz18BWNrArdIfUw=="},\n',
132+
backupKey:
133+
'{"iv":"a4Ec48bpYTnXUyxGYVdvTg==","v":1,"iter":10000,"ks":256,"ts":64,"mode"\n' +
134+
':"ccm","adata":"","cipher":"aes","salt":"fLRw4S3Gl2Y=","ct":"043lWL0p9f99Xr\n' +
135+
'S9d9LloOoKJIsb9xoh03Iszy1GPsLyCD1Fd+tNiQUNKaG5LgNS1YPOk4xfBzD1NclPNj3ycZg/e\n' +
136+
'r/vTTPIpclwC0U/jQU8wTbdP8oR2oofJ+Ttss29ryYV08wcRKurwpmxvrBuVWtNNU7TIdsqZLkm\n' +
137+
'9emXt9hBEJHlN89/ydiNkBCsqb5L5/i1aI2Kg4CLzTvuq2vOVFMFtpdP9ll/xKZX8OCjpGgOmnS\n' +
138+
'EW4+Dm1+Nau2nuEMqdux8ev4JafA+MWUe6246Guof6zpluVeRiO/ebl7yiMA52IdpuJWW9girdp\n' +
139+
'qiZaKZ6vbI7aimgLtC6OnhLq+wnc6dddE2bBJWuVE6G7VhQ6I8uVogSZfQ1Go5bY+kaMkRMVPWw\n' +
140+
'XlMO8nw/z/zwa4CJPNAcdz4ONU1Rj5K5S9Jl0duvrIWs/1aDMaAKT+F72mUs4+Rhw1y6E+vXeto\n' +
141+
'tGY4392bwX9K5/KTTHGD4CYvJCUk3RMmYVezcwsFrbdCnAhys6qUqrKy5sIkrjXnemqubPXubGT\n' +
142+
'APYhitF8LY5mk3iA8V4Areb+04ADR/qDc6/QE5HnZnM1kqQ6GgULBIrKX0Q6wRusHyVgjzryqJM\n' +
143+
'iFJbwIXaKbpjofzUACAoHy0zy2Mzmwh3ebnFoVNvPyWlvOkrmBlQYMaz4eAcE0dlufbsI2JzNwu\n' +
144+
'PIbu6ptY6Kqw1in7LgZgCS3NwzyPslkZEn80aEvbBKFQjZgvZK7Ll1z2rO3igYvm4zfv9kl3oD2\n' +
145+
'R+rScIRRVuOsgeUKGQrPekpN0ZCaHzNABJBdz7GDde6n4N48NrnEr8nwOQcRe3xzHgkmrBmb7zz\n' +
146+
'7DhGmn47mLqasml61ztbGn+QrKjLXGB3vJr09WSkCfCvoF+vW36HNJf399XgJdjg1aAa3c4HpRQ\n' +
147+
'3qRN5R5ArHcJqVdK3OYLObzNAbgKMZidLnW2ExtKRkT9/mW4scyNDwgnv653w34V7yYyKdNG1R2\n' +
148+
'usziXQizZwLdvTHhcsH5XXfwyy+8xOSyyv1ZstuIrixnYDgWbuDYTBJFqwUiue6GeN7lbzvmiq2\n' +
149+
'oG2EIT5o4QeEMd5npIyEr411jRzgsLwLpFpuEo1M"},\n',
150+
bitgoKey:
151+
'02e75778dbb3988061f438b08d2eaf8d1bd3e6decc01b57ae35da45ba902eee1b34da5234e4d65c94fa4f8c3ac1313ca3f1f13f1262545d714249c349895eb9c01',
152+
walletPassphrase: TEST_RECOVERY_PASSCODE,
153+
walletContractAddress: TEST_POLYGON_WALLET_FIRST_ADDRESS,
154+
bitgoFeeAddress: '0x4861ae0ac185c9b395df457e9d8c03ec14b558fe',
155+
recoveryDestination: '0xd5adde17fed8baed3f32b84af05b8f2816f7b560',
156+
bitgoDestinationAddress: '0xe5986ce4490deb67d2950562ceb930ddf9be7a14',
157+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
158+
gasLimit: 500000,
159+
intendedChain: intendedChain,
160+
};
161+
}
162+
163+
export function getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2(intendedChain = 'tpolygon'): any {
164+
const address = '0x3685e9831699279942c1190edbf2c33c2c3c156b';
165+
return {
166+
recoveryDestination: '0xd5adde17fed8baed3f32b84af05b8f2816f7b560',
167+
bitgoDestinationAddress: '0xe5986ce4490deb67d2950562ceb930ddf9be7a14',
168+
walletContractAddress: TEST_POLYGON_WALLET_FIRST_ADDRESS,
169+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
170+
gasLimit: 500000,
171+
intendedChain: intendedChain,
172+
address: address,
173+
amount: '100000000000000000', // 0.1 MATIC
174+
commonKeyChain:
175+
'03a139ba3bf49de33675ea869baaab8f3225afffc96835c30db401c53b335476dddf0ad919ad8cfa92967a20879753a42fd3df1d6eb0824f0294a7838faa80e963',
176+
};
177+
}
178+
179+
export function getInvalidNonBitGoRecoveryParams(): any {
180+
return {
181+
...getNonBitGoRecoveryForHotWalletsMPCv2(),
182+
userKey: 'invalidUserKey',
183+
};
184+
}
185+
186+
export function getTxListRequest(
187+
bitgoFeeAddress: any
188+
):
189+
| string
190+
| boolean
191+
| import('nock').DataMatcherMap
192+
| import('url').URLSearchParams
193+
| ((parsedObj: import('querystring').ParsedUrlQuery) => boolean) {
194+
throw new Error('Function not implemented.');
195+
}
196+
export function getTxListResponse(arg0: number, getTxListResponse: any) {
197+
throw new Error('Function not implemented.');
198+
}
199+
200+
export function getBalanceRequest(
201+
bitgoFeeAddress: any
202+
):
203+
| string
204+
| boolean
205+
| import('nock').DataMatcherMap
206+
| import('url').URLSearchParams
207+
| ((parsedObj: import('querystring').ParsedUrlQuery) => boolean) {
208+
throw new Error('Function not implemented.');
209+
}
210+
211+
export function getBalanceResponse(arg0: number, getBalanceResponse: any) {
212+
throw new Error('Function not implemented.');
213+
}
214+
215+
export function getBitgoKey() {
216+
throw new Error('Function not implemented.');
217+
}

0 commit comments

Comments
 (0)