mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-21 04:35:49 +00:00
Add getTrustlines and unit test
This commit is contained in:
@@ -10,13 +10,11 @@
|
|||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 1
|
"minimum": 1
|
||||||
},
|
},
|
||||||
"ledgerVersion": {
|
"ledgerHash": {
|
||||||
"anyOf": [
|
"type": "string",
|
||||||
{"enum": ["current", "closed", "validated"]},
|
"format": "ledgerHash"
|
||||||
{"$ref": "ledgerVersion"},
|
|
||||||
{"type": "string", "format": "ledgerHash"}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
|
"ledgerVersion": {"$ref": "ledgerVersion"},
|
||||||
"minLedgerVersion": {"$ref": "ledgerVersion"},
|
"minLedgerVersion": {"$ref": "ledgerVersion"},
|
||||||
"maxLedgerVersion": {"$ref": "ledgerVersion"},
|
"maxLedgerVersion": {"$ref": "ledgerVersion"},
|
||||||
"marker": {
|
"marker": {
|
||||||
|
|||||||
30
src/api/ledger/parse/account-trustline.js
Normal file
30
src/api/ledger/parse/account-trustline.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
'use strict';
|
||||||
|
const utils = require('./utils');
|
||||||
|
|
||||||
|
// rippled 'account_lines' returns a different format for
|
||||||
|
// trustlines than 'tx'
|
||||||
|
function parseAccountTrustline(trustline) {
|
||||||
|
const specification = utils.removeUndefined({
|
||||||
|
limit: trustline.limit,
|
||||||
|
currency: trustline.currency,
|
||||||
|
counterparty: trustline.account,
|
||||||
|
qualityIn: trustline.quality_in || undefined,
|
||||||
|
qualityOut: trustline.quality_out || undefined,
|
||||||
|
disableRippling: trustline.no_ripple,
|
||||||
|
frozen: trustline.freeze,
|
||||||
|
authorized: trustline.authorized
|
||||||
|
});
|
||||||
|
// rippled doesn't provide the counterparty's qualities
|
||||||
|
const counterparty = utils.removeUndefined({
|
||||||
|
limit: trustline.limit_peer,
|
||||||
|
disableRippling: trustline.no_ripple_peer,
|
||||||
|
frozen: trustline.freeze_peer,
|
||||||
|
authorized: trustline.peer_authorized
|
||||||
|
});
|
||||||
|
const state = {
|
||||||
|
balance: trustline.balance
|
||||||
|
};
|
||||||
|
return {specification, counterparty, state};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = parseAccountTrustline;
|
||||||
@@ -13,7 +13,7 @@ function parseTrustline(tx: Object): Object {
|
|||||||
counterparty: tx.LimitAmount.issuer,
|
counterparty: tx.LimitAmount.issuer,
|
||||||
qualityIn: tx.QualityIn,
|
qualityIn: tx.QualityIn,
|
||||||
qualityOut: tx.QualityOut,
|
qualityOut: tx.QualityOut,
|
||||||
allowRippling: (tx.Flags & flags.NoRipple) === 0,
|
disableRippling: (tx.Flags & flags.NoRipple) !== 0,
|
||||||
frozen: (tx.Flags & flags.SetFreeze) !== 0,
|
frozen: (tx.Flags & flags.SetFreeze) !== 0,
|
||||||
authorized: (tx.Flags & flags.SetAuth) !== 0
|
authorized: (tx.Flags & flags.SetAuth) !== 0
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -81,25 +81,6 @@ function parseAccountTxTransaction(tx) {
|
|||||||
return parseTransaction(tx.tx);
|
return parseTransaction(tx.tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAccountTx(remote, address, limit, marker, options, callback) {
|
|
||||||
const params = {
|
|
||||||
account: address,
|
|
||||||
ledger_index_min: options.ledgerVersion || options.minLedgerVersion || -1,
|
|
||||||
ledger_index_max: options.ledgerVersion || options.maxLedgerVersion || -1,
|
|
||||||
forward: options.earliestFirst,
|
|
||||||
binary: options.binary,
|
|
||||||
limit: Math.min(limit || DEFAULT_LIMIT, 10),
|
|
||||||
marker: marker
|
|
||||||
};
|
|
||||||
|
|
||||||
remote.requestAccountTx(params, (error, data) => {
|
|
||||||
return error ? callback(error) : callback(null, {
|
|
||||||
transactions: data.transactions.filter((tx) => tx.validated)
|
|
||||||
.map(parseAccountTxTransaction),
|
|
||||||
marker: data.marker
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function transactionFilter(address, filters, tx) {
|
function transactionFilter(address, filters, tx) {
|
||||||
if (filters.excludeFailures && tx.outcome.result !== 'tesSUCCESS') {
|
if (filters.excludeFailures && tx.outcome.result !== 'tesSUCCESS') {
|
||||||
@@ -117,27 +98,25 @@ function transactionFilter(address, filters, tx) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAccountTransactionsRecursive(
|
function getAccountTx(remote, address, options, marker, limit, callback) {
|
||||||
remote, address, limit, marker, options, callback) {
|
const params = {
|
||||||
getAccountTx(remote, address, limit, marker, options, (error, data) => {
|
account: address,
|
||||||
if (error) {
|
ledger_index_min: options.ledgerVersion || options.minLedgerVersion || -1,
|
||||||
callback(error);
|
ledger_index_max: options.ledgerVersion || options.maxLedgerVersion || -1,
|
||||||
return;
|
forward: options.earliestFirst,
|
||||||
}
|
binary: options.binary,
|
||||||
const filter = _.partial(transactionFilter, address, options);
|
limit: Math.min(limit || DEFAULT_LIMIT, 10),
|
||||||
const unfilteredTransactions = data.transactions;
|
marker: marker
|
||||||
const filteredTransactions = unfilteredTransactions.filter(filter);
|
};
|
||||||
const isExhausted = unfilteredTransactions.length === 0;
|
|
||||||
if (!isExhausted && filteredTransactions.length < limit) {
|
remote.requestAccountTx(params, (error, data) => {
|
||||||
const remaining = limit - filteredTransactions.length;
|
return error ? callback(error) : callback(null, {
|
||||||
getAccountTransactionsRecursive(
|
marker: data.marker,
|
||||||
remote, address, remaining, data.marker, options, (_err, txs) => {
|
results: data.transactions
|
||||||
return error ? callback(_err) :
|
.filter((tx) => tx.validated)
|
||||||
callback(null, filteredTransactions.concat(txs));
|
.map(parseAccountTxTransaction)
|
||||||
|
.filter(_.partial(transactionFilter, address, options))
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
callback(null, filteredTransactions.slice(0, limit));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,9 +126,9 @@ function getAccountTransactions(address, options, callback) {
|
|||||||
const limit = options.limit || DEFAULT_LIMIT;
|
const limit = options.limit || DEFAULT_LIMIT;
|
||||||
const compare = options.earliestFirst ? utils.compareTransactions :
|
const compare = options.earliestFirst ? utils.compareTransactions :
|
||||||
_.rearg(utils.compareTransactions, 1, 0);
|
_.rearg(utils.compareTransactions, 1, 0);
|
||||||
getAccountTransactionsRecursive(
|
const getter = _.partial(getAccountTx, this.remote, address, options);
|
||||||
this.remote, address, limit, null, options, (error, transactions) => {
|
utils.getRecursive(getter, limit, (error, data) => {
|
||||||
return error ? callback(error) : callback(null, transactions.sort(compare));
|
return error ? callback(error) : callback(null, data.sort(compare));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,127 +1,48 @@
|
|||||||
/* globals Promise: true */
|
|
||||||
/* eslint-disable valid-jsdoc */
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
const _ = require('lodash');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const validate = utils.common.validate;
|
const validate = utils.common.validate;
|
||||||
|
const parseAccountTrustline = require('./parse/account-trustline');
|
||||||
|
|
||||||
const DefaultPageLimit = 200;
|
function currencyFilter(currency, trustline) {
|
||||||
|
return currency === null || trustline.specification.currency === currency;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
function getAccountLines(remote, address, ledgerVersion, options, marker, limit,
|
||||||
* Retrieves all trustlines for a given account
|
callback) {
|
||||||
*
|
const requestOptions = {
|
||||||
* Notes:
|
account: address,
|
||||||
* In order to use paging, you must provide at least ledger as a query parameter
|
ledger: ledgerVersion,
|
||||||
* Additionally, any limit lower than 10 will be bumped up to 10.
|
marker: marker,
|
||||||
*
|
limit: Math.max(limit, 10),
|
||||||
* @url
|
peer: options.counterparty
|
||||||
* @param {String} request.params.account - account to retrieve trustlines for
|
};
|
||||||
*
|
|
||||||
* @query
|
const currency = options.currency ? options.currency.toUpperCase() : null;
|
||||||
* @param {String ISO 4217 Currency Code} [request.query.currency]
|
remote.requestAccountLines(requestOptions, (error, data) => {
|
||||||
* - only request trustlines with given currency
|
return error ? callback(error) :
|
||||||
* @param {RippleAddress} [request.query.counterparty]
|
callback(null, {
|
||||||
* - only request trustlines with given counterparty
|
marker: data.marker,
|
||||||
* @param {String} [request.query.marker] - start position in response paging
|
results: data.lines.map(parseAccountTrustline)
|
||||||
* @param {Number String} [request.query.limit] - max results per response
|
.filter(_.partial(currencyFilter, currency))
|
||||||
* @param {Number String} [request.query.ledger] - identifier
|
});
|
||||||
*
|
});
|
||||||
*/
|
}
|
||||||
function getTrustLines(account, options, callback) {
|
|
||||||
|
/*:: type Options = {currency: string, counterparty: string,
|
||||||
|
limit: number, ledgerVersion: number} */
|
||||||
|
function getTrustlines(account: string, options: Options,
|
||||||
|
callback: () => void): void {
|
||||||
validate.address(account);
|
validate.address(account);
|
||||||
validate.options(options);
|
validate.options(options);
|
||||||
|
|
||||||
const self = this;
|
const defaultLimit = 100;
|
||||||
|
const limit = options.limit || defaultLimit;
|
||||||
const currencyRE = new RegExp(options.currency ?
|
const ledgerVersion = options.ledgerVersion
|
||||||
('^' + options.currency.toUpperCase() + '$') : /./);
|
|| this.remote.getLedgerSequence();
|
||||||
|
const getter = _.partial(getAccountLines, this.remote, account,
|
||||||
function getAccountLines(prevResult) {
|
ledgerVersion, options);
|
||||||
const isAggregate = options.limit === undefined;
|
utils.getRecursive(getter, limit, callback);
|
||||||
if (prevResult && (!isAggregate || !prevResult.marker)) {
|
|
||||||
return Promise.resolve(prevResult);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const promise = new Promise(function(resolve, reject) {
|
module.exports.getTrustlines = getTrustlines;
|
||||||
let accountLinesRequest;
|
|
||||||
let marker;
|
|
||||||
let ledger;
|
|
||||||
let limit;
|
|
||||||
|
|
||||||
if (prevResult) {
|
|
||||||
marker = prevResult.marker;
|
|
||||||
limit = prevResult.limit;
|
|
||||||
ledger = prevResult.ledger_index;
|
|
||||||
} else {
|
|
||||||
marker = options.marker;
|
|
||||||
limit = options.limit || DefaultPageLimit;
|
|
||||||
ledger = utils.parseLedger(options.ledger);
|
|
||||||
}
|
|
||||||
|
|
||||||
accountLinesRequest = self.remote.requestAccountLines({
|
|
||||||
account: account,
|
|
||||||
marker: marker,
|
|
||||||
limit: limit,
|
|
||||||
ledger: ledger
|
|
||||||
});
|
|
||||||
|
|
||||||
if (options.counterparty) {
|
|
||||||
accountLinesRequest.message.peer = options.counterparty;
|
|
||||||
}
|
|
||||||
|
|
||||||
accountLinesRequest.once('error', reject);
|
|
||||||
accountLinesRequest.once('success', function(nextResult) {
|
|
||||||
|
|
||||||
const lines = [ ];
|
|
||||||
nextResult.lines.forEach(function(line) {
|
|
||||||
if (!currencyRE.test(line.currency)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lines.push({
|
|
||||||
account: account,
|
|
||||||
counterparty: line.account,
|
|
||||||
currency: line.currency,
|
|
||||||
limit: line.limit,
|
|
||||||
reciprocated_limit: line.limit_peer,
|
|
||||||
account_allows_rippling: line.no_ripple ? !line.no_ripple : true,
|
|
||||||
counterparty_allows_rippling: line.no_ripple_peer
|
|
||||||
? !line.no_ripple_peer : true,
|
|
||||||
account_trustline_frozen: line.freeze ? line.freeze : false,
|
|
||||||
counterparty_trustline_frozen: line.freeze_peer
|
|
||||||
? line.freeze_peer : false
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
nextResult.lines = prevResult ? prevResult.lines.concat(lines) : lines;
|
|
||||||
resolve([nextResult]);
|
|
||||||
});
|
|
||||||
accountLinesRequest.request();
|
|
||||||
});
|
|
||||||
|
|
||||||
return promise.spread(getAccountLines);
|
|
||||||
}
|
|
||||||
|
|
||||||
function respondWithTrustlines(result) {
|
|
||||||
const promise = new Promise(function(resolve) {
|
|
||||||
const trustlines = {};
|
|
||||||
|
|
||||||
if (result.marker) {
|
|
||||||
trustlines.marker = result.marker;
|
|
||||||
}
|
|
||||||
|
|
||||||
trustlines.limit = result.limit;
|
|
||||||
trustlines.ledger = result.ledger_index;
|
|
||||||
trustlines.validated = result.validated;
|
|
||||||
trustlines.trustlines = result.lines;
|
|
||||||
|
|
||||||
resolve(callback(null, trustlines));
|
|
||||||
});
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
getAccountLines()
|
|
||||||
.then(respondWithTrustlines)
|
|
||||||
.catch(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports.getTrustLines = getTrustLines;
|
|
||||||
|
|||||||
@@ -6,6 +6,29 @@ const asyncify = require('simple-asyncify');
|
|||||||
const common = require('../common');
|
const common = require('../common');
|
||||||
const ripple = common.core;
|
const ripple = common.core;
|
||||||
|
|
||||||
|
// If the marker is omitted from a response, you have reached the end
|
||||||
|
// getter(marker, limit, callback), callback(error, {marker, results})
|
||||||
|
function getRecursiveRecur(getter, marker, limit, callback) {
|
||||||
|
getter(marker, limit, (error, data) => {
|
||||||
|
if (error) {
|
||||||
|
return callback(error);
|
||||||
|
}
|
||||||
|
const remaining = limit - data.results.length;
|
||||||
|
if (remaining > 0 && data.marker !== undefined) {
|
||||||
|
getRecursiveRecur(getter, data.marker, remaining, (_error, results) => {
|
||||||
|
return _error ? callback(_error) :
|
||||||
|
callback(null, data.results.concat(results));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return callback(null, data.results.slice(0, limit));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRecursive(getter, limit, callback) {
|
||||||
|
getRecursiveRecur(getter, undefined, limit, callback);
|
||||||
|
}
|
||||||
|
|
||||||
function renameCounterpartyToIssuer(amount) {
|
function renameCounterpartyToIssuer(amount) {
|
||||||
if (amount === undefined) {
|
if (amount === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -99,6 +122,7 @@ module.exports = {
|
|||||||
renameCounterpartyToIssuer: renameCounterpartyToIssuer,
|
renameCounterpartyToIssuer: renameCounterpartyToIssuer,
|
||||||
renameCounterpartyToIssuerInOrder: renameCounterpartyToIssuerInOrder,
|
renameCounterpartyToIssuerInOrder: renameCounterpartyToIssuerInOrder,
|
||||||
attachDate: attachDate,
|
attachDate: attachDate,
|
||||||
|
getRecursive: getRecursive,
|
||||||
wrapCatch: common.wrapCatch,
|
wrapCatch: common.wrapCatch,
|
||||||
common: common
|
common: common
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const TrustSetFlags = {
|
|||||||
frozed: {set: 'SetFreeze', unset: 'ClearFreeze'}
|
frozed: {set: 'SetFreeze', unset: 'ClearFreeze'}
|
||||||
};
|
};
|
||||||
|
|
||||||
function createTrustLineTransaction(account, trustline) {
|
function createTrustlineTransaction(account, trustline) {
|
||||||
validate.address(account);
|
validate.address(account);
|
||||||
validate.trustline(trustline);
|
validate.trustline(trustline);
|
||||||
|
|
||||||
@@ -27,9 +27,9 @@ function createTrustLineTransaction(account, trustline) {
|
|||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareTrustLine(account, trustline, instructions, callback) {
|
function prepareTrustline(account, trustline, instructions, callback) {
|
||||||
const transaction = createTrustLineTransaction(account, trustline);
|
const transaction = createTrustlineTransaction(account, trustline);
|
||||||
utils.createTxJSON(transaction, this.remote, instructions, callback);
|
utils.createTxJSON(transaction, this.remote, instructions, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = utils.wrapCatch(prepareTrustLine);
|
module.exports = utils.wrapCatch(prepareTrustline);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ const submitResponse = require('./fixtures/submit-response');
|
|||||||
const transactionResponse = require('./fixtures/transaction-response');
|
const transactionResponse = require('./fixtures/transaction-response');
|
||||||
const accountTransactionsResponse =
|
const accountTransactionsResponse =
|
||||||
require('./fixtures/account-transactions-response');
|
require('./fixtures/account-transactions-response');
|
||||||
|
const trustlinesResponse = require('./fixtures/trustlines-response');
|
||||||
|
|
||||||
function checkResult(expected, done, error, response) {
|
function checkResult(expected, done, error, response) {
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -99,4 +100,10 @@ describe('RippleAPI', function() {
|
|||||||
this.api.getAccountTransactions(address, options,
|
this.api.getAccountTransactions(address, options,
|
||||||
_.partial(checkResult, accountTransactionsResponse, done));
|
_.partial(checkResult, accountTransactionsResponse, done));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('getTrustlines', function(done) {
|
||||||
|
const options = {currency: 'USD'};
|
||||||
|
this.api.getTrustlines(address, options,
|
||||||
|
_.partial(checkResult, trustlinesResponse, done));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
1
test/fixtures/acct-tx-response.js
vendored
1
test/fixtures/acct-tx-response.js
vendored
@@ -196,6 +196,7 @@ module.exports = function(request, options={}) {
|
|||||||
status: 'success',
|
status: 'success',
|
||||||
type: 'response',
|
type: 'response',
|
||||||
result: {
|
result: {
|
||||||
|
marker: request.marker === undefined ? 'ABC' : undefined,
|
||||||
transactions: [
|
transactions: [
|
||||||
{
|
{
|
||||||
ledger_index: 348860,
|
ledger_index: 348860,
|
||||||
|
|||||||
99
test/fixtures/trustlines-response.json
vendored
Normal file
99
test/fixtures/trustlines-response.json
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"specification": {
|
||||||
|
"limit": "5",
|
||||||
|
"currency": "USD",
|
||||||
|
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
|
||||||
|
"disableRippling": true,
|
||||||
|
"frozen": true
|
||||||
|
},
|
||||||
|
"counterparty": {
|
||||||
|
"limit": "0"
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"balance": "2.497605752725159"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"specification": {
|
||||||
|
"limit": "5000",
|
||||||
|
"currency": "USD",
|
||||||
|
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||||
|
},
|
||||||
|
"counterparty": {
|
||||||
|
"limit": "0"
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"balance": "0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"specification": {
|
||||||
|
"limit": "1",
|
||||||
|
"currency": "USD",
|
||||||
|
"counterparty": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun"
|
||||||
|
},
|
||||||
|
"counterparty": {
|
||||||
|
"limit": "0"
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"balance": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"specification": {
|
||||||
|
"limit": "1",
|
||||||
|
"currency": "USD",
|
||||||
|
"counterparty": "r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X",
|
||||||
|
"disableRippling": true
|
||||||
|
},
|
||||||
|
"counterparty": {
|
||||||
|
"limit": "0"
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"balance": "0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"specification": {
|
||||||
|
"limit": "500",
|
||||||
|
"currency": "USD",
|
||||||
|
"counterparty": "rfF3PNkwkq1DygW2wum2HK3RGfgkJjdPVD",
|
||||||
|
"disableRippling": true
|
||||||
|
},
|
||||||
|
"counterparty": {
|
||||||
|
"limit": "0"
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"balance": "35"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"specification": {
|
||||||
|
"limit": "0",
|
||||||
|
"currency": "USD",
|
||||||
|
"counterparty": "rE6R3DWF9fBD7CyiQciePF9SqK58Ubp8o2"
|
||||||
|
},
|
||||||
|
"counterparty": {
|
||||||
|
"limit": "100",
|
||||||
|
"disableRippling": true
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"balance": "0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"specification": {
|
||||||
|
"limit": "0",
|
||||||
|
"currency": "USD",
|
||||||
|
"counterparty": "rEhDDUUNxpXgEHVJtC2cjXAgyx5VCFxdMF",
|
||||||
|
"frozen": true
|
||||||
|
},
|
||||||
|
"counterparty": {
|
||||||
|
"limit": "1"
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"balance": "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user