From 5b4270fa0214ab6b4ee77f7673ea9a5cd093df40 Mon Sep 17 00:00:00 2001 From: Ranjna Ganesh Ram Date: Wed, 19 Aug 2026 12:17:36 +0530 Subject: [PATCH] feat(sdk-coin-zec): add shielded wallet creation support to BitGoJS SDK Adds isShielded flag support for custodial wallet creation, enabling shielded Zcash (zec/tzec) wallet generation through wallet-platform. Includes validation to restrict shielded wallets to custodial type and require enterprise parameter. Adds comprehensive test coverage for both success and error cases. Ticket: CSHLD-1430 --- modules/bitgo/test/v2/unit/wallets.ts | 67 +++++++++++++++++++ modules/sdk-core/src/bitgo/wallet/iWallets.ts | 3 + modules/sdk-core/src/bitgo/wallet/wallets.ts | 18 +++++ 3 files changed, 88 insertions(+) diff --git a/modules/bitgo/test/v2/unit/wallets.ts b/modules/bitgo/test/v2/unit/wallets.ts index c9e2c3999f..e0afcf2199 100644 --- a/modules/bitgo/test/v2/unit/wallets.ts +++ b/modules/bitgo/test/v2/unit/wallets.ts @@ -988,6 +988,73 @@ describe('V2 Wallets:', function () { }); }); + describe('Generate shielded wallet:', function () { + const tzec = bitgo.coin('tzec'); + + it('should create a new shielded custodial wallet', async function () { + const keys = ['1', '2', '3']; + + const walletParams: GenerateWalletOptions = { + label: 'shielded wallet', + isShielded: true, + enterprise: 'enterprise', + type: 'custodial', + }; + + const walletNock = nock('https://bitgo.fakeurl') + .post('/api/v2/tzec/wallet/add', (body) => { + body.multisigType.should.equal(multisigTypes.tss); + body.coinSpecific.should.deepEqual({ isShielded: true }); + return true; + }) + .times(1) + .reply(200, { ...walletParams, multisigType: multisigTypes.tss, keys }); + + const shieldedWallets = new Wallets(bitgo, tzec); + + const res = await shieldedWallets.generateWallet(walletParams); + if (!isWalletWithKeychains(res)) { + throw new Error('wallet missing required keychains'); + } + res.wallet.label().should.equal(walletParams.label); + should.equal(res.wallet.type(), walletParams.type); + res.wallet.toJSON().enterprise.should.equal(walletParams.enterprise); + res.wallet.multisigType().should.equal(multisigTypes.tss); + res.userKeychain.type.should.equal('tss'); + res.backupKeychain.type.should.equal('tss'); + res.bitgoKeychain.type.should.equal('tss'); + + walletNock.isDone().should.be.true(); + }); + + it('should reject a non-custodial shielded wallet', async function () { + const walletParams: GenerateWalletOptions = { + label: 'shielded wallet', + isShielded: true, + enterprise: 'enterprise', + type: 'hot', + }; + + const shieldedWallets = new Wallets(bitgo, tzec); + + await shieldedWallets + .generateWallet(walletParams) + .should.be.rejectedWith('shielded wallets can only be created as custodial wallets'); + }); + + it('should reject a shielded wallet without an enterprise', async function () { + const walletParams: GenerateWalletOptions = { + label: 'shielded wallet', + isShielded: true, + type: 'custodial', + }; + + const shieldedWallets = new Wallets(bitgo, tzec); + + await shieldedWallets.generateWallet(walletParams).should.be.rejectedWith('enterprise is required'); + }); + }); + describe('Generate TSS MPCv2 wallet:', async function () { const sandbox = sinon.createSandbox(); diff --git a/modules/sdk-core/src/bitgo/wallet/iWallets.ts b/modules/sdk-core/src/bitgo/wallet/iWallets.ts index f8472165a3..b8e6040b2a 100644 --- a/modules/sdk-core/src/bitgo/wallet/iWallets.ts +++ b/modules/sdk-core/src/bitgo/wallet/iWallets.ts @@ -39,6 +39,7 @@ export interface GetWalletOptions { export interface GenerateBaseMpcWalletOptions { multisigType: 'tss'; + isShielded?: boolean; label: string; enterprise: string; walletVersion?: number; @@ -250,6 +251,8 @@ export interface GenerateWalletOptions { coldDerivationSeed?: string; rootPrivateKey?: string; multisigType?: 'onchain' | 'tss' | 'blsdkg'; + // Used for zec shielded custodial wallets + isShielded?: boolean; isDistributedCustody?: boolean; bitgoKeyId?: string; commonKeychain?: string; diff --git a/modules/sdk-core/src/bitgo/wallet/wallets.ts b/modules/sdk-core/src/bitgo/wallet/wallets.ts index 770f00c602..f87ecef546 100644 --- a/modules/sdk-core/src/bitgo/wallet/wallets.ts +++ b/modules/sdk-core/src/bitgo/wallet/wallets.ts @@ -474,6 +474,22 @@ export class Wallets implements IWallets { return walletData; } + // Transparent zcash wallets are multisig and isTSS is not set inherently. + // Shielded zcash wallets are MPC + if (params.isShielded) { + assert(enterprise, 'enterprise is required for shielded wallet'); + if (type !== 'custodial') { + throw new Error('shielded wallets can only be created as custodial wallets'); + } + return this.generateCustodialMpcWallet({ + multisigType: 'tss', + isShielded: true, + label, + enterprise, + walletVersion: params.walletVersion, + }); + } + // Handle distributed custody if (isDistributedCustody) { if (!enterprise) { @@ -2024,6 +2040,7 @@ export class Wallets implements IWallets { private async generateCustodialMpcWallet({ label, multisigType, + isShielded, enterprise, walletVersion, }: GenerateBaseMpcWalletOptions): Promise { @@ -2045,6 +2062,7 @@ export class Wallets implements IWallets { enterprise, walletVersion, type: 'custodial', + ...(isShielded && { coinSpecific: { isShielded: true } }), }; // Create Wallet