Skip to content
This repository has been archived by the owner on Jul 22, 2020. It is now read-only.

Commit

Permalink
WIP: account balance multi-get API (#77)
Browse files Browse the repository at this point in the history
* feat: account balance multi-get API
* feat: remove console logs
* feat: remove console log straggler
* chore: lint
* feat: implement multi program ids
* chore: lint
* Finish v0.14 upgrade (#1)
* Revert "fix: adapt to insruction.key field changes"
This reverts commit a62f016.
* fix: Restore instruction length check
* fix: temporary fix, adapt to insruction.key field changes
  • Loading branch information
sunnygleason authored Apr 30, 2019
1 parent 65a50cd commit 8c14aa4
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 29 deletions.
52 changes: 51 additions & 1 deletion api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,25 @@
import express from 'express';
import nocache from 'nocache';
import cors from 'cors';
import expressWs from 'express-ws';
import {promisify} from 'util';
import redis from 'redis';
import WebSocket from 'ws';
import _ from 'lodash';
import './inbound-stream';
import expressWs from 'express-ws';
import geoip from 'geoip-lite';
import YAML from 'yaml';
import fs from 'fs';
import assert from 'assert';
import * as solanaWeb3 from '@solana/web3.js';

import config from './config';

//
// FIXME: make configurable
//
let FULLNODE_URL = 'http://localhost:8899';

const app = express();

const port = 3001;
Expand Down Expand Up @@ -369,4 +375,48 @@ app.get('/search/:id', (req, res) => {
sendSearchResults(req, res);
});

function sendAccountResult(req, res) {
if (!req.params.ids) {
// give up
res.status(404).send('{"error":"not_found"}\n');
return;
}

try {
let idsStr = req.params.ids;
let ids = idsStr.split(',');

let thePromises = _.map(ids, id => {
return new Promise(resolve => {
const connection = new solanaWeb3.Connection(FULLNODE_URL);
return connection
.getBalance(new solanaWeb3.PublicKey(id))
.then(balance => {
return resolve({id: id, balance: balance});
});
});
});

return Promise.all(thePromises).then(values => {
let consolidated = _.reduce(
values,
(a, v) => {
a[v.id] = v.balance;
return a;
},
{},
);

res.send(JSON.stringify(consolidated) + '\n');
});
} catch (err) {
res.status(500).send(`{"error":"server_error","err":"${err}"}\n`);
return;
}
}

app.get('/accts_bal/:ids', (req, res) => {
sendAccountResult(req, res);
});

app.listen(port, () => console.log(`Listening on port ${port}!`));
13 changes: 7 additions & 6 deletions api/inbound-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class BridgeFn {
let inst = {};

inst.keys = _.map(y.keys, z => {
return `${z.pubkey.toBase58()} (is_signer=${z.isSigner})`;
return z.pubkey.toBase58();
});
inst.program_id = y.programId.toBase58();
inst.data = b58e(y.data);
Expand Down Expand Up @@ -219,29 +219,30 @@ class RedisHandler {
},
]);

// append block hexHeight:dt:id to timeline
let txnMsg = [
message.h,
message.l,
message.s,
message.dt,
message.hash,
tx.id,
];
if (tx.instructions.length > 0) {
txnMsg.push(tx.instructions[0].program_id);
txnMsg.push(tx.instructions[0].keys.join(','));
let txInst = _.map(tx.instructions, i => {
return [i.program_id, i.keys.join(','), i.data].join('@');
}).join('|');
txnMsg.push(txInst);
} else {
// Transactions should always have at least one instruction. But if
// the Transaction was not deserialized correctly we could end up
// here.
txnMsg.push('');
txnMsg.push('');
}
txnMsg.push(tx.id);
txnMsg = txnMsg.join('#');

commands.push(['sadd', `!ent-txn:${message.hash}`, tx.id]);
commands.push(['lpush', '!txn-timeline', txnMsg]);

if (tx.instructions.length > 0) {
commands.push([
'lpush',
Expand Down
32 changes: 15 additions & 17 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,21 +307,10 @@ class App extends Component {
return;
}

let txnFun = v => {
let newObj = {};
let fields = v.split('#');

newObj.t = 'txn';
newObj.h = fields[0];
newObj.l = fields[1];
newObj.s = fields[2];
newObj.dt = fields[3];
newObj.entry_id = fields[4];
newObj.program_id = fields[5];
newObj.keys = fields[6].split(',');
newObj.id = fields[7];
let self = this;

return newObj;
let txnFun = v => {
return self.parseTransactionMessage(v);
};

this.getRemoteState(
Expand Down Expand Up @@ -439,16 +428,25 @@ class App extends Component {
parseTransactionMessage(message) {
let fields = message.split('#');

let instructions = _.map(fields[6].split('|'), i => {
let instParts = i.split('@');

return {
program_id: instParts[0],
keys: instParts[1].split(','),
data: instParts[2],
};
});

return {
t: 'txn',
h: parseInt(fields[0]),
l: fields[1],
s: parseInt(fields[2]),
dt: fields[3],
entry_id: fields[4],
program_id: fields[5],
keys: fields[6].split(','),
id: fields[7],
id: fields[5],
instructions,
};
}

Expand Down
28 changes: 23 additions & 5 deletions src/BxDataTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,21 @@ class BxDataTable extends React.Component {
renderTransactions() {
const {dataItems, noTitle} = this.props;

let collectProgramIds = tx => {
return _.chain(tx.instructions)
.map(x => x.program_id)
.uniq()
.value();
};

let collectKeys = tx => {
return _.chain(tx.instructions)
.map(x => x.keys)
.flatten()
.uniq()
.value();
};

return (
<Paper>
{!noTitle && (
Expand All @@ -86,7 +101,7 @@ class BxDataTable extends React.Component {
</div>
</TableCell>
<TableCell>
Program ID
Program ID(s)
<BxHelpLink text="Program" term="program-id" />
</TableCell>
<TableCell align="center">
Expand All @@ -102,17 +117,20 @@ class BxDataTable extends React.Component {
<TableCell component="th" scope="row">
<BxEntityLink txn={row.id} />
<br />
{_.map(row.keys, key => (
{_.map(collectKeys(row), key => (
<span key={key}>
<BxEntityLink acct_id={key} />
<span> </span>
</span>
))}
</TableCell>
<TableCell align="right" style={{verticalAlign: 'middle'}}>
<BxEntityLink prg_id={row.program_id} />
<br />
<span>&nbsp;</span>
{_.map(collectProgramIds(row), program_id => (
<span key={program_id}>
<BxEntityLink prg_id={program_id} />
<br />
</span>
))}
</TableCell>
<TableCell align="center">
{row.s}
Expand Down

0 comments on commit 8c14aa4

Please sign in to comment.