Skip to content

Commit e362cfa

Browse files
vibhavgobitgobot
authored andcommitted
test(sdk-coin-sui): cover MPCv2 recovery for token transfers
Add an MPCv2-signed recovery test under the token recovery describe block, mirroring the native-transfer MPCv2 test added in the prior commit. Asserts getTSSSignature is not called and the resulting signature is wrapped in SUI's 0x00-flag envelope. The prior commit wired signRecoveryTransaction()'s MPCv2 dispatch into both recover() and recoverSuiToken(), but only exercised the native-transfer path in tests. The ticket explicitly calls out that token recovery (getTokenTransferBuilder) must also handle MPCv2, so this closes that coverage gap found during review. Ticket: WCI-1224 Session-Id: 0c067bc3-368d-4c82-9e68-8d08c89766d5 Task-Id: 8c5b0392-4a96-4479-a83b-8ba80cd2428d
1 parent e54e9b9 commit e362cfa

1 file changed

Lines changed: 68 additions & 0 deletions

File tree

  • modules/sdk-coin-sui/test/unit

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

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,74 @@ describe('SUI:', function () {
11471147
sandBox.assert.callCount(basecoin.getInputCoins, 2);
11481148
sandBox.assert.callCount(basecoin.getFeeEstimate, 1);
11491149
});
1150+
1151+
describe('MPCv2 signed recovery', function () {
1152+
const mpcV2WalletPassphrase = 'test-passphrase-mpcv2-token';
1153+
1154+
let mpcV2UserKey: string;
1155+
let mpcV2BackupKey: string;
1156+
let mpcV2CommonKeyChain: string;
1157+
let mpcV2WalletAddress: string;
1158+
1159+
before(async function () {
1160+
const [userDkg, backupDkg] = await MPSUtil.generateEdDsaDKGKeyShares();
1161+
mpcV2CommonKeyChain = userDkg.getCommonKeychain();
1162+
mpcV2UserKey = await encrypt(mpcV2WalletPassphrase, userDkg.getReducedKeyShare().toString('base64'));
1163+
mpcV2BackupKey = await encrypt(mpcV2WalletPassphrase, backupDkg.getReducedKeyShare().toString('base64'));
1164+
1165+
const mpc = await EDDSAMethods.getInitializedMpcInstance();
1166+
const accountId = mpc.deriveUnhardened(mpcV2CommonKeyChain, 'm/0').slice(0, 64);
1167+
mpcV2WalletAddress = utils.getAddressFromPublicKey(accountId);
1168+
});
1169+
1170+
it('should recover a token txn using MPCv2 signing material without calling getTSSSignature', async function () {
1171+
getBalanceStub
1172+
.withArgs(mpcV2WalletAddress)
1173+
.resolves({ totalBalance: '1900000000', coinObjectBalance: '1900000000', fundsInAddressBalance: '0' })
1174+
.withArgs(mpcV2WalletAddress, coinType)
1175+
.resolves({ totalBalance: '1000', coinObjectBalance: '1000', fundsInAddressBalance: '0' });
1176+
getInputCoinsStub.withArgs(mpcV2WalletAddress, coinType).resolves([
1177+
{
1178+
coinType: '0x36dbef866a1d62bf7328989a10fb2f07d769f4ee587c0de4a0a256e57e0a58a8::deep::DEEP',
1179+
objectId: '0x924ab69ebba304f2975a588372b41e4e1f5db7fa824868f84199eeb1e0a15a2d',
1180+
version: '34696807',
1181+
digest: '7XRbWQTiwAUCjLLsZVpJMrABCheJBkzKVfCr7aTZZVkd',
1182+
balance: new BigNumber(1000),
1183+
},
1184+
]);
1185+
getInputCoinsStub.withArgs(mpcV2WalletAddress).resolves([
1186+
{
1187+
coinType: '0x2::sui::SUI',
1188+
objectId: '0x9146928f557cb8ab1915a5886c1362435a05b4709b586bb01d4c70e85bb53161',
1189+
version: '239',
1190+
digest: 'GLSzR6HJ319nPKAFm5x3TWHcaHZzCFSBCqhvZ1qwT5wr',
1191+
balance: new BigNumber('1230261076'),
1192+
},
1193+
]);
1194+
getFeeEstimateStub.resolves(new BigNumber(2345504));
1195+
1196+
const getTSSSignatureSpy = sandBox.spy(EDDSAMethods, 'getTSSSignature');
1197+
1198+
const res = (await basecoin.recover({
1199+
userKey: mpcV2UserKey,
1200+
backupKey: mpcV2BackupKey,
1201+
bitgoKey: mpcV2CommonKeyChain,
1202+
recoveryDestination,
1203+
walletPassphrase: mpcV2WalletPassphrase,
1204+
tokenContractAddress,
1205+
})) as MPCTxs;
1206+
1207+
res.should.not.be.empty();
1208+
res.should.hasOwnProperty('transactions');
1209+
const tx = res.transactions[0];
1210+
should.equal(tx.scanIndex, 0);
1211+
(tx.serializedTx as string).should.be.a.String().and.not.be.empty();
1212+
sandBox.assert.notCalled(getTSSSignatureSpy);
1213+
1214+
// The SUI signature envelope is 1 (flag) + 64 (signature) + 32 (pubkey) bytes.
1215+
Buffer.from(tx.signature as string, 'base64').length.should.equal(97);
1216+
});
1217+
});
11501218
});
11511219

11521220
describe('Recover Transactions for wallet with multiple addresses:', () => {

0 commit comments

Comments
 (0)