Skip to content

Commit 6ad61a9

Browse files
committed
feat(sdk-core): create message sign request
TICKET: COIN-4593
1 parent 114557f commit 6ad61a9

File tree

3 files changed

+118
-8
lines changed

3 files changed

+118
-8
lines changed

modules/bitgo/test/v2/unit/wallet.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3467,14 +3467,24 @@ describe('V2 Wallet:', function () {
34673467
nock.cleanAll();
34683468
});
34693469

3470-
it('should throw error for unsupported coins', async function () {
3471-
await tssSolWallet
3472-
.signMessage({
3473-
reqId,
3474-
message: { messageRaw },
3475-
prv: 'secretKey',
3476-
})
3477-
.should.be.rejectedWith('Message signing not supported for Testnet Solana');
3470+
describe('should throw error for unsupported coins', function () {
3471+
it('sol signMessage', async function () {
3472+
await tssSolWallet
3473+
.signMessage({
3474+
reqId,
3475+
message: { messageRaw },
3476+
prv: 'secretKey',
3477+
})
3478+
.should.be.rejectedWith('Message signing not supported for Testnet Solana');
3479+
});
3480+
3481+
it('sol create signMessage tx request', async function () {
3482+
await tssSolWallet
3483+
.createSignMessageRequest({
3484+
message: messageRaw,
3485+
})
3486+
.should.be.rejectedWith('Message signing not supported for Testnet Solana');
3487+
});
34783488
});
34793489

34803490
messageSigningCoins.map((coinName) => {
@@ -3483,6 +3493,15 @@ describe('V2 Wallet:', function () {
34833493
tssEthWallet = new Wallet(bitgo, bitgo.coin(coinName), ethWalletData);
34843494
const txRequestId = txRequestForMessageSigning.txRequestId;
34853495

3496+
it('should create tx Request with signMessage intent', async function () {
3497+
nock(bgUrl).post(`/api/v2/wallet/${tssEthWallet.id()}/msgrequests`).reply(200, txRequestForMessageSigning);
3498+
3499+
const txRequest = await tssEthWallet.createSignMessageRequest({
3500+
message: messageRaw,
3501+
});
3502+
txRequest.should.deepEqual(txRequestForMessageSigning);
3503+
});
3504+
34863505
it('should sign message', async function () {
34873506
const signMessageTssSpy = sinon.spy(tssEthWallet, 'signMessageTss' as any);
34883507
nock(bgUrl)

modules/sdk-core/src/bitgo/utils/tss/baseTSSUtils.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import { RequestTracer } from '../util';
4343
import * as openpgp from 'openpgp';
4444
import { envRequiresBitgoPubGpgKeyConfig, getBitgoMpcGpgPubKey } from '../../tss/bitgoPubKeys';
4545
import { getBitgoGpgPubKey } from '../opengpgUtils';
46+
import assert from 'assert';
4647

4748
/**
4849
* BaseTssUtil class which different signature schemes have to extend
@@ -379,6 +380,30 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
379380
return this.createTxRequestBase(intentOptions, apiVersion, preview, params.reqId);
380381
}
381382

383+
/**
384+
* Create a sign message request
385+
*
386+
* @param params
387+
*/
388+
async createSignMessageRequest(params: IntentOptionsForMessage): Promise<TxRequest> {
389+
assert(
390+
params.intentType === 'signMessage',
391+
'Intent type must be signMessage for createMsgRequestWithSignMessageIntent'
392+
);
393+
const intentOptions: PopulatedIntentForMessageSigning = {
394+
custodianMessageId: params.custodianMessageId,
395+
intentType: params.intentType,
396+
sequenceId: params.sequenceId,
397+
comment: params.comment,
398+
memo: params.memo?.value,
399+
isTss: params.isTss,
400+
messageRaw: params.messageRaw,
401+
messageEncoded: params.messageEncoded ?? '',
402+
};
403+
404+
return this.createSignMessageRequestBase(intentOptions, params.reqId);
405+
}
406+
382407
/**
383408
* Create a tx request from params for type data signing
384409
*
@@ -432,6 +457,29 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
432457
.result();
433458
}
434459

460+
/**
461+
* Calls Bitgo API to create msg request.
462+
*
463+
* @private
464+
*/
465+
private async createSignMessageRequestBase(
466+
intentOptions: PopulatedIntentForMessageSigning,
467+
reqId?: IRequestTracer
468+
): Promise<TxRequest> {
469+
const whitelistedParams = {
470+
intent: {
471+
...intentOptions,
472+
},
473+
};
474+
475+
const reqTracer = reqId || new RequestTracer();
476+
this.bitgo.setRequestTracer(reqTracer);
477+
return this.bitgo
478+
.post(this.bitgo.url(`/wallet/${this.wallet.id()}/msgrequests`, 2))
479+
.send(whitelistedParams)
480+
.result();
481+
}
482+
435483
/**
436484
* Call delete signature shares for a txRequest, the endpoint delete the signatures and return them
437485
*

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,49 @@ export class Wallet implements IWallet {
20932093
return this.signMessageTss(presign);
20942094
}
20952095

2096+
/**
2097+
* Prepares and creates a sign message request for TSS wallets, that can be used later for signing.
2098+
*
2099+
* @param params - Parameters for creating the sign message request
2100+
* @returns Promise<TxRequest> - The created transaction request for signing a message
2101+
*/
2102+
async createSignMessageRequest(params: {
2103+
message: string;
2104+
custodianMessageId?: string;
2105+
reqId?: RequestTracer;
2106+
}): Promise<TxRequest> {
2107+
if (this._wallet.multisigType !== 'tss') {
2108+
throw new Error('Message signing only supported for TSS wallets');
2109+
}
2110+
2111+
if (!this.baseCoin.supportsMessageSigning()) {
2112+
throw new Error(`Message signing not supported for ${this.baseCoin.getFullName()}`);
2113+
}
2114+
2115+
if (!params.message) {
2116+
throw new Error('message required to create message sign request');
2117+
}
2118+
2119+
const reqId = params.reqId || new RequestTracer();
2120+
2121+
try {
2122+
const intentOption: IntentOptionsForMessage = {
2123+
custodianMessageId: params.custodianMessageId,
2124+
reqId,
2125+
intentType: 'signMessage',
2126+
isTss: true,
2127+
messageRaw: params.message,
2128+
};
2129+
2130+
if (!this.tssUtils) {
2131+
throw new Error('TSS utilities not available for this wallet');
2132+
}
2133+
return await this.tssUtils.createSignMessageRequest(intentOption);
2134+
} catch (error) {
2135+
throw new Error(`Failed to create message sign request: ${error}`);
2136+
}
2137+
}
2138+
20962139
/**
20972140
* Get the user private key from either a derivation or an encrypted keychain
20982141
* @param [params.keychain / params.key] (object) or params.prv (string)

0 commit comments

Comments
 (0)