Skip to content

Commit 3878971

Browse files
authored
Merge pull request #5207 from BitGo/CE-4801
feat(sdk-api): implement custom proxy agent support in BitGoAPI
2 parents 09545ee + cab3958 commit 3878971

File tree

11 files changed

+750
-51
lines changed

11 files changed

+750
-51
lines changed

examples/ts/http-proxy/create-wallet.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { BitGoAPI } from '@bitgo/sdk-api';
22
import { Tpolygon } from '@bitgo/sdk-coin-polygon'; // Replace with your given coin (e.g. Ltc, Tltc)
3+
import { ProxyAgent } from 'proxy-agent';
34

45
// This script emulates a front-end using the BitGo SDK to BitGo backend via a proxy.
56
// Set up the BitGo connection object.
@@ -10,7 +11,9 @@ const bitgo = new BitGoAPI({
1011
// This *must* match the BitGo platform API your proxy instance is using.
1112
env: 'test',
1213
// TODO: In your real setup this would be <your.proxy.url>, where you host the proxy server.
13-
proxy: 'http://localhost:3000',
14+
customProxyAgent: new ProxyAgent({
15+
getProxyForUrl: () => 'http://localhost:3000',
16+
}),
1417
});
1518
const coin = 'tpolygon';
1619
bitgo.register(coin, Tpolygon.createInstance);

examples/ts/http-proxy/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
"author": "BitGo",
1010
"license": "ISC",
1111
"dependencies": {
12+
"proxy": "2.1.1",
13+
"proxy-agent": "6.4.0",
14+
"superagent": "9.0.1",
1215
"ts-node": "^10.8.1",
1316
"typescript": "^4.7.3",
14-
"typescript-cached-transpile": "^0.0.6",
15-
"superagent": "9.0.1",
16-
"proxy-agent": "6.4.0",
17-
"proxy": "2.1.1"
17+
"typescript-cached-transpile": "^0.0.6"
1818
}
1919
}

examples/ts/http-proxy/yarn.lock

Lines changed: 707 additions & 0 deletions
Large diffs are not rendered by default.

modules/express/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050
"io-ts": "npm:@bitgo-forks/[email protected]",
5151
"lodash": "^4.17.20",
5252
"morgan": "^1.9.1",
53-
"superagent": "^9.0.1"
53+
"superagent": "^9.0.1",
54+
"proxy-agent": "6.4.0"
5455
},
5556
"devDependencies": {
5657
"@bitgo/public-types": "3.6.0",

modules/express/src/clientRoutes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import {
5353
handleInitLightningWallet,
5454
handleUnlockLightningWallet,
5555
} from './lightning/lightningSignerRoutes';
56+
import { ProxyAgent } from 'proxy-agent';
5657

5758
const { version } = require('bitgo/package.json');
5859
const pjson = require('../package.json');
@@ -1213,12 +1214,21 @@ function prepareBitGo(config: Config) {
12131214
const userAgent = req.headers['user-agent']
12141215
? BITGOEXPRESS_USER_AGENT + ' ' + req.headers['user-agent']
12151216
: BITGOEXPRESS_USER_AGENT;
1217+
1218+
const useProxyUrl = process.env.BITGO_USE_PROXY;
12161219
const bitgoConstructorParams: BitGoOptions = {
12171220
env,
12181221
customRootURI: customRootUri,
12191222
customBitcoinNetwork,
12201223
accessToken,
12211224
userAgent,
1225+
...(useProxyUrl
1226+
? {
1227+
customProxyAgent: new ProxyAgent({
1228+
getProxyForUrl: () => useProxyUrl,
1229+
}),
1230+
}
1231+
: {}),
12221232
};
12231233

12241234
req.bitgo = new BitGo(bitgoConstructorParams);

modules/sdk-api/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
"@types/superagent": "4.1.15",
4848
"bitcoinjs-message": "npm:@bitgo-forks/[email protected]",
4949
"bluebird": "^3.5.3",
50-
"browser-or-node": "2.0.0",
5150
"debug": "3.1.0",
5251
"eol": "^0.5.0",
5352
"lodash": "^4.17.15",

modules/sdk-api/src/bitgoAPI.ts

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import * as sjcl from '@bitgo/sjcl';
2525
import * as utxolib from '@bitgo/utxo-lib';
2626
import { bip32, ECPairInterface } from '@bitgo/utxo-lib';
2727
import * as bitcoinMessage from 'bitcoinjs-message';
28-
import { isBrowser, isWebWorker } from 'browser-or-node';
2928
import { createHmac } from 'crypto';
29+
import { type Agent } from 'http';
3030
import debugLib from 'debug';
3131
import * as _ from 'lodash';
3232
import * as secp256k1 from 'secp256k1';
@@ -96,14 +96,6 @@ const PendingApprovals = require('./v1/pendingapprovals');
9696
const TravelRule = require('./v1/travelRule');
9797
const TransactionBuilder = require('./v1/transactionBuilder');
9898

99-
let enableProxyAgent = false;
100-
let proxyAgentModule;
101-
if (!isBrowser && !isWebWorker) {
102-
debug('enabling proxy-agent');
103-
enableProxyAgent = true;
104-
proxyAgentModule = require('proxy-agent');
105-
}
106-
10799
const patchedRequestMethods = ['get', 'post', 'put', 'del', 'patch', 'options'] as const;
108100

109101
export class BitGoAPI implements BitGoBase {
@@ -138,6 +130,7 @@ export class BitGoAPI implements BitGoBase {
138130
protected readonly _clientSecret?: string;
139131
protected _validate: boolean;
140132
public readonly cookiesPropagationEnabled: boolean;
133+
private _customProxyAgent?: Agent;
141134

142135
constructor(params: BitGoAPIOptions = {}) {
143136
this.cookiesPropagationEnabled = false;
@@ -278,15 +271,12 @@ export class BitGoAPI implements BitGoBase {
278271
debug('HMAC verification explicitly disabled by constructor option');
279272
this._hmacVerification = params.hmacVerification;
280273
}
281-
if (!params.proxy && process.env.BITGO_USE_PROXY) {
282-
params.proxy = process.env.BITGO_USE_PROXY;
283-
}
284274

285-
if ((process as any).browser && params.proxy) {
286-
throw new Error('cannot use https proxy params while in browser');
275+
if ((process as any).browser && params.customProxyAgent) {
276+
throw new Error('should not use https proxy while in browser');
287277
}
288278

289-
this._proxy = params.proxy;
279+
this._customProxyAgent = params.customProxyAgent;
290280

291281
// capture outer stack so we have useful debug information if fetch constants fails
292282
const e = new Error();
@@ -342,14 +332,10 @@ export class BitGoAPI implements BitGoBase {
342332
*/
343333
private requestPatch(method: (typeof patchedRequestMethods)[number], url: string) {
344334
const req = this.getAgentRequest(method, url);
345-
if (this._proxy && enableProxyAgent) {
346-
debug('proxying request through %s', this._proxy);
347-
const proxyUrl: string = this._proxy;
348-
const agent = new proxyAgentModule.ProxyAgent({
349-
getProxyForUrl: () => proxyUrl,
350-
});
351-
if (agent) {
352-
req.agent(agent);
335+
if (this._customProxyAgent) {
336+
debug('using custom proxy agent');
337+
if (this._customProxyAgent) {
338+
req.agent(this._customProxyAgent);
353339
}
354340
}
355341

@@ -585,14 +571,8 @@ export class BitGoAPI implements BitGoBase {
585571
// Proxy settings must still be respected however
586572
const resultPromise = this.getAgentRequest('get', this.url('/client/constants'));
587573
resultPromise.set('BitGo-SDK-Version', this._version);
588-
if (this._proxy && enableProxyAgent) {
589-
const proxyUrl: string = this._proxy;
590-
const agent = new proxyAgentModule.ProxyAgent({
591-
getProxyForUrl: () => proxyUrl,
592-
});
593-
if (agent) {
594-
resultPromise.agent(agent);
595-
}
574+
if (this._customProxyAgent) {
575+
resultPromise.agent(this._customProxyAgent);
596576
}
597577
const result = await resultPromise;
598578
BitGoAPI._constants[env] = result.body.constants;

modules/sdk-api/src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { EnvironmentName, IRequestTracer, V1Network } from '@bitgo/sdk-core';
22
import { ECPairInterface } from '@bitgo/utxo-lib';
3+
import { type Agent } from 'http';
34

45
export interface BitGoAPIOptions {
56
accessToken?: string;
@@ -17,7 +18,7 @@ export interface BitGoAPIOptions {
1718
zksyncExplorerApiToken?: string;
1819
bscscanApiToken?: string;
1920
hmacVerification?: boolean;
20-
proxy?: string;
21+
customProxyAgent?: Agent;
2122
refreshToken?: string;
2223
serverXpub?: string;
2324
stellarFederationServerUrl?: string;

modules/sdk-api/test/unit/bitgoAPI.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'should';
22
import { BitGoAPI } from '../../src/bitgoAPI';
3+
import { ProxyAgent } from 'proxy-agent';
34

45
describe('Constructor', function () {
56
describe('cookiesPropagationEnabled argument', function () {
@@ -36,23 +37,26 @@ describe('Constructor', function () {
3637
});
3738
});
3839
describe('http proxy agent', function () {
39-
it('http proxy agent shall be created when proxy is set', function () {
40+
it('http proxy agent shall be created when proxy(customProxyagent) is set', function () {
41+
const customProxyAgent = new ProxyAgent({
42+
getProxyForUrl: () => 'http://localhost:3000',
43+
});
4044
const bitgo = new BitGoAPI({
4145
env: 'custom',
4246
customRootURI: 'https://app.example.local',
43-
proxy: 'http://localhost:3000',
47+
customProxyAgent,
4448
});
4549

46-
bitgo.should.have.property('_proxy', 'http://localhost:3000');
50+
bitgo.should.have.property('_customProxyAgent', customProxyAgent);
4751
});
4852

49-
it('bitgo api is still initiated when proxy is not set', function () {
53+
it('bitgo api is still initiated when proxy(customProxyAgent) is not set', function () {
5054
const bitgo = new BitGoAPI({
5155
env: 'custom',
5256
customRootURI: 'https://app.example.local',
5357
});
5458

55-
bitgo.should.have.property('_proxy', undefined);
59+
bitgo.should.have.property('_customProxyAgent', undefined);
5660
});
5761
});
5862

webpack/bitgojs.config.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ module.exports = {
1212
alias: {
1313
// this is only required if using bitgo instead of just the sdk-api
1414
'@hashgraph/sdk': path.resolve('../../node_modules/@hashgraph/sdk/src/browser.js'),
15-
'proxy-agent': false,
1615
// use the default version here since we're webpacking ourselves
1716
'@bitgo/sdk-api': path.resolve('../sdk-api/dist/src/index.js'),
1817
async: path.resolve('../../node_modules/async/index.js'),
@@ -36,7 +35,7 @@ module.exports = {
3635
async: require.resolve('async'),
3736
},
3837
},
39-
externals: ['morgan', 'proxy-agent', 'wasmer_wasi_js_bg.wasm'],
38+
externals: ['morgan', 'wasmer_wasi_js_bg.wasm'],
4039
plugins: [
4140
new webpack.ProvidePlugin({
4241
Buffer: ['buffer', 'Buffer'],

0 commit comments

Comments
 (0)