Load community funds balances from mainnet Gnosis Safe

This commit is contained in:
2020-08-13 00:27:40 +02:00
parent 52172ea065
commit dec71c6f4f
11 changed files with 375 additions and 24 deletions
@@ -0,0 +1,6 @@
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
export default class BudgetBalancesComponent extends Component {
@service communityFunds
}
@@ -0,0 +1,21 @@
<table>
<thead>
<tr>
<td>Token</td>
<td>Amount</td>
<td>Fiat value</td>
</tr>
</thead>
<tbody>
<tr>
<td>WBTC</td>
<td>{{this.communityFunds.balanceWBTC.balance}}</td>
<td>{{this.communityFunds.balanceWBTC.balanceUsd}} USD</td>
</tr>
<tr>
<td>ETH</td>
<td>{{this.communityFunds.balanceETH.balance}}</td>
<td>{{this.communityFunds.balanceETH.balanceUsd}} USD</td>
</tr>
</tbody>
</table>
+4 -2
View File
@@ -3,8 +3,8 @@ import { inject as service } from '@ember/service';
import { schedule } from '@ember/runloop';
export default class ApplicationRoute extends Route {
@service kredits;
@service communityFunds;
beforeModel(/* transition */) {
const kredits = this.kredits;
@@ -30,6 +30,8 @@ export default class ApplicationRoute extends Route {
schedule('afterRender', this.kredits.syncContributors,
this.kredits.syncContributors.perform);
}
}
schedule('afterRender', this.communityFunds.fetchBalances,
this.communityFunds.fetchBalances.perform);
}
}
+32
View File
@@ -0,0 +1,32 @@
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { task } from 'ember-concurrency-decorators';
import config from 'kredits-web/config/environment';
const txServiceBaseUrl = `${config.gnosisSafe.txServiceHost}/api/v1/safes/${config.gnosisSafe.address}`;
export default class CommunityFundsService extends Service {
@tracked balanceETH = { balance: 0, balanceUsd: 0, usdConversion: 0 };
@tracked balanceWBTC = { balance: 0, balanceUsd: 0, usdConversion: 0 };
@task
*fetchBalances () {
const uri = `${txServiceBaseUrl}/balances/usd/`;
yield fetch(uri).then(res => res.json())
.then(res => {
this.processBalances(res);
})
.catch(err => {
console.log(`[community-funds] Fetching balances failed:`);
console.error(err);
});
}
processBalances (res) {
// TODO proper selection/find
const { balance, balanceUsd, usdConversion } = res[0];
this.balanceETH = { balance, balanceUsd, usdConversion };
this.balanceWBTC = res[1];
}
}
+1 -1
View File
@@ -21,7 +21,7 @@ import Contributor from 'kredits-web/models/contributor';
import Contribution from 'kredits-web/models/contribution';
import Reimbursement from 'kredits-web/models/reimbursement';
// Lets us access the model classes dynamically
const models = { Contributor, Contribution, Reimbursement }
const models = { Contributor, Contribution, Reimbursement };
export default Service.extend({
+1 -21
View File
@@ -22,27 +22,7 @@
<h2>Community funds</h2>
</header>
<div class="content">
<table>
<thead>
<tr>
<td>Token</td>
<td>Amount</td>
<td>Fiat value</td>
</tr>
</thead>
<tbody>
<tr>
<td>WBTC</td>
<td>1.17215</td>
<td>11031.15 USD</td>
</tr>
<tr>
<td>ETH</td>
<td>0.5</td>
<td>115.60 USD</td>
</tr>
</tbody>
</table>
<BudgetBalances />
</div>
</section>
</div>
+5
View File
@@ -50,6 +50,11 @@ module.exports = function(environment) {
tokens: {
'WBTC': '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599'
},
gnosisSafe: {
txServiceHost: 'https://safe-transaction.mainnet.gnosis.io',
address: '0x9CC29b8373FF92B01C1f09F31B5DD862350c167E'
}
};
+266
View File
@@ -2582,6 +2582,15 @@
"integrity": "sha512-tGRdvgC9/QMQSuSuJV45xoyhI0Pzjm7A9o/MVVA3HakXIImJbbzx/k/6dO9CUEQXIyS2y0fW6C1XaYOG7rY0FQ==",
"dev": true
},
"@ember-decorators/utils": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@ember-decorators/utils/-/utils-6.1.1.tgz",
"integrity": "sha512-0KqnoeoLKb6AyoSU65TRF5T85wmS4uDn06oARddwNPxxf/lt5jQlh41uX3W7V/fWL9tPu8x1L1Vvpc80MN1+YA==",
"dev": true,
"requires": {
"ember-cli-babel": "^7.1.3"
}
},
"@ember/edition-utils": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ember/edition-utils/-/edition-utils-1.2.0.tgz",
@@ -11284,6 +11293,263 @@
"ember-maybe-import-regenerator": "^0.1.6"
}
},
"ember-concurrency-decorators": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ember-concurrency-decorators/-/ember-concurrency-decorators-2.0.1.tgz",
"integrity": "sha512-KJ8mCZxmvgalawh/zytURsc5ParNr9avPeCDR/mE7VQxWvITHtyAuYS2s1PPFQAQggTXTZYcGnfgzjn/cDHNMQ==",
"dev": true,
"requires": {
"@ember-decorators/utils": "^6.1.0",
"ember-cli-babel": "^7.19.0",
"ember-cli-htmlbars": "^4.3.1",
"ember-cli-typescript": "^3.1.4"
},
"dependencies": {
"@babel/helper-plugin-utils": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
"integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
"dev": true
},
"@babel/plugin-transform-typescript": {
"version": "7.8.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.7.tgz",
"integrity": "sha512-7O0UsPQVNKqpHeHLpfvOG4uXmlw+MOxYvUv6Otc9uH5SYMIxvF6eBdjkWvC3f9G+VXe0RsNExyAQBeTRug/wqQ==",
"dev": true,
"requires": {
"@babel/helper-create-class-features-plugin": "^7.8.3",
"@babel/helper-plugin-utils": "^7.8.3",
"@babel/plugin-syntax-typescript": "^7.8.3"
}
},
"babel-plugin-htmlbars-inline-precompile": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/babel-plugin-htmlbars-inline-precompile/-/babel-plugin-htmlbars-inline-precompile-3.2.0.tgz",
"integrity": "sha512-IUeZmgs9tMUGXYu1vfke5I18yYJFldFGdNFQOWslXTnDWXzpwPih7QFduUqvT+awDpDuNtXpdt5JAf43Q1Hhzg==",
"dev": true
},
"broccoli-persistent-filter": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/broccoli-persistent-filter/-/broccoli-persistent-filter-2.3.1.tgz",
"integrity": "sha512-hVsmIgCDrl2NFM+3Gs4Cr2TA6UPaIZip99hN8mtkaUPgM8UeVnCbxelCvBjUBHo0oaaqP5jzqqnRVvb568Yu5g==",
"dev": true,
"requires": {
"async-disk-cache": "^1.2.1",
"async-promise-queue": "^1.0.3",
"broccoli-plugin": "^1.0.0",
"fs-tree-diff": "^2.0.0",
"hash-for-dep": "^1.5.0",
"heimdalljs": "^0.2.1",
"heimdalljs-logger": "^0.1.7",
"mkdirp": "^0.5.1",
"promise-map-series": "^0.2.1",
"rimraf": "^2.6.1",
"rsvp": "^4.7.0",
"symlink-or-copy": "^1.0.1",
"sync-disk-cache": "^1.3.3",
"walk-sync": "^1.0.0"
},
"dependencies": {
"broccoli-plugin": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-1.3.1.tgz",
"integrity": "sha512-DW8XASZkmorp+q7J4EeDEZz+LoyKLAd2XZULXyD9l4m9/hAKV3vjHmB1kiUshcWAYMgTP1m2i4NnqCE/23h6AQ==",
"dev": true,
"requires": {
"promise-map-series": "^0.2.1",
"quick-temp": "^0.1.3",
"rimraf": "^2.3.4",
"symlink-or-copy": "^1.1.8"
}
},
"walk-sync": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/walk-sync/-/walk-sync-1.1.4.tgz",
"integrity": "sha512-nowc9thB/Jg0KW4TgxoRjLLYRPvl3DB/98S89r4ZcJqq2B0alNcKDh6pzLkBSkPMzRSMsJghJHQi79qw0YWEkA==",
"dev": true,
"requires": {
"@types/minimatch": "^3.0.3",
"ensure-posix-path": "^1.1.0",
"matcher-collection": "^1.1.1"
}
}
}
},
"broccoli-plugin": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-3.1.0.tgz",
"integrity": "sha512-7w7FP8WJYjLvb0eaw27LO678TGGaom++49O1VYIuzjhXjK5kn2+AMlDm7CaUFw4F7CLGoVQeZ84d8gICMJa4lA==",
"dev": true,
"requires": {
"broccoli-node-api": "^1.6.0",
"broccoli-output-wrapper": "^2.0.0",
"fs-merger": "^3.0.1",
"promise-map-series": "^0.2.1",
"quick-temp": "^0.1.3",
"rimraf": "^2.3.4",
"symlink-or-copy": "^1.1.8"
}
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"ember-cli-htmlbars": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/ember-cli-htmlbars/-/ember-cli-htmlbars-4.4.0.tgz",
"integrity": "sha512-ohgctqk7dXIZR4TgN0xRoUYltWhghFJgqmtuswQTpZ7p74RxI9PKx+E8WV/95mGcPzraesvMNBg5utQNvcqgNg==",
"dev": true,
"requires": {
"@ember/edition-utils": "^1.2.0",
"babel-plugin-htmlbars-inline-precompile": "^3.2.0",
"broccoli-debug": "^0.6.5",
"broccoli-persistent-filter": "^2.3.1",
"broccoli-plugin": "^3.1.0",
"common-tags": "^1.8.0",
"ember-cli-babel-plugin-helpers": "^1.1.0",
"fs-tree-diff": "^2.0.1",
"hash-for-dep": "^1.5.1",
"heimdalljs-logger": "^0.1.10",
"json-stable-stringify": "^1.0.1",
"semver": "^6.3.0",
"strip-bom": "^4.0.0",
"walk-sync": "^2.0.2"
}
},
"ember-cli-typescript": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-3.1.4.tgz",
"integrity": "sha512-HJ73kL45OGRmIkPhBNFt31I1SGUvdZND+LCH21+qpq3pPlFpJG8GORyXpP+2ze8PbnITNLzwe5AwUrpyuRswdQ==",
"dev": true,
"requires": {
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4",
"@babel/plugin-proposal-optional-chaining": "^7.6.0",
"@babel/plugin-transform-typescript": "~7.8.0",
"ansi-to-html": "^0.6.6",
"broccoli-stew": "^3.0.0",
"debug": "^4.0.0",
"ember-cli-babel-plugin-helpers": "^1.0.0",
"execa": "^3.0.0",
"fs-extra": "^8.0.0",
"resolve": "^1.5.0",
"rsvp": "^4.8.1",
"semver": "^6.3.0",
"stagehand": "^1.0.0",
"walk-sync": "^2.0.0"
}
},
"execa": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz",
"integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==",
"dev": true,
"requires": {
"cross-spawn": "^7.0.0",
"get-stream": "^5.0.0",
"human-signals": "^1.1.1",
"is-stream": "^2.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^4.0.0",
"onetime": "^5.1.0",
"p-finally": "^2.0.0",
"signal-exit": "^3.0.2",
"strip-final-newline": "^2.0.0"
}
},
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"dev": true,
"requires": {
"graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
},
"fs-tree-diff": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fs-tree-diff/-/fs-tree-diff-2.0.1.tgz",
"integrity": "sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A==",
"dev": true,
"requires": {
"@types/symlink-or-copy": "^1.2.0",
"heimdalljs-logger": "^0.1.7",
"object-assign": "^4.1.0",
"path-posix": "^1.0.0",
"symlink-or-copy": "^1.1.8"
}
},
"graceful-fs": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
"dev": true
},
"is-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
"dev": true
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
"dev": true,
"requires": {
"path-key": "^3.0.0"
}
},
"rsvp": {
"version": "4.8.5",
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==",
"dev": true
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
},
"walk-sync": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/walk-sync/-/walk-sync-2.2.0.tgz",
"integrity": "sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg==",
"dev": true,
"requires": {
"@types/minimatch": "^3.0.3",
"ensure-posix-path": "^1.1.0",
"matcher-collection": "^2.0.0",
"minimatch": "^3.0.4"
},
"dependencies": {
"matcher-collection": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/matcher-collection/-/matcher-collection-2.0.1.tgz",
"integrity": "sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ==",
"dev": true,
"requires": {
"@types/minimatch": "^3.0.3",
"minimatch": "^3.0.2"
}
}
}
}
}
},
"ember-diff-attrs": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/ember-diff-attrs/-/ember-diff-attrs-0.2.2.tgz",
+1
View File
@@ -49,6 +49,7 @@
"ember-cli-sri": "^2.1.1",
"ember-cli-uglify": "^3.0.0",
"ember-concurrency": "^1.1.7",
"ember-concurrency-decorators": "^2.0.1",
"ember-export-application-global": "^2.0.1",
"ember-fetch": "^8.0.1",
"ember-flatpickr": "^2.16.2",
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | budget-balances', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<BudgetBalances />`);
assert.equal(this.element.textContent.trim(), '');
// Template block usage:
await render(hbs`
<BudgetBalances>
template block text
</BudgetBalances>
`);
assert.equal(this.element.textContent.trim(), 'template block text');
});
});
@@ -0,0 +1,12 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Service | community-funds', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let service = this.owner.lookup('service:community-funds');
assert.ok(service);
});
});