Merge remote-tracking branch 'origin/master' into v2.1
This commit is contained in:
commit
51816e9938
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1,6 +1,6 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
github: ['mempool'] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
patreon: # Replace with a single Patreon username
|
patreon: # Replace with a single Patreon username
|
||||||
open_collective: # Replace with a single Open Collective username
|
open_collective: # Replace with a single Open Collective username
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
3
.github/workflows/on-tag.yml
vendored
3
.github/workflows/on-tag.yml
vendored
@ -34,6 +34,9 @@ jobs:
|
|||||||
- name: Checkout project
|
- name: Checkout project
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Init repo for Dockerization
|
||||||
|
run: docker/init.sh "$TAG"
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v1
|
||||||
id: qemu
|
id: qemu
|
||||||
|
@ -1 +0,0 @@
|
|||||||
9d02ab1eb5ffb60d38128df903e47e11b95f13d5
|
|
@ -48,12 +48,5 @@
|
|||||||
"BISQ_MARKETS": {
|
"BISQ_MARKETS": {
|
||||||
"ENABLED": false,
|
"ENABLED": false,
|
||||||
"DATA_PATH": "/bisq/statsnode-data/btc_mainnet/db"
|
"DATA_PATH": "/bisq/statsnode-data/btc_mainnet/db"
|
||||||
},
|
|
||||||
"SPONSORS": {
|
|
||||||
"ENABLED": false,
|
|
||||||
"BTCPAY_URL": "",
|
|
||||||
"BTCPAY_AUTH": "",
|
|
||||||
"BTCPAY_WEBHOOK_URL": "",
|
|
||||||
"TWITTER_BEARER_AUTH": ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,198 +0,0 @@
|
|||||||
import config from '../config';
|
|
||||||
import axios from 'axios';
|
|
||||||
import { DB } from '../database';
|
|
||||||
import logger from '../logger';
|
|
||||||
|
|
||||||
class Donations {
|
|
||||||
private notifyDonationStatusCallback: ((invoiceId: string) => void) | undefined;
|
|
||||||
private options = {
|
|
||||||
baseURL: config.SPONSORS.BTCPAY_URL,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': config.SPONSORS.BTCPAY_AUTH,
|
|
||||||
},
|
|
||||||
timeout: 10000,
|
|
||||||
};
|
|
||||||
|
|
||||||
sponsorsCache: any[] = [];
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
public async $updateCache() {
|
|
||||||
try {
|
|
||||||
this.sponsorsCache = await this.$getDonationsFromDatabase('handle, image');
|
|
||||||
} catch (e) {
|
|
||||||
logger.warn('Setting sponsorsCache failed ' + e.message || e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setNotfyDonationStatusCallback(fn: any): void {
|
|
||||||
this.notifyDonationStatusCallback = fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
async $createRequest(amount: number, orderId: string): Promise<any> {
|
|
||||||
logger.notice('New invoice request. Handle: ' + orderId + ' Amount: ' + amount + ' BTC');
|
|
||||||
|
|
||||||
const postData = {
|
|
||||||
'price': amount,
|
|
||||||
'orderId': orderId,
|
|
||||||
'currency': 'BTC',
|
|
||||||
'itemDesc': 'Sponsor mempool.space',
|
|
||||||
'notificationUrl': config.SPONSORS.BTCPAY_WEBHOOK_URL,
|
|
||||||
'redirectURL': 'https://mempool.space/about',
|
|
||||||
};
|
|
||||||
const response = await axios.post('/invoices', postData, this.options);
|
|
||||||
return {
|
|
||||||
id: response.data.data.id,
|
|
||||||
amount: parseFloat(response.data.data.btcPrice),
|
|
||||||
addresses: response.data.data.addresses,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async $handleWebhookRequest(data: any): Promise<void> {
|
|
||||||
if (!data || !data.id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const response = await this.$getStatus(data.id);
|
|
||||||
logger.notice(`Received BTCPayServer webhook. Invoice ID: ${data.id} Status: ${response.status} BTC Paid: ${response.btcPaid}`);
|
|
||||||
if (response.status !== 'complete' && response.status !== 'confirmed' && response.status !== 'paid') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.notifyDonationStatusCallback) {
|
|
||||||
this.notifyDonationStatusCallback(data.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseFloat(response.btcPaid) < 0.01) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.orderId !== '') {
|
|
||||||
try {
|
|
||||||
const userData = await this.$getTwitterUserData(response.orderId);
|
|
||||||
const imageUrl = userData.profile_image_url.replace('normal', '200x200');
|
|
||||||
const imageBlob = await this.$downloadProfileImageBlob(imageUrl);
|
|
||||||
|
|
||||||
logger.debug('Creating database entry for donation with invoice id: ' + response.id);
|
|
||||||
await this.$addDonationToDatabase(response.btcPaid, userData.screen_name, userData.id, response.id, imageUrl, imageBlob);
|
|
||||||
this.$updateCache();
|
|
||||||
} catch (e) {
|
|
||||||
logger.err(`Error fetching twitter data for handle ${response.orderId}: ${e.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getSponsorImage(id: string): any | undefined {
|
|
||||||
const sponsor = this.sponsorsCache.find((s) => s.handle === id);
|
|
||||||
if (sponsor) {
|
|
||||||
return sponsor.image;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async $getDonationsFromDatabase(fields: string): Promise<any[]> {
|
|
||||||
try {
|
|
||||||
const connection = await DB.pool.getConnection();
|
|
||||||
const query = `SELECT ${fields} FROM donations ORDER BY id DESC`;
|
|
||||||
const [rows] = await connection.query<any>(query);
|
|
||||||
connection.release();
|
|
||||||
return rows;
|
|
||||||
} catch (e) {
|
|
||||||
logger.err('$getDonationsFromDatabase() error: ' + e.message || e);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async $getOldDonations(): Promise<any[]> {
|
|
||||||
try {
|
|
||||||
const connection = await DB.pool.getConnection();
|
|
||||||
const query = `SELECT * FROM donations WHERE twitter_id IS NULL AND handle != ''`;
|
|
||||||
const [rows] = await connection.query<any>(query);
|
|
||||||
connection.release();
|
|
||||||
return rows;
|
|
||||||
} catch (e) {
|
|
||||||
logger.err('$getLegacyDonations() error' + e.message || e);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async $getStatus(id: string): Promise<any> {
|
|
||||||
logger.debug('Fetching status for invoice: ' + id);
|
|
||||||
const response = await axios.get('/invoices/' + id, this.options);
|
|
||||||
logger.debug('Invoice status received: ' + JSON.stringify(response.data));
|
|
||||||
return response.data.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async $addDonationToDatabase(btcPaid: number, handle: string, twitter_id: number | null,
|
|
||||||
orderId: string, imageUrl: string, image: string): Promise<void> {
|
|
||||||
try {
|
|
||||||
const connection = await DB.pool.getConnection();
|
|
||||||
const query = `INSERT IGNORE INTO donations(added, amount, handle, twitter_id, order_id, imageUrl, image) VALUES (NOW(), ?, ?, ?, ?, ?, FROM_BASE64(?))`;
|
|
||||||
const params: (string | number | null)[] = [
|
|
||||||
btcPaid,
|
|
||||||
handle,
|
|
||||||
twitter_id,
|
|
||||||
orderId,
|
|
||||||
imageUrl,
|
|
||||||
image,
|
|
||||||
];
|
|
||||||
const [result]: any = await connection.query(query, params);
|
|
||||||
connection.release();
|
|
||||||
} catch (e) {
|
|
||||||
logger.err('$addDonationToDatabase() error' + e.message || e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async $updateDonation(id: number, handle: string, twitterId: number, imageUrl: string, image: string): Promise<void> {
|
|
||||||
try {
|
|
||||||
const connection = await DB.pool.getConnection();
|
|
||||||
const query = `UPDATE donations SET handle = ?, twitter_id = ?, imageUrl = ?, image = FROM_BASE64(?) WHERE id = ?`;
|
|
||||||
const params: (string | number)[] = [
|
|
||||||
handle,
|
|
||||||
twitterId,
|
|
||||||
imageUrl,
|
|
||||||
image,
|
|
||||||
id,
|
|
||||||
];
|
|
||||||
const [result]: any = await connection.query(query, params);
|
|
||||||
connection.release();
|
|
||||||
} catch (e) {
|
|
||||||
logger.err('$updateDonation() error' + e.message || e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async $getTwitterUserData(handle: string): Promise<any> {
|
|
||||||
logger.debug('Fetching Twitter API data...');
|
|
||||||
const res = await axios.get(`https://api.twitter.com/1.1/users/show.json?screen_name=${handle}`, {
|
|
||||||
headers: {
|
|
||||||
Authorization: 'Bearer ' + config.SPONSORS.TWITTER_BEARER_AUTH
|
|
||||||
},
|
|
||||||
timeout: 10000,
|
|
||||||
});
|
|
||||||
logger.debug('Twitter user data fetched:' + JSON.stringify(res.data));
|
|
||||||
return res.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async $downloadProfileImageBlob(url: string): Promise<string> {
|
|
||||||
logger.debug('Fetching image blob...');
|
|
||||||
const res = await axios.get(url, { responseType: 'arraybuffer', timeout: 10000 });
|
|
||||||
logger.debug('Image downloaded.');
|
|
||||||
return Buffer.from(res.data, 'utf8').toString('base64');
|
|
||||||
}
|
|
||||||
|
|
||||||
private async refreshSponsors(): Promise<void> {
|
|
||||||
const oldDonations = await this.$getOldDonations();
|
|
||||||
oldDonations.forEach(async (donation: any) => {
|
|
||||||
logger.debug('Migrating donation for handle: ' + donation.handle);
|
|
||||||
try {
|
|
||||||
const twitterData = await this.$getTwitterUserData(donation.handle);
|
|
||||||
const imageUrl = twitterData.profile_image_url.replace('normal', '200x200');
|
|
||||||
const imageBlob = await this.$downloadProfileImageBlob(imageUrl);
|
|
||||||
await this.$updateDonation(donation.id, twitterData.screen_name, twitterData.id, imageUrl, imageBlob);
|
|
||||||
} catch (e) {
|
|
||||||
logger.err('Failed to migrate donation for handle: ' + donation.handle + '. ' + (e.message || e));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new Donations();
|
|
@ -51,13 +51,6 @@ interface IConfig {
|
|||||||
ENABLED: boolean;
|
ENABLED: boolean;
|
||||||
DATA_PATH: string;
|
DATA_PATH: string;
|
||||||
};
|
};
|
||||||
SPONSORS: {
|
|
||||||
ENABLED: boolean;
|
|
||||||
BTCPAY_URL: string;
|
|
||||||
BTCPAY_AUTH: string;
|
|
||||||
BTCPAY_WEBHOOK_URL: string;
|
|
||||||
TWITTER_BEARER_AUTH: string;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaults: IConfig = {
|
const defaults: IConfig = {
|
||||||
@ -111,13 +104,6 @@ const defaults: IConfig = {
|
|||||||
'ENABLED': false,
|
'ENABLED': false,
|
||||||
'DATA_PATH': '/bisq/statsnode-data/btc_mainnet/db'
|
'DATA_PATH': '/bisq/statsnode-data/btc_mainnet/db'
|
||||||
},
|
},
|
||||||
'SPONSORS': {
|
|
||||||
'ENABLED': false,
|
|
||||||
'BTCPAY_URL': '',
|
|
||||||
'BTCPAY_AUTH': '',
|
|
||||||
'BTCPAY_WEBHOOK_URL': '',
|
|
||||||
'TWITTER_BEARER_AUTH': ''
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Config implements IConfig {
|
class Config implements IConfig {
|
||||||
@ -130,7 +116,6 @@ class Config implements IConfig {
|
|||||||
STATISTICS: IConfig['STATISTICS'];
|
STATISTICS: IConfig['STATISTICS'];
|
||||||
BISQ_BLOCKS: IConfig['BISQ_BLOCKS'];
|
BISQ_BLOCKS: IConfig['BISQ_BLOCKS'];
|
||||||
BISQ_MARKETS: IConfig['BISQ_MARKETS'];
|
BISQ_MARKETS: IConfig['BISQ_MARKETS'];
|
||||||
SPONSORS: IConfig['SPONSORS'];
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
const configs = this.merge(configFile, defaults);
|
const configs = this.merge(configFile, defaults);
|
||||||
@ -143,7 +128,6 @@ class Config implements IConfig {
|
|||||||
this.STATISTICS = configs.STATISTICS;
|
this.STATISTICS = configs.STATISTICS;
|
||||||
this.BISQ_BLOCKS = configs.BISQ_BLOCKS;
|
this.BISQ_BLOCKS = configs.BISQ_BLOCKS;
|
||||||
this.BISQ_MARKETS = configs.BISQ_MARKETS;
|
this.BISQ_MARKETS = configs.BISQ_MARKETS;
|
||||||
this.SPONSORS = configs.SPONSORS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
merge = (...objects: object[]): IConfig => {
|
merge = (...objects: object[]): IConfig => {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Express, Request, Response, NextFunction } from 'express';
|
import { Express, Request, Response, NextFunction } from 'express';
|
||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import * as https from 'https';
|
|
||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
import * as cluster from 'cluster';
|
import * as cluster from 'cluster';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
@ -17,7 +16,6 @@ import websocketHandler from './api/websocket-handler';
|
|||||||
import fiatConversion from './api/fiat-conversion';
|
import fiatConversion from './api/fiat-conversion';
|
||||||
import bisq from './api/bisq/bisq';
|
import bisq from './api/bisq/bisq';
|
||||||
import bisqMarkets from './api/bisq/markets';
|
import bisqMarkets from './api/bisq/markets';
|
||||||
import donations from './api/donations';
|
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
import backendInfo from './api/backend-info';
|
import backendInfo from './api/backend-info';
|
||||||
import loadingIndicators from './api/loading-indicators';
|
import loadingIndicators from './api/loading-indicators';
|
||||||
@ -25,7 +23,7 @@ import mempool from './api/mempool';
|
|||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
private wss: WebSocket.Server | undefined;
|
private wss: WebSocket.Server | undefined;
|
||||||
private server: https.Server | http.Server | undefined;
|
private server: http.Server | undefined;
|
||||||
private app: Express;
|
private app: Express;
|
||||||
private currentBackendRetryInterval = 5;
|
private currentBackendRetryInterval = 5;
|
||||||
|
|
||||||
@ -87,10 +85,6 @@ class Server {
|
|||||||
|
|
||||||
fiatConversion.startService();
|
fiatConversion.startService();
|
||||||
|
|
||||||
if (config.SPONSORS.ENABLED) {
|
|
||||||
donations.$updateCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setUpHttpApiRoutes();
|
this.setUpHttpApiRoutes();
|
||||||
this.setUpWebsocketHandling();
|
this.setUpWebsocketHandling();
|
||||||
this.runMainUpdateLoop();
|
this.runMainUpdateLoop();
|
||||||
@ -144,7 +138,6 @@ class Server {
|
|||||||
statistics.setNewStatisticsEntryCallback(websocketHandler.handleNewStatistic.bind(websocketHandler));
|
statistics.setNewStatisticsEntryCallback(websocketHandler.handleNewStatistic.bind(websocketHandler));
|
||||||
blocks.setNewBlockCallback(websocketHandler.handleNewBlock.bind(websocketHandler));
|
blocks.setNewBlockCallback(websocketHandler.handleNewBlock.bind(websocketHandler));
|
||||||
memPool.setMempoolChangedCallback(websocketHandler.handleMempoolChange.bind(websocketHandler));
|
memPool.setMempoolChangedCallback(websocketHandler.handleMempoolChange.bind(websocketHandler));
|
||||||
donations.setNotfyDonationStatusCallback(websocketHandler.handleNewDonation.bind(websocketHandler));
|
|
||||||
fiatConversion.setProgressChangedCallback(websocketHandler.handleNewConversionRates.bind(websocketHandler));
|
fiatConversion.setProgressChangedCallback(websocketHandler.handleNewConversionRates.bind(websocketHandler));
|
||||||
loadingIndicators.setProgressChangedCallback(websocketHandler.handleLoadingChanged.bind(websocketHandler));
|
loadingIndicators.setProgressChangedCallback(websocketHandler.handleLoadingChanged.bind(websocketHandler));
|
||||||
}
|
}
|
||||||
@ -156,6 +149,24 @@ class Server {
|
|||||||
.get(config.MEMPOOL.API_URL_PREFIX + 'fees/mempool-blocks', routes.getMempoolBlocks)
|
.get(config.MEMPOOL.API_URL_PREFIX + 'fees/mempool-blocks', routes.getMempoolBlocks)
|
||||||
.get(config.MEMPOOL.API_URL_PREFIX + 'backend-info', routes.getBackendInfo)
|
.get(config.MEMPOOL.API_URL_PREFIX + 'backend-info', routes.getBackendInfo)
|
||||||
.get(config.MEMPOOL.API_URL_PREFIX + 'init-data', routes.getInitData)
|
.get(config.MEMPOOL.API_URL_PREFIX + 'init-data', routes.getInitData)
|
||||||
|
.get(config.MEMPOOL.API_URL_PREFIX + 'donations', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get('https://mempool.space/api/v1/donations', { responseType: 'stream', timeout: 10000 });
|
||||||
|
response.data.pipe(res);
|
||||||
|
} catch (e) {
|
||||||
|
res.status(500).end();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.get(config.MEMPOOL.API_URL_PREFIX + 'donations/images/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get('https://mempool.space/api/v1/donations/images/' + req.params.id, {
|
||||||
|
responseType: 'stream', timeout: 10000
|
||||||
|
});
|
||||||
|
response.data.pipe(res);
|
||||||
|
} catch (e) {
|
||||||
|
res.status(500).end();
|
||||||
|
}
|
||||||
|
})
|
||||||
;
|
;
|
||||||
|
|
||||||
if (config.STATISTICS.ENABLED && config.DATABASE.ENABLED) {
|
if (config.STATISTICS.ENABLED && config.DATABASE.ENABLED) {
|
||||||
@ -195,35 +206,6 @@ class Server {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.SPONSORS.ENABLED) {
|
|
||||||
this.app
|
|
||||||
.get(config.MEMPOOL.API_URL_PREFIX + 'donations', routes.getDonations.bind(routes))
|
|
||||||
.get(config.MEMPOOL.API_URL_PREFIX + 'donations/images/:id', routes.getSponsorImage.bind(routes))
|
|
||||||
.post(config.MEMPOOL.API_URL_PREFIX + 'donations', routes.createDonationRequest.bind(routes))
|
|
||||||
.post(config.MEMPOOL.API_URL_PREFIX + 'donations-webhook', routes.donationWebhook.bind(routes))
|
|
||||||
;
|
|
||||||
} else {
|
|
||||||
this.app
|
|
||||||
.get(config.MEMPOOL.API_URL_PREFIX + 'donations', async (req, res) => {
|
|
||||||
try {
|
|
||||||
const response = await axios.get('https://mempool.space/api/v1/donations', { responseType: 'stream', timeout: 10000 });
|
|
||||||
response.data.pipe(res);
|
|
||||||
} catch (e) {
|
|
||||||
res.status(500).end();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.get(config.MEMPOOL.API_URL_PREFIX + 'donations/images/:id', async (req, res) => {
|
|
||||||
try {
|
|
||||||
const response = await axios.get('https://mempool.space/api/v1/donations/images/' + req.params.id, {
|
|
||||||
responseType: 'stream', timeout: 10000
|
|
||||||
});
|
|
||||||
response.data.pipe(res);
|
|
||||||
} catch (e) {
|
|
||||||
res.status(500).end();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.MEMPOOL.BACKEND !== 'esplora') {
|
if (config.MEMPOOL.BACKEND !== 'esplora') {
|
||||||
this.app
|
this.app
|
||||||
.get(config.MEMPOOL.API_URL_PREFIX + 'mempool', routes.getMempool)
|
.get(config.MEMPOOL.API_URL_PREFIX + 'mempool', routes.getMempool)
|
||||||
|
@ -8,10 +8,9 @@ import mempool from './api/mempool';
|
|||||||
import bisq from './api/bisq/bisq';
|
import bisq from './api/bisq/bisq';
|
||||||
import websocketHandler from './api/websocket-handler';
|
import websocketHandler from './api/websocket-handler';
|
||||||
import bisqMarket from './api/bisq/markets-api';
|
import bisqMarket from './api/bisq/markets-api';
|
||||||
import { OptimizedStatistic, RequiredSpec, TransactionExtended } from './mempool.interfaces';
|
import { RequiredSpec, TransactionExtended } from './mempool.interfaces';
|
||||||
import { MarketsApiError } from './api/bisq/interfaces';
|
import { MarketsApiError } from './api/bisq/interfaces';
|
||||||
import { IEsploraApi } from './api/bitcoin/esplora-api.interface';
|
import { IEsploraApi } from './api/bitcoin/esplora-api.interface';
|
||||||
import donations from './api/donations';
|
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
import bitcoinApi from './api/bitcoin/bitcoin-api-factory';
|
import bitcoinApi from './api/bitcoin/bitcoin-api-factory';
|
||||||
import transactionUtils from './api/transaction-utils';
|
import transactionUtils from './api/transaction-utils';
|
||||||
@ -99,79 +98,6 @@ class Routes {
|
|||||||
res.json(backendInfo.getBackendInfo());
|
res.json(backendInfo.getBackendInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createDonationRequest(req: Request, res: Response) {
|
|
||||||
const constraints: RequiredSpec = {
|
|
||||||
'amount': {
|
|
||||||
required: true,
|
|
||||||
types: ['@float']
|
|
||||||
},
|
|
||||||
'orderId': {
|
|
||||||
required: true,
|
|
||||||
types: ['@string']
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const p = this.parseRequestParameters(req.body, constraints);
|
|
||||||
if (p.error) {
|
|
||||||
res.status(400).send(p.error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p.orderId !== '' && !/^(@|)[a-zA-Z0-9_]{1,15}$/.test(p.orderId)) {
|
|
||||||
res.status(400).send('Invalid Twitter handle');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p.amount < 0.001) {
|
|
||||||
res.status(400).send('Amount needs to be at least 0.001');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p.amount > 1000) {
|
|
||||||
res.status(400).send('Amount too large');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await donations.$createRequest(p.amount, p.orderId);
|
|
||||||
res.json(result);
|
|
||||||
} catch (e) {
|
|
||||||
res.status(500).send(e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getDonations(req: Request, res: Response) {
|
|
||||||
try {
|
|
||||||
const result = await donations.$getDonationsFromDatabase('handle, imageUrl');
|
|
||||||
res.json(result);
|
|
||||||
} catch (e) {
|
|
||||||
res.status(500).send(e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getSponsorImage(req: Request, res: Response) {
|
|
||||||
try {
|
|
||||||
const result = await donations.getSponsorImage(req.params.id);
|
|
||||||
if (result) {
|
|
||||||
res.set('Content-Type', 'image/jpeg');
|
|
||||||
res.send(result);
|
|
||||||
} else {
|
|
||||||
res.status(404).end();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
res.status(500).send(e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async donationWebhook(req: Request, res: Response) {
|
|
||||||
try {
|
|
||||||
donations.$handleWebhookRequest(req.body);
|
|
||||||
res.end();
|
|
||||||
} catch (e) {
|
|
||||||
res.status(500).send(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public getBisqStats(req: Request, res: Response) {
|
public getBisqStats(req: Request, res: Response) {
|
||||||
const result = bisq.getStats();
|
const result = bisq.getStats();
|
||||||
res.json(result);
|
res.json(result);
|
||||||
|
99
docker/README.md
Normal file
99
docker/README.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# Docker
|
||||||
|
|
||||||
|
## Initialization
|
||||||
|
|
||||||
|
In an empty dir create 2 sub-dirs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p data mysql/data mysql/db-scripts
|
||||||
|
```
|
||||||
|
|
||||||
|
In the mysql/db-scripts sub-dir add the mariadb-structure.sql file from the mempool repo
|
||||||
|
|
||||||
|
Your dir should now look like that:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ls -R
|
||||||
|
.:
|
||||||
|
data mysql
|
||||||
|
|
||||||
|
./data:
|
||||||
|
|
||||||
|
./mysql:
|
||||||
|
data db-scripts
|
||||||
|
|
||||||
|
./mysql/data:
|
||||||
|
|
||||||
|
./mysql/db-scripts:
|
||||||
|
mariadb-structure.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
In the main dir add the following docker-compose.yml
|
||||||
|
|
||||||
|
```bash
|
||||||
|
version: "3.7"
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: mempool/frontend:latest
|
||||||
|
user: "1000:1000"
|
||||||
|
restart: on-failure
|
||||||
|
stop_grace_period: 1m
|
||||||
|
command: "./wait-for db:3306 --timeout=720 -- nginx -g 'daemon off;'"
|
||||||
|
ports:
|
||||||
|
- 80:8080
|
||||||
|
environment:
|
||||||
|
FRONTEND_HTTP_PORT: "8080"
|
||||||
|
BACKEND_MAINNET_HTTP_HOST: "api"
|
||||||
|
api:
|
||||||
|
image: mempool/backend:latest
|
||||||
|
user: "1000:1000"
|
||||||
|
restart: on-failure
|
||||||
|
stop_grace_period: 1m
|
||||||
|
command: "./wait-for-it.sh db:3306 --timeout=720 --strict -- ./start.sh"
|
||||||
|
volumes:
|
||||||
|
- ./data:/backend/cache
|
||||||
|
environment:
|
||||||
|
RPC_HOST: "127.0.0.1"
|
||||||
|
RPC_PORT: "8332"
|
||||||
|
RPC_USER: "mempool"
|
||||||
|
RPC_PASS: "mempool"
|
||||||
|
ELECTRS_HOST: "127.0.0.1"
|
||||||
|
ELECTRS_PORT: "50002"
|
||||||
|
MYSQL_HOST: "db"
|
||||||
|
MYSQL_PORT: "3306"
|
||||||
|
MYSQL_DATABASE: "mempool"
|
||||||
|
MYSQL_USER: "mempool"
|
||||||
|
MYSQL_PASS: "mempool"
|
||||||
|
BACKEND_MAINNET_HTTP_PORT: "8999"
|
||||||
|
CACHE_DIR: "/backend/cache/"
|
||||||
|
db:
|
||||||
|
image: mariadb:10.5.8
|
||||||
|
user: "1000:1000"
|
||||||
|
restart: on-failure
|
||||||
|
stop_grace_period: 1m
|
||||||
|
volumes:
|
||||||
|
- ./mysql/data:/var/lib/mysql
|
||||||
|
- ./mysql/db-scripts:/docker-entrypoint-initdb.d
|
||||||
|
environment:
|
||||||
|
MYSQL_DATABASE: "mempool"
|
||||||
|
MYSQL_USER: "mempool"
|
||||||
|
MYSQL_PASSWORD: "mempool"
|
||||||
|
MYSQL_ROOT_PASSWORD: "admin"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
You can update all the environment variables inside the API container, especially the RPC and ELECTRS ones
|
||||||
|
|
||||||
|
## Run it
|
||||||
|
|
||||||
|
To run our docker-compose use the following cmd:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
If everything went okay you should see the beautiful mempool :grin:
|
||||||
|
|
||||||
|
If you get stuck on "loading blocks", this means the websocket can't connect.
|
||||||
|
Check your nginx proxy setup, firewalls, etc. and open an issue if you need help.
|
@ -3,17 +3,12 @@ FROM node:12-buster-slim AS builder
|
|||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN sed -i "s!../.git/refs/heads/master!master!g" ./src/api/backend-info.ts
|
|
||||||
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get install -y build-essential python3 pkg-config
|
RUN apt-get install -y build-essential python3 pkg-config
|
||||||
RUN npm ci --production
|
RUN npm ci --production
|
||||||
RUN npm i typescript
|
RUN npm i typescript
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
RUN mv ./docker/* .
|
|
||||||
RUN mv ./mempool-config-docker.json ./mempool-config.json
|
|
||||||
|
|
||||||
FROM node:12-buster-slim
|
FROM node:12-buster-slim
|
||||||
|
|
||||||
WORKDIR /backend
|
WORKDIR /backend
|
@ -27,9 +27,9 @@
|
|||||||
"ENABLED": true,
|
"ENABLED": true,
|
||||||
"HOST": "__MYSQL_HOST__",
|
"HOST": "__MYSQL_HOST__",
|
||||||
"PORT": __MYSQL_PORT__,
|
"PORT": __MYSQL_PORT__,
|
||||||
"DATABASE": "mempool",
|
"DATABASE": "__MYSQL_DATABASE__",
|
||||||
"USERNAME": "mempool",
|
"USERNAME": "__MYSQL_USERNAME__",
|
||||||
"PASSWORD": "mempool"
|
"PASSWORD": "__MYSQL_PASSWORD__"
|
||||||
},
|
},
|
||||||
"STATISTICS": {
|
"STATISTICS": {
|
||||||
"ENABLED": true,
|
"ENABLED": true,
|
@ -14,6 +14,9 @@ __ELECTRS_MAINNET_HTTP_PORT__=${ELECTRS_PORT:=50002}
|
|||||||
# MYSQL
|
# MYSQL
|
||||||
__MYSQL_HOST__=${MYSQL_HOST:=127.0.0.1}
|
__MYSQL_HOST__=${MYSQL_HOST:=127.0.0.1}
|
||||||
__MYSQL_PORT__=${MYSQL_PORT:=3306}
|
__MYSQL_PORT__=${MYSQL_PORT:=3306}
|
||||||
|
__MYSQL_DATABASE__=${MYSQL_DATABASE:=mempool}
|
||||||
|
__MYSQL_USERNAME__=${MYSQL_USER:=mempool}
|
||||||
|
__MYSQL_PASSWORD__=${MYSQL_PASS:=mempool}
|
||||||
|
|
||||||
mkdir -p "${__MEMPOOL_BACKEND_MAINNET_CACHE_DIR__}"
|
mkdir -p "${__MEMPOOL_BACKEND_MAINNET_CACHE_DIR__}"
|
||||||
|
|
||||||
@ -25,6 +28,9 @@ sed -i "s/__ELECTRS_MAINNET_HTTP_HOST__/${__ELECTRS_MAINNET_HTTP_HOST__}/g" memp
|
|||||||
sed -i "s/__ELECTRS_MAINNET_HTTP_PORT__/${__ELECTRS_MAINNET_HTTP_PORT__}/g" mempool-config.json
|
sed -i "s/__ELECTRS_MAINNET_HTTP_PORT__/${__ELECTRS_MAINNET_HTTP_PORT__}/g" mempool-config.json
|
||||||
sed -i "s/__MYSQL_HOST__/${__MYSQL_HOST__}/g" mempool-config.json
|
sed -i "s/__MYSQL_HOST__/${__MYSQL_HOST__}/g" mempool-config.json
|
||||||
sed -i "s/__MYSQL_PORT__/${__MYSQL_PORT__}/g" mempool-config.json
|
sed -i "s/__MYSQL_PORT__/${__MYSQL_PORT__}/g" mempool-config.json
|
||||||
|
sed -i "s/__MYSQL_DATABASE__/${__MYSQL_DATABASE__}/g" mempool-config.json
|
||||||
|
sed -i "s/__MYSQL_USERNAME__/${__MYSQL_USERNAME__}/g" mempool-config.json
|
||||||
|
sed -i "s/__MYSQL_PASSWORD__/${__MYSQL_PASSWORD__}/g" mempool-config.json
|
||||||
sed -i "s!__MEMPOOL_BACKEND_MAINNET_CACHE_DIR__!${__MEMPOOL_BACKEND_MAINNET_CACHE_DIR__}!g" mempool-config.json
|
sed -i "s!__MEMPOOL_BACKEND_MAINNET_CACHE_DIR__!${__MEMPOOL_BACKEND_MAINNET_CACHE_DIR__}!g" mempool-config.json
|
||||||
sed -i "s/__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__/${__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__}/g" mempool-config.json
|
sed -i "s/__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__/${__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__}/g" mempool-config.json
|
||||||
|
|
@ -7,8 +7,6 @@ RUN apt-get install -y build-essential rsync
|
|||||||
RUN npm i
|
RUN npm i
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
RUN mv ./docker/* .
|
|
||||||
|
|
||||||
FROM nginx:1.17.8-alpine
|
FROM nginx:1.17.8-alpine
|
||||||
|
|
||||||
WORKDIR /patch
|
WORKDIR /patch
|
||||||
@ -25,13 +23,12 @@ RUN chmod +x /patch/wait-for
|
|||||||
RUN chown -R 1000:1000 /patch && chmod -R 755 /patch && \
|
RUN chown -R 1000:1000 /patch && chmod -R 755 /patch && \
|
||||||
chown -R 1000:1000 /var/cache/nginx && \
|
chown -R 1000:1000 /var/cache/nginx && \
|
||||||
chown -R 1000:1000 /var/log/nginx && \
|
chown -R 1000:1000 /var/log/nginx && \
|
||||||
|
chown -R 1000:1000 /etc/nginx/nginx.conf && \
|
||||||
chown -R 1000:1000 /etc/nginx/conf.d
|
chown -R 1000:1000 /etc/nginx/conf.d
|
||||||
RUN touch /var/run/nginx.pid && \
|
RUN touch /var/run/nginx.pid && \
|
||||||
chown -R 1000:1000 /var/run/nginx.pid
|
chown -R 1000:1000 /var/run/nginx.pid
|
||||||
|
|
||||||
USER 1000
|
USER 1000
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
|
|
||||||
ENTRYPOINT ["/patch/entrypoint.sh"]
|
ENTRYPOINT ["/patch/entrypoint.sh"]
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
@ -1,8 +1,13 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__=${BACKEND_MAINNET_HTTP_HOST:=127.0.0.1}
|
__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__=${BACKEND_MAINNET_HTTP_HOST:=127.0.0.1}
|
||||||
__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__=${BACKEND_MAINNET_HTTP_PORT:=8999}
|
__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__=${BACKEND_MAINNET_HTTP_PORT:=8999}
|
||||||
|
__MEMPOOL_FRONTEND_HTTP_PORT__=${FRONTEND_HTTP_PORT:=8080}
|
||||||
|
|
||||||
sed -i "s/__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__/${__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__}/g" /etc/nginx/conf.d/nginx-mempool.conf
|
sed -i "s/__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__/${__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__}/g" /etc/nginx/conf.d/nginx-mempool.conf
|
||||||
sed -i "s/__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__/${__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__}/g" /etc/nginx/conf.d/nginx-mempool.conf
|
sed -i "s/__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__/${__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__}/g" /etc/nginx/conf.d/nginx-mempool.conf
|
||||||
|
|
||||||
|
cp /etc/nginx/nginx.conf /patch/nginx.conf
|
||||||
|
sed -i "s/__MEMPOOL_FRONTEND_HTTP_PORT__/${__MEMPOOL_FRONTEND_HTTP_PORT__}/g" /patch/nginx.conf
|
||||||
|
cat /patch/nginx.conf > /etc/nginx/nginx.conf
|
||||||
|
|
||||||
exec "$@"
|
exec "$@"
|
18
docker/init.sh
Executable file
18
docker/init.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#backend
|
||||||
|
gitMaster="\.\.\/\.git\/refs\/heads\/master"
|
||||||
|
git ls-remote https://github.com/mempool/mempool.git $1 | awk '{ print $1}' > ./backend/master
|
||||||
|
cp ./docker/backend/* ./backend/
|
||||||
|
sed -i "s/${gitMaster}/master/g" ./backend/src/api/backend-info.ts
|
||||||
|
|
||||||
|
#frontend
|
||||||
|
localhostIP="127.0.0.1"
|
||||||
|
cp ./docker/frontend/* ./frontend
|
||||||
|
cp ./nginx.conf ./frontend/
|
||||||
|
cp ./nginx-mempool.conf ./frontend/
|
||||||
|
sed -i "s/${localhostIP}:80/0.0.0.0:__MEMPOOL_FRONTEND_HTTP_PORT__/g" ./frontend/nginx.conf
|
||||||
|
sed -i "s/${localhostIP}/0.0.0.0/g" ./frontend/nginx.conf
|
||||||
|
sed -i "s/user nobody;//g" ./frontend/nginx.conf
|
||||||
|
sed -i "s!/etc/nginx/nginx-mempool.conf!/etc/nginx/conf.d/nginx-mempool.conf!g" ./frontend/nginx.conf
|
||||||
|
sed -i "s/${localhostIP}:8999/__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__:__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__/g" ./frontend/nginx-mempool.conf
|
@ -1,62 +0,0 @@
|
|||||||
access_log /var/log/nginx/access_mempool.log;
|
|
||||||
error_log /var/log/nginx/error_mempool.log;
|
|
||||||
|
|
||||||
root /var/www/mempool/browser;
|
|
||||||
|
|
||||||
index index.html;
|
|
||||||
|
|
||||||
# fallback for all URLs i.e. /address/foo /tx/foo /block/000
|
|
||||||
location / {
|
|
||||||
try_files /$lang/$uri /$lang/$uri/ $uri $uri/ /en-US/$uri @index-redirect;
|
|
||||||
}
|
|
||||||
location @index-redirect {
|
|
||||||
add_header vary accept-language;
|
|
||||||
rewrite (.*) /$lang/index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# location block using regex are matched in order
|
|
||||||
|
|
||||||
# used to rewrite resources from /<lang>/ to /en-US/
|
|
||||||
location ~ ^/(ar|bg|bs|ca|cs|da|de|et|el|es|eo|eu|fa|fr|gl|ko|hr|id|it|he|ka|lv|lt|hu|mk|ms|nl|ja|ka|no|nb|nn|pl|pt|pt-BR|ro|ru|sk|sl|sr|sh|fi|sv|th|tr|uk|vi|zh)/resources/ {
|
|
||||||
rewrite ^/[a-zA-Z-]*/resources/(.*) /en-US/resources/$1;
|
|
||||||
}
|
|
||||||
# used for cookie override
|
|
||||||
location ~ ^/(ar|bg|bs|ca|cs|da|de|et|el|es|eo|eu|fa|fr|gl|ko|hr|id|it|he|ka|lv|lt|hu|mk|ms|nl|ja|ka|no|nb|nn|pl|pt|pt-BR|ro|ru|sk|sl|sr|sh|fi|sv|th|tr|uk|vi|zh)/ {
|
|
||||||
try_files $uri $uri/ /$1/index.html =404;
|
|
||||||
}
|
|
||||||
|
|
||||||
# static API docs
|
|
||||||
location = /api {
|
|
||||||
try_files $uri $uri/ /en-US/index.html =404;
|
|
||||||
}
|
|
||||||
location = /api/ {
|
|
||||||
try_files $uri $uri/ /en-US/index.html =404;
|
|
||||||
}
|
|
||||||
|
|
||||||
# mainnet API
|
|
||||||
location /api/v1/donations {
|
|
||||||
proxy_pass https://mempool.space;
|
|
||||||
}
|
|
||||||
location /api/v1/donations/images {
|
|
||||||
proxy_pass https://mempool.space;
|
|
||||||
}
|
|
||||||
location /api/v1/ws {
|
|
||||||
proxy_pass http://__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__:__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__/;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "Upgrade";
|
|
||||||
}
|
|
||||||
location /api/v1 {
|
|
||||||
proxy_pass http://__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__:__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__/api/v1;
|
|
||||||
}
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__:__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__/api/v1/;
|
|
||||||
}
|
|
||||||
|
|
||||||
# mainnet API
|
|
||||||
location /ws {
|
|
||||||
proxy_pass http://__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__:__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__/;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "Upgrade";
|
|
||||||
}
|
|
@ -1,128 +0,0 @@
|
|||||||
|
|
||||||
pid /var/run/nginx.pid;
|
|
||||||
|
|
||||||
worker_processes auto;
|
|
||||||
worker_rlimit_nofile 100000;
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 9000;
|
|
||||||
multi_accept on;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
sendfile on;
|
|
||||||
tcp_nopush on;
|
|
||||||
tcp_nodelay on;
|
|
||||||
|
|
||||||
server_tokens off;
|
|
||||||
server_name_in_redirect off;
|
|
||||||
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log;
|
|
||||||
error_log /var/log/nginx/error.log;
|
|
||||||
|
|
||||||
# reset timed out connections freeing ram
|
|
||||||
reset_timedout_connection on;
|
|
||||||
# maximum time between packets the client can pause when sending nginx any data
|
|
||||||
client_body_timeout 10s;
|
|
||||||
# maximum time the client has to send the entire header to nginx
|
|
||||||
client_header_timeout 10s;
|
|
||||||
# timeout which a single keep-alive client connection will stay open
|
|
||||||
keepalive_timeout 69s;
|
|
||||||
# maximum time between packets nginx is allowed to pause when sending the client data
|
|
||||||
send_timeout 10s;
|
|
||||||
|
|
||||||
# number of requests per connection, does not affect SPDY
|
|
||||||
keepalive_requests 100;
|
|
||||||
|
|
||||||
# enable gzip compression
|
|
||||||
gzip on;
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_comp_level 6;
|
|
||||||
gzip_min_length 1000;
|
|
||||||
gzip_proxied expired no-cache no-store private auth;
|
|
||||||
# text/html is always compressed by gzip module
|
|
||||||
gzip_types application/javascript application/json application/ld+json application/manifest+json application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard;
|
|
||||||
|
|
||||||
# limit request body size
|
|
||||||
client_max_body_size 10m;
|
|
||||||
|
|
||||||
# proxy cache
|
|
||||||
proxy_cache off;
|
|
||||||
proxy_cache_path /var/cache/nginx keys_zone=cache:20m levels=1:2 inactive=600s max_size=500m;
|
|
||||||
types_hash_max_size 2048;
|
|
||||||
|
|
||||||
# exempt localhost from rate limit
|
|
||||||
geo $limited_ip {
|
|
||||||
default 1;
|
|
||||||
0.0.0.0 0;
|
|
||||||
}
|
|
||||||
map $limited_ip $limited_ip_key {
|
|
||||||
1 $binary_remote_addr;
|
|
||||||
0 '';
|
|
||||||
}
|
|
||||||
|
|
||||||
# rate limit requests
|
|
||||||
limit_req_zone $limited_ip_key zone=api:5m rate=200r/m;
|
|
||||||
limit_req_zone $limited_ip_key zone=electrs:5m rate=2000r/m;
|
|
||||||
limit_req_status 429;
|
|
||||||
|
|
||||||
# rate limit connections
|
|
||||||
limit_conn_zone $limited_ip_key zone=websocket:10m;
|
|
||||||
limit_conn_status 429;
|
|
||||||
|
|
||||||
map $http_accept_language $header_lang {
|
|
||||||
default en-US;
|
|
||||||
~*^en-US en-US;
|
|
||||||
~*^en en-US;
|
|
||||||
~*^ar ar;
|
|
||||||
~*^cs cs;
|
|
||||||
~*^de de;
|
|
||||||
~*^es es;
|
|
||||||
~*^fa fa;
|
|
||||||
~*^fr fr;
|
|
||||||
~*^ja ja;
|
|
||||||
~*^ka ka;
|
|
||||||
~*^hu hu;
|
|
||||||
~*^nl nl;
|
|
||||||
~*^nn nn;
|
|
||||||
~*^pt pt;
|
|
||||||
~*^sl sl;
|
|
||||||
~*^sv sv;
|
|
||||||
~*^tr tr;
|
|
||||||
~*^uk uk;
|
|
||||||
~*^vi vi;
|
|
||||||
~*^zh zh;
|
|
||||||
}
|
|
||||||
|
|
||||||
map $cookie_lang $lang {
|
|
||||||
default $header_lang;
|
|
||||||
~*^en-US en-US;
|
|
||||||
~*^en en-US;
|
|
||||||
~*^ar ar;
|
|
||||||
~*^cs cs;
|
|
||||||
~*^de de;
|
|
||||||
~*^es es;
|
|
||||||
~*^fa fa;
|
|
||||||
~*^fr fr;
|
|
||||||
~*^ja ja;
|
|
||||||
~*^ka ka;
|
|
||||||
~*^hu hu;
|
|
||||||
~*^nl nl;
|
|
||||||
~*^nn nn;
|
|
||||||
~*^pt pt;
|
|
||||||
~*^sl sl;
|
|
||||||
~*^sv sv;
|
|
||||||
~*^tr tr;
|
|
||||||
~*^uk uk;
|
|
||||||
~*^vi vi;
|
|
||||||
~*^zh zh;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 0.0.0.0:8080;
|
|
||||||
include /etc/nginx/conf.d/nginx-mempool.conf;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,8 @@
|
|||||||
{
|
{
|
||||||
|
"/api/v1/donations": {
|
||||||
|
"target": "http://localhost:9000/",
|
||||||
|
"secure": false
|
||||||
|
},
|
||||||
"/api/v1": {
|
"/api/v1": {
|
||||||
"target": "http://localhost:8999/",
|
"target": "http://localhost:8999/",
|
||||||
"secure": false
|
"secure": false
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td i18n="BSQ token market cap">Market cap</td>
|
<td i18n="BSQ token market cap">Market cap</td>
|
||||||
<td><app-fiat [value]="price * (stats.minted - stats.burnt) / 100"></app-fiat></td>
|
<td><app-fiat [value]="price * (stats.minted - stats.burnt)"></app-fiat></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -83,4 +83,4 @@
|
|||||||
<td><span class="skeleton-loader"></span></td>
|
<td><span class="skeleton-loader"></span></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
<div class="text-small text-center offset-md-1">
|
<div class="text-small text-center offset-md-1">
|
||||||
v2.1.0
|
v2.1-SNAPSHOT ({{ gitCommit$ | async }})
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@ -173,10 +173,9 @@
|
|||||||
|
|
||||||
<div *ngIf="donationStatus === 4" class="text-center">
|
<div *ngIf="donationStatus === 4" class="text-center">
|
||||||
<h2><span i18n="about.sponsor.donation-confirmed">Donation confirmed!</span><br><span i18n="about.sponsor.thank-you">Thank you!</span></h2>
|
<h2><span i18n="about.sponsor.donation-confirmed">Donation confirmed!</span><br><span i18n="about.sponsor.thank-you">Thank you!</span></h2>
|
||||||
<p i18n="about.sponsor.sponsor-completed">If you specified a Twitter handle, the profile photo should now be visible on this page when you reload.</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br><br><br><br>
|
<br><br><br>
|
||||||
|
|
||||||
<a target="_blank" class="m-2 fw6 mb3 mt2 truncate black-80 f4 link" href="https://github.com/mempool/mempool">
|
<a target="_blank" class="m-2 fw6 mb3 mt2 truncate black-80 f4 link" href="https://github.com/mempool/mempool">
|
||||||
<span class="dib v-mid">
|
<span class="dib v-mid">
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { WebsocketService } from '../../services/websocket.service';
|
import { WebsocketService } from '../../services/websocket.service';
|
||||||
import { SeoService } from 'src/app/services/seo.service';
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
import { StateService } from 'src/app/services/state.service';
|
import { StateService } from 'src/app/services/state.service';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, Subscription } from 'rxjs';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { ApiService } from 'src/app/services/api.service';
|
import { ApiService } from 'src/app/services/api.service';
|
||||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
||||||
import { map } from 'rxjs/operators';
|
import { delay, map, retryWhen, switchMap, tap } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-about',
|
selector: 'app-about',
|
||||||
templateUrl: './about.component.html',
|
templateUrl: './about.component.html',
|
||||||
styleUrls: ['./about.component.scss'],
|
styleUrls: ['./about.component.scss'],
|
||||||
})
|
})
|
||||||
export class AboutComponent implements OnInit {
|
export class AboutComponent implements OnInit, OnDestroy {
|
||||||
gitCommit$: Observable<string>;
|
gitCommit$: Observable<string>;
|
||||||
donationForm: FormGroup;
|
donationForm: FormGroup;
|
||||||
paymentForm: FormGroup;
|
paymentForm: FormGroup;
|
||||||
@ -22,6 +22,7 @@ export class AboutComponent implements OnInit {
|
|||||||
donationObj: any;
|
donationObj: any;
|
||||||
sponsorsEnabled = this.stateService.env.SPONSORS_ENABLED;
|
sponsorsEnabled = this.stateService.env.SPONSORS_ENABLED;
|
||||||
sponsors = null;
|
sponsors = null;
|
||||||
|
requestSubscription: Subscription | undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private websocketService: WebsocketService,
|
private websocketService: WebsocketService,
|
||||||
@ -50,23 +51,37 @@ export class AboutComponent implements OnInit {
|
|||||||
.subscribe((sponsors) => {
|
.subscribe((sponsors) => {
|
||||||
this.sponsors = sponsors;
|
this.sponsors = sponsors;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.apiService.getDonation$()
|
ngOnDestroy() {
|
||||||
this.stateService.donationConfirmed$.subscribe(() => this.donationStatus = 4);
|
if (this.requestSubscription) {
|
||||||
|
this.requestSubscription.unsubscribe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
submitDonation() {
|
submitDonation() {
|
||||||
if (this.donationForm.invalid) {
|
if (this.donationForm.invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.apiService.requestDonation$(
|
this.requestSubscription = this.apiService.requestDonation$(
|
||||||
this.donationForm.get('amount').value,
|
this.donationForm.get('amount').value,
|
||||||
this.donationForm.get('handle').value
|
this.donationForm.get('handle').value
|
||||||
)
|
)
|
||||||
.subscribe((response) => {
|
.pipe(
|
||||||
this.websocketService.trackDonation(response.id);
|
tap((response) => {
|
||||||
this.donationObj = response;
|
this.donationObj = response;
|
||||||
this.donationStatus = 3;
|
this.donationStatus = 3;
|
||||||
|
}),
|
||||||
|
switchMap(() => this.apiService.checkDonation$(this.donationObj.id)
|
||||||
|
.pipe(
|
||||||
|
retryWhen((errors) => errors.pipe(delay(2000)))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).subscribe(() => {
|
||||||
|
this.donationStatus = 4;
|
||||||
|
if (this.donationForm.get('handle').value) {
|
||||||
|
this.sponsors.unshift({ handle: this.donationForm.get('handle').value });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,19 +43,23 @@ export class AddressLabelsComponent implements OnInit {
|
|||||||
} else {
|
} else {
|
||||||
this.liquid = 'Emergency Peg Out';
|
this.liquid = 'Emergency Peg Out';
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[
|
[
|
||||||
{regexp: /^OP_DUP OP_HASH160/, label: 'HTLC'},
|
// {regexp: /^OP_DUP OP_HASH160/, label: 'HTLC'},
|
||||||
{regexp: /^OP_IF OP_PUSHBYTES_33 \w{33} OP_ELSE OP_PUSHBYTES_2 \w{2} OP_CSV OP_DROP/, label: 'Force Close'}
|
{regexp: /^OP_IF OP_PUSHBYTES_33 \w{33} OP_ELSE OP_PUSHBYTES_2 \w{2} OP_CSV OP_DROP/, label: 'Force Close'}
|
||||||
].forEach((item) => {
|
].forEach((item) => {
|
||||||
if (item.regexp.test(this.vin.inner_witnessscript_asm)) {
|
if (item.regexp.test(this.vin.inner_witnessscript_asm)) {
|
||||||
this.lightning = item.label;
|
this.lightning = item.label;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (this.lightning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.vin.inner_witnessscript_asm.indexOf('OP_CHECKMULTISIG') > -1) {
|
if (this.vin.inner_witnessscript_asm.indexOf('OP_CHECKMULTISIG') > -1) {
|
||||||
const matches = this.getMatches(this.vin.inner_witnessscript_asm, /OP_PUSHNUM_([0-9])/g, 1);
|
const matches = this.getMatches(this.vin.inner_witnessscript_asm, /OP_PUSHNUM_([0-9])/g, 1);
|
||||||
this.multisig = true;
|
this.multisig = true;
|
||||||
|
@ -15,13 +15,11 @@ export interface WebsocketResponse {
|
|||||||
tx?: Transaction;
|
tx?: Transaction;
|
||||||
rbfTransaction?: Transaction;
|
rbfTransaction?: Transaction;
|
||||||
transactions?: TransactionStripped[];
|
transactions?: TransactionStripped[];
|
||||||
donationConfirmed?: boolean;
|
|
||||||
loadingIndicators?: ILoadingIndicators;
|
loadingIndicators?: ILoadingIndicators;
|
||||||
'track-tx'?: string;
|
'track-tx'?: string;
|
||||||
'track-address'?: string;
|
'track-address'?: string;
|
||||||
'track-asset'?: string;
|
'track-asset'?: string;
|
||||||
'watch-mempool'?: boolean;
|
'watch-mempool'?: boolean;
|
||||||
'track-donation'?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MempoolBlock {
|
export interface MempoolBlock {
|
||||||
|
@ -77,6 +77,10 @@ export class ApiService {
|
|||||||
return this.httpClient.get<any[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/donations');
|
return this.httpClient.get<any[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/donations');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkDonation$(orderId: string): Observable<any[]> {
|
||||||
|
return this.httpClient.get<any[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/donations/check?order_id=' + orderId);
|
||||||
|
}
|
||||||
|
|
||||||
getInitData$(): Observable<WebsocketResponse> {
|
getInitData$(): Observable<WebsocketResponse> {
|
||||||
return this.httpClient.get<WebsocketResponse>(this.apiBaseUrl + this.apiBasePath + '/api/v1/init-data');
|
return this.httpClient.get<WebsocketResponse>(this.apiBaseUrl + this.apiBasePath + '/api/v1/init-data');
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,6 @@ export class StateService {
|
|||||||
vbytesPerSecond$ = new ReplaySubject<number>(1);
|
vbytesPerSecond$ = new ReplaySubject<number>(1);
|
||||||
lastDifficultyAdjustment$ = new ReplaySubject<number>(1);
|
lastDifficultyAdjustment$ = new ReplaySubject<number>(1);
|
||||||
gitCommit$ = new ReplaySubject<string>(1);
|
gitCommit$ = new ReplaySubject<string>(1);
|
||||||
donationConfirmed$ = new Subject();
|
|
||||||
loadingIndicators$ = new ReplaySubject<ILoadingIndicators>(1);
|
loadingIndicators$ = new ReplaySubject<ILoadingIndicators>(1);
|
||||||
|
|
||||||
live2Chart$ = new Subject<OptimizedMempoolStats>();
|
live2Chart$ = new Subject<OptimizedMempoolStats>();
|
||||||
|
@ -126,10 +126,6 @@ export class WebsocketService {
|
|||||||
this.isTrackingTx = true;
|
this.isTrackingTx = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
trackDonation(id: string) {
|
|
||||||
this.websocketSubject.next({ 'track-donation': id });
|
|
||||||
}
|
|
||||||
|
|
||||||
stopTrackingTransaction() {
|
stopTrackingTransaction() {
|
||||||
if (!this.isTrackingTx) {
|
if (!this.isTrackingTx) {
|
||||||
return;
|
return;
|
||||||
@ -289,9 +285,5 @@ export class WebsocketService {
|
|||||||
if (response['git-commit']) {
|
if (response['git-commit']) {
|
||||||
this.stateService.gitCommit$.next(response['git-commit']);
|
this.stateService.gitCommit$.next(response['git-commit']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.donationConfirmed) {
|
|
||||||
this.stateService.donationConfirmed$.next(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">205</context>
|
<context context-type="linenumber">208</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/bisq/bisq-transfers/bisq-transfers.component.html</context>
|
<context context-type="sourcefile">src/app/bisq/bisq-transfers/bisq-transfers.component.html</context>
|
||||||
@ -67,7 +67,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">206</context>
|
<context context-type="linenumber">209</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/bisq/bisq-transfers/bisq-transfers.component.html</context>
|
<context context-type="sourcefile">src/app/bisq/bisq-transfers/bisq-transfers.component.html</context>
|
||||||
@ -88,7 +88,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">209</context>
|
<context context-type="linenumber">212</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">Transaction unconfirmed state</note>
|
<note priority="1" from="description">Transaction unconfirmed state</note>
|
||||||
<note priority="1" from="meaning">transaction.unconfirmed</note>
|
<note priority="1" from="meaning">transaction.unconfirmed</note>
|
||||||
@ -242,7 +242,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">198</context>
|
<context context-type="linenumber">201</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/block/block.component.html</context>
|
<context context-type="sourcefile">src/app/components/block/block.component.html</context>
|
||||||
@ -468,7 +468,7 @@
|
|||||||
<source>nSequence</source>
|
<source>nSequence</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">92</context>
|
<context context-type="linenumber">95</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">transactions-list.nsequence</note>
|
<note priority="1" from="description">transactions-list.nsequence</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -476,7 +476,7 @@
|
|||||||
<source>ScriptSig (ASM)</source>
|
<source>ScriptSig (ASM)</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">71</context>
|
<context context-type="linenumber">74</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">ScriptSig (ASM)</note>
|
<note priority="1" from="description">ScriptSig (ASM)</note>
|
||||||
<note priority="1" from="meaning">transactions-list.scriptsig.asm</note>
|
<note priority="1" from="meaning">transactions-list.scriptsig.asm</note>
|
||||||
@ -485,7 +485,7 @@
|
|||||||
<source>ScriptSig (HEX)</source>
|
<source>ScriptSig (HEX)</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">75</context>
|
<context context-type="linenumber">78</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">ScriptSig (HEX)</note>
|
<note priority="1" from="description">ScriptSig (HEX)</note>
|
||||||
<note priority="1" from="meaning">transactions-list.scriptsig.hex</note>
|
<note priority="1" from="meaning">transactions-list.scriptsig.hex</note>
|
||||||
@ -494,7 +494,7 @@
|
|||||||
<source>Witness</source>
|
<source>Witness</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">80</context>
|
<context context-type="linenumber">83</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">transactions-list.witness</note>
|
<note priority="1" from="description">transactions-list.witness</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -502,7 +502,7 @@
|
|||||||
<source>P2SH redeem script</source>
|
<source>P2SH redeem script</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">84</context>
|
<context context-type="linenumber">87</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">transactions-list.p2sh-redeem-script</note>
|
<note priority="1" from="description">transactions-list.p2sh-redeem-script</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -510,7 +510,7 @@
|
|||||||
<source>P2WSH witness script</source>
|
<source>P2WSH witness script</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">88</context>
|
<context context-type="linenumber">91</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">transactions-list.p2wsh-witness-script</note>
|
<note priority="1" from="description">transactions-list.p2wsh-witness-script</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -518,7 +518,7 @@
|
|||||||
<source>Previous output script</source>
|
<source>Previous output script</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">96</context>
|
<context context-type="linenumber">99</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">transactions-list.previous-output-script</note>
|
<note priority="1" from="description">transactions-list.previous-output-script</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -526,11 +526,11 @@
|
|||||||
<source>Load all</source>
|
<source>Load all</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">106</context>
|
<context context-type="linenumber">109</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">188</context>
|
<context context-type="linenumber">191</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">transactions-list.load-all</note>
|
<note priority="1" from="description">transactions-list.load-all</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -538,7 +538,7 @@
|
|||||||
<source>Peg-out to <x id="START_TAG_NG_CONTAINER" ctype="x-ng_container" equiv-text="<ng-container *ngTemplateOutlet="pegOutLink">"/><x id="CLOSE_TAG_NG_CONTAINER" ctype="x-ng_container" equiv-text="</ng-container>"/></source>
|
<source>Peg-out to <x id="START_TAG_NG_CONTAINER" ctype="x-ng_container" equiv-text="<ng-container *ngTemplateOutlet="pegOutLink">"/><x id="CLOSE_TAG_NG_CONTAINER" ctype="x-ng_container" equiv-text="</ng-container>"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">125</context>
|
<context context-type="linenumber">128</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">transactions-list.peg-out-to</note>
|
<note priority="1" from="description">transactions-list.peg-out-to</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -546,7 +546,7 @@
|
|||||||
<source>ScriptPubKey (ASM)</source>
|
<source>ScriptPubKey (ASM)</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">170</context>
|
<context context-type="linenumber">173</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">ScriptPubKey (ASM)</note>
|
<note priority="1" from="description">ScriptPubKey (ASM)</note>
|
||||||
<note priority="1" from="meaning">transactions-list.scriptpubkey.asm</note>
|
<note priority="1" from="meaning">transactions-list.scriptpubkey.asm</note>
|
||||||
@ -555,7 +555,7 @@
|
|||||||
<source>ScriptPubKey (HEX)</source>
|
<source>ScriptPubKey (HEX)</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">174</context>
|
<context context-type="linenumber">177</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">ScriptPubKey (HEX)</note>
|
<note priority="1" from="description">ScriptPubKey (HEX)</note>
|
||||||
<note priority="1" from="meaning">transactions-list.scriptpubkey.hex</note>
|
<note priority="1" from="meaning">transactions-list.scriptpubkey.hex</note>
|
||||||
@ -564,7 +564,7 @@
|
|||||||
<source>Type</source>
|
<source>Type</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">166</context>
|
<context context-type="linenumber">169</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/bisq/bisq-transaction-details/bisq-transaction-details.component.html</context>
|
<context context-type="sourcefile">src/app/bisq/bisq-transaction-details/bisq-transaction-details.component.html</context>
|
||||||
@ -580,7 +580,7 @@
|
|||||||
<source>data</source>
|
<source>data</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">178</context>
|
<context context-type="linenumber">181</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">transactions-list.vout.scriptpubkey-type.data</note>
|
<note priority="1" from="description">transactions-list.vout.scriptpubkey-type.data</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -588,7 +588,7 @@
|
|||||||
<source>sat</source>
|
<source>sat</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">198</context>
|
<context context-type="linenumber">201</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">sat</note>
|
<note priority="1" from="description">sat</note>
|
||||||
<note priority="1" from="meaning">shared.sat</note>
|
<note priority="1" from="meaning">shared.sat</note>
|
||||||
@ -597,7 +597,7 @@
|
|||||||
<source>Confidential</source>
|
<source>Confidential</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
|
||||||
<context context-type="linenumber">214</context>
|
<context context-type="linenumber">217</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/amount/amount.component.html</context>
|
<context context-type="sourcefile">src/app/components/amount/amount.component.html</context>
|
||||||
@ -605,7 +605,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
||||||
<context context-type="linenumber">132</context>
|
<context context-type="linenumber">134</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/asset/asset.component.html</context>
|
<context context-type="sourcefile">src/app/components/asset/asset.component.html</context>
|
||||||
@ -841,11 +841,23 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">shared.address</note>
|
<note priority="1" from="description">shared.address</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="7e69426bd97a606d8ae6026762858e6e7c86a1fd" datatype="html">
|
||||||
|
<source>Balance</source>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
||||||
|
<context context-type="linenumber">30</context>
|
||||||
|
</context-group>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/bisq/bisq-address/bisq-address.component.html</context>
|
||||||
|
<context context-type="linenumber">28</context>
|
||||||
|
</context-group>
|
||||||
|
<note priority="1" from="description">address.balance</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="a9b87c3aa4731edee661c8287ef3aab71799c0b8" datatype="html">
|
<trans-unit id="a9b87c3aa4731edee661c8287ef3aab71799c0b8" datatype="html">
|
||||||
<source>Total received</source>
|
<source>Total received</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
||||||
<context context-type="linenumber">20</context>
|
<context context-type="linenumber">21</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/bisq/bisq-address/bisq-address.component.html</context>
|
<context context-type="sourcefile">src/app/bisq/bisq-address/bisq-address.component.html</context>
|
||||||
@ -857,7 +869,7 @@
|
|||||||
<source>Total sent</source>
|
<source>Total sent</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
||||||
<context context-type="linenumber">24</context>
|
<context context-type="linenumber">25</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/bisq/bisq-address/bisq-address.component.html</context>
|
<context context-type="sourcefile">src/app/bisq/bisq-address/bisq-address.component.html</context>
|
||||||
@ -869,23 +881,11 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">address.total-sent</note>
|
<note priority="1" from="description">address.total-sent</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7e69426bd97a606d8ae6026762858e6e7c86a1fd" datatype="html">
|
|
||||||
<source>Balance</source>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
|
||||||
<context context-type="linenumber">28</context>
|
|
||||||
</context-group>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/bisq/bisq-address/bisq-address.component.html</context>
|
|
||||||
<context context-type="linenumber">28</context>
|
|
||||||
</context-group>
|
|
||||||
<note priority="1" from="description">address.balance</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="714e34125b3343df73f19ec800b43be95217d5d4" datatype="html">
|
<trans-unit id="714e34125b3343df73f19ec800b43be95217d5d4" datatype="html">
|
||||||
<source><x id="INTERPOLATION" equiv-text="{{ (transactions?.length | number) || '?' }}"/> of <x id="INTERPOLATION_1" equiv-text="{{ txCount | number }}"/> transaction</source>
|
<source><x id="INTERPOLATION" equiv-text="{{ (transactions?.length | number) || '?' }}"/> of <x id="INTERPOLATION_1" equiv-text="{{ txCount | number }}"/> transaction</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
||||||
<context context-type="linenumber">48</context>
|
<context context-type="linenumber">50</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">X of X Address Transaction</note>
|
<note priority="1" from="description">X of X Address Transaction</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -893,7 +893,7 @@
|
|||||||
<source><x id="INTERPOLATION" equiv-text="{{ (transactions?.length | number) || '?' }}"/> of <x id="INTERPOLATION_1" equiv-text="{{ txCount | number }}"/> transactions</source>
|
<source><x id="INTERPOLATION" equiv-text="{{ (transactions?.length | number) || '?' }}"/> of <x id="INTERPOLATION_1" equiv-text="{{ txCount | number }}"/> transactions</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
||||||
<context context-type="linenumber">49</context>
|
<context context-type="linenumber">51</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">X of X Address Transactions (Plural)</note>
|
<note priority="1" from="description">X of X Address Transactions (Plural)</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -901,7 +901,7 @@
|
|||||||
<source>Error loading address data.</source>
|
<source>Error loading address data.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
<context context-type="sourcefile">src/app/components/address/address.component.html</context>
|
||||||
<context context-type="linenumber">113</context>
|
<context context-type="linenumber">115</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">address.error.loading-address-data</note>
|
<note priority="1" from="description">address.error.loading-address-data</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -1020,15 +1020,23 @@
|
|||||||
<source>multisig <x id="INTERPOLATION" equiv-text="{{ multisigM }}"/> of <x id="INTERPOLATION_1" equiv-text="{{ multisigN }}"/></source>
|
<source>multisig <x id="INTERPOLATION" equiv-text="{{ multisigM }}"/> of <x id="INTERPOLATION_1" equiv-text="{{ multisigN }}"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/address-labels/address-labels.component.html</context>
|
<context context-type="sourcefile">src/app/components/address-labels/address-labels.component.html</context>
|
||||||
<context context-type="linenumber">1</context>
|
<context context-type="linenumber">5</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">address-labels.multisig</note>
|
<note priority="1" from="description">address-labels.multisig</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="aae004b987aaf258dea1829618651427b68283db" datatype="html">
|
<trans-unit id="31c09dcc0ab351767631539b208d5f7de4005473" datatype="html">
|
||||||
<source>Layer<x id="INTERPOLATION" equiv-text="{{ network === 'liquid' ? '3' : '2' }}"/> Peg-out</source>
|
<source>Lightning <x id="INTERPOLATION" equiv-text="{{ lightning }}"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/address-labels/address-labels.component.html</context>
|
<context context-type="sourcefile">src/app/components/address-labels/address-labels.component.html</context>
|
||||||
<context context-type="linenumber">2</context>
|
<context context-type="linenumber">11</context>
|
||||||
|
</context-group>
|
||||||
|
<note priority="1" from="description">address-labels.upper-layer-peg-out</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="696ade981a05c12e10df38ba6218c76e318813b3" datatype="html">
|
||||||
|
<source>Liquid <x id="INTERPOLATION" equiv-text="{{ liquid }}"/></source>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/address-labels/address-labels.component.html</context>
|
||||||
|
<context context-type="linenumber">17</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">address-labels.upper-layer-peg-out</note>
|
<note priority="1" from="description">address-labels.upper-layer-peg-out</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -1052,7 +1060,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/about/about.component.ts</context>
|
<context context-type="sourcefile">src/app/components/about/about.component.ts</context>
|
||||||
<context context-type="linenumber">37</context>
|
<context context-type="linenumber">38</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">master-page.about</note>
|
<note priority="1" from="description">master-page.about</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@ -1199,7 +1207,7 @@
|
|||||||
<source>Terms of Service</source>
|
<source>Terms of Service</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/about/about.component.html</context>
|
<context context-type="sourcefile">src/app/components/about/about.component.html</context>
|
||||||
<context context-type="linenumber">206</context>
|
<context context-type="linenumber">205</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/dashboard/dashboard.component.html</context>
|
<context context-type="sourcefile">src/app/dashboard/dashboard.component.html</context>
|
||||||
@ -1268,14 +1276,6 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<note priority="1" from="description">about.sponsor.thank-you</note>
|
<note priority="1" from="description">about.sponsor.thank-you</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="981a90db6601297002689e5fae09d38b9e374b05" datatype="html">
|
|
||||||
<source>If you specified a Twitter handle, the profile photo should now be visible on this page when you reload.</source>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/about/about.component.html</context>
|
|
||||||
<context context-type="linenumber">176</context>
|
|
||||||
</context-group>
|
|
||||||
<note priority="1" from="description">about.sponsor.sponsor-completed</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="ff4b7f4070be9e876c7610d99b9dbd53ff19dceb" datatype="html">
|
<trans-unit id="ff4b7f4070be9e876c7610d99b9dbd53ff19dceb" datatype="html">
|
||||||
<source>Loading graphs...</source>
|
<source>Loading graphs...</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
|
BIN
frontend/src/resources/screenshots/v2.1.0-dashboard.png
Normal file
BIN
frontend/src/resources/screenshots/v2.1.0-dashboard.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 482 KiB |
@ -84,24 +84,3 @@ ALTER TABLE `transactions`
|
|||||||
|
|
||||||
ALTER TABLE `statistics`
|
ALTER TABLE `statistics`
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE `donations` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`added` datetime NOT NULL,
|
|
||||||
`amount` float NOT NULL,
|
|
||||||
`handle` varchar(250) NOT NULL,
|
|
||||||
`order_id` varchar(25) NOT NULL,
|
|
||||||
`imageUrl` varchar(250) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
ALTER TABLE `donations`
|
|
||||||
ADD PRIMARY KEY (`id`);
|
|
||||||
|
|
||||||
ALTER TABLE `donations`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
|
||||||
|
|
||||||
ALTER TABLE `donations` ADD UNIQUE(`order_id`);
|
|
||||||
|
|
||||||
ALTER TABLE `donations` ADD `image` MEDIUMBLOB NULL AFTER `imageUrl`;
|
|
||||||
ALTER TABLE `donations` ADD `twitter_id` VARCHAR(250) NULL AFTER `handle`;
|
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
[mysqld]
|
|
||||||
sql_mode="NO_AUTO_VALUE_ON_ZERO"
|
|
@ -1,5 +1,5 @@
|
|||||||
#!/usr/local/bin/zsh
|
#!/usr/local/bin/zsh
|
||||||
cd /electrs
|
cd $HOME/electrs
|
||||||
source $HOME/.cargo/env
|
source $HOME/.cargo/env
|
||||||
export PATH=$HOME/.cargo/bin:$PATH
|
export PATH=$HOME/.cargo/bin:$PATH
|
||||||
|
|
||||||
@ -11,9 +11,11 @@ do
|
|||||||
-- \
|
-- \
|
||||||
-vvvv \
|
-vvvv \
|
||||||
--address-search \
|
--address-search \
|
||||||
--daemon-dir /bitcoin \
|
--db-dir /electrs \
|
||||||
|
--daemon-dir $HOME \
|
||||||
--http-addr '[::]:3000' \
|
--http-addr '[::]:3000' \
|
||||||
--cookie 'user:pass' \
|
--cookie 'user:pass' \
|
||||||
--precache-scripts /electrs/contrib/popular-scripts.txt
|
--precache-scripts $HOME/electrs/contrib/popular-scripts.txt
|
||||||
sleep 1
|
|
||||||
|
sleep 3
|
||||||
done
|
done
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#!/usr/local/bin/zsh
|
#!/usr/local/bin/zsh
|
||||||
cd /electrs
|
cd $HOME/electrs
|
||||||
source $HOME/.cargo/env
|
source $HOME/.cargo/env
|
||||||
export PATH=$HOME/.cargo/bin:$PATH
|
export PATH=$HOME/.cargo/bin:$PATH
|
||||||
|
|
||||||
@ -9,11 +9,13 @@ do
|
|||||||
--release \
|
--release \
|
||||||
--bin electrs \
|
--bin electrs \
|
||||||
-- \
|
-- \
|
||||||
-vv \
|
-vvvv \
|
||||||
--network testnet \
|
--network testnet \
|
||||||
--daemon-dir /bitcoin \
|
--db-dir /electrs \
|
||||||
|
--daemon-dir $HOME \
|
||||||
--http-addr '[::]:3002' \
|
--http-addr '[::]:3002' \
|
||||||
--cookie 'user:pass' \
|
--cookie 'user:pass' \
|
||||||
--precache-scripts /electrs/contrib/popular-scripts.txt
|
--precache-scripts $HOME/electrs/contrib/popular-scripts.txt
|
||||||
sleep 1
|
|
||||||
|
sleep 3
|
||||||
done
|
done
|
||||||
|
Loading…
x
Reference in New Issue
Block a user