Skip to content

Commit df8e227

Browse files
Merge pull request #7868 from BitGo/BTC-2887.update-wallet
feat(sdk-core): add updateWallet function and freezeDepositsFromShielded
2 parents 4e53e5a + 110d3dc commit df8e227

2 files changed

Lines changed: 110 additions & 28 deletions

File tree

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ export interface WalletCoinSpecific {
329329
hashAlgorithm?: string;
330330
pendingEcdsaTssInitialization?: boolean;
331331
features?: string[];
332+
freezeDepositsFromShielded?: boolean;
332333
/**
333334
* Lightning coin specific data starts
334335
*/
@@ -557,7 +558,13 @@ export interface UpdateAddressOptions {
557558
export interface UpdateBuildDefaultOptions {
558559
minFeeRate?: number;
559560
changeAddressType?: string;
560-
txFormat?: 'legacy' | 'psbt';
561+
txFormat?: 'legacy' | 'psbt' | 'psbt-lite';
562+
}
563+
564+
export interface UpdateWalletOptions {
565+
coinSpecific?: WalletCoinSpecific;
566+
buildDefaults?: UpdateBuildDefaultOptions;
567+
label?: string;
561568
}
562569

563570
export interface SimulateWebhookOptions {

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

Lines changed: 102 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ import {
115115
UnspentsOptions,
116116
UpdateAddressOptions,
117117
UpdateBuildDefaultOptions,
118+
UpdateWalletOptions,
118119
WalletCoinSpecific,
119120
WalletData,
120121
WalletEcdsaChallenges,
@@ -778,8 +779,13 @@ export class Wallet implements IWallet {
778779

779780
const response = await Promise.all(
780781
txPrebuilds.map(async (txPrebuild) => {
781-
const signedTransaction = await this.signTransaction({ ...transactionParams, txPrebuild });
782-
const finalTxParams = _.extend({}, signedTransaction, selectParams, { type: routeName });
782+
const signedTransaction = await this.signTransaction({
783+
...transactionParams,
784+
txPrebuild,
785+
});
786+
const finalTxParams = _.extend({}, signedTransaction, selectParams, {
787+
type: routeName,
788+
});
783789
this.bitgo.setRequestTracer(reqId);
784790
return this.sendTransaction(finalTxParams, reqId);
785791
})
@@ -795,9 +801,14 @@ export class Wallet implements IWallet {
795801
* @param params.modify - modify an existing reservation
796802
* @param params.delete - delete an existing reservation
797803
*/
798-
async manageUnspentReservations(
799-
params: ManageUnspentReservationOptions
800-
): Promise<{ unspents: { id: string; walletId: string; expireTime: string; userId?: string }[] }> {
804+
async manageUnspentReservations(params: ManageUnspentReservationOptions): Promise<{
805+
unspents: {
806+
id: string;
807+
walletId: string;
808+
expireTime: string;
809+
userId?: string;
810+
}[];
811+
}> {
801812
const filteredParams = _.pick(params, ['create', 'modify', 'delete']);
802813
this.bitgo.setRequestTracer(new RequestTracer());
803814
// The URL cannot contain the coinName, so we remove it from the URL
@@ -1446,14 +1457,29 @@ export class Wallet implements IWallet {
14461457

14471458
async updateWalletBuildDefaults(params: UpdateBuildDefaultOptions): Promise<unknown> {
14481459
common.validateParams(params, [], ['minFeeRate', 'changeAddressType', 'txFormat']);
1460+
return this.updateWallet({
1461+
buildDefaults: {
1462+
minFeeRate: params.minFeeRate,
1463+
changeAddressType: params.changeAddressType,
1464+
txFormat: params.txFormat,
1465+
},
1466+
});
1467+
}
1468+
1469+
async updateWallet(params: UpdateWalletOptions): Promise<unknown> {
1470+
const filteredParams = _.pick(params, ['coinSpecific', 'buildDefaults', 'label']);
1471+
const { coinSpecific, ...rest } = filteredParams;
14491472
return this.bitgo
14501473
.put(this.url())
14511474
.send({
1452-
buildDefaults: {
1453-
minFeeRate: params.minFeeRate,
1454-
changeAddressType: params.changeAddressType,
1455-
txFormat: params.txFormat,
1456-
},
1475+
...rest,
1476+
...(coinSpecific
1477+
? {
1478+
coinSpecific: {
1479+
[this.baseCoin.getChain()]: coinSpecific,
1480+
},
1481+
}
1482+
: {}),
14571483
})
14581484
.result();
14591485
}
@@ -1768,7 +1794,10 @@ export class Wallet implements IWallet {
17681794
keychain.prv = userPrv;
17691795
const eckey = makeRandomKey();
17701796
const secret = getSharedSecret(eckey, Buffer.from(pubkey, 'hex')).toString('hex');
1771-
const newEncryptedPrv = this.bitgo.encrypt({ password: secret, input: keychain.prv });
1797+
const newEncryptedPrv = this.bitgo.encrypt({
1798+
password: secret,
1799+
input: keychain.prv,
1800+
});
17721801

17731802
// Only one of pub/commonPub/commonKeychain should be present in the keychain
17741803
let pub = keychain.pub ?? keychain.commonPub;
@@ -1830,7 +1859,9 @@ export class Wallet implements IWallet {
18301859
throw new Error('missing required string parameter email');
18311860
}
18321861

1833-
const sharing = (await this.bitgo.getSharingKey({ email: params.email.toLowerCase() })) as any;
1862+
const sharing = (await this.bitgo.getSharingKey({
1863+
email: params.email.toLowerCase(),
1864+
})) as any;
18341865
let sharedKeychain;
18351866
if (needsKeychain) {
18361867
sharedKeychain = await this.prepareSharedKeychain(params.walletPassphrase, sharing.pubkey, sharing.path);
@@ -1931,13 +1962,18 @@ export class Wallet implements IWallet {
19311962
buildResponse.blockHeight = blockHeight;
19321963
}
19331964
let prebuild: TransactionPrebuild = (await this.baseCoin.postProcessPrebuild(
1934-
Object.assign(buildResponse, { wallet: this, buildParams: whitelistedParams })
1965+
Object.assign(buildResponse, {
1966+
wallet: this,
1967+
buildParams: whitelistedParams,
1968+
})
19351969
)) as any;
19361970
delete prebuild.wallet;
19371971
delete prebuild.buildParams;
19381972
prebuild = _.extend({}, prebuild, { walletId: this.id() });
19391973
if (this._wallet && this._wallet.coinSpecific && !params.walletContractAddress) {
1940-
prebuild = _.extend({}, prebuild, { walletContractAddress: this._wallet.coinSpecific.baseAddress });
1974+
prebuild = _.extend({}, prebuild, {
1975+
walletContractAddress: this._wallet.coinSpecific.baseAddress,
1976+
});
19411977
}
19421978
prebuild = _.extend({}, prebuild, { reqId: params.reqId });
19431979
debug('final transaction prebuild: %O', prebuild);
@@ -1962,13 +1998,21 @@ export class Wallet implements IWallet {
19621998
}
19631999
const reqId = new RequestTracer();
19642000
// Doing a sanity check for password here to avoid doing further work if we know it's wrong
1965-
const keychains = await this.getKeychainsAndValidatePassphrase({ reqId, walletPassphrase });
2001+
const keychains = await this.getKeychainsAndValidatePassphrase({
2002+
reqId,
2003+
walletPassphrase,
2004+
});
19662005
const userKeychain = keychains[0];
19672006
if (!userKeychain || !userKeychain.encryptedPrv) {
19682007
throw new Error('the user keychain does not have property encryptedPrv');
19692008
}
19702009

1971-
return this.signTransaction({ txPrebuild: { txRequestId }, walletPassphrase, reqId, keychain: userKeychain });
2010+
return this.signTransaction({
2011+
txPrebuild: { txRequestId },
2012+
walletPassphrase,
2013+
reqId,
2014+
keychain: userKeychain,
2015+
});
19722016
}
19732017

19742018
/**
@@ -2127,7 +2171,10 @@ export class Wallet implements IWallet {
21272171
params.typedData.typedDataEncoded = (this.baseCoin as any).encodeTypedData(params.typedData);
21282172
}
21292173
const keychains = await this.baseCoin.keychains().getKeysForSigning({ wallet: this, reqId: params.reqId });
2130-
const userPrvOptions: GetUserPrvOptions = { ...params, keychain: keychains[0] };
2174+
const userPrvOptions: GetUserPrvOptions = {
2175+
...params,
2176+
keychain: keychains[0],
2177+
};
21312178
assert(keychains[0].commonKeychain, 'Unable to find commonKeychain in keychains');
21322179
const presign = {
21332180
...params,
@@ -2163,7 +2210,10 @@ export class Wallet implements IWallet {
21632210
params.message.messageEncoded = (this.baseCoin as any).encodeMessage(params.message.messageRaw);
21642211
}
21652212
const keychains = await this.baseCoin.keychains().getKeysForSigning({ wallet: this, reqId: params.reqId });
2166-
const userPrvOptions: GetUserPrvOptions = { ...params, keychain: keychains[0] };
2213+
const userPrvOptions: GetUserPrvOptions = {
2214+
...params,
2215+
keychain: keychains[0],
2216+
};
21672217
assert(keychains[0].commonKeychain, 'Unable to find commonKeychain in keychains');
21682218
const presign = {
21692219
...params,
@@ -2247,7 +2297,10 @@ export class Wallet implements IWallet {
22472297

22482298
if (userPrv && params.coldDerivationSeed) {
22492299
// the derivation only makes sense when a key already exists
2250-
const derivation = this.baseCoin.deriveKeyWithSeed({ key: userPrv, seed: params.coldDerivationSeed });
2300+
const derivation = this.baseCoin.deriveKeyWithSeed({
2301+
key: userPrv,
2302+
seed: params.coldDerivationSeed,
2303+
});
22512304
userPrv = derivation.key;
22522305
} else if (!userPrv) {
22532306
if (!userKeychain || typeof userKeychain !== 'object') {
@@ -2568,7 +2621,9 @@ export class Wallet implements IWallet {
25682621
if (params.data && coin.transactionDataAllowed()) {
25692622
recipients[0].data = params.data;
25702623
}
2571-
const sendManyOptions: SendManyOptions = Object.assign({}, params, { recipients });
2624+
const sendManyOptions: SendManyOptions = Object.assign({}, params, {
2625+
recipients,
2626+
});
25722627
return this.sendMany(sendManyOptions);
25732628
}
25742629

@@ -2613,7 +2668,10 @@ export class Wallet implements IWallet {
26132668
);
26142669
}
26152670

2616-
const data = this.baseCoin.buildNftTransferData({ ...sendNftOptions, fromAddress: baseAddress });
2671+
const data = this.baseCoin.buildNftTransferData({
2672+
...sendNftOptions,
2673+
fromAddress: baseAddress,
2674+
});
26172675
let recipient;
26182676
if (this.baseCoin.getFamily() === 'vet') {
26192677
recipient = {
@@ -2650,7 +2708,10 @@ export class Wallet implements IWallet {
26502708
}
26512709
}
26522710

2653-
const data = this.baseCoin.buildNftTransferData({ ...sendNftOptions, fromAddress: baseAddress });
2711+
const data = this.baseCoin.buildNftTransferData({
2712+
...sendNftOptions,
2713+
fromAddress: baseAddress,
2714+
});
26542715
return this.sendMany({
26552716
...sendOptions,
26562717
recipients: [
@@ -3085,7 +3146,10 @@ export class Wallet implements IWallet {
30853146
const consolidations: PrebuildTransactionResult[] = [];
30863147
for (const consolidateAccountBuild of buildResponse) {
30873148
let prebuild: PrebuildTransactionResult = (await this.baseCoin.postProcessPrebuild(
3088-
Object.assign(consolidateAccountBuild, { wallet: this, buildParams: whitelistedParams })
3149+
Object.assign(consolidateAccountBuild, {
3150+
wallet: this,
3151+
buildParams: whitelistedParams,
3152+
})
30893153
)) as PrebuildTransactionResult;
30903154

30913155
delete prebuild.wallet;
@@ -3165,7 +3229,10 @@ export class Wallet implements IWallet {
31653229
});
31663230

31673231
// this gives us a set of account consolidation transactions
3168-
const unsignedBuilds = await this.buildAccountConsolidations({ ...params, apiVersion: apiVersion });
3232+
const unsignedBuilds = await this.buildAccountConsolidations({
3233+
...params,
3234+
apiVersion: apiVersion,
3235+
});
31693236
if (unsignedBuilds && unsignedBuilds.length > 0) {
31703237
// Get wallet's base address to validate destination addresses
31713238
const baseAddress = this._wallet.coinSpecific?.baseAddress || this._wallet.coinSpecific?.rootAddress;
@@ -3615,7 +3682,9 @@ export class Wallet implements IWallet {
36153682
txHex: unsignedTx.serializedTxHex,
36163683
buildParams: whitelistedParams,
36173684
feeInfo: unsignedTx.feeInfo,
3618-
...(txRequest.pendingApprovalId && { pendingApprovalId: txRequest.pendingApprovalId }),
3685+
...(txRequest.pendingApprovalId && {
3686+
pendingApprovalId: txRequest.pendingApprovalId,
3687+
}),
36193688
};
36203689
}
36213690

@@ -4003,7 +4072,11 @@ export class Wallet implements IWallet {
40034072
const latestTxRequest = await getTxRequest(this.bitgo, this.id(), signedTransaction.txRequestId, params.reqId);
40044073
const reqId = params.reqId || new RequestTracer();
40054074
this.bitgo.setRequestTracer(reqId);
4006-
const transfer: { state: string; pendingApproval?: string; txid?: string } = await this.bitgo
4075+
const transfer: {
4076+
state: string;
4077+
pendingApproval?: string;
4078+
txid?: string;
4079+
} = await this.bitgo
40074080
.post(
40084081
this.bitgo.url(
40094082
'/wallet/' + this._wallet.id + '/txrequests/' + signedTransaction.txRequestId + '/transfers',
@@ -4014,7 +4087,9 @@ export class Wallet implements IWallet {
40144087
.result();
40154088
if (latestTxRequest.state === 'pendingApproval') {
40164089
const pendingApprovals = new PendingApprovals(this.bitgo, this.baseCoin);
4017-
const pendingApproval = await pendingApprovals.get({ id: latestTxRequest.pendingApprovalId });
4090+
const pendingApproval = await pendingApprovals.get({
4091+
id: latestTxRequest.pendingApprovalId,
4092+
});
40184093
return {
40194094
pendingApproval: pendingApproval.toJSON(),
40204095
txRequest: latestTxRequest,

0 commit comments

Comments
 (0)