Skip to content

Commit 3a3ea85

Browse files
feat: eddsa recover txn signature
Ticket: WP-5166
1 parent e718dd8 commit 3a3ea85

File tree

15 files changed

+1453
-843
lines changed

15 files changed

+1453
-843
lines changed

masterBitgoExpress.json

Lines changed: 149 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,120 @@
66
"description": "BitGo Enclaved Express - Secure enclave for BitGo signing operations with mTLS"
77
},
88
"paths": {
9+
"/api/{coin}/wallet/{walletId}/accelerate": {
10+
"post": {
11+
"parameters": [
12+
{
13+
"name": "walletId",
14+
"in": "path",
15+
"required": true,
16+
"schema": {
17+
"type": "string"
18+
}
19+
},
20+
{
21+
"name": "coin",
22+
"in": "path",
23+
"required": true,
24+
"schema": {
25+
"type": "string"
26+
}
27+
}
28+
],
29+
"requestBody": {
30+
"content": {
31+
"application/json": {
32+
"schema": {
33+
"type": "object",
34+
"properties": {
35+
"pubkey": {
36+
"type": "string"
37+
},
38+
"source": {
39+
"type": "string",
40+
"enum": [
41+
"user",
42+
"backup"
43+
]
44+
},
45+
"cpfpTxIds": {
46+
"type": "array",
47+
"items": {
48+
"type": "string"
49+
}
50+
},
51+
"cpfpFeeRate": {
52+
"type": "number"
53+
},
54+
"maxFee": {
55+
"type": "number"
56+
},
57+
"rbfTxIds": {
58+
"type": "array",
59+
"items": {
60+
"type": "string"
61+
}
62+
},
63+
"feeMultiplier": {
64+
"type": "number"
65+
}
66+
},
67+
"required": [
68+
"pubkey",
69+
"source"
70+
]
71+
}
72+
}
73+
}
74+
},
75+
"responses": {
76+
"200": {
77+
"description": "OK",
78+
"content": {
79+
"application/json": {
80+
"schema": {
81+
"type": "object",
82+
"properties": {
83+
"txid": {
84+
"type": "string"
85+
},
86+
"tx": {
87+
"type": "string"
88+
}
89+
},
90+
"required": [
91+
"txid",
92+
"tx"
93+
]
94+
}
95+
}
96+
}
97+
},
98+
"500": {
99+
"description": "Internal Server Error",
100+
"content": {
101+
"application/json": {
102+
"schema": {
103+
"type": "object",
104+
"properties": {
105+
"error": {
106+
"type": "string"
107+
},
108+
"details": {
109+
"type": "string"
110+
}
111+
},
112+
"required": [
113+
"error",
114+
"details"
115+
]
116+
}
117+
}
118+
}
119+
}
120+
}
121+
}
122+
},
9123
"/api/{coin}/wallet/{walletId}/consolidate": {
10124
"post": {
11125
"parameters": [
@@ -142,9 +256,6 @@
142256
"backup"
143257
]
144258
},
145-
"walletPassphrase": {
146-
"type": "string"
147-
},
148259
"feeRate": {
149260
"type": "number"
150261
},
@@ -561,17 +672,42 @@
561672
"schema": {
562673
"type": "object",
563674
"properties": {
564-
"userPub": {
565-
"type": "string"
566-
},
567-
"backupPub": {
568-
"type": "string"
675+
"isTssRecovery": {
676+
"type": "boolean"
569677
},
570-
"bitgoPub": {
571-
"type": "string"
678+
"tssRecoveryParams": {
679+
"type": "object",
680+
"properties": {
681+
"commonKeychain": {
682+
"type": "string"
683+
}
684+
},
685+
"required": [
686+
"commonKeychain"
687+
]
572688
},
573-
"walletContractAddress": {
574-
"type": "string"
689+
"multiSigRecoveryParams": {
690+
"type": "object",
691+
"properties": {
692+
"backupPub": {
693+
"type": "string"
694+
},
695+
"bitgoPub": {
696+
"type": "string"
697+
},
698+
"userPub": {
699+
"type": "string"
700+
},
701+
"walletContractAddress": {
702+
"type": "string"
703+
}
704+
},
705+
"required": [
706+
"backupPub",
707+
"bitgoPub",
708+
"userPub",
709+
"walletContractAddress"
710+
]
575711
},
576712
"recoveryDestinationAddress": {
577713
"type": "string"
@@ -605,11 +741,7 @@
605741
}
606742
},
607743
"required": [
608-
"userPub",
609-
"backupPub",
610-
"walletContractAddress",
611-
"recoveryDestinationAddress",
612-
"apiKey"
744+
"recoveryDestinationAddress"
613745
]
614746
}
615747
}

package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727
"@api-ts/typed-express-router": "^1.1.13",
2828
"@bitgo/sdk-core": "^35.3.0",
2929
"@bitgo-beta/sdk-lib-mpc": "8.2.1-alpha.291",
30+
"@bitgo/sdk-coin-ada": "^4.11.5",
31+
"@bitgo/sdk-coin-dot": "^4.3.5",
32+
"@bitgo/sdk-coin-sui": "^5.15.5",
33+
"@bitgo/sdk-coin-near": "^2.7.0",
34+
"@bitgo/sdk-coin-sol": "^4.12.5",
3035
"bitgo": "^48.1.0",
3136
"@bitgo/abstract-utxo": "^9.21.4",
3237
"@bitgo/statics": "^54.6.0",
@@ -44,6 +49,9 @@
4449
"winston": "^3.11.0",
4550
"zod": "^3.25.48"
4651
},
52+
"resolutions": {
53+
"@bitgo/sdk-core": "^35.3.0"
54+
},
4755
"devDependencies": {
4856
"@api-ts/openapi-generator": "^5.7.0",
4957
"@types/body-parser": "^1.17.0",

src/__tests__/api/master/musigRecovery.test.ts

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,13 @@ describe('POST /api/:coin/wallet/recovery', () => {
7171
})
7272
.set('Authorization', `Bearer ${accessToken}`)
7373
.send({
74-
userPub: ethRecoveryData.userKey,
75-
backupPub: ethRecoveryData.backupKey,
74+
multiSigRecoveryParams: {
75+
userPub: ethRecoveryData.userKey,
76+
backupPub: ethRecoveryData.backupKey,
77+
walletContractAddress: ethRecoveryData.walletContractAddress,
78+
bitgoPub: undefined,
79+
},
7680
apiKey: 'etherscan-api-token',
77-
walletContractAddress: ethRecoveryData.walletContractAddress,
7881
recoveryDestinationAddress: ethRecoveryData.recoveryDestinationAddress,
7982
});
8083

@@ -89,10 +92,13 @@ describe('POST /api/:coin/wallet/recovery', () => {
8992
.post(`/api/${coin}/wallet/recovery`)
9093
.set('Authorization', `Bearer ${accessToken}`)
9194
.send({
92-
userPub: ethRecoveryData.userKey,
93-
backupPub: ethRecoveryData.backupKey,
95+
multiSigRecoveryParams: {
96+
userPub: ethRecoveryData.userKey,
97+
backupPub: ethRecoveryData.backupKey,
98+
walletContractAddress: undefined,
99+
bitgoPub: undefined,
100+
},
94101
apiKey: 'etherscan-api-token',
95-
walletContractAddress: undefined,
96102
recoveryDestinationAddress: ethRecoveryData.recoveryDestinationAddress,
97103
});
98104

@@ -105,9 +111,12 @@ describe('POST /api/:coin/wallet/recovery', () => {
105111
.post(`/api/${coin}/wallet/recovery`)
106112
.set('Authorization', `Bearer ${accessToken}`)
107113
.send({
108-
userPub: ethRecoveryData.userKey,
109-
backupPub: ethRecoveryData.backupKey,
110-
walletContractAddress: ethRecoveryData.walletContractAddress,
114+
multiSigRecoveryParams: {
115+
userPub: ethRecoveryData.userKey,
116+
backupPub: ethRecoveryData.backupKey,
117+
walletContractAddress: ethRecoveryData.walletContractAddress,
118+
bitgoPub: undefined,
119+
},
111120
recoveryDestinationAddress: undefined,
112121
});
113122

@@ -120,18 +129,24 @@ describe('POST /api/:coin/wallet/recovery', () => {
120129
.post(`/api/${coin}/wallet/recovery`)
121130
.set('Authorization', `Bearer ${accessToken}`)
122131
.send({
123-
backupPub: ethRecoveryData.backupKey,
124-
walletContractAddress: ethRecoveryData.walletContractAddress,
132+
multiSigRecoveryParams: {
133+
backupPub: ethRecoveryData.backupKey,
134+
walletContractAddress: ethRecoveryData.walletContractAddress,
135+
bitgoPub: undefined,
136+
},
125137
recoveryDestinationAddress: undefined,
126138
});
127139

128140
const responseNoBackupKey = await agent
129141
.post(`/api/${coin}/wallet/recovery`)
130142
.set('Authorization', `Bearer ${accessToken}`)
131143
.send({
132-
userPub: ethRecoveryData.userKey,
144+
multiSigRecoveryParams: {
145+
userPub: ethRecoveryData.userKey,
146+
walletContractAddress: ethRecoveryData.walletContractAddress,
147+
bitgoPub: undefined,
148+
},
133149
apiKey: 'etherscan-api-token',
134-
walletContractAddress: ethRecoveryData.walletContractAddress,
135150
recoveryDestinationAddress: undefined,
136151
});
137152

@@ -143,4 +158,18 @@ describe('POST /api/:coin/wallet/recovery', () => {
143158
responseNoBackupKey.body.should.have.property('error');
144159
responseNoBackupKey.body.error.should.match(/backupPub/i);
145160
});
161+
162+
it('should fail TSS recovery when common keychain is missing', async () => {
163+
const response = await agent
164+
.post(`/api/${coin}/wallet/recovery`)
165+
.set('Authorization', `Bearer ${accessToken}`)
166+
.send({
167+
isTssRecovery: true,
168+
recoveryDestinationAddress: ethRecoveryData.recoveryDestinationAddress,
169+
});
170+
171+
response.status.should.equal(400);
172+
response.body.should.have.property('error');
173+
response.body.error.should.match(/TSS recovery parameters are required/i);
174+
});
146175
});

src/__tests__/api/master/recoveryWallet.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,13 @@ describe('utxo recovery', () => {
153153
.post(`/api/${coin}/wallet/recovery`)
154154
.set('Authorization', `Bearer ${accessToken}`)
155155
.send({
156-
userPub,
157-
backupPub,
158-
bitgoPub,
156+
multiSigRecoveryParams: {
157+
userPub,
158+
backupPub,
159+
bitgoPub,
160+
walletContractAddress: '',
161+
},
159162
recoveryDestinationAddress: recoveryDestination,
160-
walletContractAddress: '',
161163
coin,
162164
apiKey: 'key',
163165
coinSpecificParams: {

src/__tests__/masterBitgoExpress/generateWallet.test.ts

Whitespace-only changes.

0 commit comments

Comments
 (0)