Skip to content

Commit

Permalink
Merge pull request #1066 from ExchangeUnion/raiden/balance
Browse files Browse the repository at this point in the history
feat(raiden): channel balance by currency
  • Loading branch information
Karl Ranna authored Jul 9, 2019
2 parents a63fec9 + a488fa7 commit cc8e89f
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 17 deletions.
20 changes: 15 additions & 5 deletions lib/raidenclient/RaidenClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ class RaidenClient extends SwapClient {
private host: string;
private disable: boolean;

// TODO: Populate the mapping from the database (Currency.decimalPlaces).
private static readonly UNITS_PER_CURRENCY: { [key: string]: number } = {
WETH: 10 ** 10,
DAI: 10 ** 10,
};

/**
* Creates a raiden client.
*/
Expand Down Expand Up @@ -273,14 +279,18 @@ class RaidenClient extends SwapClient {
}

/**
* Returns the total balance available across all channels.
* Returns the total balance available across all channels for a specified currency.
*/
public channelBalance = async (): Promise<ChannelBalance> => {
// TODO: refine logic to determine balance per token rather than all combined
const channels = await this.getChannels();
public channelBalance = async (currency?: string): Promise<ChannelBalance> => {
if (!currency) {
return { balance: 0, pendingOpenBalance: 0 };
}

const channels = await this.getChannels(this.tokenAddresses.get(currency));
const balance = channels.filter(channel => channel.state === 'opened')
.map(channel => channel.balance)
.reduce((acc, sum) => sum + acc, 0);
.reduce((sum, acc) => sum + acc, 0)
/ (RaidenClient.UNITS_PER_CURRENCY[currency] || 1);
return { balance, pendingOpenBalance: 0 };
}

Expand Down
26 changes: 15 additions & 11 deletions lib/service/Service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,23 +119,27 @@ class Service {
public channelBalance = async (args: { currency: string }) => {
const { currency } = args;
const balances = new Map<string, { balance: number, pendingOpenBalance: number }>();
const getBalance = async (currency: string) => {

if (currency) {
argChecks.VALID_CURRENCY(args);

const swapClient = this.swapClientManager.get(currency.toUpperCase());
if (swapClient) {
const channelBalance = await swapClient.channelBalance();
return channelBalance;
const channelBalance = await swapClient.channelBalance(currency);
balances.set(currency, channelBalance);
} else {
throw swapsErrors.SWAP_CLIENT_NOT_FOUND(currency);
}
};

if (currency) {
argChecks.VALID_CURRENCY(args);
balances.set(currency, await getBalance(currency));
} else {
for (const currency of this.orderBook.currencies) {
balances.set(currency, await getBalance(currency));
}
const balancePromises: Promise<any>[] = [];
this.swapClientManager.swapClients.forEach((swapClient, currency) => {
if (swapClient.isConnected()) {
balancePromises.push(swapClient.channelBalance(currency).then((channelBalance) => {
balances.set(currency, channelBalance);
}));
}
});
await Promise.all(balancePromises);
}

return balances;
Expand Down
4 changes: 3 additions & 1 deletion lib/swaps/SwapClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ abstract class SwapClient extends EventEmitter {

/**
* Returns the total balance available across all channels.
* @param currency the currency whose balance to query for, otherwise all/any
* currencies supported by this client are included in the balance.
*/
public abstract channelBalance(): Promise<ChannelBalance>;
public abstract channelBalance(currency?: string): Promise<ChannelBalance>;

protected setStatus = async (status: ClientStatus): Promise<void> => {
this.logger.info(`${this.constructor.name} status: ${ClientStatus[status]}`);
Expand Down
47 changes: 47 additions & 0 deletions test/jest/RaidenClient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,45 @@ const getValidTokenPaymentResponse = () => {
};
};

const channelBalance1 = 25000000;
const channelBalance2 = 5000000;
const channelBalanceTokenAddress = '0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8';
const getChannelsResponse = [
{
token_network_identifier: '0xE5637F0103794C7e05469A9964E4563089a5E6f2',
channel_identifier: 1,
partner_address: '0x61C808D82A3Ac53231750daDc13c777b59310bD9',
token_address: channelBalanceTokenAddress,
balance: channelBalance1,
total_deposit: 35000000,
state: 'opened',
settle_timeout: 100,
reveal_timeout: 30,
},
{
token_network_identifier: '0xE5637F0103794C7e05469A9964E4563089a5E6f2',
channel_identifier: 2,
partner_address: '0x2A4722462bb06511b036F00C7EbF938B2377F446',
token_address: channelBalanceTokenAddress,
balance: channelBalance2,
total_deposit: 35000000,
state: 'opened',
settle_timeout: 100,
reveal_timeout: 30,
},
{
token_network_identifier: '0xE5637F0103794C7e05469A9964E4563089a5E6f2',
channel_identifier: 3,
partner_address: '0x3b1c3C1568C848b3C12c88e2aF5E5CAa0b62071A',
token_address: channelBalanceTokenAddress,
balance: 1000000,
total_deposit: 35000000,
state: 'closed',
settle_timeout: 100,
reveal_timeout: 30,
},
];

const getValidDeal = () => {
return {
proposedQuantity: 10000,
Expand Down Expand Up @@ -93,4 +132,12 @@ describe('RaidenClient', () => {
.rejects.toMatchSnapshot();
});

test('channelBalance calculates the total balance of open channels for a currency', async () => {
raiden = new RaidenClient(config, raidenLogger);
await raiden.init();
raiden.tokenAddresses.get = jest.fn().mockReturnValue(channelBalanceTokenAddress);
raiden['getChannels'] = jest.fn()
.mockReturnValue(Promise.resolve(getChannelsResponse));
await expect(raiden.channelBalance('ABC')).resolves.toHaveProperty('balance', channelBalance1 + channelBalance2);
});
});

0 comments on commit cc8e89f

Please sign in to comment.