Skip to content

Commit 9af1239

Browse files
chore(sdk-core): change unstaking wallet id for btc unstaking
2 parents a891814 + ab12948 commit 9af1239

File tree

4 files changed

+100
-3
lines changed

4 files changed

+100
-3
lines changed

modules/bitgo/test/v2/fixtures/staking/stakingWallet.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ export default {
2323
transaction: function (
2424
status: string,
2525
buildParams?: PrebuildTransactionOptions,
26-
setTxRequestId = true
26+
setTxRequestId = true,
27+
transactionType = 'DELEGATE'
2728
): StakingTransaction {
2829
const transaction: StakingTransaction = {
2930
id: '00566722-daef-40eb-b0ac-fa5402bbfe72',
3031
stakingRequestId: '8638284a-dab2-46b9-b07f-21109a6e7220',
3132
delegationId: '505bda16-a000-461a-8421-1cf3f8617883',
32-
transactionType: 'DELEGATE',
33+
transactionType,
3334
createdDate: '2022-01-03T22:04:29.264Z',
3435
status: status,
3536
statusModifiedDate: '2022-01-03T22:04:29.264Z',
@@ -60,4 +61,20 @@ export default {
6061
actionType: 'DELEGATE',
6162
},
6263
},
64+
btcUnstakingBuildParams: {
65+
recipients: [
66+
{
67+
amount: '1234',
68+
address: 'address',
69+
data: 'data',
70+
},
71+
],
72+
stakingParams: {
73+
requestId: '8638284a-dab2-46b9-b07f-21109a6e7220',
74+
amount: '1234',
75+
validator: 'validator',
76+
actionType: 'DELEGATE',
77+
},
78+
senderWalletId: 'btcDescriptorWalletId',
79+
},
6380
};

modules/bitgo/test/v2/unit/staking/stakingWalletNonTSS.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@ describe('non-TSS Staking Wallet', function () {
1313
let bitgo;
1414
let ethBaseCoin;
1515
let maticBaseCoin;
16+
let btcBaseCoin;
1617
let enterprise;
1718
let ethWalletData: any;
19+
let btcWalletData: any;
20+
let btcDescriptorWalletData: any;
1821
let ethStakingWallet: StakingWallet;
1922
let maticStakingWallet: StakingWallet;
23+
let btcStakingWallet: StakingWallet;
2024

2125
before(function () {
2226
bitgo = TestBitGo.decorate(BitGo, { env: 'mock', microservicesUri } as any);
@@ -25,6 +29,8 @@ describe('non-TSS Staking Wallet', function () {
2529
ethBaseCoin.keychains();
2630
maticBaseCoin = bitgo.coin('matic');
2731
maticBaseCoin.keychains();
32+
btcBaseCoin = bitgo.coin('btc');
33+
btcBaseCoin.keychains();
2834

2935
enterprise = new Enterprise(bitgo, ethBaseCoin, {
3036
id: '5cf940949449412d00f53b3d92dbcaa3',
@@ -43,10 +49,26 @@ describe('non-TSS Staking Wallet', function () {
4349
enterprise: enterprise.id,
4450
keys: ['5b3424f91bf349930e340175'],
4551
};
52+
btcWalletData = {
53+
id: 'btcWalletId',
54+
coin: 'btc',
55+
enterprise: enterprise.id,
56+
keys: ['5b3424f91bf349930e340175'],
57+
coinSpecific: {},
58+
};
59+
btcDescriptorWalletData = {
60+
id: 'btcDescriptorWalletId',
61+
coin: 'btc',
62+
enterprise: enterprise.id,
63+
keys: ['5b3424f91bf349930e340175'],
64+
coinSpecific: {},
65+
};
4666
const ethWallet = new Wallet(bitgo, ethBaseCoin, ethWalletData);
4767
const maticWallet = new Wallet(bitgo, maticBaseCoin, maticWalletData);
68+
const btcWallet = new Wallet(bitgo, btcBaseCoin, btcWalletData);
4869
ethStakingWallet = ethWallet.toStakingWallet();
4970
maticStakingWallet = maticWallet.toStakingWallet();
71+
btcStakingWallet = btcWallet.toStakingWallet();
5072
});
5173

5274
const sandbox = sinon.createSandbox();
@@ -207,4 +229,41 @@ describe('non-TSS Staking Wallet', function () {
207229
stakingTransaction.should.deepEqual(transaction);
208230
});
209231
});
232+
233+
describe('BTC staking', function () {
234+
it('btc delegation transaction', async function () {
235+
const transaction = fixtures.transaction('READY', fixtures.buildParams, false);
236+
237+
nock(microservicesUri)
238+
.get(
239+
`/api/staking/v1/${btcStakingWallet.coin}/wallets/${btcStakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`
240+
)
241+
.query({ expandBuildParams: true })
242+
.reply(200, transaction);
243+
244+
const prebuildTransaction = sandbox.stub(Wallet.prototype, 'prebuildTransaction');
245+
const descriptor = sandbox.stub(StakingWallet.prototype, <any>'getDescriptorWallet');
246+
await btcStakingWallet.build(transaction);
247+
prebuildTransaction.calledOnceWithExactly(transaction.buildParams).should.be.true;
248+
descriptor.notCalled.should.be.true;
249+
});
250+
251+
it('btc undelegation transaction', async function () {
252+
const transaction = fixtures.transaction('READY', fixtures.btcUnstakingBuildParams, false, 'UNDELEGATE_WITHDRAW');
253+
254+
nock(microservicesUri)
255+
.get(
256+
`/api/staking/v1/${btcStakingWallet.coin}/wallets/${btcStakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`
257+
)
258+
.query({ expandBuildParams: true })
259+
.reply(200, transaction);
260+
nock(microservicesUri)
261+
.get(`/api/v2/btc/wallet/${btcDescriptorWalletData.id}`)
262+
.reply(200, btcDescriptorWalletData);
263+
264+
const prebuildTransaction = sandbox.stub(Wallet.prototype, 'prebuildTransaction');
265+
await btcStakingWallet.build(transaction);
266+
prebuildTransaction.calledOnceWithExactly(transaction.buildParams).should.be.true;
267+
});
268+
});
210269
});

modules/sdk-core/src/bitgo/staking/stakingWallet.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
import { BitGoBase } from '../bitgoBase';
2121
import { IWallet, PrebuildTransactionResult } from '../wallet';
2222
import { ITssUtils, RequestTracer, TssUtils } from '../utils';
23+
import assert from 'assert';
2324

2425
export class StakingWallet implements IStakingWallet {
2526
private readonly bitgo: BitGoBase;
@@ -153,9 +154,15 @@ export class StakingWallet implements IStakingWallet {
153154
if (!transaction.buildParams) {
154155
throw Error(`Staking transaction ${transaction.id} build params not expanded`);
155156
}
157+
const isBtcUndelegate =
158+
this.wallet.baseCoin.getFamily() === 'btc' && transaction.transactionType === 'UNDELEGATE_WITHDRAW';
159+
const wallet = isBtcUndelegate
160+
? await this.getDescriptorWallet(transaction)
161+
: await this.getWalletForBuildingAndSigning();
162+
156163
return {
157164
transaction: transaction,
158-
result: await (await this.getWalletForBuildingAndSigning()).prebuildTransaction(transaction.buildParams),
165+
result: await wallet.prebuildTransaction(transaction.buildParams),
159166
};
160167
}
161168
}
@@ -320,4 +327,9 @@ export class StakingWallet implements IStakingWallet {
320327
return true;
321328
}
322329
}
330+
331+
private async getDescriptorWallet(transaction: StakingTransaction): Promise<IWallet> {
332+
assert(transaction.buildParams?.senderWalletId, 'senderWalletId is required for btc undelegate transaction');
333+
return await this.wallet.baseCoin.wallets().get({ id: transaction.buildParams.senderWalletId });
334+
}
323335
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@ export interface PrebuildTransactionOptions {
111111
* This feature is supported only for specific coins, like ADA.
112112
*/
113113
senderAddress?: string;
114+
115+
/**
116+
* The wallet ID of the sender wallet when sender wallet is different from current wallet id.
117+
* @type {string}
118+
* @default {undefined}
119+
* @description For BTC unstaking, the sender wallet(a descriptor wallet) is different from original wallet
120+
* */
121+
senderWalletId?: string;
122+
114123
changeAddress?: string;
115124
allowExternalChangeAddress?: boolean;
116125
type?: string;

0 commit comments

Comments
 (0)