Skip to content

Commit e1378ac

Browse files
authored
Merge pull request #8173 from BitGo/copilot/add-get-account-resources-method
Add getAccountResources method to Wallet class
2 parents 5b21168 + d286299 commit e1378ac

File tree

4 files changed

+217
-0
lines changed

4 files changed

+217
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Get account resources for a Tron wallet at BitGo.
3+
*
4+
* This tool will help you see how to use the BitGo API to easily get
5+
* account resources information for a wallet.
6+
*
7+
* Copyright 2026, BitGo, Inc. All Rights Reserved.
8+
*/
9+
import { BitGo } from 'bitgo';
10+
11+
// TODO: change to 'production' for mainnet
12+
const env = 'test';
13+
const bitgo = new BitGo({ env });
14+
15+
// TODO: change to 'trx' for mainnet or 'ttrx:<token>' for testnet token
16+
const coin = 'ttrx';
17+
18+
// TODO: set your wallet id
19+
const walletId = '';
20+
21+
// TODO: set your access token here
22+
// You can get this from User Settings > Developer Options > Add Access Token
23+
const accessToken = '';
24+
25+
// TODO: set the addresses to query
26+
// Note: To get energy deficit for a token transfer, make sure the token exists in the address.
27+
const addresses = [''];
28+
29+
async function main() {
30+
bitgo.authenticateWithAccessToken({ accessToken });
31+
32+
const wallet = await bitgo.coin(coin).wallets().getWallet({ id: walletId });
33+
34+
console.log('Wallet ID:', wallet.id());
35+
36+
const resources = await wallet.getAccountResources({ addresses });
37+
console.log('Account Resources:', JSON.stringify(resources, null, 2));
38+
}
39+
40+
main().catch((e) => console.error(e));

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,41 @@ export interface ForwarderBalanceOptions {
539539
maximumBalance?: number;
540540
}
541541

542+
export interface GetAccountResourcesOptions {
543+
addresses: string[];
544+
destinationAddress?: string;
545+
}
546+
547+
export interface AccountResourceInfo {
548+
address: string;
549+
free_bandwidth_available: number;
550+
free_bandwidth_used: number;
551+
staked_bandwidth_available: number;
552+
staked_bandwidth_used: number;
553+
energy_available: number;
554+
energy_used: number;
555+
resourceDeficitForAssetTransfer?: {
556+
bandwidthDeficit: number;
557+
bandwidthSunRequired: string;
558+
energyDeficit?: number;
559+
energySunRequired?: string;
560+
};
561+
maxResourcesDelegatable?: {
562+
bandwidthWeight: string;
563+
energyWeight: string;
564+
};
565+
}
566+
567+
export interface FailedAddressInfo {
568+
address: string;
569+
error: string;
570+
}
571+
572+
export interface GetAccountResourcesResponse {
573+
resources: AccountResourceInfo[];
574+
failedAddresses: FailedAddressInfo[];
575+
}
576+
542577
export type CreateAddressFormat = 'base58' | 'cashaddr';
543578

544579
export interface CreateAddressOptions {
@@ -988,6 +1023,7 @@ export interface IWallet {
9881023
getAddress(params?: GetAddressOptions): Promise<any>;
9891024
createAddress(params?: CreateAddressOptions): Promise<any>;
9901025
updateAddress(params?: UpdateAddressOptions): Promise<any>;
1026+
getAccountResources(params: GetAccountResourcesOptions): Promise<GetAccountResourcesResponse>;
9911027
listWebhooks(params?: PaginationOptions): Promise<any>;
9921028
simulateWebhook(params?: SimulateWebhookOptions): Promise<any>;
9931029
addWebhook(params?: ModifyWebhookOptions): Promise<any>;

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ import {
125125
WalletType,
126126
BuildTokenApprovalResponse,
127127
WalletInitResult,
128+
GetAccountResourcesOptions,
129+
GetAccountResourcesResponse,
128130
} from './iWallet';
129131

130132
const debug = require('debug')('bitgo:v2:wallet');
@@ -1465,6 +1467,30 @@ export class Wallet implements IWallet {
14651467
return this.bitgo.put(url).send(putParams).result();
14661468
}
14671469

1470+
/**
1471+
* Get account resources for the given addresses
1472+
* @param params - options object containing addresses and optional destinationAddress
1473+
* @returns {Promise<GetAccountResourcesResponse>} - response from WP API
1474+
*/
1475+
async getAccountResources(params: GetAccountResourcesOptions): Promise<GetAccountResourcesResponse> {
1476+
const { addresses, destinationAddress } = params;
1477+
1478+
if (!Array.isArray(addresses)) {
1479+
throw new Error('addresses must be an array');
1480+
}
1481+
1482+
if (addresses.length === 0) {
1483+
throw new Error('addresses array cannot be empty');
1484+
}
1485+
1486+
const query: GetAccountResourcesOptions = { addresses };
1487+
if (destinationAddress) {
1488+
query.destinationAddress = destinationAddress;
1489+
}
1490+
1491+
return this.bitgo.get(this.url('/getAccountResources')).query(query).result();
1492+
}
1493+
14681494
async updateWalletBuildDefaults(params: UpdateBuildDefaultOptions): Promise<unknown> {
14691495
common.validateParams(params, [], ['minFeeRate', 'changeAddressType', 'txFormat']);
14701496
return this.updateWallet({
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import * as assert from 'assert';
2+
import * as sinon from 'sinon';
3+
import 'should';
4+
import { Wallet } from '../../../../src';
5+
6+
describe('Wallet - getAccountResources', function () {
7+
let wallet: Wallet;
8+
let mockBitGo: any;
9+
let mockBaseCoin: any;
10+
let mockWalletData: any;
11+
12+
beforeEach(function () {
13+
mockBitGo = {
14+
get: sinon.stub(),
15+
};
16+
17+
mockBaseCoin = {
18+
url: sinon.stub().returns('/test/coin'),
19+
supportsTss: sinon.stub().returns(false),
20+
};
21+
22+
mockWalletData = {
23+
id: 'test-wallet-id',
24+
keys: ['user-key', 'backup-key', 'bitgo-key'],
25+
};
26+
27+
wallet = new Wallet(mockBitGo, mockBaseCoin, mockWalletData);
28+
});
29+
30+
afterEach(function () {
31+
sinon.restore();
32+
});
33+
34+
describe('getAccountResources', function () {
35+
it('should call WP API with addresses parameter', async function () {
36+
const mockResponse = {
37+
resources: [
38+
{ address: 'address1', balance: 100 },
39+
{ address: 'address2', balance: 200 },
40+
],
41+
};
42+
43+
mockBitGo.get.returns({
44+
query: sinon.stub().returns({
45+
result: sinon.stub().resolves(mockResponse),
46+
}),
47+
});
48+
49+
const addresses = ['address1', 'address2'];
50+
const result = await wallet.getAccountResources({ addresses });
51+
52+
result.should.deepEqual(mockResponse);
53+
sinon.assert.calledOnce(mockBitGo.get);
54+
const queryStub = mockBitGo.get.returnValues[0].query;
55+
sinon.assert.calledWith(queryStub, { addresses });
56+
});
57+
58+
it('should call WP API with addresses and destinationAddress parameters', async function () {
59+
const mockResponse = {
60+
resources: [{ address: 'address1', balance: 100 }],
61+
};
62+
63+
mockBitGo.get.returns({
64+
query: sinon.stub().returns({
65+
result: sinon.stub().resolves(mockResponse),
66+
}),
67+
});
68+
69+
const addresses = ['address1'];
70+
const destinationAddress = 'TDestAddress123';
71+
const result = await wallet.getAccountResources({ addresses, destinationAddress });
72+
73+
result.should.deepEqual(mockResponse);
74+
sinon.assert.calledOnce(mockBitGo.get);
75+
const queryStub = mockBitGo.get.returnValues[0].query;
76+
sinon.assert.calledWith(queryStub, { addresses, destinationAddress });
77+
});
78+
79+
it('should throw error if addresses is not an array', async function () {
80+
try {
81+
await wallet.getAccountResources({ addresses: 'not-an-array' as any });
82+
assert.fail('Should have thrown error');
83+
} catch (error) {
84+
error.message.should.equal('addresses must be an array');
85+
}
86+
});
87+
88+
it('should throw error if addresses array is empty', async function () {
89+
try {
90+
await wallet.getAccountResources({ addresses: [] });
91+
assert.fail('Should have thrown error');
92+
} catch (error) {
93+
error.message.should.equal('addresses array cannot be empty');
94+
}
95+
});
96+
97+
it('should not include destinationAddress in query if not provided', async function () {
98+
const mockResponse = { resources: [] };
99+
100+
mockBitGo.get.returns({
101+
query: sinon.stub().returns({
102+
result: sinon.stub().resolves(mockResponse),
103+
}),
104+
});
105+
106+
const addresses = ['address1'];
107+
await wallet.getAccountResources({ addresses });
108+
109+
const queryStub = mockBitGo.get.returnValues[0].query;
110+
const queryArg = queryStub.firstCall.args[0];
111+
queryArg.should.deepEqual({ addresses });
112+
queryArg.should.not.have.property('destinationAddress');
113+
});
114+
});
115+
});

0 commit comments

Comments
 (0)