testmempool accept more validation & switch to JSON array format
This commit is contained in:
parent
f3232b2d5c
commit
2a43255802
@ -751,13 +751,13 @@ class BitcoinRoutes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async $testTransactions(req: Request, res: Response) {
|
private async $testTransactions(req: Request, res: Response) {
|
||||||
res.setHeader('content-type', 'text/plain');
|
|
||||||
try {
|
try {
|
||||||
const rawTxs = Common.getTransactionsFromRequest(req);
|
const rawTxs = Common.getTransactionsFromRequest(req);
|
||||||
const maxfeerate = parseFloat(req.query.maxfeerate as string);
|
const maxfeerate = parseFloat(req.query.maxfeerate as string);
|
||||||
const result = await bitcoinApi.$testMempoolAccept(rawTxs, maxfeerate);
|
const result = await bitcoinApi.$testMempoolAccept(rawTxs, maxfeerate);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
res.setHeader('content-type', 'text/plain');
|
||||||
res.status(400).send(e.message && e.code ? 'testmempoolaccept RPC error: ' + JSON.stringify({ code: e.code, message: e.message })
|
res.status(400).send(e.message && e.code ? 'testmempoolaccept RPC error: ' + JSON.stringify({ code: e.code, message: e.message })
|
||||||
: (e.message || 'Error'));
|
: (e.message || 'Error'));
|
||||||
}
|
}
|
||||||
|
@ -946,12 +946,16 @@ export class Common {
|
|||||||
return this.validateTransactionHex(matches[1].toLowerCase());
|
return this.validateTransactionHex(matches[1].toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
static getTransactionsFromRequest(req: Request): string[] {
|
static getTransactionsFromRequest(req: Request, limit: number = 25): string[] {
|
||||||
if (typeof req.body !== 'string') {
|
if (!Array.isArray(req.body) || req.body.some(hex => typeof hex !== 'string')) {
|
||||||
throw Object.assign(new Error('Non-string request body'), { code: -1 });
|
throw Object.assign(new Error('Invalid request body (should be an array of hexadecimal strings)'), { code: -1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const txs = req.body.split(',');
|
if (limit && req.body.length > limit) {
|
||||||
|
throw Object.assign(new Error('Exceeded maximum of 25 transactions'), { code: -1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const txs = req.body;
|
||||||
|
|
||||||
return txs.map(rawTx => {
|
return txs.map(rawTx => {
|
||||||
// Support both upper and lower case hex
|
// Support both upper and lower case hex
|
||||||
|
@ -131,6 +131,7 @@ class Server {
|
|||||||
})
|
})
|
||||||
.use(express.urlencoded({ extended: true }))
|
.use(express.urlencoded({ extended: true }))
|
||||||
.use(express.text({ type: ['text/plain', 'application/base64'] }))
|
.use(express.text({ type: ['text/plain', 'application/base64'] }))
|
||||||
|
.use(express.json())
|
||||||
;
|
;
|
||||||
|
|
||||||
if (config.DATABASE.ENABLED && config.FIAT_PRICE.ENABLED) {
|
if (config.DATABASE.ENABLED && config.FIAT_PRICE.ENABLED) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
td, th {
|
td, th {
|
||||||
&.allowed {
|
&.allowed {
|
||||||
width: 10%;
|
width: 10%;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
&.txid {
|
&.txid {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
@ -37,6 +37,21 @@ export class TestTransactionsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testTxs() {
|
testTxs() {
|
||||||
|
let txs: string[] = [];
|
||||||
|
try {
|
||||||
|
txs = (this.testTxsForm.get('txs')?.value as string).split(',').map(hex => hex.trim());
|
||||||
|
if (!txs?.length) {
|
||||||
|
this.error = 'At least one transaction is required';
|
||||||
|
return;
|
||||||
|
} else if (txs.length > 25) {
|
||||||
|
this.error = 'Exceeded maximum of 25 transactions';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.error = e?.message;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let maxfeerate;
|
let maxfeerate;
|
||||||
this.invalidMaxfeerate = false;
|
this.invalidMaxfeerate = false;
|
||||||
try {
|
try {
|
||||||
@ -51,7 +66,7 @@ export class TestTransactionsComponent implements OnInit {
|
|||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.error = '';
|
this.error = '';
|
||||||
this.results = [];
|
this.results = [];
|
||||||
this.apiService.testTransactions$((this.testTxsForm.get('txs')?.value as string).split(',').map(hex => hex.trim()).join(','), maxfeerate === 0.1 ? null : maxfeerate)
|
this.apiService.testTransactions$(txs, maxfeerate === 0.1 ? null : maxfeerate)
|
||||||
.subscribe((result) => {
|
.subscribe((result) => {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
this.results = result || [];
|
this.results = result || [];
|
||||||
|
@ -238,8 +238,8 @@ export class ApiService {
|
|||||||
return this.httpClient.post<any>(this.apiBaseUrl + this.apiBasePath + '/api/tx', hexPayload, { responseType: 'text' as 'json'});
|
return this.httpClient.post<any>(this.apiBaseUrl + this.apiBasePath + '/api/tx', hexPayload, { responseType: 'text' as 'json'});
|
||||||
}
|
}
|
||||||
|
|
||||||
testTransactions$(hexPayload: string, maxfeerate?: number): Observable<TestMempoolAcceptResult[]> {
|
testTransactions$(rawTxs: string[], maxfeerate?: number): Observable<TestMempoolAcceptResult[]> {
|
||||||
return this.httpClient.post<TestMempoolAcceptResult[]>(this.apiBaseUrl + this.apiBasePath + `/api/txs/test${maxfeerate != null ? '?maxfeerate=' + maxfeerate.toFixed(8) : ''}`, hexPayload);
|
return this.httpClient.post<TestMempoolAcceptResult[]>(this.apiBaseUrl + this.apiBasePath + `/api/txs/test${maxfeerate != null ? '?maxfeerate=' + maxfeerate.toFixed(8) : ''}`, rawTxs);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTransactionStatus$(txid: string): Observable<any> {
|
getTransactionStatus$(txid: string): Observable<any> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user