Merge pull request #1010 from mempool/simon/liquid-icons-api
Liquid icons api
This commit is contained in:
		
						commit
						5b22e2a000
					
				
							
								
								
									
										7
									
								
								backend/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								backend/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,7 +1,10 @@
 | 
			
		||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
 | 
			
		||||
 | 
			
		||||
# production config
 | 
			
		||||
mempool-config.json
 | 
			
		||||
# production config and external assets
 | 
			
		||||
*.json
 | 
			
		||||
!mempool-config.sample.json
 | 
			
		||||
 | 
			
		||||
icons.json
 | 
			
		||||
 | 
			
		||||
# compiled output
 | 
			
		||||
/dist
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,8 @@
 | 
			
		||||
    "INITIAL_BLOCKS_AMOUNT": 8,
 | 
			
		||||
    "MEMPOOL_BLOCKS_AMOUNT": 8,
 | 
			
		||||
    "PRICE_FEED_UPDATE_INTERVAL": 3600,
 | 
			
		||||
    "USE_SECOND_NODE_FOR_MINFEE": false
 | 
			
		||||
    "USE_SECOND_NODE_FOR_MINFEE": false,
 | 
			
		||||
    "EXTERNAL_ASSETS": []
 | 
			
		||||
  },
 | 
			
		||||
  "CORE_RPC": {
 | 
			
		||||
    "HOST": "127.0.0.1",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										39
									
								
								backend/src/api/liquid/icons.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								backend/src/api/liquid/icons.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
			
		||||
import * as fs from 'fs';
 | 
			
		||||
import config from '../../config';
 | 
			
		||||
import logger from '../../logger';
 | 
			
		||||
 | 
			
		||||
class Icons {
 | 
			
		||||
  private static FILE_NAME = './icons.json';
 | 
			
		||||
  private iconIds: string[] = [];
 | 
			
		||||
  private icons: { [assetId: string]: string; } = {};
 | 
			
		||||
 | 
			
		||||
  constructor() {}
 | 
			
		||||
 | 
			
		||||
  public loadIcons() {
 | 
			
		||||
    if (!fs.existsSync(Icons.FILE_NAME)) {
 | 
			
		||||
      logger.warn(`${Icons.FILE_NAME} does not exist. No Liquid icons loaded.`);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    const cacheData = fs.readFileSync(Icons.FILE_NAME, 'utf8');
 | 
			
		||||
    this.icons = JSON.parse(cacheData);
 | 
			
		||||
 | 
			
		||||
    for (const i in this.icons) {
 | 
			
		||||
      this.iconIds.push(i);
 | 
			
		||||
    }
 | 
			
		||||
    logger.debug(`Liquid icons has been loaded.`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getIconByAssetId(assetId: string): Buffer | undefined {
 | 
			
		||||
    const icon = this.icons[assetId];
 | 
			
		||||
    if (icon) {
 | 
			
		||||
      return Buffer.from(icon, 'base64');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getAllIconIds() {
 | 
			
		||||
    return this.iconIds;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default new Icons();
 | 
			
		||||
@ -16,6 +16,7 @@ interface IConfig {
 | 
			
		||||
    MEMPOOL_BLOCKS_AMOUNT: number;
 | 
			
		||||
    PRICE_FEED_UPDATE_INTERVAL: number;
 | 
			
		||||
    USE_SECOND_NODE_FOR_MINFEE: boolean;
 | 
			
		||||
    EXTERNAL_ASSETS: string[];
 | 
			
		||||
  };
 | 
			
		||||
  ESPLORA: {
 | 
			
		||||
    REST_API_URL: string;
 | 
			
		||||
@ -78,6 +79,7 @@ const defaults: IConfig = {
 | 
			
		||||
    'MEMPOOL_BLOCKS_AMOUNT': 8,
 | 
			
		||||
    'PRICE_FEED_UPDATE_INTERVAL': 3600,
 | 
			
		||||
    'USE_SECOND_NODE_FOR_MINFEE': false,
 | 
			
		||||
    'EXTERNAL_ASSETS': [],
 | 
			
		||||
  },
 | 
			
		||||
  'ESPLORA': {
 | 
			
		||||
    'REST_API_URL': 'http://127.0.0.1:3000',
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,8 @@ import backendInfo from './api/backend-info';
 | 
			
		||||
import loadingIndicators from './api/loading-indicators';
 | 
			
		||||
import mempool from './api/mempool';
 | 
			
		||||
import elementsParser from './api/liquid/elements-parser';
 | 
			
		||||
import syncAssets from './sync-assets';
 | 
			
		||||
import icons from './api/liquid/icons';
 | 
			
		||||
 | 
			
		||||
class Server {
 | 
			
		||||
  private wss: WebSocket.Server | undefined;
 | 
			
		||||
@ -77,6 +79,7 @@ class Server {
 | 
			
		||||
 | 
			
		||||
    this.setUpWebsocketHandling();
 | 
			
		||||
 | 
			
		||||
    await syncAssets.syncAssets();
 | 
			
		||||
    diskCache.loadMempoolCache();
 | 
			
		||||
 | 
			
		||||
    if (config.DATABASE.ENABLED) {
 | 
			
		||||
@ -87,6 +90,10 @@ class Server {
 | 
			
		||||
      statistics.startStatistics();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (config.MEMPOOL.NETWORK === 'liquid') {
 | 
			
		||||
      icons.loadIcons();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fiatConversion.startService();
 | 
			
		||||
 | 
			
		||||
    this.setUpHttpApiRoutes();
 | 
			
		||||
@ -270,6 +277,13 @@ class Server {
 | 
			
		||||
      ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (config.MEMPOOL.NETWORK === 'liquid') {
 | 
			
		||||
      this.app
 | 
			
		||||
        .get(config.MEMPOOL.API_URL_PREFIX + 'assets/icons', routes.getAllLiquidIcon)
 | 
			
		||||
        .get(config.MEMPOOL.API_URL_PREFIX + 'asset/:assetId/icon', routes.getLiquidIcon)
 | 
			
		||||
      ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (config.MEMPOOL.NETWORK === 'liquid' && config.DATABASE.ENABLED) {
 | 
			
		||||
      this.app
 | 
			
		||||
        .get(config.MEMPOOL.API_URL_PREFIX + 'liquid/pegs/month', routes.$getElementsPegsByMonth)
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ import loadingIndicators from './api/loading-indicators';
 | 
			
		||||
import { Common } from './api/common';
 | 
			
		||||
import bitcoinClient from './api/bitcoin/bitcoin-client';
 | 
			
		||||
import elementsParser from './api/liquid/elements-parser';
 | 
			
		||||
import icons from './api/liquid/icons';
 | 
			
		||||
 | 
			
		||||
class Routes {
 | 
			
		||||
  constructor() {}
 | 
			
		||||
@ -807,6 +808,26 @@ class Routes {
 | 
			
		||||
        : (e.message || 'Error'));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getLiquidIcon(req: Request, res: Response) {
 | 
			
		||||
    const result = icons.getIconByAssetId(req.params.assetId);
 | 
			
		||||
    if (result) {
 | 
			
		||||
      res.setHeader('content-type', 'image/png');
 | 
			
		||||
      res.setHeader('content-length', result.length);
 | 
			
		||||
      res.send(result);
 | 
			
		||||
    } else {
 | 
			
		||||
      res.status(404).send('Asset icon not found');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getAllLiquidIcon(req: Request, res: Response) {
 | 
			
		||||
    const result = icons.getAllIconIds();
 | 
			
		||||
    if (result) {
 | 
			
		||||
      res.json(result);
 | 
			
		||||
    } else {
 | 
			
		||||
      res.status(404).send('Asset icons not found');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default new Routes();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										32
									
								
								backend/src/sync-assets.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								backend/src/sync-assets.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
import axios from 'axios';
 | 
			
		||||
import * as fs from 'fs';
 | 
			
		||||
const fsPromises = fs.promises;
 | 
			
		||||
import config from './config';
 | 
			
		||||
import logger from './logger';
 | 
			
		||||
 | 
			
		||||
const PATH = './';
 | 
			
		||||
 | 
			
		||||
class SyncAssets {
 | 
			
		||||
  constructor() { }
 | 
			
		||||
 | 
			
		||||
  public async syncAssets() {
 | 
			
		||||
    for (const url of config.MEMPOOL.EXTERNAL_ASSETS) {
 | 
			
		||||
      await this.downloadFile(url);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async downloadFile(url: string) {
 | 
			
		||||
    const fileName = url.split('/').slice(-1)[0];
 | 
			
		||||
    logger.info(`Downloading external asset: ${fileName}...`);
 | 
			
		||||
    try {
 | 
			
		||||
      const response = await axios.get(url, {
 | 
			
		||||
        responseType: 'stream', timeout: 30000
 | 
			
		||||
      });
 | 
			
		||||
      await fsPromises.writeFile(PATH + fileName, response.data);
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
      throw new Error(`Failed to download external asset. ` + e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default new SyncAssets();
 | 
			
		||||
							
								
								
									
										96
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										96
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							@ -26,7 +26,7 @@
 | 
			
		||||
        "@fortawesome/fontawesome-svg-core": "^1.2.35",
 | 
			
		||||
        "@fortawesome/free-solid-svg-icons": "^5.15.3",
 | 
			
		||||
        "@juggle/resize-observer": "^3.3.1",
 | 
			
		||||
        "@mempool/mempool.js": "^2.2.4",
 | 
			
		||||
        "@mempool/mempool.js": "2.3.0-dev1",
 | 
			
		||||
        "@ng-bootstrap/ng-bootstrap": "^10.0.0",
 | 
			
		||||
        "@nguniversal/express-engine": "11.2.1",
 | 
			
		||||
        "@types/qrcode": "1.4.1",
 | 
			
		||||
@ -3230,12 +3230,40 @@
 | 
			
		||||
      "integrity": "sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@mempool/mempool.js": {
 | 
			
		||||
      "version": "2.2.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mempool/mempool.js/-/mempool.js-2.2.4.tgz",
 | 
			
		||||
      "integrity": "sha512-G9Ga2jHLfAuU/qXikRBtTecYr7BhLJH1WbIahefnGpgP48DCQaj1jizvuRZHhoElUvUT5flRt/O9kLjlbToqhw==",
 | 
			
		||||
      "version": "2.3.0-dev1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mempool/mempool.js/-/mempool.js-2.3.0-dev1.tgz",
 | 
			
		||||
      "integrity": "sha512-+UYGuG8qqdgrtC4J94hCs7+Dry8OprIixEarIC6rww1Nb5POz8n3NTDH8to1r0XLjPr+Du6/OX8fEN1QW94rNA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "axios": "^0.21.1",
 | 
			
		||||
        "ws": "^7.4.3"
 | 
			
		||||
        "axios": "0.24.0",
 | 
			
		||||
        "ws": "8.3.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@mempool/mempool.js/node_modules/axios": {
 | 
			
		||||
      "version": "0.24.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "follow-redirects": "^1.14.4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@mempool/mempool.js/node_modules/ws": {
 | 
			
		||||
      "version": "8.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==",
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=10.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "bufferutil": "^4.0.1",
 | 
			
		||||
        "utf-8-validate": "^5.0.2"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependenciesMeta": {
 | 
			
		||||
        "bufferutil": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "utf-8-validate": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@ng-bootstrap/ng-bootstrap": {
 | 
			
		||||
@ -4541,6 +4569,7 @@
 | 
			
		||||
      "version": "0.21.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
 | 
			
		||||
      "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "follow-redirects": "^1.14.0"
 | 
			
		||||
      }
 | 
			
		||||
@ -7264,7 +7293,7 @@
 | 
			
		||||
      "version": "4.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=0.3.1"
 | 
			
		||||
      }
 | 
			
		||||
@ -9122,7 +9151,7 @@
 | 
			
		||||
      "version": "2.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
 | 
			
		||||
      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=4"
 | 
			
		||||
      }
 | 
			
		||||
@ -9131,7 +9160,7 @@
 | 
			
		||||
      "version": "5.1.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
 | 
			
		||||
      "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "ajv": "^6.12.3",
 | 
			
		||||
        "har-schema": "^2.0.0"
 | 
			
		||||
@ -9416,7 +9445,7 @@
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "assert-plus": "^1.0.0",
 | 
			
		||||
        "jsprim": "^1.2.2",
 | 
			
		||||
@ -10385,7 +10414,7 @@
 | 
			
		||||
      "version": "0.4.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
 | 
			
		||||
      "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
 | 
			
		||||
      "devOptional": true
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/json-schema-traverse": {
 | 
			
		||||
      "version": "0.4.1",
 | 
			
		||||
@ -10453,7 +10482,7 @@
 | 
			
		||||
      "version": "1.4.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
 | 
			
		||||
      "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "assert-plus": "1.0.0",
 | 
			
		||||
        "extsprintf": "1.3.0",
 | 
			
		||||
@ -17962,6 +17991,7 @@
 | 
			
		||||
      "version": "7.4.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
 | 
			
		||||
      "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=8.3.0"
 | 
			
		||||
      }
 | 
			
		||||
@ -20409,12 +20439,28 @@
 | 
			
		||||
      "integrity": "sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw=="
 | 
			
		||||
    },
 | 
			
		||||
    "@mempool/mempool.js": {
 | 
			
		||||
      "version": "2.2.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mempool/mempool.js/-/mempool.js-2.2.4.tgz",
 | 
			
		||||
      "integrity": "sha512-G9Ga2jHLfAuU/qXikRBtTecYr7BhLJH1WbIahefnGpgP48DCQaj1jizvuRZHhoElUvUT5flRt/O9kLjlbToqhw==",
 | 
			
		||||
      "version": "2.3.0-dev1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mempool/mempool.js/-/mempool.js-2.3.0-dev1.tgz",
 | 
			
		||||
      "integrity": "sha512-+UYGuG8qqdgrtC4J94hCs7+Dry8OprIixEarIC6rww1Nb5POz8n3NTDH8to1r0XLjPr+Du6/OX8fEN1QW94rNA==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "axios": "^0.21.1",
 | 
			
		||||
        "ws": "^7.4.3"
 | 
			
		||||
        "axios": "0.24.0",
 | 
			
		||||
        "ws": "8.3.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "axios": {
 | 
			
		||||
          "version": "0.24.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
 | 
			
		||||
          "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "follow-redirects": "^1.14.4"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "ws": {
 | 
			
		||||
          "version": "8.3.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz",
 | 
			
		||||
          "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==",
 | 
			
		||||
          "requires": {}
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@ng-bootstrap/ng-bootstrap": {
 | 
			
		||||
@ -21532,6 +21578,7 @@
 | 
			
		||||
      "version": "0.21.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
 | 
			
		||||
      "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "follow-redirects": "^1.14.0"
 | 
			
		||||
      }
 | 
			
		||||
@ -23795,7 +23842,7 @@
 | 
			
		||||
      "version": "4.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
 | 
			
		||||
      "devOptional": true
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "diffie-hellman": {
 | 
			
		||||
      "version": "5.0.3",
 | 
			
		||||
@ -25290,13 +25337,13 @@
 | 
			
		||||
      "version": "2.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
 | 
			
		||||
      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
 | 
			
		||||
      "devOptional": true
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "har-validator": {
 | 
			
		||||
      "version": "5.1.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
 | 
			
		||||
      "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "ajv": "^6.12.3",
 | 
			
		||||
        "har-schema": "^2.0.0"
 | 
			
		||||
@ -25544,7 +25591,7 @@
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "assert-plus": "^1.0.0",
 | 
			
		||||
        "jsprim": "^1.2.2",
 | 
			
		||||
@ -26286,7 +26333,7 @@
 | 
			
		||||
      "version": "0.4.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
 | 
			
		||||
      "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
 | 
			
		||||
      "devOptional": true
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "json-schema-traverse": {
 | 
			
		||||
      "version": "0.4.1",
 | 
			
		||||
@ -26339,7 +26386,7 @@
 | 
			
		||||
      "version": "1.4.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
 | 
			
		||||
      "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "assert-plus": "1.0.0",
 | 
			
		||||
        "extsprintf": "1.3.0",
 | 
			
		||||
@ -32158,7 +32205,8 @@
 | 
			
		||||
    "ws": {
 | 
			
		||||
      "version": "7.4.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
 | 
			
		||||
      "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="
 | 
			
		||||
      "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
 | 
			
		||||
      "devOptional": true
 | 
			
		||||
    },
 | 
			
		||||
    "xhr2": {
 | 
			
		||||
      "version": "0.2.0",
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,10 @@
 | 
			
		||||
    "sync-assets": "node sync-assets.js && rsync -av ./dist/mempool/browser/en-US/resources ./dist/mempool/browser/resources",
 | 
			
		||||
    "sync-assets-dev": "node sync-assets.js dev",
 | 
			
		||||
    "generate-config": "node generate-config.js",
 | 
			
		||||
    "build-mempool.js": "tsc | browserify -p tinyify ./node_modules/@mempool/mempool.js/lib/index.js --standalone mempoolJS > ./dist/mempool/browser/en-US/mempool.js",
 | 
			
		||||
    "build-mempool.js": "npm run build-mempool-js && npm run build-mempool-liquid-js && npm run build-mempool-bisq-js",
 | 
			
		||||
    "build-mempool-js": "browserify -p tinyify ./node_modules/@mempool/mempool.js/lib/index.js --standalone mempoolJS > ./dist/mempool/browser/en-US/mempool.js",
 | 
			
		||||
    "build-mempool-bisq-js": "browserify -p tinyify ./node_modules/@mempool/mempool.js/lib/index-bisq.js --standalone bisqJS > ./dist/mempool/browser/en-US/bisq.js",
 | 
			
		||||
    "build-mempool-liquid-js": "browserify -p tinyify ./node_modules/@mempool/mempool.js/lib/index-liquid.js --standalone liquidJS > ./dist/mempool/browser/en-US/liquid.js",
 | 
			
		||||
    "test": "ng test",
 | 
			
		||||
    "lint": "ng lint",
 | 
			
		||||
    "e2e": "npm run generate-config && ng e2e",
 | 
			
		||||
@ -70,7 +73,7 @@
 | 
			
		||||
    "@fortawesome/fontawesome-svg-core": "^1.2.35",
 | 
			
		||||
    "@fortawesome/free-solid-svg-icons": "^5.15.3",
 | 
			
		||||
    "@juggle/resize-observer": "^3.3.1",
 | 
			
		||||
    "@mempool/mempool.js": "^2.2.4",
 | 
			
		||||
    "@mempool/mempool.js": "2.3.0-dev1",
 | 
			
		||||
    "@ng-bootstrap/ng-bootstrap": "^10.0.0",
 | 
			
		||||
    "@nguniversal/express-engine": "11.2.1",
 | 
			
		||||
    "@types/qrcode": "1.4.1",
 | 
			
		||||
 | 
			
		||||
@ -30,8 +30,10 @@
 | 
			
		||||
<ng-template [ngIf]="network.val === 'liquid'">
 | 
			
		||||
  <p>Assets</p>
 | 
			
		||||
  <a [routerLink]="['./']" fragment="get-assets" (click)="collapseItem.toggle()">GET Assets</a>
 | 
			
		||||
  <a [routerLink]="['./']" fragment="get-assets-icons" (click)="collapseItem.toggle()">GET Assets Icons</a>
 | 
			
		||||
  <a [routerLink]="['./']" fragment="get-asset-transactions" (click)="collapseItem.toggle()">GET Asset Transactions</a>
 | 
			
		||||
  <a [routerLink]="['./']" fragment="get-asset-supply" (click)="collapseItem.toggle()">GET Asset Supply</a>
 | 
			
		||||
  <a [routerLink]="['./']" fragment="get-asset-icon" (click)="collapseItem.toggle()">GET Asset Icon</a>
 | 
			
		||||
</ng-template>
 | 
			
		||||
 | 
			
		||||
<p>Blocks</p>
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ import { Component, OnInit, Input } from '@angular/core';
 | 
			
		||||
export class ApiDocsNavComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  @Input() network: any;
 | 
			
		||||
  @Input() collapseItem: any;
 | 
			
		||||
  @Input() collapseItem: any = { toggle: () => {} };
 | 
			
		||||
 | 
			
		||||
  constructor() { }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -275,6 +275,32 @@
 | 
			
		||||
            <app-code-template [hostname]="hostname" [code]="code.assetSupply" [network]="network.val" ></app-code-template>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <div class="endpoint-container" id="get-assets-icons">
 | 
			
		||||
            <a class="section-header" [routerLink]="['./']" fragment="get-assets-icons">GET Asset Icons <span>Assets</span></a>
 | 
			
		||||
            <div class="endpoint">
 | 
			
		||||
              <div class="subtitle" i18n="Api docs endpoint">Endpoint</div>
 | 
			
		||||
              <a [href]="wrapUrl(network.val, code.assetIcons)" target="_blank">GET /liquid/api/v1/assets/icons</a>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="description">
 | 
			
		||||
              <div class="subtitle" i18n>Description</div>
 | 
			
		||||
              <div>Get all the Asset IDs that has icons.</div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <app-code-template [hostname]="hostname" [code]="code.assetIcons" [network]="network.val" ></app-code-template>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <div class="endpoint-container" id="get-asset-icon">
 | 
			
		||||
            <a class="section-header" [routerLink]="['./']" fragment="get-asset-icon">GET Asset Icon <span>Assets</span></a>
 | 
			
		||||
            <div class="endpoint">
 | 
			
		||||
              <div class="subtitle" i18n="Api docs endpoint">Endpoint</div>
 | 
			
		||||
              <a [href]="wrapUrl(network.val, code.assetIcon)" target="_blank">GET /liquid/api/v1/asset/:asset_id/icon</a>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="description">
 | 
			
		||||
              <div class="subtitle" i18n>Description</div>
 | 
			
		||||
              <div>Get the icon of the specified asset.</div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <app-code-template [hostname]="hostname" [code]="code.assetIcon" [network]="network.val" ></app-code-template>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="api-category">
 | 
			
		||||
 | 
			
		||||
@ -642,24 +642,6 @@ export class ApiDocsComponent implements OnInit {
 | 
			
		||||
  console.log(asset);
 | 
			
		||||
          `,
 | 
			
		||||
        },
 | 
			
		||||
        codeSampleMainnet: {
 | 
			
		||||
          esModule: [],
 | 
			
		||||
          commonJS: [],
 | 
			
		||||
          curl: [],
 | 
			
		||||
          response: ''
 | 
			
		||||
        },
 | 
			
		||||
        codeSampleTestnet: {
 | 
			
		||||
          esModule: [],
 | 
			
		||||
          commonJS: [],
 | 
			
		||||
          curl: [],
 | 
			
		||||
          response: ''
 | 
			
		||||
        },
 | 
			
		||||
        codeSampleSignet: {
 | 
			
		||||
          esModule: [],
 | 
			
		||||
          commonJS: [],
 | 
			
		||||
          curl: [],
 | 
			
		||||
          response: ''
 | 
			
		||||
        },
 | 
			
		||||
        codeSampleLiquid: {
 | 
			
		||||
          esModule: [`6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d`],
 | 
			
		||||
          commonJS: [`6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d`],
 | 
			
		||||
@ -693,6 +675,47 @@ export class ApiDocsComponent implements OnInit {
 | 
			
		||||
          response: ''
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      assetIcons: {
 | 
			
		||||
        codeTemplate: {
 | 
			
		||||
          curl: `/api/v1/assets/icons`,
 | 
			
		||||
          commonJS: `
 | 
			
		||||
        const { %{0}: { assets } } = mempoolJS();
 | 
			
		||||
 | 
			
		||||
        const assetsIcons = await assets.getAssetsIcons();
 | 
			
		||||
 | 
			
		||||
        document.getElementById("result").textContent = JSON.stringify(assetsIcons, undefined, 2);
 | 
			
		||||
        `,
 | 
			
		||||
          esModule: `
 | 
			
		||||
  const { %{0}: { assets } } = mempoolJS();
 | 
			
		||||
 | 
			
		||||
  const assetsIcons = await assets.getAssetsIcons();
 | 
			
		||||
  console.log(assetsIcons);
 | 
			
		||||
          `,
 | 
			
		||||
        },
 | 
			
		||||
        codeSampleLiquid: {
 | 
			
		||||
          esModule: [`6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d`],
 | 
			
		||||
          commonJS: [`6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d`],
 | 
			
		||||
          curl: [`6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d`],
 | 
			
		||||
          response: `[
 | 
			
		||||
  "6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d",
 | 
			
		||||
  "ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2"
 | 
			
		||||
  ...
 | 
			
		||||
]`,
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      assetIcon: {
 | 
			
		||||
        noWrap: true,
 | 
			
		||||
        codeTemplate: {
 | 
			
		||||
          curl: `/api/v1/asset/%{1}/icon`,
 | 
			
		||||
          commonJS: `<img src="https://liquid.place/api/v1/asset/%{1}/icon">`,
 | 
			
		||||
        },
 | 
			
		||||
        codeSampleLiquid: {
 | 
			
		||||
          esModule: [`6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d`],
 | 
			
		||||
          commonJS: [`6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d`],
 | 
			
		||||
          curl: [`6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d`],
 | 
			
		||||
          response: `PNG`,
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      assetTransactions: {
 | 
			
		||||
        codeTemplate: {
 | 
			
		||||
          curl: `/api/asset/%{1}/txs`,
 | 
			
		||||
 | 
			
		||||
@ -164,6 +164,10 @@ init();`;
 | 
			
		||||
        codeText = this.replaceJSPlaceholder(codeText, code.codeSampleBisq.esModule);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (code.noWrap) {
 | 
			
		||||
        return codeText;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      let importText = `<script src="https://mempool.space/mempool.js"></script>`;
 | 
			
		||||
      if (this.env.BASE_MODULE === 'bisq') {
 | 
			
		||||
        importText = `<script src="https://bisq.markets/bisq.js"></script>`;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user