Skip to content

Commit df72204

Browse files
committed
feat(express): migrate constrctTx to typed routes
Ticket: WP-5411
1 parent 292adcc commit df72204

File tree

4 files changed

+390
-6
lines changed

4 files changed

+390
-6
lines changed

modules/express/src/clientRoutes.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ function handleApproveTransaction(req: ExpressApiRouteRequest<'express.v1.pendin
257257
* @deprecated
258258
* @param req
259259
*/
260-
function handleConstructApprovalTx(req: express.Request) {
260+
function handleConstructApprovalTx(req: ExpressApiRouteRequest<'express.v1.pendingapproval.constructTx', 'put'>) {
261261
const params = req.body || {};
262262
return req.bitgo
263263
.pendingApprovals()
@@ -1593,12 +1593,10 @@ export function setupAPIRoutes(app: express.Application, config: Config): void {
15931593

15941594
router.put('express.v1.pendingapprovals', [prepareBitGo(config), typedPromiseWrapper(handleApproveTransaction)]);
15951595

1596-
app.put(
1597-
'/api/v1/pendingapprovals/:id/constructTx',
1598-
parseBody,
1596+
router.put('express.v1.pendingapproval.constructTx', [
15991597
prepareBitGo(config),
1600-
promiseWrapper(handleConstructApprovalTx)
1601-
);
1598+
typedPromiseWrapper(handleConstructApprovalTx),
1599+
]);
16021600

16031601
app.put(
16041602
'/api/v1/wallet/:id/consolidateunspents',

modules/express/src/typedRoutes/api/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { PostUnlockLightningWallet } from './v2/unlockWallet';
2020
import { PostVerifyCoinAddress } from './v2/verifyAddress';
2121
import { PostDeriveLocalKeyChain } from './v1/deriveLocalKeyChain';
2222
import { PostCreateLocalKeyChain } from './v1/createLocalKeyChain';
23+
import { PutConstructPendingApprovalTx } from './v1/constructPendingApprovalTx';
2324

2425
export const ExpressApi = apiSpec({
2526
'express.ping': {
@@ -76,6 +77,9 @@ export const ExpressApi = apiSpec({
7677
'express.v1.keychain.local': {
7778
post: PostCreateLocalKeyChain,
7879
},
80+
'express.v1.pendingapproval.constructTx': {
81+
put: PutConstructPendingApprovalTx,
82+
},
7983
});
8084

8185
export type ExpressApi = typeof ExpressApi;
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import * as t from 'io-ts';
2+
import { httpRoute, httpRequest, optional } from '@api-ts/io-ts-http';
3+
import { BitgoExpressError } from '../../schemas/error';
4+
5+
/**
6+
* Request parameters for constructing a pending approval transaction
7+
*/
8+
export const ConstructPendingApprovalTxRequestParams = {
9+
/** The ID of the pending approval */
10+
id: t.string,
11+
};
12+
13+
/**
14+
* Request body for constructing a pending approval transaction
15+
*/
16+
export const ConstructPendingApprovalTxRequestBody = {
17+
/** The wallet passphrase to decrypt the user key (either walletPassphrase or xprv must be provided for transactionRequest type) */
18+
walletPassphrase: optional(t.string),
19+
/** The extended private key (alternative to walletPassphrase) */
20+
xprv: optional(t.string),
21+
/** Whether to use the original fee from the transaction request (cannot be used with fee, feeRate, or feeTxConfirmTarget) */
22+
useOriginalFee: optional(t.boolean),
23+
/** Custom fee amount in satoshis (cannot be used with useOriginalFee) */
24+
fee: optional(t.number),
25+
/** Custom fee rate in satoshis per kilobyte (cannot be used with useOriginalFee) */
26+
feeRate: optional(t.number),
27+
/** Custom fee confirmation target in blocks (cannot be used with useOriginalFee) */
28+
feeTxConfirmTarget: optional(t.number),
29+
};
30+
31+
/**
32+
* Response for constructing a pending approval transaction
33+
*/
34+
export const ConstructPendingApprovalTxResponse = t.type({
35+
/** The signed transaction hex */
36+
tx: t.string,
37+
/** The fee amount in satoshis */
38+
fee: optional(t.number),
39+
/** The fee rate in satoshis per kilobyte */
40+
feeRate: optional(t.number),
41+
/** Whether the transaction is instant */
42+
instant: optional(t.boolean),
43+
/** The BitGo fee amount */
44+
bitgoFee: optional(t.unknown),
45+
/** Travel information */
46+
travelInfos: optional(t.unknown),
47+
/** Estimated transaction size in bytes */
48+
estimatedSize: optional(t.number),
49+
/** Unspent transaction outputs used */
50+
unspents: optional(t.array(t.unknown)),
51+
});
52+
53+
/**
54+
* Construct a pending approval transaction
55+
*
56+
* This endpoint constructs and signs a transaction for a pending approval, returning the transaction hex
57+
* but not sending it to the network. This is useful for reviewing the transaction before approving it.
58+
*
59+
* For transaction request type approvals, either a wallet passphrase or xprv must be provided to sign the transaction.
60+
* You can optionally specify fee-related parameters to customize the transaction fee.
61+
*
62+
* @operationId express.v1.pendingapproval.constructTx
63+
*/
64+
export const PutConstructPendingApprovalTx = httpRoute({
65+
path: '/api/v1/pendingapprovals/:id/constructTx',
66+
method: 'PUT',
67+
request: httpRequest({
68+
params: ConstructPendingApprovalTxRequestParams,
69+
body: ConstructPendingApprovalTxRequestBody,
70+
}),
71+
response: {
72+
/** Successfully constructed transaction */
73+
200: ConstructPendingApprovalTxResponse,
74+
/** Invalid request or construction fails */
75+
400: BitgoExpressError,
76+
},
77+
});

0 commit comments

Comments
 (0)