-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmockBitgoServer.ts
More file actions
129 lines (109 loc) · 4.09 KB
/
mockBitgoServer.ts
File metadata and controls
129 lines (109 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import * as http from 'http';
import * as path from 'path';
import express from 'express';
import { listen, close } from './servers';
export interface MockBitgoCall {
method: string;
path: string;
body: unknown;
}
export interface MockBitgoServer {
port: number;
calls: MockBitgoCall[];
close(): Promise<void>;
}
const FIXTURES_DIR = path.resolve(__dirname, '../fixtures/bitgo');
function loadFixture(name: string): Record<string, unknown> {
return require(`${FIXTURES_DIR}/${name}.json`);
}
type SendManyFixtureMethod = 'getWallet' | 'prebuildTx' | 'sendTx';
type SupportedCoin = 'hteth' | 'tbtc';
type CoinToFixtures<C extends SupportedCoin> = {
[K in SendManyFixtureMethod]: `${K}.${C}`;
} & { acceleratePrebuildTx: `prebuildTx.accelerate.${C}` | `prebuildTx.${C}` };
/** Registry — add a new coin here to support it across all sendMany integ test routes */
const COIN_FIXTURES: { [C in SupportedCoin]: CoinToFixtures<C> } = {
hteth: {
getWallet: 'getWallet.hteth',
prebuildTx: 'prebuildTx.hteth',
sendTx: 'sendTx.hteth',
acceleratePrebuildTx: 'prebuildTx.hteth', // CPFP/RBF not applicable to EVM; reuses standard prebuild
},
tbtc: {
getWallet: 'getWallet.tbtc',
prebuildTx: 'prebuildTx.tbtc',
sendTx: 'sendTx.tbtc',
acceleratePrebuildTx: 'prebuildTx.accelerate.tbtc',
},
};
function coinFixtures(coin: string): CoinToFixtures<SupportedCoin> {
const fixtures = COIN_FIXTURES[coin as SupportedCoin];
if (!fixtures) throw new Error(`No fixtures registered for coin: ${coin}`);
return fixtures;
}
export async function startMockBitgoServer(): Promise<MockBitgoServer> {
const calls: MockBitgoCall[] = [];
const app = express();
app.use(express.json());
app.use((req, _res, next) => {
calls.push({ method: req.method, path: req.path, body: req.body });
next();
});
/** SDK calls this on every BitGo instance initialisation */
app.get('/api/v1/client/constants', (_req, res) => {
res.json({ ttl: 3600, constants: {} });
});
/** Add keychain — source distinguishes user / backup / bitgo */
app.post('/api/v2/:coin/key', (req, res) => {
const { coin } = req.params;
const source = req.body?.source;
const fixtureName =
source === 'user' ? 'addKey.user' : source === 'backup' ? 'addKey.backup' : 'addKey.bitgo';
const fixture = loadFixture(fixtureName);
return res.json({ ...fixture, coin });
});
/** Create wallet */
app.post('/api/v2/:coin/wallet/add', (req, res) => {
const { coin } = req.params;
const fixture = loadFixture('createWallet');
res.json({ ...fixture, coin });
});
/** Get wallet — coin-specific fixture */
app.get('/api/v2/:coin/wallet/:walletId', (req, res) => {
const { coin } = req.params;
const fixture = loadFixture(coinFixtures(coin).getWallet);
res.json({ ...fixture, coin });
});
/** Get keychain — matched by keyId */
app.get('/api/v2/:coin/key/:keyId', (req, res) => {
const { keyId, coin } = req.params;
const fixtureName =
keyId === 'user-key-id'
? 'getKeychain.user'
: keyId === 'backup-key-id'
? 'getKeychain.backup'
: 'getKeychain.bitgo';
const fixture = loadFixture(fixtureName);
res.json({ ...fixture, coin });
});
/** Block height for fee estimation */
app.get('/api/v2/:coin/public/block/latest', (_req, res) => {
res.json(loadFixture('blockLatest'));
});
/** Transaction prebuild — coin-specific fixture */
app.post('/api/v2/:coin/wallet/:walletId/tx/build', (req, res) => {
const { coin } = req.params;
const isAccelerate = req.body?.cpfpTxIds?.length || req.body?.rbfTxIds?.length;
const fixtureName = isAccelerate
? coinFixtures(coin).acceleratePrebuildTx
: coinFixtures(coin).prebuildTx;
res.json(loadFixture(fixtureName));
});
/** Transaction submit — coin-specific fixture */
app.post('/api/v2/:coin/wallet/:walletId/tx/send', (req, res) => {
res.json(loadFixture(coinFixtures(req.params.coin).sendTx));
});
const server = http.createServer(app);
const port = await listen(server);
return { port, calls, close: () => close(server) };
}