From aaf9e2fec34a0e3de0fdd26c2126f3515919b3f5 Mon Sep 17 00:00:00 2001 From: Doddanna17 Date: Tue, 15 Sep 2026 13:35:17 +0530 Subject: [PATCH 1/2] fix(sdk-core): restore typed subtype payloads Add typed top-level staking subtypes and verify SDK request serialization for subtype-bearing flows. Ticket: SI-1544 --- .../v2/unit/staking/stakingWalletCommon.ts | 22 ++++++++++ .../src/bitgo/staking/iStakingWallet.ts | 40 ++++++++++++++++--- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/modules/bitgo/test/v2/unit/staking/stakingWalletCommon.ts b/modules/bitgo/test/v2/unit/staking/stakingWalletCommon.ts index 80ddab3997..a1b3d58ba8 100644 --- a/modules/bitgo/test/v2/unit/staking/stakingWalletCommon.ts +++ b/modules/bitgo/test/v2/unit/staking/stakingWalletCommon.ts @@ -84,6 +84,28 @@ describe('Staking Wallet Common', function () { msScope.isDone().should.be.True(); }); + it('should forward top-level staking subtype to staking-service', async function () { + const expected = fixtures.stakingRequest([fixtures.transaction('NEW')]); + const msScope = nock(microservicesUri) + .post(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests`, { + amount: '1', + clientId: 'clientId', + subType: 'ETH_STAKE_PECTRA', + type: 'STAKE', + }) + .reply(201, expected); + + const stakingRequest = await stakingWallet.stake({ + amount: '1', + clientId: 'clientId', + subType: 'ETH_STAKE_PECTRA', + }); + + should.exist(stakingRequest); + stakingRequest.should.deepEqual(expected); + msScope.isDone().should.be.True(); + }); + it('should call staking-service to stake with optional stakeMany parameters', async function () { const expected = fixtures.stakingRequest([fixtures.transaction('NEW')]); const msScope = nock(microservicesUri) diff --git a/modules/sdk-core/src/bitgo/staking/iStakingWallet.ts b/modules/sdk-core/src/bitgo/staking/iStakingWallet.ts index ec7c8ef90f..fcb4c2d186 100644 --- a/modules/sdk-core/src/bitgo/staking/iStakingWallet.ts +++ b/modules/sdk-core/src/bitgo/staking/iStakingWallet.ts @@ -1,6 +1,34 @@ import { SignedTransaction } from '../baseCoin'; import { PrebuildTransactionOptions, PrebuildTransactionResult } from '../wallet'; +/** + * All known staking subtypes across coins. + * Used by StakeOptions.subType for compile-time type safety. + */ +export type StakingSubType = + | 'STAKE' + | 'ETH_STAKE_PECTRA' + | 'LIDO' + | 'SOL_STAKE' + | 'MARINADE' + | 'MARINADE_SELECT' + | 'NATIVE_STAKE' + | 'INFRARED_LIQUID_STAKE' + | 'WCT_STAKE' + | 'STACK' + | 'SELF_STACK' + | 'MULTI_NOMINATOR_STAKE' + | 'SINGLE_NOMINATOR_STAKE' + | 'TON_WHALES' + | 'VET_VALIDATOR_REGISTRATION' + | 'VET_UNSTAKE' + | 'VET_INCREASE_STAKE' + | 'STAVAX_STAKE' + | 'PSTAVAX_STAKE' + | 'WFLR_STAKE' + | 'VOTE' + | 'STX_BTC_POX5_BOND'; + export interface StakingRequest { id: string; amount: string; @@ -34,7 +62,7 @@ export type BabylonParams = { }; export interface Pox5StakeOptions extends Omit { - subType: 'pox5-bond'; + subType: 'STX_BTC_POX5_BOND'; bondIndex: number; signerManager: string; numCycles?: string; @@ -88,9 +116,10 @@ export interface StakeOptions { */ blsSignature?: string; /** - * subtype-specific interfaces provide their own discriminant + * coin-specific staking subtype, forwarded to staking-service. + * Restricted to known values via StakingSubType union. */ - subType?: never; + subType?: StakingSubType; /** * stx btc reward address */ @@ -214,9 +243,10 @@ export interface UnstakeOptions { clientId?: string; delegationId?: string; /** - * coin sepcific staking subtype + * coin-specific staking subtype for unstaking. + * Restricted to known values via StakingSubType union. */ - subType?: string; + subType?: StakingSubType; } export interface EthUnstakeOptions { From 10876752b799342ad930303ad9e1ebc7e26aed26 Mon Sep 17 00:00:00 2001 From: Doddanna17 Date: Tue, 15 Sep 2026 14:10:39 +0530 Subject: [PATCH 2/2] fix(sdk-core): preserve legacy pox5 subtype Keep pox5-bond wire compatibility while restoring typed subtype payload support for existing staking flows. Ticket: SI-1544 --- .../v2/unit/staking/stakingWalletCommon.ts | 26 +++++++++++++++++++ .../src/bitgo/staking/iStakingWallet.ts | 4 +-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/modules/bitgo/test/v2/unit/staking/stakingWalletCommon.ts b/modules/bitgo/test/v2/unit/staking/stakingWalletCommon.ts index a1b3d58ba8..81aabd61c8 100644 --- a/modules/bitgo/test/v2/unit/staking/stakingWalletCommon.ts +++ b/modules/bitgo/test/v2/unit/staking/stakingWalletCommon.ts @@ -106,6 +106,32 @@ describe('Staking Wallet Common', function () { msScope.isDone().should.be.True(); }); + it('should preserve the legacy PoX-5 subtype on the wire', async function () { + const expected = fixtures.stakingRequest([fixtures.transaction('NEW')]); + const msScope = nock(microservicesUri) + .post(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests`, { + amount: '1', + bondIndex: 0, + clientId: 'clientId', + signerManager: 'manager', + subType: 'pox5-bond', + type: 'STAKE', + }) + .reply(201, expected); + + const stakingRequest = await stakingWallet.stake({ + amount: '1', + bondIndex: 0, + clientId: 'clientId', + signerManager: 'manager', + subType: 'pox5-bond', + }); + + should.exist(stakingRequest); + stakingRequest.should.deepEqual(expected); + msScope.isDone().should.be.True(); + }); + it('should call staking-service to stake with optional stakeMany parameters', async function () { const expected = fixtures.stakingRequest([fixtures.transaction('NEW')]); const msScope = nock(microservicesUri) diff --git a/modules/sdk-core/src/bitgo/staking/iStakingWallet.ts b/modules/sdk-core/src/bitgo/staking/iStakingWallet.ts index fcb4c2d186..0010b4f7ed 100644 --- a/modules/sdk-core/src/bitgo/staking/iStakingWallet.ts +++ b/modules/sdk-core/src/bitgo/staking/iStakingWallet.ts @@ -27,7 +27,7 @@ export type StakingSubType = | 'PSTAVAX_STAKE' | 'WFLR_STAKE' | 'VOTE' - | 'STX_BTC_POX5_BOND'; + | 'pox5-bond'; export interface StakingRequest { id: string; @@ -62,7 +62,7 @@ export type BabylonParams = { }; export interface Pox5StakeOptions extends Omit { - subType: 'STX_BTC_POX5_BOND'; + subType: 'pox5-bond'; bondIndex: number; signerManager: string; numCycles?: string;