diff --git a/.gitignore b/.gitignore index 8e4034621e..847acba67f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /dist /db /.idea +/*.iml package-lock.json /certs /coverage @@ -13,4 +14,4 @@ package-lock.json # VSCode .vscode/ -.history \ No newline at end of file +.history diff --git a/docs/swagger/definitions.yml b/docs/swagger/definitions.yml index f1c1207dcd..ef441fec12 100644 --- a/docs/swagger/definitions.yml +++ b/docs/swagger/definitions.yml @@ -2103,4 +2103,4 @@ definitions: example: 0.5 txHash: type: 'string' - example: '0x...' + example: '0x...' \ No newline at end of file diff --git a/docs/swagger/wallet-routes.yml b/docs/swagger/wallet-routes.yml index cfde507bca..4653f11c4a 100644 --- a/docs/swagger/wallet-routes.yml +++ b/docs/swagger/wallet-routes.yml @@ -7,6 +7,12 @@ paths: operationId: 'get' produces: - 'application/json' + parameters: + - in: 'body' + name: 'body' + required: true + schema: + $ref: '#/definitions/GetWalletRequest' responses: '200': description: 'Wallet list' @@ -27,7 +33,11 @@ paths: required: true schema: $ref: '#/definitions/AddWalletRequest' - responses: '200' + responses: + '200': + description: 'Added wallet address' + schema: + $ref: '#/definitions/AddWalletResponse' /wallet/remove: delete: diff --git a/package.json b/package.json index 31254d69eb..f15e5fedab 100644 --- a/package.json +++ b/package.json @@ -94,6 +94,7 @@ "winston": "^3.3.3", "winston-daily-rotate-file": "^4.5.5", "xsswap-sdk": "^1.0.1", + "xrpl": "^2.7.0", "yarn": "^1.22.17" }, "devDependencies": { diff --git a/src/app.ts b/src/app.ts index fa22404809..4cd9e21883 100644 --- a/src/app.ts +++ b/src/app.ts @@ -119,7 +119,7 @@ export const startGateway = async () => { Math.random().toString(16).substr(2, 14) ); } - logger.info(`Gateway Version: ${gateway_version}`) // display gateway version + logger.info(`Gateway Version: ${gateway_version}`); // display gateway version logger.info(`⚡️ Starting Gateway API on port ${port}...`); if (ConfigManagerV2.getInstance().get('server.unsafeDevModeWithHTTP')) { logger.info('Running in UNSAFE HTTP! This could expose private keys.'); diff --git a/src/chains/xrpl/xrpl-middlewares.ts b/src/chains/xrpl/xrpl-middlewares.ts new file mode 100644 index 0000000000..a735999571 --- /dev/null +++ b/src/chains/xrpl/xrpl-middlewares.ts @@ -0,0 +1,24 @@ +import { HttpException } from '../../services/error-handler'; +import { XRPL } from './xrpl'; +import { NextFunction, Request, Response } from 'express'; + +export const verifyXRPLIsAvailable = async ( + req: Request, + _res: Response, + next: NextFunction +) => { + if (!req || !req.body || !req.body.network) { + throw new HttpException(404, 'No XRPL network informed.'); + } + + const xrpl = await XRPL.getInstance(req.body.network); + if (!xrpl.ready) { + await xrpl.init(); + } + + if (!xrpl.isConnected()) { + await xrpl.client.connect(); + } + + return next(); +}; diff --git a/src/chains/xrpl/xrpl.config.ts b/src/chains/xrpl/xrpl.config.ts new file mode 100644 index 0000000000..f08d3b18f1 --- /dev/null +++ b/src/chains/xrpl/xrpl.config.ts @@ -0,0 +1,62 @@ +import { ConfigManagerV2 } from '../../services/config-manager-v2'; + +export interface NetworkConfig { + name: string; + nodeUrl: string; // example: wss://xrplcluster.com/ + tokenListType: string; // default: FILE + tokenListSource: string; // default: src/chains/xrpl/xrpl_tokens.json + marketListType: string; // default: FILE + marketListSource: string; // default: src/chains/xrpl/xrpl_markets.json + nativeCurrencySymbol: string; // XRP + maxLRUCacheInstances: number; +} + +export interface Config { + // "mainnet" | "testnet" | "devnet" + network: NetworkConfig; + requestTimeout: number; // default: 20 + connectionTimeout: number; // default: 5 + feeCushion: number; // default: 1.2 + maxFeeXRP: string; // default: 2 + orderDbPath: string; +} + +// @todo: find out which configs are required +export function getXRPLConfig(chainName: string, networkName: string): Config { + const configManager = ConfigManagerV2.getInstance(); + return { + network: { + name: networkName, + nodeUrl: configManager.get( + chainName + '.networks.' + networkName + '.nodeURL' + ), + tokenListType: ConfigManagerV2.getInstance().get( + chainName + '.networks.' + networkName + '.tokenListType' + ), + tokenListSource: ConfigManagerV2.getInstance().get( + chainName + '.networks.' + networkName + '.tokenListSource' + ), + marketListType: ConfigManagerV2.getInstance().get( + chainName + '.networks.' + networkName + '.marketListType' + ), + marketListSource: ConfigManagerV2.getInstance().get( + chainName + '.networks.' + networkName + '.marketListSource' + ), + nativeCurrencySymbol: ConfigManagerV2.getInstance().get( + chainName + '.networks.' + networkName + '.nativeCurrencySymbol' + ), + maxLRUCacheInstances: ConfigManagerV2.getInstance().get( + chainName + '.maxLRUCacheInstances' + ), + }, + requestTimeout: ConfigManagerV2.getInstance().get( + chainName + '.requestTimeout' + ), + connectionTimeout: ConfigManagerV2.getInstance().get( + chainName + '.connectionTimeout' + ), + feeCushion: ConfigManagerV2.getInstance().get(chainName + '.feeCushion'), + maxFeeXRP: ConfigManagerV2.getInstance().get(chainName + '.maxFeeXRP'), + orderDbPath: ConfigManagerV2.getInstance().get(chainName + '.orderDbPath'), + }; +} diff --git a/src/chains/xrpl/xrpl.constants.ts b/src/chains/xrpl/xrpl.constants.ts new file mode 100644 index 0000000000..197920242b --- /dev/null +++ b/src/chains/xrpl/xrpl.constants.ts @@ -0,0 +1,26 @@ +import { ConfigManagerV2 } from '../../services/config-manager-v2'; + +const configManager = ConfigManagerV2.getInstance(); + +export const constants = { + retry: { + all: { + maxNumberOfRetries: + configManager.get('xrpl.retry.all.maxNumberOfRetries') || 0, // 0 means no retries + delayBetweenRetries: + configManager.get('xrpl.retry.all.delayBetweenRetries') || 0, // 0 means no delay (milliseconds) + }, + }, + timeout: { + all: configManager.get('xrpl.timeout.all') || 0, // 0 means no timeout (milliseconds) + }, + parallel: { + all: { + batchSize: configManager.get('xrpl.parallel.all.batchSize') || 0, // 0 means no batching (group all) + delayBetweenBatches: + configManager.get('xrpl.parallel.all.delayBetweenBatches') || 0, // 0 means no delay (milliseconds) + }, + }, +}; + +export default constants; diff --git a/src/chains/xrpl/xrpl.controllers.ts b/src/chains/xrpl/xrpl.controllers.ts new file mode 100644 index 0000000000..f632484fbf --- /dev/null +++ b/src/chains/xrpl/xrpl.controllers.ts @@ -0,0 +1,125 @@ +import { Wallet } from 'xrpl'; +import { XRPTokenInfo, XRPLish } from './xrpl'; +import { TokenInfo, latency } from '../../services/base'; +import { + HttpException, + LOAD_WALLET_ERROR_CODE, + LOAD_WALLET_ERROR_MESSAGE, +} from '../../services/error-handler'; +import { getNetworkId } from '../../chains/xrpl/xrpl.helpers'; + +import { + XRPLBalanceRequest, + XRPLBalanceResponse, + XRPLPollRequest, + XRPLPollResponse, +} from './xrpl.requests'; + +import { + validateXRPLBalanceRequest, + validateXRPLPollRequest, + validateXRPLGetTokenRequest, +} from './xrpl.validators'; +import { TokensRequest } from '../../network/network.requests'; + +export class XRPLController { + static async currentBlockNumber(xrplish: XRPLish): Promise { + return xrplish.getCurrentLedgerIndex(); + } + + static async balances( + xrplish: XRPLish, + req: XRPLBalanceRequest + ): Promise { + const initTime = Date.now(); + let wallet: Wallet; + + validateXRPLBalanceRequest(req); + + try { + wallet = await xrplish.getWallet(req.address); + } catch (err) { + throw new HttpException( + 500, + LOAD_WALLET_ERROR_MESSAGE + err, + LOAD_WALLET_ERROR_CODE + ); + } + + const xrplBalances = await xrplish.getAllBalance(wallet); + + const balances: Record = {}; + xrplBalances.forEach((balance) => { + balances[balance.currency] = balance.value; + }); + + return { + network: xrplish.network, + timestamp: initTime, + latency: latency(initTime, Date.now()), + address: req.address, + balances, + }; + } + + static async poll( + xrplish: XRPLish, + req: XRPLPollRequest + ): Promise { + validateXRPLPollRequest(req); + + const initTime = Date.now(); + const currentLedgerIndex = await xrplish.getCurrentLedgerIndex(); + const txData = await xrplish.getTransaction(req.txHash); + const txStatus = await xrplish.getTransactionStatusCode(txData); + const sequence = txData ? txData.result.Sequence : undefined; + const txLedgerIndex = txData ? txData.result.ledger_index : undefined; + + return { + network: xrplish.network, + timestamp: initTime, + currentLedgerIndex: currentLedgerIndex, + sequence: sequence, + txHash: req.txHash, + txStatus: txStatus, + txLedgerIndex: txLedgerIndex, + txData: txData, + }; + } + + static async getTokens( + xrplish: XRPLish, + req: TokensRequest + ): Promise<{ tokens: TokenInfo[] }> { + validateXRPLGetTokenRequest(req); + let xrpTokens: XRPTokenInfo[] = []; + if (!req.tokenSymbols) { + xrpTokens = xrplish.storedTokenList; + } else { + for (const t of req.tokenSymbols as []) { + const arr = xrplish.getTokenForSymbol(t); + if (arr !== undefined) { + arr.forEach((token) => { + xrpTokens.push(token); + }); + } + } + } + + const tokens: TokenInfo[] = []; + + // Convert xrpTokens into tokens + xrpTokens.map((xrpToken) => { + const token: TokenInfo = { + address: xrpToken.issuer, + chainId: getNetworkId(req.network), + decimals: 15, + name: xrpToken.title, + symbol: xrpToken.code, + }; + tokens.push(token); + }); + + return { tokens }; + } +} diff --git a/src/chains/xrpl/xrpl.helpers.ts b/src/chains/xrpl/xrpl.helpers.ts new file mode 100644 index 0000000000..0f27134b18 --- /dev/null +++ b/src/chains/xrpl/xrpl.helpers.ts @@ -0,0 +1,147 @@ +// import web3 from 'web3'; +import { default as constants } from './../../chains/xrpl/xrpl.constants'; +import { XRPLNetworkID } from './xrpl.requests'; + +/** + * + * @param value + * @param errorMessage + */ +export const getNotNullOrThrowError = ( + value?: any, + errorMessage: string = 'Value is null or undefined' +): R => { + if (value === undefined || value === null) throw new Error(errorMessage); + + return value as R; +}; + +/** + * + * @param milliseconds + */ +export const sleep = (milliseconds: number) => + new Promise((callback) => setTimeout(callback, milliseconds)); + +/** + * Same as Promise.all(items.map(item => task(item))), but it waits for + * the first {batchSize} promises to finish before starting the next batch. + * + * @template A + * @template B + * @param {function(A): B} task The task to run for each item. + * @param {A[]} items Arguments to pass to the task for each call. + * @param {int} batchSize The number of items to process at a time. + * @param {int} delayBetweenBatches Delay between each batch (milliseconds). + * @returns {B[]} + */ +export const promiseAllInBatches = async ( + task: (item: I) => O, + items: any[], + batchSize: number = constants.parallel.all.batchSize, + delayBetweenBatches: number = constants.parallel.all.delayBetweenBatches +): Promise => { + let position = 0; + let results: any[] = []; + + if (!batchSize) { + batchSize = items.length; + } + + while (position < items.length) { + const itemsForBatch = items.slice(position, position + batchSize); + results = [ + ...results, + ...(await Promise.all(itemsForBatch.map((item) => task(item)))), + ]; + position += batchSize; + + if (position < items.length) { + if (delayBetweenBatches > 0) { + await sleep(delayBetweenBatches); + } + } + } + + return results; +}; + +/** + * + */ +// export const getRandonBN = () => { +// return web3.utils.toBN(web3.utils.randomHex(32)); +// }; + +/** + * @param targetObject + * @param targetFunction + * @param targetParameters + * @param maxNumberOfRetries 0 means no retries + * @param delayBetweenRetries 0 means no delay (milliseconds) + * @param timeout 0 means no timeout (milliseconds) + * @param timeoutMessage + */ +// export const runWithRetryAndTimeout = async ( +// targetObject: any, +// targetFunction: (...args: any[]) => R, +// targetParameters: any, +// maxNumberOfRetries: number = constants.retry.all.maxNumberOfRetries, +// delayBetweenRetries: number = constants.retry.all.delayBetweenRetries, +// timeout: number = constants.timeout.all, +// timeoutMessage: string = 'Timeout exceeded.' +// ): Promise => { +// let retryCount = 0; +// let timer: any; + +// if (timeout > 0) { +// timer = setTimeout(() => new Error(timeoutMessage), timeout); +// } + +// do { +// try { +// const result = await targetFunction.apply(targetObject, targetParameters); + +// if (timeout > 0) { +// clearTimeout(timer); +// } + +// return result as R; +// } catch (error) { +// retryCount++; +// if (retryCount < maxNumberOfRetries) { +// if (delayBetweenRetries > 0) { +// await sleep(delayBetweenRetries); +// } +// } else { +// throw error; +// } +// } +// } while (retryCount < maxNumberOfRetries); + +// throw Error('Unknown error.'); +// }; + +export function getNetworkId(network: string = ''): number { + switch (network) { + case 'mainnet': + return XRPLNetworkID.MAINNET; + + case 'testnet': + return XRPLNetworkID.TESTNET; + + case 'devnet': + return XRPLNetworkID.DEVNET; + + default: + return 0; + } +} + +export function getBaseTokenFromMarketId(marketId: string): string { + return marketId.split('-')[0]; +} + +export function getQuoteTokenFromMarketId(marketId: string): string { + return marketId.split('-')[1]; +} diff --git a/src/chains/xrpl/xrpl.order-storage.ts b/src/chains/xrpl/xrpl.order-storage.ts new file mode 100644 index 0000000000..24f1765da2 --- /dev/null +++ b/src/chains/xrpl/xrpl.order-storage.ts @@ -0,0 +1,197 @@ +import { LocalStorage } from '../../services/local-storage'; +import { ReferenceCountingCloseable } from '../../services/refcounting-closeable'; +import { Order } from '../../connectors/xrpl/xrpl.types'; +import { OrderStatus } from '../../connectors/xrpl/xrpl.types'; + +// store the order for when a transaction was initiated +// this will be used to monitor the order status when +// the order is included in the orderbook on XRP Ledger +export class XRPLOrderStorage extends ReferenceCountingCloseable { + readonly localStorage: LocalStorage; + + protected constructor(dbPath: string) { + super(dbPath); + this.localStorage = LocalStorage.getInstance(dbPath, this.handle); + } + + public async init(): Promise { + try { + await this.localStorage.init(); + } catch (error) { + throw new Error('Failed to initialize local storage: ' + error); + } + } + + public storageStatus(): string { + return this.localStorage.dbStatus; + } + + public async saveOrder( + chain: string, + network: string, + walletAddress: string, + order: Order + ): Promise { + return this.localStorage.save( + chain + '/' + network + '/' + walletAddress + '/' + order.hash, + JSON.stringify(order) + ); + } + + public async deleteOrder( + chain: string, + network: string, + walletAddress: string, + order: Order + ): Promise { + return this.localStorage.del( + chain + '/' + network + '/' + walletAddress + '/' + order.hash + ); + } + + public async getOrders( + chain: string, + network: string, + walletAddress: string + ): Promise> { + return this.localStorage.get((key: string, value: string) => { + const splitKey = key.split('/'); + if ( + splitKey.length === 4 && + splitKey[0] === chain && + splitKey[1] === network && + splitKey[2] === walletAddress + ) { + return [splitKey[3], JSON.parse(value)]; + } + return; + }); + } + + public async getOrdersByState( + chain: string, + network: string, + walletAddress: string, + state: OrderStatus + ): Promise> { + return this.localStorage.get((key: string, value: string) => { + const splitKey = key.split('/'); + if ( + splitKey.length === 4 && + splitKey[0] === chain && + splitKey[1] === network && + splitKey[2] === walletAddress + ) { + const order: Order = JSON.parse(value); + if (order.state === state) { + return [splitKey[3], order]; + } + } + return; + }); + } + + public async getOrdersByMarket( + chain: string, + network: string, + walletAddress: string, + marketId: string + ): Promise> { + return this.localStorage.get((key: string, value: string) => { + const splitKey = key.split('/'); + if ( + splitKey.length === 4 && + splitKey[0] === chain && + splitKey[1] === network && + splitKey[2] === walletAddress + ) { + const order: Order = JSON.parse(value); + if (order.marketId === marketId) { + return [splitKey[3], order]; + } + } + return; + }); + } + + // TODO: Investigate why this method is giving empty results, considering removeing it + // public async getOrderByMarketAndHash( + // chain: string, + // network: string, + // walletAddress: string, + // marketId: string, + // hash: string + // ): Promise> { + // return this.localStorage.get((key: string, value: string) => { + // const splitKey = key.split('/'); + // if ( + // splitKey.length === 4 && + // splitKey[0] === chain && + // splitKey[1] === network && + // splitKey[2] === walletAddress + // ) { + // const order: Order = JSON.parse(value); + // if (order.marketId === marketId && order.hash === parseInt(hash)) { + // return [splitKey[3], order]; + // } + // } + // return; + // }); + // } + + public async getOrdersByHash( + chain: string, + network: string, + walletAddress: string, + hash: string + ): Promise> { + return this.localStorage.get((key: string, value: string) => { + const splitKey = key.split('/'); + if ( + splitKey.length === 4 && + splitKey[0] === chain && + splitKey[1] === network && + splitKey[2] === walletAddress && + splitKey[3] === hash + ) { + const order: Order = JSON.parse(value); + return [splitKey[3], order]; + } + return; + }); + } + + public async getInflightOrders( + chain: string, + network: string, + walletAddress: string + ): Promise> { + return this.localStorage.get((key: string, value: string) => { + const splitKey = key.split('/'); + if ( + splitKey.length === 4 && + splitKey[0] === chain && + splitKey[1] === network && + splitKey[2] === walletAddress + ) { + const order: Order = JSON.parse(value); + if ( + order.state === OrderStatus.OPEN || + order.state === OrderStatus.PENDING_OPEN || + order.state === OrderStatus.PENDING_CANCEL || + order.state === OrderStatus.PARTIALLY_FILLED + ) { + return [splitKey[3], order]; + } + } + return; + }); + } + + public async close(handle: string): Promise { + await super.close(handle); + if (this.refCount < 1) { + await this.localStorage.close(this.handle); + } + } +} diff --git a/src/chains/xrpl/xrpl.order-tracker.ts b/src/chains/xrpl/xrpl.order-tracker.ts new file mode 100644 index 0000000000..61a2c2f3c8 --- /dev/null +++ b/src/chains/xrpl/xrpl.order-tracker.ts @@ -0,0 +1,1073 @@ +import { + Client, + Wallet, + TxResponse, + AccountTxResponse, + rippleTimeToUnixTime, + TransactionStream, + TransactionMetadata, + Transaction, + dropsToXrp, +} from 'xrpl'; +import { XRPL } from './xrpl'; +import { XRPLCLOB } from '../../../src/connectors/xrpl/xrpl'; +import { getXRPLConfig } from './xrpl.config'; +import { + OrderStatus, + Order, + InflightOrders, + TransaformedAccountTransaction, + TransactionIntentType, + TransactionIntent, + AccountTransaction, + ResponseOnlyTxInfo, + CreatedNode, + ModifiedNode, + DeletedNode, + FillData, + Market, +} from '../../connectors/xrpl/xrpl.types'; +import { OrderMutexManager } from '../../connectors/xrpl/xrpl.utils'; +import { + getBaseTokenFromMarketId, + getQuoteTokenFromMarketId, +} from './xrpl.helpers'; +import { + isModifiedNode, + isDeletedNode, + isCreatedNode, +} from 'xrpl/dist/npm/models/transactions/metadata'; + +import LRUCache from 'lru-cache'; +import { XRPLOrderStorage } from './xrpl.order-storage'; + +// This class should: +// 1. Track orders that are created by xrpl.postOrder +// 2. Track orders that are deleted by xrpl.deleteOrder +// 3. Pool the XRP Ledger to update the inflight orders status +// 4. Provide interface to get order by states + +export class OrderTracker { + private static _instances: LRUCache; + private readonly _xrpl: XRPL; + private readonly _xrplClob: XRPLCLOB; + private readonly _orderStorage: XRPLOrderStorage; + private _wallet: Wallet; + private _orderMutexManager: OrderMutexManager; + private _inflightOrders: InflightOrders; + private _isTracking: boolean; + private _isProcessing: boolean; + private _orderTrackingInterval: number; + + public chain: string; + public network: string; + + private constructor(chain: string, network: string, wallet: Wallet) { + this.chain = chain; + this.network = network; + + this._xrpl = XRPL.getInstance(network); + this._xrplClob = XRPLCLOB.getInstance(chain, network); + this._orderStorage = this._xrpl.orderStorage; + this._wallet = wallet; + this._inflightOrders = {}; + this._orderMutexManager = new OrderMutexManager(this._inflightOrders); + this._isTracking = false; + this._isProcessing = false; + // set tracking interval to 1 seconds + this._orderTrackingInterval = 1000; + this.startTracking(); + } + + public static getInstance( + chain: string, + network: string, + wallet: Wallet + ): OrderTracker { + if (OrderTracker._instances === undefined) { + const config = getXRPLConfig(chain, network); + OrderTracker._instances = new LRUCache({ + max: config.network.maxLRUCacheInstances, + }); + } + const instanceKey = chain + network + wallet.classicAddress; + if (!OrderTracker._instances.has(instanceKey)) { + OrderTracker._instances.set( + instanceKey, + new OrderTracker(chain, network, wallet) + ); + } + + return OrderTracker._instances.get(instanceKey) as OrderTracker; + } + + public get wallet(): Wallet { + return this._wallet; + } + + public get isTracking(): boolean { + return this._isTracking; + } + + public async addOrder(order: Order): Promise { + this._inflightOrders[order.hash] = order; + + // Check if isProcessing is on, if so, wait until it's done + while (this._isProcessing) { + await new Promise((resolve) => setTimeout(resolve, 100)); + } + + // Mark isProcessing as true + this._isProcessing = true; + + // save inflightOrders to DB + await this.saveInflightOrdersToDB(); + + // Mark isProcessing as false + this._isProcessing = false; + } + + public getOrder(hash: number): Order | undefined { + return this._inflightOrders[hash]; + } + + async saveInflightOrdersToDB(): Promise { + await Promise.all( + Object.keys(this._inflightOrders).map(async (hash) => { + await this._orderStorage.saveOrder( + this.chain, + this.network, + this._wallet.classicAddress, + this._inflightOrders[parseInt(hash)] + ); + }) + ); + } + + public async loadInflightOrders(): Promise { + const orders = await this._orderStorage.getInflightOrders( + this.chain, + this.network, + this._wallet.classicAddress + ); + + Object.keys(orders).forEach((hash) => { + this._inflightOrders[parseInt(hash)] = orders[parseInt(hash)]; + }); + this._orderMutexManager.updateOrders(this._inflightOrders); + } + + public async startTracking(): Promise { + if (this._isTracking) { + return; + } + + this._isTracking = true; + + await this._xrpl.ensureConnection(); + await this.loadInflightOrders(); + + const client = this._xrpl.client; + + client.on('transaction', async (event) => { + // Check if isProcessing is on, if so, wait until it's done + while (this._isProcessing) { + await new Promise((resolve) => setTimeout(resolve, 100)); + } + + // Mark isProcessing as true + this._isProcessing = true; + + const updatedOrders = await this.processTransactionStream( + this._inflightOrders, + event, + this._orderMutexManager + ); + + // merge updateOrders with inflightOrders + Object.keys(updatedOrders).forEach((hash) => { + this._inflightOrders[parseInt(hash)] = updatedOrders[parseInt(hash)]; + }); + + this._orderMutexManager.updateOrders(this._inflightOrders); + + // Save inflightOrders to DB + await this.saveInflightOrdersToDB(); + + // Mark isProcessing as false + this._isProcessing = false; + }); + + await client.request({ + command: 'subscribe', + accounts: [this._wallet.classicAddress], + }); + + while (this._isTracking) { + // Make sure connection is good + await this._xrpl.ensureConnection(); + + // Check if isProcessing is on, if so, wait until it's done + while (this._isProcessing) { + await new Promise((resolve) => setTimeout(resolve, 100)); + } + + // Mark isProcessing as true + this._isProcessing = true; + + // Check inflightOrders + const updatedOrders = await this.checkOpenOrders( + this._inflightOrders, + this._wallet.classicAddress, + client, + this._orderMutexManager + ); + + // merge updateOrders with inflightOrders + Object.keys(updatedOrders).forEach((hash) => { + this._inflightOrders[parseInt(hash)] = updatedOrders[parseInt(hash)]; + }); + + // Update mutex manager + this._orderMutexManager.updateOrders(this._inflightOrders); + // Save inflightOrders to DB + await this.saveInflightOrdersToDB(); + + // Mark isProcessing as false + this._isProcessing = false; + + // Wait for next interval + await new Promise((resolve) => + setTimeout(resolve, this._orderTrackingInterval) + ); + } + } + + public async stopTracking(): Promise { + this._isTracking = false; + const client = this._xrpl.client; + client.removeAllListeners('transaction'); + + if (client.isConnected()) { + await client.request({ + command: 'unsubscribe', + accounts: [this._wallet.classicAddress], + }); + } + } + + public static async stopTrackingOnAllInstances(): Promise { + const instances = OrderTracker._instances; + if (instances === undefined) { + return; + } + + await Promise.all( + Array.from(instances.values()).map(async (instance) => { + await instance.stopTracking(); + }) + ); + } + + public static async stopTrackingOnAllInstancesForNetwork( + network: string + ): Promise { + const instances = OrderTracker._instances; + if (instances === undefined) { + return; + } + + await Promise.all( + Array.from(instances.values()).map(async (instance) => { + if (instance.network === network) { + await instance.stopTracking(); + } + }) + ); + } + + async checkOpenOrders( + openOrders: InflightOrders, + account: string, + client: Client, + omm: OrderMutexManager + ) { + // TODO + // 1. Get the minLedgerIndex from the inflightOrders + // 2. Get the transactions stack based on minLedgerIndex and account id + // 3. Process the transactions stack + // 4. Update the inflightOrders + const ordersToCheck: InflightOrders = openOrders; + + // 1. Get the minLedgerIndex from the inflightOrders + const hashes = Object.keys(ordersToCheck); + let minLedgerIndex = await this._xrpl.getCurrentLedgerIndex(); + for (const hash of hashes) { + if (ordersToCheck[parseInt(hash)].updatedAtLedgerIndex < minLedgerIndex) { + minLedgerIndex = ordersToCheck[parseInt(hash)].updatedAtLedgerIndex; + } + } + + // 2. Get the transactions stack based on minLedgerIndex and account id + const txStack = await this.getTransactionsStack( + client, + account, + minLedgerIndex + ); + + // 3. Process the transactions stack + if (txStack === null) { + return ordersToCheck; + } + + if (txStack.result?.transactions === undefined) { + return ordersToCheck; + } + + const transactionStack = txStack.result.transactions; + transactionStack.reverse(); + + for (const tx of transactionStack) { + const transformedTx = this.transformAccountTransaction(tx); + + if (transformedTx === null) { + continue; + } + + const updatedOrders = await this.processTransactionStream( + ordersToCheck, + transformedTx, + omm + ); + + // merge updateOrders to ordersToCheck + Object.keys(updatedOrders).forEach((hash) => { + ordersToCheck[parseInt(hash)] = updatedOrders[parseInt(hash)]; + }); + } + + return ordersToCheck; + } + + async processTransactionStream( + inflightOrders: InflightOrders, + transaction: TransactionStream | TransaformedAccountTransaction, + omm: OrderMutexManager + ): Promise { + // TODO: Extend this function to handle multiple intents + const transactionIntents = await this.getTransactionIntentsFromStream( + this.wallet.classicAddress, + transaction + ); + + const ordersToCheck = inflightOrders; + // console.log('Transaction intent: '); + // console.log(inspect(transactionIntent, { colors: true, depth: null })); + + if (transactionIntents.length === 0) { + // console.log('No intent found!'); + return ordersToCheck; + } + + for (const intent of transactionIntents) { + if (intent.sequence === undefined) { + continue; + } + + const matchOrder = ordersToCheck[intent.sequence]; + + if (matchOrder === undefined) { + // console.log('No match order found!'); + continue; + } + + // Wait until the order is not locked + while (omm.isLocked(matchOrder.hash)) { + // console.log('Order is locked! Wait for 300ms'); + await new Promise((resolve) => setTimeout(resolve, 300)); + } + + // Lock the order + omm.lock(matchOrder.hash); + + matchOrder.updatedAt = transaction.transaction.date + ? rippleTimeToUnixTime(transaction.transaction.date) + : 0; + matchOrder.updatedAtLedgerIndex = transaction.ledger_index ?? 0; + + // Find if transaction.transaction.hash already in associatedTxns, if not, then push it + const foundIndex = matchOrder.associatedTxns.findIndex((hash) => { + return hash === intent.tx.transaction.hash; + }); + + if (foundIndex === -1) { + matchOrder.associatedTxns.push(intent.tx.transaction.hash ?? 'UNKNOWN'); + } else { + // console.log('Transaction already found!'); + } + + let filledAmount = 0.0; + let node: CreatedNode | ModifiedNode | DeletedNode | undefined; + let fields: any; + let foundTradeIndex = 0; + let fillData: FillData; + + switch (intent.type) { + case TransactionIntentType.OFFER_CREATE_FINALIZED: + // console.log('Offer create finalized!'); + if (matchOrder.state === OrderStatus.PENDING_OPEN) { + matchOrder.state = OrderStatus.OPEN; + } + break; + + case TransactionIntentType.OFFER_CANCEL_FINALIZED: + // console.log('Offer cancel finalized!'); + matchOrder.state = OrderStatus.CANCELED; + break; + + case TransactionIntentType.OFFER_PARTIAL_FILL: + // console.log('Offer partial fill!'); + matchOrder.state = OrderStatus.PARTIALLY_FILLED; + + if (intent.node === undefined) { + // console.log('No node found!'); + break; + } + + node = intent.node as CreatedNode | ModifiedNode; + + if (isCreatedNode(node)) { + fields = node.CreatedNode.NewFields; + } else { + fields = node.ModifiedNode.FinalFields; + } + + // Update filled amount + if (matchOrder.tradeType === 'SELL') { + if (typeof fields.TakerGets === 'string') { + filledAmount = + parseFloat(matchOrder.amount) - + parseFloat(dropsToXrp(fields.TakerGets as string)); + } else { + filledAmount = + parseFloat(matchOrder.amount) - + parseFloat(fields.TakerGets.value as string); + } + } + + if (matchOrder.tradeType === 'BUY') { + if (typeof fields.TakerPays === 'string') { + filledAmount = + parseFloat(matchOrder.amount) - + parseFloat(dropsToXrp(fields.TakerPays as string)); + } else { + filledAmount = + parseFloat(matchOrder.amount) - + parseFloat(fields.TakerPays.value as string); + } + } + + // add intent as trade date + foundTradeIndex = matchOrder.associatedFills.findIndex((fill) => { + if (node === undefined) { + return ( + fill.tradeId === + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + `${intent.type}-${transaction.transaction.hash!}` + ); + } + + if (isCreatedNode(node)) { + return ( + fill.tradeId === + `${intent.type}-${node.CreatedNode.LedgerIndex}` + ); + } + + if (isModifiedNode(node)) { + return ( + fill.tradeId === + `${intent.type}-${node.ModifiedNode.LedgerIndex}` + ); + } + + return false; + }); + + if (foundTradeIndex === -1) { + fillData = this.buildFillData( + intent, + node, + matchOrder, + transaction + ); + matchOrder.associatedFills.push(fillData); + } else { + // console.log('FillData already found!'); + } + + // console.log('Filled amount: ', filledAmount); + matchOrder.filledAmount = filledAmount.toString(); + break; + + case TransactionIntentType.OFFER_FILL: + matchOrder.state = OrderStatus.FILLED; + matchOrder.filledAmount = matchOrder.amount; + + // add intent as trade date + node = intent.node as CreatedNode | DeletedNode | undefined; + + foundTradeIndex = matchOrder.associatedFills.findIndex((fill) => { + if (node === undefined) { + return ( + fill.tradeId === + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + `${intent.type}-${transaction.transaction.hash!}` + ); + } + + if (isCreatedNode(node)) { + return ( + fill.tradeId === + `${intent.type}-${node.CreatedNode.LedgerIndex}` + ); + } + + if (isDeletedNode(node)) { + return ( + fill.tradeId === + `${intent.type}-${node.DeletedNode.LedgerIndex}` + ); + } + + return false; + }); + + if (foundTradeIndex === -1) { + fillData = this.buildFillData( + intent, + node, + matchOrder, + transaction + ); + + matchOrder.associatedFills.push(fillData); + } else { + // console.log('FillData already found!'); + } + break; + + case TransactionIntentType.OFFER_EXPIRED_OR_UNFUNDED: + matchOrder.state = OrderStatus.OFFER_EXPIRED_OR_UNFUNDED; + break; + + case TransactionIntentType.UNKNOWN: + matchOrder.state = OrderStatus.UNKNOWN; + break; + } + + // Check matchOrder value + // console.log('Updated matchOrder: '); + // console.log(inspect(matchOrder, { colors: true, depth: null })); + + // Update ordersToCheck + ordersToCheck[matchOrder.hash] = matchOrder; + + // Release the lock + omm.release(matchOrder.hash); + } + + return ordersToCheck; + } + + // Utility methods + async getTransactionIntentsFromStream( + walletAddress: string, + transaction: TransactionStream | TransaformedAccountTransaction + ): Promise { + const transactionType = transaction.transaction.TransactionType; + const intents: TransactionIntent[] = []; + + if (transaction.transaction.Sequence === undefined) { + return [ + { + type: TransactionIntentType.UNKNOWN, + sequence: 0, + tx: transaction, + }, + ]; + } + + if (transaction.meta === undefined) { + return [ + { + type: TransactionIntentType.UNKNOWN, + sequence: transaction.transaction.Sequence, + tx: transaction, + }, + ]; + } + + if (transaction.transaction.Account !== walletAddress) { + // console.log('Transaction is not from wallet!'); + switch (transactionType) { + case 'OfferCreate': + for (const affnode of transaction.meta.AffectedNodes) { + if (isModifiedNode(affnode)) { + if (affnode.ModifiedNode.LedgerEntryType == 'Offer') { + // Usually a ModifiedNode of type Offer indicates a previous Offer that + // was partially consumed by this one. + if (affnode.ModifiedNode.FinalFields === undefined) { + intents.push({ + type: TransactionIntentType.UNKNOWN, + sequence: transaction.transaction.Sequence, + tx: transaction, + node: affnode, + }); + } + + const finalFields = affnode.ModifiedNode.FinalFields as any; + + intents.push({ + type: TransactionIntentType.OFFER_PARTIAL_FILL, + sequence: finalFields.Sequence as number, + tx: transaction, + node: affnode, + }); + } + } else if (isDeletedNode(affnode)) { + if (affnode.DeletedNode.LedgerEntryType == 'Offer') { + // The removed Offer may have been fully consumed, or it may have been + // found to be expired or unfunded. + if (affnode.DeletedNode.FinalFields === undefined) { + intents.push({ + type: TransactionIntentType.UNKNOWN, + sequence: transaction.transaction.Sequence, + tx: transaction, + node: affnode, + }); + } + + const finalFields = affnode.DeletedNode.FinalFields as any; + + intents.push({ + type: TransactionIntentType.OFFER_FILL, + sequence: finalFields.Sequence as number, + tx: transaction, + node: affnode, + }); + } + } + } + break; + } + } else { + // console.log('Transaction is from wallet!'); + let consumedNodeCount = 0; + let createNodeCount = 0; + let deleteNodeCount = 0; + + switch (transactionType) { + case 'OfferCreate': + for (const affnode of transaction.meta.AffectedNodes) { + if (isModifiedNode(affnode)) { + if (affnode.ModifiedNode.LedgerEntryType == 'Offer') { + // Usually a ModifiedNode of type Offer indicates a previous Offer that + // was partially consumed by this one. + + if (affnode.ModifiedNode.FinalFields === undefined) { + intents.push({ + type: TransactionIntentType.UNKNOWN, + sequence: transaction.transaction.Sequence, + tx: transaction, + node: affnode, + }); + } + + const finalFields = affnode.ModifiedNode.FinalFields as any; + intents.push({ + type: TransactionIntentType.OFFER_PARTIAL_FILL, + sequence: finalFields.Sequence as number, + tx: transaction, + node: affnode, + }); + consumedNodeCount++; + } + } else if (isDeletedNode(affnode)) { + if (affnode.DeletedNode.LedgerEntryType == 'Offer') { + // The removed Offer may have been fully consumed, or it may have been + // found to be expired or unfunded. + if (affnode.DeletedNode.FinalFields === undefined) { + intents.push({ + type: TransactionIntentType.UNKNOWN, + sequence: transaction.transaction.Sequence, + tx: transaction, + node: affnode, + }); + } else { + const finalFields = affnode.DeletedNode.FinalFields as any; + + if ( + transaction.transaction.Account === walletAddress && + finalFields.Account === walletAddress + ) { + const replacingOfferSequnce = + transaction.transaction.OfferSequence; + + if (finalFields.Sequence !== replacingOfferSequnce) { + intents.push({ + type: TransactionIntentType.OFFER_EXPIRED_OR_UNFUNDED, + sequence: finalFields.Sequence as number, + tx: transaction, + node: affnode, + }); + } else { + intents.push({ + type: TransactionIntentType.OFFER_CANCEL_FINALIZED, + sequence: finalFields.Sequence as number, + tx: transaction, + node: affnode, + }); + } + } else { + intents.push({ + type: TransactionIntentType.OFFER_FILL, + sequence: finalFields.Sequence as number, + tx: transaction, + node: affnode, + }); + consumedNodeCount++; + } + } + } + } else if (isCreatedNode(affnode)) { + if (affnode.CreatedNode.LedgerEntryType == 'Offer') { + if (affnode.CreatedNode.NewFields === undefined) { + intents.push({ + type: TransactionIntentType.UNKNOWN, + sequence: transaction.transaction.Sequence, + tx: transaction, + node: affnode, + }); + } else { + const newFields = affnode.CreatedNode.NewFields as any; + if (consumedNodeCount > 0) { + intents.push({ + type: TransactionIntentType.OFFER_PARTIAL_FILL, + sequence: newFields.Sequence, + tx: transaction, + node: affnode, + }); + } else { + intents.push({ + type: TransactionIntentType.OFFER_CREATE_FINALIZED, + sequence: newFields.Sequence, + tx: transaction, + node: affnode, + }); + } + createNodeCount++; + } + } + } + } + + if (createNodeCount === 0) { + if (consumedNodeCount > 0) { + intents.push({ + type: TransactionIntentType.OFFER_FILL, + sequence: transaction.transaction.Sequence, + tx: transaction, + }); + } else { + intents.push({ + type: TransactionIntentType.UNKNOWN, + sequence: transaction.transaction.Sequence, + tx: transaction, + }); + } + } + break; + + case 'OfferCancel': + for (const affnode of transaction.meta.AffectedNodes) { + if (isDeletedNode(affnode)) { + if (affnode.DeletedNode.LedgerEntryType == 'Offer') { + if (affnode.DeletedNode.FinalFields === undefined) { + intents.push({ + type: TransactionIntentType.UNKNOWN, + sequence: transaction.transaction.OfferSequence, + tx: transaction, + node: affnode, + }); + } else { + const finalFields = affnode.DeletedNode.FinalFields as any; + + if (finalFields.Account === walletAddress) { + intents.push({ + type: TransactionIntentType.OFFER_CANCEL_FINALIZED, + sequence: finalFields.Sequence as number, + tx: transaction, + node: affnode, + }); + deleteNodeCount++; + } + } + } + } + } + + if (deleteNodeCount === 0) { + intents.push({ + type: TransactionIntentType.OFFER_CANCEL_FINALIZED, + sequence: transaction.transaction.OfferSequence, + tx: transaction, + }); + } + break; + } + } + + return intents; + } + async getTransaction( + client: Client, + txHash: string + ): Promise { + if (txHash === '') { + return null; + } + + const tx_resp = await client.request({ + command: 'tx', + transaction: txHash, + binary: false, + }); + + const result = tx_resp; + + return result; + } + + async getTransactionsStack( + client: Client, + account: string, + minLedgerIndex: number + ): Promise { + if (account === '') { + return null; + } + + const tx_resp: AccountTxResponse = await client.request({ + command: 'account_tx', + account: account, + ledger_index_min: minLedgerIndex, + binary: false, + }); + + const result = tx_resp; + + return result; + } + + transformAccountTransaction( + transaction: AccountTransaction + ): TransaformedAccountTransaction | null { + if (typeof transaction.meta === 'string') { + return null; + } + + if (transaction.tx === undefined) { + return null; + } + + const transformedTx: TransaformedAccountTransaction = { + ledger_index: transaction.tx.ledger_index ?? 0, + meta: transaction.meta as TransactionMetadata, + transaction: transaction.tx as Transaction & ResponseOnlyTxInfo, + tx_blob: transaction.tx_blob, + validated: transaction.validated, + }; + + return transformedTx; + } + + buildFillData( + intent: TransactionIntent, + node: CreatedNode | ModifiedNode | DeletedNode | undefined, + order: Order, + transaction: TransactionStream | TransaformedAccountTransaction + ): FillData { + let tradeId: string; + const orderHash: number = order.hash; + + if (node === undefined) { + const feeToken = + order.tradeType === 'BUY' + ? getQuoteTokenFromMarketId(order.marketId) + : getBaseTokenFromMarketId(order.marketId); + const fee = this.calculateFee( + order.marketId, + order.tradeType, + order.amount + ); + const timestamp = transaction.transaction.date + ? rippleTimeToUnixTime(transaction.transaction.date) + : 0; + return { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + tradeId: `${intent.type}-${transaction.transaction.hash!}`, + orderHash: order.hash, + price: order.price, + quantity: order.amount, + feeToken: feeToken, + side: order.tradeType, + fee: fee, + timestamp: timestamp, + type: 'Taker', + }; + } + + if (isModifiedNode(node)) { + tradeId = `${intent.type}-${node.ModifiedNode.LedgerIndex}`; + } else if (isDeletedNode(node)) { + tradeId = `${intent.type}-${node.DeletedNode.LedgerIndex}`; + } else { + tradeId = `${intent.type}-${node.CreatedNode.LedgerIndex}`; + } + + const price = order.price; + const quantity = this.getFilledAmountFromNode( + order, + node, + order.tradeType + ).toString(); + const feeToken = + order.tradeType === 'BUY' + ? getQuoteTokenFromMarketId(order.marketId) + : getBaseTokenFromMarketId(order.marketId); + const side = order.tradeType; + const fee = this.calculateFee(order.marketId, order.tradeType, quantity); + const timestamp = transaction.transaction.date + ? rippleTimeToUnixTime(transaction.transaction.date) + : 0; + const type = 'Maker'; + + return { + tradeId, + orderHash, + price, + quantity, + feeToken, + side, + fee, + timestamp, + type, + }; + } + + calculateFee(marketId: string, tradeType: string, quantity: string): string { + let fee = '0'; + const market = this._xrplClob.parsedMarkets[marketId] as Market; + + if (market === undefined) { + return '0'; + } + + if (tradeType === 'BUY') { + fee = (parseFloat(quantity) * market.quoteTransferRate).toString(); + } else { + fee = (parseFloat(quantity) * market.baseTransferRate).toString(); + } + + return fee; + } + + getFilledAmountFromNode( + order: Order, + node: CreatedNode | ModifiedNode | DeletedNode, + tradeType: string + ): number { + let filledAmount = 0; + let ledgerEntryType = ''; + let previousFields: any, finalFields: any; + + try { + if (isModifiedNode(node)) { + ledgerEntryType = node.ModifiedNode.LedgerEntryType; + previousFields = node.ModifiedNode.PreviousFields; + finalFields = node.ModifiedNode.FinalFields; + } else if (isDeletedNode(node)) { + ledgerEntryType = node.DeletedNode.LedgerEntryType; + previousFields = node.DeletedNode.PreviousFields; + finalFields = node.DeletedNode.FinalFields; + } else { + ledgerEntryType = node.CreatedNode.LedgerEntryType; + previousFields = undefined; + finalFields = node.CreatedNode.NewFields; + } + } catch (error) { + throw new Error('Error parsing node: ' + error); + } + + if (ledgerEntryType === 'Offer' && isCreatedNode(node)) { + if (finalFields === undefined) throw new Error('Final fields undefined'); + + if (tradeType === 'SELL') { + if (typeof finalFields.TakerGets === 'string') { + filledAmount = + parseFloat(order.amount) - + parseFloat(dropsToXrp(finalFields.TakerGets as string)); + } else { + filledAmount = + parseFloat(order.amount) - + parseFloat(finalFields.TakerGets.value as string); + } + } + + if (tradeType === 'BUY') { + if (typeof finalFields.TakerPays === 'string') { + filledAmount = + parseFloat(order.amount) - + parseFloat(dropsToXrp(finalFields.TakerPays as string)); + } else { + filledAmount = + parseFloat(order.amount) - + parseFloat(finalFields.TakerPays.value as string); + } + } + } else if (ledgerEntryType === 'Offer') { + if (previousFields === undefined) + throw new Error('Previous fields undefined'); + if (finalFields === undefined) throw new Error('Final fields undefined'); + + if (tradeType === 'SELL') { + if (typeof finalFields.TakerGets === 'string') { + filledAmount = + parseFloat(dropsToXrp(previousFields.TakerGets as string)) - + parseFloat(dropsToXrp(finalFields.TakerGets as string)); + } else { + filledAmount = + parseFloat(previousFields.TakerGets.value as string) - + parseFloat(finalFields.TakerGets.value as string); + } + } + + if (tradeType === 'BUY') { + if (typeof finalFields.TakerPays === 'string') { + filledAmount = + parseFloat(dropsToXrp(previousFields.TakerPays as string)) - + parseFloat(dropsToXrp(finalFields.TakerPays as string)); + } else { + filledAmount = + parseFloat(previousFields.TakerPays.value as string) - + parseFloat(finalFields.TakerPays.value as string); + } + } + } else { + throw new Error('Invalid ledgerEntryType type'); + } + + return filledAmount; + } +} diff --git a/src/chains/xrpl/xrpl.requests.ts b/src/chains/xrpl/xrpl.requests.ts new file mode 100644 index 0000000000..a4682054ed --- /dev/null +++ b/src/chains/xrpl/xrpl.requests.ts @@ -0,0 +1,62 @@ +import { NetworkSelectionRequest } from '../../services/common-interfaces'; +import { TxResponse } from 'xrpl'; + +export interface XRPLBalanceRequest extends NetworkSelectionRequest { + address: string; + tokenSymbols: string[]; +} + +export interface XRPLBalanceResponse { + network: string; + timestamp: number; + latency: number; + address: string; + balances: Record; +} + +export type TokenBalance = { + currency: string; + issuer?: string; + value: string; +}; + +export interface XRPLTokenRequest extends NetworkSelectionRequest { + address: string; // the user's Solana address as Base58 + token: string; // the token symbol the spender will be approved for +} + +export interface XRPLTokenResponse { + network: string; + timestamp: number; + token: string; // the token symbol the spender will be approved for + mintAddress: string; + accountAddress?: string; + amount: string | null; +} + +export interface XRPLPollRequest extends NetworkSelectionRequest { + txHash: string; +} + +export enum TransactionResponseStatusCode { + FAILED = -1, + PENDING = 0, + CONFIRMED = 1, +} + +export interface XRPLPollResponse { + network: string; + timestamp: number; + currentLedgerIndex: number; + sequence?: number; + txHash: string; + txStatus: number; + txLedgerIndex?: number; + txData?: TxResponse; +} + +export enum XRPLNetworkID { + MAINNET = 1000, + TESTNET = 2000, + DEVNET = 3000, +} diff --git a/src/chains/xrpl/xrpl.ts b/src/chains/xrpl/xrpl.ts new file mode 100644 index 0000000000..de63335f22 --- /dev/null +++ b/src/chains/xrpl/xrpl.ts @@ -0,0 +1,501 @@ +import { + Client, + Wallet, + LedgerStream, + ValidationStream, + TransactionStream, + PeerStatusStream, + ConsensusStream, + PathFindStream, + TxResponse, + TransactionMetadata, +} from 'xrpl'; +import axios from 'axios'; +import { promises as fs } from 'fs'; +import crypto from 'crypto'; +import fse from 'fs-extra'; +import path from 'path'; +import { rootPath } from '../../paths'; +import { TokenListType, walletPath, MarketListType } from '../../services/base'; +import { ConfigManagerCertPassphrase } from '../../services/config-manager-cert-passphrase'; +import { getXRPLConfig } from './xrpl.config'; +// import { logger } from '../../services/logger'; +import { TransactionResponseStatusCode, TokenBalance } from './xrpl.requests'; +import { XRPLOrderStorage } from './xrpl.order-storage'; +import { OrderTracker } from './xrpl.order-tracker'; +import { ReferenceCountingCloseable } from '../../services/refcounting-closeable'; +import { XRPLController } from './xrpl.controllers'; + +export type XRPTokenInfo = { + id: number; + code: string; + issuer: string; + title: string; + trustlines: number; + placeInTop: null; +}; + +export type MarketInfo = { + id: number; + marketId: string; + baseIssuer: string; + quoteIssuer: string; + baseTokenID: number; + quoteTokenID: number; +}; + +export type Fee = { + base: string; + median: string; + minimum: string; + openLedger: string; +}; + +export class XRPL implements XRPLish { + private static _instances: { [name: string]: XRPL }; + public rpcUrl; + public fee: Fee; + + protected tokenList: XRPTokenInfo[] = []; + protected marketList: MarketInfo[] = []; + private _tokenMap: Record = {}; + private _marketMap: Record = {}; + + private _client: Client; + private _nativeTokenSymbol: string; + private _chain: string; + private _network: string; + private _requestCount: number; + private _metricsLogInterval: number; + private _tokenListSource: string; + private _marketListSource: string; + private _tokenListType: TokenListType; + private _marketListType: MarketListType; + + private _ready: boolean = false; + private initializing: boolean = false; + + private readonly _refCountingHandle: string; + private readonly _orderStorage: XRPLOrderStorage; + + public controller: typeof XRPLController; + + private constructor(network: string) { + const config = getXRPLConfig('xrpl', network); + + this._chain = 'xrpl'; + this._network = network; + this.rpcUrl = config.network.nodeUrl; + this._nativeTokenSymbol = config.network.nativeCurrencySymbol; + this._tokenListSource = config.network.tokenListSource; + this._tokenListType = config.network.tokenListType; + this._marketListSource = config.network.marketListSource; + this._marketListType = config.network.marketListType; + + this._client = new Client(this.rpcUrl, { + timeout: config.requestTimeout, + connectionTimeout: config.connectionTimeout, + feeCushion: config.feeCushion, + maxFeeXRP: config.maxFeeXRP, + }); + + this.fee = { + base: '0', + median: '0', + minimum: '0', + openLedger: '0', + }; + + this._requestCount = 0; + this._metricsLogInterval = 300000; // 5 minutes + + this.onValidationReceived(this.requestCounter.bind(this)); + // setInterval(this.metricLogger.bind(this), this.metricsLogInterval); + + this._refCountingHandle = ReferenceCountingCloseable.createHandle(); + this._orderStorage = XRPLOrderStorage.getInstance( + this.resolveDBPath(config.orderDbPath), + this._refCountingHandle + ); + this._orderStorage.declareOwnership(this._refCountingHandle); + this.controller = XRPLController; + } + + public static getInstance(network: string): XRPL { + if (XRPL._instances === undefined) { + XRPL._instances = {}; + } + if (!(network in XRPL._instances)) { + XRPL._instances[network] = new XRPL(network); + } + + return XRPL._instances[network]; + } + + public static getConnectedInstances(): { [name: string]: XRPL } { + return XRPL._instances; + } + + public resolveDBPath(oldPath: string): string { + if (oldPath.charAt(0) === '/') return oldPath; + const dbDir: string = path.join(rootPath(), 'db/'); + fse.mkdirSync(dbDir, { recursive: true }); + return path.join(dbDir, oldPath); + } + + public get client() { + return this._client; + } + + public onConnected(callback: () => void) { + this._client.on('connected', callback); + } + + public onDisconnected(callback: (code: number) => void) { + this._client.on('disconnected', callback); + } + + public onLedgerClosed(callback: (ledger: LedgerStream) => void) { + this._client.on('ledgerClosed', callback); + } + + public onValidationReceived( + callback: (validation: ValidationStream) => void + ) { + this._client.on('validationReceived', callback); + } + + public onTransaction(callback: (tx: TransactionStream) => void) { + this._client.on('transaction', callback); + } + + public onPeerStatusChange(callback: (status: PeerStatusStream) => void) { + this._client.on('peerStatusChange', callback); + } + + public onConsensusPhase(callback: (phase: ConsensusStream) => void) { + this._client.on('consensusPhase', callback); + } + + public onPathFind(callback: (path: PathFindStream) => void) { + this._client.on('path_find', callback); + } + + public onError(callback: (...err: any[]) => void): void { + this._client.on('error', callback); + } + + async init(): Promise { + if (!this.ready() && !this.initializing) { + this.initializing = true; + await this.ensureConnection(); + await this.loadTokens(this._tokenListSource, this._tokenListType); + await this.loadMarkets(this._marketListSource, this._marketListType); + await this.getFee(); + await this._orderStorage.init(); + this._ready = true; + this.initializing = false; + } + } + + async loadTokens( + tokenListSource: string, + tokenListType: TokenListType + ): Promise { + this.tokenList = await this.getTokenList(tokenListSource, tokenListType); + if (this.tokenList) { + this.tokenList.forEach((token: XRPTokenInfo) => { + if (!this._tokenMap[token.code]) { + this._tokenMap[token.code] = []; + } + + this._tokenMap[token.code].push(token); + }); + } + } + + async loadMarkets( + marketListSource: string, + marketListType: MarketListType + ): Promise { + this.marketList = await this.getMarketList( + marketListSource, + marketListType + ); + if (this.marketList) { + this.marketList.forEach((market: MarketInfo) => { + if (!this._marketMap[market.marketId]) { + this._marketMap[market.marketId] = []; + } + + this._marketMap[market.marketId].push(market); + }); + } + } + + async getTokenList( + tokenListSource: string, + tokenListType: TokenListType + ): Promise { + let tokens; + if (tokenListType === 'URL') { + const resp = await axios.get(tokenListSource); + tokens = resp.data.tokens; + } else { + tokens = JSON.parse(await fs.readFile(tokenListSource, 'utf8')); + } + return tokens; + } + + async getMarketList( + marketListSource: string, + marketListType: TokenListType + ): Promise { + let markets; + if (marketListType === 'URL') { + const resp = await axios.get(marketListSource); + markets = resp.data.tokens; + } else { + markets = JSON.parse(await fs.readFile(marketListSource, 'utf8')); + } + return markets; + } + + public get storedTokenList(): XRPTokenInfo[] { + return this.tokenList; + } + + public get storedMarketList(): MarketInfo[] { + return this.marketList; + } + + public getTokenForSymbol(code: string): XRPTokenInfo[] | undefined { + return this._tokenMap[code] ? this._tokenMap[code] : undefined; + } + + public getWalletFromSeed(seed: string): Wallet { + const wallet = Wallet.fromSeed(seed); + + return wallet; + } + + async getWallet(address: string): Promise { + const path = `${walletPath}/${this.chain}`; + + const encryptedSeed: string = await fse.readFile( + `${path}/${address}.json`, + 'utf8' + ); + + const passphrase = ConfigManagerCertPassphrase.readPassphrase(); + if (!passphrase) { + throw new Error('missing passphrase'); + } + const decrypted = await this.decrypt(encryptedSeed, passphrase); + + return Wallet.fromSeed(decrypted); + } + + async encrypt(secret: string, password: string): Promise { + const algorithm = 'aes-256-ctr'; + const iv = crypto.randomBytes(16); + const salt = crypto.randomBytes(32); + const key = crypto.pbkdf2Sync(password, salt, 5000, 32, 'sha512'); + const cipher = crypto.createCipheriv(algorithm, key, iv); + const encrypted = Buffer.concat([cipher.update(secret), cipher.final()]); + + const ivJSON = iv.toJSON(); + const saltJSON = salt.toJSON(); + const encryptedJSON = encrypted.toJSON(); + + return JSON.stringify({ + algorithm, + iv: ivJSON, + salt: saltJSON, + encrypted: encryptedJSON, + }); + } + + async decrypt(encryptedSecret: string, password: string): Promise { + const hash = JSON.parse(encryptedSecret); + const salt = Buffer.from(hash.salt, 'utf8'); + const iv = Buffer.from(hash.iv, 'utf8'); + + const key = crypto.pbkdf2Sync(password, salt, 5000, 32, 'sha512'); + + const decipher = crypto.createDecipheriv(hash.algorithm, key, iv); + + const decrpyted = Buffer.concat([ + decipher.update(Buffer.from(hash.encrypted, 'hex')), + decipher.final(), + ]); + + return decrpyted.toString(); + } + + async getNativeBalance(wallet: Wallet): Promise { + await this.ensureConnection(); + const balance = await this._client.getXrpBalance(wallet.address); + return balance; + } + + async getAllBalance(wallet: Wallet): Promise> { + await this.ensureConnection(); + const balances: Array = []; + const respBalances = await this._client.getBalances(wallet.address); + + respBalances.forEach((token) => { + if (token.currency === 'XRP') { + balances.push({ + currency: token.currency, + value: token.value, + }); + } else { + const filtered = this.getTokenForSymbol(token.currency); + + // TODO: this is for filtering out tokens that are not in token list + if (filtered === undefined) { + return; + } + + balances.push({ + currency: token.currency, + issuer: token.issuer, + value: token.value, + }); + } + }); + + return balances; + } + + ready(): boolean { + return this._ready; + } + + isConnected(): boolean { + return this._client.isConnected(); + } + + async ensureConnection() { + if (!this.isConnected()) { + await this._client.connect(); + } + } + + public get chain(): string { + return this._chain; + } + + public get network(): string { + return this._network; + } + + public get nativeTokenSymbol(): string { + return this._nativeTokenSymbol; + } + + public requestCounter(): void { + this._requestCount += 1; + } + + // public metricLogger(): void { + // logger.info( + // this.requestCount + + // ' request(s) sent in last ' + + // this.metricsLogInterval / 1000 + + // ' seconds.' + // ); + // this._requestCount = 0; // reset + // } + + public get requestCount(): number { + return this._requestCount; + } + + public get metricsLogInterval(): number { + return this._metricsLogInterval; + } + + public async getCurrentLedgerIndex(): Promise { + await this.ensureConnection(); + const currentIndex = await this.client.getLedgerIndex(); + return currentIndex; + } + + public async getCurrentBlockNumber(): Promise { + await this.ensureConnection(); + const currentIndex = await this.getCurrentLedgerIndex(); + return currentIndex; + } + + public async getTransactionStatusCode( + txData: TxResponse | null + ): Promise { + let txStatus; + if (!txData) { + txStatus = TransactionResponseStatusCode.FAILED; + } else { + if (txData.result.validated === false) { + txStatus = TransactionResponseStatusCode.PENDING; + } else { + if ((txData.result.meta).TransactionResult) { + const result = (txData.result.meta) + .TransactionResult; + txStatus = + result == 'tesSUCCESS' + ? TransactionResponseStatusCode.CONFIRMED + : TransactionResponseStatusCode.FAILED; + } else { + txStatus = TransactionResponseStatusCode.FAILED; + } + } + } + return txStatus; + } + + async getTransaction(txHash: string): Promise { + await this.ensureConnection(); + const tx_resp = await this._client.request({ + command: 'tx', + transaction: txHash, + binary: false, + }); + + const result = tx_resp; + + return result; + } + + async close() { + if (this._network in XRPL._instances) { + await OrderTracker.stopTrackingOnAllInstancesForNetwork(this._network); + await this._orderStorage.close(this._refCountingHandle); + await this._client.disconnect(); + delete XRPL._instances[this._network]; + } + } + + async getFee() { + await this.ensureConnection(); + const tx_resp = await this._client.request({ + command: 'fee', + }); + + this.fee = { + base: tx_resp.result.drops.base_fee, + median: tx_resp.result.drops.median_fee, + minimum: tx_resp.result.drops.minimum_fee, + openLedger: tx_resp.result.drops.open_ledger_fee, + }; + + return this.fee; + } + + public get orderStorage(): XRPLOrderStorage { + return this._orderStorage; + } +} + +export type XRPLish = XRPL; +export const XRPLish = XRPL; diff --git a/src/chains/xrpl/xrpl.validators.ts b/src/chains/xrpl/xrpl.validators.ts new file mode 100644 index 0000000000..8325c82cec --- /dev/null +++ b/src/chains/xrpl/xrpl.validators.ts @@ -0,0 +1,47 @@ +import { + validateTokenSymbols, + mkValidator, + mkRequestValidator, + RequestValidator, + Validator, + isBase58, + validateTxHash, +} from '../../services/validators'; + +// invalid parameter errors +export const invalidXRPLAddressError: string = + 'The spender param is not a valid XRPL address (20 bytes, base 58 encoded).'; + +export const invalidXRPLPrivateKeyError: string = + 'The privateKey param is not a valid XRPL seed key (16 bytes, base 58 encoded).'; + +// test if a string matches the shape of an XRPL address +export const isXRPLAddress = (str: string): boolean => { + return isBase58(str) && str.length <= 35 && str.charAt(0) == 'r'; +}; + +// test if a string matches the shape of an XRPL seed key +export const isXRPLSeedKey = (str: string): boolean => { + return isBase58(str) && str.charAt(0) == 's'; +}; + +// given a request, look for a key called address that is an Solana address +export const validateXRPLAddress: Validator = mkValidator( + 'address', + invalidXRPLAddressError, + (val) => typeof val === 'string' && isXRPLAddress(val) +); + +// request types and corresponding validators + +export const validateXRPLBalanceRequest: RequestValidator = mkRequestValidator([ + validateXRPLAddress, +]); + +export const validateXRPLPollRequest: RequestValidator = mkRequestValidator([ + validateTxHash, +]); + +export const validateXRPLGetTokenRequest: RequestValidator = mkRequestValidator( + [validateTokenSymbols] +); diff --git a/src/clob/clob.validators.ts b/src/clob/clob.validators.ts index 8019b5e271..2604927be8 100644 --- a/src/clob/clob.validators.ts +++ b/src/clob/clob.validators.ts @@ -12,6 +12,8 @@ import { validateNetwork, } from '../chains/ethereum/ethereum.validators'; +import { isXRPLAddress } from '../chains/xrpl/xrpl.validators'; + import { validateConnector, validateAmount, @@ -98,7 +100,9 @@ export const validateWallet: Validator = mkValidator( (val) => { return ( typeof val === 'string' && - (isAddress(val.slice(0, 42)) || isValidKujiraPublicKey(val)) + (isAddress(val.slice(0, 42)) || + isValidKujiraPublicKey(val) || + isXRPLAddress(val)) ); } ); diff --git a/src/connectors/connectors.routes.ts b/src/connectors/connectors.routes.ts index ad4d13c9de..949db3ee84 100644 --- a/src/connectors/connectors.routes.ts +++ b/src/connectors/connectors.routes.ts @@ -19,6 +19,7 @@ import { DexalotCLOBConfig } from './dexalot/dexalot.clob.config'; import { TinymanConfig } from './tinyman/tinyman.config'; import { CurveConfig } from './curve/curveswap.config'; import { PlentyConfig } from './plenty/plenty.config'; +import { XRPLCLOBConfig } from './xrpl/xrpl.clob.config'; import { KujiraConfig } from './kujira/kujira.config'; export namespace ConnectorsRoutes { @@ -138,6 +139,12 @@ export namespace ConnectorsRoutes { chain_type: PlentyConfig.config.chainType, available_networks: PlentyConfig.config.availableNetworks, }, + { + name: 'xrpl', + trading_type: XRPLCLOBConfig.config.tradingTypes, + chain_type: XRPLCLOBConfig.config.chainType, + available_networks: XRPLCLOBConfig.config.availableNetworks, + }, { name: 'kujira', trading_type: KujiraConfig.config.tradingTypes, diff --git a/src/connectors/xrpl/xrpl.clob.config.ts b/src/connectors/xrpl/xrpl.clob.config.ts new file mode 100644 index 0000000000..786c0ddd66 --- /dev/null +++ b/src/connectors/xrpl/xrpl.clob.config.ts @@ -0,0 +1,21 @@ +import { AvailableNetworks } from '../../services/config-manager-types'; +// import { ConfigManagerV2 } from '../../services/config-manager-v2'; + +export namespace XRPLCLOBConfig { + export interface NetworkConfig { + tradingTypes: Array; + chainType: string; + availableNetworks: Array; + } + + export const config: NetworkConfig = { + tradingTypes: ['CLOB_SPOT'], + chainType: 'XRPL', + availableNetworks: [ + { + chain: 'xrpl', + networks: ['mainnet', 'testnet'], + }, + ], + }; +} diff --git a/src/connectors/xrpl/xrpl.ts b/src/connectors/xrpl/xrpl.ts new file mode 100644 index 0000000000..f065ee75e4 --- /dev/null +++ b/src/connectors/xrpl/xrpl.ts @@ -0,0 +1,612 @@ +import { MarketInfo, XRPL } from '../../chains/xrpl/xrpl'; +import { XRPLOrderStorage } from '../../chains/xrpl/xrpl.order-storage'; +import { + Client, + Wallet, + Transaction, + xrpToDrops, + AccountInfoResponse, + BookOffersResponse, +} from 'xrpl'; +import { OrderTracker } from '../../chains/xrpl/xrpl.order-tracker'; +import { + Market, + MarketNotFoundError, + Token, + TradeType, + Orderbook, + PriceLevel, + Order, +} from './xrpl.types'; +import { + getTakerGetsAmount, + getTakerPaysAmount, + getTakerGetsFundedAmount, + getTakerPaysFundedAmount, +} from './xrpl.utils'; +import { + ClobMarketsRequest, + ClobOrderbookRequest, + ClobTickerRequest, + ClobGetOrderRequest, + ClobPostOrderRequest, + ClobDeleteOrderRequest, + CLOBMarkets, + ClobGetOrderResponse, +} from '../../clob/clob.requests'; +import { promiseAllInBatches } from '../../chains/xrpl/xrpl.helpers'; +import { + CLOBish, + NetworkSelectionRequest, +} from '../../services/common-interfaces'; +import LRUCache from 'lru-cache'; +import { getXRPLConfig } from '../../chains/xrpl/xrpl.config'; +import { isUndefined } from 'mathjs'; + +// const XRP_FACTOR = 1000000; +const ORDERBOOK_LIMIT = 100; +const TXN_SUBMIT_DELAY = 100; +export class XRPLCLOB implements CLOBish { + private static _instances: LRUCache; + private readonly _client: Client; + private readonly _xrpl: XRPL; + private readonly _orderStorage: XRPLOrderStorage; + + private _ready: boolean = false; + private _isSubmittingTxn: boolean = false; + + public parsedMarkets: CLOBMarkets = {}; + public chain: string; + public network: string; + + private constructor(chain: string, network: string) { + this.chain = chain; + this.network = network; + + this._xrpl = XRPL.getInstance(network); + this._client = this._xrpl.client; + this._orderStorage = this._xrpl.orderStorage; + } + + public static getInstance(chain: string, network: string): XRPLCLOB { + if (XRPLCLOB._instances === undefined) { + const config = getXRPLConfig(chain, network); + XRPLCLOB._instances = new LRUCache({ + max: config.network.maxLRUCacheInstances, + }); + } + const instanceKey = chain + network; + if (!XRPLCLOB._instances.has(instanceKey)) { + XRPLCLOB._instances.set(instanceKey, new XRPLCLOB(chain, network)); + } + + return XRPLCLOB._instances.get(instanceKey) as XRPLCLOB; + } + + public async loadMarkets() { + const rawMarkets = await this.fetchMarkets(); + for (const market of rawMarkets) { + this.parsedMarkets[market.marketId] = market; + } + } + + public async init() { + if (!this._xrpl.ready() || Object.keys(this.parsedMarkets).length === 0) { + await this._xrpl.init(); + await this.loadMarkets(); + this._ready = true; + } + } + + public ready(): boolean { + return this._ready; + } + + public getInfo(): string { + const info = `XRPLCLOB: ${this.chain} ${this.network} | RCP URL: ${this._xrpl.rpcUrl} | XRPLCLOB ready: ${this._ready}`; + + return info; + } + + // CLOB methods: + // TODO: Find and correct the required market info in client + public async markets( + req: ClobMarketsRequest + ): Promise<{ markets: Array }> { + if (req.market && req.market.split('-').length === 2) { + const marketsAsArray: Array = []; + marketsAsArray.push(this.parsedMarkets[req.market]); + return { markets: marketsAsArray }; + } + + const marketsAsArray: Array = []; + for (const market in this.parsedMarkets) { + marketsAsArray.push(this.parsedMarkets[market]); + } + + return { markets: marketsAsArray }; + } + + public async orderBook(req: ClobOrderbookRequest): Promise { + return await this.getOrderBook(this.parsedMarkets[req.market]); + } + + // Utility methods: + async fetchMarkets(): Promise { + const loadedMarkets: Market[] = []; + const markets = this._xrpl.storedMarketList; + const getMarket = async (market: MarketInfo): Promise => { + const processedMarket = await this.getMarket(market); + loadedMarkets.push(processedMarket); + }; + + await promiseAllInBatches(getMarket, markets, 1, 1); + + return loadedMarkets; + } + + async getMarket(market: MarketInfo): Promise { + if (!market) throw new MarketNotFoundError(`No market informed.`); + let baseTickSize, + baseTransferRate, + quoteTickSize, + quoteTransferRate: number; + const zeroTransferRate = 1000000000; + + const [baseCurrency, quoteCurrency] = market.marketId.split('-'); + const baseIssuer = market.baseIssuer; + const quoteIssuer = market.quoteIssuer; + + if (baseCurrency != 'XRP') { + const baseMarketResp: AccountInfoResponse = await this._client.request({ + command: 'account_info', + ledger_index: 'validated', + account: baseIssuer, + }); + + if (!baseMarketResp) + throw new MarketNotFoundError( + `Market "${baseCurrency}.${baseIssuer}" not found.` + ); + + baseTickSize = baseMarketResp.result.account_data.TickSize ?? 15; + const rawTransferRate = + baseMarketResp.result.account_data.TransferRate ?? zeroTransferRate; + baseTransferRate = rawTransferRate / zeroTransferRate - 1; + } else { + baseTickSize = 6; + baseTransferRate = 0; + } + + if (quoteCurrency != 'XRP') { + const quoteMarketResp: AccountInfoResponse = await this._client.request({ + command: 'account_info', + ledger_index: 'validated', + account: quoteIssuer, + }); + + if (!quoteMarketResp) + throw new MarketNotFoundError( + `Market "${quoteCurrency}.${quoteIssuer}" not found.` + ); + + quoteTickSize = quoteMarketResp.result.account_data.TickSize ?? 15; + const rawTransferRate = + quoteMarketResp.result.account_data.TransferRate ?? zeroTransferRate; + quoteTransferRate = rawTransferRate / zeroTransferRate - 1; + } else { + quoteTickSize = 6; + quoteTransferRate = 0; + } + + const smallestTickSize = Math.min(baseTickSize, quoteTickSize); + const minimumOrderSize = Math.pow(10, -smallestTickSize); + + const result = { + marketId: market.marketId, + minimumOrderSize: minimumOrderSize, + smallestTickSize: smallestTickSize, + baseTickSize, + quoteTickSize, + baseTransferRate: baseTransferRate, + quoteTransferRate: quoteTransferRate, + baseIssuer: baseIssuer, + quoteIssuer: quoteIssuer, + baseCurrency: baseCurrency, + quoteCurrency: quoteCurrency, + }; + + return result; + } + + async getOrderBook( + market: MarketInfo, + limit: number = ORDERBOOK_LIMIT + ): Promise { + const [baseCurrency, quoteCurrency] = market.marketId.split('-'); + const baseIssuer = market.baseIssuer; + const quoteIssuer = market.quoteIssuer; + + const baseRequest: any = { + currency: baseCurrency, + }; + + const quoteRequest: any = { + currency: quoteCurrency, + }; + + if (baseIssuer) { + baseRequest['issuer'] = baseIssuer; + } + if (quoteIssuer) { + quoteRequest['issuer'] = quoteIssuer; + } + + const { bids, asks } = await this.getOrderBookFromXRPL( + baseRequest, + quoteRequest, + limit + ); + + const buys: PriceLevel[] = []; + const sells: PriceLevel[] = []; + + bids.forEach((bid) => { + let price, quantity: string; + + if ( + isUndefined(bid.taker_gets_funded) && + isUndefined(bid.taker_pays_funded) + ) { + if (isUndefined(bid.TakerGets)) return; + if (isUndefined(bid.TakerPays)) return; + + price = ( + parseFloat(getTakerGetsAmount(bid)) / + parseFloat(getTakerPaysAmount(bid)) + ).toString(); + quantity = getTakerPaysAmount(bid); + } else { + if (isUndefined(bid.taker_gets_funded)) return; + if (isUndefined(bid.taker_pays_funded)) return; + + price = ( + parseFloat(getTakerGetsFundedAmount(bid)) / + parseFloat(getTakerPaysFundedAmount(bid)) + ).toString(); + quantity = getTakerPaysFundedAmount(bid); + } + + buys.push({ + price, + quantity, + timestamp: Date.now(), + }); + }); + + asks.forEach((ask) => { + let price, quantity: string; + + if ( + isUndefined(ask.taker_gets_funded) && + isUndefined(ask.taker_pays_funded) + ) { + if (isUndefined(ask.TakerGets)) return; + if (isUndefined(ask.TakerPays)) return; + + price = ( + parseFloat(getTakerPaysAmount(ask)) / + parseFloat(getTakerGetsAmount(ask)) + ).toString(); + quantity = getTakerGetsAmount(ask); + } else { + if (isUndefined(ask.taker_gets_funded)) return; + if (isUndefined(ask.taker_pays_funded)) return; + + price = ( + parseFloat(getTakerPaysFundedAmount(ask)) / + parseFloat(getTakerGetsFundedAmount(ask)) + ).toString(); + quantity = getTakerGetsFundedAmount(ask); + } + + sells.push({ + price, + quantity, + timestamp: Date.now(), + }); + }); + + return { + buys, + sells, + }; + } + + public async ticker( + req: ClobTickerRequest + ): Promise<{ markets: Array }> { + const getMarkets = await this.markets(req); + const markets = getMarkets.markets; + + const marketsWithMidprice = await Promise.all( + markets.map(async (market) => { + const midprice = await this.getMidPriceForMarket( + this.parsedMarkets[market.marketId] + ); + return { ...market, midprice }; + }) + ); + + return { markets: marketsWithMidprice }; + } + + public async orders( + req: ClobGetOrderRequest + ): Promise<{ orders: ClobGetOrderResponse['orders'] }> { + if (!req.address) return { orders: [] }; + if (!req.orderId) return { orders: [] }; + + if (req.orderId === 'all') { + if (!req.market) return { orders: [] }; + const marketId = this.parsedMarkets[req.market].marketId; + const orders = await this._orderStorage.getOrdersByMarket( + this.chain, + this.network, + req.address, + marketId + ); + + const keys = Object.keys(orders); + const ordersArray = keys.map((key) => orders[key]); + + return { orders: ordersArray } as ClobGetOrderResponse; + } else { + const orders = await this._orderStorage.getOrdersByHash( + this.chain, + this.network, + req.address, + req.orderId + ); + + const keys = Object.keys(orders); + const ordersArray = keys.map((key) => orders[key]); + + return { orders: ordersArray } as ClobGetOrderResponse; + } + } + + public async postOrder( + req: ClobPostOrderRequest + ): Promise<{ txHash: string }> { + const market = this.parsedMarkets[req.market] as Market; + const [baseCurrency, quoteCurrency] = market.marketId.split('-'); + const baseIssuer = market.baseIssuer; + const quoteIssuer = market.quoteIssuer; + + const wallet = await this.getWallet(req.address); + const total = parseFloat(req.price) * parseFloat(req.amount); + + let we_pay: Token = { + currency: '', + issuer: '', + value: '', + }; + let we_get: Token = { currency: '', issuer: '', value: '' }; + + if (req.side == TradeType.SELL) { + we_pay = { + currency: baseCurrency, + issuer: baseIssuer, + value: Number( + parseFloat(req.amount).toPrecision(market.smallestTickSize) + ).toString(), + }; + we_get = { + currency: quoteCurrency, + issuer: quoteIssuer, + value: Number(total.toPrecision(market.smallestTickSize)).toString(), + }; + } else { + we_pay = { + currency: quoteCurrency, + issuer: quoteIssuer, + value: Number(total.toPrecision(market.smallestTickSize)).toString(), + }; + we_get = { + currency: baseCurrency, + issuer: baseIssuer, + value: Number( + parseFloat(req.amount).toPrecision(market.smallestTickSize) + ).toString(), + }; + } + + if (we_pay.currency == 'XRP') { + we_pay.value = xrpToDrops(we_pay.value); + } + + if (we_get.currency == 'XRP') { + we_get.value = xrpToDrops(we_get.value); + } + + const offer: Transaction = { + TransactionType: 'OfferCreate', + Account: wallet.classicAddress, + TakerGets: we_pay.currency == 'XRP' ? we_pay.value : we_pay, + TakerPays: we_get.currency == 'XRP' ? we_get.value : we_get, + }; + + const { prepared, signed } = await this.submitTxn(offer, wallet); + + const currentTime = Date.now(); + const currentLedgerIndex = await this.getCurrentBlockNumber(); + + const order: Order = { + hash: prepared.Sequence ? prepared.Sequence : 0, + marketId: baseCurrency + '-' + quoteCurrency, + price: req.price, + amount: req.amount, + filledAmount: '0', + state: 'PENDING_OPEN', + tradeType: req.side, + orderType: 'LIMIT', + createdAt: currentTime, + createdAtLedgerIndex: currentLedgerIndex, + updatedAt: currentTime, + updatedAtLedgerIndex: currentLedgerIndex, + associatedTxns: [signed.hash], + associatedFills: [], + }; + + await this.trackOrder(wallet, order); + + return { txHash: signed.hash }; + } + + public async deleteOrder( + req: ClobDeleteOrderRequest + ): Promise<{ txHash: string }> { + const wallet = await this.getWallet(req.address); + const offer: Transaction = { + TransactionType: 'OfferCancel', + Account: wallet.classicAddress, + OfferSequence: parseInt(req.orderId), + }; + + const { signed } = await this.submitTxn(offer, wallet); + + let order = this.getOrder(wallet, req); + + if (order) { + order.state = 'PENDING_CANCEL'; + order.updatedAt = Date.now(); + order.updatedAtLedgerIndex = await this.getCurrentBlockNumber(); + order.associatedTxns.push(signed.hash); + } else { + order = { + hash: parseInt(req.orderId), + marketId: '', + price: '', + amount: '', + filledAmount: '', + state: 'PENDING_CANCEL', + tradeType: TradeType.UNKNOWN, + orderType: 'LIMIT', + createdAt: Date.now(), + createdAtLedgerIndex: await this.getCurrentBlockNumber(), + updatedAt: Date.now(), + updatedAtLedgerIndex: await this.getCurrentBlockNumber(), + associatedTxns: [signed.hash], + associatedFills: [], + }; + } + + await this.trackOrder(wallet, order); + + return { txHash: signed.hash }; + } + + public estimateGas(_req: NetworkSelectionRequest): { + gasPrice: number; + gasPriceToken: string; + gasLimit: number; + gasCost: number; + } { + return this.getFeeEstimate(); + } + + private async submitTxn(offer: Transaction, wallet: Wallet) { + while (this._isSubmittingTxn) { + await new Promise((resolve) => setTimeout(resolve, TXN_SUBMIT_DELAY)); + } + + this._isSubmittingTxn = true; + const prepared = await this._client.autofill(offer); + const signed = wallet.sign(prepared); + await this._client.submit(signed.tx_blob); + this._isSubmittingTxn = false; + return { prepared, signed }; + } + + private async getWallet(address: string) { + const wallet = await this._xrpl.getWallet(address); + return wallet; + } + + private async getOrderBookFromXRPL( + baseRequest: any, + quoteRequest: any, + limit: number + ) { + const orderbook_resp_ask: BookOffersResponse = await this._client.request({ + command: 'book_offers', + ledger_index: 'validated', + taker_gets: baseRequest, + taker_pays: quoteRequest, + limit, + }); + + const orderbook_resp_bid: BookOffersResponse = await this._client.request({ + command: 'book_offers', + ledger_index: 'validated', + taker_gets: quoteRequest, + taker_pays: baseRequest, + limit, + }); + + const asks = orderbook_resp_ask.result.offers; + const bids = orderbook_resp_bid.result.offers; + return { bids, asks }; + } + + private async getCurrentBlockNumber() { + return await this._client.getLedgerIndex(); + } + + private getFeeEstimate() { + const fee_estimate = this._xrpl.fee; + + return { + gasPrice: parseFloat(fee_estimate.median), + gasPriceToken: this._xrpl.nativeTokenSymbol, + gasLimit: parseFloat(this._client.maxFeeXRP), + gasCost: parseFloat(fee_estimate.median) * this._client.feeCushion, + }; + } + + private getOrder(wallet: Wallet, req: ClobDeleteOrderRequest) { + const orderTracker = OrderTracker.getInstance( + this.chain, + this.network, + wallet + ); + + return orderTracker.getOrder(parseInt(req.orderId)); + } + + private async trackOrder(wallet: Wallet, order: Order) { + const orderTracker = OrderTracker.getInstance( + this.chain, + this.network, + wallet + ); + + await orderTracker.addOrder(order); + } + + private async getMidPriceForMarket(market: MarketInfo) { + const orderbook = await this.getOrderBook(market, 1); + try { + const bestAsk = orderbook.sells[0]; + const bestBid = orderbook.buys[0]; + const midPrice = + (parseFloat(bestAsk.price) + parseFloat(bestBid.price)) / 2; + return midPrice; + } catch (error) { + // TODO: report this error + + return 0; + } + } +} diff --git a/src/connectors/xrpl/xrpl.types.ts b/src/connectors/xrpl/xrpl.types.ts new file mode 100644 index 0000000000..71db38ae42 --- /dev/null +++ b/src/connectors/xrpl/xrpl.types.ts @@ -0,0 +1,331 @@ +import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable'; +import { + BookOffer, + TransactionStream, + TransactionMetadata, + Transaction, +} from 'xrpl'; + +export type IMap = ImmutableMap; +export const IMap = ImmutableMap; +export type ISet = ImmutableSet; +export const ISet = ImmutableSet; + +export enum TradeType { + BUY = 'BUY', + SELL = 'SELL', + UNKNOWN = 'UNKNOWN', +} + +export enum OrderStatus { + OPEN = 'OPEN', + CANCELED = 'CANCELED', + FILLED = 'FILLED', + PARTIALLY_FILLED = 'PARTIALLY_FILLED', + PENDING_OPEN = 'PENDING_OPEN', + PENDING_CANCEL = 'PENDING_CANCEL', + FAILED = 'FAILED', + OFFER_EXPIRED_OR_UNFUNDED = 'OFFER_EXPIRED_OR_UNFUNDED', + UNKNOWN = 'UNKNOWN', +} + +export enum OrderType { + LIMIT = 'LIMIT', + PASSIVE = 'PASSIVE', + IOC = 'IOC', // Immediate or Cancel + FOK = 'FOK', // Fill or Kill + SELL = 'SELL', // Sell +} + +export enum TransactionIntentType { + OFFER_CREATE_FINALIZED = 'OfferCreateFinalized', + OFFER_CANCEL_FINALIZED = 'OfferCancelFinalized', + OFFER_PARTIAL_FILL = 'OfferPartialFill', + OFFER_FILL = 'OfferFill', + OFFER_EXPIRED_OR_UNFUNDED = 'OfferExpiredOrUnfunded', + UNKNOWN = 'UNKNOWN', +} + +export interface Token { + currency: string; + issuer: string; + value: string; +} + +export type GetMarketsRequest = + | Record + | { name: string } + | { names: string[] }; + +export interface GetMarketResponse { + name: string; + minimumOrderSize: number; + tickSize: number; + baseTransferRate: number; + quoteTransferRate: number; +} + +export interface Market { + marketId: string; + minimumOrderSize: number; + smallestTickSize: number; + baseTickSize: number; + quoteTickSize: number; + baseTransferRate: number; + quoteTransferRate: number; + baseIssuer: string; + quoteIssuer: string; + baseCurrency: string; + quoteCurrency: string; +} + +export type GetMarketsResponse = + | IMap + | GetMarketResponse; + +export type GetTickersRequest = + | Record + | { marketName: string } + | { marketNames: string[] }; + +export interface GetTickerResponse { + price: number; + timestamp: number; +} + +export type GetTickersResponse = + | IMap + | GetTickerResponse; + +export interface Ticker { + price: number; + timestamp: number; +} + +export interface GetOrderRequest { + sequence: number; + signature: string; +} + +export type GetOrdersRequest = + | Record + | { orders: GetOrderRequest[] }; + +export interface GetOrderResponse { + sequence: number; + status: OrderStatus; + signature: string; + transactionResult: string; +} + +export type GetOrdersResponse = Record; + +export type GetOrderBooksRequest = + | Record + | { marketName: string; limit: number } + | { marketNames: string[]; limit: number }; + +export interface GetOrderBookResponse { + market: GetMarketResponse; + topAsk: number; + topBid: number; + midPrice: number; + bids: BookOffer[]; + asks: BookOffer[]; + timestamp: number; +} + +export type GetOrderBooksResponse = + | IMap + | GetOrderBookResponse; + +export interface CreateOrderRequest { + walletAddress: string; + marketName: string; + side: TradeType; + price: number; + amount: number; + type?: OrderType; + sequence?: number; +} + +export interface CreateOrderResponse { + walletAddress: string; + marketName: string; + price: number; + amount: number; + side: TradeType; + status?: OrderStatus; + type?: OrderType; + fee?: number; + sequence: number; + orderLedgerIndex?: string; + signature?: string; + transactionResult?: string; +} + +export type CreateOrdersResponse = + | IMap + | CreateOrderResponse + | Record; + +export interface CancelOrderRequest { + walletAddress: string; + offerSequence: number; +} + +export type CancelOrdersRequest = + | Record + | { order: CancelOrderRequest } + | { orders: CancelOrderRequest[] }; + +export interface CancelOrderResponse { + walletAddress: string; + status?: OrderStatus; + signature?: string; + transactionResult?: string; +} + +export type CancelOrdersResponse = + | IMap + | CancelOrderResponse + | Record; + +export interface GetOpenOrderRequest { + marketName: string; + walletAddress: string; +} + +export interface GetOpenOrderResponse { + sequence: number; + marketName: string; + price: string; + amount: string; + side: TradeType; +} + +export type GetOpenOrdersResponse = + | any + | IMap> + | IMap + | GetOpenOrderResponse; + +export class XRPLishError extends Error {} + +export class MarketNotFoundError extends XRPLishError {} + +export interface PriceLevel { + price: string; + quantity: string; + timestamp: number; +} +export interface Orderbook { + buys: PriceLevel[]; + sells: PriceLevel[]; +} + +export interface Order { + hash: number; + marketId: string; + price: string; + amount: string; + filledAmount: string; + state: string; + tradeType: string; + orderType: string; + createdAt: number; + createdAtLedgerIndex: number; + updatedAt: number; + updatedAtLedgerIndex: number; + associatedTxns: string[]; + associatedFills: FillData[]; +} + +export interface InflightOrders { + [hash: number]: Order; +} + +export interface OrderLocks { + [key: number]: boolean; +} + +export interface AccountTransaction { + ledger_index: number; + meta: string | TransactionMetadata; + tx?: Transaction & ResponseOnlyTxInfo; + tx_blob?: string; + validated: boolean; +} + +export interface TransaformedAccountTransaction { + ledger_index: number; + meta: TransactionMetadata; + transaction: Transaction & ResponseOnlyTxInfo; + tx_blob?: string; + validated: boolean; +} + +export interface ResponseOnlyTxInfo { + date?: number; + hash?: string; + ledger_index?: number; + inLedger?: number; +} + +export interface TransactionIntent { + type: TransactionIntentType; + sequence?: number; + tx: TransactionStream | TransaformedAccountTransaction; + filledAmount?: string; + node?: Node; +} + +export interface FillData { + tradeId: string; + orderHash: number; + price: string; + quantity: string; + feeToken: string; + side: string; + fee: string; + timestamp: number; + type: string; +} + +type Node = CreatedNode | ModifiedNode | DeletedNode; + +export interface CreatedNode { + CreatedNode: { + LedgerEntryType: string; + LedgerIndex: string; + NewFields: { + [field: string]: unknown; + }; + }; +} +export interface ModifiedNode { + ModifiedNode: { + LedgerEntryType: string; + LedgerIndex: string; + FinalFields?: { + [field: string]: unknown; + }; + PreviousFields?: { + [field: string]: unknown; + }; + PreviousTxnID?: string; + PreviousTxnLgrSeq?: number; + }; +} +export interface DeletedNode { + DeletedNode: { + LedgerEntryType: string; + LedgerIndex: string; + FinalFields: { + [field: string]: unknown; + }; + PreviousFields?: { + [field: string]: unknown; + }; + }; +} diff --git a/src/connectors/xrpl/xrpl.utils.ts b/src/connectors/xrpl/xrpl.utils.ts new file mode 100644 index 0000000000..78c5f4008a --- /dev/null +++ b/src/connectors/xrpl/xrpl.utils.ts @@ -0,0 +1,114 @@ +import { InflightOrders, OrderLocks } from './xrpl.types'; +import { BookOffer, dropsToXrp } from 'xrpl'; +import { XRPL } from '../../chains/xrpl/xrpl'; + +export class OrderMutexManager { + private locks: OrderLocks = {}; + private orders: InflightOrders = {}; // orders to manage + + constructor(ordersToManage: InflightOrders) { + this.orders = ordersToManage; + + Object.keys(this.orders).forEach((hash) => { + this.locks[parseInt(hash)] = false; + }); + } + + // lock an order by hash + lock(hash: number) { + this.locks[hash] = true; + } + + // release an order by hash + release(hash: number) { + this.locks[hash] = false; + } + + // reset all locks + reset() { + Object.keys(this.orders).forEach((hash) => { + this.locks[parseInt(hash)] = false; + }); + } + + // add new orders to manage + addOrders(orders: InflightOrders) { + Object.keys(orders).forEach((hash) => { + this.orders[parseInt(hash)] = orders[parseInt(hash)]; + this.locks[parseInt(hash)] = false; + }); + } + + // remove orders from manage + removeOrders(orders: InflightOrders) { + Object.keys(orders).forEach((hash) => { + delete this.orders[parseInt(hash)]; + delete this.locks[parseInt(hash)]; + }); + } + + // update orders list and locks + updateOrders(orders: InflightOrders) { + this.orders = orders; + this.reset(); + } + + // get lock satus of an order by hash + isLocked(hash: number) { + return this.locks[hash]; + } +} + +export function getTakerGetsAmount(offer: BookOffer): string { + if (typeof offer.TakerGets === 'string') { + return dropsToXrp(offer.TakerGets); + } + + return offer.TakerGets.value; +} + +export function getTakerPaysAmount(offer: BookOffer): string { + if (typeof offer.TakerPays === 'string') { + return dropsToXrp(offer.TakerPays); + } + + return offer.TakerPays.value; +} + +export function getTakerGetsFundedAmount(offer: BookOffer): string { + if (typeof offer.taker_gets_funded === 'string') { + return dropsToXrp(offer.taker_gets_funded); + } + + if (!offer.taker_gets_funded) { + return '0'; + } + + return offer.taker_gets_funded.value; +} + +export function getTakerPaysFundedAmount(offer: BookOffer): string { + if (typeof offer.taker_pays_funded === 'string') { + return dropsToXrp(offer.taker_pays_funded); + } + + if (!offer.taker_pays_funded) { + return '0'; + } + + return offer.taker_pays_funded.value; +} + +export async function getsSequenceNumberFromTxn( + network: string, + TxnHash: string +): Promise { + const xrpl = XRPL.getInstance(network); + const txn = await xrpl.getTransaction(TxnHash); + + if (txn) { + return txn.result.Sequence; + } + + return undefined; +} diff --git a/src/network/network.controllers.ts b/src/network/network.controllers.ts index d1ca7b234d..75b6702f75 100644 --- a/src/network/network.controllers.ts +++ b/src/network/network.controllers.ts @@ -19,6 +19,7 @@ import { getInitializedChain, UnsupportedChainException, } from '../services/connection-manager'; +import { XRPL } from '../chains/xrpl/xrpl'; export async function getStatus( req: StatusRequest @@ -98,6 +99,11 @@ export async function getStatus( tezosConnections ? Object.values(tezosConnections) : [] ); + const xrplConnections = XRPL.getConnectedInstances(); + connections = connections.concat( + xrplConnections ? Object.values(xrplConnections) : [] + ); + const kujiraConnections = Kujira.getConnectedInstances(); connections = connections.concat( kujiraConnections ? Object.values(kujiraConnections) : [] diff --git a/src/services/base.ts b/src/services/base.ts index 7d152a7b50..b2049651c3 100644 --- a/src/services/base.ts +++ b/src/services/base.ts @@ -5,6 +5,9 @@ import { isFractionString, isFloatString } from './validators'; // the type of information source for tokens export type TokenListType = 'FILE' | 'URL'; +// the type of information source for markets +export type MarketListType = 'FILE' | 'URL'; + // represent a token any chain, it may require some work arounds export interface TokenInfo { address: string; diff --git a/src/services/connection-manager.ts b/src/services/connection-manager.ts index 18f6d87c31..58bc2df752 100644 --- a/src/services/connection-manager.ts +++ b/src/services/connection-manager.ts @@ -6,6 +6,7 @@ import { Harmony } from '../chains/harmony/harmony'; import { Polygon } from '../chains/polygon/polygon'; import { Xdc } from '../chains/xdc/xdc'; import { Tezos } from '../chains/tezos/tezos'; +import { XRPL, XRPLish } from '../chains/xrpl/xrpl'; import { MadMeerkat } from '../connectors/mad_meerkat/mad_meerkat'; import { Openocean } from '../connectors/openocean/openocean'; import { Pangolin } from '../connectors/pangolin/pangolin'; @@ -39,6 +40,7 @@ import { Plenty } from '../connectors/plenty/plenty'; import { Curve } from '../connectors/curve/curve'; import { Kujira } from '../chains/kujira/kujira'; import { KujiraCLOB } from '../connectors/kujira/kujira'; +import { XRPLCLOB } from '../connectors/xrpl/xrpl'; export type ChainUnion = | Algorand @@ -47,6 +49,7 @@ export type ChainUnion = | Nearish | Xdcish | Tezosish + | XRPLish | Kujira; export type Chain = T extends Algorand @@ -61,6 +64,8 @@ export type Chain = T extends Algorand ? Xdcish : T extends Tezosish ? Tezosish + : T extends XRPLish + ? XRPLish : T extends KujiraCLOB ? KujiraCLOB : never; @@ -122,6 +127,8 @@ export async function getChainInstance( connection = Xdc.getInstance(network); } else if (chain === 'tezos') { connection = Tezos.getInstance(network); + } else if (chain === 'xrpl') { + connection = XRPL.getInstance(network); } else if (chain === 'kujira') { connection = Kujira.getInstance(network); } else { @@ -139,6 +146,7 @@ export type ConnectorUnion = | CLOBish | Tinyman | Plenty + | XRPLCLOB | Curve | KujiraCLOB; @@ -156,6 +164,8 @@ export type Connector = T extends Uniswapish ? Tinyman : T extends Plenty ? Plenty + : T extends XRPLish + ? XRPLCLOB : T extends KujiraCLOB ? KujiraCLOB : never; @@ -206,6 +216,8 @@ export async function getConnector( connectorInstance = Tinyman.getInstance(network); } else if (chain === 'tezos' && connector === 'plenty') { connectorInstance = Plenty.getInstance(network); + } else if (chain === 'xrpl' && connector === 'xrpl') { + connectorInstance = XRPLCLOB.getInstance(chain, network); } else if (chain === 'kujira' && connector === 'kujira') { connectorInstance = KujiraCLOB.getInstance(chain, network); } else if ( diff --git a/src/services/schema/xrpl-schema.json b/src/services/schema/xrpl-schema.json new file mode 100644 index 0000000000..5c9b88d2cc --- /dev/null +++ b/src/services/schema/xrpl-schema.json @@ -0,0 +1,77 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "networks": { + "type": "object", + "patternProperties": { + "^\\w+$": { + "type": "object", + "properties": { + "nodeURL": { "type": "string" }, + "tokenListType": { "type": "string" }, + "tokenListSource": { "type": "string" }, + "marketListType": { "type": "string" }, + "marketListSource": { "type": "string" }, + "nativeCurrencySymbol": { "type": "string" } + }, + "required": [ + "nodeURL", + "tokenListType", + "tokenListSource", + "nativeCurrencySymbol" + ], + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "network": { "type": "string" }, + "requestTimeout": { "type": "integer" }, + "connectionTimeout": { "type": "integer" }, + "feeCushion": { "type": "number" }, + "maxFeeXRP": { "type": "string" }, + "orderDbPath": { "type": "string" }, + "maxLRUCacheInstances": { "type": "number" }, + "retry": { + "type": "object", + "required": ["all"], + "properties": { + "all": { + "type": "object", + "required": ["maxNumberOfRetries", "delayBetweenRetries"], + "properties": { + "maxNumberOfRetries": { "type": "integer" }, + "delayBetweenRetries": { + "type": "integer" + } + } + } + } + }, + "timeout": { + "type": "object", + "required": ["all"], + "properties": { + "all": { "type": "integer" } + } + }, + "parallel": { + "type": "object", + "required": ["all"], + "properties": { + "all": { + "type": "object", + "required": ["batchSize", "delayBetweenBatches"], + "properties": { + "batchSize": { "type": "integer" }, + "delayBetweenBatches": { + "type": "integer" + } + } + } + } + } + }, + "additionalProperties": false +} diff --git a/src/services/wallet/wallet.controllers.ts b/src/services/wallet/wallet.controllers.ts index 1877f24503..b666eb6e58 100644 --- a/src/services/wallet/wallet.controllers.ts +++ b/src/services/wallet/wallet.controllers.ts @@ -2,6 +2,7 @@ import fse from 'fs-extra'; import { Xdc } from '../../chains/xdc/xdc'; import { Cosmos } from '../../chains/cosmos/cosmos'; import { Tezos } from '../../chains/tezos/tezos'; +import { XRPL } from '../../chains/xrpl/xrpl'; import { Kujira } from '../../chains/kujira/kujira'; import { @@ -139,6 +140,12 @@ export async function addWallet( } else { throw new Error('Kujira wallet requires an account number.'); } + } else if (connection instanceof XRPL) { + address = connection.getWalletFromSeed(req.privateKey).classicAddress; + encryptedPrivateKey = await connection.encrypt( + req.privateKey, + passphrase + ); } if (address === undefined || encryptedPrivateKey === undefined) { @@ -168,7 +175,11 @@ export async function signMessage( if (req.chain === 'tezos') { const chain: Tezosish = await getInitializedChain(req.chain, req.network); const wallet = await chain.getWallet(req.address); - return { signature: (await wallet.signer.sign("0x03" + req.message)).sbytes.slice(4) }; + return { + signature: (await wallet.signer.sign('0x03' + req.message)).sbytes.slice( + 4 + ), + }; } else { const chain: Ethereumish = await getInitializedChain( req.chain, diff --git a/src/services/wallet/wallet.validators.ts b/src/services/wallet/wallet.validators.ts index 489d71a940..aed3ee0420 100644 --- a/src/services/wallet/wallet.validators.ts +++ b/src/services/wallet/wallet.validators.ts @@ -8,6 +8,10 @@ import { } from '../validators'; const { fromBase64 } = require('@cosmjs/encoding'); +import { + invalidXRPLPrivateKeyError, + isXRPLSeedKey, +} from '../../chains/xrpl/xrpl.validators'; export const invalidAlgorandPrivateKeyOrMnemonicError: string = 'The privateKey param is not a valid Algorand private key or mnemonic.'; @@ -62,7 +66,7 @@ export const isTezosPrivateKey = (str: string): boolean => { } catch { return false; } -} +}; // given a request, look for a key called privateKey that is an Ethereum private key export const validatePrivateKey: Validator = mkSelectingValidator( @@ -124,6 +128,11 @@ export const validatePrivateKey: Validator = mkSelectingValidator( invalidTezosPrivateKeyError, (val) => typeof val === 'string' && isTezosPrivateKey(val) ), + xrpl: mkValidator( + 'privateKey', + invalidXRPLPrivateKeyError, + (val) => typeof val === 'string' && isXRPLSeedKey(val) + ), kujira: mkValidator( 'privateKey', invalidKujiraPrivateKeyError, @@ -161,6 +170,7 @@ export const validateChain: Validator = mkValidator( val === 'cosmos' || val === 'binance-smart-chain' || val === 'tezos' || + val === 'xrpl' || val === 'kujira') ); diff --git a/src/templates/lists/xrpl_markets.json b/src/templates/lists/xrpl_markets.json new file mode 100644 index 0000000000..b385debb72 --- /dev/null +++ b/src/templates/lists/xrpl_markets.json @@ -0,0 +1,50 @@ +[ + { + "id": 1, + "marketId": "SOLO-XRP", + "baseIssuer": "rsoLo2S1kiGeCcn6hCUXVrCpGMWLrRrLZz", + "quoteIssuer": "", + "baseTokenID": 31, + "quoteTokenID": 0 + }, + { + "id": 2, + "marketId": "SOLO-USDC", + "baseIssuer": "rsoLo2S1kiGeCcn6hCUXVrCpGMWLrRrLZz", + "quoteIssuer": "rcEGREd8NmkKRE8GE424sksyt1tJVFZwu", + "baseTokenID": 31, + "quoteTokenID": 18465 + }, + { + "id": 3, + "marketId": "USDC-XRP", + "baseIssuer": "rcEGREd8NmkKRE8GE424sksyt1tJVFZwu", + "quoteIssuer": "", + "baseTokenID": 18465, + "quoteTokenID": 0 + }, + { + "id": 4, + "marketId": "USDC-USD", + "baseIssuer": "rcEGREd8NmkKRE8GE424sksyt1tJVFZwu", + "quoteIssuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "baseTokenID": 18465, + "quoteTokenID": 16603 + }, + { + "id": 5, + "marketId": "BTC-XRP", + "baseIssuer": "rchGBxcD1A1C2tdxF6papQYZ8kjRKMYcL", + "quoteIssuer": "", + "baseTokenID": 1381, + "quoteTokenID": 0 + }, + { + "id": 6, + "marketId": "BTC-USD", + "baseIssuer": "rchGBxcD1A1C2tdxF6papQYZ8kjRKMYcL", + "quoteIssuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "baseTokenID": 1381, + "quoteTokenID": 16603 + } +] diff --git a/src/templates/lists/xrpl_markets_devnet.json b/src/templates/lists/xrpl_markets_devnet.json new file mode 100644 index 0000000000..0637a088a0 --- /dev/null +++ b/src/templates/lists/xrpl_markets_devnet.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/src/templates/lists/xrpl_markets_testnet.json b/src/templates/lists/xrpl_markets_testnet.json new file mode 100644 index 0000000000..806f37894e --- /dev/null +++ b/src/templates/lists/xrpl_markets_testnet.json @@ -0,0 +1,34 @@ +[ + { + "id": 1, + "marketId": "SOLO-XRP", + "baseIssuer": "rHZwvHEs56GCmHupwjA4RY7oPA3EoAJWuN", + "quoteIssuer": "", + "baseTokenID": 3, + "quoteTokenID": 0 + }, + { + "id": 2, + "marketId": "SOLO-USD", + "baseIssuer": "rHZwvHEs56GCmHupwjA4RY7oPA3EoAJWuN", + "quoteIssuer": "rh8LssQyeBdEXk7Zv86HxHrx8k2R2DBUrx", + "baseTokenID": 3, + "quoteTokenID": 2 + }, + { + "id": 3, + "marketId": "USD-XRP", + "baseIssuer": "rh8LssQyeBdEXk7Zv86HxHrx8k2R2DBUrx", + "quoteIssuer": "", + "baseTokenID": 2, + "quoteTokenID": 0 + }, + { + "id": 4, + "marketId": "USD-VND", + "baseIssuer": "rh8LssQyeBdEXk7Zv86HxHrx8k2R2DBUrx", + "quoteIssuer": "rh8LssQyeBdEXk7Zv86HxHrx8k2R2DBUrx", + "baseTokenID": 2, + "quoteTokenID": 1 + } +] diff --git a/src/templates/lists/xrpl_tokens.json b/src/templates/lists/xrpl_tokens.json new file mode 100644 index 0000000000..2cf5cadba0 --- /dev/null +++ b/src/templates/lists/xrpl_tokens.json @@ -0,0 +1,12378 @@ +[ + { + "id": 0, + "code": "XRP", + "issuer": "", + "title": "XRP", + "trustlines": -1, + "placeInTop": 0 + }, + { + "id": 31, + "code": "SOLO", + "issuer": "rsoLo2S1kiGeCcn6hCUXVrCpGMWLrRrLZz", + "title": "Sologenic", + "trustlines": 288976, + "placeInTop": 1 + }, + { + "id": 16602, + "code": "CSC", + "issuer": "rCSCManTZ8ME9EoLrSHHYKW8PPwWMgkwr", + "title": "CasinoCoin", + "trustlines": 54154, + "placeInTop": 2 + }, + { + "id": 18190, + "code": "CORE", + "issuer": "rcoreNywaoz2ZCQ8Lg2EbSLnGuRBmun6D", + "title": "Coreum", + "trustlines": 65817, + "placeInTop": 3 + }, + { + "id": 248, + "code": "ELS", + "issuer": "rHXuEaRYnnJHbDeuBH5w8yPh5uwNVh5zAg", + "title": "Elysian", + "trustlines": 109452, + "placeInTop": 4 + }, + { + "id": 16605, + "code": "Equilibrium", + "issuer": "rpakCr61Q92abPXJnVboKENmpKssWyHpwu", + "title": "Equilibrium", + "trustlines": 34827, + "placeInTop": 5 + }, + { + "id": 17073, + "code": "BTC", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "title": "Bitstamp", + "trustlines": 18187, + "placeInTop": 6 + }, + { + "id": 16603, + "code": "USD", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "title": "Gatehub", + "trustlines": 110980, + "placeInTop": 7 + }, + { + "id": 17074, + "code": "USD", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "title": "Bitstamp", + "trustlines": 26696, + "placeInTop": 8 + }, + { + "id": 16818, + "code": "XPUNK", + "issuer": "rHEL3bM4RFsvF8kbQj3cya8YiDvjoEmxLq", + "title": "XRPL PUNKS", + "trustlines": 12074, + "placeInTop": 9 + }, + { + "id": 103, + "code": "VGB", + "issuer": "rhcyBrowwApgNonehKBj8Po5z4gTyRknaU", + "title": "Vagabond VGB", + "trustlines": 56661, + "placeInTop": 10 + }, + { + "id": 182, + "code": "RPR", + "issuer": "r3qWgpz2ry3BhcRJ8JE6rxM8esrfhuKp4R", + "title": "The Reaper", + "trustlines": 24140, + "placeInTop": 11 + }, + { + "id": 18542, + "code": "xSPECTAR", + "issuer": "rh5jzTCdMRCVjQ7LT6zucjezC47KATkuvv", + "title": "xSPECTAR NFT", + "trustlines": 9868, + "placeInTop": 12 + }, + { + "id": 16826, + "code": "BAY", + "issuer": "r4uq8urnYrT6LnZaadPyusyKCS68HVJtRn", + "title": "Bored Apes XRP Club", + "trustlines": 8247, + "placeInTop": 13 + }, + { + "id": 17296, + "code": "OXP", + "issuer": "rrno7Nj4RkFJLzC4nRaZiLF5aHwcTVon3d", + "title": "onXRP", + "trustlines": 9851, + "placeInTop": 14 + }, + { + "id": 16726, + "code": "ADV", + "issuer": "rPneN8WPHZJaMT9pF4Ynyyq4pZZZSeTuHu", + "title": "AdvisorBid", + "trustlines": 10454, + "placeInTop": 15 + }, + { + "id": 17363, + "code": "xBIBLx", + "issuer": "rnH9o6qdym34K293Pq3FZp5Ko7SpZxEbeG", + "title": "Bibliomp", + "trustlines": 4441, + "placeInTop": 16 + }, + { + "id": 16600, + "code": "EUR", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "title": "Gatehub", + "trustlines": 85461, + "placeInTop": 17 + }, + { + "id": 225, + "code": "XRdoge", + "issuer": "rLqUC2eCPohYvJCEBJ77eCCqVL2uEiczjA", + "title": "XRdoge Labs", + "trustlines": 26611, + "placeInTop": 18 + }, + { + "id": 99, + "code": "XDX", + "issuer": "rMJAXYsbNzhwp7FfYnAsYP5ty3R9XnurPo", + "title": "D.P.MonksFinance LTD", + "trustlines": 28866, + "placeInTop": 19 + }, + { + "id": 18469, + "code": "STX", + "issuer": "rSTAYKxF2K77ZLZ8GoAwTqPGaphAqMyXV", + "title": "StaykX", + "trustlines": 12098, + "placeInTop": 20 + }, + { + "id": 369, + "code": "xSTIK", + "issuer": "rJNV9i4Q6zvRhpE2zjxgkvff3eGHQohZht", + "title": "xSTIK Official", + "trustlines": 24267, + "placeInTop": 21 + }, + { + "id": 18621, + "code": "XLIST", + "issuer": "rNy8hFXoXEaJwkiT6U6ED5CWsfZHELNcnr", + "title": "XList", + "trustlines": 4286, + "placeInTop": 22 + }, + { + "id": 374, + "code": "xCoin", + "issuer": "rXCoYSUnkpygdtfpz3Df8dKQuRZjM9UFi", + "title": "XRPLCOINS", + "trustlines": 27151, + "placeInTop": 23 + }, + { + "id": 17807, + "code": "ShibaNFT", + "issuer": "rnRXAnVZTyattZXEpKpgTyvdm17DpjrzSZ", + "title": "ShibaNFT OFFICIAL", + "trustlines": 23572, + "placeInTop": 24 + }, + { + "id": 375, + "code": "OCW", + "issuer": "rK9DrarGKnVEo2nYp5MfVRXRYf5yRX3mwD", + "title": "OnChain Whales", + "trustlines": 19078, + "placeInTop": 25 + }, + { + "id": 16660, + "code": "XBLADE", + "issuer": "rfVTbKsRgyurPddRiWaReuiK9Tvms8XGj1", + "title": "XBLADE", + "trustlines": 7449, + "placeInTop": 26 + }, + { + "id": 250, + "code": "Greyhound", + "issuer": "rJWBaKCpQw47vF4rr7XUNqr34i4CoXqhKJ", + "title": "Greyhound", + "trustlines": 10211, + "placeInTop": 27 + }, + { + "id": 18606, + "code": "BPM", + "issuer": "rDBMvpjV6DoWvr3LqMUG8JBgd4QbBoU1E2", + "title": "BPM Wallet", + "trustlines": 2910, + "placeInTop": 28 + }, + { + "id": 16723, + "code": "JUNK", + "issuer": "r4pDJ7bT1rANe9nAdFR9pyVRwtJZQUEFpj", + "title": "Junkie", + "trustlines": 6455, + "placeInTop": 29 + }, + { + "id": 378, + "code": "FKM", + "issuer": "raivZznHUty6vxDYiQD8K5KgwvPKwjpruz", + "title": "FKM", + "trustlines": 11620, + "placeInTop": 30 + }, + { + "id": 16955, + "code": "SGB", + "issuer": "rctArjqVvTHihekzDeecKo6mkTYTUSBNc", + "title": "GateHub SGB", + "trustlines": 23121, + "placeInTop": 31 + }, + { + "id": 17839, + "code": "LUC", + "issuer": "rsygE5ynt2iSasscfCCeqaGBGiFKMCAUu7", + "title": "Lucretius", + "trustlines": 31076, + "placeInTop": 32 + }, + { + "id": 85, + "code": "RDX", + "issuer": "rQa3LW1Au4GxGHzDBkCMKuPcn326w4Wcj2", + "title": "D.P.MonksFinance LTD", + "trustlines": 17418, + "placeInTop": 33 + }, + { + "id": 18740, + "code": "XRDC", + "issuer": "rcLASSiCq8LWcymCHaCgK19QMEvUspuRM", + "title": "XRdogeClassic", + "trustlines": 3319, + "placeInTop": 34 + }, + { + "id": 16724, + "code": "LOX", + "issuer": "rLLJvh6bwj2eTYwzLL484AW6EyH4rdZqWZ", + "title": "LoxNetwork", + "trustlines": 13716, + "placeInTop": 35 + }, + { + "id": 16849, + "code": "HUGETITS", + "issuer": "rEKKMW3MDVgrjPdcJLx49KEhF9ATEQwzPy", + "trustlines": 5454, + "placeInTop": 36 + }, + { + "id": 12, + "code": "CLUB", + "issuer": "r9pAKbAMx3wpMAS9XvvDzLYppokfKWTSq4", + "title": "Club589", + "trustlines": 7113, + "placeInTop": 37 + }, + { + "id": 16735, + "code": "XMEN", + "issuer": "rwc4q24X5Ui76v72WWaNFozBLoZiPj3oKV", + "title": "VerseX", + "trustlines": 10504, + "placeInTop": 38 + }, + { + "id": 16793, + "code": "IGC", + "issuer": "raP6XZypcFR1WkDzaKjv91FtYRCURvePWW", + "title": "iHunt4", + "trustlines": 5514, + "placeInTop": 39 + }, + { + "id": 16685, + "code": "Xoge", + "issuer": "rJMtvf5B3GbuFMrqybh5wYVXEH4QE8VyU1", + "title": "Xoge", + "trustlines": 17536, + "placeInTop": 40 + }, + { + "id": 212, + "code": "XRSHIB", + "issuer": "rN3EeRSxh9tLHAUDmL7Chh3vYYoUafAyyM", + "title": "XR SHIB", + "trustlines": 25681, + "placeInTop": 41 + }, + { + "id": 17058, + "code": "ETC", + "issuer": "rDAN8tzydyNfnNf2bfUQY6iR96UbpvNsze", + "title": "GateHub ETC", + "trustlines": 22783, + "placeInTop": 42 + }, + { + "id": 37, + "code": "xToadz", + "issuer": "rpRW1FumRWhhaLmoYwS1SqEXsnCccvpsAU", + "title": "xToadz & sToadz", + "trustlines": 10227, + "placeInTop": 43 + }, + { + "id": 289, + "code": "xShroom", + "issuer": "rHqLei9xJch13JioYHsDUwWJoz81QQh6LU", + "title": "xShrooms", + "trustlines": 4048, + "placeInTop": 44 + }, + { + "id": 187, + "code": "XGBL", + "issuer": "rMy6sCaDVF1C2BT3qmNG6kgjVDZqZ74uoF", + "title": "Xungible", + "trustlines": 24545, + "placeInTop": 45 + }, + { + "id": 16598, + "code": "CX1", + "issuer": "rKk7mu1dNB25fsPEJ4quoQd5B8QmaxewKi", + "title": "ChorusX", + "trustlines": 60567, + "placeInTop": 46 + }, + { + "id": 18946, + "code": "XSP", + "issuer": "rPUNKXyoE6zZB3nRSTuU7DoUKiQfi8KeK8", + "title": "Standard Punks", + "trustlines": 14368, + "placeInTop": 47 + }, + { + "id": 18789, + "code": "RLT", + "issuer": "rUetS7kbVYJZ76za5ywa1DgViNZMgT9Bvq", + "title": "Rocket Launch", + "trustlines": 5520, + "placeInTop": 48 + }, + { + "id": 292, + "code": "xAliens", + "issuer": "rDbAT7ZnkBBxKYL8myUY68c1chaKLBbNKw", + "trustlines": 4801, + "placeInTop": 49 + }, + { + "id": 18985, + "code": "CHP", + "issuer": "rhFNUEAKyXZmJHsnfJvH8hM12Ydk2icEof", + "title": "Chop Chop", + "trustlines": 10885, + "placeInTop": 50 + }, + { + "id": 16646, + "code": "MLD", + "issuer": "rhJYDuVMQxabTyiWuHQkQyDxr6uZEdpv5u", + "title": "Hurrian", + "trustlines": 28844, + "placeInTop": 51 + }, + { + "id": 16792, + "code": "XGOLD", + "issuer": "r4XSSBVGENvgUrZFijX8xvsJtp9Mi2UPz9", + "title": "XGOLD", + "trustlines": 5634, + "placeInTop": 51 + }, + { + "id": 251, + "code": "FSE", + "issuer": "rs1MKY54miDtMFEGyNuPd3BLsXauFZUSrj", + "title": "strategyengine", + "trustlines": 32019, + "placeInTop": 52 + }, + { + "id": 171, + "code": "TRSRY", + "issuer": "rLBnhMjV6ifEHYeV4gaS6jPKerZhQddFxW", + "title": "TREASURY XRPL", + "trustlines": 28380, + "placeInTop": 53 + }, + { + "id": 299, + "code": "XFLOKI", + "issuer": "rUtXeAXonpFpgKubAa7LxcLd7NFep92T1t", + "title": "XFLOKI", + "trustlines": 13100, + "placeInTop": 54 + }, + { + "id": 16662, + "code": "SwissTech", + "issuer": "raq7pGaYrLZRa88v6Py9V5oWMYEqPYr8Tz", + "trustlines": 20271, + "placeInTop": 55 + }, + { + "id": 89, + "code": "XVR", + "issuer": "rRCA6gnPkvpKmWwfcYxHQ845gFQ5ThYQe", + "title": "VerseX - $XMEN $XVR", + "trustlines": 4971, + "placeInTop": 56 + }, + { + "id": 18693, + "code": "XWAR", + "issuer": "rJAm3vMSiwCZHxLygaTdmiqCUG8YeSJFVy", + "trustlines": 4046, + "placeInTop": 57 + }, + { + "id": 16668, + "code": "Nerian", + "issuer": "rGEekk1PRyozC1ZEZCXL7EZcko4rrrETGh", + "title": "Nerian", + "trustlines": 9994, + "placeInTop": 58 + }, + { + "id": 16635, + "code": "SmartNFT", + "issuer": "rf8dxyFrYWEcUQAM7QXdbbtcRPzjvoQybK", + "title": "SmartNFT", + "trustlines": 18054, + "placeInTop": 59 + }, + { + "id": 16621, + "code": "SEC", + "issuer": "rDN4Ux1WFJJsPCdqdfZgrDZ2icxdAmg2w", + "title": "SEC Coin", + "trustlines": 31347, + "placeInTop": 60 + }, + { + "id": 16725, + "code": "SmartLOX", + "issuer": "rBdZkMKuPnzYVVkyL2DrQKV3DsYt5PPVRh", + "title": "SmartLOX", + "trustlines": 13728, + "placeInTop": 61 + }, + { + "id": 165, + "code": "XSQUAD", + "issuer": "roBYiFtZsTRpWEUw6TtpUCwZCfjcQeRBg", + "trustlines": 11470, + "placeInTop": 62 + }, + { + "id": 16609, + "code": "Schmeckles", + "issuer": "rPxw83ZP6thv7KmG5DpAW4cDW55DZRZ9wu", + "title": "Schmeckles", + "trustlines": 15829, + "placeInTop": 63 + }, + { + "id": 17, + "code": "XQK", + "issuer": "rHKrPGdpaqNRqRvmsiqQhD6azqc4npWoLC", + "title": "XQuake", + "trustlines": 25875, + "placeInTop": 64 + }, + { + "id": 17867, + "code": "$XRPLedgerETF", + "issuer": "raChAW5DVscGKimsCFLhHREpD86NsLF74Z", + "title": "XRPL ETF", + "trustlines": 8998, + "placeInTop": 65 + }, + { + "id": 269, + "code": "FCX", + "issuer": "rwSgqza9DUzr8oPDkJz8xUbPbaxAyoeLus", + "title": "FCX Focus", + "trustlines": 14769, + "placeInTop": 66 + }, + { + "id": 17062, + "code": "BCH", + "issuer": "rcyS4CeCZVYvTiKcxj6Sx32ibKwcDHLds", + "title": "GateHub BCH", + "trustlines": 15477, + "placeInTop": 66 + }, + { + "id": 18994, + "code": "Sanctum", + "issuer": "rNcqT1tds4vdroichNKuTh3Ppd8KAdFHnN", + "title": "Sanctum \u26a1\ufe0f", + "trustlines": 12800, + "placeInTop": 67 + }, + { + "id": 16729, + "code": "MONKEE", + "issuer": "rG5tVG4yoGvMTKiFEEEFpjG3qj2tGMP44o", + "title": "MONKEE MONKEE | NFT GAME", + "trustlines": 5446, + "placeInTop": 68 + }, + { + "id": 16823, + "code": "XDUDE", + "issuer": "rU5LE7X6yyu9DuHsLdHhWSiUVTgpyRK1vz", + "title": "XDUDE", + "trustlines": 5411, + "placeInTop": 69 + }, + { + "id": 18836, + "code": "Alpha", + "issuer": "rT8svWEMW3n5XTgezHEqpRdkuMnTafUfS", + "title": "Alpha Shares", + "trustlines": 5012, + "placeInTop": 70 + }, + { + "id": 18555, + "code": "XLoyalitY", + "issuer": "rfQNEfqLQc5L34rS92Xh5nVtk9NVHbv4Gj", + "title": "XLoyalitY", + "trustlines": 3228, + "placeInTop": 71 + }, + { + "id": 18880, + "code": "MetaLOX", + "issuer": "rDkjv8oQrgzHjjwZNnFAjWWrhRJgg6g56T", + "title": "MetaLOX", + "trustlines": 3224, + "placeInTop": 72 + }, + { + "id": 16631, + "code": "DFI", + "issuer": "rUY6tjGN8PJDVyVFLztRZLmPZ8uTBUfa2Z", + "title": "Denarii", + "trustlines": 6278, + "placeInTop": 73 + }, + { + "id": 16671, + "code": "XBOT", + "issuer": "rn9SkVczEzWQ3siieX7PcBVYpbRPRGbTgq", + "title": "X BOT CLUB", + "trustlines": 6532, + "placeInTop": 74 + }, + { + "id": 18406, + "code": "xTREME", + "issuer": "rwzfKxHPyzBbGidViMB9bw86WDFSFwMW9J", + "title": "XtremeXRPL", + "trustlines": 7951, + "placeInTop": 75 + }, + { + "id": 118, + "code": "NVL", + "issuer": "r458JvSEmmPwrRbEtmrHvWsGqZjq8jK6aE", + "title": "Northern VoIP NVL", + "trustlines": 13452, + "placeInTop": 76 + }, + { + "id": 181, + "code": "XParrot", + "issuer": "r3hmy4JpSHPWuomNsGtCkKrCqALakDAJiJ", + "title": "XParrots Official", + "trustlines": 9379, + "placeInTop": 77 + }, + { + "id": 16742, + "code": "XBAE", + "issuer": "rGc7CTU22AbPg8drYWTYsdGVk6nfssSPBK", + "title": "CLUBXBAE", + "trustlines": 4619, + "placeInTop": 78 + }, + { + "id": 18828, + "code": "xMAGIC", + "issuer": "rBHdammEERq7nxvHkzRzCUu872k3uQYVvg", + "title": "MAGICAL FINANCE", + "trustlines": 23411, + "placeInTop": 79 + }, + { + "id": 22, + "code": "XMETA", + "issuer": "r3XwJ1hr1PtbRvbhuUkybV6tmYzzA11WcB", + "title": "XMETA", + "trustlines": 30142, + "placeInTop": 80 + }, + { + "id": 17802, + "code": "TPR", + "issuer": "rht98AstPWmLPQMrwd9YDrcDoTjw9Tiu4B", + "title": "Tipper", + "trustlines": 17633, + "placeInTop": 81 + }, + { + "id": 18810, + "code": "XPHO", + "issuer": "rsVZrh3cvisTSHFcEZqPK1ioRzxbeG4PBk", + "title": "XRPhone", + "trustlines": 8958, + "placeInTop": 82 + }, + { + "id": 16904, + "code": "LXA", + "issuer": "rMa6n3DhTqwDGwU6ZquX1iSuaY1tCNLziY", + "title": "LamboXapes", + "trustlines": 6332, + "placeInTop": 83 + }, + { + "id": 18943, + "code": "SSM", + "issuer": "rPmrbwPKweofumw3fNBaoGdWDSc6wDKwKd", + "title": "FK\u20a5", + "trustlines": 4462, + "placeInTop": 84 + }, + { + "id": 16869, + "code": "XFLOKIs", + "issuer": "rKKDTqx8Lxw2sf2tUgNR81rvhRDhv5kFpz", + "title": "XFLOKI", + "trustlines": 6183, + "placeInTop": 85 + }, + { + "id": 277, + "code": "HADA", + "issuer": "rsR5JSisuXsbipP6sGdKdz5agjxn8BhHUC", + "title": "HADA Coin", + "trustlines": 7686, + "placeInTop": 86 + }, + { + "id": 16941, + "code": "HADALITE", + "issuer": "rHiPGSMBbzDGpoTPmk2dXaTk12ZV1pLVCZ", + "title": "HADALITE", + "trustlines": 8248, + "placeInTop": 87 + }, + { + "id": 116, + "code": "HCATS", + "issuer": "rGomRdjcf3e5zW5qjD7KU6YZmWbAk8u3hp", + "title": "XRPL HappyCats", + "trustlines": 7065, + "placeInTop": 88 + }, + { + "id": 18623, + "code": "JANGA", + "issuer": "r97C2XF4S5yzL2FzvXjdsyfYnswS4ee8TR", + "title": "Leo King\u2019s \ud83d\udc51 NFT", + "trustlines": 7120, + "placeInTop": 89 + }, + { + "id": 16739, + "code": "PARC", + "issuer": "rE42R1mbjGtMzzFTL5aqpbTrj3TDVq71jo", + "title": "Pixel Ape Rowboat Club", + "trustlines": 11880, + "placeInTop": 90 + }, + { + "id": 18139, + "code": "XRAIN", + "issuer": "rh3tLHbXwZsp7eciw2Qp8g7bN9RnyGa2pF", + "title": "XRPL RAINFOREST / $XRAIN", + "trustlines": 4529, + "placeInTop": 90 + }, + { + "id": 16636, + "code": "editions", + "issuer": "rfXwi3SqywQ2gSsvHgfdVsyZdTVM15BG7Z", + "title": "Editions", + "trustlines": 28590, + "placeInTop": 91 + }, + { + "id": 363, + "code": "GZX", + "issuer": "rNgsoCk6mjBq5jcqitBpg1gdfYhKajXsM2", + "title": "GreenZoneX", + "trustlines": 10026, + "placeInTop": 92 + }, + { + "id": 145, + "code": "TALENT", + "issuer": "r92SQCuWhYoB4w2UnKU7PKj4Mh7jSyemrH", + "title": "TalentChain", + "trustlines": 15209, + "placeInTop": 93 + }, + { + "id": 24, + "code": "XZillas", + "issuer": "rhwVLo1ckgcGSD6j7bF7BCPjuR3tshjbVM", + "title": "XZilla NFTs", + "trustlines": 11613, + "placeInTop": 93 + }, + { + "id": 16838, + "code": "Xpossum", + "issuer": "rfQr7LLaNvG93A3e2h6tjub3pi2oNTbvMA", + "title": "XRPL Awesome Possum", + "trustlines": 2704, + "placeInTop": 93 + }, + { + "id": 234, + "code": "XRPanda", + "issuer": "r9uQt7Y34SwSyKqdb5sMmAqk37rh3Y4V7", + "title": "XRPanda", + "trustlines": 10491, + "placeInTop": 94 + }, + { + "id": 16604, + "code": "Calorie", + "issuer": "rNqGa93B8ewQP9mUwpwqA19SApbf62U7PY", + "title": "Calorie Token", + "trustlines": 24080, + "placeInTop": 95 + }, + { + "id": 371, + "code": "LUSD", + "issuer": "rfL4Sci2ag5hhkpDuqtWYov6j3mshVWLgU", + "title": "Limited Currency", + "trustlines": 12638, + "placeInTop": 96 + }, + { + "id": 183, + "code": "NET", + "issuer": "rHi8oNeNe6JsKTaBbfhrQdEfDXHGhBcTXQ", + "title": "ZanyClub", + "trustlines": 7596, + "placeInTop": 96 + }, + { + "id": 18801, + "code": "OVX", + "issuer": "rDsvn6aJG4YMQdHnuJtP9NLrFp18JYTJUf", + "title": "onXRP", + "trustlines": 3056, + "placeInTop": 97 + }, + { + "id": 18897, + "code": "ArcX", + "issuer": "rHJUjSCYcgzF4CiYvi3UVdvXGbtXGJ6Fmz", + "title": "Arcade X (ARC-X)", + "trustlines": 1921, + "placeInTop": 98 + }, + { + "id": 16942, + "code": "DUCK", + "issuer": "rT5pAVAokKezWrjqnMBF3G8ah4fxVWVVx", + "title": "DuckRocket", + "trustlines": 8179, + "placeInTop": 99 + }, + { + "id": 16754, + "code": "SeagullCoin", + "issuer": "rnqiA8vuNriU9pqD1ZDGFH8ajQBL25Wkno", + "title": "Bored Seagull Club", + "trustlines": 7105, + "placeInTop": 99 + }, + { + "id": 16, + "code": "XWhales", + "issuer": "rw2LTTiDKAWMZeeNwvhxoYHMaCYMJretRR", + "trustlines": 10160, + "placeInTop": 100 + }, + { + "id": 324, + "code": "MLN", + "issuer": "rw5nJ4E54qtJYdX8WW6KeSaZjg67rGCR4K", + "title": "MLNToken", + "trustlines": 13673, + "placeInTop": 100 + }, + { + "id": 168, + "code": "xGoblin", + "issuer": "rpBCGo3e3cKqHoxjghK8AUeWYK2awGA6fB", + "title": "xGoblin", + "trustlines": 6357, + "placeInTop": 100 + }, + { + "id": 136, + "code": "XRSWAN", + "issuer": "rUHoc9nQyZzahE5rq26QHkvBmnvCEoPAhZ", + "title": "XRSwan", + "trustlines": 6414, + "placeInTop": 105 + }, + { + "id": 33, + "code": "XWWP", + "issuer": "roDdiwDhPUs8PVxq3S6buGSgNSmfVu9Xg", + "title": "XWWPlanes", + "trustlines": 6123, + "placeInTop": 108 + }, + { + "id": 241, + "code": "CCN", + "issuer": "rG1bDjT25WyvPz757YC9NqdRKyz9ywF8e8", + "title": "CollegeCoinNetwork", + "trustlines": 17205, + "placeInTop": 109 + }, + { + "id": 16752, + "code": "AFA", + "issuer": "ratAFAXeeKaVuAxuWB9W1LuXD5m7Aqf2BH", + "trustlines": 3206, + "placeInTop": 111 + }, + { + "id": 18275, + "code": "EMBRS", + "issuer": "rPbKMFvHbdEGBog98UjZXRdUx37MFKMfxB", + "title": "Quarter Onion Games", + "trustlines": 5207, + "placeInTop": 112 + }, + { + "id": 16732, + "code": "XRPitbull", + "issuer": "rfGDNXbLExX5BjktQYFgY4kfkK8mNzmuqJ", + "title": "XRPitbull", + "trustlines": 4364, + "placeInTop": 113 + }, + { + "id": 18384, + "code": "XRCS", + "issuer": "rn2aUSJ3mwt72pP4jx8JDyq9ipt9itDqcb", + "title": "XRCS", + "trustlines": 11934, + "placeInTop": 114 + }, + { + "id": 302, + "code": "FAKTURY", + "issuer": "rNwBNkHz3ZAnx77XFjGR8nRnZHw4gKgmpr", + "title": "FAKT\u00dcRY", + "trustlines": 3375, + "placeInTop": 115 + }, + { + "id": 16715, + "code": "DBX", + "issuer": "rHLJNqxCoPXdm4CnLd3w63ZFRqAUU2U4vS", + "title": "Dragonites X", + "trustlines": 19147, + "placeInTop": 116 + }, + { + "id": 261, + "code": "CNFT", + "issuer": "rUte5RZgB68nEU5QfjfM8qD6HtmKo5ebqo", + "title": "CollegeCoinNetwork / XBear NFTs", + "trustlines": 5555, + "placeInTop": 117 + }, + { + "id": 18137, + "code": "XCC", + "issuer": "rKuuRSQM2pTtv8ZrhQbU6kBgusCD79cem3", + "title": "X Charity Club", + "trustlines": 14433, + "placeInTop": 118 + }, + { + "id": 18007, + "code": "SNUB", + "issuer": "rNCRr79JC8YcA8pG4VAzhrshYxahKCodnX", + "title": "SnubNetwork", + "trustlines": 12879, + "placeInTop": 119 + }, + { + "id": 18419, + "code": "UtiliteX", + "issuer": "rKDsnVfFMzdqrU8Bqno37d29L8ZW3hvrf8", + "title": "TREASURY XRPL", + "trustlines": 7440, + "placeInTop": 120 + }, + { + "id": 95, + "code": "TGO", + "issuer": "rTGoNeK6vpu28U2oE5tiqhH3x8z2jBhxv", + "title": "ThingsGoOnline", + "trustlines": 7452, + "placeInTop": 121 + }, + { + "id": 18368, + "code": "GiezwaCoin", + "issuer": "r1taMrSAWRWJkaLhyCpPTnVj3qQmngzvN", + "title": "GiezwaCoin", + "trustlines": 9365, + "placeInTop": 122 + }, + { + "id": 17799, + "code": "xDREAMS", + "issuer": "raJt8azeqGixW8D1xSNLrELJu2m8W9EAit", + "title": "xDREAMS", + "trustlines": 4235, + "placeInTop": 123 + }, + { + "id": 16867, + "code": "XTRUMP", + "issuer": "rhvxJ9FjU1QCinoQStNkoZASbjqfBF7LN1", + "title": "XTRUMP", + "trustlines": 9761, + "placeInTop": 124 + }, + { + "id": 283, + "code": "PALEOCOIN", + "issuer": "rPfuLd1XmVyxkggAiT9fpLQU81GLb6UDZg", + "title": "Paleocoin", + "trustlines": 11851, + "placeInTop": 125 + }, + { + "id": 18590, + "code": "xBay", + "issuer": "rDVvK7xd2M6ZJr9a8suURWLqAeg7FyoDKT", + "title": "xBay", + "trustlines": 11993, + "placeInTop": 126 + }, + { + "id": 161, + "code": "xMochi", + "issuer": "rPaC5HFXToBuqHjSgjhmJaMejrF6DHRXKL", + "title": "xMochiDonuts", + "trustlines": 6718, + "placeInTop": 127 + }, + { + "id": 18935, + "code": "AEN", + "issuer": "rwuBxcFaUAEVYVDZvXvDXpHkEKoE8Zy1KX", + "trustlines": 10359, + "placeInTop": 128 + }, + { + "id": 1, + "code": "MRM", + "issuer": "rNjQ9HZYiBk1WhuscDkmJRSc3gbrBqqAaQ", + "title": "Mr. Mole", + "trustlines": 17995, + "placeInTop": 129 + }, + { + "id": 16787, + "code": "SSE", + "issuer": "rMDQTunsjE32sAkBDbwixpWr8TJdN5YLxu", + "title": "strategyengine", + "trustlines": 11438, + "placeInTop": 130 + }, + { + "id": 17297, + "code": "XRPLT", + "issuer": "rnSW2PRsGk5gX1q7xT5m3iyqrcR62yN9et", + "title": "XRPLToken", + "trustlines": 5175, + "placeInTop": 131 + }, + { + "id": 18833, + "code": "UCB", + "issuer": "rQUFEwFT1YdWbMFvCVh9CwbVndRdFEPdDf", + "title": "UCB Network", + "trustlines": 10101, + "placeInTop": 132 + }, + { + "id": 16711, + "code": "UVX", + "issuer": "r4XUTsMNJoT8Cs6rNHzbif5MpZ7sPH1nWF", + "title": "UnvaxCoin", + "trustlines": 15042, + "placeInTop": 133 + }, + { + "id": 18437, + "code": "XFAMOUS", + "issuer": "r9ZfGV6RpBNA6oewp3WLeyhE5fqvFaMoUs", + "title": "XrpFamous", + "trustlines": 8063, + "placeInTop": 134 + }, + { + "id": 16745, + "code": "xCIV", + "issuer": "rUampeA54U7Fcfwp5cxrRarS37eiaT44HB", + "title": "xCIV Pioneer", + "trustlines": 11001, + "placeInTop": 135 + }, + { + "id": 178, + "code": "XJOY", + "issuer": "rJAvx8FtrLR3RyZyM1LyVQFxxsLdT1PmdS", + "title": "SnwomanYC | Genesis Portal", + "trustlines": 5374, + "placeInTop": 136 + }, + { + "id": 16648, + "code": "xBillie", + "issuer": "rp3d8cQKMS4r68Gx12kcMxGQuyi9nT2Qm4", + "title": "xHustlers", + "trustlines": 4472, + "placeInTop": 137 + }, + { + "id": 144, + "code": "TBBOB", + "issuer": "rMxrnxXHi3aibzQ79B91AtzXBYfbPqbzZK", + "trustlines": 10064, + "placeInTop": 138 + }, + { + "id": 16672, + "code": "XRGary", + "issuer": "rCE2rxDDZtM7qkHAxorjkfLiHX71HtqTY", + "trustlines": 12664, + "placeInTop": 139 + }, + { + "id": 16651, + "code": "LOVE", + "issuer": "rDpdyF9LtYpwRdHZs8sghaPscE8rH9sgfs", + "trustlines": 16553, + "placeInTop": 140 + }, + { + "id": 18193, + "code": "LRUB", + "issuer": "rnyGDFEqnNwpyzievKCMhHUi4xs6HnUqPA", + "title": "Limited Currency RUB", + "trustlines": 9095, + "placeInTop": 141 + }, + { + "id": 17290, + "code": "LGBP", + "issuer": "rfL4Sci2ag5hhkpDuqtWYov6j3mshVWLgU", + "title": "Limited Currency", + "trustlines": 9312, + "placeInTop": 142 + }, + { + "id": 191, + "code": "1MC", + "issuer": "rsJvPP7GVdPfe5zmQtvxAJVZAmDUGfhkV1", + "title": "1 Market Coin", + "trustlines": 13027, + "placeInTop": 143 + }, + { + "id": 213, + "code": "Cheetah", + "issuer": "rfLudDNMJeu3yD6wEPj37GJ9LBpQ4u42d6", + "title": "Cheetah", + "trustlines": 9762, + "placeInTop": 144 + }, + { + "id": 18356, + "code": "AnimaCoin", + "issuer": "rGQrZvndQsJV2S5cnSdiRFMPT1Fz1Ccvuj", + "title": "Anima", + "trustlines": 12433, + "placeInTop": 145 + }, + { + "id": 16800, + "code": "XMEMEcoin", + "issuer": "rWE5SePEBuVjJUoKXA6x87hQ59YPZCVD6", + "trustlines": 4816, + "placeInTop": 146 + }, + { + "id": 18756, + "code": "XCHN", + "issuer": "rHMcxniNwG8LG4tfrmNjoAjDBqWkp2b6d7", + "trustlines": 5123, + "placeInTop": 147 + }, + { + "id": 195, + "code": "Peas", + "issuer": "rPAArd4yZAJaDCR5gs41YYmGphfj6yzh3R", + "title": "XRPeas", + "trustlines": 14167, + "placeInTop": 148 + }, + { + "id": 18218, + "code": "LPHP", + "issuer": "rnyGDFEqnNwpyzievKCMhHUi4xs6HnUqPA", + "title": "Limited Currency PHP", + "trustlines": 7448, + "placeInTop": 149 + }, + { + "id": 10, + "code": "XAVE", + "issuer": "rn2rjQnzbynPT2xNJhpBQ7e2aLxNnxLAfa", + "title": "XRP avengers", + "trustlines": 8485, + "placeInTop": 150 + }, + { + "id": 17878, + "code": "XrpVault", + "issuer": "rNJhYNbxtRj8upde5BQHRSUssNAoFwhc83", + "title": "The Vault", + "trustlines": 12902, + "placeInTop": 151 + }, + { + "id": 150, + "code": "DRT", + "issuer": "rfDhSfY5JMtCrje7hGxC8Gk6dC5PgNJh63", + "title": "DaRT Art Museum and Marketplace", + "trustlines": 23648, + "placeInTop": 152 + }, + { + "id": 18896, + "code": "XBT", + "issuer": "radcGxrrqjJb7KfJojjrN1Syn36UC5wQQ6", + "title": "XRStakeBet", + "trustlines": 2999, + "placeInTop": 153 + }, + { + "id": 38, + "code": "BumCrack", + "issuer": "rBuFBE8nx5Zpojj6EY3Lfh4sd1CHskFRC7", + "title": "B C XRP", + "trustlines": 13403, + "placeInTop": 154 + }, + { + "id": 16776, + "code": "XRPL3DAPES", + "issuer": "rLBW9d9cfEY4ZFPbgqKzEpoEHjKeLrotWZ", + "title": "3D Ape Club", + "trustlines": 16134, + "placeInTop": 155 + }, + { + "id": 18432, + "code": "XAI", + "issuer": "r9YmVNAQo9TAwDVW9WmUPdX8qRCdpeYKiE", + "title": "X-A.I. NFT", + "trustlines": 20123, + "placeInTop": 156 + }, + { + "id": 18206, + "code": "LJPY", + "issuer": "rnyGDFEqnNwpyzievKCMhHUi4xs6HnUqPA", + "title": "Limited Currency JPY", + "trustlines": 8930, + "placeInTop": 157 + }, + { + "id": 16707, + "code": "SINGLE", + "issuer": "rhtmgZUbTzfH6xQKqqzF835uRVPFMqFYRe", + "title": "Single Interest", + "trustlines": 2422, + "placeInTop": 158 + }, + { + "id": 17879, + "code": "HMN", + "issuer": "rNUJ4qxmEEU8Et79nmdypwoDzSsuk437Rz", + "title": "HMN NFT", + "trustlines": 6289, + "placeInTop": 159 + }, + { + "id": 18213, + "code": "LSVC", + "issuer": "rnyGDFEqnNwpyzievKCMhHUi4xs6HnUqPA", + "title": "Limited Currency SVC", + "trustlines": 3735, + "placeInTop": 160 + }, + { + "id": 18558, + "code": "GamerXGold", + "issuer": "rMczrvMki7DuXsuMf3zGUrqAmWvLKZNnt2", + "title": "GamerXGold", + "trustlines": 16249, + "placeInTop": 161 + }, + { + "id": 18216, + "code": "LKRW", + "issuer": "rnyGDFEqnNwpyzievKCMhHUi4xs6HnUqPA", + "title": "Limited Currency KRW", + "trustlines": 5534, + "placeInTop": 162 + }, + { + "id": 17918, + "code": "XStack", + "issuer": "rHqNZURCvyrx4DZDF6rxYTpeaQnWrNB1tv", + "title": "xStackCoin", + "trustlines": 9752, + "placeInTop": 163 + }, + { + "id": 18036, + "code": "xRaccoon", + "issuer": "rKECgn8LhVwMtHyiGZcRu2H1e5mTo6Gdw", + "title": "xRaccoon", + "trustlines": 4490, + "placeInTop": 164 + }, + { + "id": 18924, + "code": "xGBR", + "issuer": "rnBG7eQk9pPZtfD19uBDyxBUoaYD4HUFWm", + "trustlines": 9475, + "placeInTop": 165 + }, + { + "id": 18990, + "code": "LUCKY", + "issuer": "rUjUNsSxPwTcd3YDTqDtfXHdmZd7C8tFkM", + "trustlines": 8215, + "placeInTop": 166 + }, + { + "id": 18282, + "code": "XRIV", + "issuer": "rMFeo6PiEqeZad4z29ivEj5adGp2TuH2YY", + "trustlines": 7815, + "placeInTop": 167 + }, + { + "id": 18321, + "code": "LIDR", + "issuer": "rnGvMu8P6evJEYY4cPyzcy4N1m5gcYRjaH", + "title": "Limited USD (LUSD)", + "trustlines": 5060, + "placeInTop": 168 + }, + { + "id": 17594, + "code": "NICE", + "issuer": "r96uXvCJxe3Yeeo9wCtJsLSpJiFUz2hvsB", + "title": "NICEToken", + "trustlines": 23772, + "placeInTop": 169 + }, + { + "id": 16809, + "code": "SCS", + "issuer": "rHYr9XNQJf1Kury1wGkht7Hrb9d43PqSMw", + "title": "CareShareCoin", + "trustlines": 5919, + "placeInTop": 170 + }, + { + "id": 18794, + "code": "CSX", + "issuer": "rG9eYQaixAV16SWpuDaQAZnfcaJx11DtJz", + "title": "C-S-XRP \u22b9", + "trustlines": 4374, + "placeInTop": 171 + }, + { + "id": 18424, + "code": "XUH", + "issuer": "rftZzz4iroaBENgwAPEgFRk2pHb3QrEDxe", + "title": "UNI HIVE | XUH", + "trustlines": 8135, + "placeInTop": 172 + }, + { + "id": 18060, + "code": "PXLTRBE", + "issuer": "rw9h8CvTmbZbhRwR6u7NPAwjcQuf3CaDoU", + "title": "xPixelTribes NFT", + "trustlines": 7845, + "placeInTop": 173 + }, + { + "id": 18890, + "code": "Gacha", + "issuer": "rsGsuzivHfnAP2S7hNAE4morQBZPdN4en3", + "title": "GACHA Lottery Club", + "trustlines": 3708, + "placeInTop": 174 + }, + { + "id": 16666, + "code": "GorillaGold", + "issuer": "rGQtGHrgN4FK1RcEn83q4t8aK6BobzDEMK", + "title": "GORILLA$Gold XRP", + "trustlines": 2828, + "placeInTop": 175 + }, + { + "id": 18323, + "code": "LVND", + "issuer": "rnGvMu8P6evJEYY4cPyzcy4N1m5gcYRjaH", + "title": "Limited USD (LUSD)", + "trustlines": 4483, + "placeInTop": 176 + }, + { + "id": 18583, + "code": "xwest", + "issuer": "rGxTL4RgJeJcN3SySxAQMnMnWXDEELjMfk", + "title": "XrpWest", + "trustlines": 3462, + "placeInTop": 177 + }, + { + "id": 18219, + "code": "LSGD", + "issuer": "rnyGDFEqnNwpyzievKCMhHUi4xs6HnUqPA", + "title": "Limited Currency SGD", + "trustlines": 4406, + "placeInTop": 178 + }, + { + "id": 18288, + "code": "MDLR", + "issuer": "rMdLraa4jWJvpjpDpvmDEuVtjo3WwyWDKw", + "trustlines": 8329, + "placeInTop": 179 + }, + { + "id": 16794, + "code": "xianggang", + "issuer": "rMUqLuW4RpBvVAKNoaCubvbXgzuSnf6P8J", + "title": "xianggang.hk", + "trustlines": 10030, + "placeInTop": 180 + }, + { + "id": 16664, + "code": "ALGX", + "issuer": "ravdhDikgTwFsqFrJ3DuhVUYdAbxJLjdNT", + "title": "Cosmonaut NFT - Welcome to the Allegiance!", + "trustlines": 4511, + "placeInTop": 181 + }, + { + "id": 17937, + "code": "Maroo", + "issuer": "rEiqU48BP7iPDipRwU3cPQqo2EbDFi123P", + "title": "Burning Maroo", + "trustlines": 6139, + "placeInTop": 182 + }, + { + "id": 1381, + "code": "BTC", + "issuer": "rchGBxcD1A1C2tdxF6papQYZ8kjRKMYcL", + "title": "GateHub BTC", + "trustlines": 115393, + "placeInTop": null + }, + { + "id": 17804, + "code": "GCB", + "issuer": "rNdwi8ain5ibXNB9A7H3zzKtSxgVzAqqAe", + "trustlines": 33404, + "placeInTop": null + }, + { + "id": 16601, + "code": "ETH", + "issuer": "rcA8X3TVMST1n3CJeAdGk1RdRCHii7N2h", + "title": "Gatehub Fifth", + "trustlines": 90505, + "placeInTop": null + }, + { + "id": 320, + "code": "PASA", + "issuer": "rBPtuMc4HBR1SuZyZv8hs7WBVxLBYrzxbY", + "title": "PASA COIN", + "trustlines": 25615, + "placeInTop": null + }, + { + "id": 16599, + "code": "KGE", + "issuer": "rNhSjAMnDJc9tDHH1R4sqggvgDGa8Bwj5T", + "title": "Kinjo Gear", + "trustlines": 21319, + "placeInTop": null + }, + { + "id": 16615, + "code": "Daric", + "issuer": "rK9AtihZZYWAwZQnJCYzZnyW833vbcPXPf", + "title": "Daric", + "trustlines": 21573, + "placeInTop": null + }, + { + "id": 17976, + "code": "XRWeb", + "issuer": "rDegPvsK5c2nzaKTn2PsuPZjs8b3neDDn", + "title": "XRWeb", + "trustlines": 21889, + "placeInTop": null + }, + { + "id": 252, + "code": "CodeCoin", + "issuer": "rGbsKNrVURRfU1WEb1aEqaoyRJDkvssyBa", + "title": "CodeCoin", + "trustlines": 21750, + "placeInTop": null + }, + { + "id": 17676, + "code": "xCBS", + "issuer": "rNvhXtgDdd4Sh3NKLXcUH9Hozs4dqu62we", + "title": "xCBS | XRPL", + "trustlines": 21483, + "placeInTop": null + }, + { + "id": 18353, + "code": "HMC", + "issuer": "raXY8RFAKixBZGw8nhDRHvVCKd2RzeoeLq", + "title": "Himalaya", + "trustlines": 24770, + "placeInTop": null + }, + { + "id": 16617, + "code": "XUM", + "issuer": "r465PJyGWUE8su1oVoatht6cXZJTg1jc2m", + "title": "XUM Universal Money", + "trustlines": 26206, + "placeInTop": null + }, + { + "id": 16644, + "code": "APXX", + "issuer": "rL2sSC2eMm6xYyx1nqZ9MW4AP185mg7N9t", + "title": "ApexSafariXRPL", + "trustlines": 19066, + "placeInTop": null + }, + { + "id": 17671, + "code": "XGF", + "issuer": "rJnn9jdwaBfuyq383hNiX2oowLuLUm2DZD", + "title": "XGF | xGreen Fund", + "trustlines": 18777, + "placeInTop": null + }, + { + "id": 17149, + "code": "PGN", + "issuer": "rPUSoeJaHQzrXATtGniVjwBQQDEtJcdwFq", + "title": "PGN", + "trustlines": 17529, + "placeInTop": null + }, + { + "id": 16611, + "code": "Gift", + "issuer": "rBXXRBZ46rwCkS9mHom3WW8u7gSytb5KcZ", + "title": "XRPLGift", + "trustlines": 18129, + "placeInTop": null + }, + { + "id": 17184, + "code": "XRTemplate", + "issuer": "rMX54z8VgtRhPefzqVkdG3LxsuGdFQcXxr", + "title": "XRTemplate", + "trustlines": 16944, + "placeInTop": null + }, + { + "id": 236, + "code": "Zinfinite", + "issuer": "rGMU2cbbMhzodpecrjLQ2A814DqL8LFxjY", + "title": "Zinfinite", + "trustlines": 16848, + "placeInTop": null + }, + { + "id": 194, + "code": "XRSoftware", + "issuer": "rJZ9Hpaeqy3fdBvjVUjx1fW1bE75HgaJbr", + "title": "XRSoftware", + "trustlines": 15507, + "placeInTop": null + }, + { + "id": 16639, + "code": "NFTL", + "issuer": "r3DCE2UVaqQaGQragAjmwL6kNicF2rw6PL", + "title": "Elliot | NFT-Loving.com", + "trustlines": 15355, + "placeInTop": null + }, + { + "id": 16622, + "code": "CNY", + "issuer": "razqQKzJRdB4UxFPWf5NEpEG3WMkmwgcXA", + "title": "RippleChina", + "trustlines": 29660, + "placeInTop": null + }, + { + "id": 201, + "code": "ELM", + "issuer": "rQB9HhhBCq2zAVpwQD3jV9ja39DmomdWj1", + "title": "Elements ELM", + "trustlines": 14957, + "placeInTop": null + }, + { + "id": 18110, + "code": "XTriviA", + "issuer": "rhLr8bGvHvBgYXAHNPyXrQAcKGrQ2X5nU4", + "title": "XTriviA", + "trustlines": 14954, + "placeInTop": null + }, + { + "id": 16713, + "code": "GOLD", + "issuer": "rGQtGHrgN4FK1RcEn83q4t8aK6BobzDEMK", + "title": "Eric \ud83c\uddfa\ud83c\uddf8 #GOLD \ud83c\uddfa\ud83c\uddf2 #XRP $10+ \ud83c\uddfa\ud83c\uddf8 #XMETA", + "trustlines": 14949, + "placeInTop": null + }, + { + "id": 16917, + "code": "xHulk", + "issuer": "r43PooeaFyp2cCfqxMkZLu47VKUDaCzQVt", + "title": "xHulk", + "trustlines": 14996, + "placeInTop": null + }, + { + "id": 9, + "code": "BBulldoge", + "issuer": "r3b8BtKC4d8r4Je7PDJhzAgNTLR64seTDu", + "title": "Bully Bulldoge - #BBULLDOGE", + "trustlines": 14549, + "placeInTop": null + }, + { + "id": 17401, + "code": "TipCoin", + "issuer": "rsUjMrcGu8ANoTwv3zUJE6MzSL6K7fMyPU", + "title": "TipCoin", + "trustlines": 15215, + "placeInTop": null + }, + { + "id": 16673, + "code": "BlackFriday", + "issuer": "raFpHssoH3rWkMy9XLjA6NDRW2y44tiFVM", + "title": "Black Friday", + "trustlines": 13377, + "placeInTop": null + }, + { + "id": 16650, + "code": "XWM", + "issuer": "rJzBh2Sktnps8CoLVJeDjj3Y2aDzXhrAFL", + "title": "XWM World Money", + "trustlines": 17655, + "placeInTop": null + }, + { + "id": 16886, + "code": "XRBear", + "issuer": "rKxqkAbT2BQUbtnknSAJon7kX89gUKpZu3", + "title": "XRBear coin", + "trustlines": 13084, + "placeInTop": null + }, + { + "id": 16663, + "code": "OCEAN", + "issuer": "rPCrPJ9Uz988tD1aQVAToioDcCGZ8nbBTn", + "title": "Ocean Assist", + "trustlines": 12827, + "placeInTop": null + }, + { + "id": 235, + "code": "PIN", + "issuer": "rhx9yNhbo7xtTy6rBY8xrUYkuYdyVs5Arb", + "title": "XrPiNFT", + "trustlines": 13570, + "placeInTop": null + }, + { + "id": 17626, + "code": "CNY", + "issuer": "rKiCet8SdvWxPXnAgYarFUXMh1zCPz432Y", + "title": "Ripple Fox", + "trustlines": 17733, + "placeInTop": null + }, + { + "id": 16619, + "code": "POKER", + "issuer": "rfNWXEENu93dvCBnjpFY7mRpprZzBUx8hC", + "title": "POKER", + "trustlines": 14229, + "placeInTop": null + }, + { + "id": 5, + "code": "Cake", + "issuer": "ra1XmvmraMiRYarFrHEU7XDojvRyipU5Vg", + "title": "Cake Coin", + "trustlines": 11637, + "placeInTop": null + }, + { + "id": 16949, + "code": "SPREAD", + "issuer": "rwPzJd39swHT6NfxvgGFYE7q9q7EcqKuKW", + "title": "Spread Love Token", + "trustlines": 12228, + "placeInTop": null + }, + { + "id": 17657, + "code": "MONTEZUMA", + "issuer": "rNJpp2TXWrtFfNs8mbEsrj8gj6XVHfHywD", + "title": "MONTEZUMA", + "trustlines": 12153, + "placeInTop": null + }, + { + "id": 208, + "code": "XRsaitama", + "issuer": "r3nEJus5Ryoo9ckNmY8XHogoPnLfP1unFv", + "title": "XRsaitama", + "trustlines": 12179, + "placeInTop": null + }, + { + "id": 18439, + "code": "FRD", + "issuer": "rEsdnLqeFgXSTeexMAFB7ZauRoMMWvSL4e", + "title": "Ferda Network \ud83d\udc7e", + "trustlines": 12268, + "placeInTop": null + }, + { + "id": 16676, + "code": "XSD", + "issuer": "r9PwqmHiGiE7yAXmG5mk7wSJAeezLqE7Ei", + "title": "XStreetDogs", + "trustlines": 11981, + "placeInTop": null + }, + { + "id": 18259, + "code": "xFlashChain", + "issuer": "rJgcjY1MZJjw946qRqN57V3TGg9PZEA1bw", + "title": "xFlashchain Official", + "trustlines": 11626, + "placeInTop": null + }, + { + "id": 16608, + "code": "SimbaXRP", + "issuer": "rDqwjJ8fUqdyfPjJZ3h93J1XY8hz6CjEYo", + "title": "Simba XRP", + "trustlines": 12056, + "placeInTop": null + }, + { + "id": 18171, + "code": "XrPinoy", + "issuer": "rt3hn4EYMV39xd7pwqMHacJVSu2kEA18x", + "title": "XrPinoy", + "trustlines": 10791, + "placeInTop": null + }, + { + "id": 18574, + "code": "GEN", + "issuer": "r9sSz7JA6NWfPq9cPtEbg4rDBdVuLHi68g", + "title": "ProjectGenesisXrpl", + "trustlines": 11616, + "placeInTop": null + }, + { + "id": 340, + "code": "XDogelon", + "issuer": "rNFKrSUW1xKzDwHz8J9uVAs4GpxtEUoAsF", + "title": "XDogelon", + "trustlines": 11207, + "placeInTop": null + }, + { + "id": 370, + "code": "UMMO", + "issuer": "rfGqDiFegcMm8e9saj48ED74PkotwJCmJd", + "title": "Ummo", + "trustlines": 10875, + "placeInTop": null + }, + { + "id": 180, + "code": "XRMOON", + "issuer": "rBBh2z5wsxE9gcVE2yUU39UntvRMHDKPpq", + "title": "XRMOON COIN", + "trustlines": 11005, + "placeInTop": null + }, + { + "id": 18170, + "code": "XJWL", + "issuer": "rMatwcXVLoRq7yoRR7KNT4Kg8ft8osnJKi", + "title": "xJewelryNFT", + "trustlines": 10318, + "placeInTop": null + }, + { + "id": 18315, + "code": "MORTAL", + "issuer": "rHyCV84JWbmhbCAJYpcd76HXcnhJ4uY4Q7", + "title": "Mortal Kombat", + "trustlines": 9986, + "placeInTop": null + }, + { + "id": 19036, + "code": "OVO", + "issuer": "r3jQzqfGVagsWNbSxMJpQV8VK7jHHmdv5j", + "trustlines": 15978, + "placeInTop": null + }, + { + "id": 16720, + "code": "XRTEACH", + "issuer": "r42RmRk42JYCAvzSifSGAgsZuJBUm2yJSE", + "title": "XRTEACH", + "trustlines": 9477, + "placeInTop": null + }, + { + "id": 367, + "code": "Fluff", + "issuer": "rG81ZwWpJbwvkrSPMWYRNAQ4JrYVGzDZfx", + "title": "xCorgi | Fluff", + "trustlines": 10425, + "placeInTop": null + }, + { + "id": 2, + "code": "WEED", + "issuer": "raDF491dC9XF1guG5zZkWWpNQoFquwt2cp", + "trustlines": 9287, + "placeInTop": null + }, + { + "id": 17959, + "code": "Lil2", + "issuer": "rENNLZVLWMLvwM69h4fR8B43qptEUUG4QH", + "title": "LilShib", + "trustlines": 10031, + "placeInTop": null + }, + { + "id": 366, + "code": "ELVC", + "issuer": "rLb593mo6Nerw7eWvC19gR1fLggeWX6u6s", + "title": "Tuition DeFi Network", + "trustlines": 9811, + "placeInTop": null + }, + { + "id": 16801, + "code": "IRE", + "issuer": "rfTYvAG86Y1L61RQjbxHTyJmphYzHgguCd", + "title": "IRE - Blockchain in Real Estate", + "trustlines": 10438, + "placeInTop": null + }, + { + "id": 16766, + "code": "INL", + "issuer": "rsARtxd6M1RBoGKwoGh4ujCQ9A6iDYEu4s", + "title": "InNewLife", + "trustlines": 15356, + "placeInTop": null + }, + { + "id": 18125, + "code": "Blessed", + "issuer": "rQr6VLuduLeFoWBERechDs3NB2cynoujhQ", + "title": "Blessed Token", + "trustlines": 9175, + "placeInTop": null + }, + { + "id": 131, + "code": "Planet", + "issuer": "rntdU6TyFEjyf8JRkrG3ggJnsFF55zRSq3", + "title": "Planet Coin", + "trustlines": 9242, + "placeInTop": null + }, + { + "id": 123, + "code": "XReddog", + "issuer": "rUWpPmEHBQfb6xgcTtVrGUK5ppztU5GDUF", + "title": "XReddog", + "trustlines": 9265, + "placeInTop": null + }, + { + "id": 16643, + "code": "DIA", + "issuer": "rQfWiU7kRbJBFSXRyQh7GTUeEP6qJ4kp2F", + "title": "DIA_PROJECT official", + "trustlines": 12387, + "placeInTop": null + }, + { + "id": 21, + "code": "EliteX", + "issuer": "rPHqxokbdbRHFZ6RLN4TqJrYd3zF3kE1Vd", + "title": "EliteX", + "trustlines": 8659, + "placeInTop": null + }, + { + "id": 14, + "code": "xNinjas", + "issuer": "r9am4mhbWRByfAU7bYAzmN15pGKT3mDW8p", + "title": "xNinjas", + "trustlines": 12892, + "placeInTop": null + }, + { + "id": 18071, + "code": "PZA", + "issuer": "rBi1kmPw7axgkTDG31GFhtuACaveohfYnj", + "title": "XRPLPIZZA \ud83c\udf55", + "trustlines": 8890, + "placeInTop": null + }, + { + "id": 18295, + "code": "RCN", + "issuer": "rPGxCzMicNJRe1U1CD5QyNjXdLUtdgSa7B", + "title": "ToonRaccoon", + "trustlines": 8559, + "placeInTop": null + }, + { + "id": 16850, + "code": "Women", + "issuer": "rGiv7xKG4ShaRz4KPxgzXC1teMBxnaPyRU", + "title": "Women Coin", + "trustlines": 7767, + "placeInTop": null + }, + { + "id": 16894, + "code": "XRCATE", + "issuer": "rjb1JbdHruegp7vmcPmDU5EzYgTUtuLLK", + "title": "XRcate", + "trustlines": 8356, + "placeInTop": null + }, + { + "id": 86, + "code": "XRPets", + "issuer": "rESKaHTUhDD5mT2p1H99Y3KeJVc6Y7t4vx", + "title": "XRPets", + "trustlines": 7947, + "placeInTop": null + }, + { + "id": 16722, + "code": "XWSB", + "issuer": "rLpL5d9qubKjht8GnkxgnVTQPq9MKNc757", + "title": "XRPwallstreetbets", + "trustlines": 10563, + "placeInTop": null + }, + { + "id": 172, + "code": "QLX", + "issuer": "rMQhWnHuYVmjRcyptPvrueKdLvjQT2Nquc", + "title": "Aquila X", + "trustlines": 11564, + "placeInTop": null + }, + { + "id": 16706, + "code": "CBT", + "issuer": "rJbpn78QJxKpwz8daMCHxHVWauq3xdMn9M", + "title": "CannaToken", + "trustlines": 7748, + "placeInTop": null + }, + { + "id": 17568, + "code": "JPY", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 13287, + "placeInTop": null + }, + { + "id": 199, + "code": "ARUNA", + "issuer": "rfjqDHJ7FQyYFqeaUqTEdpEaxiQLv4LzKm", + "title": "ARUNA XRPL", + "trustlines": 6993, + "placeInTop": null + }, + { + "id": 17685, + "code": "CNY", + "issuer": "rPT74sUcTBTQhkHVD54WGncoqXEAMYbmH7", + "title": "RippleQK", + "trustlines": 11321, + "placeInTop": null + }, + { + "id": 17967, + "code": "XCSI", + "issuer": "rn7jqzyoMbECYPgH1j5AcsegKXNrc8JU91", + "title": "XCSI - Cat Society NFT", + "trustlines": 7310, + "placeInTop": null + }, + { + "id": 157, + "code": "X3DPUNK", + "issuer": "rKGMZbfKhVhmbQU5DwGgF6tgQMzzK5ydxr", + "title": "X3D PUNK", + "trustlines": 8992, + "placeInTop": null + }, + { + "id": 16789, + "code": "Zini", + "issuer": "rGCoUJgDA3CzdohdPr9vX7p1p2kixaASnK", + "title": "Zinfinite", + "trustlines": 6578, + "placeInTop": null + }, + { + "id": 17178, + "code": "XSharkNFT", + "issuer": "rGtBVC62X6vPQP2gpaaHNHGxhNxGx7FEfH", + "title": "XSharkNFT", + "trustlines": 6865, + "placeInTop": null + }, + { + "id": 77, + "code": "XREbook", + "issuer": "rMgfWUcBd45TXyszMb5LnopD5SDnAmDZsR", + "title": "XREbook", + "trustlines": 6950, + "placeInTop": null + }, + { + "id": 16885, + "code": "XSch", + "issuer": "rG8Ccx5i9m3mJQFreD3cyggQH1pd5WziZy", + "title": "xSchnauzer (XRPL)", + "trustlines": 6527, + "placeInTop": null + }, + { + "id": 16887, + "code": "XFLOKIVERSE", + "issuer": "rwCCrZuotr9P5XmfoSY1ibVzRecLcwtxp3", + "title": "XFLOKIVERSE", + "trustlines": 8302, + "placeInTop": null + }, + { + "id": 18613, + "code": "NEKASHI", + "issuer": "r46H9jJc6T5aTkC1J1oFHFFxHG2HXGEndc", + "trustlines": 8079, + "placeInTop": null + }, + { + "id": 16981, + "code": "XRPoo", + "issuer": "rpa7p8yeDFNkNsFEiR1ZHQqxjsLzBUmwzD", + "title": "XRPoo", + "trustlines": 6325, + "placeInTop": null + }, + { + "id": 18446, + "code": "99D", + "issuer": "rNg8LsQefsxWF2snf4BaVgg7CjAtz6BYVc", + "title": "99DAYS", + "trustlines": 14829, + "placeInTop": null + }, + { + "id": 18964, + "code": "HDT", + "issuer": "rEmLBstEaNQqgodQnTMUn9UtkRPi3ieAWu", + "title": "HoldDiamondToken", + "trustlines": 8522, + "placeInTop": null + }, + { + "id": 17684, + "code": "BTC", + "issuer": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q", + "title": "BTC 2 Ripple", + "trustlines": 10166, + "placeInTop": null + }, + { + "id": 28, + "code": "XShibanu", + "issuer": "rpD9gvxp7RCKrTrYAyTdueF9ApApbP5ZnN", + "title": "XShibanu", + "trustlines": 7601, + "placeInTop": null + }, + { + "id": 26, + "code": "LogX", + "issuer": "rw1mh3E436LfF2MDrHJNm65wbRG2ZCM3kv", + "trustlines": 6262, + "placeInTop": null + }, + { + "id": 16612, + "code": "XPG", + "issuer": "rfJwWjrxZU5Vsk9sTVXKLdyrce1CDTjhDf", + "title": "XRPiggies Official", + "trustlines": 8162, + "placeInTop": null + }, + { + "id": 16836, + "code": "SKS", + "issuer": "rNspzJyaq7D2aHB8npk1pg2NuR8BrJ78L3", + "trustlines": 8073, + "placeInTop": null + }, + { + "id": 16876, + "code": "SPOOKYX", + "issuer": "r3L2Lcnm3o2tnDw2fmNiVJDKtFDYTgUksj", + "title": "SPOOKYX", + "trustlines": 6483, + "placeInTop": null + }, + { + "id": 17930, + "code": "BTC", + "issuer": "rpJZ5WyotdphojwMLxCr2prhULvG3Voe3X", + "trustlines": 5947, + "placeInTop": null + }, + { + "id": 18014, + "code": "OnlyFans", + "issuer": "rhvfUwU2qkNfeUdrDp28xF4xXDxu6xhBVz", + "title": "OnlyFansXRP", + "trustlines": 7123, + "placeInTop": null + }, + { + "id": 377, + "code": "TEEF", + "issuer": "rfcdWJmFhMVomRM5MqniSZuYfCyZyvRkkh", + "title": "teefcoin", + "trustlines": 7141, + "placeInTop": null + }, + { + "id": 16750, + "code": "XRdragon", + "issuer": "rEMzCUeRZbx6ydthbi2RVNYdRbuqqsrYof", + "title": "XRdragon", + "trustlines": 6804, + "placeInTop": null + }, + { + "id": 333, + "code": "XLE", + "issuer": "rnQPyTLGVD1exGZCBD9XcXvbedMG7Sy4iU", + "title": "XLEcoin", + "trustlines": 6077, + "placeInTop": null + }, + { + "id": 17045, + "code": "nexit", + "issuer": "r9prnHupoaKPkGkhiPVtcUJjZ2uUHymtX1", + "title": "Nexit", + "trustlines": 5874, + "placeInTop": null + }, + { + "id": 245, + "code": "BTCX", + "issuer": "rBnuiD54Mk4FmeU8WhBfstxnB5XEFt4QBQ", + "title": "Bitcoin X", + "trustlines": 8889, + "placeInTop": null + }, + { + "id": 253, + "code": "XTK", + "issuer": "rXTKdHWuppSjkbiKoEv53bfxHAn1MxmTb", + "title": "Kudos", + "trustlines": 24440, + "placeInTop": null + }, + { + "id": 16624, + "code": "FUX", + "issuer": "r9S8MujtHbaVfoLeSdGyXus9TR9UbgyD3Y", + "title": "FUX", + "trustlines": 9795, + "placeInTop": null + }, + { + "id": 217, + "code": "KAT", + "issuer": "rEmWWStdxxLUtTAzhRS5VWvtjtNUwWcfeM", + "title": "Katz Army", + "trustlines": 8796, + "placeInTop": null + }, + { + "id": 18212, + "code": "XCHANGE", + "issuer": "rwdsHNyqF3i6iEbpD5mXytNNEdHQdEMHjm", + "title": "XCHANGE", + "trustlines": 5315, + "placeInTop": null + }, + { + "id": 16734, + "code": "SPK", + "issuer": "rBGuYfE3H3AyhWANSe4fKrf8z1aF7hFznB", + "title": "SPARKER TOKEN $SPK", + "trustlines": 6048, + "placeInTop": null + }, + { + "id": 16670, + "code": "STC", + "issuer": "r4J3XtWvu869Jnk2zLp9jnzcA37VeqpPiA", + "title": "Streetcoin", + "trustlines": 5092, + "placeInTop": null + }, + { + "id": 163, + "code": "DKP", + "issuer": "rM7zpZQBfz9y2jEkDrKcXiYPitJx9YTS1J", + "title": "DragonKill", + "trustlines": 10358, + "placeInTop": null + }, + { + "id": 18430, + "code": "CRX", + "issuer": "r4RHp5hGQvi3tibM7Zpj4Hzr2DK97uSrsF", + "title": "CRX", + "trustlines": 4826, + "placeInTop": null + }, + { + "id": 270, + "code": "LuckyCharms", + "issuer": "rECNBBTFzyqdMMp44V74DAdqctvi2qDTPd", + "title": "LuckyCharmsCoin", + "trustlines": 6675, + "placeInTop": null + }, + { + "id": 109, + "code": "GRIME", + "issuer": "r3Xh1GTVBPooVkc5jWSAtzKXQPPPFJKgb9", + "title": "Grime Coin", + "trustlines": 15670, + "placeInTop": null + }, + { + "id": 27, + "code": "IRV", + "issuer": "rueUkJYAQnP9wqHrKQXrsCwXeRziVn377", + "trustlines": 4772, + "placeInTop": null + }, + { + "id": 359, + "code": "RUG", + "issuer": "rfEJ1ksD22TsCy8hdKoJuC6Xfc33VCKPUs", + "title": "TheRugPhxProject", + "trustlines": 5644, + "placeInTop": null + }, + { + "id": 17707, + "code": "USD", + "issuer": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q", + "title": "SnapSwap", + "trustlines": 7848, + "placeInTop": null + }, + { + "id": 223, + "code": "Arcverse", + "issuer": "rUwA9KAe3i3W2yhqh3Lc4XTJCo4bTpdPcX", + "title": "Arcverse", + "trustlines": 4753, + "placeInTop": null + }, + { + "id": 16884, + "code": "XRS", + "issuer": "rfM28hjg87v52SVyCxHuG1VnqqDpb4Bm5Y", + "title": "XRSQUID", + "trustlines": 5681, + "placeInTop": null + }, + { + "id": 18604, + "code": "MDK", + "issuer": "r4pDW1tz1ynuqBAnaf4ReDwpZQCKGv3qdN", + "title": "MR. Desert King", + "trustlines": 8617, + "placeInTop": null + }, + { + "id": 18477, + "code": "FUEL", + "issuer": "rJ4KcB9GueMDYzYzr7XR3j4jd82gG7tbEt", + "title": "Fuel Save", + "trustlines": 4501, + "placeInTop": null + }, + { + "id": 16731, + "code": "XSAMO", + "issuer": "rMVufScdiavFvGzVBZryTTRu2DxRuEqos5", + "title": "xSamoyed", + "trustlines": 6374, + "placeInTop": null + }, + { + "id": 18850, + "code": "WWW", + "issuer": "rpzuRVqQmQeh5Pw2JYgNgLUBdinuNk4ozR", + "title": "World Wild Web on XRP \ud83c\udf10", + "trustlines": 4586, + "placeInTop": null + }, + { + "id": 16736, + "code": "XHASBULL", + "issuer": "rpMevF5zLLyFm2eNd9KUMe6bcyafRHuSnh", + "title": "XRP Hasbulla", + "trustlines": 5824, + "placeInTop": null + }, + { + "id": 17209, + "code": "ALV", + "issuer": "raEQc5krJ2rUXyi6fgmUAf63oAXmF7p6jp", + "title": "Allvor", + "trustlines": 6750, + "placeInTop": null + }, + { + "id": 18205, + "code": "XSHIO", + "issuer": "rGxSsVktuy9aCzckSbTf3yQissD3oD2va5", + "title": "Xshio NFT", + "trustlines": 9700, + "placeInTop": null + }, + { + "id": 17921, + "code": "TROPA", + "issuer": "r9BSm9VwgFKCsjksYuzHJ1QebneFyrS5bu", + "title": "CrypTropa_NFT", + "trustlines": 11884, + "placeInTop": null + }, + { + "id": 16900, + "code": "EGG", + "issuer": "rfPhEGpVC72d29oxghgA9Zjuas65pMg1Df", + "title": "EggsRP", + "trustlines": 5139, + "placeInTop": null + }, + { + "id": 294, + "code": "CCR", + "issuer": "rPAKJxHcHEkjPtpsSTGGMWLvpibZiuRJHi", + "trustlines": 4287, + "placeInTop": null + }, + { + "id": 16956, + "code": "BabyThug", + "issuer": "rHGjhK35BEH42VYQh5cSXADNHh6HeWj116", + "title": "BabyThug", + "trustlines": 4325, + "placeInTop": null + }, + { + "id": 281, + "code": "PXCS", + "issuer": "rNwgtMaqziGqLiDzeXE91B8D2cB5m2fDhc", + "trustlines": 4330, + "placeInTop": null + }, + { + "id": 16847, + "code": "ShibaInuX", + "issuer": "r4N5gak4yRXHyCvTbJggHvbYLRCbM8E9YT", + "title": "ShibaInuX ", + "trustlines": 6431, + "placeInTop": null + }, + { + "id": 18093, + "code": "MetaGEX", + "issuer": "r3zLnFU24bSsYrAo55mJxYXccnojjCHmpK", + "title": "MetaGEX", + "trustlines": 4536, + "placeInTop": null + }, + { + "id": 346, + "code": "XSaitama", + "issuer": "rwUSJdemymbvn8WRa3WutKkVMrjkLpiFNy", + "title": "XSaitama", + "trustlines": 4312, + "placeInTop": null + }, + { + "id": 17259, + "code": "NBA", + "issuer": "rfHALygLHj6EwfXNSFCSLX6Kp3yfFSpuuP", + "title": "NBA Coin || XRPL", + "trustlines": 11529, + "placeInTop": null + }, + { + "id": 16740, + "code": "SURV", + "issuer": "rHrjHawcjA2TihAqtE7nWzArpWkiFseHM4", + "title": "SURV", + "trustlines": 4520, + "placeInTop": null + }, + { + "id": 16952, + "code": "Hellbound", + "issuer": "rML7dFchDJHHMwgCbSYE26TM2qdYnBWe9r", + "title": "Hellbound", + "trustlines": 4196, + "placeInTop": null + }, + { + "id": 16848, + "code": "XFIT", + "issuer": "rwAe5VFjRhwwgCnAGmEfb33kkWYqR8mnoh", + "title": "XFitness", + "trustlines": 5497, + "placeInTop": null + }, + { + "id": 16798, + "code": "CAP", + "issuer": "rBwMPfwkB3kFJd65ui4JZmDvEzEequMLnJ", + "title": "Captain Coin", + "trustlines": 4379, + "placeInTop": null + }, + { + "id": 16899, + "code": "BabyXRdoge", + "issuer": "rH9mTEofDstHfgT83kutpT5fJgKxKBAvqv", + "title": "BabyXRdoge", + "trustlines": 5036, + "placeInTop": null + }, + { + "id": 52, + "code": "xNUTz", + "issuer": "rNutz8XfqZgVRDhtdo6Z2MeuVaqB9zfZkw", + "title": "XRPL NUTZ", + "trustlines": 5053, + "placeInTop": null + }, + { + "id": 16930, + "code": "MRG", + "issuer": "rHpwTr391FggkYS1PPkfkM4NGTgF57YuLC", + "title": "Merge MRG", + "trustlines": 5200, + "placeInTop": null + }, + { + "id": 16903, + "code": "xBullwife", + "issuer": "rHNdmrLoen999m7HJpTDVPtazcRzn9DMdH", + "title": "xBullwife", + "trustlines": 3942, + "placeInTop": null + }, + { + "id": 17999, + "code": "YOL", + "issuer": "rMJEj344HVDBVy5KH8fcnDfwQCmQ4H2HPF", + "title": "yourOwnLanguage NFT", + "trustlines": 8663, + "placeInTop": null + }, + { + "id": 16678, + "code": "BRM", + "issuer": "rBpYMFddcphoZDv5MswtyMp9hV6b49bEcV", + "title": "BerylliumNFT", + "trustlines": 4079, + "placeInTop": null + }, + { + "id": 16728, + "code": "XElon", + "issuer": "rfwbcU8RkmVaEEHhX2yqvLyw5xhaugbvSm", + "title": "XElon", + "trustlines": 5536, + "placeInTop": null + }, + { + "id": 11, + "code": "XMoon", + "issuer": "rEvV6gWZn2HgEr3nkj3xBmgCTqyWcknjMD", + "title": "XMoon", + "trustlines": 6506, + "placeInTop": null + }, + { + "id": 17974, + "code": "UFm", + "issuer": "rUNFLAKEnWicv4XsnoZrmSN1pXSWSMgZXc", + "title": "Unflake", + "trustlines": 7816, + "placeInTop": null + }, + { + "id": 18005, + "code": "KATANA", + "issuer": "r3uVTkdzg8BGvfChrpMetH5noSn5XawzMz", + "title": "xKATANA", + "trustlines": 7137, + "placeInTop": null + }, + { + "id": 16881, + "code": "XrplSquid", + "issuer": "rbgAh9aQV7ij8cNifgFgtiebU6vm9yXci", + "title": "Xrpl Squid", + "trustlines": 4071, + "placeInTop": null + }, + { + "id": 16804, + "code": "RCN", + "issuer": "r4GquJLRTAmEMLECBKaSMLB8pV4dmLWNxX", + "trustlines": 6501, + "placeInTop": null + }, + { + "id": 249, + "code": "MGS", + "issuer": "rHP4bHzghBdzskqcaPciL5WRGkHosB5zYx", + "title": "MG.Social", + "trustlines": 13074, + "placeInTop": null + }, + { + "id": 16748, + "code": "XLOTTO", + "issuer": "rHoPikA81frt2FSNaW5ZHdv6LfKZfeqguY", + "title": "XRP Lotto", + "trustlines": 3971, + "placeInTop": null + }, + { + "id": 315, + "code": "XBE", + "issuer": "rJvcZcc8BfJXvWtV7sGJPNXTgdv8AvXKRJ", + "title": "XBE | XBee Mekaverse NFT", + "trustlines": 6004, + "placeInTop": null + }, + { + "id": 16819, + "code": "EroticCoin", + "issuer": "rN7kuYm6QbuVHtcybjZcdjvHP1XNFtNjah", + "title": "EroticCoin", + "trustlines": 4465, + "placeInTop": null + }, + { + "id": 67, + "code": "ConservationCoin", + "issuer": "rU6JmvUpdxsx8gxLLgfcRhfz5ASNmGpSwm", + "title": "ConservationCoin", + "trustlines": 9868, + "placeInTop": null + }, + { + "id": 17929, + "code": "JPY", + "issuer": "r94s8px6kSw1uZ1MV98dhSRTvc6VMPoPcN", + "title": "TokyoJPY", + "trustlines": 7538, + "placeInTop": null + }, + { + "id": 18785, + "code": "xMFA", + "issuer": "rLBxKkudr4qCU3R6d3o1uKHmqrTqeyjSdr", + "title": "Mining Farm", + "trustlines": 5054, + "placeInTop": null + }, + { + "id": 314, + "code": "XCROC", + "issuer": "rpLw9SsJz52DpYWL5ohS2s71FgVeohHACQ", + "title": "XCROC", + "trustlines": 4812, + "placeInTop": null + }, + { + "id": 17342, + "code": "CNY", + "issuer": "rnuF96W4SZoCJmbHYBFoJZpR8eCaxNvekK", + "title": "rippleCN", + "trustlines": 5721, + "placeInTop": null + }, + { + "id": 16755, + "code": "XSMARTFOX", + "issuer": "rHRMqfYAPc73RtVeaywbESc3Zd49Ly9jyG", + "title": "XSMARTFOX", + "trustlines": 4163, + "placeInTop": null + }, + { + "id": 17077, + "code": "BANK", + "issuer": "rN7HDdMy9uq6tKY27ZhGTamZ1RG6pMWubE", + "title": "BANK", + "trustlines": 4767, + "placeInTop": null + }, + { + "id": 140, + "code": "FYX", + "issuer": "r91QDSnUm99ty84TNsv5ai4HufjFMsHJDF", + "title": "Fyrox", + "trustlines": 5370, + "placeInTop": null + }, + { + "id": 336, + "code": "BuffKittyRewards", + "issuer": "rHingngfqfmXVL4FKaeAsyrdW9eGVkGWr8", + "title": "XKITTY", + "trustlines": 3204, + "placeInTop": null + }, + { + "id": 239, + "code": "RDG", + "issuer": "rgJsp6hH3mXopHyW8yM85rJYSVy8NYgWr", + "trustlines": 3468, + "placeInTop": null + }, + { + "id": 18385, + "code": "MEOW", + "issuer": "rh1MUWz6HJGWQgRUwsVeRdiKR2cDBkZDDj", + "title": "MeowXrplsNfts", + "trustlines": 6000, + "placeInTop": null + }, + { + "id": 63, + "code": "Franklin", + "issuer": "rMgnr9ePkQbY23ZjzCyCu977viGTjRyFBT", + "title": "Franklin's", + "trustlines": 5237, + "placeInTop": null + }, + { + "id": 16733, + "code": "GUP", + "issuer": "rPrTFNxEEk29356c7LuriRTpornftmzG2c", + "title": "Guppiez", + "trustlines": 3378, + "placeInTop": null + }, + { + "id": 93, + "code": "Xcicada", + "issuer": "rE55raRDWcy4car7fhFQTaQ1ToYTyCDzz8", + "title": "Xcicada", + "trustlines": 6437, + "placeInTop": null + }, + { + "id": 70, + "code": "XWARS", + "issuer": "rLC88EkvQUmVM3PVzDejTBzRGx1hKwBsUf", + "trustlines": 7688, + "placeInTop": null + }, + { + "id": 18414, + "code": "LUAH", + "issuer": "rnVFEE67uFP4vNKtb2fPZwCuJAek5tnPrz", + "title": "Limited USD (LUSD)", + "trustlines": 4124, + "placeInTop": null + }, + { + "id": 16761, + "code": "XBCP", + "issuer": "rsxRfhJh9GZe1dcjH7XwL9rSr6AjQmiM9A", + "title": "XBCP | BLUECHIPX", + "trustlines": 3221, + "placeInTop": null + }, + { + "id": 16682, + "code": "XRYODA", + "issuer": "r344ghnxmqQf5GsyZobTwtAEn39kUcjVV1", + "title": "XRBB YODA", + "trustlines": 5331, + "placeInTop": null + }, + { + "id": 16853, + "code": "TULDOK", + "issuer": "r9qGMJMreNBYdEqJ7mNrUjyCj44fDUEe1G", + "title": "$TULDOK COIN", + "trustlines": 3028, + "placeInTop": null + }, + { + "id": 18893, + "code": "TSX", + "issuer": "rHTC7FLrK4NWnZRduLmXUDGWVQMrXarAvB", + "title": "Teleport", + "trustlines": 6146, + "placeInTop": null + }, + { + "id": 184, + "code": "xCorgi", + "issuer": "rERY8GCz7A1AN1RkDN1CkPVh8ids6PNgPP", + "title": "xCorgi | Fluff", + "trustlines": 6363, + "placeInTop": null + }, + { + "id": 18780, + "code": "LGX", + "issuer": "rP5VrjHKXTFwp1WYwVvhAc9KU9YmbN3rLC", + "title": "Logos XRP", + "trustlines": 3789, + "placeInTop": null + }, + { + "id": 18415, + "code": "KiLLeRcOiN", + "issuer": "rJMZZfwM1s3Pgy4fKzEgmK7YHf9wpUBg6w", + "trustlines": 2965, + "placeInTop": null + }, + { + "id": 66, + "code": "XGM", + "issuer": "rseMc5T1mqfMQB4pWt6XwwMKG6YhWEGnFv", + "title": "xGm", + "trustlines": 9427, + "placeInTop": null + }, + { + "id": 16861, + "code": "XPoets", + "issuer": "raQ1XkLHnUsrYqApWzX3pVirZdArG2h7x1", + "title": "XPoets", + "trustlines": 3046, + "placeInTop": null + }, + { + "id": 16844, + "code": "XHN", + "issuer": "rD1SDBGrD5XNN6NrXQWistmzfGX22foe3H", + "trustlines": 3874, + "placeInTop": null + }, + { + "id": 16953, + "code": "TRUMP", + "issuer": "rNRh1YobQDUuFyiXnUY9NJB7b2MLDJJGHg", + "title": "TrumpCoin", + "trustlines": 2778, + "placeInTop": null + }, + { + "id": 16620, + "code": "ANBU", + "issuer": "ratHp7D5w5bhDyxz9hiJGbBhny5kzJRu1f", + "title": "AnbuLegends", + "trustlines": 9571, + "placeInTop": null + }, + { + "id": 16943, + "code": "xBull", + "issuer": "rNpNdUKp631RXzqxbjjCYsJp6g8Q5T5cGh", + "title": "xBull", + "trustlines": 4777, + "placeInTop": null + }, + { + "id": 17823, + "code": "XDR", + "issuer": "r4SQf7WwtrbEXmv7XLasLiSvpoYRq6urQs", + "title": "XRP DROID", + "trustlines": 6291, + "placeInTop": null + }, + { + "id": 18148, + "code": "FLNGL", + "issuer": "rpzHixvdL2hZ6Y1kmkW4tFnnShq4Vgu691", + "title": "TheXFallenAngel", + "trustlines": 6054, + "placeInTop": null + }, + { + "id": 321, + "code": "Ethos", + "issuer": "rwxjYdik47PBJ2UsxseeoFdsa2LdAdaSQW", + "title": "Ethos", + "trustlines": 4679, + "placeInTop": null + }, + { + "id": 16769, + "code": "DNSK", + "issuer": "rDNSKmHYj6NZfy1hvxNaT1kyUChvJFerkd", + "title": "DNSK POKERHUB", + "trustlines": 2701, + "placeInTop": null + }, + { + "id": 247, + "code": "SPORT", + "issuer": "rwxwUwWpWAQK6jFRcW12Vx97riBu91MDPi", + "trustlines": 3980, + "placeInTop": null + }, + { + "id": 306, + "code": "Cultured", + "issuer": "rpFrFgdGnaQL7KFc9SPDYMd6YS3m4smscV", + "title": "Cultured Coin", + "trustlines": 3345, + "placeInTop": null + }, + { + "id": 18378, + "code": "OMENP", + "issuer": "rNS9dmNa8wNheRD5mZ8R4YtyWt7ySsYw2V", + "title": "OMEN Ltd.", + "trustlines": 5896, + "placeInTop": null + }, + { + "id": 16828, + "code": "sachay", + "issuer": "raj1sz7iCt6ZmGPp1vhZ7DjRjgxcTA889h", + "title": "SachayCoin", + "trustlines": 2795, + "placeInTop": null + }, + { + "id": 18733, + "code": "xRiddler", + "issuer": "rMKehfMwCNTBo3KoCZvqea35KNyatus3hy", + "title": "xRiddler", + "trustlines": 4882, + "placeInTop": null + }, + { + "id": 16747, + "code": "XBuddha", + "issuer": "rJRE6wwTSsPe5A7rRC2R3v2FbPVY7rbxuN", + "title": "XBuddha", + "trustlines": 2718, + "placeInTop": null + }, + { + "id": 16606, + "code": "XCASTLE", + "issuer": "rpU1YBKBCE3rnms5vwgXHHouLapVZv7KDu", + "title": "XCastleCoin", + "trustlines": 5612, + "placeInTop": null + }, + { + "id": 18702, + "code": "SNX", + "issuer": "rUhkGuauku4yw2tAPGZCV7atBSRXkgZ6pV", + "trustlines": 2925, + "placeInTop": null + }, + { + "id": 16770, + "code": "Voodoo", + "issuer": "rPE6vTZZyu32TK6FYtSd443TR9HXvayL5", + "title": "Voodoo", + "trustlines": 2594, + "placeInTop": null + }, + { + "id": 337, + "code": "ZEN", + "issuer": "rD2C8cVUEdu1o6hiaouxzMpZELRYnVZnh4", + "title": "nowandzen", + "trustlines": 2817, + "placeInTop": null + }, + { + "id": 18748, + "code": "ASH", + "issuer": "rGETqxutoKZ6VcXTE7Yh1fyaUj5pro7PuE", + "title": "AfterShock", + "trustlines": 3101, + "placeInTop": null + }, + { + "id": 16845, + "code": "1Mill", + "issuer": "rPWsEKUdVCgrKVM8x3ZbcdWY3eKTckziVH", + "title": "1MillClubXRPL", + "trustlines": 3147, + "placeInTop": null + }, + { + "id": 18616, + "code": "GAMECOIN", + "issuer": "rGRbhMeHyi5yi1x5vkFrZD8sHzkr5HfH3g", + "title": "GAMECOIN", + "trustlines": 2926, + "placeInTop": null + }, + { + "id": 16984, + "code": "xKyouko", + "issuer": "rpyNDFjy2W2wE3o5hB9HUiDCwvz26LeuXf", + "title": "xKyouko", + "trustlines": 3797, + "placeInTop": null + }, + { + "id": 18326, + "code": "LZAR", + "issuer": "rnGvMu8P6evJEYY4cPyzcy4N1m5gcYRjaH", + "title": "Limited USD (LUSD)", + "trustlines": 2513, + "placeInTop": null + }, + { + "id": 18637, + "code": "XMF", + "issuer": "rP6pULkW5nNsWYsy1wcf4p4YfkGrKCHeRe", + "title": "XMafia", + "trustlines": 6167, + "placeInTop": null + }, + { + "id": 139, + "code": "VCOXRP", + "issuer": "rDecvvWKRtfFhSB33nHWMZ6aZfknA1ngvo", + "title": "Valor University of the Future", + "trustlines": 2341, + "placeInTop": null + }, + { + "id": 16607, + "code": "MATE", + "issuer": "rpWapSyB4dPhjMms2cYMEmTfc6BGpbpZBv", + "title": "Mates | Premium NFTs", + "trustlines": 8484, + "placeInTop": null + }, + { + "id": 16846, + "code": "xdrop", + "issuer": "rwCZMiLKFd1Nct6MAJuhcD6ALv1h4UsyKf", + "title": "XdropXrpl", + "trustlines": 2565, + "placeInTop": null + }, + { + "id": 16858, + "code": "XPoems", + "issuer": "rH8hYUS6jr9dk3W96ZCYp8fcuwk5FGQEJG", + "title": "XPoets", + "trustlines": 2393, + "placeInTop": null + }, + { + "id": 18220, + "code": "LTWD", + "issuer": "rnyGDFEqnNwpyzievKCMhHUi4xs6HnUqPA", + "title": "Limited Currency TWD", + "trustlines": 2855, + "placeInTop": null + }, + { + "id": 193, + "code": "XCRA", + "issuer": "rNFDYKcnrUCjxaoUFzBYSiFHs2NLmXT1Gp", + "title": "XCRA NFT", + "trustlines": 6237, + "placeInTop": null + }, + { + "id": 18610, + "code": "JUMBO", + "issuer": "rLAstRsF3MWQfQw11gEsPyWvmR2oe5zXjE", + "title": "FLYING JUMBO", + "trustlines": 4313, + "placeInTop": null + }, + { + "id": 23, + "code": "MWG", + "issuer": "rGfKifFcz1mpobiRyKwNL7MoVjDoiefeYT", + "title": "MotionWreck Games", + "trustlines": 7097, + "placeInTop": null + }, + { + "id": 309, + "code": "xShasta", + "issuer": "rne1owrwbP5Q4W8LvH9BM9shjWNQ5dKwqZ", + "title": "xShasta", + "trustlines": 3636, + "placeInTop": null + }, + { + "id": 16957, + "code": "XRZodiac", + "issuer": "rwuPyekh28TpWgm2BZmC8vEddEmFSf4jb", + "title": "Zodiac XRP", + "trustlines": 2115, + "placeInTop": null + }, + { + "id": 275, + "code": "XRLZ", + "issuer": "rPVaiUCm98WPCtQbLhXkSk3prFR1aTZTmx", + "title": "XRILLAZ", + "trustlines": 3845, + "placeInTop": null + }, + { + "id": 16841, + "code": "XSHIB", + "issuer": "rJ1bzYHJq8MpGpBaw4mBChuUcAUME44CVg", + "title": "XSHIB", + "trustlines": 2750, + "placeInTop": null + }, + { + "id": 16962, + "code": "BNM", + "issuer": "rHEULEU5TQwCpnMoJVkaPX9TB9UrXWrZtF", + "title": "Block News Media (BNM,DAO)", + "trustlines": 2379, + "placeInTop": null + }, + { + "id": 329, + "code": "XSPUNK", + "issuer": "rPB7vXTeWrQ5nxEpQbLvay8nfJUJfeecYL", + "title": "XSPUNK", + "trustlines": 4810, + "placeInTop": null + }, + { + "id": 271, + "code": "INVST", + "issuer": "rsoiJStU1o7PLZcoqyQRsCtfWqchdNrcBZ", + "title": "InvestorCoin", + "trustlines": 2815, + "placeInTop": null + }, + { + "id": 18584, + "code": "ORG", + "issuer": "rPq1ReXJ8uEyyRf2BTMu5bj7nKsQ4JTgBu", + "title": "Snub Network", + "trustlines": 2574, + "placeInTop": null + }, + { + "id": 18688, + "code": "XRsilver", + "issuer": "rEAYBYLaar6Bih2ZZXTNWC14XcdRGeHoVk", + "title": "XRsilver \u2739", + "trustlines": 4760, + "placeInTop": null + }, + { + "id": 16727, + "code": "BMG", + "issuer": "rpR32FXJoGv5K9Qwyu3cW8dSCWeu29cy88", + "title": "Bullish Moments", + "trustlines": 2676, + "placeInTop": null + }, + { + "id": 17055, + "code": "DSH", + "issuer": "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", + "title": "GateHub DASH", + "trustlines": 13352, + "placeInTop": null + }, + { + "id": 18316, + "code": "RELM", + "issuer": "rKWXCzjycHKiV5c5VzR8M5NXbz5AJjB1fd", + "title": "ELEMENTUM RELMVERSE", + "trustlines": 4637, + "placeInTop": null + }, + { + "id": 16737, + "code": "Xgirls", + "issuer": "rDLfe8aoNDtrVA5BZC79j37cmhSYCHdHpm", + "title": "Xgirls", + "trustlines": 8106, + "placeInTop": null + }, + { + "id": 18489, + "code": "XAnime", + "issuer": "r9ij4uZm8tmDuWUigymNQZRkKRevGV3vv5", + "title": "XAnime Official", + "trustlines": 3725, + "placeInTop": null + }, + { + "id": 167, + "code": "BAYNANA", + "issuer": "rJ9uU9jKxNcsNQM2CLKUhPxNn8P4xmhDVq", + "title": "BAYNANA", + "trustlines": 3273, + "placeInTop": null + }, + { + "id": 18325, + "code": "LARS", + "issuer": "rnGvMu8P6evJEYY4cPyzcy4N1m5gcYRjaH", + "title": "Limited USD (LUSD)", + "trustlines": 2572, + "placeInTop": null + }, + { + "id": 16637, + "code": "COLORS", + "issuer": "r4R8yypDDRZjBBLsUmT3KNusmVPYs5YqSV", + "title": "XRPL COLORS", + "trustlines": 5148, + "placeInTop": null + }, + { + "id": 16653, + "code": "Becky", + "issuer": "rMNtmZNvBQqjd9AXyn9Gt4n2FVNt5LZiRD", + "title": "Bud Buddies", + "trustlines": 2946, + "placeInTop": null + }, + { + "id": 301, + "code": "DUSTNFT", + "issuer": "rpnZtxkk8hcNzPkaKF76wwoFVzcd9T211j", + "title": "DuStToToKeN", + "trustlines": 2095, + "placeInTop": null + }, + { + "id": 17938, + "code": "xSD", + "issuer": "rGbNLwrYNuPim39crh1bjyyauefF1VHPoj", + "title": "XrpWest", + "trustlines": 5147, + "placeInTop": null + }, + { + "id": 16812, + "code": "Bitcorn", + "issuer": "rMDtnJDp9naCLVhrUJM6t6baTcijmM8PtG", + "title": "Bitcorn", + "trustlines": 2242, + "placeInTop": null + }, + { + "id": 169, + "code": "POLAR", + "issuer": "rfdistkMFGQ7HAgu5JvsQdRHbm15EMgWmX", + "title": "xrPolarBears", + "trustlines": 8484, + "placeInTop": null + }, + { + "id": 17953, + "code": "Chamillions", + "issuer": "r3DuEtGbKxbvkJ3evEEmveCNzw5JTUaHed", + "title": "Chamillions | XRPL", + "trustlines": 2913, + "placeInTop": null + }, + { + "id": 18757, + "code": "PIT", + "issuer": "rN7NMsuSzrRJR3q969CQ2ctgLjnLcLZRer", + "title": "MR. Desert King", + "trustlines": 2562, + "placeInTop": null + }, + { + "id": 16638, + "code": "LEUR", + "issuer": "rfL4Sci2ag5hhkpDuqtWYov6j3mshVWLgU", + "title": "Limited Currency", + "trustlines": 3579, + "placeInTop": null + }, + { + "id": 104, + "code": "XRhino", + "issuer": "r4Bej4WbpCdSpYCvi1rETFyR6X2bzJYHoN", + "title": "XRhino NFT ( XRPL )", + "trustlines": 3621, + "placeInTop": null + }, + { + "id": 231, + "code": "LCNY", + "issuer": "rfL4Sci2ag5hhkpDuqtWYov6j3mshVWLgU", + "title": "Limited Currency", + "trustlines": 3000, + "placeInTop": null + }, + { + "id": 18079, + "code": "Universal", + "issuer": "r3Q5nzkGA9WDz2gCZ3ZSEy2yYseSASru3m", + "title": "universal-digital-assets", + "trustlines": 1870, + "placeInTop": null + }, + { + "id": 16859, + "code": "DarksideCoin", + "issuer": "rLL1yVgd48DX82zSSZrewqHWLvtQy2HN2X", + "trustlines": 1773, + "placeInTop": null + }, + { + "id": 18084, + "code": "Snow", + "issuer": "rBH11ewwW35V6fuyo79tYQvDn1C8MiHHo7", + "title": "xSNOW", + "trustlines": 1790, + "placeInTop": null + }, + { + "id": 17114, + "code": "LINR", + "issuer": "rfL4Sci2ag5hhkpDuqtWYov6j3mshVWLgU", + "title": "Limited Currency", + "trustlines": 6536, + "placeInTop": null + }, + { + "id": 17078, + "code": "XBIDEN", + "issuer": "rJKvGk8EEdmkrQuu24oJ6cSerMw7gT2jKz", + "title": "Joe Biden #XBIDEN #XRPL", + "trustlines": 2720, + "placeInTop": null + }, + { + "id": 17863, + "code": "XON", + "issuer": "rswdYCe1dy1LK2wA1Kcs9j8Za3UupBes3K", + "title": "XON", + "trustlines": 2086, + "placeInTop": null + }, + { + "id": 16610, + "code": "xPiggies", + "issuer": "rGH6hm9YcSog35ZuxKkbKbKftMmaTh9vXt", + "title": "XRPiggies", + "trustlines": 4104, + "placeInTop": null + }, + { + "id": 16824, + "code": "Dalgona", + "issuer": "rn88jxrNUWBfQR9hfoB2MDjiGcvbiV7M3o", + "title": "Dalgona Candy official", + "trustlines": 2413, + "placeInTop": null + }, + { + "id": 17975, + "code": "XRBytes", + "issuer": "rBYTeShhNnTGqUTXAd2dCPd6rVYVD1qeHL", + "title": "XRBytes", + "trustlines": 4377, + "placeInTop": null + }, + { + "id": 18533, + "code": "HOGX", + "issuer": "rwM9XzFHdCxnpNFjanc4Sd3N96cz8ip5pQ", + "title": "HOG X", + "trustlines": 2899, + "placeInTop": null + }, + { + "id": 16813, + "code": "AVegazCoin", + "issuer": "rGmjWPmd5oCJcvG7N45npLRaqL62whVFfJ", + "title": "AVegazCoin", + "trustlines": 1966, + "placeInTop": null + }, + { + "id": 17996, + "code": "XDRT", + "issuer": "r9Xw2WnvPBbgur6gqnevmyuRofWZuC4iNt", + "title": "XDRT_office", + "trustlines": 7389, + "placeInTop": null + }, + { + "id": 17190, + "code": "111", + "issuer": "rpwnicj25Rh3QEmdxCLRYVTf69ABHP9soy", + "title": "Angel Coin", + "trustlines": 2594, + "placeInTop": null + }, + { + "id": 16822, + "code": "AngelNFT", + "issuer": "rD6VQ6Qx95sVaYbLM2Qnqn6Fde4ijaaqsu", + "title": "Angel Coin", + "trustlines": 2126, + "placeInTop": null + }, + { + "id": 16655, + "code": "BoredPandas", + "issuer": "rMaPkHEY5zVoZ3XV482tm4fuMRnJTuoAZp", + "trustlines": 2397, + "placeInTop": null + }, + { + "id": 284, + "code": "Fractal", + "issuer": "rw9oZfkjNkaarwpyrTLjfHzfnUuoGFY8V8", + "title": "NFT Labs", + "trustlines": 2753, + "placeInTop": null + }, + { + "id": 18397, + "code": "XRSaga", + "issuer": "rnb3HAXaQX6J2RA2dZaTeNNDKMvc4N7B9k", + "title": "XRSaga", + "trustlines": 2770, + "placeInTop": null + }, + { + "id": 16661, + "code": "Xapes", + "issuer": "rB8Lrw5eY42Kk6DE6AwMiC1K4tyudg8URB", + "title": "Gorilla X Warfare", + "trustlines": 5253, + "placeInTop": null + }, + { + "id": 18675, + "code": "3DAPES", + "issuer": "rP58cvnsDBXmmGi2Cp4CZ2UV6v5muFFntZ", + "title": "3DAPES \u2122", + "trustlines": 9564, + "placeInTop": null + }, + { + "id": 18598, + "code": "XBAg", + "issuer": "rauUywaCisP1MaeZ67DHf4qKmXUBz7Traq", + "title": "B I T H E R O", + "trustlines": 2962, + "placeInTop": null + }, + { + "id": 18509, + "code": "chilledchimps", + "issuer": "rMSzPTgQVfZVQViNrG5zGA8899orcyavFL", + "title": "chilled x chimps", + "trustlines": 4209, + "placeInTop": null + }, + { + "id": 16875, + "code": "XPoet", + "issuer": "rHp991Ms5hV5f4NYoeUeCymmmAFMMt2to8", + "title": "XPoets", + "trustlines": 1561, + "placeInTop": null + }, + { + "id": 16920, + "code": "ChildSupport", + "issuer": "rU97WDGnPtrUXT1qw1Fqk5VKS41gi8UQgD", + "title": "Child Support Token", + "trustlines": 4071, + "placeInTop": null + }, + { + "id": 16630, + "code": "VCZ", + "issuer": "rJ3GrAXX821D7XnnMgndBGe6CgZnEHXr1o", + "title": "VincenzoNFT", + "trustlines": 2078, + "placeInTop": null + }, + { + "id": 4, + "code": "xCross", + "issuer": "rDZzGy4YnpjKSvWsToHRCcGvcyinjuKEv9", + "title": "XRPCross", + "trustlines": 5639, + "placeInTop": null + }, + { + "id": 17018, + "code": "PNP", + "issuer": "r98XNSpxf7fHLfdBupcjiMWMdNmhq74Pnp", + "trustlines": 1477, + "placeInTop": null + }, + { + "id": 18448, + "code": "DOG", + "issuer": "rHkqAyggqiSvhBdrvfbCbzqbD6nUyGy2CQ", + "title": "Doggy coin", + "trustlines": 3653, + "placeInTop": null + }, + { + "id": 16649, + "code": "XReefs", + "issuer": "rN1fBKQdLRcMUG8VCDihKPqmTgBfgSu4rm", + "trustlines": 4228, + "placeInTop": null + }, + { + "id": 19042, + "code": "BTC", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 4031, + "placeInTop": null + }, + { + "id": 17876, + "code": "EMOJISQUAD", + "issuer": "rpFNHu3W8g6CvvdCgvwRaQidpRGrGnpwg3", + "title": "XRemojisquad", + "trustlines": 1460, + "placeInTop": null + }, + { + "id": 18214, + "code": "LBRL", + "issuer": "rnyGDFEqnNwpyzievKCMhHUi4xs6HnUqPA", + "title": "Limited Currency BRL", + "trustlines": 2682, + "placeInTop": null + }, + { + "id": 246, + "code": "XSG", + "issuer": "rN7RrccWk5hbZQEX4f5ED3zuLuFKNiT64", + "trustlines": 1788, + "placeInTop": null + }, + { + "id": 260, + "code": "MAYC", + "issuer": "rfdjz9HVpd5ixQE6LBK2cZT9XhJEYpgBtC", + "title": "Monster Ape XRP Club", + "trustlines": 2488, + "placeInTop": null + }, + { + "id": 17536, + "code": "BRL", + "issuer": "rfNZPxoZ5Uaamdp339U9dCLWz2T73nZJZH", + "title": "Rippex", + "trustlines": 2542, + "placeInTop": null + }, + { + "id": 154, + "code": "xVerse", + "issuer": "rfQ6YtuSMVY25mJ9XhN35gHiwotiASvfyS", + "title": "xVerse", + "trustlines": 3802, + "placeInTop": null + }, + { + "id": 17012, + "code": "HOG", + "issuer": "rwwjSYw5X2YPWRZ6cebeYUFkBLyh8tT71B", + "trustlines": 2344, + "placeInTop": null + }, + { + "id": 18123, + "code": "XCHAM", + "issuer": "rKmrHQFrixTEV4z8JPhFLFyzsN8ZGtYkS5", + "title": "XCHAMELEONS / $XCHAM XRPL \ud83e\udd8e", + "trustlines": 5780, + "placeInTop": null + }, + { + "id": 17309, + "code": "XLM", + "issuer": "rKiCet8SdvWxPXnAgYarFUXMh1zCPz432Y", + "title": "Ripple Fox", + "trustlines": 2344, + "placeInTop": null + }, + { + "id": 288, + "code": "DTT", + "issuer": "r3ygvUawCTEPZ7kosTktJ963K3KcrGXbGS", + "title": "DuStToToKeN", + "trustlines": 1762, + "placeInTop": null + }, + { + "id": 297, + "code": "XSWAP", + "issuer": "rDBWu8fWvxaY9dgNQXy2MYVtm3TRNY5FqE", + "trustlines": 2218, + "placeInTop": null + }, + { + "id": 16907, + "code": "ZULU", + "issuer": "rLcoMGVSZDWz3rWheEbPpeQMq2MNfmUoLb", + "title": "JustBull", + "trustlines": 1345, + "placeInTop": null + }, + { + "id": 18320, + "code": "LAED", + "issuer": "rnGvMu8P6evJEYY4cPyzcy4N1m5gcYRjaH", + "title": "Limited USD (LUSD)", + "trustlines": 2169, + "placeInTop": null + }, + { + "id": 300, + "code": "XKITTY", + "issuer": "rDzxZghEmGVRAvbpNSDbHGPgETkqHiZ5di", + "title": "XKITTY", + "trustlines": 2207, + "placeInTop": null + }, + { + "id": 17188, + "code": "SENIACOIN", + "issuer": "rpoHuxKPrqTfkH7L4cQwtNRKZzszWG6uyZ", + "trustlines": 1978, + "placeInTop": null + }, + { + "id": 18327, + "code": "LCAD", + "issuer": "rnGvMu8P6evJEYY4cPyzcy4N1m5gcYRjaH", + "title": "Limited USD (LUSD)", + "trustlines": 1917, + "placeInTop": null + }, + { + "id": 18301, + "code": "XDV", + "issuer": "rUd5EHPczA1dxLkc43svhfX5htRvQzFHdX", + "title": "The Vault", + "trustlines": 2148, + "placeInTop": null + }, + { + "id": 16922, + "code": "cryptopokecoin", + "issuer": "rMWEKWXeSFEM64mUfA83TNvBh8pogRQzNw", + "title": "Cryptopokecoin", + "trustlines": 1264, + "placeInTop": null + }, + { + "id": 18215, + "code": "LVEB", + "issuer": "rnyGDFEqnNwpyzievKCMhHUi4xs6HnUqPA", + "title": "Limited Currency USD", + "trustlines": 2396, + "placeInTop": null + }, + { + "id": 17637, + "code": "QAU", + "issuer": "r3ttJ41YnMrKiLqGUXJpQE8urqyMGjC8vE", + "title": "GateHub Fifth", + "trustlines": 7903, + "placeInTop": null + }, + { + "id": 15, + "code": "BisonArmy", + "issuer": "rKewBkTsHrjWiDTnsrAB2kjTg9bkCTMMyc", + "title": "Bison Army", + "trustlines": 14137, + "placeInTop": null + }, + { + "id": 18811, + "code": "XRPLTGT", + "issuer": "rspdZ6yA1VKPcA2fJxKeWUfmcrqRrF9CJ9", + "trustlines": 1289, + "placeInTop": null + }, + { + "id": 18545, + "code": "MKT", + "issuer": "rMD4eSH2doKurPNy6K3bQ6Hx1Z7EhoXnY2", + "title": "MetaKnight360 XRPL", + "trustlines": 3663, + "placeInTop": null + }, + { + "id": 16830, + "code": "LIFE", + "issuer": "rMmg2nrgRAJupwXJRAtEMqmezzHFAStE76", + "title": "LIFE COIN FUND", + "trustlines": 2189, + "placeInTop": null + }, + { + "id": 16889, + "code": "XCHIBI", + "issuer": "rKjxYk6pocyAJHD8k34tq1h6FGYCkwsoLG", + "title": "XCHIBI | NFT Collection", + "trustlines": 4322, + "placeInTop": null + }, + { + "id": 18922, + "code": "THECITYOFGIEZWA", + "issuer": "raiata7DoTJL5CMHuYC8BYGE6J4psyCMcE", + "title": "THE CITY OF GIEZWA", + "trustlines": 1424, + "placeInTop": null + }, + { + "id": 18258, + "code": "XDOWO", + "issuer": "r3RBkBa2hvfW2iZLj8yKo9PDeFCH9n9Ww1", + "trustlines": 1834, + "placeInTop": null + }, + { + "id": 16771, + "code": "FloydCoin", + "issuer": "rKF4FfwcjQK6pCJPFZ6xYmvmgynaf5DXTw", + "title": "George Floyd Coin", + "trustlines": 1204, + "placeInTop": null + }, + { + "id": 18004, + "code": "DSF", + "issuer": "rsiSiZosBx2kiz1sRd1NEi838qWumVXzqx", + "title": "DeepSpaceFlare", + "trustlines": 2338, + "placeInTop": null + }, + { + "id": 18447, + "code": "xALPACA", + "issuer": "rhjyUA6MVvx26XnRZsTfFkPGkyov7s2H4d", + "title": "Alpaca NFTs", + "trustlines": 1796, + "placeInTop": null + }, + { + "id": 106, + "code": "Xvroom", + "issuer": "rNio2YtPkiAvQMTFSCQPmPhjMdkMzWrLAS", + "title": "Xvroom", + "trustlines": 3564, + "placeInTop": null + }, + { + "id": 16642, + "code": "OSSA", + "issuer": "rEidsGjRCX8VYQdMtY9hLMzj8cNMFdqzWp", + "title": "Calvaria", + "trustlines": 5134, + "placeInTop": null + }, + { + "id": 16964, + "code": "CubanCoin", + "issuer": "rsF3pzhPeSFdMKCVWuRF9k36Xt1qXFyLsF", + "trustlines": 2519, + "placeInTop": null + }, + { + "id": 203, + "code": "LogoArt", + "issuer": "rGQLkT1U7K3S9pGiXFrQKtsVuLHc9PumKY", + "title": "LogoArt", + "trustlines": 4161, + "placeInTop": null + }, + { + "id": 18968, + "code": "DTG", + "issuer": "rqUktVQrvc7f7mMHxLk4mvqPXVut4cUzP", + "title": "DatingXRPL", + "trustlines": 2092, + "placeInTop": null + }, + { + "id": 17214, + "code": "ZERO", + "issuer": "rfH4wavPbouU5bceEuP2Y7vrwVzKLdZero", + "trustlines": 1681, + "placeInTop": null + }, + { + "id": 18596, + "code": "ATMT", + "issuer": "rPXFg78B1b4ZSisfdibXztT5kPmp5HTDXe", + "title": "ARNILLA STUDIOS", + "trustlines": 8170, + "placeInTop": null + }, + { + "id": 18778, + "code": "XJMP", + "issuer": "rB64rftMocgcJtYN1E7P1B75z1JmrVUWnW", + "title": "XJumper", + "trustlines": 3071, + "placeInTop": null + }, + { + "id": 16913, + "code": "PHP", + "issuer": "rBpQSMUo4pJGcwkDJxhxg9K9Vmq4Kt4d8H", + "title": "Xrpl Squid", + "trustlines": 1747, + "placeInTop": null + }, + { + "id": 16746, + "code": "XBUGS", + "issuer": "rLAMN7QmVfrGJdt6mb4pZsp8rSjKosTfaJ", + "title": "XRBUGS", + "trustlines": 2952, + "placeInTop": null + }, + { + "id": 16878, + "code": "XPoem", + "issuer": "rBXM5Q2GaWqt3ARThHAd9A3Q6MBPwdAJG8", + "title": "XPoets", + "trustlines": 1206, + "placeInTop": null + }, + { + "id": 244, + "code": "XLION", + "issuer": "rU6ANcasdcDmRiF9JuW2rj7KYmPGKAEUYy", + "title": "LAME LIONS XRPL / $XLION", + "trustlines": 4312, + "placeInTop": null + }, + { + "id": 16797, + "code": "GigCoin", + "issuer": "rEF5RN6VkfEvkHeK9tkTodV8Cj9bhnM1Qj", + "title": "GigCoin", + "trustlines": 4152, + "placeInTop": null + }, + { + "id": 16988, + "code": "EGL", + "issuer": "r44zdwNnFAYFW89hUhsz52m31paXnWvySg", + "trustlines": 2753, + "placeInTop": null + }, + { + "id": 18065, + "code": "KNIFES", + "issuer": "rBdhf3SADW7ZXk6VaCDM9Pzq5FkKngNVF7", + "title": "META WEAPON (XRPL)", + "trustlines": 5706, + "placeInTop": null + }, + { + "id": 16827, + "code": "NerdX", + "issuer": "rUBbS5qeACf13KtqGUigr9rUDqZL7PLAT7", + "title": "NerdX", + "trustlines": 2322, + "placeInTop": null + }, + { + "id": 16803, + "code": "KING", + "issuer": "rPxEDPLfNp18mmhnmgn8pnxdWqo8UfnhRy", + "title": "King Coin", + "trustlines": 4076, + "placeInTop": null + }, + { + "id": 330, + "code": "xLordeEdge", + "issuer": "rnQPyTLGVD1exGZCBD9XcXvbedMG7Sy4iU", + "title": "XLEcoin", + "trustlines": 3743, + "placeInTop": null + }, + { + "id": 17152, + "code": "XmemeGoldBox", + "issuer": "r9w99F78djkcfJ6X9AKuowGvk42YYs4Fz4", + "title": "XmemeGoldBox", + "trustlines": 1146, + "placeInTop": null + }, + { + "id": 16674, + "code": "XGalaxyDust", + "issuer": "rJ3SiADSaiMu5YaygY94pE4X4PCwHECg7a", + "title": "XGalaxy", + "trustlines": 1035, + "placeInTop": null + }, + { + "id": 30, + "code": "XRParmy", + "issuer": "rDFqUqByvp86TmNppRT4svFrpZwnsymnvU", + "title": "XRP Army Coin", + "trustlines": 4945, + "placeInTop": null + }, + { + "id": 18752, + "code": "XME", + "issuer": "rana9qGVUedcBGeEXjECMnTcMRQvL9GCvW", + "trustlines": 2571, + "placeInTop": null + }, + { + "id": 16768, + "code": "LFGO", + "issuer": "rBETMo1JSfigtMfU8kBem95vKcFmjG9gSw", + "trustlines": 2953, + "placeInTop": null + }, + { + "id": 263, + "code": "GUY", + "issuer": "rJmKe5N1JPa4ocst5MAbVpu3Ggzv4kdVku", + "title": "XRPL GUYS / $GUY", + "trustlines": 2344, + "placeInTop": null + }, + { + "id": 348, + "code": "HappyRacoon", + "issuer": "rBq2VLqRcthMU57n6Nw9125PF1Mxng4uyq", + "title": "HappyRacoon", + "trustlines": 4737, + "placeInTop": null + }, + { + "id": 170, + "code": "XMW", + "issuer": "ra2hRLUM28o9XYEHdyqKvFurXa5EYNqApE", + "title": "MicroWorld", + "trustlines": 3450, + "placeInTop": null + }, + { + "id": 18807, + "code": "JPY", + "issuer": "rMAz5ZnK73nyNUL4foAvaxdreczCkG3vA6", + "title": "Ripple Trade Japan", + "trustlines": 2668, + "placeInTop": null + }, + { + "id": 18976, + "code": "HDG", + "issuer": "rsKKfXJ3txRq12JSs9xxv9BMBYGFWWCQNo", + "title": "HolddiamondGold", + "trustlines": 1450, + "placeInTop": null + }, + { + "id": 310, + "code": "xSHIBOSHIS", + "issuer": "rUH4VReNsA3eQZY86TAbErBz49GdZGqHzJ", + "title": "xSHIBOSHIS", + "trustlines": 3638, + "placeInTop": null + }, + { + "id": 17848, + "code": "KRW", + "issuer": "rUkMKjQitpgAM5WTGk79xpjT38DEJY283d", + "title": "Pax Moneta", + "trustlines": 1999, + "placeInTop": null + }, + { + "id": 17107, + "code": "REP", + "issuer": "rckzVpTnKpP4TJ1puQe827bV3X4oYtdTP", + "title": "GateHub REP", + "trustlines": 18818, + "placeInTop": null + }, + { + "id": 16790, + "code": "GomiCoin", + "issuer": "r3jDb7aM3UDGSttVNcC7pxz1akGmPRsDkN", + "trustlines": 1934, + "placeInTop": null + }, + { + "id": 158, + "code": "XCL", + "issuer": "rswu4hb6GhDse1CGEisZrYhCCAPPbDDcAp", + "title": "XCLONE NFTS", + "trustlines": 4152, + "placeInTop": null + }, + { + "id": 17040, + "code": "xDave", + "issuer": "rDaVeTZrFWNz9uFxf3bqdPTpLAsNc1fDF7", + "trustlines": 1266, + "placeInTop": null + }, + { + "id": 214, + "code": "XHH", + "issuer": "rJWRqdKTRfqoeHERBDJukWWNTRrnwayDca", + "title": "HodlHippos", + "trustlines": 3583, + "placeInTop": null + }, + { + "id": 18684, + "code": "FOX", + "issuer": "rNrLLdKFEZaw1Bao6Twjes7Jm4jHg1rthU", + "trustlines": 1413, + "placeInTop": null + }, + { + "id": 113, + "code": "XMZ", + "issuer": "rfyE95hzWAE93h2sKvW92nX3Mf6eC3Vs7D", + "title": "xrplmonkeyz", + "trustlines": 2289, + "placeInTop": null + }, + { + "id": 16829, + "code": "FGARY", + "issuer": "rKYsFjADNw4ZVdN5CEvpDUBJndktRGYUrK", + "title": "F**k Gary", + "trustlines": 941, + "placeInTop": null + }, + { + "id": 16652, + "code": "xThug", + "issuer": "rULz7kXrUkXDqPvW5t3PrBn8XJ3GJytqUi", + "title": "xThug", + "trustlines": 4342, + "placeInTop": null + }, + { + "id": 82, + "code": "JSC", + "issuer": "rJ726mi7cXLfsnuehL84nmjjK14Rmx2ZQG", + "title": "Junkies | The Junkiverse | Junction", + "trustlines": 3686, + "placeInTop": null + }, + { + "id": 18453, + "code": "V3SafeMoon", + "issuer": "rENCYqb6HKcCRbRWBuufG1vwZp7JFe6pBE", + "title": "SafeMoonV3XRPL", + "trustlines": 3115, + "placeInTop": null + }, + { + "id": 16831, + "code": "BADxTruckzNFT", + "issuer": "rKas8SuSUBs7qQ7TaC1fQw3sviXBethJ2r", + "title": "BADxTruckz", + "trustlines": 1564, + "placeInTop": null + }, + { + "id": 18846, + "code": "nftwest", + "issuer": "rGxTL4RgJeJcN3SySxAQMnMnWXDEELjMfk", + "trustlines": 2279, + "placeInTop": null + }, + { + "id": 16893, + "code": "xLetsGoBrandon", + "issuer": "rpXQdkj19vvcEdoF6vqkbEkkFkyn4QN2sq", + "title": "XTRUMP", + "trustlines": 2081, + "placeInTop": null + }, + { + "id": 17153, + "code": "XmemeGoldenSmile", + "issuer": "rKNfnXcioJdKikc5hcwSrcxaqjdHwYRqMU", + "title": "XmemeGoldenSmile", + "trustlines": 942, + "placeInTop": null + }, + { + "id": 17087, + "code": "FEST", + "issuer": "rGXQdR5z5ykUjAUnyxJBT66ZpLnCua31q5", + "trustlines": 929, + "placeInTop": null + }, + { + "id": 17590, + "code": "XAG", + "issuer": "rpG9E7B3ocgaKqG7vmrsu3jmGwex8W4xAG", + "title": "Xrpalike Gene", + "trustlines": 1547, + "placeInTop": null + }, + { + "id": 79, + "code": "SLX", + "issuer": "rpzM9uVZ8NqQA1pcamhtd9afKaWLLG5rke", + "title": "Skullaxa", + "trustlines": 4279, + "placeInTop": null + }, + { + "id": 17710, + "code": "EUR", + "issuer": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q", + "title": "SnapSwap", + "trustlines": 1833, + "placeInTop": null + }, + { + "id": 16699, + "code": "Xmonk", + "issuer": "rKuFp7TsTtQk7EXQthSAqiz7rwiFsaVtzG", + "trustlines": 5330, + "placeInTop": null + }, + { + "id": 209, + "code": "PENG", + "issuer": "rf668i9G2d6Xd39tZF19uKGLV3XsvrxFw7", + "title": "TheXRPenguins", + "trustlines": 3898, + "placeInTop": null + }, + { + "id": 17695, + "code": "ADA", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 1318, + "placeInTop": null + }, + { + "id": 285, + "code": "XSplash", + "issuer": "rw3Xyya7wcGvJsbuF2oSVY5BcR9pvbtRAR", + "title": "Xsplash", + "trustlines": 2369, + "placeInTop": null + }, + { + "id": 16961, + "code": "BANANA", + "issuer": "r3KSyXmYTYd6wd6ZwtrbEhQMjnJW3xpK4j", + "title": "Club X NFT - Bearable Bulls coming soon", + "trustlines": 1576, + "placeInTop": null + }, + { + "id": 16786, + "code": "XRPayNet", + "issuer": "r9rRLst96Ue4YTDQkWWkX1ePB6p6Ye4FkA", + "title": "XRPayNet", + "trustlines": 2510, + "placeInTop": null + }, + { + "id": 17024, + "code": "XMEMEXquisiteGcoin", + "issuer": "rDCCBV7riXcnQ3r345sqGJfqXFLpCfMUqd", + "title": "XMEMEXquisiteGcoin", + "trustlines": 856, + "placeInTop": null + }, + { + "id": 17708, + "code": "RJP", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 1844, + "placeInTop": null + }, + { + "id": 18561, + "code": "CAD", + "issuer": "r3ADD8kXSUKHd6zTCKfnKT3zV9EZHjzp1S", + "title": "RippleUnion", + "trustlines": 992, + "placeInTop": null + }, + { + "id": 18296, + "code": "SeagullMansions", + "issuer": "rHr4mUQjRusoNNYnzCp5BFumyWjycgVHJS", + "trustlines": 1808, + "placeInTop": null + }, + { + "id": 18465, + "code": "USDC", + "issuer": "rcEGREd8NmkKRE8GE424sksyt1tJVFZwu", + "title": "GateHub USDC", + "trustlines": 3407, + "placeInTop": null + }, + { + "id": 16999, + "code": "RIBBITS", + "issuer": "rPmb5BPBAbE9jmNaFXNPH5kZEPDpRxaY77", + "trustlines": 1749, + "placeInTop": null + }, + { + "id": 16796, + "code": "MGT", + "issuer": "rwpQQdPJZmnGFNrPfbtCjtStdBxZK8qs3W", + "trustlines": 2857, + "placeInTop": null + }, + { + "id": 17533, + "code": "XNF", + "issuer": "rPKSvQ1qFAksr7hzk2wC2xtqSqFbxP3wvg", + "title": "NoFiatCoin", + "trustlines": 1495, + "placeInTop": null + }, + { + "id": 17189, + "code": "EmojiCoin", + "issuer": "rP7RsraS3viv9kGb4XNCY1N7JyaniDJB2z", + "title": "EmojiCoin", + "trustlines": 746, + "placeInTop": null + }, + { + "id": 155, + "code": "XALANA", + "issuer": "r8zkzkjvHxTFDkHJrqpssCd5HDUjCgxck", + "title": "Xalana", + "trustlines": 7170, + "placeInTop": null + }, + { + "id": 16704, + "code": "EGG", + "issuer": "rfwgeFU65NdYN5xDmogu9gB3hroYFhAqnL", + "title": "$BUN/$EGG", + "trustlines": 1098, + "placeInTop": null + }, + { + "id": 18692, + "code": "BTFD", + "issuer": "rERyZhzaBHjMcm3Cm1Gh8c4Vw1gPusFuLf", + "title": "Buythedip", + "trustlines": 842, + "placeInTop": null + }, + { + "id": 176, + "code": "BMA", + "issuer": "rVosg6X2B873FwaVZPM44CMjccSG5Ha6E", + "title": "BMAC - Blind Mummy Apes Club", + "trustlines": 3044, + "placeInTop": null + }, + { + "id": 18918, + "code": "CQR", + "issuer": "rpuEFKFoKESeoTMusx73znFGjbPqxiTPyg", + "title": "CQRFinance", + "trustlines": 1115, + "placeInTop": null + }, + { + "id": 138, + "code": "CCB", + "issuer": "rBxoALcypxTDYbkJr8MWLeUPYq64vAQpT4", + "title": "CucumberBrothers", + "trustlines": 6945, + "placeInTop": null + }, + { + "id": 19076, + "code": "ETH", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 2407, + "placeInTop": null + }, + { + "id": 17359, + "code": "NUDES", + "issuer": "rUckw1CEPF2vacf2o53kLDk4oLZd7Ha4LT", + "title": "Nudes Token", + "trustlines": 701, + "placeInTop": null + }, + { + "id": 18535, + "code": "XGBALLZ", + "issuer": "rPa8cmndFgf5sexbYDGaU3zx83qAWrBKrc", + "title": "XungiBallz", + "trustlines": 2411, + "placeInTop": null + }, + { + "id": 17588, + "code": "JCB", + "issuer": "rBfVgTnsdh8ckC19RM8aVGNuMZnpwrMP6n", + "trustlines": 5952, + "placeInTop": null + }, + { + "id": 17159, + "code": "xToadzXXL", + "issuer": "rhiagNCMcF342muHW6oMgdsf9uutCWv5Vw", + "title": "xToadz & sToadz", + "trustlines": 1540, + "placeInTop": null + }, + { + "id": 317, + "code": "SigmaFinance", + "issuer": "rpU72WXz1b9bnq4ZePgMvddovTwFXxY2Ar", + "title": "Sigma Finance", + "trustlines": 3227, + "placeInTop": null + }, + { + "id": 355, + "code": "xPEPE", + "issuer": "rw5e5krAvv1DrWyzmEr1NtNzg5jR26u5Gj", + "title": "xPEPE", + "trustlines": 1473, + "placeInTop": null + }, + { + "id": 17922, + "code": "CNY", + "issuer": "rM8199qFwspxiWNZRChZdZbGN5WrCepVP1", + "title": "DotPayco", + "trustlines": 1231, + "placeInTop": null + }, + { + "id": 293, + "code": "xKangaMK1", + "issuer": "rPwdrA6YFGR6k5rPyT6QPx7MrQAavUtyz5", + "title": "Combat Kanga", + "trustlines": 3022, + "placeInTop": null + }, + { + "id": 19106, + "code": "WTC", + "issuer": "rHZP1pA3THovFqvwgtM2tnJWrS54hSrDiG", + "trustlines": 801, + "placeInTop": null + }, + { + "id": 16721, + "code": "SRCIC", + "issuer": "rPnUe2Weo2JhMaXzkLHVkvdLxvVppEdkcr", + "title": "Sinceresponse", + "trustlines": 1683, + "placeInTop": null + }, + { + "id": 16679, + "code": "Xdinominers", + "issuer": "rH35xqtkhQPzYr8jyzp1rHbiG17KpuXa1s", + "title": "Xislanders_XDNT_Xdinos", + "trustlines": 3394, + "placeInTop": null + }, + { + "id": 18458, + "code": "MINT", + "issuer": "rwCsCz93A1svS6Yv8hFqUeKLdTLhBpvqGD", + "title": "\ud83e\ude84 MagicMint \ud83c\udf43", + "trustlines": 1736, + "placeInTop": null + }, + { + "id": 16692, + "code": "BZS", + "issuer": "rwNRkFw1zkELgiaGDEAYVhtZo9ogxSAXPD", + "title": "BALL ZACK SYNDICATE", + "trustlines": 2178, + "placeInTop": null + }, + { + "id": 17028, + "code": "IWC", + "issuer": "rPjWvuHydeXvkbXnjEX6gutkzxuN23Wuh4", + "title": "Islamic World Coin Community", + "trustlines": 896, + "placeInTop": null + }, + { + "id": 17761, + "code": "DOG", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 1630, + "placeInTop": null + }, + { + "id": 17321, + "code": "JKY", + "issuer": "rMi5Xw5Wi99SAqFfuWNAJZXwEMhBk4syHG", + "trustlines": 596, + "placeInTop": null + }, + { + "id": 17023, + "code": "AZHT", + "issuer": "rpNFcwPV9STzW8jaa2Hqt3MhbSRnkbkAof", + "title": "Joe(XRP)Cool", + "trustlines": 1712, + "placeInTop": null + }, + { + "id": 18723, + "code": "XRPhone", + "issuer": "rGzzsoiXsM3RmHU9Fu9eDQ6hoNoouyQiNT", + "title": "XRPhone", + "trustlines": 16299, + "placeInTop": null + }, + { + "id": 17587, + "code": "CNY", + "issuer": "rBfVgTnsdh8ckC19RM8aVGNuMZnpwrMP6n", + "trustlines": 2925, + "placeInTop": null + }, + { + "id": 18195, + "code": "Modulr", + "issuer": "rzxFbGjPaW6jE2WyzqmEHKhbSQmMkkJdr", + "trustlines": 571, + "placeInTop": null + }, + { + "id": 17674, + "code": "X20", + "issuer": "rNmdY5wPVTx9awvX6WyDfJwbdgLzc8AY8c", + "title": "XLS-20.art", + "trustlines": 8838, + "placeInTop": null + }, + { + "id": 16842, + "code": "icoin", + "issuer": "rJSTh1VLk52tFC3VRXkNWu7Q4nYmfZv7BZ", + "title": "Icoin", + "trustlines": 7614, + "placeInTop": null + }, + { + "id": 358, + "code": "xLoveMonster", + "issuer": "rsQRCHYZzsSjMpAs63TtPFkittdJzY3gET", + "title": "Love Monster", + "trustlines": 12418, + "placeInTop": null + }, + { + "id": 19104, + "code": "JPY", + "issuer": "rDKcJtUW5b8URJB5AVb41jkTeETfXWwahe", + "trustlines": 2469, + "placeInTop": null + }, + { + "id": 295, + "code": "PPT", + "issuer": "rpdRSNVE5UU26ewDzJZs4afEwkTvCHXwVA", + "title": "Pretty Pandas SGB", + "trustlines": 1947, + "placeInTop": null + }, + { + "id": 17877, + "code": "XZOMBIE", + "issuer": "rpwJD6xNmDTq28jcBmAem8KMGLSYChZRpR", + "title": "XZOMBIE", + "trustlines": 3217, + "placeInTop": null + }, + { + "id": 18638, + "code": "PCSH", + "issuer": "rEQqDLHYBA5cLuVpm3by6kaThvZQJL8q68", + "title": "xPEPE", + "trustlines": 855, + "placeInTop": null + }, + { + "id": 326, + "code": "HIGH", + "issuer": "raDF491dC9XF1guG5zZkWWpNQoFquwt2cp", + "trustlines": 2828, + "placeInTop": null + }, + { + "id": 18224, + "code": "GCB", + "issuer": "rUXUGrsSgqya9CxiA4oxzSgNmDhsb6qZ6c", + "trustlines": 601, + "placeInTop": null + }, + { + "id": 17355, + "code": "XZV", + "issuer": "r4JgusJLQt1sMsUEnXSFAXPNnbCocs6Fxf", + "title": "Officialexcluzeev", + "trustlines": 6604, + "placeInTop": null + }, + { + "id": 177, + "code": "KegsRP", + "issuer": "rJzCA6r1UXKLxVpLf31XVb5Na57hYYZ6n2", + "title": "KegsRPIssuer", + "trustlines": 1971, + "placeInTop": null + }, + { + "id": 318, + "code": "Munchies", + "issuer": "raDF491dC9XF1guG5zZkWWpNQoFquwt2cp", + "trustlines": 2825, + "placeInTop": null + }, + { + "id": 18512, + "code": "HAV", + "issuer": "rPjKLDFj3jXMTBFFw8ZUZbjrTWm63DEPYN", + "trustlines": 895, + "placeInTop": null + }, + { + "id": 16834, + "code": "Yonix", + "issuer": "rHXqJwSnD21pFY7NyRuZ1AUX7WYaK7V7sJ", + "title": "Yoniverse", + "trustlines": 1606, + "placeInTop": null + }, + { + "id": 18913, + "code": "ALBA", + "issuer": "rPzvaUJzQ7EVxuPYXPfwLtSRXGpfxDGt9h", + "title": "ALBA", + "trustlines": 521, + "placeInTop": null + }, + { + "id": 18459, + "code": "USDT", + "issuer": "rcvxE9PS9YBwxtGg1qNeewV6ZB3wGubZq", + "title": "GateHub USDT", + "trustlines": 1737, + "placeInTop": null + }, + { + "id": 17052, + "code": "LTC", + "issuer": "rcRzGWq6Ng3jeYhqnmM4zcWcUh69hrQ8V", + "title": "GateHub LTC", + "trustlines": 2216, + "placeInTop": null + }, + { + "id": 110, + "code": "XRSharPei", + "issuer": "rQHp4ipKWh4M53omvbkhwZXYjwQVXXycPb", + "title": "Linsey Bracken", + "trustlines": 539, + "placeInTop": null + }, + { + "id": 6, + "code": "TAC", + "issuer": "rE2EBYiPVALWzHob18YK47P8HgkEv6T1pV", + "title": "Trippy Apes Club", + "trustlines": 3000, + "placeInTop": null + }, + { + "id": 137, + "code": "Arnies", + "issuer": "rfzRVCV35aXN2xNRf2hhq3o8DFDpUt8DEa", + "title": "ARNIE'S NFT (XRPL)", + "trustlines": 3071, + "placeInTop": null + }, + { + "id": 16710, + "code": "XSTX", + "issuer": "r9KanwHSeSYB9DXfgc3sDuoE3sRsnQv4wo", + "title": "XSTX", + "trustlines": 3818, + "placeInTop": null + }, + { + "id": 16898, + "code": "XPoesy", + "issuer": "rMoDRBbLkYBRvagYZZakCtydEzMVwvrcqL", + "title": "XPoets", + "trustlines": 1478, + "placeInTop": null + }, + { + "id": 16778, + "code": "XDNT", + "issuer": "rnijBVqpT1RpMkLS9BsUZBneFeFrjz2h94", + "trustlines": 1210, + "placeInTop": null + }, + { + "id": 16616, + "code": "CFC", + "issuer": "rsxUkmjnAn8PRDz8RYrPusb9mTDYn5NqG8", + "trustlines": 10496, + "placeInTop": null + }, + { + "id": 16762, + "code": "xLabor", + "issuer": "rP4DR419Lafe6RPyS1vbFXW7DPpUHw2iR", + "title": "Xlabor", + "trustlines": 2306, + "placeInTop": null + }, + { + "id": 16960, + "code": "BAPE", + "issuer": "r3KSyXmYTYd6wd6ZwtrbEhQMjnJW3xpK4j", + "title": "Club X NFT - Bearable Bulls coming soon", + "trustlines": 1401, + "placeInTop": null + }, + { + "id": 17970, + "code": "FNGRS", + "issuer": "rwJfQcN7EzaDcpcmCQYef8mxpsHZceeWAC", + "title": "xFingeRs NFT", + "trustlines": 1899, + "placeInTop": null + }, + { + "id": 17051, + "code": "XAU", + "issuer": "rcoef87SYMJ58NAFx7fNM5frVknmvHsvJ", + "title": "BPG Kovine", + "trustlines": 5381, + "placeInTop": null + }, + { + "id": 17956, + "code": "XPixelPanties", + "issuer": "rMuPmDnooeqcjf28ZxsTF5Z1i2wa81Bw6z", + "title": "Xpixelpanties", + "trustlines": 1109, + "placeInTop": null + }, + { + "id": 19044, + "code": "BTC", + "issuer": "rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX", + "title": "Dividend Rippler", + "trustlines": 1119, + "placeInTop": null + }, + { + "id": 18163, + "code": "Krill", + "issuer": "r9FGdbCdjjRAWkn37kKgCQDsdm3NzgHieD", + "title": "XWhales Official", + "trustlines": 1690, + "placeInTop": null + }, + { + "id": 17943, + "code": "STR", + "issuer": "rKiCet8SdvWxPXnAgYarFUXMh1zCPz432Y", + "title": "Ripple Fox", + "trustlines": 869, + "placeInTop": null + }, + { + "id": 17691, + "code": "GKO", + "issuer": "ruazs5h1qEsqpke88pcqnaseXdm6od2xc", + "title": "Geckocoin", + "trustlines": 985, + "placeInTop": null + }, + { + "id": 18481, + "code": "BAFC", + "issuer": "r1qbiB6ib51kqNuipc3Asja4itGv2hUeY", + "title": "Bored Ape Football Club", + "trustlines": 2139, + "placeInTop": null + }, + { + "id": 19054, + "code": "JPY", + "issuer": "rJRi8WW24gt9X85PHAxfWNPCizMMhqUQwg", + "title": "Digital Gate Japan", + "trustlines": 843, + "placeInTop": null + }, + { + "id": 185, + "code": "FatCat", + "issuer": "rQ9oCoSZx72ztd1rpifUnGfwCwUdnr4Rds", + "title": "Fat Cats", + "trustlines": 2102, + "placeInTop": null + }, + { + "id": 16780, + "code": "SEAGULLAPARTMENTS", + "issuer": "rKjevbXgCs6sP8XTLz6SgcE5RKCLuiS1r3", + "title": "Bored Seagull Club", + "trustlines": 950, + "placeInTop": null + }, + { + "id": 17410, + "code": "CUTE", + "issuer": "rMyLn261pBVKtgMbzFpbAsFFBL7ksbFvvM", + "title": "CUTE Token XRPL", + "trustlines": 894, + "placeInTop": null + }, + { + "id": 132, + "code": "xCuisine", + "issuer": "rQKMxxEjhZcH1dXcReQdPGWWtf8zkiwukK", + "title": "Master Chef_Cuisine NFT", + "trustlines": 3783, + "placeInTop": null + }, + { + "id": 18492, + "code": "XLUX", + "issuer": "rsA8pK4EbEHLBv6HPpk1r1ND8RchPabTHC", + "title": "Lux Lions NFT | Bringing the Lux to Luxury", + "trustlines": 711, + "placeInTop": null + }, + { + "id": 18676, + "code": "AAX", + "issuer": "r4xyzqvcJFk9Vghfvmp9dX1LUdesN43F5H", + "title": "Anonymous Astronauts", + "trustlines": 1479, + "placeInTop": null + }, + { + "id": 17655, + "code": "ULT", + "issuer": "rKiCet8SdvWxPXnAgYarFUXMh1zCPz432Y", + "title": "Ripple Fox", + "trustlines": 690, + "placeInTop": null + }, + { + "id": 17402, + "code": "XRPHOENIX", + "issuer": "rMDxGz8kg1TKBNBC8C9n3pYGEQ9MsQFJHG", + "title": "XRPHOENIX", + "trustlines": 1473, + "placeInTop": null + }, + { + "id": 18585, + "code": "KODOKU", + "issuer": "rJa1mYRd57AGqoZfWK2kD9UhemQDE4osHE", + "title": "XRPL KODOKU", + "trustlines": 1110, + "placeInTop": null + }, + { + "id": 19011, + "code": "XAUR", + "issuer": "rpHNkyZpZTpW9w8zpxUcwAbgLNCGyLHPFm", + "trustlines": 8676, + "placeInTop": null + }, + { + "id": 18873, + "code": "PHOENIX", + "issuer": "rEpsJ5NaJpQisqmggsCL3TA2YeevgbAFGu", + "title": "PhoenixSwap", + "trustlines": 941, + "placeInTop": null + }, + { + "id": 17542, + "code": "JED", + "issuer": "rMUVZiUKrcZNqfpgNJRqQjpatGCPZSdrB8", + "title": "Got Jed?", + "trustlines": 593, + "placeInTop": null + }, + { + "id": 141, + "code": "INDI", + "issuer": "r3Uqw95RzBpcFCSVNphAgWWhjsQTxG5xvV", + "title": "Indigena", + "trustlines": 1938, + "placeInTop": null + }, + { + "id": 16985, + "code": "XLLAMAS", + "issuer": "rM7eceNskZB43X7aCDe22moJBEw9u42aN8", + "title": "Llamapalooza", + "trustlines": 1778, + "placeInTop": null + }, + { + "id": 17392, + "code": "xrplapps", + "issuer": "rBMPRPhbJPYER9k4HDwJY9PwrFQoB5wu89", + "trustlines": 378, + "placeInTop": null + }, + { + "id": 17762, + "code": "RBJ", + "issuer": "rEYD5k6kZPARQbKfB9GpiNPDY93kRQgPKj", + "title": "Ripple-Bank-Japan", + "trustlines": 339, + "placeInTop": null + }, + { + "id": 18191, + "code": "Greenfuel", + "issuer": "rEbZTML6KCMwRMqD6hRTw6K8kqKgLRnEH1", + "title": "GreenFuel", + "trustlines": 2490, + "placeInTop": null + }, + { + "id": 18741, + "code": "StakeXR", + "issuer": "rL5777XtQsBcwwRFWFuvcp5R8xNhTyRJrM", + "title": "StakeXR", + "trustlines": 1874, + "placeInTop": null + }, + { + "id": 18895, + "code": "EUR", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "title": "Bitstamp", + "trustlines": 953, + "placeInTop": null + }, + { + "id": 18534, + "code": "Xcrusader", + "issuer": "rhXa7avJF65iC27j6KRDRrWo2mVqrfVUmZ", + "title": "Xcrusader", + "trustlines": 2793, + "placeInTop": null + }, + { + "id": 18033, + "code": "DEBRIS", + "issuer": "r3FajLvMRbDCJ2n1NH3F6P1ZtpsfL7h9tm", + "title": "Debris", + "trustlines": 2757, + "placeInTop": null + }, + { + "id": 17388, + "code": "SGB", + "issuer": "rhrFfvzZAytd8UHPH87UHMgHQ18nnLbpgN", + "title": "GateHub SGB", + "trustlines": 2720, + "placeInTop": null + }, + { + "id": 18818, + "code": "PAW", + "issuer": "rD9V13zAF1RoLUDiCqyi6BwVQe4oWVaNgH", + "trustlines": 822, + "placeInTop": null + }, + { + "id": 112, + "code": "MZT", + "issuer": "r3657An8zaoTVae8mkyamKp4ddELSFKmcn", + "title": "MZT", + "trustlines": 9196, + "placeInTop": null + }, + { + "id": 47, + "code": "Galaxy", + "issuer": "r3Si5cWtHZZuKXQERoaTKc7Vhw53RdGi2A", + "title": "GALAXY", + "trustlines": 3650, + "placeInTop": null + }, + { + "id": 18539, + "code": "GOTV", + "issuer": "r9DS9LyzgvBhBm5WPsgW6kGzUpddyszkUV", + "title": "Guardians Of The Vault", + "trustlines": 1077, + "placeInTop": null + }, + { + "id": 16681, + "code": "TeddyBoys", + "issuer": "rUQp5C29SacMCbUrhrQYHGkqSQNsHULARQ", + "title": "TEDDY BOYS NFT | XRPL", + "trustlines": 6963, + "placeInTop": null + }, + { + "id": 18921, + "code": "XPD", + "issuer": "rfMc2D2GpZiHiXbq44xQHAC2bGK1qbtMA3", + "trustlines": 565, + "placeInTop": null + }, + { + "id": 17389, + "code": "ImmortalXKX", + "issuer": "rpAx21eFgJA6n8UWZfPjmkvaFzHzuvS8t6", + "title": "Crypto Prince", + "trustlines": 401, + "placeInTop": null + }, + { + "id": 18965, + "code": "XGO!", + "issuer": "rnucXjMr92b229V2KHgjG6V1Hz3JjsgqQN", + "title": "XGameOn", + "trustlines": 3198, + "placeInTop": null + }, + { + "id": 276, + "code": "PAY", + "issuer": "rMH8M1a1vWi6EwySMVwrnPLg6R6PzDpBVT", + "title": "XRPL Pay", + "trustlines": 2631, + "placeInTop": null + }, + { + "id": 18602, + "code": "AlienJump", + "issuer": "rajXWmVmQrFF8Bj1nzkT9JaWhPFXu1EoDw", + "title": "AlienJumpXrpl", + "trustlines": 1281, + "placeInTop": null + }, + { + "id": 18203, + "code": "MEMORY", + "issuer": "rfTsfrviaNgJ1URQf4FVWjsr59ULr1FNgu", + "trustlines": 722, + "placeInTop": null + }, + { + "id": 222, + "code": "xPug", + "issuer": "rNxNMb7h5ZT86EXy6nHtxSpf4W8ZMLNy6b", + "title": "xPug", + "trustlines": 3856, + "placeInTop": null + }, + { + "id": 16959, + "code": "UnionCoin", + "issuer": "rMYeffeDZeJtMWDM7StFj3hQxpB5KL6hfa", + "title": "UNION COIN", + "trustlines": 2968, + "placeInTop": null + }, + { + "id": 19045, + "code": "BTC", + "issuer": "rJHygWcTLVpSXkowott6kzgZU6viQSVYM1", + "title": "Justcoin", + "trustlines": 670, + "placeInTop": null + }, + { + "id": 18340, + "code": "GALA", + "issuer": "rf5YPb9y9P3fTjhxNaZqmrwaj5ar8PG1gM", + "title": "GateHub GALA", + "trustlines": 1193, + "placeInTop": null + }, + { + "id": 19105, + "code": "USD", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 663, + "placeInTop": null + }, + { + "id": 17283, + "code": "Boss", + "issuer": "r9bBb26SkJDW9dEXKFHkZdJvQVXE5pTwTM", + "title": "Bostonkrypto", + "trustlines": 267, + "placeInTop": null + }, + { + "id": 18157, + "code": "2CD", + "issuer": "rDxLqyy7UEAbbz1kC9HqnjLXae3KZLPNPM", + "title": "2Cold", + "trustlines": 696, + "placeInTop": null + }, + { + "id": 18562, + "code": "KRW", + "issuer": "rwdRX4jgRB5rZkbbbG7ezVTBKdBNKVrtpR", + "title": "Digital Gate Korea", + "trustlines": 646, + "placeInTop": null + }, + { + "id": 16779, + "code": "XRbitcoincash", + "issuer": "rEjwniYhYR5QDZzK1a1x2359j8j8N43Ypw", + "title": "XRbitcoincash", + "trustlines": 2447, + "placeInTop": null + }, + { + "id": 18537, + "code": "WEN", + "issuer": "rp2Em1RYo9sxJPJAMe9bDCkdDhirqUYQZC", + "title": "Club X NFT - Bearable Bulls coming soon", + "trustlines": 336, + "placeInTop": null + }, + { + "id": 17532, + "code": "XEC", + "issuer": "rNx3ty1w48iAa4JDfqhZk6bphwXxvCEtZP", + "title": "El-coin", + "trustlines": 1661, + "placeInTop": null + }, + { + "id": 18798, + "code": "XMG", + "issuer": "rQnMyMX5abtQrrsMm2rjws3agapxyKiPGZ", + "title": "XMG - XRPL Gaming Ecosystem", + "trustlines": 824, + "placeInTop": null + }, + { + "id": 16703, + "code": "DRIPPED", + "issuer": "rKtfM2S7EVkp3vF5WVM44L8RyGjrmE4ZG5", + "title": "DRIPPED", + "trustlines": 2345, + "placeInTop": null + }, + { + "id": 16781, + "code": "punkdninjas", + "issuer": "r95N6Va2n2EdKGnDCGNKLgtXBxpd1Xy3MH", + "title": "PunkdNinjas", + "trustlines": 2020, + "placeInTop": null + }, + { + "id": 19058, + "code": "USD", + "issuer": "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9", + "title": "Payroutes", + "trustlines": 756, + "placeInTop": null + }, + { + "id": 17592, + "code": "JUD", + "issuer": "r9qouqdcygAWyoFGPxwMN3LoJkpHJHoCBd", + "trustlines": 359, + "placeInTop": null + }, + { + "id": 19053, + "code": "JPY", + "issuer": "r9ZFPSb1TFdnJwbTMYHvVwFK1bQPUCVNfJ", + "title": "Ripple Exchange Tokyo", + "trustlines": 552, + "placeInTop": null + }, + { + "id": 18283, + "code": "Animabox", + "issuer": "rHxrNp8ruthrrrmhBdcQosNQNRQ1QTzi1o", + "title": "\ud835\udc00\ud835\udc27\ud835\udc22\ud835\udc26\ud835\udc1a\ud835\udc01\ud835\udc28\ud835\udc31 \ud835\udc0d\ud835\udc05\ud835\udc13 on XRPL \ud83d\udc0d", + "trustlines": 2095, + "placeInTop": null + }, + { + "id": 313, + "code": "xPizza", + "issuer": "rUMwLWFzwcD2topAKsg5NBbhq7dtu4gRCU", + "title": "XRPizzaParty", + "trustlines": 2776, + "placeInTop": null + }, + { + "id": 16948, + "code": "Diamond", + "issuer": "rfSTRox25KWznAtKCLqJ29zPxwErkhbX49", + "title": "Diamond", + "trustlines": 2175, + "placeInTop": null + }, + { + "id": 18536, + "code": "ZANIMAL", + "issuer": "rLacyEG9x5q3VXtoS3AnobnfedKmU89f6Q", + "trustlines": 582, + "placeInTop": null + }, + { + "id": 17558, + "code": "ICE", + "issuer": "r4H3F9dDaYPFwbrUsusvNAHLz2sEZk4wE5", + "trustlines": 578, + "placeInTop": null + }, + { + "id": 17405, + "code": "VRB", + "issuer": "rBfVgTnsdh8ckC19RM8aVGNuMZnpwrMP6n", + "trustlines": 3737, + "placeInTop": null + }, + { + "id": 17740, + "code": "BCC", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 596, + "placeInTop": null + }, + { + "id": 100, + "code": "XKINGAPES", + "issuer": "rK6H71AGq5ndQ3ChRL3rKABB14qmj68GwW", + "title": "XKING APES", + "trustlines": 3875, + "placeInTop": null + }, + { + "id": 17485, + "code": "SCZ", + "issuer": "rScheetz28HPqwAo3sxCtqKxU5TPWbLEf", + "title": "Scheetz", + "trustlines": 326, + "placeInTop": null + }, + { + "id": 17412, + "code": "xGaf", + "issuer": "rGidCc3AXaFzHLJrZSd1R9u7nM2YKKtUFK", + "title": "xGAF", + "trustlines": 3864, + "placeInTop": null + }, + { + "id": 18947, + "code": "ALPHA", + "issuer": "rwSqY5LuiU6nZutikF2Ubnm47MwDnaKGUz", + "title": "3DAPES\u2122", + "trustlines": 897, + "placeInTop": null + }, + { + "id": 162, + "code": "DONKY", + "issuer": "rMZnj5DdExmoUmm9QnEgmiKw3QEA9oRdjL", + "title": "XRDonkey", + "trustlines": 3150, + "placeInTop": null + }, + { + "id": 228, + "code": "DOG", + "issuer": "rbUNsWhC4vqUwcsaWeLH9FBnMNBkxAka4", + "title": "XRP DOG", + "trustlines": 1127, + "placeInTop": null + }, + { + "id": 18716, + "code": "NIO", + "issuer": "rawT5z6bFKigVRHqu29TdZ6aBejvMEqxxT", + "title": "Nitro", + "trustlines": 384, + "placeInTop": null + }, + { + "id": 18802, + "code": "xRYO", + "issuer": "rLPZJ6xQkq36DurkpqsQkggMpMktPVUrVD", + "trustlines": 396, + "placeInTop": null + }, + { + "id": 18934, + "code": "LTC", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 1566, + "placeInTop": null + }, + { + "id": 19041, + "code": "BTC", + "issuer": "rKxKhXZCeSDsbkyB8DVgxpjy5AHubFkMFe", + "title": "Rippex", + "trustlines": 1177, + "placeInTop": null + }, + { + "id": 18796, + "code": "BabyXRP", + "issuer": "rHMNE7vcmAQQqdkuKzTTEg9SJY7nZVvgUV", + "trustlines": 562, + "placeInTop": null + }, + { + "id": 233, + "code": "XCEL", + "issuer": "rDZU6y1wDuZPLxkUkr6GFwE6EdJtJu3Lk3", + "trustlines": 1321, + "placeInTop": null + }, + { + "id": 17851, + "code": "FLEA", + "issuer": "r3G2QxjkCJCqDub6z3SSrAVoJQVEsJ2NtU", + "trustlines": 596, + "placeInTop": null + }, + { + "id": 17931, + "code": "USD", + "issuer": "rBfVgTnsdh8ckC19RM8aVGNuMZnpwrMP6n", + "trustlines": 3897, + "placeInTop": null + }, + { + "id": 18617, + "code": "Bits", + "issuer": "rnYtXosnrsbtVTRkMNfBX2CHzjPQom1WJv", + "title": "X-A.I. NFT", + "trustlines": 759, + "placeInTop": null + }, + { + "id": 18359, + "code": "XCLOWN", + "issuer": "rEg5q7fmkF387T85T1b3dzViEfspMzcccJ", + "title": "xrpl clown", + "trustlines": 1605, + "placeInTop": null + }, + { + "id": 18843, + "code": "XCC", + "issuer": "r3fJbmdnFhQwHKxD1QDwMfmras9jLoh4RW", + "title": "XCleanCoin (XCC)", + "trustlines": 2201, + "placeInTop": null + }, + { + "id": 17819, + "code": "FMM", + "issuer": "rKiCet8SdvWxPXnAgYarFUXMh1zCPz432Y", + "title": "Ripple Fox", + "trustlines": 438, + "placeInTop": null + }, + { + "id": 18054, + "code": "ILS", + "issuer": "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9", + "title": "Payroutes", + "trustlines": 380, + "placeInTop": null + }, + { + "id": 17548, + "code": "RIP", + "issuer": "rEYD5k6kZPARQbKfB9GpiNPDY93kRQgPKj", + "title": "Ripple-Bank-Japan", + "trustlines": 202, + "placeInTop": null + }, + { + "id": 17665, + "code": "CCK", + "issuer": "rp2PaYDxVwDvaZVLEQv7bHhoFQEyX1mEx7", + "title": "P2pay-Cold", + "trustlines": 228, + "placeInTop": null + }, + { + "id": 361, + "code": "Tribe", + "issuer": "rh6MHdcZDRwfcqFyAQP4bvZvKTyArnTR2W", + "title": "Tribe XRPL", + "trustlines": 9750, + "placeInTop": null + }, + { + "id": 16659, + "code": "XLINDEN", + "issuer": "rNjHfrvYTbCXMkkPDfLF6RtFcr4YbK3UL5", + "title": "XLINDEN", + "trustlines": 1700, + "placeInTop": null + }, + { + "id": 17796, + "code": "589", + "issuer": "rstHc6J8zLvrK8HdoNX4Mj66FQRVkUSTfb", + "title": "589", + "trustlines": 660, + "placeInTop": null + }, + { + "id": 16856, + "code": "BSC", + "issuer": "rsdK4XBXoG5JUHwR56Deq2ncTqjr4TxSi7", + "title": "Bored Seagull Club", + "trustlines": 2363, + "placeInTop": null + }, + { + "id": 94, + "code": "Cannabis", + "issuer": "rDdVN3HqhJb36XXLHpbeVmHxuUCfx7ryRm", + "title": "XCANNABIS", + "trustlines": 4678, + "placeInTop": null + }, + { + "id": 120, + "code": "CCC", + "issuer": "r433dvTW1cM1JGWTeRXTPTbCA87BcUoScj", + "title": "Content Connections Coin (CCC)", + "trustlines": 7023, + "placeInTop": null + }, + { + "id": 16839, + "code": "GodBit", + "issuer": "rKzPmuWL2pExMTqudrsHDySWY6y6nNVKxT", + "title": "GodBit", + "trustlines": 1766, + "placeInTop": null + }, + { + "id": 17914, + "code": "YZK", + "issuer": "rJr2Jy71Mb6kqv4iux79wvadq2LtqLSsdz", + "title": "Yozok", + "trustlines": 4238, + "placeInTop": null + }, + { + "id": 17847, + "code": "STR", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 1385, + "placeInTop": null + }, + { + "id": 19047, + "code": "BTC", + "issuer": "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9", + "title": "Payroutes", + "trustlines": 550, + "placeInTop": null + }, + { + "id": 81, + "code": "koi", + "issuer": "rBzhSC1vWsMXgMSWoiE2m6bHmXynyDxkUN", + "title": "IXRPWORLD", + "trustlines": 3544, + "placeInTop": null + }, + { + "id": 18643, + "code": "XPIRATES", + "issuer": "rKZNq2QU6TcHnBDEpEhnikMfmuUQedKg51", + "title": "xPirates", + "trustlines": 876, + "placeInTop": null + }, + { + "id": 259, + "code": "CWC", + "issuer": "rHm8VBgtAwKAWyueyhrDxDfwQ5k2M6Tz3W", + "title": "ClownWorldCoin", + "trustlines": 1502, + "placeInTop": null + }, + { + "id": 17269, + "code": "PHX", + "issuer": "rfEJ1ksD22TsCy8hdKoJuC6Xfc33VCKPUs", + "title": "TheRugPhxProject", + "trustlines": 633, + "placeInTop": null + }, + { + "id": 17463, + "code": "RPS", + "issuer": "r9wx4BoPPDtNYMkEY7Xj5bJK25JfyNwSZ", + "title": "Ripplerps", + "trustlines": 201, + "placeInTop": null + }, + { + "id": 18838, + "code": "WAKEx", + "issuer": "rpxVbcAHxZPPPJJF9NE3e9FN4eSJLTs6NL", + "title": "WAKEx", + "trustlines": 511, + "placeInTop": null + }, + { + "id": 18827, + "code": "XDEX", + "issuer": "rPXRmaPf4PDXikmXF1nAyxxVpyyVhyx1We", + "trustlines": 3743, + "placeInTop": null + }, + { + "id": 19015, + "code": "USD", + "issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun", + "title": "The Rock Trading", + "trustlines": 554, + "placeInTop": null + }, + { + "id": 354, + "code": "XREX", + "issuer": "rPasXvMsRmrqmK9HMT5MQp8ie8ZVoFBwtG", + "title": "XREX", + "trustlines": 4051, + "placeInTop": null + }, + { + "id": 17032, + "code": "SOF", + "issuer": "rGwNpLfBtJ9t1q8G1e3pgKa1n1ibgjqRph", + "title": "SoFCenter", + "trustlines": 1470, + "placeInTop": null + }, + { + "id": 18162, + "code": "MTM", + "issuer": "rMtMPTwyU6jWTS18sJFnii2kCoBioUEure", + "trustlines": 528, + "placeInTop": null + }, + { + "id": 18687, + "code": "PXP", + "issuer": "rPXPpTDcGL2zhNS2DFCbsep97H6sraTT7s", + "trustlines": 364, + "placeInTop": null + }, + { + "id": 18894, + "code": "EUR", + "issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun", + "title": "The Rock Trading", + "trustlines": 441, + "placeInTop": null + }, + { + "id": 16688, + "code": "DBDXR", + "issuer": "rH3jeL5UgE8KKJYSN8LoQX2mgh2kZoja4x", + "title": "Digital Black Dollar 1.0", + "trustlines": 1055, + "placeInTop": null + }, + { + "id": 17554, + "code": "NXT", + "issuer": "ra9eZxMbJrUcgV8ui7aPc161FgrqWScQxV", + "title": "Peercover", + "trustlines": 413, + "placeInTop": null + }, + { + "id": 64, + "code": "ELF", + "issuer": "rKhkLTgZrAaHXY5NzquXfJmXX3TRpV1Dmv", + "trustlines": 5065, + "placeInTop": null + }, + { + "id": 16795, + "code": "CentralReserve", + "issuer": "rfAPdqD3W33CHAGMb4P7tpJVyNE1AGuZHg", + "trustlines": 1942, + "placeInTop": null + }, + { + "id": 16843, + "code": "Xalienware", + "issuer": "r9T7w5KuVhb9B5Ddj6ps5AhnZNikAY2caK", + "title": "Xalienware", + "trustlines": 3885, + "placeInTop": null + }, + { + "id": 16986, + "code": "STREAM", + "issuer": "rE3BGaHdGfMYF5kXsWkkiV7DUyr7aRXKGF", + "title": "STREAM", + "trustlines": 3989, + "placeInTop": null + }, + { + "id": 17015, + "code": "QUX", + "issuer": "rfEG1uxjAqeLv8joDqeUqomssVWSpoX6h4", + "trustlines": 1328, + "placeInTop": null + }, + { + "id": 16799, + "code": "XNC", + "issuer": "rfoD7GTb7UNt8dkC6PVrx234N4ivRqf6LF", + "title": "XrpNurse", + "trustlines": 2556, + "placeInTop": null + }, + { + "id": 17535, + "code": "XPY", + "issuer": "rEVxaqydnDTqiLC6ivwEAAG4j21zS2LuLe", + "trustlines": 185, + "placeInTop": null + }, + { + "id": 16837, + "code": "XSL", + "issuer": "rLA1aoxTqUx7RYPLBZ4XmzjWNNUZcQkL95", + "trustlines": 734, + "placeInTop": null + }, + { + "id": 16882, + "code": "BMZ", + "issuer": "rsH7ktoKiuXx1zefgFreuaNGjUAt7ZWRPY", + "title": "xrplmonkeyz", + "trustlines": 2306, + "placeInTop": null + }, + { + "id": 18189, + "code": "ApesPunk", + "issuer": "rD7JGkzLtHUuKiyhiWuKvwU23mkD8kmQ5Z", + "title": "ApesPunk - XRPL", + "trustlines": 2200, + "placeInTop": null + }, + { + "id": 18252, + "code": "XMKAT", + "issuer": "r38btybd7kRqPctNJmcsf9SrCC3uzjPccf", + "title": "LAME LIONS XRPL \ud83d\udc51", + "trustlines": 1119, + "placeInTop": null + }, + { + "id": 17082, + "code": "XKF", + "issuer": "rG6RZ93xFrgCcXhWdh2hAWDeDwydMvS19J", + "title": "CombatKangaFuel", + "trustlines": 1329, + "placeInTop": null + }, + { + "id": 19043, + "code": "BTC", + "issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun", + "title": "The Rock Trading", + "trustlines": 536, + "placeInTop": null + }, + { + "id": 373, + "code": "UsaveMe", + "issuer": "rLL124XfvHPNJGMkrScm2HMACA2hkzKsL7", + "title": "Usaveme", + "trustlines": 4821, + "placeInTop": null + }, + { + "id": 17700, + "code": "MXN", + "issuer": "rG6FZ31hDHN1K5Dkbma3PSB5uVCuVVRzfn", + "title": "Bitso", + "trustlines": 471, + "placeInTop": null + }, + { + "id": 16906, + "code": "XRGold", + "issuer": "rGMjJsTD6LgQo2usixuox16PSwm4m9X5Ym", + "trustlines": 1837, + "placeInTop": null + }, + { + "id": 124, + "code": "TESLA", + "issuer": "r91SCjzULbyv3Y4o1Czem5pcYYxjNJuaNo", + "title": "$TESLA", + "trustlines": 5120, + "placeInTop": null + }, + { + "id": 18856, + "code": "xAds", + "issuer": "rsMQEnuvEqzeNPu7ZNpGctGBrWLv4x2mb2", + "title": "xAds - XRPL", + "trustlines": 612, + "placeInTop": null + }, + { + "id": 16775, + "code": "XRbitcoin", + "issuer": "rGQaHbQHCsTLQtboQPwUBasXjLvk8uDbpT", + "title": "XRbitcoin", + "trustlines": 704, + "placeInTop": null + }, + { + "id": 17849, + "code": "NZD", + "issuer": "rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc", + "title": "Coinex", + "trustlines": 1318, + "placeInTop": null + }, + { + "id": 18625, + "code": "CTC", + "issuer": "rHZP1pA3THovFqvwgtM2tnJWrS54hSrDiG", + "trustlines": 213, + "placeInTop": null + }, + { + "id": 19075, + "code": "KRW", + "issuer": "rPxU6acYni7FcXzPCMeaPSwKcuS2GTtNVN", + "title": "EXRP", + "trustlines": 500, + "placeInTop": null + }, + { + "id": 17557, + "code": "DOG", + "issuer": "ra9eZxMbJrUcgV8ui7aPc161FgrqWScQxV", + "title": "Peercover", + "trustlines": 290, + "placeInTop": null + }, + { + "id": 16744, + "code": "MooM", + "issuer": "rDWgjsCDx93gscZ99MXZAcymiNaBHrzk9H", + "title": "XRP MooM", + "trustlines": 1160, + "placeInTop": null + }, + { + "id": 18460, + "code": "WXRP", + "issuer": "rEa5QY8tdbjgitLyfKF1E5Qx3VGgvbUhB3", + "title": "GateHub WXRP", + "trustlines": 836, + "placeInTop": null + }, + { + "id": 174, + "code": "xHAM", + "issuer": "rQ9BmiUbMus85EiPQKYnMxMA8KBagawbQy", + "title": "xHustlers", + "trustlines": 985, + "placeInTop": null + }, + { + "id": 18001, + "code": "XMasons", + "issuer": "rfS2WUDbrMn25MbnD9XHivbQ5oYsdpvqLm", + "title": "Xmasons", + "trustlines": 8763, + "placeInTop": null + }, + { + "id": 319, + "code": "XLGBTQ", + "issuer": "r4cXkPESi5UsWuqC3yaHczitiH4oXAExh", + "title": "XLGBTQCOIN", + "trustlines": 1590, + "placeInTop": null + }, + { + "id": 17005, + "code": "XRP2", + "issuer": "r9rRLst96Ue4YTDQkWWkX1ePB6p6Ye4FkA", + "title": "XRPayNet", + "trustlines": 2351, + "placeInTop": null + }, + { + "id": 18338, + "code": "TUSK", + "issuer": "raMsKbJcRYLF1nwhWPntqXuwBdtftfi234", + "title": "Sturdy Hogs Society", + "trustlines": 1480, + "placeInTop": null + }, + { + "id": 198, + "code": "Xwizard", + "issuer": "rUifimbEkHzyQYM88iJzhUnFSYPvAkiFtZ", + "title": "CbotLabsInc.", + "trustlines": 2368, + "placeInTop": null + }, + { + "id": 16945, + "code": "SNG", + "issuer": "rBuoRCgafUXHamjGwB8wRBZFqPAbdLiUni", + "title": "ShopNGo", + "trustlines": 2046, + "placeInTop": null + }, + { + "id": 18057, + "code": "DIGI", + "issuer": "rnWyNGvkj2ZewctN3HNNbY5dLibFQPX3C1", + "title": "digifish", + "trustlines": 2110, + "placeInTop": null + }, + { + "id": 18541, + "code": "ApeX", + "issuer": "rG7RzbDAnaNW2fVrpjQtqmtcdArdQJoUxK", + "title": "ApeX", + "trustlines": 1386, + "placeInTop": null + }, + { + "id": 18840, + "code": "xOracleDNA", + "issuer": "rhTNWsKKaQwDvVZPXE9QtLPyreZmDZ99gN", + "trustlines": 157, + "placeInTop": null + }, + { + "id": 17534, + "code": "YOU", + "issuer": "rGvWKKaVboTqY6GwP7afhDkYZ5qQMTvora", + "title": "Youcoin", + "trustlines": 229, + "placeInTop": null + }, + { + "id": 72, + "code": "XAnime", + "issuer": "rHjnXe9uqesd1jKbcTsekG1Jp5ZYHPCWWR", + "trustlines": 3990, + "placeInTop": null + }, + { + "id": 19021, + "code": "xDood", + "issuer": "rBWSH3LmPtEfUrAF3QwWUWegvJyfEPjVkX", + "trustlines": 895, + "placeInTop": null + }, + { + "id": 3, + "code": "XXXRP", + "issuer": "rJiBnVT8dxj2QrGu84MH3qWtDzXMTR7QUJ", + "title": "XXXRP Token", + "trustlines": 3020, + "placeInTop": null + }, + { + "id": 18749, + "code": "IWC", + "issuer": "rNiFYEzNcwYnQ9cbt1fagK5gmVMXEcxGNy", + "title": "IWC", + "trustlines": 146, + "placeInTop": null + }, + { + "id": 17556, + "code": "XMF", + "issuer": "rHKTzLQjXo7JM7JrKEZo2jyDtC7iqS6NJp", + "title": "Mastersfg2", + "trustlines": 274, + "placeInTop": null + }, + { + "id": 18842, + "code": "xOracleLAND", + "issuer": "rhTNWsKKaQwDvVZPXE9QtLPyreZmDZ99gN", + "trustlines": 146, + "placeInTop": null + }, + { + "id": 17547, + "code": "HLD", + "issuer": "rP9SFQTj7FY3KXGw3e9EvgrPYGpq1pd4yy", + "trustlines": 284, + "placeInTop": null + }, + { + "id": 364, + "code": "Keanu", + "issuer": "rPFfFbAjVMjTKGzHnJQkpfLUNBwor7RQJY", + "title": "Keanu crypto", + "trustlines": 5478, + "placeInTop": null + }, + { + "id": 16684, + "code": "XRPMASKZ", + "issuer": "rPB7bqp3wHBHhVrpfjZfGXotegxfrYcQCW", + "title": "XRPMaskz", + "trustlines": 3154, + "placeInTop": null + }, + { + "id": 16852, + "code": "META", + "issuer": "r9fTXcvbkgJ9ggEgjV3UmzM7sqs9Phb177", + "title": "META", + "trustlines": 2954, + "placeInTop": null + }, + { + "id": 17279, + "code": "JNG", + "issuer": "rhbQYNVTzBzrv75igTeePyHxGzJ8L8P532", + "trustlines": 2209, + "placeInTop": null + }, + { + "id": 17709, + "code": "MFS", + "issuer": "razccN2G1Q3UcGSiRjGNM8xqgowMxDiGhv", + "title": "MFS", + "trustlines": 138, + "placeInTop": null + }, + { + "id": 17538, + "code": "BIG", + "issuer": "rHoUTGMxWKbrTTF8tpAjysjpu8PWrbt1Wx", + "title": "Smartys", + "trustlines": 202, + "placeInTop": null + }, + { + "id": 18487, + "code": "APE", + "issuer": "rHXHbdcVjHHcmyX7X76VZzmMvBkF4wehsU", + "title": "\ud83e\uddea\ud83e\uddea BMAC - Blind Mummy Apes Club\ud83d\udc99\ud83d\udc9b", + "trustlines": 480, + "placeInTop": null + }, + { + "id": 18694, + "code": "XCOIN", + "issuer": "rBw4swPcXBAgZUcYBYqcpSrCf25cu34nc8", + "trustlines": 1817, + "placeInTop": null + }, + { + "id": 18845, + "code": "xOracleRECR", + "issuer": "rhTNWsKKaQwDvVZPXE9QtLPyreZmDZ99gN", + "trustlines": 140, + "placeInTop": null + }, + { + "id": 17540, + "code": "FRX", + "issuer": "rPA73XSVQ3UEz7gSixREhMzBMtF4RGZPie", + "title": "Frinkcoin", + "trustlines": 130, + "placeInTop": null + }, + { + "id": 16714, + "code": "INT", + "issuer": "rwLMRFbMgihwDKAn7dnLdsNztXGbFafS9u", + "title": "InTroitStudio", + "trustlines": 1955, + "placeInTop": null + }, + { + "id": 18210, + "code": "BisonG", + "issuer": "rn3Gd6hQqc5ZK1VvfyWyrzhad3aTdPaFLs", + "title": "BisonGrass", + "trustlines": 1556, + "placeInTop": null + }, + { + "id": 18257, + "code": "AURORA", + "issuer": "rPnac2Qunw9ofqiY5ur4jd83dNMbk5THYh", + "title": "AstralsOnX", + "trustlines": 4563, + "placeInTop": null + }, + { + "id": 18402, + "code": "xDoCash", + "issuer": "rNsUnCdoFL2498VFc3aH84dSyrotP2mzLD", + "trustlines": 351, + "placeInTop": null + }, + { + "id": 19089, + "code": "XLE", + "issuer": "rwCkSpBEyhhMjB1Yz17dpTJZ1UPg7ppsgU", + "trustlines": 13857, + "placeInTop": null + }, + { + "id": 90, + "code": "XTIM", + "issuer": "rsr4t5kg3gUZwEwMMcymWeus5hfpDSMQbG", + "title": "XTIMfund", + "trustlines": 4913, + "placeInTop": null + }, + { + "id": 18844, + "code": "xOracleNEO", + "issuer": "rhTNWsKKaQwDvVZPXE9QtLPyreZmDZ99gN", + "trustlines": 128, + "placeInTop": null + }, + { + "id": 19100, + "code": "xMalaya", + "issuer": "rLYcBjVF5vXhBVdWQELcv7FyRfRuakPnzr", + "title": "Malaya Infinity", + "trustlines": 2740, + "placeInTop": null + }, + { + "id": 338, + "code": "XRXumm", + "issuer": "rKdCXSihHYED8Ree8HwKBgE9GPWJ8nduqb", + "title": "XRXumm", + "trustlines": 1849, + "placeInTop": null + }, + { + "id": 16718, + "code": "LoveLand", + "issuer": "r325Com8CdPAmEuYABTz3djfP4KEHurU2z", + "title": "Love Monster \uea00", + "trustlines": 1185, + "placeInTop": null + }, + { + "id": 16686, + "code": "DNINE", + "issuer": "rhrKhg5XkwA4ttHrGsnizXXmZUe2TpnRFs", + "title": "Divine Nine NFT", + "trustlines": 1855, + "placeInTop": null + }, + { + "id": 18284, + "code": "ROK", + "issuer": "rn4f4cpyDSriqdohMTRkwSKt1ga7D1q25H", + "trustlines": 137, + "placeInTop": null + }, + { + "id": 18953, + "code": "xr77", + "issuer": "rcLASSiCq8LWcymCHaCgK19QMEvUspuRM", + "title": "XR77", + "trustlines": 898, + "placeInTop": null + }, + { + "id": 18957, + "code": "XGOLD", + "issuer": "rDHZhSSatHAG4ubxsDedRUgTXCJAWRvpo2", + "title": "Xgoldxrpl", + "trustlines": 2834, + "placeInTop": null + }, + { + "id": 17551, + "code": "XAU", + "issuer": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH", + "title": "Ripple Singapore", + "trustlines": 303, + "placeInTop": null + }, + { + "id": 18266, + "code": "xOPS", + "issuer": "rGY49448umDTQtAjMLBA6t7HHZZSJoC26m", + "trustlines": 595, + "placeInTop": null + }, + { + "id": 18841, + "code": "xOracleGG", + "issuer": "rhTNWsKKaQwDvVZPXE9QtLPyreZmDZ99gN", + "trustlines": 133, + "placeInTop": null + }, + { + "id": 18274, + "code": "NFTR", + "issuer": "rBGi34LU3FFd5dnVD2bWbdMxJEkSVfwWpe", + "title": "Bitcoin X", + "trustlines": 1119, + "placeInTop": null + }, + { + "id": 19016, + "code": "USD", + "issuer": "ra9eZxMbJrUcgV8ui7aPc161FgrqWScQxV", + "title": "Peercover", + "trustlines": 309, + "placeInTop": null + }, + { + "id": 119, + "code": "House", + "issuer": "rJ9XgtypsnSJt3x6R1crbs7qFRqa6YvcRi", + "title": "Meta House", + "trustlines": 2029, + "placeInTop": null + }, + { + "id": 17337, + "code": "VGO", + "issuer": "rPYJU7Un1ayZ9uHe3QQm8fRiGKZnGYNzhv", + "title": "Vagabond VGO", + "trustlines": 1180, + "placeInTop": null + }, + { + "id": 18634, + "code": "GXWCoin", + "issuer": "rBaQ4z5kpEwH84cz1Gkve4wCpz5g9xrvpz", + "trustlines": 341, + "placeInTop": null + }, + { + "id": 18917, + "code": "XWC", + "issuer": "rwdpB514zQMLx4Uy5feJBJUtx6LJZMaZLm", + "title": "XRPL WORLD CUP", + "trustlines": 609, + "placeInTop": null + }, + { + "id": 18834, + "code": "WSTH", + "issuer": "rnwTawWCLjXKroP7CBLFLxpidSCR3UoHKG", + "trustlines": 704, + "placeInTop": null + }, + { + "id": 18891, + "code": "JEN", + "issuer": "rntNAksJQhpyxvPWoAVtgS8ML1SsrpZuuw", + "trustlines": 783, + "placeInTop": null + }, + { + "id": 16968, + "code": "BMS", + "issuer": "rpR32FXJoGv5K9Qwyu3cW8dSCWeu29cy88", + "title": "Bullish Moments", + "trustlines": 926, + "placeInTop": null + }, + { + "id": 18931, + "code": "MOB", + "issuer": "rBqn27sZcfjR8LvcgESPBjgrMybRkk11da", + "title": "M.O.B", + "trustlines": 537, + "placeInTop": null + }, + { + "id": 18933, + "code": "XrAkita", + "issuer": "rJzgPGTrjLV1JHivpu7428WMti6pACz44V", + "trustlines": 438, + "placeInTop": null + }, + { + "id": 127, + "code": "GBL", + "issuer": "rfQvbpZvihhRULL7mJhaSYgK3TUcZq3NAp", + "title": "GBL", + "trustlines": 5766, + "placeInTop": null + }, + { + "id": 18978, + "code": "USD", + "issuer": "rKiCet8SdvWxPXnAgYarFUXMh1zCPz432Y", + "title": "Ripple Fox", + "trustlines": 836, + "placeInTop": null + }, + { + "id": 16773, + "code": "META$", + "issuer": "rNtqjpucnCuxhKVtMy2iefRofPFVXFD5PR", + "title": "META$", + "trustlines": 3380, + "placeInTop": null + }, + { + "id": 17784, + "code": "USD", + "issuer": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH", + "title": "Ripple Singapore", + "trustlines": 341, + "placeInTop": null + }, + { + "id": 18987, + "code": "BTC", + "issuer": "rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc", + "title": "Coinex", + "trustlines": 1172, + "placeInTop": null + }, + { + "id": 16808, + "code": "Drip", + "issuer": "rhWbFN1Q3owPfYY3FjMmKTzTXs6A3uKVtm", + "title": "XCoinDropper", + "trustlines": 1589, + "placeInTop": null + }, + { + "id": 18721, + "code": "Greenpower", + "issuer": "rhNv8T5waDTyxbSVfiFGn7E1b45CUj5Ae6", + "title": "Greenpower", + "trustlines": 873, + "placeInTop": null + }, + { + "id": 18849, + "code": "ASX", + "issuer": "r3RqTN9tso5TB9HuB4aeiDmrWZEuMSnP8Q", + "trustlines": 12400, + "placeInTop": null + }, + { + "id": 19056, + "code": "USD", + "issuer": "rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc", + "title": "Coinex", + "trustlines": 1218, + "placeInTop": null + }, + { + "id": 18911, + "code": "EmiC", + "issuer": "rBAtoMmpDbyQytkonpuz1fzcf4htdMXzqK", + "title": "Emirate Club", + "trustlines": 7741, + "placeInTop": null + }, + { + "id": 19008, + "code": "XRD3", + "issuer": "rD3hZoj626diqEA5S8FpJymz8R6X8ffVqS", + "title": "xRonin Labs | SOLD OUT!", + "trustlines": 298, + "placeInTop": null + }, + { + "id": 16791, + "code": "TGC", + "issuer": "r4ZPfDiqxQRvcwXoriEHjR9a9DkuboYyZ8", + "trustlines": 795, + "placeInTop": null + }, + { + "id": 16905, + "code": "XRPugs", + "issuer": "rsfPbNNHWz5262XgaYtrWvTgfX34seaNgh", + "title": "XRPugs", + "trustlines": 3203, + "placeInTop": null + }, + { + "id": 219, + "code": "PEENZ", + "issuer": "rLDEELKZST8eRYpNPS1hr6LWZbQnZ9NkYy", + "title": "XRPeenz", + "trustlines": 1852, + "placeInTop": null + }, + { + "id": 16669, + "code": "EMB", + "issuer": "rfQYLw1szMWWCob7VtAGtZtYtmLtCCPLLs", + "title": "EMOTION BOX TOKEN", + "trustlines": 3035, + "placeInTop": null + }, + { + "id": 18551, + "code": "InfantXapes", + "issuer": "rsz5MtMPLfrT5ZHFP4TUigMwMzugACRKhs", + "title": "Gorilla X Warfare", + "trustlines": 332, + "placeInTop": null + }, + { + "id": 298, + "code": "OPI", + "issuer": "rLekuNt7xSRBJKBtxr4nqa3obGmUa9nmYZ", + "trustlines": 885, + "placeInTop": null + }, + { + "id": 19077, + "code": "ETC", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 407, + "placeInTop": null + }, + { + "id": 130, + "code": "DBD", + "issuer": "rMuUAyEwGpQAKKHWjEjJdMWqDQp9mbDrVU", + "title": "Digital Black Dollar 1.0", + "trustlines": 3660, + "placeInTop": null + }, + { + "id": 17560, + "code": "XMG", + "issuer": "rHKTzLQjXo7JM7JrKEZo2jyDtC7iqS6NJp", + "title": "Mastersfg2", + "trustlines": 277, + "placeInTop": null + }, + { + "id": 18209, + "code": "XASTRAL", + "issuer": "rwCNcLU7Q2pSz9tkLVQaAg5dN4NhXfKXKX", + "title": "AstralsOnX", + "trustlines": 3738, + "placeInTop": null + }, + { + "id": 18755, + "code": "MTBX", + "issuer": "rJJfuHfwrYLkbzWeoiuQZbzv7Ffi9GEgn7", + "title": "Metabox | $MTBX", + "trustlines": 7166, + "placeInTop": null + }, + { + "id": 40, + "code": "FireFly", + "issuer": "rPo2RQ7JsCSd3WeSKm75XFNZE3oNFPDAbu", + "trustlines": 3951, + "placeInTop": null + }, + { + "id": 360, + "code": "KOLS", + "issuer": "rUThGrdjD3q227DtSAKtviXqpicWjKG9xK", + "title": "KOLS", + "trustlines": 5669, + "placeInTop": null + }, + { + "id": 16976, + "code": "Xange", + "issuer": "r3V7BTuupF5mACHg2vpDRotDqGbMPh5GMv", + "trustlines": 937, + "placeInTop": null + }, + { + "id": 17129, + "code": "VERIFYTEST", + "issuer": "rrhsaymUStZEyGpLP1FBPxkpfNoroAQHtV", + "trustlines": 352, + "placeInTop": null + }, + { + "id": 17841, + "code": "Xrock", + "issuer": "rockUQqYKy3vpCtVnF7yigDiZw887rhN7", + "title": "XRock", + "trustlines": 1816, + "placeInTop": null + }, + { + "id": 16811, + "code": "MAYA", + "issuer": "rGk8tKECA9fxh38ikDAJYn1NSdDcYdY6XF", + "title": "MAYABLUE.X", + "trustlines": 1300, + "placeInTop": null + }, + { + "id": 17591, + "code": "STR", + "issuer": "rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc", + "title": "Coinex", + "trustlines": 1108, + "placeInTop": null + }, + { + "id": 17791, + "code": "USD", + "issuer": "rPDXxSZcuVL3ZWoyU82bcde3zwvmShkRyF", + "title": "WisePass", + "trustlines": 195, + "placeInTop": null + }, + { + "id": 16820, + "code": "MSNGR2", + "issuer": "rHAhxoWNM8vNt5VENuTtS2UAF6BHpDfM7", + "title": "Center for Collaborative Economics", + "trustlines": 651, + "placeInTop": null + }, + { + "id": 17095, + "code": "Earnie", + "issuer": "rsK7bK78azgdi1hD9ZWNXQwmYQ5xrSVE25", + "title": "Earnie", + "trustlines": 3030, + "placeInTop": null + }, + { + "id": 18865, + "code": "JPY", + "issuer": "rUFcQnmGYEuvJVJnZy8QBc9ouKJbpvK7QU", + "title": "DigitalCurrency-ALL", + "trustlines": 228, + "placeInTop": null + }, + { + "id": 339, + "code": "XGalaxy", + "issuer": "rh61FBhuEwAMQ9yArSaEFd8g4dZpJoj6AW", + "title": "XGalaxy", + "trustlines": 3277, + "placeInTop": null + }, + { + "id": 17256, + "code": "Churchcoin", + "issuer": "rKLKvCbtDhNzVzJCvfts6yrzvNUTxYjAi1", + "title": "ChristJesus", + "trustlines": 203, + "placeInTop": null + }, + { + "id": 18503, + "code": "XAU", + "issuer": "rrh7rf1gV2pXAoqA8oYbpHd8TKv5ZQeo67", + "title": "GBI", + "trustlines": 411, + "placeInTop": null + }, + { + "id": 18594, + "code": "LCC", + "issuer": "rG9Fo4mgx5DEZp7zKUEchs3R3jSMbx3NhR", + "trustlines": 1009, + "placeInTop": null + }, + { + "id": 29, + "code": "XRPZclan", + "issuer": "rHuJFGGuN47uzehRxt9GXXsrSaJpVV1zTD", + "title": "Marko Kucic", + "trustlines": 2295, + "placeInTop": null + }, + { + "id": 17223, + "code": "CreatureNFT", + "issuer": "rGWUGk9BUnknFeyPHSxmkv6UPnt4Zs4c92", + "title": "CreatureNFT", + "trustlines": 1215, + "placeInTop": null + }, + { + "id": 18420, + "code": "Loot", + "issuer": "rwJacRXodYJbmJgtjkPrq3zJ2WznCUNHB8", + "title": "xPixelTribes NFT", + "trustlines": 2796, + "placeInTop": null + }, + { + "id": 18633, + "code": "BIOX", + "issuer": "rELctAeDJweX171c359zo8V6zbmgosskkL", + "title": "BIOX\u20223DNFT 2\u00d7\u00d7\u00d7\u2022", + "trustlines": 1427, + "placeInTop": null + }, + { + "id": 18977, + "code": "CNY", + "issuer": "rJ1adrpGS3xsnQMb9Cw54tWJVFPuSdZHK", + "title": "Iripplepay", + "trustlines": 147, + "placeInTop": null + }, + { + "id": 16656, + "code": "ZAC", + "issuer": "rnFkVZytG6YZEGihGeGud9QPqjg4VgSXQg", + "title": "ZAC - NFT | Metaverse", + "trustlines": 1424, + "placeInTop": null + }, + { + "id": 18405, + "code": "SaveUkraine", + "issuer": "rERVWdcnYcWX66c3jH8BBTig47BUkF4bhN", + "title": "Save Ukraine! \ud83c\uddfa\ud83c\udde6", + "trustlines": 483, + "placeInTop": null + }, + { + "id": 17692, + "code": "RDD", + "issuer": "ra9eZxMbJrUcgV8ui7aPc161FgrqWScQxV", + "title": "Peercover", + "trustlines": 133, + "placeInTop": null + }, + { + "id": 19049, + "code": "BTC", + "issuer": "rnuF96W4SZoCJmbHYBFoJZpR8eCaxNvekK", + "title": "rippleCN", + "trustlines": 295, + "placeInTop": null + }, + { + "id": 18854, + "code": "XBeards", + "issuer": "rPdNJ8vZtneXFnmpxfe6bN3pSiwdXKsz6t", + "trustlines": 12598, + "placeInTop": null + }, + { + "id": 17085, + "code": "AURA", + "issuer": "rN2FLTp3TY3skA5axWFDBZJ1PFQMjaQ6V8", + "title": "MAYABLUE.X", + "trustlines": 910, + "placeInTop": null + }, + { + "id": 17693, + "code": "SGD", + "issuer": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH", + "title": "Ripple Singapore", + "trustlines": 319, + "placeInTop": null + }, + { + "id": 18600, + "code": "xBTS", + "issuer": "rap2LWtavwsczeUVeWrXBQvizkTnhxWvLU", + "title": "BTSSTUDIOS", + "trustlines": 1289, + "placeInTop": null + }, + { + "id": 147, + "code": "Kraken", + "issuer": "rDrMVcBp81Zu2PsRXUSLnhojDJ3ARKmFa5", + "title": "KrakenNFT", + "trustlines": 4596, + "placeInTop": null + }, + { + "id": 17913, + "code": "XGOLF", + "issuer": "raJkCbedyFbLEETxAsGdEhVmdFe2BNJguT", + "title": "ApeX GOLF CLUB", + "trustlines": 3801, + "placeInTop": null + }, + { + "id": 18937, + "code": "JPY", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "title": "Bitstamp", + "trustlines": 219, + "placeInTop": null + }, + { + "id": 186, + "code": "XRPETE", + "issuer": "rwNMJ7S9cLMUeBG391eEk9psw4KcPpANKC", + "title": "Digital Black Dollar 1.0", + "trustlines": 3388, + "placeInTop": null + }, + { + "id": 16805, + "code": "DKS", + "issuer": "rpPEq83L7m5uVQ8sQ39eDSqwuWKnq9BHWF", + "trustlines": 1176, + "placeInTop": null + }, + { + "id": 97, + "code": "XrplEstate", + "issuer": "rfHXsDASoEphWsH6V2fmHyEbytkDscDZSA", + "title": "XRPL.ESTATE", + "trustlines": 3854, + "placeInTop": null + }, + { + "id": 17221, + "code": "XRPoodle", + "issuer": "rp1EfhEfouAZpvrLEGxWymLmPcEgJgUoCL", + "title": "XRPoodle", + "trustlines": 1389, + "placeInTop": null + }, + { + "id": 17550, + "code": "XAG", + "issuer": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH", + "title": "Ripple Singapore", + "trustlines": 208, + "placeInTop": null + }, + { + "id": 17689, + "code": "FLC", + "issuer": "rKUxrnNCpXCXAz49Vhtoo6VLfsV7yxU7x3", + "title": "FLCFree", + "trustlines": 194, + "placeInTop": null + }, + { + "id": 17690, + "code": "BTC", + "issuer": "rPDXxSZcuVL3ZWoyU82bcde3zwvmShkRyF", + "title": "WisePass", + "trustlines": 129, + "placeInTop": null + }, + { + "id": 17743, + "code": "AGC", + "issuer": "rfqspG4S6H3NLYGecx3FHHYjPeYSNCdApf", + "trustlines": 131, + "placeInTop": null + }, + { + "id": 18360, + "code": "L3X", + "issuer": "rJUcFtzXGGnNfvsxYp9wVUmwmZikr8gS9G", + "trustlines": 677, + "placeInTop": null + }, + { + "id": 18691, + "code": "MAYUNG", + "issuer": "rMUWw9gAAA3tPcsE16EXxQfepa4Bz7uqjr", + "trustlines": 935, + "placeInTop": null + }, + { + "id": 204, + "code": "XRV", + "issuer": "rMav3Zzkoy4xBnowXkfJ4VGqCWowRvo91q", + "trustlines": 2289, + "placeInTop": null + }, + { + "id": 17318, + "code": "MinerCoin", + "issuer": "rJcDBGuShjinAbX2RU9uh1fkjhaSsBnA2Y", + "trustlines": 532, + "placeInTop": null + }, + { + "id": 17697, + "code": "ZPR", + "issuer": "rUSrgqXVFEw5ZaruTqiDrXDecRuGnhFqu8", + "title": "Z-payment", + "trustlines": 183, + "placeInTop": null + }, + { + "id": 18983, + "code": "BTRAX", + "issuer": "r9K7XjYJ1gYbiYMUpFH1kZMWRpXHjg62EN", + "title": "BTRAX", + "trustlines": 123, + "placeInTop": null + }, + { + "id": 17837, + "code": "RMB", + "issuer": "rLbppnUciWQ2AfLkcdTfBwb1yh97Kc9cfx", + "trustlines": 143, + "placeInTop": null + }, + { + "id": 18483, + "code": "xDoKids", + "issuer": "rPXAnR6jGjhLKDkULLTYxHTLJD6YaB8LRg", + "trustlines": 208, + "placeInTop": null + }, + { + "id": 19038, + "code": "GBP", + "issuer": "rBycsjqxD8RVZP5zrrndiVtJwht7Z457A8", + "title": "Ripula", + "trustlines": 154, + "placeInTop": null + }, + { + "id": 19060, + "code": "LTC", + "issuer": "rJHygWcTLVpSXkowott6kzgZU6viQSVYM1", + "title": "Justcoin", + "trustlines": 199, + "placeInTop": null + }, + { + "id": 17822, + "code": "WormiesPixel", + "issuer": "rUAB829ttzH55qJWEoTFTyyoFCCk3ffFLL", + "title": "WormiesPixel NFT", + "trustlines": 2484, + "placeInTop": null + }, + { + "id": 18926, + "code": "TPD", + "issuer": "rahwRP4um493Vj1AbNwXauNhq9NKaBGEGw", + "trustlines": 498, + "placeInTop": null + }, + { + "id": 16675, + "code": "Sports", + "issuer": "rUG5J5tUSXba4qEhQCQYAZuQuoGHbLyoSb", + "trustlines": 1799, + "placeInTop": null + }, + { + "id": 18022, + "code": "GBP", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "title": "Bitstamp", + "trustlines": 220, + "placeInTop": null + }, + { + "id": 18830, + "code": "BTC", + "issuer": "ra9eZxMbJrUcgV8ui7aPc161FgrqWScQxV", + "title": "Peercover", + "trustlines": 193, + "placeInTop": null + }, + { + "id": 17284, + "code": "WXWARS", + "issuer": "rpuxwHsnZzAd9GiX1kdkgmxgxmGEiH8bmS", + "trustlines": 510, + "placeInTop": null + }, + { + "id": 18421, + "code": "Bitcoin", + "issuer": "rDwXoFKfXEd1cvobSKbfziJ6MZXCgeeSGd", + "trustlines": 117, + "placeInTop": null + }, + { + "id": 18905, + "code": "XDUDEZ", + "issuer": "r39XAsDCCeTm9xSMHXbJVGQ9xGpSgBrHmb", + "trustlines": 279, + "placeInTop": null + }, + { + "id": 17022, + "code": "CoinShares", + "issuer": "rG8656fyrmQVvDfnA5FCYkRpGNUDWXqkQ2", + "title": "CoinShares", + "trustlines": 1148, + "placeInTop": null + }, + { + "id": 17053, + "code": "UMKM", + "issuer": "rLBiwuD6frqK7kZoHeCxRip5m11VZAtgAE", + "title": "UMKM", + "trustlines": 1900, + "placeInTop": null + }, + { + "id": 75, + "code": "UFO", + "issuer": "rD8eKQc7nwVDPspWn87oP8SVaio2kYvuGe", + "trustlines": 2964, + "placeInTop": null + }, + { + "id": 17466, + "code": "JerryCoin", + "issuer": "rHMSpKBiqJgStVrRWXp2m7yXouEGKZaDsW", + "title": "JerryCoin (XRPL)", + "trustlines": 119, + "placeInTop": null + }, + { + "id": 17756, + "code": "BTC", + "issuer": "rMLtFZE6ZvLkiRet8Bncs8EZEWQYXyXixN", + "title": "Christian", + "trustlines": 226, + "placeInTop": null + }, + { + "id": 265, + "code": "XFLAM", + "issuer": "rHNVwZbDdYG5v6LwTGLkxHfqkbahp82C2K", + "title": "XFLAM NFT", + "trustlines": 1417, + "placeInTop": null + }, + { + "id": 243, + "code": "SAP", + "issuer": "r3eSGpqe6TQViqWPusD9EUZCZRAp48SNRz", + "title": "Sapling", + "trustlines": 2673, + "placeInTop": null + }, + { + "id": 16810, + "code": "DIamondsAreForever", + "issuer": "rtFGbpDE4aG5RgpweVao4439BoPoCmzai", + "trustlines": 428, + "placeInTop": null + }, + { + "id": 18317, + "code": "TBG", + "issuer": "rLmEVaa5r6pAr41UjYu2MveQYdnAhB9qnV", + "title": "The Bird Gang 3D (on XRPL)", + "trustlines": 1598, + "placeInTop": null + }, + { + "id": 19078, + "code": "REP", + "issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS", + "title": "Mr. Exchange", + "trustlines": 316, + "placeInTop": null + }, + { + "id": 17932, + "code": "BTS", + "issuer": "rKiCet8SdvWxPXnAgYarFUXMh1zCPz432Y", + "title": "Ripple Fox", + "trustlines": 106, + "placeInTop": null + }, + { + "id": 18085, + "code": "VIOLITY", + "issuer": "rahh5M9CqSH8GU7iN2yWVD8SmLqvjqb72q", + "title": "VIOLITY COIN", + "trustlines": 6210, + "placeInTop": null + }, + { + "id": 18445, + "code": "SER", + "issuer": "rq7vZn33BtRippR8Nv63ho5dDcwuXhKfm", + "title": "\ud83e\uddea\ud83e\uddea BMAC - Blind Mummy Apes Club\ud83d\udc99\ud83d\udc9b", + "trustlines": 187, + "placeInTop": null + }, + { + "id": 19063, + "code": "LTC", + "issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun", + "title": "The Rock Trading", + "trustlines": 254, + "placeInTop": null + }, + { + "id": 17919, + "code": "ShinaInu", + "issuer": "rNRZeJgJrkrMp5VLxrB1yMvZC8jswddqoG", + "title": "Shina Inu XRP", + "trustlines": 1298, + "placeInTop": null + }, + { + "id": 18068, + "code": "xSOLDIER", + "issuer": "rNvEKeW4YidGSgV35swkkzFXeUCKRAHZrv", + "title": "xSOLDIER", + "trustlines": 1988, + "placeInTop": null + }, + { + "id": 257, + "code": "BDH", + "issuer": "r4MEoGepHyv1ZeBNM7R7k4GdmBiXnTDE9t", + "trustlines": 1451, + "placeInTop": null + }, + { + "id": 19107, + "code": "JPY", + "issuer": "rUT8s655PfCmd6GLek6LDefVsEHFnSW8Tg", + "title": "El-live", + "trustlines": 1495, + "placeInTop": null + }, + { + "id": 379, + "code": "MMX", + "issuer": "rEYnYboUF5z8QWQ8SsJTkARNkKGrA6Zgpc", + "trustlines": 4357, + "placeInTop": null + }, + { + "id": 16816, + "code": "DuckCoin", + "issuer": "rPM611tLXe65iT22sX4SdmgjiFq5Je9ubm", + "title": "Duck Art NFT@Japanese Creator", + "trustlines": 438, + "placeInTop": null + }, + { + "id": 17360, + "code": "PIKACHU", + "issuer": "rGk8tKECA9fxh38ikDAJYn1NSdDcYdY6XF", + "title": "MAYABLUE.X", + "trustlines": 210, + "placeInTop": null + }, + { + "id": 17470, + "code": "HULK", + "issuer": "rGk8tKECA9fxh38ikDAJYn1NSdDcYdY6XF", + "title": "MAYABLUE.X", + "trustlines": 144, + "placeInTop": null + }, + { + "id": 18045, + "code": "JCS", + "issuer": "rPU6sXCNzsjcTUEmgJQ5SxDUzY2y1RyYKd", + "title": "Jesus Christ Saves token (JCS)", + "trustlines": 755, + "placeInTop": null + }, + { + "id": 18683, + "code": "CPUNK", + "issuer": "rBEm7MdHwVpg9yhW5ygZCsFRDteL7qDhkL", + "trustlines": 310, + "placeInTop": null + }, + { + "id": 44, + "code": "Multiverse", + "issuer": "rwSL2dcMrF3Qgt6NzEmctEy8XdQBMbM7nG", + "title": "Multiverse", + "trustlines": 3454, + "placeInTop": null + }, + { + "id": 273, + "code": "xGIL", + "issuer": "rBTGEj2yAxMz6VLCd97wB6sG1htNmFuNLX", + "title": "The Xennials", + "trustlines": 654, + "placeInTop": null + }, + { + "id": 18454, + "code": "XRAPTOR", + "issuer": "r4kfpQUbs716GpcE8peKmDHaSGQwXZHBqb", + "title": "XRaptor", + "trustlines": 4053, + "placeInTop": null + }, + { + "id": 18652, + "code": "MAGIC", + "issuer": "rwCsCz93A1svS6Yv8hFqUeKLdTLhBpvqGD", + "trustlines": 202, + "placeInTop": null + }, + { + "id": 18764, + "code": "XSF", + "issuer": "rnZJrGXURD4VubtB5aDRBCsfphmbWBBokT", + "trustlines": 331, + "placeInTop": null + }, + { + "id": 17286, + "code": "XRMETA", + "issuer": "rwnNN6rQSi65U3agEB1jSaD5xc2sWRrNhA", + "title": "XR Meta Worlds", + "trustlines": 3026, + "placeInTop": null + }, + { + "id": 17291, + "code": "CAT", + "issuer": "rnY5qZei5KYoGV1FKv5mPEfC1CAR3aGk38", + "title": "XCATGIRL", + "trustlines": 478, + "placeInTop": null + }, + { + "id": 17758, + "code": "CAD", + "issuer": "raBDVR7JFq3Yho2jf7mcx36sjTwpRJJrGU", + "title": "Bluzelle", + "trustlines": 164, + "placeInTop": null + }, + { + "id": 18142, + "code": "BIRDIEBUCKZ", + "issuer": "rLazWTdfkhFsAscNyr1zCZDM7nxW17AALK", + "title": "BIRDIEBUCKZ", + "trustlines": 1737, + "placeInTop": null + }, + { + "id": 18063, + "code": "SANtoken", + "issuer": "rhZVq1wrgGqWTxoP217H6WxLEGmh3U1Tie", + "title": "Satoshi San", + "trustlines": 8919, + "placeInTop": null + }, + { + "id": 19061, + "code": "LTC", + "issuer": "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9", + "title": "Payroutes", + "trustlines": 189, + "placeInTop": null + }, + { + "id": 16890, + "code": "XRI", + "issuer": "rBhGj6Hn2MMDe3Jf9toPmqGRxgYbq6RHTR", + "trustlines": 1600, + "placeInTop": null + }, + { + "id": 18019, + "code": "BTC", + "issuer": "rBfVgTnsdh8ckC19RM8aVGNuMZnpwrMP6n", + "trustlines": 2428, + "placeInTop": null + }, + { + "id": 18579, + "code": "DFG", + "issuer": "rUfSfEZVyAJDZaRciWYGRAFfB61Wri7LQJ", + "title": "xDeepGifs", + "trustlines": 10137, + "placeInTop": null + }, + { + "id": 18832, + "code": "XPBK", + "issuer": "rDKWKyBQ1pRjLk4v21MZDd2TeZcsGMfQLR", + "trustlines": 433, + "placeInTop": null + }, + { + "id": 18988, + "code": "USD", + "issuer": "r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X", + "title": "WeExchange", + "trustlines": 124, + "placeInTop": null + }, + { + "id": 114, + "code": "UtopiaCoin", + "issuer": "rBfJyugMXyLuE42CM8fVcMBvGt7EhYK9Yh", + "title": "world Utopia", + "trustlines": 2566, + "placeInTop": null + }, + { + "id": 153, + "code": "FUNG", + "issuer": "rHJZySo32ni2VFcnAbevhkEBRBn42wmW6b", + "title": "The Fungal Foundation", + "trustlines": 4386, + "placeInTop": null + }, + { + "id": 264, + "code": "Xmas", + "issuer": "r3KSsS21XwJQgNz4k7MnrHDXgueFYRfn3g", + "title": "Xmas", + "trustlines": 2359, + "placeInTop": null + }, + { + "id": 18318, + "code": "RVRSE", + "issuer": "rHfxbz1LayuEv6GiS46PHmQiW61wDnmCZy", + "title": "ELEMENTUM RELMVERSE", + "trustlines": 1658, + "placeInTop": null + }, + { + "id": 18839, + "code": "XPCH", + "issuer": "rUAWSkedYnTK42QRZeUzNDqZFJZBTPCHrk", + "title": "XPCHANGER", + "trustlines": 1090, + "placeInTop": null + }, + { + "id": 17352, + "code": "VENOM", + "issuer": "rN2FLTp3TY3skA5axWFDBZJ1PFQMjaQ6V8", + "title": "MAYABLUE.X", + "trustlines": 248, + "placeInTop": null + }, + { + "id": 19039, + "code": "AUD", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "title": "Bitstamp", + "trustlines": 129, + "placeInTop": null + }, + { + "id": 121, + "code": "XCHEESEMOON", + "issuer": "rE6F5x9SCyMouBBBRKyoxvpdUkxiTb5wtq", + "title": "XCHEESEMOON", + "trustlines": 3568, + "placeInTop": null + }, + { + "id": 211, + "code": "PIXELS", + "issuer": "rJs4bB6dTHY7GBva5TfT4usBk8wnGdZ4CA", + "title": "PixelsNFT", + "trustlines": 2465, + "placeInTop": null + }, + { + "id": 16817, + "code": "MSNGR1", + "issuer": "rHAhxoWNM8vNt5VENuTtS2UAF6BHpDfM7", + "title": "Center for Collaborative Economics", + "trustlines": 284, + "placeInTop": null + }, + { + "id": 58, + "code": "NSM", + "issuer": "rhtR4fZnbCBpEMk6mqdYrXpy1vNUbAcgYM", + "trustlines": 1757, + "placeInTop": null + }, + { + "id": 71, + "code": "NGoat", + "issuer": "rEs1552ZJS5N9g5L612XSYd7KTuawa8Gtq", + "title": "NGoat", + "trustlines": 3065, + "placeInTop": null + }, + { + "id": 16954, + "code": "TWETTY", + "issuer": "raVFV5cMjZYxHxQ4c67YYffyzjSQCXKUDZ", + "title": "TWETTY TOKEN", + "trustlines": 3211, + "placeInTop": null + }, + { + "id": 17334, + "code": "Iqc", + "issuer": "rBfhKxjwEhmnU7jXgAwdvjB3qjW7RhFkGk", + "title": "IQ cutie", + "trustlines": 256, + "placeInTop": null + }, + { + "id": 18021, + "code": "CHF", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "title": "Bitstamp", + "trustlines": 102, + "placeInTop": null + }, + { + "id": 18605, + "code": "INT", + "issuer": "rh3c9m4unJ2HUpeCoMT5UZ3EDRzd7uBaG2", + "title": "INFINITUM", + "trustlines": 15985, + "placeInTop": null + }, + { + "id": 18885, + "code": "ASS", + "issuer": "rNfPfYv4Ysmrcwz7VTBs6GMhh5GSXexNA8", + "trustlines": 141, + "placeInTop": null + }, + { + "id": 17205, + "code": "FDG", + "issuer": "r9ajH627G23Ex8AAxYkdGaK8eXJ8EapRJE", + "trustlines": 583, + "placeInTop": null + }, + { + "id": 17864, + "code": "MOOD", + "issuer": "rGQtGHrgN4FK1RcEn83q4t8aK6BobzDEMK", + "title": "MOOD", + "trustlines": 999, + "placeInTop": null + }, + { + "id": 18248, + "code": "XRSHINJA", + "issuer": "rsGXGiNsvpCXCm3oybsWqXgrw5BEhY6rRu", + "title": "XRshinja", + "trustlines": 1359, + "placeInTop": null + }, + { + "id": 18456, + "code": "BON", + "issuer": "rHkqAyggqiSvhBdrvfbCbzqbD6nUyGy2CQ", + "title": "Doggy coin", + "trustlines": 257, + "placeInTop": null + }, + { + "id": 18910, + "code": "xHOPE", + "issuer": "rsNrejFNpzZeup75gchNotWeJZDCU1cXKz", + "title": "xHOPE", + "trustlines": 622, + "placeInTop": null + }, + { + "id": 237, + "code": "XrDragonFly", + "issuer": "rKMqegsS5uQbEDU8aDAq2NDtjmDvw465dS", + "trustlines": 1989, + "placeInTop": null + }, + { + "id": 376, + "code": "CodeFuel", + "issuer": "rsF5u4uqCQeRCUkdcBqdabbWTdytw9HxWW", + "title": "CodeCoin", + "trustlines": 617, + "placeInTop": null + }, + { + "id": 17479, + "code": "GALACTUS", + "issuer": "rGk8tKECA9fxh38ikDAJYn1NSdDcYdY6XF", + "title": "MAYABLUE.X", + "trustlines": 104, + "placeInTop": null + }, + { + "id": 17486, + "code": "CHARIZARD", + "issuer": "rGk8tKECA9fxh38ikDAJYn1NSdDcYdY6XF", + "title": "MAYABLUE.X", + "trustlines": 144, + "placeInTop": null + }, + { + "id": 19057, + "code": "USD", + "issuer": "rpDMez6pm6dBve2TJsmDpv7Yae6V5Pyvy2", + "title": "Lake BTC", + "trustlines": 178, + "placeInTop": null + }, + { + "id": 232, + "code": "xDef", + "issuer": "r41kez71qtoNGjMGU8bAFHKt7LCTPdupHi", + "title": "def", + "trustlines": 722, + "placeInTop": null + }, + { + "id": 17183, + "code": "Q17", + "issuer": "rBfhKxjwEhmnU7jXgAwdvjB3qjW7RhFkGk", + "title": "IQ cutie", + "trustlines": 501, + "placeInTop": null + }, + { + "id": 18286, + "code": "XREnergy", + "issuer": "rhc5KqhFNvqwcEYzLqN1V7ypZjQdM7FSXi", + "title": "XrEnergy", + "trustlines": 4788, + "placeInTop": null + }, + { + "id": 18423, + "code": "XWARS", + "issuer": "r9WCKRUG6Cp4tTTLNs3jEFKBUvrbikZ2yr", + "title": "XWars NFT | XRPL", + "trustlines": 313, + "placeInTop": null + }, + { + "id": 83, + "code": "Drizakeo", + "issuer": "rMrCjb6kBtXSFKx8ABMAtCo9H9ChDZE7WK", + "title": "XRP_Drizakeo", + "trustlines": 2512, + "placeInTop": null + }, + { + "id": 92, + "code": "xGBTC", + "issuer": "r4ZXk448HRwZN57H4X8GXXkr93hJQojgWQ", + "title": "RKIDZ_official (Former xGBTC)", + "trustlines": 5915, + "placeInTop": null + }, + { + "id": 282, + "code": "GOD", + "issuer": "rsBd5xoQN4GEpdqtCf4CUHycQYvPF31Fvn", + "trustlines": 431, + "placeInTop": null + }, + { + "id": 16977, + "code": "Xmicron", + "issuer": "rHULkU1xNzhaycHcHeNWFJQ2Jgpamuy4zQ", + "title": "Xmicron", + "trustlines": 556, + "placeInTop": null + }, + { + "id": 17013, + "code": "RSS", + "issuer": "rBKMemZWVwfwm3TfeD3Nt7FpwRTrDzvhh8", + "title": "RSS token / Captivatoken", + "trustlines": 1750, + "placeInTop": null + }, + { + "id": 18806, + "code": "YUM", + "issuer": "rMg4ZumKpM2BekKrFDUCRULBSvuiMqbYUM", + "trustlines": 7192, + "placeInTop": null + }, + { + "id": 133, + "code": "THCoin", + "issuer": "rs1x5ZqpE6SUMfpnvjZhQyQCbLhtYu2sKx", + "title": "$THCoin", + "trustlines": 1450, + "placeInTop": null + }, + { + "id": 287, + "code": "XStorm", + "issuer": "rGe6YD14SMJXSasbTw6fNHnK9ZdLh2PMUw", + "trustlines": 830, + "placeInTop": null + }, + { + "id": 18566, + "code": "AUD", + "issuer": "rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc", + "title": "Coinex", + "trustlines": 1226, + "placeInTop": null + }, + { + "id": 17017, + "code": "xQuotient", + "issuer": "rpjYnDqU3sFrA8R4AeYqXtJiDEHmy9a33A", + "trustlines": 1536, + "placeInTop": null + }, + { + "id": 17292, + "code": "MOON", + "issuer": "rGQtGHrgN4FK1RcEn83q4t8aK6BobzDEMK", + "title": "GORILLA$Gold XRP", + "trustlines": 1304, + "placeInTop": null + }, + { + "id": 18196, + "code": "APPOLIS", + "issuer": "rpw7nNCNQWj9hjV1fonjgox7q4Mb2TkqtU", + "title": "CRYPTAPPOLIS", + "trustlines": 5477, + "placeInTop": null + }, + { + "id": 18681, + "code": "XDistrict", + "issuer": "rwtPQV4gu83aLagD74rM8mjYNknigXAKL4", + "title": "XDistrict", + "trustlines": 699, + "placeInTop": null + }, + { + "id": 56, + "code": "XRDogeGF", + "issuer": "rEMhjbzTbtGN451Ckw39m82PJg2kM7n23b", + "title": "xdogegf", + "trustlines": 2208, + "placeInTop": null + }, + { + "id": 88, + "code": "HTL", + "issuer": "rhH3hVt8kbbqLVNwT52AhfJYBN7aRXsSgX", + "title": "Hotel Coin", + "trustlines": 5835, + "placeInTop": null + }, + { + "id": 108, + "code": "XNARWHAL", + "issuer": "rwav87wr2c3DPNXneidEm3dGUgY6EBf8mo", + "title": "XNARWHAL XRPL NFT", + "trustlines": 2948, + "placeInTop": null + }, + { + "id": 17475, + "code": "RONIN", + "issuer": "rGk8tKECA9fxh38ikDAJYn1NSdDcYdY6XF", + "title": "MAYABLUE.X", + "trustlines": 132, + "placeInTop": null + }, + { + "id": 18367, + "code": "FOREST", + "issuer": "rE9zfbno2FE9hJNfpuBzWL4AtEyRNtNJLX", + "title": "Love Monster \uea00", + "trustlines": 544, + "placeInTop": null + }, + { + "id": 18872, + "code": "XDPC", + "issuer": "rByyTXWjLnYxKRVD39XbvV6YZjDYRGLbyW", + "title": "Dripped Tech", + "trustlines": 7990, + "placeInTop": null + }, + { + "id": 122, + "code": "Robot", + "issuer": "rEiYPtVB19fgasmonT9WUjX4cmC8YjSDqv", + "title": "RoboCoin", + "trustlines": 2982, + "placeInTop": null + }, + { + "id": 17000, + "code": "DRIFTTOKEN", + "issuer": "r3LMUktBCGYteqri1b35ifcRdkZ9uFiEWE", + "title": "DRIFTTOKEN", + "trustlines": 2191, + "placeInTop": null + }, + { + "id": 17195, + "code": "ANOYA", + "issuer": "rHzp9zuLb9b7pRwskKN259NsyzTRmMVJBR", + "title": "ANOYA", + "trustlines": 567, + "placeInTop": null + }, + { + "id": 19086, + "code": "BambooSwap", + "issuer": "rnptNDiFdEZoM67XpR8WQu7zQLSwsuXwjv", + "title": "BambooSwap", + "trustlines": 206, + "placeInTop": null + }, + { + "id": 17544, + "code": "XCC", + "issuer": "rUFcQnmGYEuvJVJnZy8QBc9ouKJbpvK7QU", + "title": "DigitalCurrency-ALL", + "trustlines": 129, + "placeInTop": null + }, + { + "id": 17844, + "code": "XRTIGER", + "issuer": "r4bLPg11nvq23XcGamtdDUWQ29chA5UhYo", + "title": "xrTiger", + "trustlines": 1139, + "placeInTop": null + }, + { + "id": 17845, + "code": "XWGL", + "issuer": "rhMz9DtWqjvG7L3MGqFo46UiYnACQoExXq", + "title": "XWiggle", + "trustlines": 1971, + "placeInTop": null + }, + { + "id": 18097, + "code": "METAVERSE", + "issuer": "rGeGwsRy6mqcgJ7cUN39tmWwzCMhJE91VL", + "title": "METAVERSE", + "trustlines": 903, + "placeInTop": null + }, + { + "id": 18951, + "code": "COCONUTS", + "issuer": "rU5mbWvY2ZuUHnX9kv4TMVR8ctns32DXwR", + "trustlines": 181, + "placeInTop": null + }, + { + "id": 101, + "code": "xTulips", + "issuer": "rUZNppbpNCvvsaBt2XxRhsV3TEtotir4Ps", + "title": "XRPL - xTulips", + "trustlines": 2045, + "placeInTop": null + }, + { + "id": 17168, + "code": "MYBALLS", + "issuer": "rf6R7t11MubRLUcR17ngkLvoQbuRbmHvHV", + "trustlines": 868, + "placeInTop": null + }, + { + "id": 18745, + "code": "GBB", + "issuer": "rNy5WCqUGi3qWiQumYrcCqz4zyBVfKv1Sz", + "trustlines": 210, + "placeInTop": null + }, + { + "id": 107, + "code": "CRYSTAL", + "issuer": "rJ9QRoE5tmuwwpX5LJwefAxao2odPhKUkC", + "title": "CRYSTAL", + "trustlines": 2271, + "placeInTop": null + }, + { + "id": 279, + "code": "Squid", + "issuer": "rJQZQyG8JbxdDFzWR7iKjWfq68rTd9bRY7", + "trustlines": 438, + "placeInTop": null + }, + { + "id": 18593, + "code": "CHIWEENIE", + "issuer": "rpkKss6Dndbs17xkPgAMob4mzQURshh3Rd", + "title": "Chiweenie Gang \ud83d\udc36 XRPL NFT", + "trustlines": 1799, + "placeInTop": null + }, + { + "id": 206, + "code": "Xowl", + "issuer": "rPUJshc2EqJkAw3Yj8NDXHVg3gsuS25ywD", + "title": "Xowl", + "trustlines": 2857, + "placeInTop": null + }, + { + "id": 224, + "code": "XSlime", + "issuer": "rNiPyJBQRpnGTzXtX9NCHUxK89wAPtYXg4", + "title": "XSlime", + "trustlines": 2430, + "placeInTop": null + }, + { + "id": 17264, + "code": "Sand", + "issuer": "r3V7BTuupF5mACHg2vpDRotDqGbMPh5GMv", + "trustlines": 934, + "placeInTop": null + }, + { + "id": 32, + "code": "Bears", + "issuer": "rEiX8SjACtfq1Hhyjb6RGywuqpJx5S7ivT", + "title": "Brave Bears", + "trustlines": 1637, + "placeInTop": null + }, + { + "id": 43, + "code": "MOIN", + "issuer": "rwQUNK99CsdQGv1D159YbcCFde9SvfZ5Lc", + "title": "MOIN", + "trustlines": 2289, + "placeInTop": null + }, + { + "id": 53, + "code": "hellz", + "issuer": "rK6AXD3rh1PZviVNUvYVtagjGn1W5Y9qwv", + "title": "Rocketfella DeMoon", + "trustlines": 2248, + "placeInTop": null + }, + { + "id": 17555, + "code": "XID", + "issuer": "rHNcPKr7kyKc2YMgC77wX9QBGZZJmPX3Sq", + "title": "Garaxia", + "trustlines": 508, + "placeInTop": null + }, + { + "id": 8, + "code": "BabyXRP", + "issuer": "rB4uA81SR2pTtdPRX1A67jD8kxya6cmTnj", + "title": "BabyXRP", + "trustlines": 1871, + "placeInTop": null + }, + { + "id": 17154, + "code": "XMEME*PROPERTY*Pool", + "issuer": "rwrARYbfw3XBQfM19qyJBWupMGvxFyfKpE", + "trustlines": 716, + "placeInTop": null + }, + { + "id": 16753, + "code": "ASTRO", + "issuer": "r3ntcD5rB42dhJRKb3bKKbkci9vCKMSGe4", + "title": "ASTRO", + "trustlines": 3431, + "placeInTop": null + }, + { + "id": 16873, + "code": "FLY", + "issuer": "rRv7cJEoKwQpBC3RoJBjy5LpbpKYDJq2n", + "trustlines": 1829, + "placeInTop": null + }, + { + "id": 16877, + "code": "LGB", + "issuer": "rPxpxtvnettNyuD7daQd36mURiLRC5kX1k", + "trustlines": 1747, + "placeInTop": null + }, + { + "id": 16950, + "code": "SHIT", + "issuer": "rsWMZk95Y116pRDdgowiCskA9k2gsNDWvC", + "title": "xShit", + "trustlines": 919, + "placeInTop": null + }, + { + "id": 18744, + "code": "DQS", + "issuer": "rNy5WCqUGi3qWiQumYrcCqz4zyBVfKv1Sz", + "trustlines": 361, + "placeInTop": null + }, + { + "id": 19085, + "code": "CaRRots", + "issuer": "rafgLy8LPU3mqMGCRbkJcaGWuDwoUCAuwQ", + "title": "XRDonkey", + "trustlines": 229, + "placeInTop": null + }, + { + "id": 19, + "code": "MetaMind", + "issuer": "rsXreKYGtmSzJi8ZnSdBTMgQnqaQ5V8H7S", + "title": "MetaMind", + "trustlines": 2124, + "placeInTop": null + }, + { + "id": 17850, + "code": "DuskCity", + "issuer": "rLHrC9UbWkEPKscwTzXGZVvZsQmfZst3fq", + "title": "DuskCity", + "trustlines": 1862, + "placeInTop": null + }, + { + "id": 18121, + "code": "LTC", + "issuer": "rBfVgTnsdh8ckC19RM8aVGNuMZnpwrMP6n", + "trustlines": 1370, + "placeInTop": null + }, + { + "id": 18377, + "code": "XMetaShiba", + "issuer": "rHze1SoTdFsfzEEoBRktSfBfbvBuWYTcVX", + "title": "XMetaShiba", + "trustlines": 4557, + "placeInTop": null + }, + { + "id": 18736, + "code": "ALT", + "issuer": "rabAY9tuU3T5zbYbyo7JcTevtwpjS83Ypc", + "title": "ALTseason", + "trustlines": 894, + "placeInTop": null + }, + { + "id": 111, + "code": "Aquaverse", + "issuer": "rLHB5uY44TyrMiY6jss35GC5uqFq1aZvL3", + "title": "Aquaverse", + "trustlines": 2492, + "placeInTop": null + }, + { + "id": 192, + "code": "GOONS", + "issuer": "r9qzEdXC2haAkCqE61rBwLW9VnWnCxSmFE", + "title": "XRP GOONS NFT / XRP DOODLE PUNKS NFT", + "trustlines": 3273, + "placeInTop": null + }, + { + "id": 210, + "code": "RUBY", + "issuer": "rQhCaHR3FHwAFSibHAzZCRBMtfLMczUhMK", + "title": "Ruby Play Network", + "trustlines": 1966, + "placeInTop": null + }, + { + "id": 16764, + "code": "STAR", + "issuer": "ratQpkkji1EwuX3b71xAnvssVTdDQkdeCv", + "trustlines": 509, + "placeInTop": null + }, + { + "id": 16872, + "code": "XIB", + "issuer": "rhoqaYdqnjEp4RmZuUCpLiYRsMTTMoJ37r", + "trustlines": 1047, + "placeInTop": null + }, + { + "id": 18826, + "code": "LOW", + "issuer": "rrzQdKukvET4tE7ZmUSxJrAmXAquQnMFG", + "title": "Legends of Warriors", + "trustlines": 823, + "placeInTop": null + }, + { + "id": 18915, + "code": "YXRP", + "issuer": "rEzPNsT6RzKj6ocQw3TjMBjBP2w5M2RiAS", + "trustlines": 106, + "placeInTop": null + }, + { + "id": 20, + "code": "MAA", + "issuer": "rHVCcQYcEuQ7z5bDZXFXe8devDK7Qs2ZAW", + "title": "Xmonkeyz", + "trustlines": 1825, + "placeInTop": null + }, + { + "id": 16680, + "code": "Spidey", + "issuer": "rsK5Hq8eGCkjmjPjYo8vSzfDwYnrqH3yC5", + "title": "Spidey", + "trustlines": 1548, + "placeInTop": null + }, + { + "id": 16683, + "code": "MAB", + "issuer": "rHVCcQYcEuQ7z5bDZXFXe8devDK7Qs2ZAW", + "title": "Xmonkeyz", + "trustlines": 1584, + "placeInTop": null + }, + { + "id": 17169, + "code": "ElonCumV2", + "issuer": "rsJ2rPXQhomvas42UKqDUWKXtMj3JoYLom", + "trustlines": 1138, + "placeInTop": null + }, + { + "id": 17972, + "code": "XRR", + "issuer": "rbkkBEKbToXLdqC8vPdCRgh4wf3kVD9zd", + "trustlines": 140, + "placeInTop": null + }, + { + "id": 296, + "code": "VOTE", + "issuer": "rsHukuxaGdUPUQgAc5568Avb9V6sk15R2w", + "title": "VOTE", + "trustlines": 757, + "placeInTop": null + }, + { + "id": 17044, + "code": "hellzANGELS", + "issuer": "rfya4QvfJEM7rUKUp9BLTGnUoUYaKDRUTa", + "title": "Rocketfella DeMoon", + "trustlines": 1388, + "placeInTop": null + }, + { + "id": 18417, + "code": "VCT", + "issuer": "rUwbSpFZeiJ5fNb1PjhFwyMrcQdj5URtNE", + "title": "VIRTUAL CITY TOKEN", + "trustlines": 1861, + "placeInTop": null + }, + { + "id": 152, + "code": "XAnimalier", + "issuer": "rJmuQJGXSkaoru4SeoCTUiYFf5wwaqARoc", + "title": "XAnimalier_NFT_Token", + "trustlines": 2302, + "placeInTop": null + }, + { + "id": 16743, + "code": "PoopyGary", + "issuer": "rp8XtYFuqneAztu9rue9L6EF774oLFD7YB", + "title": "GTFO GARY", + "trustlines": 692, + "placeInTop": null + }, + { + "id": 17104, + "code": "XRPLGOLD", + "issuer": "rJpjxzativvm31tEh9frBBBvuqhCssom4D", + "title": "XRPL.Gold", + "trustlines": 704, + "placeInTop": null + }, + { + "id": 17157, + "code": "CO2", + "issuer": "rQas7oYeAPR1tN7dzPq9xrYqE4yfrmvHky", + "title": "CO2ious", + "trustlines": 1473, + "placeInTop": null + }, + { + "id": 17177, + "code": "XRPORSHA", + "issuer": "r9WUWJrCJ87MRGmNhVNDd1XwLXm9A6dH6c", + "title": "X.R.PETE", + "trustlines": 753, + "placeInTop": null + }, + { + "id": 17369, + "code": "VVIIIIXDIAMONDHANDS", + "issuer": "rNmrNAmQwzKWUTcoW69s6fZ23iUpKJZEnK", + "title": "Diamond", + "trustlines": 147, + "placeInTop": null + }, + { + "id": 17881, + "code": "BEER", + "issuer": "rMyLn261pBVKtgMbzFpbAsFFBL7ksbFvvM", + "title": "CUTE Token XRPL", + "trustlines": 823, + "placeInTop": null + }, + { + "id": 18277, + "code": "OWL", + "issuer": "rKE5db4MR3Y6Hf7rMFMW8s8PvUQkqmJoy8", + "title": "CryptoOwl", + "trustlines": 1617, + "placeInTop": null + }, + { + "id": 16625, + "code": "MAC", + "issuer": "rHVCcQYcEuQ7z5bDZXFXe8devDK7Qs2ZAW", + "title": "Xmonkeyz", + "trustlines": 422, + "placeInTop": null + }, + { + "id": 16939, + "code": "BUN", + "issuer": "rG7YrUpRQUq7wsr9m44aZTvXUrMe9zjTG5", + "title": "$BUN/$EGG", + "trustlines": 2695, + "placeInTop": null + }, + { + "id": 17118, + "code": "XPIMPIN", + "issuer": "rUmwhpkg6L9yENtY8ovrVekBhAfkEdnwPr", + "trustlines": 330, + "placeInTop": null + }, + { + "id": 18418, + "code": "XCFN", + "issuer": "rnGBXMR8qeEfcjZAbM9cu7xXPBcBXMiJBv", + "title": "xCFN | Crypto Financial Network", + "trustlines": 1065, + "placeInTop": null + }, + { + "id": 18526, + "code": "Xcrb", + "issuer": "rG6dVRn7dNkyFgJX3RvNkUoTqrVLMe5i1i", + "title": "XMetacribz", + "trustlines": 636, + "placeInTop": null + }, + { + "id": 13, + "code": "TBE", + "issuer": "rP9szzcmZp2PrJEhrCskiRT3ESM1kcmYLL", + "title": "TerraMammal", + "trustlines": 802, + "placeInTop": null + }, + { + "id": 78, + "code": "xRabbit", + "issuer": "rKXHVEekLubmBZQj6fTSGwk9yfaoC7nPGk", + "title": "xRabbit", + "trustlines": 3525, + "placeInTop": null + }, + { + "id": 115, + "code": "EVA", + "issuer": "rf1xyzhgedeJUegPfVP69fEjqpzGusLP9Q", + "title": "EVA", + "trustlines": 1964, + "placeInTop": null + }, + { + "id": 17371, + "code": "KRYPTON", + "issuer": "rN2FLTp3TY3skA5axWFDBZJ1PFQMjaQ6V8", + "title": "MAYABLUE.X", + "trustlines": 110, + "placeInTop": null + }, + { + "id": 17442, + "code": "COFFEE", + "issuer": "rLwxtcVyuU3EVJZQhN9h3ZtbMBVNm9sh9r", + "trustlines": 131, + "placeInTop": null + }, + { + "id": 18369, + "code": "JNKZ", + "issuer": "rhc6NxfCW74z4zJKTPPc2kNg1sh8EoX3H5", + "title": "Whitelist Junkiez", + "trustlines": 1649, + "placeInTop": null + }, + { + "id": 18403, + "code": "BRBR", + "issuer": "rEzHW6nqgU6fquF3jeV37H8jS9jnGJwwAu", + "title": "Barber Coin", + "trustlines": 615, + "placeInTop": null + }, + { + "id": 18407, + "code": "XMonke", + "issuer": "rUzHZZ74Yain1Pu7ZsLH4VsF6WaQ1fUkL6", + "title": "xMonke | XRPL - Pre Sale live now!", + "trustlines": 803, + "placeInTop": null + }, + { + "id": 18552, + "code": "xrAPE", + "issuer": "rnxUn5EosoE9BhWHvCkFHWrwAEgmx5ogJq", + "title": "xrAPE", + "trustlines": 681, + "placeInTop": null + }, + { + "id": 18992, + "code": "xWing", + "issuer": "r4VyMvq1FyPJ8h27hVQYgKZxD3jTDmE4C1", + "title": "xWINGS", + "trustlines": 11409, + "placeInTop": null + }, + { + "id": 61, + "code": "RFL", + "issuer": "ra34sTcYZAEScDwp7zKug43yL4XwDtg6qH", + "title": "Rufalo", + "trustlines": 2999, + "placeInTop": null + }, + { + "id": 102, + "code": "MonkeyBucks", + "issuer": "rwK7r9CcfCXRLWxM2Sfc4DN2M9NnekYG22", + "trustlines": 2160, + "placeInTop": null + }, + { + "id": 17171, + "code": "Aqua", + "issuer": "r36n9PBrv7vNuok4Bok3dj1Hn87CuzMeTY", + "title": "Aqua", + "trustlines": 370, + "placeInTop": null + }, + { + "id": 18399, + "code": "XSUP", + "issuer": "rJQt4a313p5W32W2UY2BEBTDBgyikd3PGS", + "title": "X- SUP", + "trustlines": 2690, + "placeInTop": null + }, + { + "id": 18449, + "code": "XMND", + "issuer": "rEMAJB3rVeufmZuTqA9oAafwcp3HrXJTS5", + "title": "M\u2200NDRILL", + "trustlines": 1462, + "placeInTop": null + }, + { + "id": 16940, + "code": "CATCOIN", + "issuer": "rKxReH5riwRFzhJdZULT4SyybTZ8EffW4p", + "title": "CAT COIN", + "trustlines": 1392, + "placeInTop": null + }, + { + "id": 17382, + "code": "Concepts", + "issuer": "rKBWxeTF2TsURqYdgMCDv1s5fhogUp9XdG", + "title": "Digital Concepts", + "trustlines": 672, + "placeInTop": null + }, + { + "id": 17677, + "code": "SYS", + "issuer": "rJr7aKTWthoXgMS65W86fzC5Ccu38ShhXv", + "title": "SYSTEMAXRPL", + "trustlines": 4187, + "placeInTop": null + }, + { + "id": 18510, + "code": "SSTEAM", + "issuer": "rMkxC2pFKCfBdjF9LAJyzneHAhDssaafri", + "title": "Shiba Spaceship Team", + "trustlines": 4517, + "placeInTop": null + }, + { + "id": 16880, + "code": "Kiss", + "issuer": "rnHQqnwWGJ4RXs515LTvdGTNXhWtpYseY3", + "title": "SendMeKiss", + "trustlines": 1777, + "placeInTop": null + }, + { + "id": 17860, + "code": "Zerolimits", + "issuer": "rnES5iow3n1PzUa24fi61DYusxWPDNkD2P", + "title": "ZeroLimits", + "trustlines": 2620, + "placeInTop": null + }, + { + "id": 18525, + "code": "xVIP", + "issuer": "rE152quC47yC128sGJKYfJYN7vjx7of4Mq", + "trustlines": 136, + "placeInTop": null + }, + { + "id": 18923, + "code": "SPR", + "issuer": "rNqTJRgWeWaf75qaTQKg2TNXVpysuR1N9M", + "trustlines": 351, + "placeInTop": null + }, + { + "id": 18991, + "code": "XL2", + "issuer": "rBKtqxDNFdPavMPTnWAdoiokF5mJ3dGMYZ", + "title": "Lineage II XRP", + "trustlines": 670, + "placeInTop": null + }, + { + "id": 16851, + "code": "MOLE", + "issuer": "rEPU1qNvPkYC9hJtrD3rVuCJt8NV8DyEck", + "trustlines": 1405, + "placeInTop": null + }, + { + "id": 16888, + "code": "LUV", + "issuer": "r3nCM71dq1fS2tUNXoJfJgqkXUV2tsE4S4", + "title": "1111Love", + "trustlines": 765, + "placeInTop": null + }, + { + "id": 16911, + "code": "MoonParty", + "issuer": "rf4yfV3MmKKhsEUVAvoVeg6kGS5fR9vvuH", + "trustlines": 1654, + "placeInTop": null + }, + { + "id": 17308, + "code": "HBX", + "issuer": "rpTUkUBRXzc9qxSemyRGFn1igGgb22Mpgm", + "trustlines": 448, + "placeInTop": null + }, + { + "id": 17370, + "code": "XMEME*StabilityPool1", + "issuer": "rLu5fHv3Fqf6c9DBAv1LJufokVRVFhjBaW", + "title": "NFT Private Bank (Matic V2 hybrid NFTs)", + "trustlines": 134, + "placeInTop": null + }, + { + "id": 18366, + "code": "BEER", + "issuer": "rJSPpLt2tjxaVTaKVBrCPn3Lj8TWZ4y6CY", + "title": "BEER Token", + "trustlines": 945, + "placeInTop": null + }, + { + "id": 18969, + "code": "BROTHEL", + "issuer": "rfA5gMg37fKLq9wL3hsiPxi5MtoCK3ENfn", + "trustlines": 163, + "placeInTop": null + }, + { + "id": 36, + "code": "Beez", + "issuer": "rsUZwB2sgFZiHY8XooW2cVzMmCZfcwiWxJ", + "trustlines": 2340, + "placeInTop": null + }, + { + "id": 175, + "code": "TWITCHCOIN", + "issuer": "raYeuXagc8j7NfzRJRLCqyXqzPpKFLWbJU", + "title": "$Ripple\\TWITCHCOIN", + "trustlines": 1220, + "placeInTop": null + }, + { + "id": 17009, + "code": "XRPC", + "issuer": "rJXQCqcjjmBouu7x2pYF6PKKBt7waVAR9D", + "title": "x", + "trustlines": 2497, + "placeInTop": null + }, + { + "id": 17011, + "code": "XLeMi", + "issuer": "rEgLd5rcZ9CUdpDhNZ6vnkpznXQBnwTUna", + "title": "XLeMi", + "trustlines": 1008, + "placeInTop": null + }, + { + "id": 17037, + "code": "BZO", + "issuer": "rHyB8fpHCTB4NhwayEtNH9DsjLue33n1ph", + "trustlines": 973, + "placeInTop": null + }, + { + "id": 17239, + "code": "SAA", + "issuer": "rEN3MR4XsJCTNTVzYAMq82RDSdNhRU2ejb", + "title": "XSkeleton", + "trustlines": 433, + "placeInTop": null + }, + { + "id": 18383, + "code": "QUARRY", + "issuer": "rnNsTa5w5hw3KbTVF7rDQd7RWUEje5Ak5C", + "title": "Love Monster \uea00", + "trustlines": 575, + "placeInTop": null + }, + { + "id": 18476, + "code": "AYNIR", + "issuer": "rhK7Ci1QvXTBJwRVBt7qFSAPQaCjq5zonR", + "title": "AYNIR : All You Need Is Reward$$$$$", + "trustlines": 1012, + "placeInTop": null + }, + { + "id": 18782, + "code": "XZVO", + "issuer": "rQfXMb8ASNWVtpKjJYsQbANeR3WS4QWeZq", + "trustlines": 111, + "placeInTop": null + }, + { + "id": 142, + "code": "CNF", + "issuer": "raTqPZNVpWUQWWRtoG6kUMqnzLdDcfVXqJ", + "title": "ChickensNFT (XRPL)", + "trustlines": 1933, + "placeInTop": null + }, + { + "id": 156, + "code": "Xrplogistic", + "issuer": "rBmZ49VHoGKmDYVGuYsFn448FZcU8JfkGk", + "title": "XRP_Logistic", + "trustlines": 1253, + "placeInTop": null + }, + { + "id": 325, + "code": "XFRUIT", + "issuer": "rQ3HF6YLbB95K5hZRAAMG7X32a1rHE9Yc2", + "trustlines": 1693, + "placeInTop": null + }, + { + "id": 332, + "code": "FRESH", + "issuer": "rw4v5ByH4ew8FZ58NSHxv3ARbetN2TYZF5", + "trustlines": 1576, + "placeInTop": null + }, + { + "id": 16978, + "code": "BURN", + "issuer": "rBb4mVtbtxtEELncFiFULNjaZrBiNJFi3f", + "trustlines": 452, + "placeInTop": null + }, + { + "id": 17202, + "code": "XMP", + "issuer": "rKcmW712NbLw2h29BMr47cwX2HAUNEbwrt", + "title": "XMP", + "trustlines": 101, + "placeInTop": null + }, + { + "id": 17212, + "code": "MICE", + "issuer": "r4M5rrfTSbfh61SH5VANcBGqZgkworfaHQ", + "title": "Biker Mice From Moon - NFT", + "trustlines": 1325, + "placeInTop": null + }, + { + "id": 17225, + "code": "RealMadridfancoin", + "issuer": "rK4saUHTVTpbX7cqzX2zEnZovbDpXxUmk9", + "title": "RealMadridCoinXRP", + "trustlines": 1077, + "placeInTop": null + }, + { + "id": 17299, + "code": "XSwans", + "issuer": "rJYMx2ZHgjocAP3aiK1STbP3CTZASN5Sy8", + "title": "xSwans", + "trustlines": 831, + "placeInTop": null + }, + { + "id": 17411, + "code": "TAROT", + "issuer": "rMyLn261pBVKtgMbzFpbAsFFBL7ksbFvvM", + "title": "CUTE Token XRPL", + "trustlines": 186, + "placeInTop": null + }, + { + "id": 17682, + "code": "XBEAR", + "issuer": "rKXoBbYN5ZKj2Y7Tmhh5xquLMQegqpgNVA", + "trustlines": 392, + "placeInTop": null + }, + { + "id": 18720, + "code": "MTA", + "issuer": "r95bSz69js5MrCoMdhejdGHvHyPRXumLTm", + "trustlines": 664, + "placeInTop": null + }, + { + "id": 18971, + "code": "Meet", + "issuer": "raiuzYGdqxXHG5gQqWZsLdPmuFWXS6oGRF", + "title": "Meet", + "trustlines": 408, + "placeInTop": null + }, + { + "id": 160, + "code": "XAPECLUB", + "issuer": "rHLsj6TzL3jqNVjLaZQkqHissV9FSfMdH5", + "title": "X APE CLUB", + "trustlines": 1739, + "placeInTop": null + }, + { + "id": 16921, + "code": "XrGuru", + "issuer": "rU2RMypDRDod46wpyGqAKo4oHdBKmVctGw", + "title": "XrGuru", + "trustlines": 1904, + "placeInTop": null + }, + { + "id": 16998, + "code": "ProCrypto", + "issuer": "rNcnGzKCtKp6mqrMDS3Ss1T7P1XfDcNXJF", + "title": "ProCrypto Coin", + "trustlines": 458, + "placeInTop": null + }, + { + "id": 17142, + "code": "GEODIS", + "issuer": "rhqnPosMaQvXf3uX84NWbgdRi9yeE7BX8d", + "trustlines": 449, + "placeInTop": null + }, + { + "id": 17476, + "code": "NFTminer", + "issuer": "rnW1yosT7YpR7c9dxSNXNRJe7wYaj2xUzV", + "trustlines": 171, + "placeInTop": null + }, + { + "id": 17694, + "code": "BSD", + "issuer": "r9qouqdcygAWyoFGPxwMN3LoJkpHJHoCBd", + "trustlines": 295, + "placeInTop": null + }, + { + "id": 17862, + "code": "xMinecraft", + "issuer": "rwBrXocEipnM1nc4Kwaq3DQwh8tmBdRCg9", + "title": "xMinecraft", + "trustlines": 1191, + "placeInTop": null + }, + { + "id": 18256, + "code": "Metacasinocoin", + "issuer": "rMBVH1skxjcC1PguikTkx9XP9ydVNpCued", + "title": "MetaCasinoCoin", + "trustlines": 1637, + "placeInTop": null + }, + { + "id": 18493, + "code": "XARMY", + "issuer": "r9kT7eetFtMTZNG6tCaPVQ7Gsc5FaWJTkK", + "title": "XRP Army", + "trustlines": 255, + "placeInTop": null + }, + { + "id": 18620, + "code": "Earn", + "issuer": "rQB3o5oCHPCeGoFGnd9us97N6RsFmTj735", + "trustlines": 1612, + "placeInTop": null + }, + { + "id": 18989, + "code": "Btrax", + "issuer": "rzxFbGjPaW6jE2WyzqmEHKhbSQmMkkJdr", + "trustlines": 430, + "placeInTop": null + }, + { + "id": 151, + "code": "Popcorn", + "issuer": "rPYFeHg6zzD4cxyyfgToX9zAtrDwyeJwUA", + "title": "Pop Corn", + "trustlines": 1882, + "placeInTop": null + }, + { + "id": 16613, + "code": "AXOL", + "issuer": "rGkvzG2RLhCYCtdgtDxaejjaQn4BSJYoy8", + "title": "Axolotl $AXOL XRPL", + "trustlines": 4961, + "placeInTop": null + }, + { + "id": 16857, + "code": "DOP", + "issuer": "rH24cKuAFByzvHDbSx1gvghBDZNb1hb1QD", + "trustlines": 505, + "placeInTop": null + }, + { + "id": 17050, + "code": "MONKS", + "issuer": "rGQtGHrgN4FK1RcEn83q4t8aK6BobzDEMK", + "title": "GORILLA$Gold XRP", + "trustlines": 726, + "placeInTop": null + }, + { + "id": 17800, + "code": "SPUD", + "issuer": "rfzMhyP9EnSgCJ18BZGwj4uH2dLF1YtTzv", + "title": "Sinister Spuds on XRPL", + "trustlines": 930, + "placeInTop": null + }, + { + "id": 18126, + "code": "METAVISION", + "issuer": "rKuuGaBjzt3CV1sX9VgbJUGTDQ6iUSQ2Rr", + "title": "METAVISION", + "trustlines": 801, + "placeInTop": null + }, + { + "id": 18357, + "code": "XdinoKings", + "issuer": "rMxxPovLbYHdcVTpYRiQRoXe1hrke5X6wr", + "title": "Xislanders_XDNT_Xdinos", + "trustlines": 1254, + "placeInTop": null + }, + { + "id": 18619, + "code": "XLEGO", + "issuer": "rsa4uUHzFotQn3gYrW5WjPKibUtSEGXhNi", + "title": "XLEGO", + "trustlines": 355, + "placeInTop": null + }, + { + "id": 18737, + "code": "TZE", + "issuer": "r3ta6EfJVWc7W3cHsnr9srw8amPpWFWiyx", + "trustlines": 109, + "placeInTop": null + }, + { + "id": 18795, + "code": "XRPanther", + "issuer": "rJqN2Bh4e3VwRxj7c8ejVYqhJUbYscQFv1", + "trustlines": 4956, + "placeInTop": null + }, + { + "id": 18817, + "code": "AURAM", + "issuer": "rswTVUVg2kXcvUhfsHSY7a6Yt3aWbyrD9y", + "trustlines": 1077, + "placeInTop": null + }, + { + "id": 19131, + "code": "DAC", + "issuer": "rpmkKzAkJHccD4WxPA5wWimnqocDb4mYzf", + "title": "The Dirty Ape Club", + "trustlines": 432, + "placeInTop": null + }, + { + "id": 74, + "code": "XBadge", + "issuer": "rUrcmbmUADwdkXwtcKiLiFXPNmqQp3EnSE", + "title": "XBadge", + "trustlines": 3459, + "placeInTop": null + }, + { + "id": 220, + "code": "XST", + "issuer": "r9KanwHSeSYB9DXfgc3sDuoE3sRsnQv4wo", + "title": "XSTX", + "trustlines": 2594, + "placeInTop": null + }, + { + "id": 16708, + "code": "JTK", + "issuer": "rESV9W43vQoYNpFf4zJJH7AWgUzNFnHBhN", + "title": "JTK_Coin", + "trustlines": 795, + "placeInTop": null + }, + { + "id": 16860, + "code": "eBets", + "issuer": "rwjTUshHMCGzDkH7S2LPkGcsGx72GgnR2q", + "title": "eBets.crypto", + "trustlines": 1284, + "placeInTop": null + }, + { + "id": 16910, + "code": "PAV", + "issuer": "r4FJh3RK7LpW7UA5u3BJqdFpavQM3Lkwdh", + "trustlines": 1546, + "placeInTop": null + }, + { + "id": 16918, + "code": "xLottery", + "issuer": "rm1avCK5oSVe52N4iEteoFKY27owuBvny", + "trustlines": 1624, + "placeInTop": null + }, + { + "id": 16958, + "code": "XMONSTERs", + "issuer": "rNRc22evysPxh7LhefqFaYtg39YpNfinnN", + "title": "XRPL.Monster", + "trustlines": 1192, + "placeInTop": null + }, + { + "id": 17119, + "code": "Ethereum", + "issuer": "rf6FbkVyYPa9nqrSrRpMDPhBEoAL8bw9GL", + "trustlines": 146, + "placeInTop": null + }, + { + "id": 17121, + "code": "KPK", + "issuer": "rpvQdrkjcnJcimiVazstciB593xhFfxVVG", + "trustlines": 1462, + "placeInTop": null + }, + { + "id": 17218, + "code": "CoinBankShards", + "issuer": "rUhbURn9gPQWcjfqTip5YsMSstBfX8UV9h", + "trustlines": 200, + "placeInTop": null + }, + { + "id": 17373, + "code": "Amazon", + "issuer": "rf4DcrzpBMy2fU2Jdc4RtENTXzrifbdPh7", + "trustlines": 363, + "placeInTop": null + }, + { + "id": 17537, + "code": "XIA", + "issuer": "rsbgrRPMTykHoStSYst8jbqkscAnHCPWY8", + "title": "Digger", + "trustlines": 183, + "placeInTop": null + }, + { + "id": 17629, + "code": "GXZV", + "issuer": "r3u8KaU7ubXQmLMrc3jhEE7vfFpMTMLTWb", + "trustlines": 4079, + "placeInTop": null + }, + { + "id": 18000, + "code": "xWolf", + "issuer": "rKoeHxZcfcoCPsDeEnDSxypcSF5gifH9eM", + "title": "xWolves Pack", + "trustlines": 2262, + "placeInTop": null + }, + { + "id": 18012, + "code": "Scrap", + "issuer": "r3Q5nzkGA9WDz2gCZ3ZSEy2yYseSASru3m", + "title": "universal-digital-assets", + "trustlines": 182, + "placeInTop": null + }, + { + "id": 18280, + "code": "BLKN", + "issuer": "r4acpp9fdgFLcFWfBQSn7fzmXrvCTSW95v", + "trustlines": 351, + "placeInTop": null + }, + { + "id": 18297, + "code": "XDRAW", + "issuer": "rQnpjsUA9SQyPHzSm7aMo6UVQmq1RSKAqn", + "title": "XDRAW", + "trustlines": 1216, + "placeInTop": null + }, + { + "id": 18451, + "code": "MLK", + "issuer": "rHkqAyggqiSvhBdrvfbCbzqbD6nUyGy2CQ", + "title": "Doggy coin", + "trustlines": 3222, + "placeInTop": null + }, + { + "id": 18609, + "code": "Chibs", + "issuer": "rBp3bumejqA1x5uVJRJbx7Ue1viCWpf3cU", + "title": "CrossChainChibs NFT", + "trustlines": 1491, + "placeInTop": null + }, + { + "id": 18631, + "code": "HWT", + "issuer": "rGXPVoPPk8d2cSKFzvugzgTRfyro96z937", + "trustlines": 751, + "placeInTop": null + }, + { + "id": 18655, + "code": "XNFT", + "issuer": "raPmRsVDTnLibYLPSYDjCtFdQh2kNjFrNZ", + "title": "NFTSXRPL", + "trustlines": 781, + "placeInTop": null + }, + { + "id": 18889, + "code": "XLTC", + "issuer": "rLMcg5dXz4x62mTiyb8xuA3kxAKsqzpB9j", + "trustlines": 148, + "placeInTop": null + }, + { + "id": 148, + "code": "SSP", + "issuer": "rN1fgXFQsDnaqL4fpr1Ktthz2yooKkF1Pf", + "title": "SSP", + "trustlines": 1806, + "placeInTop": null + }, + { + "id": 291, + "code": "RCO", + "issuer": "rErVND2kovUvNeZEt1AY9QirN3W2TJqFdi", + "trustlines": 621, + "placeInTop": null + }, + { + "id": 341, + "code": "Multiversexrpl", + "issuer": "ra3tUVitg1Uhv2XHJNQBxP2o5SbApTVQsp", + "trustlines": 577, + "placeInTop": null + }, + { + "id": 16687, + "code": "NFG", + "issuer": "rLzhZeAWFJ8RWS7yZfF7fMZ8sv5EzP8XF9", + "title": "NFG.NFT", + "trustlines": 1511, + "placeInTop": null + }, + { + "id": 16705, + "code": "GVC", + "issuer": "rN5nHQYbpwbabamejBYELSxVbKd95g5UFQ", + "title": "XRPL Bats/Grumpy Vampire Club NFT", + "trustlines": 1057, + "placeInTop": null + }, + { + "id": 16784, + "code": "INSTAGRAM", + "issuer": "raQCAsCVEh3Ysqr5fj4MNHsp46MBjEGJhU", + "title": "INSTAGRAM COIN", + "trustlines": 454, + "placeInTop": null + }, + { + "id": 16865, + "code": "NDI", + "issuer": "rKhDUSLzPY7H7VhPLeYKrsS4tnvZxW7A9t", + "title": "XSwords", + "trustlines": 447, + "placeInTop": null + }, + { + "id": 16892, + "code": "XRPFN", + "issuer": "rLQ4tws9SJWRLuqorq7468gMuygWF3i9YN", + "trustlines": 1560, + "placeInTop": null + }, + { + "id": 17021, + "code": "MCM", + "issuer": "rLpXBZrtyHYtN5rXVYUVZvBBx5aiECQbbx", + "title": "MetaMCM", + "trustlines": 895, + "placeInTop": null + }, + { + "id": 17047, + "code": "MAD", + "issuer": "rHVCcQYcEuQ7z5bDZXFXe8devDK7Qs2ZAW", + "title": "Xmonkeyz", + "trustlines": 714, + "placeInTop": null + }, + { + "id": 17267, + "code": "xMetaCube", + "issuer": "rN3AbAi3DN7fGjR4yA6k84RbhpNEUiLCVj", + "title": "Creative xMetaCube World_XRPLtoken", + "trustlines": 930, + "placeInTop": null + }, + { + "id": 17439, + "code": "KCK", + "issuer": "ra13xSGX6pv1dos7bXi7oMKvRavaJgT3kT", + "trustlines": 216, + "placeInTop": null + }, + { + "id": 17577, + "code": "GUY", + "issuer": "rw1rvdHuTE5gFmv6Sqy7rAYVmBQuXk3Ewh", + "trustlines": 197, + "placeInTop": null + }, + { + "id": 17598, + "code": "Lil", + "issuer": "raZ87rZoVjgg8oc5LijSigyN8rbutXGdbw", + "title": "LilShib", + "trustlines": 4147, + "placeInTop": null + }, + { + "id": 18053, + "code": "USD", + "issuer": "rbwE6wsxzYat1YyGGxzAwq6wBSF5MdoAg", + "title": "R9coin", + "trustlines": 179, + "placeInTop": null + }, + { + "id": 18059, + "code": "LAV", + "issuer": "rPbghDDBotsY2V2gmxCeCddooAY97UStTM", + "title": "Lavender", + "trustlines": 390, + "placeInTop": null + }, + { + "id": 18165, + "code": "EAT", + "issuer": "rBExFc4xruwQbcDgyuVYMADf2MXoHsUZ7L", + "title": "eatozee", + "trustlines": 1237, + "placeInTop": null + }, + { + "id": 18302, + "code": "mXm", + "issuer": "rfXHsMTsLKQPrrTYWtX3fgRPtGCF2drtA2", + "title": "metaXmon", + "trustlines": 6061, + "placeInTop": null + }, + { + "id": 18486, + "code": "HHDaimondHand", + "issuer": "rQrJZnVYhqJ2DjBwQzmMLdpZb5Do8zDcpV", + "title": "HH Diamond Hand Token", + "trustlines": 3390, + "placeInTop": null + }, + { + "id": 18529, + "code": "SMR", + "issuer": "rM96qPVWy16Z5inZyP4JRPeentt63x6yiG", + "trustlines": 120, + "placeInTop": null + }, + { + "id": 18784, + "code": "EXO", + "issuer": "raUFQ3JkVvEREHpbLHmupa5aweJJvtr88v", + "trustlines": 757, + "placeInTop": null + }, + { + "id": 17070, + "code": "ZEN", + "issuer": "rE8Zn9dScGmycaYXCmNSebwwdjZxxvCxcY", + "trustlines": 1690, + "placeInTop": null + }, + { + "id": 17122, + "code": "AIR", + "issuer": "rKhrjrteasANkNRFku535yXfSwijmLLsVK", + "title": "Airdrop Master", + "trustlines": 848, + "placeInTop": null + }, + { + "id": 17201, + "code": "TRL", + "issuer": "rP9szzcmZp2PrJEhrCskiRT3ESM1kcmYLL", + "title": "TerraMammal", + "trustlines": 363, + "placeInTop": null + }, + { + "id": 17287, + "code": "Sainte", + "issuer": "rGS37CXmscR8S9eYuqAHVw9837FTx1snuw", + "trustlines": 202, + "placeInTop": null + }, + { + "id": 17843, + "code": "Three", + "issuer": "rPpXBAzmc99baYbuhSuQCwb6YuNxyTBdYV", + "title": "Three Token", + "trustlines": 960, + "placeInTop": null + }, + { + "id": 18547, + "code": "xJxS", + "issuer": "rJ18qDqXrLKLKagh2bLHLGwVu7AnHZVou7", + "trustlines": 130, + "placeInTop": null + }, + { + "id": 18601, + "code": "OXC", + "issuer": "rJK9noFthmEptcCXDGSMqkHJFwsyYf6PzT", + "title": "OnlyXPunks", + "trustlines": 1187, + "placeInTop": null + }, + { + "id": 19101, + "code": "BabyTan", + "issuer": "r3dXMYohmJxZVHryGucu7XbcwTV44euPe7", + "trustlines": 202, + "placeInTop": null + }, + { + "id": 57, + "code": "X69", + "issuer": "raWsXY8tVytuoZf9kfXXpqYHropz6kEA91", + "title": "$X69 (6,9)", + "trustlines": 2559, + "placeInTop": null + }, + { + "id": 334, + "code": "XARMY", + "issuer": "rD7exzMoMx5mTpock7Fg3kCPcMWFX8ZgPm", + "title": "xARMY", + "trustlines": 3288, + "placeInTop": null + }, + { + "id": 16717, + "code": "XWG", + "issuer": "rMJdH3KdxytqB7ibsvqK8ufCTtPDeT2GQA", + "title": "Wooden Gorilla", + "trustlines": 2150, + "placeInTop": null + }, + { + "id": 16965, + "code": "DDD", + "issuer": "rBixCrcCsbSf3ZeF9zxsLym9KMp2dQde34", + "title": "DDD Token", + "trustlines": 1133, + "placeInTop": null + }, + { + "id": 17089, + "code": "ISO20022", + "issuer": "rfoPuEFfxdskQu8nkJwyGb7HEjFHM5ijvH", + "trustlines": 102, + "placeInTop": null + }, + { + "id": 17120, + "code": "XRDraco", + "issuer": "rwH9BJ8sSVYuQjaTmuabGJLXS9B6Eo7MpT", + "trustlines": 380, + "placeInTop": null + }, + { + "id": 17268, + "code": "GEN", + "issuer": "rG9XbrVXUaBKVE2hxgUBqBNXhFtvo6XTas", + "title": "Genosix", + "trustlines": 2005, + "placeInTop": null + }, + { + "id": 18143, + "code": "Bullish", + "issuer": "rpQrqLasrD2uMUj2NRHJ9jc8d8rcT9q4oA", + "title": "The Bullish Club", + "trustlines": 841, + "placeInTop": null + }, + { + "id": 18230, + "code": "BCH", + "issuer": "rJDrynNXYLnENUSJkUoyepkq9QtAWmhWxM", + "title": "B-Ch Checker", + "trustlines": 3013, + "placeInTop": null + }, + { + "id": 18236, + "code": "XANC", + "issuer": "rHMd5mbLQafuZbN4q6tahY23kxPBnDEhYw", + "trustlines": 255, + "placeInTop": null + }, + { + "id": 18253, + "code": "WarpedAliensGame", + "issuer": "rUKxcRrVWYgCSCrMabkAD3rGBDh9LKLX3N", + "title": "\ud835\udd4e\ud835\udd52\ud835\udd63\ud835\udd61\ud835\udd56\ud835\udd55 \ud835\udd38\ud835\udd5d\ud835\udd5a\ud835\udd56\ud835\udd5f\ud835\udd64 \ud835\udd3e\ud835\udd52\ud835\udd5e\ud835\udd56 \ud835\udd60\ud835\udd5f \ud835\udd4f\u211d\u2119\ud835\udd43", + "trustlines": 1114, + "placeInTop": null + }, + { + "id": 18291, + "code": "HIW", + "issuer": "rh1db2S5sJwzWbqehfK2UXEfP3wu5svXbj", + "title": "HighIQWorld", + "trustlines": 1564, + "placeInTop": null + }, + { + "id": 18343, + "code": "Xombie", + "issuer": "rEPT3uPk7Zu2x4FdqGukrDJwtRP5tgYdw2", + "title": "Xombieverse", + "trustlines": 1004, + "placeInTop": null + }, + { + "id": 18365, + "code": "ETNL", + "issuer": "rfYcf2iZiLRuLxK94VReVPk4WaxGpRB6Fn", + "title": "Eternal Citizens", + "trustlines": 1621, + "placeInTop": null + }, + { + "id": 18381, + "code": "MYACRON", + "issuer": "rP8Fc1THdhSRRf4AYdWTxAx3UooKNsWhSz", + "title": "Love Monster \uea00", + "trustlines": 617, + "placeInTop": null + }, + { + "id": 18513, + "code": "ITEMX", + "issuer": "rfF83CBpuBwX2NkSPcTsnbn3iqwH1uPCbU", + "title": "ITEMX PROPERTIES", + "trustlines": 2558, + "placeInTop": null + }, + { + "id": 18963, + "code": "LYL", + "issuer": "rLoyaLty93xeM35DhizSQdJd8AqLXA39W5", + "trustlines": 360, + "placeInTop": null + }, + { + "id": 18995, + "code": "LOP", + "issuer": "rLoPH2gfKN63jA6AB5smFKdUHywi89s96g", + "trustlines": 2185, + "placeInTop": null + }, + { + "id": 19009, + "code": "AFRICA", + "issuer": "rfef9Ft3FagH947ggDDeNc4sbxKD9nWhPH", + "trustlines": 428, + "placeInTop": null + }, + { + "id": 87, + "code": "AGT", + "issuer": "rDPKnRGk1ceea1h2iNbxCyzVp4MQn3jdtF", + "trustlines": 2138, + "placeInTop": null + }, + { + "id": 91, + "code": "RAIN", + "issuer": "r3cBTiMpEzRdmCgPoBNV7z73CUEPmtZQsC", + "trustlines": 1970, + "placeInTop": null + }, + { + "id": 16658, + "code": "XSteam", + "issuer": "rMPEa5WFjqTtrLnBgzJJPXgyRXtVzSgZb6", + "trustlines": 1415, + "placeInTop": null + }, + { + "id": 16667, + "code": "XWITCH", + "issuer": "rDz3DMjckHrNvpbrQMkpg9uWUf56Q7fzXr", + "title": "The Witch Chibi Official", + "trustlines": 1848, + "placeInTop": null + }, + { + "id": 16902, + "code": "TYO", + "issuer": "rnFiZ5KbTxNmAd6XzvDGxtwvaSQfgwSSG6", + "title": "Tokyo", + "trustlines": 1456, + "placeInTop": null + }, + { + "id": 16927, + "code": "UNC", + "issuer": "rMwmwEFNe9Ao7DEcu4DuRWcFQiXVaCTnYh", + "trustlines": 1517, + "placeInTop": null + }, + { + "id": 16929, + "code": "TRI", + "issuer": "rGrxS9nHnExHCRyH61K8bg51dMmP4nH5hC", + "trustlines": 1156, + "placeInTop": null + }, + { + "id": 17215, + "code": "ServicesOnCall", + "issuer": "raq36mQ26mziAmucxY4tb9dPtzCWnZT7YH", + "trustlines": 1441, + "placeInTop": null + }, + { + "id": 17246, + "code": "XRBitcoin", + "issuer": "rnkUKwv2PJZrem1DecEzCHtnHUwDsEoZYi", + "title": "XRBitcoin", + "trustlines": 210, + "placeInTop": null + }, + { + "id": 17805, + "code": "FQT", + "issuer": "rHUXRWp8DqH2vZSaq9b8qUzrBXDtAwBcwr", + "title": "FooCuties", + "trustlines": 2707, + "placeInTop": null + }, + { + "id": 18066, + "code": "xETH", + "issuer": "rsBC7azvcV3BDzSsJxPeg1z8T4FRzMTAPt", + "trustlines": 657, + "placeInTop": null + }, + { + "id": 18070, + "code": "BonesNFT", + "issuer": "rwc5Uwwo8h4ByfBZ31sM5sxizQmf3FGzY1", + "title": "BonesNFT", + "trustlines": 452, + "placeInTop": null + }, + { + "id": 18128, + "code": "METADEX", + "issuer": "rPgJC4uGuM5j7vLWDwz3Sgkbs5pzP9dba7", + "title": "METADEX", + "trustlines": 456, + "placeInTop": null + }, + { + "id": 18164, + "code": "WEB3", + "issuer": "rwdbu6JD98vzkazZhA8bJi5vGk6XC31Aqq", + "title": "WEB3", + "trustlines": 422, + "placeInTop": null + }, + { + "id": 18267, + "code": "XRMeta", + "issuer": "rwHPGXBVXez6yFiqCtUogoax1TCzCDmLmu", + "trustlines": 163, + "placeInTop": null + }, + { + "id": 18413, + "code": "888", + "issuer": "rLkLGhmomU9RrYrAqaY459w8de3VcEBUG", + "trustlines": 378, + "placeInTop": null + }, + { + "id": 18416, + "code": "WBN", + "issuer": "rfCdVNjLdrGvTisnCmVNd4noP8yfZKoCBp", + "title": "Wild Bee Network", + "trustlines": 3995, + "placeInTop": null + }, + { + "id": 18467, + "code": "FRN", + "issuer": "rna7iiis1Ji6KXPRzvavwVrTNDXpxM1cTF", + "trustlines": 136, + "placeInTop": null + }, + { + "id": 18511, + "code": "FIG", + "issuer": "r4UGsoSSCG3Xfq191N3SDEfBLBzyuAo4Vx", + "trustlines": 113, + "placeInTop": null + }, + { + "id": 18712, + "code": "VFVT", + "issuer": "rnN8H9hxCBntJrJULsveK62eUdkftGP73r", + "trustlines": 236, + "placeInTop": null + }, + { + "id": 18724, + "code": "Shibaluna", + "issuer": "rs4BLVqLDujsuJST6NTZ4rpPv6NnYYjyTF", + "trustlines": 297, + "placeInTop": null + }, + { + "id": 18881, + "code": "POO", + "issuer": "rshitKoinuxBNACMhL6QLwAsfWCUDxYobm", + "trustlines": 110, + "placeInTop": null + }, + { + "id": 18948, + "code": "xBAFC", + "issuer": "rnwgiTTyapeXTD7srnFQzoQFn6P64bVETi", + "trustlines": 490, + "placeInTop": null + }, + { + "id": 18984, + "code": "FacelessWarrior", + "issuer": "r4J9VFFTqYCsdNtTUV1isqHnEsMsDYC6rJ", + "trustlines": 108, + "placeInTop": null + }, + { + "id": 19014, + "code": "Eliz", + "issuer": "rUUuaVpMwtZrD3xT1SbYH1tQVPndthxgrB", + "trustlines": 8873, + "placeInTop": null + }, + { + "id": 343, + "code": "PGS", + "issuer": "rBzmXKofJoDQuPS2bcMtNboGiz1i6EHPm8", + "trustlines": 1491, + "placeInTop": null + }, + { + "id": 344, + "code": "XRKishaInu", + "issuer": "rP5nLxe6XpNDwS9rxZWaJgv14Hbt27E32o", + "title": "XRKishaInu", + "trustlines": 742, + "placeInTop": null + }, + { + "id": 16756, + "code": "XFORTUNE", + "issuer": "rMe6YEJPaPAbRkgub1qD9nFUVJhfCmsMq", + "title": "xFortune", + "trustlines": 529, + "placeInTop": null + }, + { + "id": 16757, + "code": "MEDBED", + "issuer": "rKoJxciEmcejEaCg1gjrxHRXD4vzMg87qP", + "title": "MED BED", + "trustlines": 910, + "placeInTop": null + }, + { + "id": 16765, + "code": "Supreme", + "issuer": "rJUnK2UtHS4xrHtetEBWYTpajQzxrGKjbV", + "title": "Supreme Coin", + "trustlines": 843, + "placeInTop": null + }, + { + "id": 16788, + "code": "JEW", + "issuer": "rHd5as6pt2DJeyx7oZJjkTCZQHGY4f7yxQ", + "title": "XRPL JEWEL", + "trustlines": 893, + "placeInTop": null + }, + { + "id": 16909, + "code": "GSO", + "issuer": "rEqgJ6AyGRBpSk4vmiPUMaJD3zs9WMyKAh", + "trustlines": 1595, + "placeInTop": null + }, + { + "id": 16979, + "code": "$GM", + "issuer": "rhcMVnUV3ZUozysgbgs2Vtsco9zkzqNCMD", + "trustlines": 181, + "placeInTop": null + }, + { + "id": 17002, + "code": "XRL", + "issuer": "rsFJqThf8hZgw1VUEQK3HRpu77kKmPnYB9", + "title": "XRLunaNFT", + "trustlines": 2215, + "placeInTop": null + }, + { + "id": 17003, + "code": "Illuvium", + "issuer": "rMwmindr4En3k4UzhXDa814QXtzqd5nErc", + "trustlines": 542, + "placeInTop": null + }, + { + "id": 17064, + "code": "Xrpinu", + "issuer": "rasXLV2Qi8tc97nywVhQvHHfhHgZHvgYwf", + "trustlines": 1017, + "placeInTop": null + }, + { + "id": 17115, + "code": "GOMD", + "issuer": "rasLGGWLbSEgqm1JWycjvc2sAxUugRo8gt", + "trustlines": 296, + "placeInTop": null + }, + { + "id": 17117, + "code": "Lookey", + "issuer": "rwoVSDUwCVdCpwnkH2Ahh5o7KHfWXLQXmb", + "title": "Lookey", + "trustlines": 823, + "placeInTop": null + }, + { + "id": 17135, + "code": "XLOAN", + "issuer": "r37ueqMppLw8tL9xmu5vRouiAcqwgbtqug", + "trustlines": 1307, + "placeInTop": null + }, + { + "id": 18043, + "code": "ANGELA", + "issuer": "rHcGz1DpZ3XvVCyk6MbXvUuVSVJHqDAKVM", + "title": "Angela - The Little Girl", + "trustlines": 3225, + "placeInTop": null + }, + { + "id": 18044, + "code": "XBEATGIRL", + "issuer": "rs2gfQxFDHE73v7TqBbhqZyKLKiaFppNch", + "title": "Beatrix Girl Project", + "trustlines": 802, + "placeInTop": null + }, + { + "id": 18083, + "code": "ZNT", + "issuer": "rZntokeNtr8m9DYfyLnr2nfTzAxJDnhV9", + "trustlines": 285, + "placeInTop": null + }, + { + "id": 18468, + "code": "XRJapan", + "issuer": "rs4Rz7EiNnWXyVTbm11y3qpj94VVZPxHqm", + "title": "XRJapan", + "trustlines": 601, + "placeInTop": null + }, + { + "id": 18941, + "code": "XRPU", + "issuer": "rEjDDNL1opuSBEBs4eF3ToM4MWj1dd5M8M", + "trustlines": 120, + "placeInTop": null + }, + { + "id": 19137, + "code": "XMusic", + "issuer": "rnSmVZ9z2E9jJ3ac7PJXvobSE7XcYxGmzt", + "trustlines": 272, + "placeInTop": null + }, + { + "id": 41, + "code": "XAMMO", + "issuer": "rGoPVzsJUU4Y6NNfn1Q6tq5TKRVC5yAA44", + "trustlines": 1847, + "placeInTop": null + }, + { + "id": 54, + "code": "CRIME", + "issuer": "rfd79jYCtevdGuu1sq55pf36z6pyYioNXm", + "title": "Rocketfella DeMoon", + "trustlines": 1632, + "placeInTop": null + }, + { + "id": 229, + "code": "MAE", + "issuer": "rHVCcQYcEuQ7z5bDZXFXe8devDK7Qs2ZAW", + "title": "Xmonkeyz", + "trustlines": 159, + "placeInTop": null + }, + { + "id": 286, + "code": "RCO", + "issuer": "rLr45PV5dECH4NhNgzhG3mbDAYxuyj4u5q", + "title": "Reconcile", + "trustlines": 865, + "placeInTop": null + }, + { + "id": 16677, + "code": "XGalaxyStone", + "issuer": "rDE5vYYXxJnfLZTHbzBFo4gjAr9FhAyqqC", + "title": "XGalaxy", + "trustlines": 450, + "placeInTop": null + }, + { + "id": 16923, + "code": "Lightyear", + "issuer": "rLo5NSbWw28LvS5F81BXdYSSnv5hiBA6ES", + "trustlines": 1598, + "placeInTop": null + }, + { + "id": 16924, + "code": "NEC", + "issuer": "rNEhdhji1ByXNMMGp28oZHnwv5bHzUz9mv", + "title": "META", + "trustlines": 2882, + "placeInTop": null + }, + { + "id": 16933, + "code": "PRH", + "issuer": "rMwmwEFNe9Ao7DEcu4DuRWcFQiXVaCTnYh", + "trustlines": 1218, + "placeInTop": null + }, + { + "id": 17016, + "code": "XDO", + "issuer": "rwLLijjmG4jto3sUVPCAifKLggid5feBAZ", + "trustlines": 494, + "placeInTop": null + }, + { + "id": 17048, + "code": "XRIC", + "issuer": "radgfhTRPvEA9jM3GmYXj7gXetg6kSi26G", + "trustlines": 562, + "placeInTop": null + }, + { + "id": 17111, + "code": "ECON", + "issuer": "rpCXAqJaHaRqf4rHMjNrCpsKi1Dc2mJS8F", + "trustlines": 128, + "placeInTop": null + }, + { + "id": 17213, + "code": "EXP", + "issuer": "r9MawWuzyeeSj6GrqWbuT3BNbr6N6GPCYy", + "trustlines": 105, + "placeInTop": null + }, + { + "id": 17295, + "code": "Seby", + "issuer": "rLSG5R79BYecTmvkt5P5qxiJvxCa8p7KHA", + "trustlines": 321, + "placeInTop": null + }, + { + "id": 17315, + "code": "RogueBotNFT", + "issuer": "rDdR9FkkV61sNZZi6miRBDnQvXaNYJdiSc", + "trustlines": 224, + "placeInTop": null + }, + { + "id": 17408, + "code": "MOWGLI", + "issuer": "rfRdAtFRGCBan1E5ALXd7Hkcmdg3Xu48gF", + "title": "MOWGLI", + "trustlines": 520, + "placeInTop": null + }, + { + "id": 17951, + "code": "SNUB", + "issuer": "r9xBBqi5phd8R23omHQVHeBNjhDSrTmrMm", + "trustlines": 875, + "placeInTop": null + }, + { + "id": 18217, + "code": "XMS", + "issuer": "rasAaG4DTg1uCRJTLMAMNfdpTQgVnpM46g", + "title": "xrp multisender", + "trustlines": 1863, + "placeInTop": null + }, + { + "id": 18279, + "code": "STC", + "issuer": "rKL6wV9fP3drGHcu9eh443Q4xVERyWwWAQ", + "title": "XrpFoundationSaveTheChildren", + "trustlines": 1039, + "placeInTop": null + }, + { + "id": 18292, + "code": "Deity", + "issuer": "rGziqYkxHk2LyrUFmo4qkLmpJmK2jhk1KT", + "trustlines": 114, + "placeInTop": null + }, + { + "id": 18322, + "code": "OVEGG", + "issuer": "r9MdSTXZpykBgasdGFDjJT5p93vxuennAG", + "title": "Oviparous Collectables", + "trustlines": 670, + "placeInTop": null + }, + { + "id": 18330, + "code": "MFX", + "issuer": "r4nvnPfHr797Q6zipQKPkh8RZ3cHHLxc5D", + "trustlines": 421, + "placeInTop": null + }, + { + "id": 18341, + "code": "BRZ", + "issuer": "r4i4KNPm26RJqvqtx7HkG9Tc4u2uDBL9gg", + "trustlines": 143, + "placeInTop": null + }, + { + "id": 18380, + "code": "NEKATEST", + "issuer": "rh52WX72oNdwJj6rePE9qCpGjFReBXHoHk", + "trustlines": 133, + "placeInTop": null + }, + { + "id": 18450, + "code": "FUD", + "issuer": "rHkqAyggqiSvhBdrvfbCbzqbD6nUyGy2CQ", + "title": "Doggy coin", + "trustlines": 1584, + "placeInTop": null + }, + { + "id": 18479, + "code": "XFrogman", + "issuer": "rDmBDjjRCiMjHjHzC6m7nd11gGnz2k3Dm9", + "title": "XFrog-man", + "trustlines": 1207, + "placeInTop": null + }, + { + "id": 18568, + "code": "Maharlika", + "issuer": "rDqZqBahgSD73Pi2EwXG6ukcVmcSFtM1tT", + "title": "Maharlikan Guild", + "trustlines": 372, + "placeInTop": null + }, + { + "id": 18803, + "code": "Kidscoin", + "issuer": "rBXYEbSkQaGF3H87bjMz5s6QXAjZKwDGvd", + "trustlines": 118, + "placeInTop": null + }, + { + "id": 18903, + "code": "XPUNKFC", + "issuer": "rJH2ucwzEFcfVyrYCiLHAVwL1VkFHnA96h", + "trustlines": 328, + "placeInTop": null + }, + { + "id": 18949, + "code": "XVPWT", + "issuer": "rXvoteCZbhqMXVx11URCbJpTbkP7Jm1jd", + "trustlines": 187, + "placeInTop": null + }, + { + "id": 18996, + "code": "MUFT", + "issuer": "rw8YAeA3NvxC8usv17mY9FkmS1ei2PqKFm", + "trustlines": 6359, + "placeInTop": null + }, + { + "id": 19012, + "code": "FOOTBALL WORLD CUP", + "issuer": "rUcxXj42XfvtEgz7cXxn4LGcuDzfm7AHTm", + "trustlines": 7543, + "placeInTop": null + }, + { + "id": 129, + "code": "CROM", + "issuer": "rszWfxUVGNAM3Z5YCDQDKpndMKd8WcwK3p", + "trustlines": 643, + "placeInTop": null + }, + { + "id": 143, + "code": "Davavi", + "issuer": "raQeA6mQ5uQDEKd8YagzBQk1LgpHWzKnhD", + "trustlines": 439, + "placeInTop": null + }, + { + "id": 278, + "code": "WMP", + "issuer": "rJMdV26oyxrgZDsPKX8WUVJ55rNbSq3ynX", + "trustlines": 729, + "placeInTop": null + }, + { + "id": 16700, + "code": "KALA", + "issuer": "rfCVwJsq6L8hpsutJ1TSobfuwDJhVtGgmW", + "trustlines": 532, + "placeInTop": null + }, + { + "id": 16749, + "code": "EDUC", + "issuer": "rhRTEyx3Lq4c3RpLo5f5Xibt8YB8XtCxfv", + "title": "Education Token (EDUC on XRPL)", + "trustlines": 1744, + "placeInTop": null + }, + { + "id": 16908, + "code": "XVI", + "issuer": "rMHaa4WrVkpzyJcq9ES3kAe82ofx72DshZ", + "title": "LiveLikeKingz", + "trustlines": 1594, + "placeInTop": null + }, + { + "id": 16970, + "code": "MFC", + "issuer": "ra13xSGX6pv1dos7bXi7oMKvRavaJgT3kT", + "trustlines": 480, + "placeInTop": null + }, + { + "id": 16971, + "code": "MBT", + "issuer": "rwXySmQxaUQn7UAnBv4QpvWv5sJTB2isE1", + "trustlines": 347, + "placeInTop": null + }, + { + "id": 16995, + "code": "ChristmasCoin", + "issuer": "rP9N1D5TicAXC6qAPBJn27bprhSTJ4MEsi", + "trustlines": 1105, + "placeInTop": null + }, + { + "id": 17106, + "code": "DOBE", + "issuer": "rJyME8DgwdnJVtkUPyiEAJhA9XQHsENn9Z", + "trustlines": 539, + "placeInTop": null + }, + { + "id": 17112, + "code": "BullCuck", + "issuer": "rwGfgbLRVrDV3x2Fcu95ADDqtZMtaT4X1T", + "trustlines": 218, + "placeInTop": null + }, + { + "id": 17124, + "code": "ASSHAWK", + "issuer": "r3hCP115jHm2a6CyeXPxfBaJsWrxHMTKvV", + "trustlines": 721, + "placeInTop": null + }, + { + "id": 17145, + "code": "LAVS", + "issuer": "r42Jgmfh9vg7rkX6uyyNyMwhByBMiVuprU", + "trustlines": 269, + "placeInTop": null + }, + { + "id": 17179, + "code": "MGK", + "issuer": "r9G3u3YeVbNhNHHsKYRTsra4tApKkuxuSQ", + "trustlines": 577, + "placeInTop": null + }, + { + "id": 17217, + "code": "XRPDoggy", + "issuer": "rBR9kEXdwwDdGksDto4VaaqsgeA15qDG3q", + "title": "XRPDoggy", + "trustlines": 218, + "placeInTop": null + }, + { + "id": 17222, + "code": "GIVE", + "issuer": "rBvjBZF2qRd1o9fwWT3wbjyCMQ5GQ8KK1k", + "trustlines": 245, + "placeInTop": null + }, + { + "id": 17248, + "code": "Bitcoin", + "issuer": "r388N5HgmPCunXhM5QULAW4KMpeg7HVWkP", + "title": "Meme", + "trustlines": 244, + "placeInTop": null + }, + { + "id": 17249, + "code": "XRSaitama", + "issuer": "r9KmfUKBVVKJAJbrnQXoMUg36f9ztk74dd", + "title": "XRSaitama", + "trustlines": 122, + "placeInTop": null + }, + { + "id": 17252, + "code": "XBG", + "issuer": "r4X9JkeMrQMCW2N6dGc3XK9PFoirpW3NbS", + "trustlines": 158, + "placeInTop": null + }, + { + "id": 17276, + "code": "UFC", + "issuer": "rgfTzdr7TJVmdXBmUYyjjm2RHACAXf53c", + "trustlines": 265, + "placeInTop": null + }, + { + "id": 17281, + "code": "LGBTQ", + "issuer": "rJcDBGuShjinAbX2RU9uh1fkjhaSsBnA2Y", + "trustlines": 228, + "placeInTop": null + }, + { + "id": 17567, + "code": "XRPArmy", + "issuer": "rN8Pat8HPwshmySmwre2uKGrdiJXjSzKK7", + "trustlines": 134, + "placeInTop": null + }, + { + "id": 17681, + "code": "CONTRACTOR", + "issuer": "rKdQVsJBFdAvBrugdEEqa1MnnP7u8u4cQJ", + "title": "ContractorCoin", + "trustlines": 995, + "placeInTop": null + }, + { + "id": 17861, + "code": "XRBet", + "issuer": "rUbKCXsCsrvRyFJYUMbbWsTmnuiYtuJrdS", + "trustlines": 851, + "placeInTop": null + }, + { + "id": 17866, + "code": "Orphanage", + "issuer": "rBg9cmGA5bBnbnCxCgvcHhwypvVAwxNH7x", + "trustlines": 464, + "placeInTop": null + }, + { + "id": 17995, + "code": "Xrew", + "issuer": "r4mneNcxKRSpVGn7GZi1BdngAkSqMAeQmz", + "trustlines": 637, + "placeInTop": null + }, + { + "id": 18255, + "code": "CANNACOIN", + "issuer": "rnheY8yPSVhqWZ9XfSsyRjdUmzmeMqrUD2", + "trustlines": 186, + "placeInTop": null + }, + { + "id": 18276, + "code": "BabyShibainu", + "issuer": "rEKwMCi1hBdoy8MZ1nz963Gec4Tw1YbCgR", + "title": "BabyShibainu", + "trustlines": 108, + "placeInTop": null + }, + { + "id": 18355, + "code": "DIDIT", + "issuer": "rfRxsnwWSUAL6HPb8d9JZHVQWGrLqoAeUc", + "trustlines": 147, + "placeInTop": null + }, + { + "id": 18438, + "code": "CREDITS", + "issuer": "rL1UgNF8TcHw6YCSfbG1ricGArwiqReUNm", + "trustlines": 189, + "placeInTop": null + }, + { + "id": 18484, + "code": "PITx", + "issuer": "rsAHS3agHAyo671V8EFcERoEcEgTeeTW6G", + "trustlines": 208, + "placeInTop": null + }, + { + "id": 18501, + "code": "DBC", + "issuer": "rJpcfNjUXTx5RFEYeyzSerKCKuLk9FZPt", + "trustlines": 191, + "placeInTop": null + }, + { + "id": 18528, + "code": "PARA", + "issuer": "rft1ngEhJwNxTeQDmaqDy7Sg6bQG9YrQYQ", + "trustlines": 115, + "placeInTop": null + }, + { + "id": 18573, + "code": "RugPull", + "issuer": "rpiQEQA1i8LFvdgSZbeHBnNUWETppKPWC7", + "title": "Project Rug Pull", + "trustlines": 186, + "placeInTop": null + }, + { + "id": 18591, + "code": "KTY", + "issuer": "rLYHx7r6uhRaot5UFcRN3arVDMWjfCrodu", + "trustlines": 106, + "placeInTop": null + }, + { + "id": 18697, + "code": "VEND", + "issuer": "rpo8Yt5R5UeTXsxXih7qPeKwXHQj7yj8iL", + "title": "VEND", + "trustlines": 103, + "placeInTop": null + }, + { + "id": 18711, + "code": "TURD", + "issuer": "rH4yQVPK4W3MhJ7gTxotA3BatrdnZQ7YMB", + "trustlines": 114, + "placeInTop": null + }, + { + "id": 18743, + "code": "AstroXRPL", + "issuer": "rhv815JJApsRygvDrKq1t9iDgxmK4xDnPq", + "title": "Astro XRPL", + "trustlines": 654, + "placeInTop": null + }, + { + "id": 18758, + "code": "NCX", + "issuer": "rNAnrcZRxQ2PFYkT78wKTjNHzE7EFqA1E3", + "trustlines": 245, + "placeInTop": null + }, + { + "id": 18816, + "code": "PMC", + "issuer": "rfrmCTJe3zekYFbJfD8QtnTrRrsXvnPyBT", + "title": "PMCissuer", + "trustlines": 643, + "placeInTop": null + }, + { + "id": 18829, + "code": "PRN", + "issuer": "rDsvn6aJG4YMQdHnuJtP9NLrFp18JYTJUf", + "trustlines": 622, + "placeInTop": null + }, + { + "id": 18888, + "code": "Metropolis", + "issuer": "rawczbKvJYwY8TkYhLwAP9mmUhhJMWqwBk", + "trustlines": 157, + "placeInTop": null + }, + { + "id": 18925, + "code": "TDAC", + "issuer": "rpWpPUfN27A8dTz8fJZw4b4HiRX6igsKPZ", + "trustlines": 417, + "placeInTop": null + }, + { + "id": 39, + "code": "JUK", + "issuer": "rN7nWFdRLLiAp33FkQsnPvP7rB2ZMEQ5TF", + "title": "Jukebox", + "trustlines": 2033, + "placeInTop": null + }, + { + "id": 51, + "code": "POP", + "issuer": "rsWg7DAsQmpMDdawUjB95yPwsxXFRxj47H", + "trustlines": 1794, + "placeInTop": null + }, + { + "id": 256, + "code": "CriptoSaurioToken", + "issuer": "rsXdt9Sr9AwZbQtFxSLN9yYVsJ8XidJEVK", + "title": "CriptoSaurios", + "trustlines": 429, + "placeInTop": null + }, + { + "id": 16641, + "code": "WQZ", + "issuer": "r9FbhqdSKTtPhdpCF8pFzzCkHFHUpXLTLG", + "trustlines": 710, + "placeInTop": null + }, + { + "id": 16693, + "code": "Guidance", + "issuer": "r3NEThqCUvgLjA7zdrKfvxDANwsmviLMik", + "title": "Guidance", + "trustlines": 929, + "placeInTop": null + }, + { + "id": 16712, + "code": "XPLNT", + "issuer": "rUtPYqtPBzUpP88PhxN5knDEXcBQpUQbPd", + "trustlines": 410, + "placeInTop": null + }, + { + "id": 16741, + "code": "IGWT", + "issuer": "rPT5ZhM1UUzTg1kfYBJfo3WGxetM66C3pD", + "title": "IGWTrustline", + "trustlines": 1186, + "placeInTop": null + }, + { + "id": 16774, + "code": "XSILVER", + "issuer": "rUpm9huRVf4WoyDc4r18AjfuufZjT3KiTD", + "title": "DSK", + "trustlines": 1332, + "placeInTop": null + }, + { + "id": 16783, + "code": "KadushiXR", + "issuer": "rMx6J6daq9jj6Bq7YN7CGZZNQF2LYrP2y1", + "title": "KadushiXR", + "trustlines": 675, + "placeInTop": null + }, + { + "id": 16912, + "code": "ATH", + "issuer": "rr7GXFTucu3EYKprApnhin4pFDT6WdCRH", + "trustlines": 9014, + "placeInTop": null + }, + { + "id": 16916, + "code": "Axcoin", + "issuer": "ravaGccetHsptXRYojsa142yfW8TpnJAAq", + "trustlines": 1593, + "placeInTop": null + }, + { + "id": 16926, + "code": "RTS", + "issuer": "rMwmwEFNe9Ao7DEcu4DuRWcFQiXVaCTnYh", + "trustlines": 1095, + "placeInTop": null + }, + { + "id": 16935, + "code": "AHCX", + "issuer": "rLLiLAdbwvcDYNDr5gLowiu7DVS3mCaTLz", + "trustlines": 1780, + "placeInTop": null + }, + { + "id": 16993, + "code": "YWY", + "issuer": "rKioikK11rirQCUKySNsxoJHGHuiCD2ixK", + "trustlines": 1656, + "placeInTop": null + }, + { + "id": 17029, + "code": "XSB4", + "issuer": "rwf1QDbXehT5WuQ9E6hvdS5QoYyk6kgby6", + "trustlines": 645, + "placeInTop": null + }, + { + "id": 17039, + "code": "ASSCHEEKS", + "issuer": "rsAUydzTsZijrqXdmSapSQJ5cYyvxuP8f8", + "trustlines": 835, + "placeInTop": null + }, + { + "id": 17056, + "code": "CrucifixCoin", + "issuer": "rGx4j3jaG4RbqG6UabiwvznmEv7cgvkHCG", + "trustlines": 486, + "placeInTop": null + }, + { + "id": 17067, + "code": "Bluetongue", + "issuer": "rGDRWQtEhx8NWk59zQrShdv2eEizrZezNe", + "trustlines": 420, + "placeInTop": null + }, + { + "id": 17132, + "code": "LIT", + "issuer": "rKa3U3n3Zdcz2sy43iiimihYZXrfXk6aY8", + "trustlines": 284, + "placeInTop": null + }, + { + "id": 17140, + "code": "XRHasbulla", + "issuer": "r96QK5tcjNgCWjsccMMY1rhramhqYqBQhj", + "title": "XRHasbulla", + "trustlines": 181, + "placeInTop": null + }, + { + "id": 17216, + "code": "NATN", + "issuer": "rLnU3fo18hhpJG2sZvSkuyooLeB4crHRCy", + "trustlines": 390, + "placeInTop": null + }, + { + "id": 17219, + "code": "FoFF", + "issuer": "rG2mAZ5A2YH1UeXVjsQqh6UaZXBnpiLi9Y", + "title": "FoFF", + "trustlines": 329, + "placeInTop": null + }, + { + "id": 17227, + "code": "TravisScott", + "issuer": "rMwkHmHCjS9qYHUb7zzADZ2yhmmuh4Nhor", + "trustlines": 261, + "placeInTop": null + }, + { + "id": 17243, + "code": "BSG", + "issuer": "rLcoMGVSZDWz3rWheEbPpeQMq2MNfmUoLb", + "title": "JustBull", + "trustlines": 101, + "placeInTop": null + }, + { + "id": 17254, + "code": "MARVEL", + "issuer": "rhcJCDrptNXDyRip9TsPEvydEwfeHHcG1y", + "trustlines": 180, + "placeInTop": null + }, + { + "id": 17257, + "code": "TEXRP", + "issuer": "rwsbKbvqZZs8QbMfkfk5QL6f2MtfgubYud", + "trustlines": 556, + "placeInTop": null + }, + { + "id": 17282, + "code": "META", + "issuer": "rNEhdhji1ByXNMMGp28oZHnwv5bHzUz9mv", + "title": "META", + "trustlines": 866, + "placeInTop": null + }, + { + "id": 17289, + "code": "BRAVE", + "issuer": "rLWDjNnrFvm45uSASGnB9tZoJCnZc2jpMt", + "trustlines": 140, + "placeInTop": null + }, + { + "id": 17322, + "code": "APE", + "issuer": "rJ9b5v7UoW3HbprCU7ZwXfmuuGFN7DJfbf", + "trustlines": 230, + "placeInTop": null + }, + { + "id": 17367, + "code": "HEAL", + "issuer": "rUnkAepqGa9r6mGzpR3p2C1CYYsPurb8wj", + "trustlines": 150, + "placeInTop": null + }, + { + "id": 17398, + "code": "CNY", + "issuer": "rMTqE8ExnkRDuAVrrD7QJubz6JUmkr1P47", + "trustlines": 161, + "placeInTop": null + }, + { + "id": 17447, + "code": "Tree", + "issuer": "rHAhxoWNM8vNt5VENuTtS2UAF6BHpDfM7", + "title": "Center for Collaborative Economics", + "trustlines": 166, + "placeInTop": null + }, + { + "id": 17574, + "code": "MissionRicher", + "issuer": "rKDTfkQ81nRrUCmQriFtfeNAcB4penRzD5", + "trustlines": 201, + "placeInTop": null + }, + { + "id": 17597, + "code": "JJJ", + "issuer": "rwumuHoumJp4YpVzVDMRStnGfLjb89gnvp", + "trustlines": 301, + "placeInTop": null + }, + { + "id": 17622, + "code": "COVID", + "issuer": "rGniT8LXLhgCdwRzyErbKXKoEKyhKfxeur", + "trustlines": 138, + "placeInTop": null + }, + { + "id": 17660, + "code": "XSaitama", + "issuer": "rPDhUfhMLV5ZKGwRBY7oWeQfv1tqzEAcdk", + "title": "XSaitama", + "trustlines": 185, + "placeInTop": null + }, + { + "id": 17663, + "code": "CarbonKiss", + "issuer": "rfuCSriA4SxjA1Mi1aEYsftCQXyjTtq96i", + "trustlines": 153, + "placeInTop": null + }, + { + "id": 17838, + "code": "Xphunk", + "issuer": "rspymsbKNiMdvuoQsvvc2rFDDxm9a27wbq", + "trustlines": 189, + "placeInTop": null + }, + { + "id": 17916, + "code": "XCT", + "issuer": "rwrhYVch6n8Ljvh4EsUvypByCHPQQNKmT8", + "trustlines": 658, + "placeInTop": null + }, + { + "id": 18011, + "code": "JesusCoin", + "issuer": "rNTJyUiXZWDGAUYZxDJtj3k4FLsjyJeSUs", + "trustlines": 159, + "placeInTop": null + }, + { + "id": 18154, + "code": "HornyHorsy", + "issuer": "rfE2kuFdc9W89ZLiXFed4AX29eesH3t1kQ", + "title": "Horny Horsy NFT", + "trustlines": 820, + "placeInTop": null + }, + { + "id": 18158, + "code": "SHOP", + "issuer": "rH4hB2ufbMQWkPbwoZ27mAGtKaPeGdtv71", + "title": "SHOPSPOT", + "trustlines": 258, + "placeInTop": null + }, + { + "id": 18176, + "code": "SourGrapes", + "issuer": "rfS3BN2KpaC6h1jt8RJvZ74M8r5NdZAhHp", + "title": "SourGrapes", + "trustlines": 493, + "placeInTop": null + }, + { + "id": 18228, + "code": "Veteran", + "issuer": "r3Q5nzkGA9WDz2gCZ3ZSEy2yYseSASru3m", + "title": "Universal Digital Assets", + "trustlines": 193, + "placeInTop": null + }, + { + "id": 18254, + "code": "XQUEENS", + "issuer": "rE8VLqoUNiHFzCYaHiWP7KbfmvszNbQ23o", + "trustlines": 278, + "placeInTop": null + }, + { + "id": 18382, + "code": "XRPellet", + "issuer": "rw7WTwbVaxzjPdFw2SkHY3nr97DHwaAD5g", + "title": "XRPellet Official", + "trustlines": 609, + "placeInTop": null + }, + { + "id": 18396, + "code": "MFX", + "issuer": "rLHfNhaVAHXjPFvB7HxtZzY6JuuUKn9dDR", + "trustlines": 103, + "placeInTop": null + }, + { + "id": 18472, + "code": "CGC", + "issuer": "ra2wxKYJ834PVipcwboRQdx8XQ5iFiDyDY", + "trustlines": 101, + "placeInTop": null + }, + { + "id": 18559, + "code": "XDR", + "issuer": "rHkuWrDPcCX6EmZZi6YN5m6go7iDpoEdyN", + "trustlines": 109, + "placeInTop": null + }, + { + "id": 18682, + "code": "Divitiae", + "issuer": "rn6Ehu3VADTf9dK7spjfztKS4QaJg8ef7n", + "trustlines": 125, + "placeInTop": null + }, + { + "id": 18703, + "code": "XrtTrucker", + "issuer": "rpo5fZyJ3L3i5bLdjZTdWkKnPxrAgB2STk", + "trustlines": 458, + "placeInTop": null + }, + { + "id": 18814, + "code": "Kakaw", + "issuer": "rLfDcXdbcySa1L3RnvZvaX2sL111z64DkB", + "trustlines": 112, + "placeInTop": null + }, + { + "id": 18938, + "code": "DedAss", + "issuer": "rHYvhab6JEFcoipghVYjUz5LwMCB7sZmVm", + "title": "DedAss", + "trustlines": 451, + "placeInTop": null + }, + { + "id": 18954, + "code": "FANs", + "issuer": "rGQmh24opk1H44xhH4mGZczbYc7cWuwq3B", + "trustlines": 154, + "placeInTop": null + }, + { + "id": 18955, + "code": "XLunx", + "issuer": "r9Jtt239HADKXGJf61f4WEVAR76c3xoVCa", + "trustlines": 533, + "placeInTop": null + }, + { + "id": 18998, + "code": "CygnetX", + "issuer": "rJYMx2ZHgjocAP3aiK1STbP3CTZASN5Sy8", + "trustlines": 2579, + "placeInTop": null + }, + { + "id": 19136, + "code": "XKZN", + "issuer": "r9adfTxcTeTp1BJQXqtvTvsoK2kr8xYQzR", + "title": "XKaizen", + "trustlines": 18238, + "placeInTop": null + }, + { + "id": 18, + "code": "SDOGI", + "issuer": "rLdNVRKiVM4kvMbLzkZr97BtXcYeeoA19R", + "trustlines": 9090, + "placeInTop": null + }, + { + "id": 35, + "code": "ROOTS", + "issuer": "r3BvncNn56fptaXNXi3xxYZY6owrv4snpx", + "trustlines": 2013, + "placeInTop": null + }, + { + "id": 49, + "code": "SPCLUB", + "issuer": "r4Hoe49khvxSmoWZjQM2jBE8BENHXYpW7k", + "trustlines": 2101, + "placeInTop": null + }, + { + "id": 55, + "code": "COWPUNKS", + "issuer": "rJQs456Y5bhukH14zfFjfzCUoTHtgtamPp", + "trustlines": 1918, + "placeInTop": null + }, + { + "id": 62, + "code": "XSamurai", + "issuer": "raxgWzLpqyiCZbAqYDidy9uB92HU8xHm9M", + "title": "BullishMomentsNFTs", + "trustlines": 2259, + "placeInTop": null + }, + { + "id": 65, + "code": "ANIMA", + "issuer": "r3zbjkCSB4vbBmzFhkWudKhJG7J9fc2Q83", + "title": "Anima", + "trustlines": 4850, + "placeInTop": null + }, + { + "id": 68, + "code": "CLOUD3", + "issuer": "rD7ouXraLQj74kxrHy1aXfjHyMprYf4TCs", + "title": "CLOUD3", + "trustlines": 1813, + "placeInTop": null + }, + { + "id": 73, + "code": "crimeGAME", + "issuer": "rPHS3C24Zmdqn7cf2iKm9XYE4JuJwzmqKr", + "title": "Rocketfella DeMoon", + "trustlines": 1925, + "placeInTop": null + }, + { + "id": 76, + "code": "EXT", + "issuer": "rDL5AvJAQMP9ZvzUjfySoFzNoRM5ctWafD", + "title": "LegacyNFT", + "trustlines": 1517, + "placeInTop": null + }, + { + "id": 128, + "code": "STEM", + "issuer": "rMqnqCtwLfsgmHXi4wUmJd2ad1SK7S6KhE", + "title": "STEM", + "trustlines": 3865, + "placeInTop": null + }, + { + "id": 159, + "code": "XROBOCROT", + "issuer": "rhagSQvDqPsD1nTN4CjKX1KfnzK3h8wEEa", + "title": "xrobocrot", + "trustlines": 1088, + "placeInTop": null + }, + { + "id": 164, + "code": "589XRP", + "issuer": "rhzvvrBSJh8BMpMGzy4us3VkUKGjzD34cb", + "trustlines": 439, + "placeInTop": null + }, + { + "id": 188, + "code": "XShaolin", + "issuer": "raxgWzLpqyiCZbAqYDidy9uB92HU8xHm9M", + "title": "BullishMomentsNFTs", + "trustlines": 458, + "placeInTop": null + }, + { + "id": 189, + "code": "XWomen", + "issuer": "rEK6feXWGNwD34xjXfetggyrdxyr78YaYY", + "trustlines": 489, + "placeInTop": null + }, + { + "id": 190, + "code": "Xpotion", + "issuer": "rJDWouEkBDUncQAYjfNb34Q6fSmy6QVjAm", + "trustlines": 948, + "placeInTop": null + }, + { + "id": 200, + "code": "XMaori", + "issuer": "raxgWzLpqyiCZbAqYDidy9uB92HU8xHm9M", + "title": "BullishMomentsNFTs", + "trustlines": 934, + "placeInTop": null + }, + { + "id": 202, + "code": "XFighter", + "issuer": "raxgWzLpqyiCZbAqYDidy9uB92HU8xHm9M", + "title": "BullishMomentsNFTs", + "trustlines": 482, + "placeInTop": null + }, + { + "id": 205, + "code": "XBRAIN", + "issuer": "rEYz7xucLcUQYLdFzakHodSbuFwTV95f3T", + "title": "OFFICIAL XBRAINS XRPL ", + "trustlines": 3093, + "placeInTop": null + }, + { + "id": 207, + "code": "JennaX", + "issuer": "rHYTL5dyJFGFNCXoLBo4Yhuw2o4HAhRUiP", + "title": "#xPUNK Queen", + "trustlines": 3264, + "placeInTop": null + }, + { + "id": 226, + "code": "Redu", + "issuer": "r4hgK937DndYtxAKTT3pFQDebssMxyR3rJ", + "title": "ReducedLunch", + "trustlines": 1181, + "placeInTop": null + }, + { + "id": 262, + "code": "MSNGR3", + "issuer": "rHAhxoWNM8vNt5VENuTtS2UAF6BHpDfM7", + "title": "Center for Collaborative Economics", + "trustlines": 1122, + "placeInTop": null + }, + { + "id": 268, + "code": "Jaguar", + "issuer": "rURPhsxs1E38R2nmZkbfQtATgm955Apbwh", + "trustlines": 509, + "placeInTop": null + }, + { + "id": 272, + "code": "XFI", + "issuer": "rf38TgVezFfowhzAbmyT6etXUyg8UpjA4g", + "title": "xFinance", + "trustlines": 849, + "placeInTop": null + }, + { + "id": 274, + "code": "XRPBee", + "issuer": "rfvAg9pyBt2DzqRMLtTAfJtGEmWV4bWSAH", + "trustlines": 520, + "placeInTop": null + }, + { + "id": 280, + "code": "BSM", + "issuer": "rM8kLDwknWLBqGfiEHfqkR7QPVJMQn2Fn3", + "trustlines": 765, + "placeInTop": null + }, + { + "id": 303, + "code": "MIRI", + "issuer": "rnnGyUPdxurQL8zrNNaimZ1xA8y1yyNTCT", + "trustlines": 599, + "placeInTop": null + }, + { + "id": 304, + "code": "GuildCoin", + "issuer": "rG5CupSkB3RS8FPqZm2f38DwgGVyweMfYb", + "title": "GuildTower", + "trustlines": 1238, + "placeInTop": null + }, + { + "id": 305, + "code": "XSIC", + "issuer": "rncTRYJNaaYsCVdLYvReQsMgkigjpNuHA6", + "trustlines": 897, + "placeInTop": null + }, + { + "id": 307, + "code": "Opossum", + "issuer": "rsGJhb6aGZ86AAwJj3z45XcYs1MsRL5cDH", + "trustlines": 549, + "placeInTop": null + }, + { + "id": 308, + "code": "CryptoLand", + "issuer": "rBdz9ovrGstn3oToQawBSgVdo1TuuiNqEz", + "trustlines": 3286, + "placeInTop": null + }, + { + "id": 311, + "code": "CREATE", + "issuer": "rP6Df42wRkct2BJBNTgTSVEpjzVqCrTXBM", + "trustlines": 1735, + "placeInTop": null + }, + { + "id": 312, + "code": "ART", + "issuer": "rENp871DKiJjJrswC5Mz4fRXdEnqHj4Qny", + "trustlines": 1823, + "placeInTop": null + }, + { + "id": 316, + "code": "EDCOLLECT", + "issuer": "rJdeSa9Z8hp4YPBSu4EPRszZKAyY3MWFUS", + "trustlines": 1447, + "placeInTop": null + }, + { + "id": 322, + "code": "XBK", + "issuer": "rw2C1dawoWgJhDf3TxrT4GpLrq1NXmzfRb", + "trustlines": 593, + "placeInTop": null + }, + { + "id": 323, + "code": "RHAD", + "issuer": "rhkQRnmE9L6JgSjGGApJ6mntZCuVsfshHT", + "title": "D.P.MonksFinance LTD", + "trustlines": 3302, + "placeInTop": null + }, + { + "id": 327, + "code": "COLLECT", + "issuer": "rwNM54zKJDC8sTfcFYAmNLAoPVGEJkE2iA", + "trustlines": 1300, + "placeInTop": null + }, + { + "id": 331, + "code": "SMART", + "issuer": "r3JhTE5sSShKg84Z5ZW6WEGtEQSuXuMXqv", + "trustlines": 1723, + "placeInTop": null + }, + { + "id": 352, + "code": "FCXVoteYES", + "issuer": "rfF5kbub1f87oSdc9Bi26z9chZJhJMpEXJ", + "trustlines": 197, + "placeInTop": null + }, + { + "id": 362, + "code": "2Cents", + "issuer": "rErA5dLpi3dgHwCD8DJGeeCNs896cnsJQz", + "title": "2CentsCoin", + "trustlines": 424, + "placeInTop": null + }, + { + "id": 16626, + "code": "XUSD", + "issuer": "rfxkJ3eN9oT21thV8MxqFRG71x5xqvzywR", + "trustlines": 1374, + "placeInTop": null + }, + { + "id": 16629, + "code": "XMONSTER", + "issuer": "rPvTZzYC8uJiDsjahWqAuGKBY3TrQKCTYH", + "trustlines": 632, + "placeInTop": null + }, + { + "id": 16634, + "code": "FLR", + "issuer": "rcxJwVnftZzXqyH9YheB8TgeiZUhNo1Eu", + "title": "GateHub FLR", + "trustlines": 22643, + "placeInTop": null + }, + { + "id": 16647, + "code": "XPcoin", + "issuer": "rfpzfcK67GNnptw9Z8P7cjx5B7zhu1zv1e", + "title": "xpmarket", + "trustlines": 12447, + "placeInTop": null + }, + { + "id": 16689, + "code": "RST", + "issuer": "rBLbjkrenS6x369ifpxxj3bMvgWNp7kUCv", + "trustlines": 232, + "placeInTop": null + }, + { + "id": 16690, + "code": "QST", + "issuer": "rKTCrDyfH5dwbndZcvBRqG5UVQgD6mbTHT", + "trustlines": 374, + "placeInTop": null + }, + { + "id": 16691, + "code": "XURB", + "issuer": "rUszxyeKQhqr3KMYYgmpY2vinJB6hZbpTz", + "trustlines": 571, + "placeInTop": null + }, + { + "id": 16694, + "code": "LiFi", + "issuer": "rLWnYnn1hcr8mX113oMD87iv4ugJ6unnJB", + "trustlines": 428, + "placeInTop": null + }, + { + "id": 16696, + "code": "RKIDZ", + "issuer": "rMqyDimznTdwE1DY1V7TrwXvR7iUQZGLF5", + "title": "RKIDZ_official (Former xGBTC)", + "trustlines": 1446, + "placeInTop": null + }, + { + "id": 16697, + "code": "BACT", + "issuer": "rGrUmXd7R8BUqgNFvGqF3JXudh8YuXBFVR", + "trustlines": 534, + "placeInTop": null + }, + { + "id": 16701, + "code": "MHR", + "issuer": "rw1a6Ey51sasTgug64yN9owSjBV8JuZQeH", + "trustlines": 624, + "placeInTop": null + }, + { + "id": 16702, + "code": "XSumo", + "issuer": "raxgWzLpqyiCZbAqYDidy9uB92HU8xHm9M", + "title": "BullishMomentsNFTs", + "trustlines": 922, + "placeInTop": null + }, + { + "id": 16719, + "code": "LWTNFT", + "issuer": "rNyS4GdVJXyZV1sWufsKSAaLZwfnuJSBnf", + "trustlines": 688, + "placeInTop": null + }, + { + "id": 16738, + "code": "XLU", + "issuer": "rGa5AVLKXmn2o1XpEzswXrcMvYzjqEPHKt", + "trustlines": 635, + "placeInTop": null + }, + { + "id": 16758, + "code": "iPictorial", + "issuer": "r3CqqV1oChF4S6fsRhqZe93Ycn1ujgsJpZ", + "trustlines": 303, + "placeInTop": null + }, + { + "id": 16759, + "code": "MPT", + "issuer": "rUaNggdMiSwbytLUMecVxXKutsT3VDRV1g", + "title": "MONEY PRINTER TOKEN", + "trustlines": 1750, + "placeInTop": null + }, + { + "id": 16767, + "code": "XrpMoonParty", + "issuer": "rBx5m4QEFbGeBCRpNcT2P8YdXZNeTJsa4A", + "title": "XRP MoonParty", + "trustlines": 1507, + "placeInTop": null + }, + { + "id": 16772, + "code": "MHX", + "issuer": "rMGgjBz8BLvqNdrWtQKtsCe9ssdWn8KA5A", + "title": "Mhxproject", + "trustlines": 2930, + "placeInTop": null + }, + { + "id": 16777, + "code": "Xgen", + "issuer": "rKw6No7RYJJPRYTqnfcexG2B2Ng4jiivCJ", + "title": "GrowYourOwnNFT", + "trustlines": 979, + "placeInTop": null + }, + { + "id": 16782, + "code": "XRInjuredPunks", + "issuer": "rB9894majqFpciVNcN7HFZ5uTpukDfjfcp", + "title": "XR_InjuredPunks", + "trustlines": 1181, + "placeInTop": null + }, + { + "id": 16806, + "code": "WYM", + "issuer": "rGh6VWMaLEkY8zTTNgT1gXbBY7CEEwhQLH", + "title": "Sonar Muse", + "trustlines": 8076, + "placeInTop": null + }, + { + "id": 16854, + "code": "AGUILA", + "issuer": "rEL1KXDjqmPSXX9DFHcegsF9M3du9vFskK", + "trustlines": 1325, + "placeInTop": null + }, + { + "id": 16855, + "code": "CRYPTO", + "issuer": "rRbiKwcueo6MchUpMFDce9XpDwHhRLPFo", + "trustlines": 1448, + "placeInTop": null + }, + { + "id": 16862, + "code": "XCOLLAB", + "issuer": "ranTVywEvZEJnMqUxifTydbXZDNWx2zM7i", + "trustlines": 1593, + "placeInTop": null + }, + { + "id": 16863, + "code": "XLEARN", + "issuer": "rMofCVmt7Raz4RAPn9uE5jxxN4mFnFHG5g", + "trustlines": 681, + "placeInTop": null + }, + { + "id": 16866, + "code": "XPORN", + "issuer": "raee1iBjzvC43ntPwLkR2G7cLZn1yont3d", + "trustlines": 624, + "placeInTop": null + }, + { + "id": 16870, + "code": "XNAUT", + "issuer": "rnWgBhdddyEw8VURoXLPXWhvuqZzCLdcES", + "trustlines": 1009, + "placeInTop": null + }, + { + "id": 16871, + "code": "XChess", + "issuer": "rhrme3Dt99E8Zpzf6xqy9mV8ntfrioo1Cw", + "trustlines": 1301, + "placeInTop": null + }, + { + "id": 16874, + "code": "GVBK", + "issuer": "r3LATMBogx3Y1r4FcWC1p7MEKPMUzQmpSj", + "trustlines": 2062, + "placeInTop": null + }, + { + "id": 16883, + "code": "XFR", + "issuer": "ra7tqyvUjEeqeZ1DASguxPaz2A5trVyh9g", + "trustlines": 2144, + "placeInTop": null + }, + { + "id": 16895, + "code": "XWhale", + "issuer": "rLNkSRESSC7eihdWYysGLPY77WkmWnwk3s", + "title": "XWhales Official", + "trustlines": 1602, + "placeInTop": null + }, + { + "id": 16896, + "code": "XMC", + "issuer": "rKXXAvKSDV5SgGCc41XfdKcFTFgpsY5jKz", + "trustlines": 790, + "placeInTop": null + }, + { + "id": 16897, + "code": "PNP", + "issuer": "rhZrzqDBvRBTbUYwz1bQcGgZE3PNoMh938", + "trustlines": 1354, + "placeInTop": null + }, + { + "id": 16901, + "code": "XRV", + "issuer": "rBQKSqCmW63fcyvxSthPqvQrgiw3zn9keP", + "title": "HRM AVATAR-TIC CLUB ", + "trustlines": 829, + "placeInTop": null + }, + { + "id": 16914, + "code": "NIXY", + "issuer": "rp3pUDg84qArgBU9mwGUph6NoQeKzeBtbo", + "trustlines": 1578, + "placeInTop": null + }, + { + "id": 16915, + "code": "BCHX", + "issuer": "r4L9Q861brng8jTDhk73VCDUgPfKxPcXwT", + "title": "BCHX", + "trustlines": 1246, + "placeInTop": null + }, + { + "id": 16919, + "code": "BeerToken", + "issuer": "r9RuvgPQPDndJDtLBrf6pAxKSmYxkbsgjd", + "trustlines": 347, + "placeInTop": null + }, + { + "id": 16932, + "code": "ALTv", + "issuer": "rUTG9Xb4Zo38rXNxRffKBjZ3Tw7nu3XJKs", + "trustlines": 1148, + "placeInTop": null + }, + { + "id": 16934, + "code": "RSA", + "issuer": "rMwmwEFNe9Ao7DEcu4DuRWcFQiXVaCTnYh", + "trustlines": 1531, + "placeInTop": null + }, + { + "id": 16936, + "code": "POM", + "issuer": "r9q2WGafALdAGXS2ercbjsB8Fs93z5khWB", + "trustlines": 1926, + "placeInTop": null + }, + { + "id": 16937, + "code": "DONG", + "issuer": "rfL4Sci2ag5hhkpDuqtWYov6j3mshVWLgU", + "title": "Limited Currency", + "trustlines": 1805, + "placeInTop": null + }, + { + "id": 16938, + "code": "XSPACE", + "issuer": "rDGCeU9CjeM2KGdjqtrUPYeku7ByvHycUP", + "title": "XspaceNft", + "trustlines": 3204, + "placeInTop": null + }, + { + "id": 16944, + "code": "EliteXash", + "issuer": "rBxgRFM6SAeZN2FuvvQEpsPdFewoj2AesG", + "title": "EliteXash", + "trustlines": 1279, + "placeInTop": null + }, + { + "id": 16946, + "code": "SPC", + "issuer": "rfxkJ3eN9oT21thV8MxqFRG71x5xqvzywR", + "trustlines": 1501, + "placeInTop": null + }, + { + "id": 16947, + "code": "SSS", + "issuer": "rUDk3xTdHoVruu41mr9Jh5NyRg4svHpbnT", + "trustlines": 1759, + "placeInTop": null + }, + { + "id": 16951, + "code": "XBHT", + "issuer": "rQGwFj7F1C5G2xLpM5D9cRPf79dR4hutpc", + "title": "XBE | XBee Mekaverse NFT", + "trustlines": 2845, + "placeInTop": null + }, + { + "id": 16967, + "code": "Reciprocity", + "issuer": "rw5f98uNdDgu9uR6zhCRrku84b34aiJ3tj", + "trustlines": 202, + "placeInTop": null + }, + { + "id": 16969, + "code": "VacationCoin", + "issuer": "rDNf5DaPfVQfRNJhCYozgNtTUYSBwjqJMo", + "title": "VacationCoin", + "trustlines": 1157, + "placeInTop": null + }, + { + "id": 16972, + "code": "CONSCIENCE", + "issuer": "r9xA4QFhBrK96f7bgpEaT7hACY1Eynt9RL", + "trustlines": 387, + "placeInTop": null + }, + { + "id": 16973, + "code": "UnitOne", + "issuer": "r4dfajeq79mzxusPtvQXvEgt8uPJL7NKuD", + "trustlines": 458, + "placeInTop": null + }, + { + "id": 16974, + "code": "ARC", + "issuer": "rHXyFWcZDMcic25fQvAomQhZiu71sHroom", + "trustlines": 951, + "placeInTop": null + }, + { + "id": 16980, + "code": "LANDX", + "issuer": "rwsf7M8HuPLvozQhKHn4wSwLMtezVCS6sF", + "trustlines": 1063, + "placeInTop": null + }, + { + "id": 16990, + "code": "TOX", + "issuer": "r3EqmKHKr2VrdCsQcMxbPcCzMXjzdCd67P", + "trustlines": 2361, + "placeInTop": null + }, + { + "id": 16996, + "code": "Checkone", + "issuer": "rHZbWwtDYtvv47o2J1m9er8iM3FBRQfm6n", + "trustlines": 1846, + "placeInTop": null + }, + { + "id": 16997, + "code": "PokemonTCG", + "issuer": "rQUqp1zizdKLLMQZLBZtDDXvGDZqvCUMiy", + "title": "Gotta Catch\u2019em All! Nft Master!", + "trustlines": 1963, + "placeInTop": null + }, + { + "id": 17010, + "code": "BikiniBotton", + "issuer": "rEEzEsszXMM69ZmXpEboich1b5BJJAymoz", + "title": "BikiniBotton", + "trustlines": 560, + "placeInTop": null + }, + { + "id": 17014, + "code": "INFTM", + "issuer": "rGzaBTzsYjp7xahHQoqbE1tvKeRoNzeY6n", + "trustlines": 575, + "placeInTop": null + }, + { + "id": 17025, + "code": "XCE", + "issuer": "r9UEc2Xf2Y2TWrvBM5m7H9d7AyfZLc8wtB", + "trustlines": 336, + "placeInTop": null + }, + { + "id": 17027, + "code": "XDev", + "issuer": "rn45ynjsuP5NMefYQBYMHqbF5CSjxG2y9n", + "trustlines": 338, + "placeInTop": null + }, + { + "id": 17030, + "code": "GOLDEGG", + "issuer": "rBmUo4jaGtXm63QRCKA2RvSkXavrqsjuiH", + "trustlines": 1177, + "placeInTop": null + }, + { + "id": 17031, + "code": "GCX", + "issuer": "rNuW7ohW2iztvASjftFnBqEbdkz1xge2Bk", + "title": "GCX", + "trustlines": 414, + "placeInTop": null + }, + { + "id": 17033, + "code": "SHIA", + "issuer": "rKyiVTgYvcyorY1VzSLVmQWNZbFQGVwn1D", + "trustlines": 1092, + "placeInTop": null + }, + { + "id": 17036, + "code": "OREX", + "issuer": "rLcB1vwd9ANrkXcznNfrHF3ohJi2dB4Dka", + "trustlines": 1242, + "placeInTop": null + }, + { + "id": 17038, + "code": "KAA", + "issuer": "rECnFHk4WLGS9AmFUGYnkmmn5SNrBFp6o4", + "trustlines": 792, + "placeInTop": null + }, + { + "id": 17042, + "code": "UNC", + "issuer": "rwo1fD9XWRt6sswqTomC96sENkEG7wn1jS", + "trustlines": 1177, + "placeInTop": null + }, + { + "id": 17059, + "code": "Aether", + "issuer": "rHAhxoWNM8vNt5VENuTtS2UAF6BHpDfM7", + "title": "Center for Collaborative Economics", + "trustlines": 833, + "placeInTop": null + }, + { + "id": 17068, + "code": "PROJECT", + "issuer": "rJkMidTCfjFgp345EmwS4NWuZjjvAoWvyx", + "trustlines": 1476, + "placeInTop": null + }, + { + "id": 17075, + "code": "XRBIGPP", + "issuer": "rMKbvDuJK9gviR1z4LQMqF6VjEvhJMNvci", + "trustlines": 1828, + "placeInTop": null + }, + { + "id": 17079, + "code": "SOLOC", + "issuer": "r3JjKDmVpeWBMNu9kUMrPR2Vr26bAYDr14", + "trustlines": 1778, + "placeInTop": null + }, + { + "id": 17083, + "code": "XRPLDOGE", + "issuer": "rwCnxiJaGhsQTrCPNcZ7VoLEc6ZYfC1wVC", + "title": "XRPLDOGE", + "trustlines": 2245, + "placeInTop": null + }, + { + "id": 17105, + "code": "COBB", + "issuer": "rfKibygzNr84tfFTV8A4fU11kSyA53Pt7s", + "trustlines": 604, + "placeInTop": null + }, + { + "id": 17113, + "code": "TMC", + "issuer": "rJ212MuKJ2uvh1vTqqEkJK1V11FPob7Zrk", + "trustlines": 270, + "placeInTop": null + }, + { + "id": 17116, + "code": "MM2", + "issuer": "rrap7mxsSDGCAzKmtR6ttQmJEMUsMBrFC5", + "trustlines": 217, + "placeInTop": null + }, + { + "id": 17123, + "code": "KMBT", + "issuer": "ratNgPXEX4kASLZ3cwpU7uSMLDYFBJFCU9", + "trustlines": 184, + "placeInTop": null + }, + { + "id": 17125, + "code": "AuCoin", + "issuer": "rDAePhvSKX4gKSrjEAw8kA8xmPNhyx9Fiu", + "trustlines": 439, + "placeInTop": null + }, + { + "id": 17126, + "code": "CHAD", + "issuer": "r9nPB99QH8nNEjTtN5xfqnbDUpiduBZjdG", + "trustlines": 1026, + "placeInTop": null + }, + { + "id": 17127, + "code": "SDOGE", + "issuer": "rhCLRdLc2MCxvtoumcKZFNfxMEhQLfxdTq", + "trustlines": 1731, + "placeInTop": null + }, + { + "id": 17130, + "code": "XVikings", + "issuer": "raxgWzLpqyiCZbAqYDidy9uB92HU8xHm9M", + "title": "BullishMomentsNFTs", + "trustlines": 287, + "placeInTop": null + }, + { + "id": 17133, + "code": "xMAGA", + "issuer": "rQfCaTEkahVPNfKYbu2Bw3KT6fTFepf2kw", + "trustlines": 1275, + "placeInTop": null + }, + { + "id": 17138, + "code": "CX3", + "issuer": "rDxdjF5bECFfM4TgnnNue9o5ovNDNR2hec", + "trustlines": 1872, + "placeInTop": null + }, + { + "id": 17143, + "code": "EXQ", + "issuer": "raL4mET7PsaEj7bYujSNH1i1CzpuJ9Fw4W", + "trustlines": 471, + "placeInTop": null + }, + { + "id": 17144, + "code": "Xbud", + "issuer": "rKw6No7RYJJPRYTqnfcexG2B2Ng4jiivCJ", + "title": "GrowYourOwnNFT", + "trustlines": 494, + "placeInTop": null + }, + { + "id": 17147, + "code": "BRLZ", + "issuer": "rEghiMbiboaWGJi7gaYPM6tFGt4xKGQhgm", + "trustlines": 483, + "placeInTop": null + }, + { + "id": 17161, + "code": "XAP", + "issuer": "rwBiSxAQx7KC1WV6Zua1YVvcfJQdLPkG33", + "trustlines": 683, + "placeInTop": null + }, + { + "id": 17163, + "code": "LGT", + "issuer": "rBnXtGYjH28RHkcUkuv2R21hHuKWHmnieC", + "trustlines": 799, + "placeInTop": null + }, + { + "id": 17164, + "code": "Xgrow", + "issuer": "rKw6No7RYJJPRYTqnfcexG2B2Ng4jiivCJ", + "title": "GrowYourOwnNFT", + "trustlines": 303, + "placeInTop": null + }, + { + "id": 17167, + "code": "KYC", + "issuer": "rKTCrDyfH5dwbndZcvBRqG5UVQgD6mbTHT", + "trustlines": 249, + "placeInTop": null + }, + { + "id": 17173, + "code": "AXS", + "issuer": "rKU59Uaj3HVzSFAbSMXcdvrRsDR5CMC9Ez", + "trustlines": 105, + "placeInTop": null + }, + { + "id": 17176, + "code": "MOSS", + "issuer": "rNvoCBsP2HcFhBh2r1JncHEs3YtYGdiZoy", + "trustlines": 180, + "placeInTop": null + }, + { + "id": 17198, + "code": "XRI", + "issuer": "rPaAiDAo5uWeqhaAWZw6Sgbv1RBZzkeKmw", + "trustlines": 832, + "placeInTop": null + }, + { + "id": 17203, + "code": "SCAMx", + "issuer": "rU1KpfQhCprYH6rGBVVPie4faUb9E2vZQB", + "title": "SCAMx", + "trustlines": 395, + "placeInTop": null + }, + { + "id": 17204, + "code": "VRP", + "issuer": "rJk9sq1a3jhBr7mqx9SXmkLgpNNXwV7SDj", + "trustlines": 338, + "placeInTop": null + }, + { + "id": 17206, + "code": "XCOLLECT", + "issuer": "r314X1hJQRPWHMx7exD2xonYR8owWRYYEm", + "trustlines": 645, + "placeInTop": null + }, + { + "id": 17220, + "code": "CRYPTOPIUM", + "issuer": "rMNcmHJ2FnSze3wMZAuacESE4G2Y5G78dV", + "trustlines": 224, + "placeInTop": null + }, + { + "id": 17224, + "code": "VIAL", + "issuer": "r9VgcESgJeT7E5c7ENkhEQ2t3Y97a7i7Kh", + "trustlines": 517, + "placeInTop": null + }, + { + "id": 17233, + "code": "LAND", + "issuer": "rHAhxoWNM8vNt5VENuTtS2UAF6BHpDfM7", + "title": "Center for Collaborative Economics", + "trustlines": 262, + "placeInTop": null + }, + { + "id": 17241, + "code": "XRPP", + "issuer": "rnTAZgihNyG12FeNwXBtHQz7sfULraxRPP", + "trustlines": 432, + "placeInTop": null + }, + { + "id": 17244, + "code": "XCumRocket", + "issuer": "r4PG82JC4ApzSB9cmu1bbfVnJrkUY8j9yB", + "title": "XCumRocket", + "trustlines": 334, + "placeInTop": null + }, + { + "id": 17253, + "code": "GOLD", + "issuer": "raqT4Q5sz4t66bbooaCRLMPoiKyLRDNX8Y", + "trustlines": 168, + "placeInTop": null + }, + { + "id": 17258, + "code": "EXPC", + "issuer": "rLb593mo6Nerw7eWvC19gR1fLggeWX6u6s", + "title": "Tuition DeFi Network", + "trustlines": 228, + "placeInTop": null + }, + { + "id": 17260, + "code": "UnvaxxedSperm", + "issuer": "rLZn9qH5ivDCpMrSiW6EPutxwDZinXuYK7", + "trustlines": 150, + "placeInTop": null + }, + { + "id": 17262, + "code": "FRLZ", + "issuer": "rLT9fAFcChvKVkZpiV3H2NYabfnZzsLkii", + "trustlines": 335, + "placeInTop": null + }, + { + "id": 17275, + "code": "BINANCE", + "issuer": "rU2VgeFkmYKxiUdizrc6KC9ru72892UgFc", + "trustlines": 402, + "placeInTop": null + }, + { + "id": 17303, + "code": "EPWC", + "issuer": "rLb593mo6Nerw7eWvC19gR1fLggeWX6u6s", + "title": "Tuition DeFi Network", + "trustlines": 199, + "placeInTop": null + }, + { + "id": 17310, + "code": "DEF", + "issuer": "rBXoMDvgeWB12djrk2ye87qLZaxvtRzRP", + "trustlines": 164, + "placeInTop": null + }, + { + "id": 17313, + "code": "NKY", + "issuer": "rhZrzqDBvRBTbUYwz1bQcGgZE3PNoMh938", + "trustlines": 177, + "placeInTop": null + }, + { + "id": 17320, + "code": "Check", + "issuer": "rHZbWwtDYtvv47o2J1m9er8iM3FBRQfm6n", + "trustlines": 169, + "placeInTop": null + }, + { + "id": 17323, + "code": "Fegx", + "issuer": "rsiNNJppE3WjQVHALGZtVP9efHLVTUmdnS", + "trustlines": 203, + "placeInTop": null + }, + { + "id": 17324, + "code": "LimitedCoin", + "issuer": "rQpFGJfvyZBJFG9tq2rf6x7vuVgLdEURzY", + "trustlines": 182, + "placeInTop": null + }, + { + "id": 17325, + "code": "AzteX", + "issuer": "raxgWzLpqyiCZbAqYDidy9uB92HU8xHm9M", + "title": "BullishMomentsNFTs", + "trustlines": 179, + "placeInTop": null + }, + { + "id": 17326, + "code": "BALLS", + "issuer": "rKHpPgZwQ8EwQzsdrA6b4kavQNvWgkawj1", + "trustlines": 140, + "placeInTop": null + }, + { + "id": 17335, + "code": "XRPARMY", + "issuer": "rwTUoSbmTFoaJhQops4RzQ9vBDq5DKggc6", + "trustlines": 689, + "placeInTop": null + }, + { + "id": 17343, + "code": "618X", + "issuer": "r9ubsFeHjxfDuSMCKyPP6RBajctTTKU7zR", + "trustlines": 272, + "placeInTop": null + }, + { + "id": 17347, + "code": "Mikey", + "issuer": "rHZbWwtDYtvv47o2J1m9er8iM3FBRQfm6n", + "trustlines": 232, + "placeInTop": null + }, + { + "id": 17348, + "code": "SNX", + "issuer": "rNaKJ8p83WqNqGqpxP5E2yvPxqa122Jtfw", + "title": "Sk8Nation", + "trustlines": 178, + "placeInTop": null + }, + { + "id": 17366, + "code": "CRYPTOPIANS", + "issuer": "rR7zH1VECwtBWapGwrKWWwYTrjohyXRid", + "trustlines": 727, + "placeInTop": null + }, + { + "id": 17386, + "code": "HNT", + "issuer": "raP6XZypcFR1WkDzaKjv91FtYRCURvePWW", + "title": "InGameCredit", + "trustlines": 165, + "placeInTop": null + }, + { + "id": 17397, + "code": "USD", + "issuer": "rMTqE8ExnkRDuAVrrD7QJubz6JUmkr1P47", + "trustlines": 180, + "placeInTop": null + }, + { + "id": 17399, + "code": "KUR", + "issuer": "rG5tu1u5CZMMho6gXPivwe37qxd6H8r5gm", + "trustlines": 195, + "placeInTop": null + }, + { + "id": 17420, + "code": "GENXRPVNKS", + "issuer": "rawUvd4DMGrqnB1vfrMF9RFQ79m3b8tCDz", + "trustlines": 163, + "placeInTop": null + }, + { + "id": 17424, + "code": "VIIIIXDIAMONDHANDS", + "issuer": "r3LMqrZrBmzruZwz6CVJWkKZVo1u3nF9xK", + "trustlines": 339, + "placeInTop": null + }, + { + "id": 17437, + "code": "PDT", + "issuer": "rhd96ShDBo73iNTKb4Q57T9RUwryvM7oFB", + "title": "Physical Digital", + "trustlines": 1998, + "placeInTop": null + }, + { + "id": 17438, + "code": "ALI", + "issuer": "rppZmZ1iyXZicAqesDjsxP8rSg29H78auh", + "trustlines": 156, + "placeInTop": null + }, + { + "id": 17440, + "code": "Airborne", + "issuer": "rfYxu5QSjvhV3ZF1xokR9ka6dhoBhCCuwf", + "trustlines": 143, + "placeInTop": null + }, + { + "id": 17450, + "code": "GNT", + "issuer": "rfPUTMdYiWTMzfNaHwJNtTyZLAM4S65emU", + "trustlines": 153, + "placeInTop": null + }, + { + "id": 17469, + "code": "ABC", + "issuer": "r3dudPWiCWiT7rnwocRMSS1LWftzvzLFgN", + "trustlines": 131, + "placeInTop": null + }, + { + "id": 17589, + "code": "HKD", + "issuer": "rPT74sUcTBTQhkHVD54WGncoqXEAMYbmH7", + "title": "RippleQK", + "trustlines": 2612, + "placeInTop": null + }, + { + "id": 17630, + "code": "Loviocoin", + "issuer": "rDQgnkSVndqgWHW2ETERfcWKpLJyxCua9X", + "trustlines": 164, + "placeInTop": null + }, + { + "id": 17912, + "code": "AmericaFirstCoin", + "issuer": "rL2R4f9wJY1aaKZncrW7wiDdqncze9N22w", + "trustlines": 758, + "placeInTop": null + }, + { + "id": 17915, + "code": "Xvex", + "issuer": "r3f7jVpnLa7YrQw5yPfMnjjAcUtAbeL4xU", + "trustlines": 876, + "placeInTop": null + }, + { + "id": 17917, + "code": "NPK", + "issuer": "rV64miFA53xbWS3x9A6nRnzxMqLHN1t2h", + "title": "NATIONAL PRESTO INDUSTRIES INCs", + "trustlines": 1508, + "placeInTop": null + }, + { + "id": 17958, + "code": "BET", + "issuer": "rUeKohnBUioHMPV3Xptem3Sfi6XFjXWCHx", + "trustlines": 291, + "placeInTop": null + }, + { + "id": 17965, + "code": "GLF", + "issuer": "rLcj6P5tWAxQo7hqKtvqH7BCh6BpSu4fGj", + "trustlines": 423, + "placeInTop": null + }, + { + "id": 17971, + "code": "MonedaX", + "issuer": "rsLx8UkM9rC5aPF9xYY53TJrUbXHBLBeoq", + "trustlines": 952, + "placeInTop": null + }, + { + "id": 17979, + "code": "Nolacoinz", + "issuer": "raoYTMEoNJuL4MNDAN8Gf9C1W6wXQgvvNq", + "trustlines": 736, + "placeInTop": null + }, + { + "id": 17998, + "code": "XFLEX", + "issuer": "rwMYX4MC2PRffAxa7opuGCS899kZNYcwQV", + "trustlines": 319, + "placeInTop": null + }, + { + "id": 18003, + "code": "xWolfpack", + "issuer": "rpizJeQexuFTEbKP6fHSAVyHLBS9gNQ7H2", + "title": "xWolves Pack", + "trustlines": 648, + "placeInTop": null + }, + { + "id": 18006, + "code": "TBone", + "issuer": "rHMfdnZ65NsYpih5EmLSUTkD2tKVjE8Kne", + "trustlines": 240, + "placeInTop": null + }, + { + "id": 18062, + "code": "XrHero", + "issuer": "rwy4a3sbk9myeE1yKjghLKWceP33TRkVEg", + "title": "XrHero", + "trustlines": 1757, + "placeInTop": null + }, + { + "id": 18064, + "code": "KAWAII", + "issuer": "rKAWAaScBH7S865y1sw8ME78prx8T9jRxd", + "trustlines": 191, + "placeInTop": null + }, + { + "id": 18069, + "code": "XTLM", + "issuer": "r9TEnt2kANJGjVaGQ16iQXQ6DkUD6vWeUJ", + "trustlines": 487, + "placeInTop": null + }, + { + "id": 18087, + "code": "Coincoction", + "issuer": "rNZ4MP4mjFefyDEg6riBv6dwZqnB8RHsqh", + "trustlines": 232, + "placeInTop": null + }, + { + "id": 18094, + "code": "LedgerPunks", + "issuer": "rLpunkscgfzS8so59bUCJBVqZ3eHZue64r", + "title": "Ledger Punks", + "trustlines": 1926, + "placeInTop": null + }, + { + "id": 18112, + "code": "OMUA", + "issuer": "rfxCJNw1U4QGxChPN26jSyQA1pCzWBXgHG", + "trustlines": 364, + "placeInTop": null + }, + { + "id": 18124, + "code": "REMetaNFT", + "issuer": "r3iijjcY2qFoSWX1XerumKTkA6VYDhKSmF", + "trustlines": 203, + "placeInTop": null + }, + { + "id": 18131, + "code": "ENV", + "issuer": "rKpu9NjEmwk5USt1A2FBDoVQGajeqgM8na", + "title": "Project ENV", + "trustlines": 5364, + "placeInTop": null + }, + { + "id": 18140, + "code": "BYO", + "issuer": "rhrJEWRUmbUj4vtrCyrXzRRLLiNL5N3Jcg", + "trustlines": 419, + "placeInTop": null + }, + { + "id": 18155, + "code": "VISION", + "issuer": "rJHDa7TbSdfEZBht5JiauCBUCeFmAGREsL", + "title": "VISION", + "trustlines": 233, + "placeInTop": null + }, + { + "id": 18167, + "code": "JEONG", + "issuer": "rL2aPkRMabXiZ9kyhu9hJG6JvqnvLiooCM", + "title": "JEONGx", + "trustlines": 506, + "placeInTop": null + }, + { + "id": 18174, + "code": "MONSTERS", + "issuer": "rUhkwGEEZDSXxvUWDtSChcbNa83m7tUeP7", + "title": "MONSTERS", + "trustlines": 366, + "placeInTop": null + }, + { + "id": 18180, + "code": "BEAST", + "issuer": "r4S7yMBM4gr172BqQbwLwg9yCPeuke5nxt", + "title": "LIQUIDBEAST", + "trustlines": 186, + "placeInTop": null + }, + { + "id": 18194, + "code": "METAFURY", + "issuer": "rwTHewW7HoFdWPwSrV8gqEbQ8SSaUcdU9x", + "trustlines": 466, + "placeInTop": null + }, + { + "id": 18197, + "code": "XRPortals", + "issuer": "rpok532CPqiHzfz38Bg1rE3j5UURaRUMbE", + "title": "XRPortals", + "trustlines": 2019, + "placeInTop": null + }, + { + "id": 18198, + "code": "JeepLifeCoin", + "issuer": "r9aZ1iWLPK8KX9HnNpwnXCVqfumPnyrd8f", + "trustlines": 408, + "placeInTop": null + }, + { + "id": 18204, + "code": "RZ1", + "issuer": "rsg27AT1bfzuZnpRdk9xjJqUvhHsGDFBQm", + "trustlines": 204, + "placeInTop": null + }, + { + "id": 18222, + "code": "XLegendz", + "issuer": "rrUJjso8ZouDQ9gwE1BhaAcL7kfzDxukF", + "trustlines": 267, + "placeInTop": null + }, + { + "id": 18229, + "code": "REALX", + "issuer": "rsuK9Qk7T21Mp2STr3VV2kCwMqydS4ARXU", + "trustlines": 342, + "placeInTop": null + }, + { + "id": 18242, + "code": "KRYPTONITE", + "issuer": "rHJRMuxGiEBAxfwwwpuhSx8FLXqdZmpmQ2", + "title": "KRYPTONITE", + "trustlines": 202, + "placeInTop": null + }, + { + "id": 18243, + "code": "XPAND", + "issuer": "rMHoU2HGVuobGb9EiW7XZrcyXmKTPqYqG8", + "trustlines": 545, + "placeInTop": null + }, + { + "id": 18244, + "code": "Xfight", + "issuer": "rnffCSePCGuGhFA7wHTHHQLGv356ktTTbs", + "trustlines": 251, + "placeInTop": null + }, + { + "id": 18265, + "code": "Holoatomos", + "issuer": "rhoLoAtom8J9hrGFWdkm7PrGRB5qv9D8SN", + "trustlines": 179, + "placeInTop": null + }, + { + "id": 18285, + "code": "ShivaX", + "issuer": "rE1RjM1nthauTbbYurioK4BrSViECHyDdG", + "title": "ShivaX", + "trustlines": 612, + "placeInTop": null + }, + { + "id": 18287, + "code": "WHALE", + "issuer": "rsArLYPERuJmpN3Nc64K3hQgQdPw1ftHRc", + "title": "Whalealert", + "trustlines": 126, + "placeInTop": null + }, + { + "id": 18289, + "code": "Playcoin", + "issuer": "rPLAYcoiNxikbojBES2k48WvpzNCy6DdvL", + "trustlines": 158, + "placeInTop": null + }, + { + "id": 18290, + "code": "XCO", + "issuer": "raHTCKfgrtvSZthnUAVctDj87McDAmKkY2", + "title": "TheOfficialCryptoOpinionsXRPL", + "trustlines": 973, + "placeInTop": null + }, + { + "id": 18319, + "code": "LTRY", + "issuer": "rnGvMu8P6evJEYY4cPyzcy4N1m5gcYRjaH", + "title": "Limited USD (LUSD)", + "trustlines": 304, + "placeInTop": null + }, + { + "id": 18324, + "code": "LAUD", + "issuer": "rnGvMu8P6evJEYY4cPyzcy4N1m5gcYRjaH", + "title": "Limited USD (LUSD)", + "trustlines": 222, + "placeInTop": null + }, + { + "id": 18328, + "code": "LNGN", + "issuer": "rnGvMu8P6evJEYY4cPyzcy4N1m5gcYRjaH", + "title": "Limited USD (LUSD)", + "trustlines": 196, + "placeInTop": null + }, + { + "id": 18329, + "code": "Shinsekai", + "issuer": "rftChNukekxjRqXhKXEie3ArMUXvGvuS1R", + "trustlines": 359, + "placeInTop": null + }, + { + "id": 18354, + "code": "XMART", + "issuer": "r3wfBuKopdM37gsHvCwhJBDaw4avnxTJCV", + "title": "Xmart", + "trustlines": 948, + "placeInTop": null + }, + { + "id": 18376, + "code": "BRIX", + "issuer": "rUi3o9XGQqVrXQtQftGx5CrJsbQ4ezu2PP", + "trustlines": 261, + "placeInTop": null + }, + { + "id": 18379, + "code": "NutritionalPoints", + "issuer": "rBtqm3b3wHoA2De5JGCHrvZoZfo5ZaWQvz", + "trustlines": 168, + "placeInTop": null + }, + { + "id": 18386, + "code": "XAF", + "issuer": "rBZ6uZVjvjYQSdMcXVjkDTYExYLz3g2JGZ", + "trustlines": 132, + "placeInTop": null + }, + { + "id": 18387, + "code": "VREP", + "issuer": "rEQ3rAEUerdR1wvsdM3ZiLchsWrFqrD3mp", + "trustlines": 174, + "placeInTop": null + }, + { + "id": 18388, + "code": "VERDICT", + "issuer": "rDSq68YvnMhGqcPdGEkwvfACidcgVb729b", + "trustlines": 167, + "placeInTop": null + }, + { + "id": 18404, + "code": "N8token", + "issuer": "rDPsTswPnub3WKgB2Gk3YVF4Enb3YKSSNK", + "trustlines": 161, + "placeInTop": null + }, + { + "id": 18409, + "code": "EKO", + "issuer": "rELGFk3TqoPZpFSn7jX8mjhryX7ghB36Nn", + "trustlines": 110, + "placeInTop": null + }, + { + "id": 18410, + "code": "ECO", + "issuer": "rMeLaNib2qQzALSCKbRMPYid9VerBeQf93", + "title": "Eyes Charity", + "trustlines": 1740, + "placeInTop": null + }, + { + "id": 18412, + "code": "SMC", + "issuer": "rMaZAY3Wvi2gvKWrK8sMFRKzMwqC6jvmJU", + "title": "Smart casino 77", + "trustlines": 1345, + "placeInTop": null + }, + { + "id": 18426, + "code": "CLC", + "issuer": "rBLrMbqmMq9zD8X5LF1veDYEFuDXco8wLZ", + "trustlines": 168, + "placeInTop": null + }, + { + "id": 18435, + "code": "HackleToken", + "issuer": "r7VbtrZGPa1MVwNSascBqYRDxSWWb4TkX", + "trustlines": 150, + "placeInTop": null + }, + { + "id": 18436, + "code": "SQUIRT", + "issuer": "r3rXHvHwxzG9kEmZPpxJWTSS9gX9Ph6zqz", + "title": "Squirt NFT", + "trustlines": 294, + "placeInTop": null + }, + { + "id": 18440, + "code": "Hog", + "issuer": "rwM9XzFHdCxnpNFjanc4Sd3N96cz8ip5pQ", + "title": "HOG X", + "trustlines": 4618, + "placeInTop": null + }, + { + "id": 18442, + "code": "CANNA", + "issuer": "rs7xQ3XUadLvsqE441qDRkmKVVc2Uk6dJ6", + "title": "CANNA", + "trustlines": 139, + "placeInTop": null + }, + { + "id": 18443, + "code": "THCC", + "issuer": "rKJ7N8BJ7QboaoR5Esdp87xjcdJyQ5gFmD", + "trustlines": 198, + "placeInTop": null + }, + { + "id": 18444, + "code": "LCC", + "issuer": "rhFGZnmDBFJ3zdFKnUcpJhXUZzRP2qdEWd", + "trustlines": 1783, + "placeInTop": null + }, + { + "id": 18461, + "code": "Zarm", + "issuer": "raRpmZorhdF7okc8VGSBL29MgJKZmhB6pt", + "trustlines": 171, + "placeInTop": null + }, + { + "id": 18462, + "code": "MNFTC", + "issuer": "rwJZA6eZDxPtgzhG2BCPYe7hdDEDH5wXKc", + "title": "NFT sport cards XRP", + "trustlines": 1417, + "placeInTop": null + }, + { + "id": 18463, + "code": "GRT", + "issuer": "rEYYEdggF5yuNRMrVfCYSVjxYYhyA4NJLs", + "trustlines": 153, + "placeInTop": null + }, + { + "id": 18466, + "code": "PureX", + "issuer": "rD4xUGE8KJG78erSEZrAERT1LPLdHn4UUF", + "trustlines": 124, + "placeInTop": null + }, + { + "id": 18473, + "code": "DogeCh", + "issuer": "r4QVHaB8xz626d6uXm7BNdnoqyYHL82mJ2", + "title": "Doge Chief", + "trustlines": 742, + "placeInTop": null + }, + { + "id": 18482, + "code": "XRPBOTS", + "issuer": "rBRUZL91cJdnDwLHrQvutfHcJqNo1mtuQk", + "trustlines": 193, + "placeInTop": null + }, + { + "id": 18495, + "code": "Bolt", + "issuer": "rEWW6c7dqdr2sbAj9YMkZedoxeADdYTLry", + "trustlines": 119, + "placeInTop": null + }, + { + "id": 18500, + "code": "XBOT", + "issuer": "rfQ2G4gjbR2zAtq6xPppwJsAdsEX8Pc3Rd", + "trustlines": 244, + "placeInTop": null + }, + { + "id": 18502, + "code": "SIPS", + "issuer": "rUJxe8tyLgz6yLXLG8hggUqEnhPG3rtZzF", + "trustlines": 125, + "placeInTop": null + }, + { + "id": 18508, + "code": "CGT", + "issuer": "rp4KDV51A5dW6aySXgQkRUKnHVjFF2PQwr", + "title": "PwntNub", + "trustlines": 175, + "placeInTop": null + }, + { + "id": 18514, + "code": "xRATIONS", + "issuer": "rPArqPnUr39t8uui6THzj7VZSbDXgTNEVp", + "trustlines": 148, + "placeInTop": null + }, + { + "id": 18515, + "code": "xSOLDIERZ", + "issuer": "rwZXCQryUWczJPHrQzx5paK24yRC3J27HA", + "trustlines": 577, + "placeInTop": null + }, + { + "id": 18530, + "code": "CryptoLand1", + "issuer": "rPUTfxRRQx6bA1JVPDyjVyo4p1QvwTBiAi", + "trustlines": 187, + "placeInTop": null + }, + { + "id": 18531, + "code": "Animal", + "issuer": "r4VgKR5eeiERTrWP7wJ1QWXAJkFtCkbZa8", + "title": "Animal XRPL", + "trustlines": 612, + "placeInTop": null + }, + { + "id": 18557, + "code": "XRPACK", + "issuer": "rnzddNSJjunBR6D1hCK4pXb5nHAc6g7v2q", + "trustlines": 235, + "placeInTop": null + }, + { + "id": 18565, + "code": "UACoin", + "issuer": "rGwLmsvsDw7Q24cykGg4GjiX2fEorL9RBf", + "title": "UACoin", + "trustlines": 862, + "placeInTop": null + }, + { + "id": 18647, + "code": "Xsnowman", + "issuer": "rMFUMfjPp9tpBCCbNiYQouF8rL7Se7DTcA", + "trustlines": 694, + "placeInTop": null + }, + { + "id": 18674, + "code": "EBC", + "issuer": "rPwTbNH5P7u7yKiJcCCCaMqaBc5K9B3VQ1", + "trustlines": 120, + "placeInTop": null + }, + { + "id": 18677, + "code": "EBCGLD", + "issuer": "rUpMe5mhxjRkcGMDoH1gCx5ZNGaupiouTP", + "trustlines": 168, + "placeInTop": null + }, + { + "id": 18689, + "code": "FHS", + "issuer": "rNjTh2qW9YT4TdjrwRWYg9qvFBn1PxfZbR", + "trustlines": 1335, + "placeInTop": null + }, + { + "id": 18739, + "code": "xRStake", + "issuer": "r33VJfqaEJScqTEfzgcyRyMezU3kbeqkPF", + "trustlines": 161, + "placeInTop": null + }, + { + "id": 18746, + "code": "ECMM", + "issuer": "rUgQc7xDJJXKhgNW2UjtPkmS2bJro61Fw6", + "trustlines": 117, + "placeInTop": null + }, + { + "id": 18779, + "code": "xMF", + "issuer": "rU4RTVw3ZnqfgAeZtgLPb8prMEdX7VKFmw", + "trustlines": 393, + "placeInTop": null + }, + { + "id": 18812, + "code": "SBT", + "issuer": "rhdHkYbFfB4CoXmStFGmue9G86U5JvPUyS", + "trustlines": 105, + "placeInTop": null + }, + { + "id": 18813, + "code": "xKai", + "issuer": "rDuyXNdzmuPRJd1PoscMDFosEAGccV3Utf", + "trustlines": 549, + "placeInTop": null + }, + { + "id": 18831, + "code": "PCT", + "issuer": "rUbmmkH6VV4ZuWMNynCasKRKViZDP94VDD", + "trustlines": 117, + "placeInTop": null + }, + { + "id": 18884, + "code": "CSE", + "issuer": "rURjz2DgcnZnJitnrZTWp3BDP2VSUcnoCm", + "title": "CSE", + "trustlines": 1465, + "placeInTop": null + }, + { + "id": 18892, + "code": "SAPLING", + "issuer": "rDh9fTkJRCDn6fwDYfogcTsbLmn24hoxMr", + "trustlines": 107, + "placeInTop": null + }, + { + "id": 18899, + "code": "RUN", + "issuer": "rBAtmcnMpVc9tRwzEZgEoZ4wCJCHphSZQ3", + "title": "V-Runners", + "trustlines": 895, + "placeInTop": null + }, + { + "id": 18929, + "code": "UNI", + "issuer": "rw7L8CVYMYD7bFSRCUYTtaaLdneGzi7o9i", + "trustlines": 116, + "placeInTop": null + }, + { + "id": 18940, + "code": "LCT", + "issuer": "r3FSvMsMnMAXXJ9KwN3p6rNrTnKQGDaSiE", + "trustlines": 488, + "placeInTop": null + }, + { + "id": 18966, + "code": "TG$", + "issuer": "rsYKuosdXNfL2J93vaRasddqWVbKHkFzWq", + "trustlines": 1596, + "placeInTop": null + }, + { + "id": 18967, + "code": "MOSHI", + "issuer": "rDgk9RorPEsJLcuGwMBeo3NTQP4AmkGR3j", + "trustlines": 141, + "placeInTop": null + }, + { + "id": 18986, + "code": "INUPOX", + "issuer": "rpRStNPrA8Gm47v1HpD8wdePXb1EFhmTrv", + "trustlines": 127, + "placeInTop": null + }, + { + "id": 18993, + "code": "XNS", + "issuer": "rKbJX2GNtz2j14ESjWzwWj3QPC2oinyjff", + "trustlines": 103, + "placeInTop": null + }, + { + "id": 19020, + "code": "CROWN", + "issuer": "rNcqizvdrT1YRF19eLGUHQUyejNzkJKMBh", + "trustlines": 115, + "placeInTop": null + }, + { + "id": 19035, + "code": "666", + "issuer": "rJefvWQpP2tXVbND6xQRDg4fJNiMDsaoWH", + "trustlines": 107, + "placeInTop": null + }, + { + "id": 19037, + "code": "EVC", + "issuer": "rwz3y9C2q9XQmJDmBqjRU1Fn2xdkR7o59H", + "trustlines": 115, + "placeInTop": null + }, + { + "id": 19082, + "code": "CAD", + "issuer": "rL7CF4YGNBRk6a4U6f851yQDSddJJopu6v", + "trustlines": 151, + "placeInTop": null + }, + { + "id": 19088, + "code": "XKZ", + "issuer": "rDLFMcRrBJkEcRuXBSbWKYDtHum3EqDBGD", + "trustlines": 123, + "placeInTop": null + }, + { + "id": 19102, + "code": "xNVL", + "issuer": "rUKq3udJjjqfnirVCyCrTmK3kK21rfuChn", + "trustlines": 1154, + "placeInTop": null + }, + { + "id": 19114, + "code": "DAK", + "issuer": "rGTudhV2JHUegPmaozAR5F4US6o3skNxe8", + "title": "ONLINE CASINO SINGAPORE", + "trustlines": 1614, + "placeInTop": null + }, + { + "id": 19135, + "code": "SOUND", + "issuer": "rPazDXf3XHGqftSUKa7tStN33VWNHp6Nns", + "trustlines": 16530, + "placeInTop": null + }, + { + "id": 19139, + "code": "CHUB", + "issuer": "rU3DQ71saRwTuknZimDH1uJW7YFS1wocUY", + "trustlines": 4185, + "placeInTop": null + }, + { + "id": 48, + "code": "DIX", + "issuer": "rEiAdjhb552sX6q1tAZ2jHE5hQRMiCTGfy", + "title": "DIX", + "trustlines": 2578, + "placeInTop": null + }, + { + "id": 242, + "code": "IQC", + "issuer": "rGieogBAoXZGq6acVCs9xbMMZaARtGqyyK", + "title": "IQ_Network", + "trustlines": 1077, + "placeInTop": null + }, + { + "id": 17274, + "code": "GZX", + "issuer": "rPK6DvvoF8CVHGURSGNccCxKDXMnRAchHD", + "trustlines": 443, + "placeInTop": null + } +] diff --git a/src/templates/lists/xrpl_tokens_devnet.json b/src/templates/lists/xrpl_tokens_devnet.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/src/templates/lists/xrpl_tokens_devnet.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/templates/lists/xrpl_tokens_testnet.json b/src/templates/lists/xrpl_tokens_testnet.json new file mode 100644 index 0000000000..20eda9535b --- /dev/null +++ b/src/templates/lists/xrpl_tokens_testnet.json @@ -0,0 +1,34 @@ +[ + { + "id": 0, + "code": "XRP", + "issuer": "", + "title": "XRP", + "trustlines": -1, + "placeInTop": 0 + }, + { + "id": 1, + "code": "VND", + "issuer": "rh8LssQyeBdEXk7Zv86HxHrx8k2R2DBUrx", + "title": "Vietnam Dong", + "trustlines": 999, + "placeInTop": 1 + }, + { + "id": 2, + "code": "USD", + "issuer": "rh8LssQyeBdEXk7Zv86HxHrx8k2R2DBUrx", + "title": "United States Dollar", + "trustlines": 999, + "placeInTop": 1 + }, + { + "id": 3, + "code": "SOLO", + "issuer": "rHZwvHEs56GCmHupwjA4RY7oPA3EoAJWuN", + "title": "Sologenic", + "trustlines": 999, + "placeInTop": 1 + } +] diff --git a/src/templates/root.yml b/src/templates/root.yml index 2dc4d913c5..fba009cfd5 100644 --- a/src/templates/root.yml +++ b/src/templates/root.yml @@ -108,6 +108,10 @@ configurations: configurationPath: plenty.yml schemaPath: plenty-schema.json + $namespace xrpl: + configurationPath: xrpl.yml + schemaPath: xrpl-schema.json + $namespace curve: configurationPath: curve.yml schemaPath: cronos-connector-schema.json diff --git a/src/templates/xrpl.yml b/src/templates/xrpl.yml new file mode 100644 index 0000000000..f689206695 --- /dev/null +++ b/src/templates/xrpl.yml @@ -0,0 +1,39 @@ +networks: + mainnet: + nodeURL: wss://xrplcluster.com/ + tokenListType: "FILE" + tokenListSource: "/home/gateway/conf/lists/xrpl_tokens.json" + marketListType: "FILE" + marketListSource: "/home/gateway/conf/lists/xrpl_markets.json" + nativeCurrencySymbol: "XRP" + testnet: + nodeURL: wss://s.altnet.rippletest.net:51233/ + tokenListType: "FILE" + tokenListSource: "/home/gateway/conf/lists/xrpl_tokens_testnet.json" + marketListType: "FILE" + marketListSource: "/home/gateway/conf/lists/xrpl_markets_testnet.json" + nativeCurrencySymbol: "XRP" + devnet: + nodeURL: wss://s.devnet.rippletest.net:51233/ + tokenListType: "FILE" + tokenListSource: "/home/gateway/conf/lists/xrpl_tokens_devnet.json" + marketListType: "FILE" + marketListSource: "/home/gateway/conf/lists/xrpl_markets_devnet.json" + nativeCurrencySymbol: "XRP" +network: "xrpl" +requestTimeout: 2000 +connectionTimeout: 2000 +feeCushion: 1.2 +maxFeeXRP: "2" +orderDbPath: "db/xrpl.level" +maxLRUCacheInstances: 10 +retry: + all: + maxNumberOfRetries: 3 # 0 means no retries + delayBetweenRetries: 1 # in milliseconds, 0 means no delay +timeout: + all: 0 # in milliseconds, 0 means no timeout. +parallel: + all: + batchSize: 1 # 0 means no batching, group all + delayBetweenBatches: 1 # in milliseconds, 0 means no delay diff --git a/test/chains/xrpl/xrpl.routes.test.ts b/test/chains/xrpl/xrpl.routes.test.ts new file mode 100644 index 0000000000..2dc46cce09 --- /dev/null +++ b/test/chains/xrpl/xrpl.routes.test.ts @@ -0,0 +1,116 @@ +import request from 'supertest'; +import { XRPL } from '../../../src/chains/xrpl/xrpl'; +import { patch, unpatch } from '../../services/patch'; +import { gatewayApp } from '../../../src/app'; +import { Wallet } from 'xrpl'; + +let xrplChain: XRPL; + +const wallet1 = Wallet.fromSecret('sEd74fJ432TFE4f5Sy48gLyzknkdc1t'); // r9wmQfStbNfPJ2XqAN7KH4iP8NJKmqPe16 +const wallet2 = Wallet.fromSecret('sEd7oiMn5napJBthB2z4CtN5nVi56Bd'); // r3z4R6KQWfwRf9G15AhUZe2GN67Sj6PYNV + +const patchWallet = () => { + patch(xrplChain, 'getWallet', (walletAddress: string) => { + if (walletAddress === 'r9wmQfStbNfPJ2XqAN7KH4iP8NJKmqPe16') return wallet1; + + return wallet2; + }); +}; + +const patchDatabase = () => { + patch(xrplChain, '_orderStorage', { + declareOwnership: () => { + return; + }, + init: () => { + return; + }, + close: () => { + return; + }, + }); +}; + +beforeAll(async () => { + xrplChain = XRPL.getInstance('testnet'); + patchDatabase(); + await xrplChain.init(); +}); + +afterAll(async () => { + unpatch(); + await xrplChain.close(); +}); + +describe('POST /chain/balances', () => { + it('should return 200 with correct parameters', async () => { + patchWallet(); + await request(gatewayApp) + .post(`/chain/balances`) + .send({ + chain: 'xrpl', + network: 'testnet', + address: 'r3z4R6KQWfwRf9G15AhUZe2GN67Sj6PYNV', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(res.body).toBeDefined(); + }); + }); + + it('should return 404 when parameters are invalid/incomplete', async () => { + unpatch(); + await request(gatewayApp) + .post(`/chain/balances`) + .send({ + chain: 'xrpl', + network: 'testnet', + }) + .expect(404); + }); +}); + +describe('POST /chain/poll', () => { + it('should return 200 with correct parameters', async () => { + const res = await request(gatewayApp).post('/chain/poll').send({ + chain: 'xrpl', + network: 'testnet', + txHash: + 'A4A9E7C76ACA5527AC09A7540F263CA48FF40F5CFE04DD19B7173B05E3685077', // noqa: mock + }); + expect(res.statusCode).toEqual(200); + }); + + it('should get unknown error with invalid txHash', async () => { + const res = await request(gatewayApp).post('/chain/poll').send({ + chain: 'xrpl', + network: 'testnet', + txHash: 123, + }); + expect(res.statusCode).toEqual(404); + }); +}); + +describe('GET /chain/tokens', () => { + it('should return 200 with correct parameters', async () => { + const res = await request(gatewayApp) + .get('/chain/tokens') + .query({ + chain: 'xrpl', + network: 'testnet', + tokenSymbols: ['XRP', 'SOLO'], + }); + expect(res.statusCode).toEqual(200); + }); + + it('should get unknown error with invalid tokenSymbols', async () => { + const res = await request(gatewayApp).get('/chain/tokens').query({ + chain: 'xrpl', + network: 'testnet', + tokenSymbols: 123, + }); + expect(res.statusCode).toEqual(404); + }); +}); diff --git a/test/chains/xrpl/xrpl.validator.test.ts b/test/chains/xrpl/xrpl.validator.test.ts new file mode 100644 index 0000000000..553c676176 --- /dev/null +++ b/test/chains/xrpl/xrpl.validator.test.ts @@ -0,0 +1,143 @@ +import { + validateXRPLAddress, + validateXRPLBalanceRequest, + validateXRPLPollRequest, + validateXRPLGetTokenRequest, + invalidXRPLAddressError, +} from '../../../src/chains/xrpl/xrpl.validators'; +import { HttpException } from '../../../src/services/error-handler'; + +import { + invalidTxHashError, + invalidTokenSymbolsError, +} from '../../../src/services/validators'; + +import { missingParameter } from '../../../src/services/validators'; + +import 'jest-extended'; + +describe('validateXRPLPollRequest', () => { + it('valid when req.txHash is a txHash', () => { + expect( + validateXRPLPollRequest({ + txHash: + '92EE240C1C31E50AAA7E3C00A6280A4BE52E65B5A8A4C1B4A6FEF9E170B14D0F', // noqa: mock + }) + ).toEqual(undefined); + }); + + it('return error when req.txHash does not exist', () => { + try { + validateXRPLPollRequest({ + hello: 'world', + }); + } catch (error) { + expect((error as HttpException).message).toEqual( + missingParameter('txHash') + ); + } + }); + + it('return error when req.txHash is invalid', () => { + try { + validateXRPLPollRequest({ + txHash: 123, + }); + } catch (error) { + expect((error as HttpException).message).toEqual(invalidTxHashError); + } + }); +}); + +describe('validateAddress', () => { + it('valid when req.address is a address', () => { + expect( + validateXRPLAddress({ + address: 'r9wmQfStbNfPJ2XqAN7KH4iP8NJKmqPe16', + }) + ).toEqual([]); + }); + + it('return error when req.address does not exist', () => { + expect( + validateXRPLAddress({ + hello: 'world', + }) + ).toEqual([missingParameter('address')]); + }); + + it('return error when req.address is invalid', () => { + expect( + validateXRPLAddress({ + address: 123, + }) + ).toEqual([invalidXRPLAddressError]); + }); +}); + +describe('validateXRPLBalanceRequest', () => { + it('valid when req.token is a token and address is a valid address', () => { + expect( + validateXRPLBalanceRequest({ + address: 'r9wmQfStbNfPJ2XqAN7KH4iP8NJKmqPe16', + }) + ).toEqual(undefined); + }); + + it('return error when req.address is invalid', () => { + try { + validateXRPLBalanceRequest({ + address: 123, + }); + } catch (error) { + expect((error as HttpException).message).toEqual(invalidXRPLAddressError); + } + }); +}); + +describe('validateXRPLGetTokenRequest', () => { + it('valid when req.tokenSymbols is a token and address is a valid address', () => { + expect( + validateXRPLGetTokenRequest({ + address: 'r9wmQfStbNfPJ2XqAN7KH4iP8NJKmqPe16', + tokenSymbols: ['XRP'], + }) + ).toEqual(undefined); + }); + + it('return error when req.tokenSymbols and req.address does not exist', () => { + try { + validateXRPLGetTokenRequest({ + hello: 'world', + }); + } catch (error) { + expect((error as HttpException).message).toEqual( + missingParameter('tokenSymbols') + ); + } + }); + + it('return error when req.tokenSymbols is invalid', () => { + try { + validateXRPLGetTokenRequest({ + address: 'r9wmQfStbNfPJ2XqAN7KH4iP8NJKmqPe16', + tokenSymbols: 123, + }); + } catch (error) { + expect((error as HttpException).message).toEqual( + invalidTokenSymbolsError + ); + } + }); + + it('return error when req.address is invalid', () => { + try { + validateXRPLGetTokenRequest({ + address: 123, + tokenSymbols: ['XRP'], + }); + } catch (error) { + expect((error as HttpException).message).toEqual(invalidXRPLAddressError); + } + }); +}); diff --git a/test/connectors/xrpl/xrpl.e2e.test.ts b/test/connectors/xrpl/xrpl.e2e.test.ts new file mode 100644 index 0000000000..60d87dc21d --- /dev/null +++ b/test/connectors/xrpl/xrpl.e2e.test.ts @@ -0,0 +1,536 @@ +import request from 'supertest'; +import { gatewayApp } from '../../../src/app'; +import { Wallet } from 'xrpl'; +import { XRPL } from '../../../src/chains/xrpl/xrpl'; +import { XRPLCLOB } from '../../../src/connectors/xrpl/xrpl'; +import { getsSequenceNumberFromTxn } from '../../../src/connectors/xrpl/xrpl.utils'; +import { patch, unpatch } from '../../services/patch'; +import { Order } from '../../../src/connectors/xrpl/xrpl.types'; + +let xrpl: XRPL; +let xrplCLOB: XRPLCLOB; +const wallet1 = Wallet.fromSecret('sEd74fJ432TFE4f5Sy48gLyzknkdc1t'); // r9wmQfStbNfPJ2XqAN7KH4iP8NJKmqPe16 +const wallet2 = Wallet.fromSecret('sEd7oiMn5napJBthB2z4CtN5nVi56Bd'); // r3z4R6KQWfwRf9G15AhUZe2GN67Sj6PYNV +const MARKET = 'USD-VND'; +let postedOrderTxn: string; + +const INVALID_REQUEST = { + chain: 'unknown', + network: 'testnet', +}; + +const patchWalletXRPL = () => { + patch(xrpl, 'getWallet', (walletAddress: string) => { + if (walletAddress === 'r9wmQfStbNfPJ2XqAN7KH4iP8NJKmqPe16') return wallet1; + + return wallet2; + }); +}; + +beforeAll(async () => { + xrpl = XRPL.getInstance('testnet'); + xrplCLOB = XRPLCLOB.getInstance('xrpl', 'testnet'); + patchWalletXRPL(); + await xrpl.init(); + await xrplCLOB.init(); + + // wait for 1 second to make sure the database is ready + await new Promise((resolve) => setTimeout(resolve, 1000)); +}); + +beforeEach(() => { + patchWalletXRPL(); +}); + +afterAll(async () => { + await xrpl.close(); +}); + +// 1st Scenario: +// 1. Get estimated gas price +// 2. Get markets list +// 3. Get ticker info +// 4. Get orderbook +// 5. Post an order +// 6. Get posted order details +// 7. Cancel the posted order + +describe('Get estimated gas price', () => { + it('should return 200 with proper request', async () => { + await request(gatewayApp) + .get(`/clob/estimateGas`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => expect(res.body.gasPrice).toBeDefined()); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .get(`/clob/estimateGas`) + .query(INVALID_REQUEST) + .expect(404); + }); +}); + +describe('Get Markets List', () => { + it('should return a list of markets', async () => { + await request(gatewayApp) + .get(`/clob/markets`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(res.body.markets.length).toBeGreaterThan(0); + }); + }); +}); + +describe(`Get ticker info for ${MARKET}`, () => { + it('should return 200 with proper request', async () => { + await request(gatewayApp) + .get(`/clob/ticker`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + market: MARKET, + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => expect(res.body.markets[0].baseCurrency).toEqual('USD')) + .expect((res) => + expect(res.body.markets[0].quoteCurrency).toEqual('VND') + ); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .get(`/clob/ticker`) + .query(INVALID_REQUEST) + .expect(404); + }); +}); + +describe('Post order', () => { + it('should return 200 with proper request', async () => { + await request(gatewayApp) + .post(`/clob/orders`) + .send({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: 'r9wmQfStbNfPJ2XqAN7KH4iP8NJKmqPe16', // noqa: mock + market: MARKET, + price: '20000', + amount: '0.1', + side: 'BUY', + orderType: 'LIMIT', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(res.body.txHash).toBeDefined(); + postedOrderTxn = res.body.txHash; + }); + }); + + it('should return PENDING_OPEN with proper request', async () => { + await checkOrderStatus( + postedOrderTxn, + 10, + 'PENDING_OPEN', + 500, + wallet1.address, + true + ); + }); + + it('should return OPEN with proper request', async () => { + await checkOrderStatus( + postedOrderTxn, + 9, + 'OPEN', + 1000, + wallet1.address, + true + ); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .post(`/clob/orders`) + .send(INVALID_REQUEST) + .expect(404); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .get(`/clob/orders`) + .query(INVALID_REQUEST) + .expect(404); + }); +}); + +describe('Get orderbook details', () => { + it('should return 200 with proper request with USD-VND', async () => { + await request(gatewayApp) + .get(`/clob/orderBook`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + market: MARKET, + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(res.body.buys.length).toBeGreaterThan(0); + }); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .get(`/clob/orderBook`) + .query(INVALID_REQUEST) + .expect(404); + }); +}); + +describe('Delete order', () => { + it('should return 200 with proper request', async () => { + const postedOrderSequence = await getsSequenceNumberFromTxn( + 'testnet', + postedOrderTxn + ); + + expect(postedOrderSequence).toBeDefined(); + + await request(gatewayApp) + .delete(`/clob/orders`) + .send({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: 'r9wmQfStbNfPJ2XqAN7KH4iP8NJKmqPe16', // noqa: mock + market: MARKET, + orderId: postedOrderSequence?.toString(), + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => expect(res.body.txHash).toBeDefined()); + }); + + it('should return PENDING_CANCEL with proper request', async () => { + await checkOrderStatus( + postedOrderTxn, + 10, + 'PENDING_CANCEL', + 500, + wallet1.address, + true + ); + }); + + it('should return CANCELED with proper request', async () => { + await checkOrderStatus( + postedOrderTxn, + 9, + 'CANCELED', + 1000, + wallet1.address, + true + ); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .delete(`/clob/orders`) + .send(INVALID_REQUEST) + .expect(404); + }); +}); + +// 2nd Senario: +// 1. Post an order +// 2. Get posted order details +// 3. Verify the posted order status is PENDING_OPEN +// 4. Wait for 5 seconds and then verify the posted order status is OPEN +// 5. Use 2nd wallet to create a counter order to consume the posted order partially +// 6. Verify the posted order status is PARTIALLY_FILLED +// 7. Use 2nd wallet to create a counter order to consume the posted order completely +// 8. Verify the posted order status is FILLED + +describe('Post order to be consumed', () => { + it('should return 200 with proper request', async () => { + await request(gatewayApp) + .post(`/clob/orders`) + .send({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: wallet2.address, // noqa: mock + market: MARKET, + price: '20000', + amount: '0.1', + side: 'BUY', + orderType: 'LIMIT', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(res.body.txHash).toBeDefined(); + postedOrderTxn = res.body.txHash; + }); + }); + + it('should return PENDING_OPEN with proper request', async () => { + await checkOrderStatus( + postedOrderTxn, + 9, + 'PENDING_OPEN', + 1000, + wallet2.address, + true + ); + }); + + it('should return OPEN with proper request', async () => { + await checkOrderStatus( + postedOrderTxn, + 9, + 'OPEN', + 1000, + wallet2.address, + true + ); + }); + + describe('Consume posted order', () => { + it('should return 200 with proper request', async () => { + await request(gatewayApp) + .post(`/clob/orders`) + .send({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: wallet1.classicAddress, // noqa: mock + market: MARKET, + price: '19999', + amount: '0.05', + side: 'SELL', + orderType: 'LIMIT', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(res.body.txHash).toBeDefined(); + }); + }); + + it('should return PARTIALLY_FILLED with proper request', async () => { + await checkOrderStatus( + postedOrderTxn, + 9, + 'PARTIALLY_FILLED', + 1000, + wallet2.classicAddress, + true + ); + }); + + it('should return 200 with proper request', async () => { + await request(gatewayApp) + .post(`/clob/orders`) + .send({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: wallet1.classicAddress, // noqa: mock + market: MARKET, + price: '19999', + amount: '0.051', + side: 'SELL', + orderType: 'LIMIT', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(res.body.txHash).toBeDefined(); + }); + }); + + it('should return FILLED with proper request', async () => { + await checkOrderStatus( + postedOrderTxn, + 9, + 'FILLED', + 1000, + wallet2.classicAddress, + true + ); + }); + + it('should cancel outstanding orders', async () => { + let wallet1OutstandingOrders: Order[] = []; + let wallet2OutstandingOrders: Order[] = []; + + await request(gatewayApp) + .get(`/clob/orders`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: wallet1.classicAddress, + market: MARKET, + orderId: 'all', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .then((res) => { + wallet1OutstandingOrders = res.body.orders.filter((order: Order) => { + return order.state !== 'FILLED' && order.state !== 'CANCELED'; + }); + }); + + await request(gatewayApp) + .get(`/clob/orders`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: wallet2.classicAddress, + market: MARKET, + orderId: 'all', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .then((res) => { + wallet2OutstandingOrders = res.body.orders.filter((order: Order) => { + return order.state !== 'FILLED' && order.state !== 'CANCELED'; + }); + }); + + if (wallet1OutstandingOrders.length > 0) { + wallet1OutstandingOrders.forEach(async (order) => { + await request(gatewayApp) + .delete(`/clob/orders`) + .send({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: wallet1.classicAddress, // noqa: mock + market: MARKET, + orderId: order.hash.toString(), + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => expect(res.body.txHash).toBeDefined()); + }); + } + + if (wallet2OutstandingOrders.length > 0) { + wallet2OutstandingOrders.forEach(async (order) => { + await request(gatewayApp) + .delete(`/clob/orders`) + .send({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: wallet2.classicAddress, // noqa: mock + market: MARKET, + orderId: order.hash.toString(), + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => expect(res.body.txHash).toBeDefined()); + }); + } + + await new Promise((resolve) => setTimeout(resolve, 5000)); + unpatch(); + }); + }); +}); + +async function checkOrderStatus( + postedOrderTxn: string, + maxCheckCount: number, + state: string, + requestFrequency: number = 1000, + walletAddress: string, + getAllOrdres: boolean = false +) { + const postedOrderSequence = await getsSequenceNumberFromTxn( + 'testnet', + postedOrderTxn + ); + + if (postedOrderSequence === undefined) { + throw new Error('postedOrderSequence is undefined'); + } + + let hasPassed = false; + let checkCount = 0; + let orderState = ''; + let orders: Order[] = []; + + while (!hasPassed && checkCount < maxCheckCount) { + await request(gatewayApp) + .get(`/clob/orders`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: walletAddress, + market: MARKET, + orderId: getAllOrdres ? 'all' : postedOrderSequence, + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .then((res) => { + orders = res.body.orders; + }); + + if (orders.length > 0) { + const postedOrder = orders.find( + (order) => order.hash === postedOrderSequence + ); + + if (postedOrder !== undefined) { + orderState = postedOrder.state; + if (orderState === state) { + hasPassed = true; + } + } + } + + checkCount++; + await new Promise((resolve) => setTimeout(resolve, requestFrequency)); + } + + expect(orderState).toBe(state); + expect(hasPassed).toBe(true); +} diff --git a/test/connectors/xrpl/xrpl.routes.test.ts b/test/connectors/xrpl/xrpl.routes.test.ts new file mode 100644 index 0000000000..cbd6da15be --- /dev/null +++ b/test/connectors/xrpl/xrpl.routes.test.ts @@ -0,0 +1,628 @@ +import request from 'supertest'; +import { gatewayApp } from '../../../src/app'; +import { XRPL } from '../../../src/chains/xrpl/xrpl'; +import { XRPLCLOB } from '../../../src/connectors/xrpl/xrpl'; +import {} from '../../../src/chains/xrpl/xrpl.order-tracker'; +import { Order } from '../../../src/connectors/xrpl/xrpl.types'; +import { patch, unpatch } from '../../services/patch'; + +let xrpl: XRPL; +let xrplCLOB: XRPLCLOB; + +const TX_HASH = + 'ADEC6FF35C49B9FF5D06741B5D219D194568919A57876E29296AC530EB25F1CB'; // noqa: mock +const MARKET = 'USD-XRP'; + +const MARKETS = { + 'USD-XRP': { + marketId: 'USD-XRP', + minimumOrderSize: 1, + tickSize: 1, + baseTransferRate: 1, + quoteTransferRate: 1, + baseIssuer: 'r999', + quoteIssuer: '', + baseCurrency: 'USD', + quoteCurrency: 'XRP', + }, + 'BTC-XRP': { + marketId: 'BTC-XRP', + minimumOrderSize: 1, + tickSize: 1, + baseTransferRate: 1, + quoteTransferRate: 1, + baseIssuer: 'r888', + quoteIssuer: '', + baseCurrency: 'BTC', + quoteCurrency: 'XRP', + }, +}; + +const ORDER = { + hash: 1234567, + marketId: 'USD-XRP', + price: '1', + amount: '1', + filledAmount: '0', + state: 'OPEN', + tradeType: 'BUY', + orderType: 'LIMIT', + createdAt: 1234567, + createdAtLedgerIndex: 1234567, + updatedAt: 1234567, + updatedAtLedgerIndex: 1234567, + associatedTxns: [TX_HASH], + associatedFills: [], +}; + +const ORDER_BOOK_1 = { + asks: [ + { + Account: 'rBTwLga3i2gz3doX6Gva3MgEV8ZCD8jjah', + BookDirectory: + 'DFA3B6DDAB58C7E8E5D944E736DA4B7046C30E4F460FD9DE4E1282583CD33780', + BookNode: '0', + Flags: 0, + LedgerEntryType: 'Offer', + OwnerNode: '0', + PreviousTxnID: + '5F8F23607A58A936A5F1D355A7A7491474AABB115C70F5773F3510082EE9B9CB', + PreviousTxnLgrSeq: 80327788, + Sequence: 95908936, + TakerGets: '60133000000', + TakerPays: { + currency: 'USD', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + value: '31328.481625431', + }, + index: 'BBA5F7052917489072A98DDBE46D3258C5A58BB00771FB784A315F6F9C27A9F2', + owner_funds: '60199074323', + quality: '0.000000520986507', + }, + { + Account: 'rBndiPPKs9k5rjBb7HsEiqXKrz8AfUnqWq', + BookDirectory: + 'DFA3B6DDAB58C7E8E5D944E736DA4B7046C30E4F460FD9DE4E12826062F5399E', + BookNode: '0', + Flags: 0, + LedgerEntryType: 'Offer', + OwnerNode: '0', + PreviousTxnID: + 'AEA372417F1BEA783D317ADA70ECE577424F186F663AD621C2B26350784611AC', + PreviousTxnLgrSeq: 80327786, + Sequence: 2591399, + TakerGets: '2618294750', + TakerPays: { + currency: 'USD', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + value: '1364.1054', + }, + index: '6F758711E36E2DBDD6806F123B0266FF7C2556D6918F068573E9B8B6F0FA44B0', + owner_funds: '2648294730', + quality: '0.0000005209900069501342', + }, + { + Account: 'r39rBggWHTUN95x31mAdxPCC7XnhuHRHor', + BookDirectory: + 'DFA3B6DDAB58C7E8E5D944E736DA4B7046C30E4F460FD9DE4E12843D2E482F0A', + BookNode: '0', + Flags: 131072, + LedgerEntryType: 'Offer', + OwnerNode: '1024a', + PreviousTxnID: + '4C9178098581A43C88E8C42760D9CF86CCDC9B18B99DDA20E91CEA63BC156559', + PreviousTxnLgrSeq: 80327776, + Sequence: 3289832, + TakerGets: '404927402', + TakerPays: { + currency: 'USD', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + value: '211.046051649151', + }, + index: '41E60EC5FE55577CC6B9DDE07EF0A6659D2B069E25F12F75BCEDCF94E2007B7B', + owner_funds: '23953272168', + quality: '0.0000005211947885145866', + }, + ], + bids: [ + { + Account: 'rhG9NsvuiG9q3acfR8YbuQd5MabMVDocpc', + BookDirectory: + '4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5B06E2259ADB6200', + BookNode: '0', + Flags: 0, + LedgerEntryType: 'Offer', + OwnerNode: '3', + PreviousTxnID: + 'F4D2C5D67C38C30E611815222D1402ECD438DE167252BF434E2CFA58BF69E804', + PreviousTxnLgrSeq: 80326053, + Sequence: 79612812, + TakerGets: { + currency: 'USD', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + value: '5', + }, + TakerPays: '9687505', + index: '379709FE07C7209BF66F31255822049087E1B4977B556462E46D5F26183C2CC7', + owner_funds: '67.76153742499045', + quality: '1937501', + }, + { + Account: 'rBTwLga3i2gz3doX6Gva3MgEV8ZCD8jjah', + BookDirectory: + '4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5B06E72B1C323523', + BookNode: '0', + Flags: 0, + LedgerEntryType: 'Offer', + OwnerNode: '0', + PreviousTxnID: + '79759B2B346BADF16A3E0A7CC52F7EE77AAE356FAB04178F097329CAEBD25FB5', + PreviousTxnLgrSeq: 80327788, + Sequence: 95908935, + TakerGets: { + currency: 'USD', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + value: '102932.4316', + }, + TakerPays: '200000000000', + index: '2C61AF858D251FE41FDF7768B42C412C39A49FC562B063A1A40A4C175AD8C6A6', + owner_funds: '192823.71422378', + quality: '1943022.202926371', + }, + { + Account: 'r39rBggWHTUN95x31mAdxPCC7XnhuHRHor', + BookDirectory: + '4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5B06E72BAB10809A', + BookNode: '0', + Flags: 0, + LedgerEntryType: 'Offer', + OwnerNode: '1024a', + PreviousTxnID: + 'A5F18BB1F514F879E6B896F2353E84E5AD67D537B494D5C3237B7AA7B93CA9EC', + PreviousTxnLgrSeq: 80327776, + Sequence: 3289831, + TakerGets: { + currency: 'USD', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + value: '14.1299883707017', + }, + TakerPays: '27454915', + index: '65D89D4C9EE529A927E4C831EE873F94BEBCDF29D3CCADD676AE77F7B1283A60', + owner_funds: '537.8134698861974', + quality: '1943024.599859354', + }, + ], +}; + +const ORDER_BOOK_2 = { + asks: [ + { + Account: 'rhWVeCa6aL7U5argwYiUpMD9Gxtd6kxkNw', + BookDirectory: + 'DFA3B6DDAB58C7E8E5D944E736DA4B7046C30E4F460FD9DE491CC6E836AE4000', + BookNode: '0', + Flags: 131072, + LedgerEntryType: 'Offer', + OwnerNode: '0', + PreviousTxnID: + '44A811F5EE120D2215A7F482BDC4C0AF048C82C895C69E7E0FEC6163FCA5A48E', + PreviousTxnLgrSeq: 33839380, + Sequence: 33834963, + TakerGets: '2000000', + TakerPays: { + currency: 'USD', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + value: '0.0000162', + }, + index: '772B28EBC0CB840329A49BF6B696EC454444560C1EA343EB1C29C9421889C45F', + owner_funds: '1383999940', + quality: '8100000000000000e-27', + }, + { + Account: 'rJHjA2WqqYWSh4ttCPW1b9aSyFkisfz93j', + BookDirectory: + 'DFA3B6DDAB58C7E8E5D944E736DA4B7046C30E4F460FD9DE491CDAE1056DB731', + BookNode: '0', + Flags: 0, + LedgerEntryType: 'Offer', + OwnerNode: '0', + PreviousTxnID: + '5AA8D0E7FAB6E1C854F8E69C3C84A095FC9FEFF3BF29072D2D435758CA52DB9E', + PreviousTxnLgrSeq: 17154522, + Sequence: 17130191, + TakerGets: '123123000000', + TakerPays: { + currency: 'USD', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + value: '1', + }, + index: 'BC91DD45090AC3C2955A1877706BB8E637E1AE9D4A5731A942A06C2887839DB0', + owner_funds: '967999808', + quality: '8121959341471537e-27', + taker_gets_funded: '967999808', + taker_pays_funded: { + currency: 'USD', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + value: '0.007862055083128254', + }, + }, + { + Account: 'rMFwQW3F5EvvJ4mu9dBZ3kWnEwj9SHjoGd', + BookDirectory: + 'DFA3B6DDAB58C7E8E5D944E736DA4B7046C30E4F460FD9DE4D1D9B1F5D20D555', + BookNode: '0', + Flags: 0, + LedgerEntryType: 'Offer', + OwnerNode: '0', + PreviousTxnID: + 'CF1FDE17372D00219401EB4847B3281A2AF76485BEB0EDF7DF7A6D5DC387C6C6', + PreviousTxnLgrSeq: 16948251, + Sequence: 16801746, + TakerGets: '12000000', + TakerPays: { + currency: 'USD', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + value: '1', + }, + index: '52F6B9F706D7324BBC6DC35EAFBE54E213930C99BD2432261D452E937C2817B8', + owner_funds: '175107078', + quality: '0.00000008333333333333333', + }, + ], + bids: [], +}; + +const GAS_PRICES = { + gasPrice: '500000000', + gasPriceToken: 'Token', + gasLimit: '1000', + gasCost: '100', +}; + +const INVALID_REQUEST = { + chain: 'unknown', + network: 'testnet', +}; + +beforeAll(async () => { + xrpl = XRPL.getInstance('testnet'); + xrplCLOB = XRPLCLOB.getInstance('xrpl', 'testnet'); + patchConnect(); +}); + +// eslint-disable-next-line @typescript-eslint/no-empty-function +beforeEach(() => { + patchConnect(); + patchFee(); + patchOrderTracking(); + patchCurrentBlockNumber(); + patchMarkets(); +}); + +// afterEach(() => { +// unpatch(); +// }); + +afterAll(async () => { + await xrpl.close(); + unpatch(); +}); + +const patchConnect = () => { + patch(xrpl, 'ensureConnection', async () => { + return Promise.resolve(); + }); +}; + +const patchFee = () => { + patch(xrpl, 'getFee', () => { + return { + base: '1', + median: '1', + minimum: '1', + openLedger: '1', + }; + }); +}; + +const patchOrderTracking = () => { + patch(xrplCLOB, 'trackOrder', () => { + return Promise.resolve(); + }); +}; + +const patchGetOrder = () => { + patch(xrplCLOB, 'getOrder', () => { + return undefined; + }); +}; + +const patchCurrentBlockNumber = (withError: boolean = false) => { + patch(xrplCLOB, 'getCurrentBlockNumber', () => { + return withError ? -1 : 100; + }); +}; + +const patchMarkets = () => { + patch(xrplCLOB, 'parsedMarkets', MARKETS); +}; + +const patchGetMidPriceForMarket = () => { + patch(xrplCLOB, 'getMidPriceForMarket', () => { + return 1.0; + }); +}; + +const patchGetOrderBookFromXRPL = (orderbook: any) => { + patch(xrplCLOB, 'getOrderBookFromXRPL', () => { + return orderbook; + }); +}; + +const patchOrders = () => { + patch(xrplCLOB, '_orderStorage', { + async getOrdersByHash() { + const orders: Record = { [ORDER.hash]: ORDER }; + return orders; + }, + // async getOrderByMarketAndHash() { + // const orders: Record = { [ORDER.hash]: ORDER }; + // return orders; + // }, + async getOrdersByMarket() { + const orders: Record = { [ORDER.hash]: ORDER }; + return orders; + }, + }); +}; + +const patchSubmitTxn = () => { + patch(xrplCLOB, 'submitTxn', () => { + return { + prepared: { + Sequence: 1234567, + }, + signed: { + hash: TX_HASH, + }, + }; + }); +}; + +const patchGetWallet = () => { + patch(xrplCLOB, 'getWallet', () => { + return { + classicAddress: 'rh8LssQyeBdEXk7Zv86HxHrx8k2R2DBUrx', + }; + }); +}; + +const patchGasPrices = () => { + patch(xrplCLOB, 'getFeeEstimate', () => { + return GAS_PRICES; + }); +}; + +describe('GET /clob/markets', () => { + it('should return 200 with proper request', async () => { + patchMarkets(); + await request(gatewayApp) + .get(`/clob/markets`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(Object.values(res.body.markets).length).toEqual(2); + }); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .get(`/clob/markets`) + .query(INVALID_REQUEST) + .expect(404); + }); +}); + +describe('GET /clob/orderBook', () => { + it('should return 200 with proper request with ORDER_BOOK_1', async () => { + patchMarkets(); + patchGetOrderBookFromXRPL(ORDER_BOOK_1); + await request(gatewayApp) + .get(`/clob/orderBook`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + market: MARKET, + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(res.body.buys[0].price).toEqual('0.5161287658690241'); + }) + .expect((res) => expect(res.body.buys[0].quantity).toEqual('9.687505')) + .expect((res) => + expect(res.body.sells[0].price).toEqual('0.5209865069999999') + ) + .expect((res) => expect(res.body.sells[0].quantity).toEqual('60133')); + }); + + it('should return 200 with proper request with ORDER_BOOK_2', async () => { + patchMarkets(); + patchGetOrderBookFromXRPL(ORDER_BOOK_2); + await request(gatewayApp) + .get(`/clob/orderBook`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + market: MARKET, + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => expect(res.body.buys[0]).toBeUndefined()) + .expect((res) => expect(res.body.sells[0].price).toEqual('0.0000081')) + .expect((res) => expect(res.body.sells[0].quantity).toEqual('2')); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .get(`/clob/orderBook`) + .query(INVALID_REQUEST) + .expect(404); + }); +}); + +describe('GET /clob/ticker', () => { + it('should return 200 with proper request', async () => { + patchMarkets(); + patchGetMidPriceForMarket(); + await request(gatewayApp) + .get(`/clob/ticker`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + market: MARKET, + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(res.body.markets[0].baseCurrency).toEqual('USD'); + }) + .expect((res) => expect(res.body.markets[0].quoteCurrency).toEqual('XRP')) + .expect((res) => expect(res.body.markets[0].midprice).toEqual(1)); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .get(`/clob/ticker`) + .query(INVALID_REQUEST) + .expect(404); + }); +}); + +describe('GET /clob/orders', () => { + it('should return 200 with proper request', async () => { + patchMarkets(); + patchOrders(); + await request(gatewayApp) + .get(`/clob/orders`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + market: MARKET, + address: 'rh8LssQyeBdEXk7Zv86HxHrx8k2R2DBUrx', // noqa: mock + orderId: '1234567', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => { + expect(res.body.orders.length).toEqual(1); + }); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .get(`/clob/orders`) + .query(INVALID_REQUEST) + .expect(404); + }); +}); + +describe('POST /clob/orders', () => { + it('should return 200 with proper request', async () => { + patchMarkets(); + patchSubmitTxn(); + patchGetWallet(); + await request(gatewayApp) + .post(`/clob/orders`) + .send({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: 'rh8LssQyeBdEXk7Zv86HxHrx8k2R2DBUrx', // noqa: mock + market: MARKET, + price: '1', + amount: '1', + side: 'BUY', + orderType: 'LIMIT', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => expect(res.body.txHash).toEqual(TX_HASH)); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .post(`/clob/orders`) + .send(INVALID_REQUEST) + .expect(404); + }); +}); + +describe('DELETE /clob/orders', () => { + it('should return 200 with proper request', async () => { + patchSubmitTxn(); + patchGetWallet(); + patchGetOrder(); + await request(gatewayApp) + .delete(`/clob/orders`) + .send({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + address: 'rh8LssQyeBdEXk7Zv86HxHrx8k2R2DBUrx', // noqa: mock + market: MARKET, + orderId: '1234567', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => expect(res.body.txHash).toEqual(TX_HASH)); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .delete(`/clob/orders`) + .send(INVALID_REQUEST) + .expect(404); + }); +}); + +describe('GET /clob/estimateGas', () => { + it('should return 200 with proper request', async () => { + patchGasPrices(); + patchGetOrder(); + await request(gatewayApp) + .get(`/clob/estimateGas`) + .query({ + chain: 'xrpl', + network: 'testnet', + connector: 'xrpl', + }) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200) + .expect((res) => expect(res.body.gasPrice).toEqual(GAS_PRICES.gasPrice)); + }); + + it('should return 404 when parameters are invalid', async () => { + await request(gatewayApp) + .get(`/clob/estimateGas`) + .query(INVALID_REQUEST) + .expect(404); + }); +}); diff --git a/yarn.lock b/yarn.lock index 3af0387dd1..8e6c3eb9f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3844,6 +3844,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.3.tgz#f0b991c32cfc6a4e7f3399d6cb4b8cf9a0315014" integrity sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw== +"@types/node@10.12.18": + version "10.12.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" + integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== + "@types/node@11.11.6": version "11.11.6" resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" @@ -4816,6 +4821,17 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== +assert@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" + integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== + dependencies: + call-bind "^1.0.2" + is-nan "^1.3.2" + object-is "^1.1.5" + object.assign "^4.1.4" + util "^0.12.5" + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -4994,7 +5010,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base-x@^3.0.2, base-x@^3.0.6, base-x@^3.0.8: +base-x@^3.0.2, base-x@^3.0.6, base-x@^3.0.8, base-x@^3.0.9: version "3.0.9" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== @@ -5048,6 +5064,11 @@ bech32@^2.0.0: resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== +big-integer@^1.6.48: + version "1.6.51" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" + integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== + big.js@6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.1.1.tgz#63b35b19dc9775c94991ee5db7694880655d5537" @@ -5099,6 +5120,19 @@ bindings@^1.3.0, bindings@^1.3.1, bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +bip32@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/bip32/-/bip32-2.0.6.tgz#6a81d9f98c4cd57d05150c60d8f9e75121635134" + integrity sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA== + dependencies: + "@types/node" "10.12.18" + bs58check "^2.1.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + tiny-secp256k1 "^1.1.3" + typeforce "^1.11.5" + wif "^2.0.6" + bip39@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.4.tgz#5b11fed966840b5e1b8539f0f54ab6392969b2a0" @@ -5269,7 +5303,7 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.0.1, brorand@^1.1.0: +brorand@^1.0.1, brorand@^1.0.5, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== @@ -5377,7 +5411,7 @@ bs58@^4.0.0, bs58@^4.0.1: dependencies: base-x "^3.0.2" -bs58check@^2.1.2: +bs58check@<3.0.0, bs58check@^2.1.1, bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== @@ -5439,6 +5473,14 @@ buffer@6.0.1: base64-js "^1.3.1" ieee754 "^1.2.1" +buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" @@ -5447,14 +5489,6 @@ buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: base64-js "^1.3.1" ieee754 "^1.1.13" -buffer@^6.0.3, buffer@~6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - bufferutil@4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.5.tgz#da9ea8166911cc276bf677b8aed2d02d31f59028" @@ -6252,11 +6286,16 @@ decimal.js-light@^2.5.0, decimal.js-light@^2.5.1: resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== -decimal.js@^10.2.1, decimal.js@^10.3.1, decimal.js@^10.4.3: +decimal.js@^10.2.0, decimal.js@^10.4.3: version "10.4.3" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== +decimal.js@^10.2.1, decimal.js@^10.3.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" + integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== + decode-uri-component@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" @@ -8948,6 +8987,14 @@ is-lower-case@^1.1.0: dependencies: lower-case "^1.1.0" +is-nan@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" @@ -10292,7 +10339,7 @@ lodash.values@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347" integrity sha512-r0RwvdCv8id9TUblb/O7rYPwVy6lerCbcawrfdo9iC/1t1wsNMJknO79WNBgwkH0hIeJ08jmvvESbFpNb4jH0Q== -lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.2.1, lodash@^4.7.0: +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.2.1, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -10961,10 +11008,15 @@ nan@2.14.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== +nan@^2.13.2: + version "2.18.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.18.0.tgz#26a6faae7ffbeb293a39660e88a76b82e30b7554" + integrity sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w== + nan@^2.14.0: - version "2.17.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" - integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + version "2.16.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.16.0.tgz#664f43e45460fb98faf00edca0bb0d7b8dce7916" + integrity sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA== nano-json-stream-parser@^0.1.2: version "0.1.2" @@ -11259,6 +11311,14 @@ object-inspect@^1.12.3, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== +object-is@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -12547,6 +12607,37 @@ ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2: hash-base "^3.0.0" inherits "^2.0.1" +ripple-address-codec@^4.2.5, ripple-address-codec@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/ripple-address-codec/-/ripple-address-codec-4.3.1.tgz#68fbaf646bb8567f70743af7f1ce4479f73efbf6" + integrity sha512-Qa3+9wKVvpL/xYtT6+wANsn0A1QcC5CT6IMZbRJZ/1lGt7gmwIfsrCuz1X0+LCEO7zgb+3UT1I1dc0k/5dwKQQ== + dependencies: + base-x "^3.0.9" + create-hash "^1.1.2" + +ripple-binary-codec@^1.4.3: + version "1.10.0" + resolved "https://registry.yarnpkg.com/ripple-binary-codec/-/ripple-binary-codec-1.10.0.tgz#549f7fb3d3faf6b2d09fe7032bdcc4e6f8b5a511" + integrity sha512-qWXxubgXBV3h5NTaaLiusZ1FhPqSy+bCYHHarfZ3bMmO2alRa1Ox61jvX1Zyozok8PcF3gs3bKwZci4RTlA07w== + dependencies: + assert "^2.0.0" + big-integer "^1.6.48" + buffer "6.0.3" + create-hash "^1.2.0" + decimal.js "^10.2.0" + ripple-address-codec "^4.3.1" + +ripple-keypairs@^1.1.5: + version "1.3.1" + resolved "https://registry.yarnpkg.com/ripple-keypairs/-/ripple-keypairs-1.3.1.tgz#7fa531df36b138134afb53555a87d7f5eb465b2e" + integrity sha512-dmPlraWKJciFJxHcoubDahGnoIalG5e/BtV6HNDUs7wLXmtnLMHt6w4ed9R8MTL2zNrVPiIdI/HCtMMo0Tm7JQ== + dependencies: + bn.js "^5.1.1" + brorand "^1.0.5" + elliptic "^6.5.4" + hash.js "^1.0.3" + ripple-address-codec "^4.3.1" + rlp@^2.2.3, rlp@^2.2.4: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" @@ -13624,6 +13715,17 @@ tiny-invariant@^1.1.0: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== +tiny-secp256k1@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz#7e224d2bee8ab8283f284e40e6b4acb74ffe047c" + integrity sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA== + dependencies: + bindings "^1.3.0" + bn.js "^4.11.8" + create-hmac "^1.1.7" + elliptic "^6.4.0" + nan "^2.13.2" + tiny-typed-emitter@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz#b3b027fdd389ff81a152c8e847ee2f5be9fad7b5" @@ -13975,6 +14077,11 @@ typedarray-to-buffer@^4.0.0: resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-4.0.0.tgz#cdd2933c61dd3f5f02eda5d012d441f95bfeb50a" integrity sha512-6dOYeZfS3O9RtRD1caom0sMxgK59b27+IwoNy8RDPsmslSGOyU+mpTamlaIW7aNKi90ZQZ9DFaZL3YRoiSCULQ== +typeforce@^1.11.5: + version "1.18.0" + resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" + integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== + typescript-compare@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/typescript-compare/-/typescript-compare-0.0.2.tgz#7ee40a400a406c2ea0a7e551efd3309021d5f425" @@ -14897,6 +15004,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wif@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/wif/-/wif-2.0.6.tgz#08d3f52056c66679299726fade0d432ae74b4704" + integrity sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ== + dependencies: + bs58check "<3.0.0" + winston-daily-rotate-file@^4.5.5: version "4.7.1" resolved "https://registry.yarnpkg.com/winston-daily-rotate-file/-/winston-daily-rotate-file-4.7.1.tgz#f60a643af87f8867f23170d8cd87dbe3603a625f" @@ -15006,6 +15120,11 @@ ws@^7, ws@^7.2.0, ws@^7.4.5, ws@^7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== +ws@^8.2.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" + integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== + ws@^8.5.0: version "8.13.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" @@ -15089,6 +15208,21 @@ xmlhttprequest@1.8.0: resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== +xrpl@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/xrpl/-/xrpl-2.7.0.tgz#3f0d04f1bf79cce34e711b666a6172bd5fd19348" + integrity sha512-P4M/Myxn2U7wl1avAG2Y/JuJMlKw2boLNx0f9woYQJLrS68sICmAfGOYKqPSzwRPc9P7kmydNrk+737nmFW5Vw== + dependencies: + bignumber.js "^9.0.0" + bip32 "^2.0.6" + bip39 "^3.0.4" + https-proxy-agent "^5.0.0" + lodash "^4.17.4" + ripple-address-codec "^4.2.5" + ripple-binary-codec "^1.4.3" + ripple-keypairs "^1.1.5" + ws "^8.2.2" + xss@^1.0.8: version "1.0.14" resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.14.tgz#4f3efbde75ad0d82e9921cc3c95e6590dd336694"