Skip to content
Closed
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 modules/abstract-cosmos/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"@cosmjs/stargate": "^0.29.5",
"bignumber.js": "^9.1.1",
"cosmjs-types": "^0.6.1",
"lodash": "^4.18.0",
"lodash": "^4.17.21",
"protobufjs": "^7.4.0",
"superagent": "^9.0.1"
},
Expand Down
2 changes: 1 addition & 1 deletion modules/abstract-eth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"ethereumjs-util": "7.1.5",
"ethers": "^5.1.3",
"keccak": "^3.0.3",
"lodash": "^4.18.0",
"lodash": "4.17.21",
"secp256k1": "5.0.1",
"superagent": "^9.0.1"
},
Expand Down
2 changes: 1 addition & 1 deletion modules/abstract-substrate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"bs58": "^4.0.1",
"hi-base32": "^0.5.1",
"joi": "^17.4.0",
"lodash": "^4.18.0",
"lodash": "^4.17.15",
"tweetnacl": "^1.0.3"
},
"gitHead": "18e460ddf02de2dbf13c2aa243478188fb539f0c",
Expand Down
2 changes: 1 addition & 1 deletion modules/abstract-utxo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"bignumber.js": "^9.0.2",
"debug": "^3.1.0",
"io-ts": "npm:@bitgo-forks/io-ts@2.1.4",
"lodash": "^4.18.0",
"lodash": "^4.17.14",
"superagent": "^9.0.1"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion modules/bitgo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
"@bitgo/utxo-lib": "^11.22.0",
"@types/superagent": "^4.1.3",
"bignumber.js": "^9.1.1",
"lodash": "^4.18.0",
"lodash": "^4.17.14",
"openpgp": "5.11.3",
"stellar-sdk": "^10.0.1",
"superagent": "^9.0.1"
Expand Down
1 change: 1 addition & 0 deletions modules/bitgo/test/v2/unit/keychains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ describe('V2 Keychains', function () {
n.asset !== UnderlyingAsset.ARCUSDC &&
n.asset !== UnderlyingAsset.ZKSYNCERA &&
n.asset !== UnderlyingAsset.HYPERLIQUID &&
n.asset !== UnderlyingAsset.BOBAETH &&
coinFamilyValues.includes(n.name)
);

Expand Down
2 changes: 1 addition & 1 deletion modules/express/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"express": "4.21.2",
"io-ts": "npm:@bitgo-forks/io-ts@2.1.4",
"io-ts-types": "^0.5.19",
"lodash": "^4.18.0",
"lodash": "^4.17.20",
"morgan": "^1.9.1",
"proxy-agent": "6.4.0",
"proxyquire": "^2.1.3",
Expand Down
6 changes: 1 addition & 5 deletions modules/express/src/clientRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ export async function handleV2OFCSignPayload(

const walletPassphrase = bodyWalletPassphrase || getWalletPwFromEnv(wallet.id());
const tradingAccount = wallet.toTradingAccount();
const stringifiedPayload = typeof payload === 'string' ? payload : JSON.stringify(payload);
const stringifiedPayload = JSON.stringify(payload);
const signature = await tradingAccount.signPayload({
payload: stringifiedPayload,
walletPassphrase,
Expand Down Expand Up @@ -1693,10 +1693,6 @@ export function setupAPIRoutes(app: express.Application, config: Config): void {
router.post('express.decrypt', [prepareBitGo(config), typedPromiseWrapper(handleDecrypt)]);
router.post('express.encrypt', [prepareBitGo(config), typedPromiseWrapper(handleEncrypt)]);
router.post('express.verifyaddress', [prepareBitGo(config), typedPromiseWrapper(handleVerifyAddress)]);
router.post('express.v1.calculateminerfeeinfo', [
prepareBitGo(config),
typedPromiseWrapper(handleCalculateMinerFeeInfo),
]);
router.post('express.calculateminerfeeinfo', [
prepareBitGo(config),
typedPromiseWrapper(handleCalculateMinerFeeInfo),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,22 @@ export const CalculateMinerFeeInfoResponse = t.type({
});

/**
* Calculate miner fee info (v1)
* Calculate miner fee info
*
* Calculates the estimated size and fee for a transaction based on the number and types of inputs and outputs.
* This is useful for estimating the fee before creating a transaction.
*
* @operationId express.v1.calculateminerfeeinfo
* The calculation takes into account:
* 1. The number and types of inputs (P2SH, P2PKH, P2SH-P2WSH)
* 2. The number of outputs
* 3. Whether the transaction contains uncompressed public keys
* 4. The fee rate (in satoshis per kilobyte)
*
* @operationId express.calculateminerfeeinfo
* @tag express
*/
export const PostV1CalculateMinerFeeInfo = httpRoute({
path: '/api/v1/calculateminerfeeinfo',
export const PostCalculateMinerFeeInfo = httpRoute({
path: '/api/v[12]/calculateminerfeeinfo',
method: 'POST',
request: httpRequest({
body: CalculateMinerFeeInfoRequestBody,
Expand Down
8 changes: 2 additions & 6 deletions modules/express/src/typedRoutes/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { PostLogin } from './common/login';
import { PostDecrypt } from './common/decrypt';
import { PostEncrypt } from './common/encrypt';
import { PostVerifyAddress } from './common/verifyAddress';
import { PostV1CalculateMinerFeeInfo } from './v1/calculateMinerFeeInfo';
import { PostV2CalculateMinerFeeInfo } from './v2/calculateMinerFeeInfo';
import { PostCalculateMinerFeeInfo } from './common/calculateMinerFeeInfo';
import { PostAcceptShare } from './v1/acceptShare';
import { PostSimpleCreate } from './v1/simpleCreate';
import { PutPendingApproval } from './v1/pendingApproval';
Expand Down Expand Up @@ -104,11 +103,8 @@ export const ExpressVerifyCoinAddressApiSpec = apiSpec({
});

export const ExpressCalculateMinerFeeInfoApiSpec = apiSpec({
'express.v1.calculateminerfeeinfo': {
post: PostV1CalculateMinerFeeInfo,
},
'express.calculateminerfeeinfo': {
post: PostV2CalculateMinerFeeInfo,
post: PostCalculateMinerFeeInfo,
},
});

Expand Down
31 changes: 0 additions & 31 deletions modules/express/src/typedRoutes/api/v2/calculateMinerFeeInfo.ts

This file was deleted.

7 changes: 4 additions & 3 deletions modules/express/src/typedRoutes/api/v2/lightningState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ import { WalletState } from '../../../lightning/codecs';
export const LightningStateParams = {
/** A lightning coin name (e.g., lnbtc or tlnbtc) */
coin: t.string,
/** The wallet ID. */
/** The ID of the lightning self-custody wallet */
walletId: t.string,
} as const;

export const LightningStateResponse200 = t.type({
/** NON_EXISTING LOCKED UNLOCKED RPC_ACTIVE SERVER_ACTIVE WAITING_TO_START */
state: WalletState,
});

Expand All @@ -29,10 +28,12 @@ export const LightningStateResponse = {
} as const;

/**
* Lightning - Get node state
*
* This is only used for self-custody lightning. Get the current state of the lightning node.
*
* @operationId express.lightning.getState
* @tag Express
* @tag express
*/
export const GetLightningState = httpRoute({
method: 'GET',
Expand Down
22 changes: 12 additions & 10 deletions modules/express/src/typedRoutes/api/v2/lightningWithdraw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { BitgoExpressError } from '../../schemas/error';
export const LightningWithdrawParams = {
/** The coin identifier (e.g., 'lnbtc', 'tlnbtc') */
coin: t.string,
/** The wallet ID. */
/** The ID of the wallet */
id: t.string,
} as const;

Expand All @@ -27,17 +27,17 @@ const LightningOnchainRecipient = t.type({
* Request body for lightning onchain withdrawal
*/
export const LightningWithdrawRequestBody = {
/** A list of on-chain recipients with their withdrawal amounts. */
/** Array of recipients to pay */
recipients: t.array(LightningOnchainRecipient),
/** The wallet passphrase. */
/** Wallet passphrase for signing */
passphrase: t.string,
/** Optional fee rate for the transaction in satoshis per virtual byte. Cannot be used with numBlocks. */
/** Fee rate in satoshis per virtual byte (as string that will be converted to BigInt) */
satsPerVbyte: optional(BigIntFromString),
/** The number of blocks required to confirm a transaction. You can use numBlocks to estimate the fee rate by targeting confirmation within a given number of blocks. If both satsPerVbyte and numBlocks are absent, the transaction defaults to 2 blocks for confirmation. */
/** Target number of blocks for confirmation */
numBlocks: optional(t.number),
/** Optional sequence ID for the withdrawal transfer. */
/** Optional sequence ID for the withdraw transfer */
sequenceId: optional(t.string),
/** Optional comment for the withdrawal transfer. */
/** Optional comment for the withdraw transfer */
comment: optional(t.string),
} as const;

Expand Down Expand Up @@ -174,7 +174,7 @@ const PendingApproval = t.intersection([
*/
const LightningWithdrawResponse = t.intersection([
t.type({
/** Transaction request identifier. */
/** Unique identifier for withdraw request submitted to BitGo */
txRequestId: t.string,
/** Status of withdraw request submission to BitGo */
txRequestState: TxRequestState,
Expand All @@ -199,10 +199,12 @@ export const LightningWithdrawResponseType = {
} as const;

/**
* Withdraw onchain balance from a lightning wallet to a regular onchain address.
* Lightning Onchain Withdrawal API
*
* Withdraws lightning balance to an onchain Bitcoin address
*
* @operationId express.v2.wallet.lightningWithdraw
* @tag Express
* @tag express
*/
export const PostLightningWalletWithdraw = httpRoute({
path: '/api/v2/{coin}/wallet/{id}/lightning/withdraw',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ import { OfcSignPayloadBody, OfcSignPayloadResponse } from './ofcSignPayload';
* - Encrypted private keys must be available in the file system
* - Wallet passphrase must be provided via request body or environment variable
*
* **Flow**:
* 1. Reads encrypted private key from filesystem
* 2. Decrypts private key using wallet passphrase
* 3. Signs the payload with the decrypted key
* 4. Returns signed payload and hex-encoded signature
*
* @operationId express.v2.ofc.extSignPayload
* @tag Express
* @tag express
*/
export const PostOfcExtSignPayload = httpRoute({
path: '/api/v2/ofc/signPayload',
Expand Down
26 changes: 0 additions & 26 deletions modules/express/test/unit/clientRoutes/signPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,32 +87,6 @@ describe('Sign an arbitrary payload with trading account key', function () {
throw new Error(`Response did not match expected codec`);
});
});
it('should not double-stringify when decoded payload is already a string', async function () {
// When the io-ts Json codec matches a string input (left-to-right union resolution),
// decoded.payload is the original string. The handler must not JSON.stringify it again.
const expectedResponse = {
payload: stringifiedPayload,
signature,
};
const req = {
bitgo: bitGoStub,
body: {
payload: stringifiedPayload,
walletId,
},
decoded: {
walletId,
payload: stringifiedPayload,
},
query: {},
} as unknown as ExpressApiRouteRequest<'express.ofc.signPayload', 'post'>;
const result = await handleV2OFCSignPayload(req).should.be.resolvedWith(expectedResponse);
result.payload.should.equal(stringifiedPayload);
result.payload.should.not.startWith('"');
decodeOrElse('OfcSignPayloadResponse200', OfcSignPayloadResponse[200], result, (_) => {
throw new Error(`Response did not match expected codec`);
});
});
it('should decode handler response with OfcSignPayloadResponse codec', async function () {
const expected = {
payload: JSON.stringify(payload),
Expand Down
43 changes: 12 additions & 31 deletions modules/express/test/unit/typedRoutes/calculateMinerFeeInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import * as t from 'io-ts';
import {
CalculateMinerFeeInfoRequestBody,
CalculateMinerFeeInfoResponse,
PostV1CalculateMinerFeeInfo,
} from '../../../src/typedRoutes/api/v1/calculateMinerFeeInfo';
import { PostV2CalculateMinerFeeInfo } from '../../../src/typedRoutes/api/v2/calculateMinerFeeInfo';
PostCalculateMinerFeeInfo,
} from '../../../src/typedRoutes/api/common/calculateMinerFeeInfo';
import { assertDecode } from './common';
import 'should';
import 'should-http';
Expand Down Expand Up @@ -302,43 +301,25 @@ describe('CalculateMinerFeeInfo codec tests', function () {
});
});

describe('PostV1CalculateMinerFeeInfo route definition', function () {
it('should have the correct path for v1', function () {
assert.strictEqual(PostV1CalculateMinerFeeInfo.path, '/api/v1/calculateminerfeeinfo');
describe('PostCalculateMinerFeeInfo route definition', function () {
it('should have the correct path', function () {
assert.strictEqual(PostCalculateMinerFeeInfo.path, '/api/v[12]/calculateminerfeeinfo');
});

it('should have the correct HTTP method', function () {
assert.strictEqual(PostV1CalculateMinerFeeInfo.method, 'POST');
assert.strictEqual(PostCalculateMinerFeeInfo.method, 'POST');
});

it('should have the correct request configuration', function () {
assert.ok(PostV1CalculateMinerFeeInfo.request);
// Verify the route is configured with a request property
assert.ok(PostCalculateMinerFeeInfo.request);
});

it('should have the correct response types', function () {
assert.ok(PostV1CalculateMinerFeeInfo.response[200]);
assert.ok(PostV1CalculateMinerFeeInfo.response[400]);
assert.ok(PostV1CalculateMinerFeeInfo.response[404]);
});
});

describe('PostV2CalculateMinerFeeInfo route definition', function () {
it('should have the correct path for v2', function () {
assert.strictEqual(PostV2CalculateMinerFeeInfo.path, '/api/v2/calculateminerfeeinfo');
});

it('should have the correct HTTP method', function () {
assert.strictEqual(PostV2CalculateMinerFeeInfo.method, 'POST');
});

it('should have the correct request configuration', function () {
assert.ok(PostV2CalculateMinerFeeInfo.request);
});

it('should have the correct response types', function () {
assert.ok(PostV2CalculateMinerFeeInfo.response[200]);
assert.ok(PostV2CalculateMinerFeeInfo.response[400]);
assert.ok(PostV2CalculateMinerFeeInfo.response[404]);
// Check that the response object has the expected status codes
assert.ok(PostCalculateMinerFeeInfo.response[200]);
assert.ok(PostCalculateMinerFeeInfo.response[400]);
assert.ok(PostCalculateMinerFeeInfo.response[404]);
});
});

Expand Down
Loading
Loading