Skip to content

Commit 8a50ff8

Browse files
committed
fix(sdk-coin-stx): return required fields for unsigned sweep
Ticket: COIN-3893
1 parent ffa03f7 commit 8a50ff8

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

modules/sdk-coin-stx/src/lib/iface.ts

+9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22
import { ClarityValue, PayloadType } from '@stacks/transactions';
3+
import { TransactionExplanation as BaseTransactionExplanation } from '@bitgo/sdk-core';
34

45
export interface TxData {
56
id: string;
@@ -107,6 +108,14 @@ export interface RecoveryOptions {
107108
contractId?: string;
108109
}
109110

111+
export interface RecoveryInfo extends BaseTransactionExplanation {
112+
txHex: string;
113+
feeInfo?: {
114+
fee: string;
115+
};
116+
coin?: string;
117+
}
118+
110119
export interface RecoveryTransaction {
111120
txHex: string;
112121
}

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

+22-6
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,13 @@ import { findContractTokenNameUsingContract, findTokenNameByContract, getAddress
4242
import {
4343
AddressDetails,
4444
NativeStxBalance,
45+
RecoveryInfo,
4546
RecoveryOptions,
4647
RecoveryTransaction,
4748
SingleFungibleTokenBalance,
4849
StxNonceResponse,
4950
StxTxnFeeEstimationResponse,
51+
TxData,
5052
} from './lib/iface';
5153
import { TransferBuilder } from './lib/transferBuilder';
5254
import { FungibleTokenTransferBuilder } from './lib/fungibleTokenTransferBuilder';
@@ -410,6 +412,23 @@ export class Stx extends BaseCoin {
410412
}
411413
}
412414

415+
/**
416+
* Format for offline vault signing
417+
* @param {BaseTransaction} tx - base transaction
418+
* @returns {Promise<RecoveryInfo>}
419+
*/
420+
protected async formatForOfflineVault(tx: BaseTransaction): Promise<RecoveryInfo> {
421+
const txJson: TxData = tx.toJson();
422+
const transactionExplanation: RecoveryInfo = (await this.explainTransaction({
423+
txHex: tx.toBroadcastFormat(),
424+
feeInfo: { fee: txJson.fee },
425+
})) as RecoveryInfo;
426+
transactionExplanation.coin = this.getChain();
427+
transactionExplanation.feeInfo = { fee: txJson.fee };
428+
transactionExplanation.txHex = tx.toBroadcastFormat();
429+
return transactionExplanation;
430+
}
431+
413432
/**
414433
* Get the recoverable amount & fee after subtracting the txn fee
415434
* @param {String} serializedHex - serialized txn hex
@@ -667,9 +686,9 @@ export class Stx extends BaseCoin {
667686
* @param {String} params.bitgoKey - encrypted bitgo public key
668687
* @param {String} params.walletPassphrase - wallet password
669688
* @param {String} params.contractId - contract id of the token (mandatory for token recovery)
670-
* @returns {Promise<RecoveryTransaction>} RecoveryTransaction.txHex - hex of serialized transaction (signed or unsigned)
689+
* @returns {Promise<RecoveryInfo|RecoveryTransaction>} RecoveryTransaction.txHex - hex of serialized transaction (signed or unsigned)
671690
*/
672-
async recover(params: RecoveryOptions): Promise<RecoveryTransaction> {
691+
async recover(params: RecoveryOptions): Promise<RecoveryInfo | RecoveryTransaction> {
673692
if (!this.isValidAddress(params.rootAddress)) {
674693
throw new Error('invalid root address!');
675694
}
@@ -713,12 +732,9 @@ export class Stx extends BaseCoin {
713732
contractAddressInput: contractAddress,
714733
contractName: contractName,
715734
});
716-
const serializedTx: string = tx.toBroadcastFormat();
717735

718736
if (isUnsignedSweep) {
719-
return {
720-
txHex: serializedTx,
721-
};
737+
return await this.formatForOfflineVault(tx);
722738
}
723739
// check the private key & sign
724740
if (!keys[0].privateKey) {

modules/sdk-coin-stx/test/unit/sip10Token.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ITransactionRecipient, Wallet, Memo } from '@bitgo/sdk-core';
66

77
import { Sip10Token } from '../../src';
88
import * as testData from '../fixtures';
9-
import { RecoveryOptions, RecoveryTransaction } from '../../src/lib/iface';
9+
import { RecoveryInfo, RecoveryOptions, RecoveryTransaction } from '../../src/lib/iface';
1010
import assert from 'assert';
1111

1212
describe('Sip10Token:', function () {
@@ -309,9 +309,12 @@ describe('Sip10Token:', function () {
309309
bitgoKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.BITGO_PUB_KEY,
310310
contractId: 'STAG18E45W613FZ3H4ZMF6QHH426EXM5QTSAVWYH.tsip6dp-token',
311311
};
312-
const response: RecoveryTransaction = await basecoin.recover(recoveryOptions);
312+
const response: RecoveryInfo = (await basecoin.recover(recoveryOptions)) as RecoveryInfo;
313313
response.should.have.property('txHex');
314+
response.should.have.property('coin');
315+
response.should.have.property('feeInfo');
314316
assert.deepEqual(response.txHex, testData.COLD_WALLET_TOKEN_UNSIGNED_SWEEP_TX_HEX, 'tx hex not matching!');
317+
assert.deepEqual(response.coin, 'tstx:tsip6dp', 'coin not matching!');
315318
});
316319

317320
it('should fail with insufficient balance when native stx balance is lower than fee for sip10', async () => {

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { cvToString } from '@stacks/transactions';
99

1010
import * as testData from '../fixtures';
1111
import { Stx, StxLib, Tstx } from '../../src';
12-
import { RecoveryOptions, RecoveryTransaction } from '../../src/lib/iface';
12+
import { RecoveryInfo, RecoveryOptions, RecoveryTransaction } from '../../src/lib/iface';
1313

1414
const { KeyPair } = StxLib;
1515

@@ -399,9 +399,12 @@ describe('STX:', function () {
399399
recoveryDestination: testData.DESTINATION_ADDRESS_WRW,
400400
bitgoKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.BITGO_PUB_KEY,
401401
};
402-
const response: RecoveryTransaction = await basecoin.recover(recoveryOptions);
402+
const response: RecoveryInfo = await basecoin.recover(recoveryOptions);
403403
response.should.have.property('txHex');
404+
response.should.have.property('coin');
405+
response.should.have.property('feeInfo');
404406
assert.deepEqual(response.txHex, testData.COLD_WALLET_UNSIGNED_SWEEP_TX_HEX, 'tx hex not matching!');
407+
assert.deepEqual(response.coin, 'tstx', 'coin not matching!');
405408
});
406409

407410
it('should throw invalid root address when root address is missing or invalid', async function () {

0 commit comments

Comments
 (0)