Skip to content

Commit ffb5c22

Browse files
committed
Merge branch 'master' into rel/latest
# Conflicts: # modules/express/package.json # modules/sdk-coin-canton/package.json # modules/sdk-core/package.json
2 parents db0ea50 + f560d2d commit ffb5c22

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3633
-515
lines changed

modules/express/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
"superagent": "^9.0.1"
5959
},
6060
"devDependencies": {
61-
"@bitgo/public-types": "5.22.0",
61+
"@bitgo/public-types": "5.29.0",
6262
"@bitgo/sdk-lib-mpc": "^10.8.0",
6363
"@bitgo/sdk-test": "^9.1.3",
6464
"@types/argparse": "^1.0.36",

modules/express/src/clientRoutes.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -724,11 +724,11 @@ async function handleV2SignTxWallet(req: express.Request) {
724724
* handle sign transaction
725725
* @param req
726726
*/
727-
async function handleV2SignTx(req: express.Request) {
727+
async function handleV2SignTx(req: ExpressApiRouteRequest<'express.v2.coin.signtx', 'post'>) {
728728
const bitgo = req.bitgo;
729-
const coin = bitgo.coin(req.params.coin);
729+
const coin = bitgo.coin(req.decoded.coin);
730730
try {
731-
return await coin.signTransaction(req.body);
731+
return await coin.signTransaction(req.decoded);
732732
} catch (error) {
733733
console.log('error while signing the transaction ', error);
734734
throw error;
@@ -1632,7 +1632,7 @@ export function setupAPIRoutes(app: express.Application, config: Config): void {
16321632
router.post('express.ofc.signPayload', [prepareBitGo(config), typedPromiseWrapper(handleV2OFCSignPayload)]);
16331633

16341634
// sign transaction
1635-
app.post('/api/v2/:coin/signtx', parseBody, prepareBitGo(config), promiseWrapper(handleV2SignTx));
1635+
router.post('express.v2.coin.signtx', [prepareBitGo(config), typedPromiseWrapper(handleV2SignTx)]);
16361636
app.post('/api/v2/:coin/wallet/:id/signtx', parseBody, prepareBitGo(config), promiseWrapper(handleV2SignTxWallet));
16371637
app.post(
16381638
'/api/v2/:coin/wallet/:id/signtxtss',

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { PostCreateAddress } from './v2/createAddress';
2626
import { PutFanoutUnspents } from './v1/fanoutUnspents';
2727
import { PostOfcSignPayload } from './v2/ofcSignPayload';
2828
import { PostWalletRecoverToken } from './v2/walletRecoverToken';
29+
import { PostCoinSignTx } from './v2/coinSignTx';
2930

3031
export const ExpressApi = apiSpec({
3132
'express.ping': {
@@ -100,6 +101,9 @@ export const ExpressApi = apiSpec({
100101
'express.v2.wallet.recovertoken': {
101102
post: PostWalletRecoverToken,
102103
},
104+
'express.v2.coin.signtx': {
105+
post: PostCoinSignTx,
106+
},
103107
});
104108

105109
export type ExpressApi = typeof ExpressApi;
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import * as t from 'io-ts';
2+
import { httpRoute, httpRequest, optional } from '@api-ts/io-ts-http';
3+
import { TransactionRequest as TxRequestResponse } from '@bitgo/public-types';
4+
import { BitgoExpressError } from '../../schemas/error';
5+
6+
/**
7+
* Request parameters for signing a transaction
8+
*/
9+
export const CoinSignTxParams = {
10+
/** The coin type */
11+
coin: t.string,
12+
} as const;
13+
14+
/**
15+
* Transaction prebuild information
16+
*/
17+
export const TransactionPrebuild = t.partial({
18+
/** Transaction in hex format */
19+
txHex: t.string,
20+
/** Transaction in base64 format (for some coins) */
21+
txBase64: t.string,
22+
/** Transaction in JSON format (for some coins) */
23+
txInfo: t.any,
24+
/** Wallet ID for the transaction */
25+
walletId: t.string,
26+
/** Next contract sequence ID (for ETH) */
27+
nextContractSequenceId: t.number,
28+
/** Whether this is a batch transaction (for ETH) */
29+
isBatch: t.boolean,
30+
/** EIP1559 transaction parameters (for ETH) */
31+
eip1559: t.any,
32+
/** Hop transaction data (for ETH) */
33+
hopTransaction: t.any,
34+
/** Backup key nonce (for ETH) */
35+
backupKeyNonce: t.any,
36+
/** Recipients of the transaction */
37+
recipients: t.any,
38+
});
39+
40+
/**
41+
* Request body for signing a transaction
42+
*/
43+
export const CoinSignTxBody = {
44+
/** Private key for signing */
45+
prv: optional(t.string),
46+
/** Transaction prebuild data */
47+
txPrebuild: optional(TransactionPrebuild),
48+
/** Whether this is the last signature in a multi-sig tx */
49+
isLastSignature: optional(t.boolean),
50+
/** Gas limit for ETH transactions */
51+
gasLimit: optional(t.union([t.string, t.number])),
52+
/** Gas price for ETH transactions */
53+
gasPrice: optional(t.union([t.string, t.number])),
54+
/** Transaction expiration time */
55+
expireTime: optional(t.number),
56+
/** Sequence ID for transactions */
57+
sequenceId: optional(t.number),
58+
/** Public keys for multi-signature transactions */
59+
pubKeys: optional(t.array(t.string)),
60+
/** For EVM cross-chain recovery */
61+
isEvmBasedCrossChainRecovery: optional(t.boolean),
62+
/** Recipients of the transaction */
63+
recipients: optional(t.any),
64+
/** Custodian transaction ID */
65+
custodianTransactionId: optional(t.string),
66+
/** Signing step for MuSig2 */
67+
signingStep: optional(t.union([t.literal('signerNonce'), t.literal('signerSignature'), t.literal('cosignerNonce')])),
68+
/** Allow non-segwit signing without previous transaction */
69+
allowNonSegwitSigningWithoutPrevTx: optional(t.boolean),
70+
} as const;
71+
72+
/**
73+
* Response for a fully signed transaction
74+
*/
75+
export const FullySignedTransactionResponse = t.type({
76+
/** Transaction in hex format */
77+
txHex: t.string,
78+
});
79+
80+
/**
81+
* Response for a half-signed account transaction
82+
*/
83+
export const HalfSignedAccountTransactionResponse = t.type({
84+
halfSigned: t.partial({
85+
txHex: optional(t.string),
86+
payload: optional(t.string),
87+
txBase64: optional(t.string),
88+
}),
89+
});
90+
91+
/**
92+
* Response for a half-signed UTXO transaction
93+
*/
94+
export const HalfSignedUtxoTransactionResponse = t.type({
95+
txHex: t.string,
96+
});
97+
98+
/**
99+
* Response for a transaction request
100+
*/
101+
export const SignedTransactionRequestResponse = t.type({
102+
txRequestId: t.string,
103+
});
104+
105+
/**
106+
* Response for signing a transaction
107+
*
108+
* Uses TxRequestResponse (TransactionRequest) from @bitgo/public-types for TSS transaction requests
109+
* (supports both Lite and Full versions)
110+
*/
111+
export const CoinSignTxResponse = {
112+
/** Successfully signed transaction */
113+
200: t.union([
114+
FullySignedTransactionResponse,
115+
HalfSignedAccountTransactionResponse,
116+
HalfSignedUtxoTransactionResponse,
117+
SignedTransactionRequestResponse,
118+
TxRequestResponse,
119+
]),
120+
/** Error response */
121+
400: BitgoExpressError,
122+
};
123+
124+
/**
125+
* Sign a transaction for a specific coin
126+
*
127+
* This endpoint signs a transaction for a specific coin type.
128+
* The request body is passed directly to coin.signTransaction() and varies by coin.
129+
* Common fields include:
130+
* - txPrebuild: Contains transaction data like txHex or txBase64
131+
* - prv: Private key for signing
132+
* - isLastSignature: Whether this is the last signature in a multi-sig tx
133+
* - gasLimit: Gas limit for ETH transactions
134+
* - gasPrice: Gas price for ETH transactions
135+
* - expireTime: Transaction expiration time
136+
* - sequenceId: Sequence ID for transactions
137+
* - pubKeys: Public keys for multi-signature transactions
138+
* - isEvmBasedCrossChainRecovery: For EVM cross-chain recovery
139+
*
140+
* @operationId express.v2.coin.signtx
141+
*/
142+
export const PostCoinSignTx = httpRoute({
143+
path: '/api/v2/:coin/signtx',
144+
method: 'POST',
145+
request: httpRequest({
146+
params: CoinSignTxParams,
147+
body: CoinSignTxBody,
148+
}),
149+
response: CoinSignTxResponse,
150+
});

0 commit comments

Comments
 (0)