Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/ts/list-wallet-addresses-by-balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function main() {
const addresses = await wallet.addressesByBalance({
token: 'tapt:usdt',
});
console.log(JSON.stringify(addresses.addresses));
console.log(JSON.stringify(addresses.addresses, null, 2));
}

main().catch((e) => console.error(e));
74 changes: 74 additions & 0 deletions examples/ts/trx/delegate-resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Build and sign a TRX DelegateResource transaction via the BitGo platform.
*
* DelegateResource allows a TRX holder who has frozen TRX (via FreezeBalanceV2)
* to delegate the resulting BANDWIDTH or ENERGY resources to another address,
* without transferring TRX itself.
*
* Prerequisites:
* - Valid BitGo access token
* - TRX wallet with frozen balance (via FreezeBalanceV2)
* - Wallet passphrase for signing
*
* Copyright 2026, BitGo, Inc. All Rights Reserved.
*/
import { BitGoAPI } from '@bitgo/sdk-api';
import { Ttrx } from '@bitgo/sdk-coin-trx';
require('dotenv').config({ path: '../../../.env' });

// TODO: change to 'production' for mainnet
const bitgo = new BitGoAPI({
accessToken: process.env.TESTNET_ACCESS_TOKEN,
env: 'test',
});

const coin = 'ttrx';
bitgo.register(coin, Ttrx.createInstance);

const walletId = '';
const walletPassphrase = '';
const otp = '000000';

// TODO: set the receiver address (the address that will use the delegated resources)
const receiverAddress = '';

// TODO: set the amount of frozen TRX to delegate, in SUN (1 TRX = 1,000,000 SUN)
const amountSun = '1000000';

// TODO: set the resource type to delegate: 'energy' or 'bandwidth'
const resource = 'bandwidth';

async function main() {
const wallet = await bitgo.coin(coin).wallets().getWallet({ id: walletId });
console.log('Wallet ID:', wallet.id());

// Unlock the session for signing
const unlock = await bitgo.unlock({ otp, duration: 3600 });
if (!unlock) {
throw new Error('error unlocking session');
}

// Build, sign, and send the transaction in one step
// The SDK handles prebuild, user half-sign, platform co-signing, and broadcasting
const result = await wallet.sendMany({
type: 'delegateResource',
stakingParams: {
receiver_address: receiverAddress,
amount: amountSun,
resource,
},
recipients: [
{
address: receiverAddress,
amount: '0',
},
],
walletPassphrase,
});

console.log('Transaction sent successfully!');
console.log('TX ID:', result.txid);
console.log('Result:', JSON.stringify(result, null, 2));
}

main().catch((e) => console.error(e));
20 changes: 9 additions & 11 deletions examples/ts/trx/get-account-resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,29 @@
*
* Copyright 2026, BitGo, Inc. All Rights Reserved.
*/
import { BitGo } from 'bitgo';
import { BitGoAPI } from "@bitgo/sdk-api";
import { Ttrx } from "@bitgo/sdk-coin-trx";
require('dotenv').config({ path: '../../../.env' });

// TODO: change to 'production' for mainnet
const env = 'test';
const bitgo = new BitGo({ env });
const bitgo = new BitGoAPI({
accessToken: process.env.TESTNET_ACCESS_TOKEN,
env: 'test',
});

// TODO: change to 'trx' for mainnet or 'ttrx:<token>' for testnet token
const coin = 'ttrx';
bitgo.register(coin, Ttrx.createInstance);

// TODO: set your wallet id
const walletId = '';

// TODO: set your access token here
// You can get this from User Settings > Developer Options > Add Access Token
const accessToken = '';

// TODO: set the addresses to query
// Note: To get energy deficit for a token transfer, make sure the token exists in the address.
// Note: To get energy deficit for a token transfer/consolidation, make sure the token exists in the address.
const addresses = [''];

async function main() {
bitgo.authenticateWithAccessToken({ accessToken });

const wallet = await bitgo.coin(coin).wallets().getWallet({ id: walletId });

console.log('Wallet ID:', wallet.id());

const resources = await wallet.getAccountResources({ addresses });
Expand Down
49 changes: 49 additions & 0 deletions examples/ts/trx/get-resource-delegations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Get resource delegations for a TRX wallet at BitGo.
*
* This tool will help you see how to use the BitGo SDK to query
* outgoing and incoming ENERGY/BANDWIDTH delegations for a wallet.
*
* Prerequisites:
* - Valid BitGo access token
* - TRX wallet ID
*
* Copyright 2026, BitGo, Inc. All Rights Reserved.
*/
import { BitGoAPI } from '@bitgo/sdk-api';
import { Ttrx } from '@bitgo/sdk-coin-trx';
require('dotenv').config({ path: '../../../.env' });

// TODO: change to 'production' for mainnet
const bitgo = new BitGoAPI({
accessToken: process.env.TESTNET_ACCESS_TOKEN,
env: 'test',
});

// TODO: change to 'trx' for mainnet
const coin = 'ttrx';
bitgo.register(coin, Ttrx.createInstance);

const walletId = '';

// TODO: (optional) filter by delegation type
const type: 'outgoing' | 'incoming' | undefined = undefined;

// TODO: (optional) filter by resource type (e.g. 'ENERGY', 'energy', 'BANDWIDTH', 'bandwidth')
const resource: string | undefined = undefined;

// TODO: (optional) maximum number of results to return
const limit: number | undefined = undefined;

async function main() {
const wallet = await bitgo.coin(coin).wallets().get({ id: walletId });
const result = await wallet.getResourceDelegations({ type, resource, limit });

console.log('Wallet Address:', result.address);
console.log('Coin:', result.coin);
console.log('Outgoing Delegations:', result.delegations.outgoing.length);
console.log('Incoming Delegations:', result.delegations.incoming.length);
console.log('Resource Delegations:', JSON.stringify(result, null, 2));
}

main().catch((e) => console.error(e));
75 changes: 75 additions & 0 deletions examples/ts/trx/undelegate-resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Build and sign a TRX UndelegateResource transaction via the BitGo platform.
*
* DelegateResource allows a TRX holder who has frozen TRX (via FreezeBalanceV2)
* to reclaim the BANDWIDTH or ENERGY resource from another address.
*
* Prerequisites:
* - Valid BitGo access token
* - TRX wallet with frozen balance (via FreezeBalanceV2)
* - Wallet passphrase for signing
*
* Copyright 2026, BitGo, Inc. All Rights Reserved.
*/
import { WalletCoinSpecific } from 'bitgo';
import {BitGoAPI} from "@bitgo/sdk-api";
import {Ttrx} from "@bitgo/sdk-coin-trx";
require('dotenv').config({ path: '../../../.env' });

// TODO: change to 'production' for mainnet
const bitgo = new BitGoAPI({
accessToken: process.env.TESTNET_ACCESS_TOKEN,
env: 'test',
});

const coin = 'ttrx';
bitgo.register(coin, Ttrx.createInstance);

const walletId = '';
const walletPassphrase = '';
const otp = '000000';

// TODO: set the receiver address (the address from which resource will be reclaimed)
const receiverAddress = '';

// TODO: set the amount of frozen TRX to undelegate, in SUN (1 TRX = 1,000,000 SUN)
const amountSun = '1000000';

// TODO: set the resource type to undelegate: 'energy' or 'bandwidth'
const resource = 'bandwidth';

async function main() {

const wallet = await bitgo.coin(coin).wallets().getWallet({ id: walletId });
console.log('Wallet ID:', wallet.id());

// Unlock the session for signing
const unlock = await bitgo.unlock({ otp, duration: 3600 });
if (!unlock) {
throw new Error('error unlocking session');
}

// Build, sign, and send the transaction in one step
// The SDK handles prebuild, user half-sign, platform co-signing, and broadcasting
const result = await wallet.sendMany({
type: 'undelegateResource',
stakingParams: {
receiver_address: receiverAddress,
amount: amountSun,
resource,
},
recipients: [
{
address: receiverAddress,
amount: '0',
},
],
walletPassphrase,
});

console.log('Transaction sent successfully!');
console.log('TX ID:', result.txid);
console.log('Result:', JSON.stringify(result, null, 2));
}

main().catch((e) => console.error(e));
19 changes: 8 additions & 11 deletions modules/express/src/clientRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1036,17 +1036,14 @@ export async function handleV2ResourceDelegations(
req: ExpressApiRouteRequest<'express.v2.wallet.resourcedelegations', 'get'>
) {
const bitgo = req.bitgo;
const coin = req.decoded.coin;
const walletId = req.decoded.id;
const query: Record<string, string> = {};
if (req.decoded.type) query.type = req.decoded.type;
if (req.decoded.resource) query.resource = req.decoded.resource;
if (req.decoded.limit !== undefined) query.limit = String(req.decoded.limit);
if (req.decoded.nextBatchPrevId) query.nextBatchPrevId = req.decoded.nextBatchPrevId;
return bitgo
.get(bitgo.url(`/${coin}/wallet/${walletId}/resourcedelegations`, 2))
.query(query)
.result();
const coin = bitgo.coin(req.decoded.coin);
const wallet = await coin.wallets().get({ id: req.decoded.id });
return wallet.getResourceDelegations({
type: req.decoded.type,
resource: req.decoded.resource,
limit: req.decoded.limit,
nextBatchPrevId: req.decoded.nextBatchPrevId,
});
}

/**
Expand Down
48 changes: 31 additions & 17 deletions modules/express/test/unit/clientRoutes/trxResourceDelegation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,18 @@ describe('TRX Resource Delegation handlers', () => {
},
};

function createBitgoStub(result: unknown) {
const resultStub = sandbox.stub().resolves(result);
const queryStub = sandbox.stub().returns({ result: resultStub });
const getStub = sandbox.stub().returns({ query: queryStub });
const urlStub = sandbox
.stub()
.returns('https://test.bitgo.com/api/v2/ttrx/wallet/walletId123/resourcedelegations');
const bitgoStub = sinon.createStubInstance(BitGo as any, { get: getStub, url: urlStub });
return { bitgoStub, getStub, queryStub, resultStub };
function createMocks(result: unknown) {
const getResourceDelegationsStub = sandbox.stub().resolves(result);
const walletStub = { getResourceDelegations: getResourceDelegationsStub };
const coinStub = {
wallets: () => ({ get: () => Promise.resolve(walletStub) }),
};
const bitgoStub = sinon.createStubInstance(BitGo as any, { coin: coinStub });
return { bitgoStub, getResourceDelegationsStub };
}

it('should forward type and resource query params', async () => {
const { bitgoStub, queryStub } = createBitgoStub(mockDelegations);
const { bitgoStub, getResourceDelegationsStub } = createMocks(mockDelegations);

const mockRequest = {
bitgo: bitgoStub,
Expand All @@ -124,11 +123,16 @@ describe('TRX Resource Delegation handlers', () => {
};

await handleV2ResourceDelegations(mockRequest as express.Request & typeof mockRequest);
queryStub.should.be.calledOnceWith({ type: 'outgoing', resource: 'ENERGY' });
getResourceDelegationsStub.should.be.calledOnceWith({
type: 'outgoing',
resource: 'ENERGY',
limit: undefined,
nextBatchPrevId: undefined,
});
});

it('should convert limit to string when forwarding', async () => {
const { bitgoStub, queryStub } = createBitgoStub(mockDelegations);
it('should forward limit param', async () => {
const { bitgoStub, getResourceDelegationsStub } = createMocks(mockDelegations);

const mockRequest = {
bitgo: bitgoStub,
Expand All @@ -140,11 +144,16 @@ describe('TRX Resource Delegation handlers', () => {
};

await handleV2ResourceDelegations(mockRequest as express.Request & typeof mockRequest);
queryStub.should.be.calledOnceWith({ limit: '10' });
getResourceDelegationsStub.should.be.calledOnceWith({
type: undefined,
resource: undefined,
limit: 10,
nextBatchPrevId: undefined,
});
});

it('should forward nextBatchPrevId for pagination', async () => {
const { bitgoStub, queryStub } = createBitgoStub(mockDelegations);
const { bitgoStub, getResourceDelegationsStub } = createMocks(mockDelegations);

const mockRequest = {
bitgo: bitgoStub,
Expand All @@ -157,11 +166,16 @@ describe('TRX Resource Delegation handlers', () => {
};

await handleV2ResourceDelegations(mockRequest as express.Request & typeof mockRequest);
queryStub.should.be.calledOnceWith({ type: 'incoming', nextBatchPrevId: 'cursor-abc123' });
getResourceDelegationsStub.should.be.calledOnceWith({
type: 'incoming',
resource: undefined,
limit: undefined,
nextBatchPrevId: 'cursor-abc123',
});
});

it('should return codec-valid delegations result', async () => {
const { bitgoStub } = createBitgoStub(mockDelegations);
const { bitgoStub } = createMocks(mockDelegations);

const mockRequest = {
bitgo: bitgoStub,
Expand Down
Loading
Loading