Merge pull request #214 from 67P/chore/remove_last_ethereum_bits
Remove mentions of Ethereum from UI and code, refactor wallet connect
This commit was merged in pull request #214.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<form onsubmit={{action "submit"}}>
|
<form onsubmit={{action "submit"}}>
|
||||||
<p>
|
<p>
|
||||||
<label for="c-account">Ethereum account</label>
|
<label for="c-account">Rootstock account</label>
|
||||||
<Input @type="text"
|
<Input @type="text"
|
||||||
@value={{this.account}}
|
@value={{this.account}}
|
||||||
name="account" id="c-account"
|
name="account" id="c-account"
|
||||||
|
|||||||
@@ -1,45 +1,37 @@
|
|||||||
import Component from '@ember/component';
|
import Component from '@glimmer/component';
|
||||||
|
import { tracked } from '@glimmer/tracking';
|
||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
import { computed } from '@ember/object';
|
import { action } from '@ember/object';
|
||||||
import { isPresent } from '@ember/utils';
|
import { isPresent } from '@ember/utils';
|
||||||
|
|
||||||
export default Component.extend({
|
export default class TopbarAccountPanelComponent extends Component {
|
||||||
|
@service router;
|
||||||
|
@service kredits;
|
||||||
|
|
||||||
tagName: '',
|
@tracked setupInProgress = false;
|
||||||
|
|
||||||
kredits: service(),
|
get userHasWallet () {
|
||||||
router: service(),
|
|
||||||
|
|
||||||
setupInProgress: false,
|
|
||||||
|
|
||||||
userHasEthereumWallet: computed(function() {
|
|
||||||
return isPresent(window.ethereum);
|
return isPresent(window.ethereum);
|
||||||
}),
|
|
||||||
|
|
||||||
showConnectButton: computed('userHasEthereumWallet',
|
|
||||||
'kredits.hasAccounts', function() {
|
|
||||||
return this.userHasEthereumWallet &&
|
|
||||||
!this.kredits.hasAccounts;
|
|
||||||
}),
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
|
|
||||||
signup() {
|
|
||||||
this.router.transitionTo('signup');
|
|
||||||
},
|
|
||||||
|
|
||||||
async connectAccount() {
|
|
||||||
try {
|
|
||||||
await window.ethereum.enable();
|
|
||||||
this.set('setupInProgress', true);
|
|
||||||
await this.kredits.setup();
|
|
||||||
this.set('setupInProgress', false);
|
|
||||||
} catch (error) {
|
|
||||||
this.set('setupInProgress', false);
|
|
||||||
console.log('Opening Ethereum wallet failed:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
get walletConnected () {
|
||||||
|
return this.userHasWallet && this.kredits.hasAccounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
get walletDisconnected () {
|
||||||
|
return this.userHasWallet && !this.kredits.hasAccounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
signup () {
|
||||||
|
this.router.transitionTo('signup');
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
async connectWallet () {
|
||||||
|
this.setupInProgress = true;
|
||||||
|
await this.kredits.connectWallet();
|
||||||
|
this.setupInProgress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,16 +2,15 @@
|
|||||||
{{#if this.setupInProgress}}
|
{{#if this.setupInProgress}}
|
||||||
Connecting account...
|
Connecting account...
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if (and this.kredits.hasAccounts this.kredits.currentUser)}}
|
{{#if (and this.walletConnected this.kredits.currentUser)}}
|
||||||
{{this.kredits.currentUser.name}}
|
{{this.kredits.currentUser.name}}
|
||||||
{{#if this.kredits.currentUserIsCore}}
|
|
||||||
<span class="core-flag">(core)</span>
|
|
||||||
{{/if}}
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="anonymous">Anonymous</span>
|
<span class="anonymous">Anonymous</span>
|
||||||
<button onclick={{action "signup"}} class="small" type="button">Sign up</button>
|
<button onclick={{action "signup"}} id="signup"
|
||||||
{{#if this.showConnectButton}}
|
class="small" type="button">Sign up</button>
|
||||||
<button onclick={{action "connectAccount"}} class="small green" type="button">Connect account</button>
|
{{#if this.walletDisconnected}}
|
||||||
|
<button onclick={{action "connectWallet"}} id="connect"
|
||||||
|
class="small green" type="button">Connect wallet</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import Controller from '@ember/controller';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import { action } from '@ember/object';
|
||||||
|
import { tracked } from '@glimmer/tracking';
|
||||||
|
import config from 'kredits-web/config/environment';
|
||||||
|
import { isAddress } from 'web3-utils';
|
||||||
|
|
||||||
|
export default class AccountController extends Controller {
|
||||||
|
@service kredits;
|
||||||
|
|
||||||
|
@tracked accountAddress = null;
|
||||||
|
|
||||||
|
get isValidEthAccount () {
|
||||||
|
return isAddress(this.accountAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
get signupButtonDisabled () {
|
||||||
|
return !this.isValidEthAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
completeSignup () {
|
||||||
|
const payload = {
|
||||||
|
accessToken: this.kredits.githubAccessToken,
|
||||||
|
account: this.accountAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(config.githubSignupUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
})
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.error) {
|
||||||
|
alert('Creating profile failed. We have been notified about this error and will take a look soon. Sorry!');
|
||||||
|
console.warn('Creating contributor profile failed:',
|
||||||
|
JSON.parse(data.error.body).error.message)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
console.log('[signup/account] Created contributor:', data);
|
||||||
|
|
||||||
|
this.kredits.githubAccessToken = null;
|
||||||
|
this.accountAddress = null;
|
||||||
|
|
||||||
|
this.transitionToRoute('signup.complete');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import Controller from '@ember/controller';
|
|
||||||
import { computed } from '@ember/object';
|
|
||||||
import { alias, not } from '@ember/object/computed';
|
|
||||||
import { isAddress } from 'web3-utils';
|
|
||||||
import { inject as service } from '@ember/service';
|
|
||||||
import config from 'kredits-web/config/environment';
|
|
||||||
|
|
||||||
export default Controller.extend({
|
|
||||||
|
|
||||||
kredits: service(),
|
|
||||||
|
|
||||||
ethAddress: null,
|
|
||||||
githubAccessToken: alias('kredits.githubAccessToken'),
|
|
||||||
|
|
||||||
isValidEthAccount: computed('ethAddress', function() {
|
|
||||||
return isAddress(this.ethAddress);
|
|
||||||
}),
|
|
||||||
|
|
||||||
signupButtonDisabled: not('isValidEthAccount'),
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
|
|
||||||
completeSignup () {
|
|
||||||
const payload = {
|
|
||||||
accessToken: this.githubAccessToken,
|
|
||||||
account: this.ethAddress
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch(config.githubSignupUrl, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(payload)
|
|
||||||
})
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(data => {
|
|
||||||
console.log('Created contributor:', data);
|
|
||||||
|
|
||||||
this.setProperties({
|
|
||||||
githubAccessToken: null,
|
|
||||||
ethAddress: null
|
|
||||||
});
|
|
||||||
|
|
||||||
this.transitionToRoute('signup.complete');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
import Controller from '@ember/controller';
|
import Controller from '@ember/controller';
|
||||||
|
import { action } from '@ember/object';
|
||||||
import config from 'kredits-web/config/environment';
|
import config from 'kredits-web/config/environment';
|
||||||
|
|
||||||
export default Controller.extend({
|
export default class IndexController extends Controller {
|
||||||
|
|
||||||
actions: {
|
|
||||||
|
|
||||||
connectGithub () {
|
|
||||||
window.location = config.githubConnectUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@action
|
||||||
|
connectGithub () {
|
||||||
|
window.location = config.githubConnectUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ Router.map(function() {
|
|||||||
});
|
});
|
||||||
this.route('signup', function() {
|
this.route('signup', function() {
|
||||||
this.route('github');
|
this.route('github');
|
||||||
this.route('eth-account');
|
this.route('account');
|
||||||
this.route('complete');
|
this.route('complete');
|
||||||
});
|
});
|
||||||
this.route('budget', function() {
|
this.route('budget', function() {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import Route from '@ember/routing/route';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import { isEmpty } from '@ember/utils';
|
||||||
|
|
||||||
|
export default class SignupAccountRoute extends Route {
|
||||||
|
@service kredits;
|
||||||
|
|
||||||
|
async setupController (controller) {
|
||||||
|
if (!window.ethereum) return;
|
||||||
|
|
||||||
|
if (this.kredits.hasAccounts) {
|
||||||
|
controller.accountAddress = this.kredits.currentUserAccounts.firstObject;
|
||||||
|
} else {
|
||||||
|
return this.kredits.connectWallet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
redirect () {
|
||||||
|
if (isEmpty(this.kredits.githubAccessToken)) {
|
||||||
|
this.transitionTo('signup.index');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import Route from '@ember/routing/route';
|
|
||||||
import { inject as service } from '@ember/service';
|
|
||||||
import { isEmpty } from '@ember/utils';
|
|
||||||
|
|
||||||
export default Route.extend({
|
|
||||||
|
|
||||||
kredits: service(),
|
|
||||||
|
|
||||||
redirect () {
|
|
||||||
this._super(...arguments);
|
|
||||||
|
|
||||||
if (isEmpty(this.kredits.githubAccessToken)) {
|
|
||||||
this.transitionTo('signup.index');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -22,7 +22,7 @@ export default Route.extend({
|
|||||||
|
|
||||||
this.kredits.set('githubAccessToken', accessToken);
|
this.kredits.set('githubAccessToken', accessToken);
|
||||||
|
|
||||||
this.transitionTo('signup.eth-account');
|
this.transitionTo('signup.account');
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import config from 'kredits-web/config/environment';
|
|||||||
|
|
||||||
function createStore(name) {
|
function createStore(name) {
|
||||||
let networkName;
|
let networkName;
|
||||||
if (config.web3RequiredNetworkName) {
|
if (config.web3NetworkName) {
|
||||||
networkName = config.web3RequiredNetworkName.toLocaleLowerCase().replace(' ', '-');
|
networkName = config.web3NetworkName.toLocaleLowerCase().replace(' ', '-');
|
||||||
} else {
|
} else {
|
||||||
networkName = 'custom';
|
networkName = 'custom';
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-24
@@ -5,7 +5,7 @@ import Service from '@ember/service';
|
|||||||
import EmberObject from '@ember/object';
|
import EmberObject from '@ember/object';
|
||||||
import { computed } from '@ember/object';
|
import { computed } from '@ember/object';
|
||||||
import { alias, filterBy, notEmpty, sort } from '@ember/object/computed';
|
import { alias, filterBy, notEmpty, sort } from '@ember/object/computed';
|
||||||
import { isEmpty, isPresent } from '@ember/utils';
|
import { isEmpty } from '@ember/utils';
|
||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
import { task, taskGroup } from 'ember-concurrency';
|
import { task, taskGroup } from 'ember-concurrency';
|
||||||
@@ -15,6 +15,7 @@ import processContributorData from 'kredits-web/utils/process-contributor-data';
|
|||||||
import processContributionData from 'kredits-web/utils/process-contribution-data';
|
import processContributionData from 'kredits-web/utils/process-contribution-data';
|
||||||
import processReimbursementData from 'kredits-web/utils/process-reimbursement-data';
|
import processReimbursementData from 'kredits-web/utils/process-reimbursement-data';
|
||||||
import formatKredits from 'kredits-web/utils/format-kredits';
|
import formatKredits from 'kredits-web/utils/format-kredits';
|
||||||
|
import switchNetwork from 'kredits-web/utils/switch-network';
|
||||||
|
|
||||||
import config from 'kredits-web/config/environment';
|
import config from 'kredits-web/config/environment';
|
||||||
import Contributor from 'kredits-web/models/contributor';
|
import Contributor from 'kredits-web/models/contributor';
|
||||||
@@ -55,6 +56,21 @@ export default Service.extend({
|
|||||||
this.set('contributors', []);
|
this.set('contributors', []);
|
||||||
this.set('contributions', []);
|
this.set('contributions', []);
|
||||||
this.set('reimbursements', []);
|
this.set('reimbursements', []);
|
||||||
|
|
||||||
|
if (window.ethereum) {
|
||||||
|
window.ethereum.on('chainChanged', this.handleUserChainChanged);
|
||||||
|
window.ethereum.on('accountsChanged', this.handleAccountsChanged);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleUserChainChanged (chainId) {
|
||||||
|
console.log('User-provided chain ID changed to', chainId);
|
||||||
|
window.location.reload();
|
||||||
|
},
|
||||||
|
|
||||||
|
handleAccountsChanged (accounts) {
|
||||||
|
console.log('User-provided accounts changed to', accounts);
|
||||||
|
window.location.reload();
|
||||||
},
|
},
|
||||||
|
|
||||||
// This is called in the application route's beforeModel(). So it is
|
// This is called in the application route's beforeModel(). So it is
|
||||||
@@ -64,7 +80,7 @@ export default Service.extend({
|
|||||||
let ethProvider;
|
let ethProvider;
|
||||||
|
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
function instantiateWithoutAccount () {
|
function instantiateWithoutWallet () {
|
||||||
console.debug('[kredits] Creating new instance from npm module class');
|
console.debug('[kredits] Creating new instance from npm module class');
|
||||||
console.debug(`[kredits] providerURL: ${config.web3ProviderUrl}`);
|
console.debug(`[kredits] providerURL: ${config.web3ProviderUrl}`);
|
||||||
ethProvider = new ethers.providers.JsonRpcProvider(config.web3ProviderUrl);
|
ethProvider = new ethers.providers.JsonRpcProvider(config.web3ProviderUrl);
|
||||||
@@ -74,44 +90,50 @@ export default Service.extend({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function instantiateWithAccount (web3Provider, context) {
|
async function instantiateWithWallet (web3Provider, context) {
|
||||||
console.debug('[kredits] Using user-provided Web3 instance, e.g. from Metamask');
|
console.debug('[kredits] Using user-provided Web3 instance, e.g. from Metamask');
|
||||||
ethProvider = new ethers.providers.Web3Provider(web3Provider);
|
ethProvider = new ethers.providers.Web3Provider(web3Provider);
|
||||||
|
const network = await ethProvider.getNetwork();
|
||||||
|
const accounts = await ethProvider.listAccounts();
|
||||||
|
const chainId = config.web3ChainId;
|
||||||
|
|
||||||
const network = await ethProvider.getNetwork();
|
if (isEmpty(accounts)) return instantiateWithoutWallet();
|
||||||
if (isPresent(config.web3RequiredChainId) &&
|
|
||||||
network.chainId !== config.web3RequiredChainId) {
|
|
||||||
return instantiateWithoutAccount();
|
|
||||||
}
|
|
||||||
|
|
||||||
ethProvider.listAccounts().then(accounts => {
|
if (network.chainId !== chainId) {
|
||||||
|
return switchNetwork();
|
||||||
|
} else {
|
||||||
context.set('currentUserAccounts', accounts);
|
context.set('currentUserAccounts', accounts);
|
||||||
const ethSigner = accounts.length === 0 ? null : ethProvider.getSigner();
|
const ethSigner = accounts.length === 0 ? null : ethProvider.getSigner();
|
||||||
resolve({
|
resolve({
|
||||||
ethProvider,
|
ethProvider,
|
||||||
ethSigner
|
ethSigner
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.ethereum) {
|
if (window.ethereum) {
|
||||||
if (window.ethereum.isConnected()) {
|
instantiateWithWallet(window.ethereum, this);
|
||||||
instantiateWithAccount(window.ethereum, this);
|
} else {
|
||||||
} else {
|
instantiateWithoutWallet();
|
||||||
instantiateWithoutAccount();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Legacy dapp browsers...
|
|
||||||
else if (window.web3) {
|
|
||||||
instantiateWithAccount(window.web3.currentProvider, this);
|
|
||||||
}
|
|
||||||
// Non-dapp browsers...
|
|
||||||
else {
|
|
||||||
instantiateWithoutAccount();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async connectWallet () {
|
||||||
|
const provider = new ethers.providers.Web3Provider(window.ethereum);
|
||||||
|
const network = await provider.getNetwork();
|
||||||
|
const chainId = config.web3ChainId;
|
||||||
|
const chainIdHex = `0x${Number(chainId).toString(16)}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await window.ethereum.request({ method: 'eth_requestAccounts' });
|
||||||
|
if (network.chainId !== chainId) await switchNetwork(chainIdHex);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Connecting wallet failed:', err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async setup () {
|
async setup () {
|
||||||
const kredits = await this.getEthProvider().then(providerAndSigner => {
|
const kredits = await this.getEthProvider().then(providerAndSigner => {
|
||||||
return new Kredits(providerAndSigner.ethProvider, providerAndSigner.ethSigner, {
|
return new Kredits(providerAndSigner.ethProvider, providerAndSigner.ethSigner, {
|
||||||
|
|||||||
+30
-26
@@ -45,14 +45,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="contributions-by-type">
|
{{#if this.contributionsConfirmed}}
|
||||||
<header>
|
<section id="contributions-by-type">
|
||||||
<h2>Contributions by type</h2>
|
<header>
|
||||||
</header>
|
<h2>Contributions by type</h2>
|
||||||
<div class="content">
|
</header>
|
||||||
<ChartContributionsByType @contributions={{this.contributions}} />
|
<div class="content">
|
||||||
</div>
|
<ChartContributionsByType @contributions={{this.contributions}} />
|
||||||
</section>
|
</div>
|
||||||
|
</section>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="contributions">
|
<div id="contributions">
|
||||||
@@ -87,24 +89,26 @@
|
|||||||
</section>
|
</section>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<section id="contributions-confirmed">
|
{{#if this.contributionsConfirmed}}
|
||||||
<header class="with-nav">
|
<section id="contributions-confirmed">
|
||||||
<h2>Confirmed Contributions</h2>
|
<header class="with-nav">
|
||||||
<nav>
|
<h2>Confirmed Contributions</h2>
|
||||||
<button type="button"
|
<nav>
|
||||||
onclick={{action "toggleQuickFilterConfirmed"}}
|
<button type="button"
|
||||||
class="small {{if this.showQuickFilterConfirmed "active"}}">
|
onclick={{action "toggleQuickFilterConfirmed"}}
|
||||||
filter
|
class="small {{if this.showQuickFilterConfirmed "active"}}">
|
||||||
</button>
|
filter
|
||||||
</nav>
|
</button>
|
||||||
</header>
|
</nav>
|
||||||
<div class="content">
|
</header>
|
||||||
<ContributionList @contributions={{this.contributionsConfirmedSorted}}
|
<div class="content">
|
||||||
@vetoContribution={{action "vetoContribution"}}
|
<ContributionList @contributions={{this.contributionsConfirmedSorted}}
|
||||||
@selectedContributionId={{this.selectedContributionId}}
|
@vetoContribution={{action "vetoContribution"}}
|
||||||
@showQuickFilter={{this.showQuickFilterConfirmed}} />
|
@selectedContributionId={{this.selectedContributionId}}
|
||||||
</div>
|
@showQuickFilter={{this.showQuickFilterConfirmed}} />
|
||||||
</section>
|
</div>
|
||||||
|
</section>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if this.showFullContributionSync}}
|
{{#if this.showFullContributionSync}}
|
||||||
<section id="sync-all-contributions">
|
<section id="sync-all-contributions">
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<p>
|
<p>
|
||||||
<a href="https://rinkeby.etherscan.io/address/{{this.model.account}}" class="button small" target="_blank" rel="noopener noreferrer">Inspect Ethereum transactions</a>
|
<a href="https://explorer.testnet.rsk.co/address/{{this.model.account}}" class="button small" target="_blank" rel="noopener noreferrer">Inspect Rootstock transactions</a>
|
||||||
{{#if this.model.ipfsHash}}
|
{{#if this.model.ipfsHash}}
|
||||||
<a href="{{this.ipfsGatewayUrl}}/{{this.model.ipfsHash}}" class="button small" target="_blank" rel="noopener noreferrer">Inspect IPFS profile</a>
|
<a href="{{this.ipfsGatewayUrl}}/{{this.model.ipfsHash}}" class="button small" target="_blank" rel="noopener noreferrer">Inspect IPFS profile</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<header>
|
||||||
|
<h2>Complete your contributor profile</h2>
|
||||||
|
</header>
|
||||||
|
<div class="content text-lg">
|
||||||
|
<p class="mb-8">
|
||||||
|
Kredits allow you to to earn rewards for your contributions, in the form of
|
||||||
|
dynamic open-source grants. As a regular contributor, you can also take
|
||||||
|
part in the community's project governance and finances.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In order to interact with the system you will need a
|
||||||
|
<a href="https://rootstock.io" target="_blank" rel="noopener noreferrer">Rootstock</a>
|
||||||
|
wallet/account.
|
||||||
|
</p>
|
||||||
|
<form>
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
Rootstock address:<br>
|
||||||
|
<Input @type="text" @value={{this.accountAddress}} placeholder="0xF18E631Ea191aE4ebE70046Fcb01a436554421BA4" class={{if this.isValidEthAccount "valid" ""}} />
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
<p class="actions">
|
||||||
|
<button {{on "click" (fn this.completeSignup)}}
|
||||||
|
disabled={{this.signupButtonDisabled}}
|
||||||
|
type="button">
|
||||||
|
Complete my profile
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
@@ -7,7 +7,8 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Why not say hi to your fellow contributors
|
Why not say hi to your fellow contributors
|
||||||
<a href="https://wiki.kosmos.org/Main_Page#Community_.2F_Getting_in_touch_.2F_Getting_involved">in one of our chat rooms</a>?.
|
<a href="https://wiki.kosmos.org/Main_Page#Community_.2F_Getting_in_touch_.2F_Getting_involved"
|
||||||
|
target="_blank" rel="noopener noreferrer">in one of our chat rooms</a>?.
|
||||||
</p>
|
</p>
|
||||||
<p class="actions">
|
<p class="actions">
|
||||||
<LinkTo @route="dashboard" class="button small">Return to dashboard</LinkTo>
|
<LinkTo @route="dashboard" class="button small">Return to dashboard</LinkTo>
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
<header>
|
|
||||||
<h2>Complete your contributor profile</h2>
|
|
||||||
</header>
|
|
||||||
<div class="content text-lg">
|
|
||||||
<p class="mb-8">
|
|
||||||
Kredits allow you to take part in project governance, and to earn rewards for
|
|
||||||
your contributions. For both, you will need an Ethereum wallet/account.
|
|
||||||
</p>
|
|
||||||
<form>
|
|
||||||
<p>
|
|
||||||
<label>
|
|
||||||
Ethereum account:<br>
|
|
||||||
<Input @type="text" @value={{this.ethAddress}} placeholder="0xF18E631Ea191aE4ebE70046Fcb01a436554421BA4" class={{if this.isValidEthAccount "valid" ""}} />
|
|
||||||
</label>
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
<p class="actions">
|
|
||||||
<button disabled={{this.signupButtonDisabled}}
|
|
||||||
onclick={{action "completeSignup"}}
|
|
||||||
type="button">
|
|
||||||
Complete my profile
|
|
||||||
</button>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import config from 'kredits-web/config/environment';
|
||||||
|
|
||||||
|
export default async function () {
|
||||||
|
const networkName = config.web3NetworkName;
|
||||||
|
const chainId = config.web3ChainId;
|
||||||
|
const chainIdHex = `0x${Number(chainId).toString(16)}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await window.ethereum.request({
|
||||||
|
method: 'wallet_switchEthereumChain',
|
||||||
|
params: [{ chainId: chainIdHex }]
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
// This error code indicates that the chain has not been added to MetaMask
|
||||||
|
if (err.code === 4902) {
|
||||||
|
await window.ethereum.request({
|
||||||
|
method: 'wallet_addEthereumChain',
|
||||||
|
params: [{
|
||||||
|
chainId: chainIdHex,
|
||||||
|
chainName: networkName,
|
||||||
|
rpcUrls: [ config.web3ProviderUrl ],
|
||||||
|
nativeCurrency: { name: 'tRBTC', symbol: 'tRBTC', decimals: 18 }
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.warn('Failed to switch chains:', err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-5
@@ -26,11 +26,11 @@ module.exports = function(environment) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
web3ProviderUrl: 'https://rsk-testnet.kosmos.org',
|
web3ProviderUrl: 'https://rsk-testnet.kosmos.org',
|
||||||
web3RequiredChainId: 31,
|
web3ChainId: 31,
|
||||||
web3RequiredNetworkName: 'RSK Testnet',
|
web3NetworkName: 'RSK Testnet',
|
||||||
|
|
||||||
githubConnectUrl: 'https://hal8000.chat.kosmos.org/kredits/signup/connect/github',
|
githubConnectUrl: 'https://hal8000.kosmos.chat/kredits/signup/connect/github',
|
||||||
githubSignupUrl: 'https://hal8000.chat.kosmos.org/kredits/signup/github',
|
githubSignupUrl: 'https://hal8000.kosmos.chat/kredits/signup/github',
|
||||||
|
|
||||||
ipfs: {
|
ipfs: {
|
||||||
host: 'ipfs.kosmos.org',
|
host: 'ipfs.kosmos.org',
|
||||||
@@ -82,7 +82,12 @@ module.exports = function(environment) {
|
|||||||
|
|
||||||
if (process.env.WEB3_PROVIDER_URL) {
|
if (process.env.WEB3_PROVIDER_URL) {
|
||||||
ENV.web3ProviderUrl = process.env.WEB3_PROVIDER_URL;
|
ENV.web3ProviderUrl = process.env.WEB3_PROVIDER_URL;
|
||||||
ENV.web3RequiredChainId = null;
|
}
|
||||||
|
if (process.env.WEB3_CHAIN_ID) {
|
||||||
|
ENV.web3ChainId = parseInt(process.env.WEB3_CHAIN_ID);
|
||||||
|
}
|
||||||
|
if (process.env.WEB3_NETWORK_NAME) {
|
||||||
|
ENV.web3NetworkName = process.env.WEB3_NETWORK_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ENV;
|
return ENV;
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
"start": "ember serve",
|
"start": "ember serve",
|
||||||
"test": "npm-run-all lint:* test:*",
|
"test": "npm-run-all lint:* test:*",
|
||||||
"test:ember": "ember test",
|
"test:ember": "ember test",
|
||||||
"start:local": "WEB3_PROVIDER_URL=http://localhost:8545 ember serve",
|
"start:local": "WEB3_PROVIDER_URL=http://localhost:8545 WEB3_CHAIN_ID=1337 WEB3_NETWORK_NAME='Hardhat Devchain' ember serve",
|
||||||
"build": "ember build --environment=production",
|
"build": "ember build --environment=production",
|
||||||
"build-prod": "rm -rf release/* && ember build -prod --output-path release",
|
"build-prod": "rm -rf release/* && ember build -prod --output-path release",
|
||||||
"preversion": "npm test",
|
"preversion": "npm test",
|
||||||
|
|||||||
@@ -3,37 +3,90 @@ import { setupRenderingTest } from 'ember-qunit';
|
|||||||
import { render } from '@ember/test-helpers';
|
import { render } from '@ember/test-helpers';
|
||||||
import hbs from 'htmlbars-inline-precompile';
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
|
||||||
|
function stubWalletApi () {
|
||||||
|
window.ethereum = {
|
||||||
|
on: function() { return true; },
|
||||||
|
request: function() { return Promise.resolve(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module('Integration | Component | topbar-account-panel', function(hooks) {
|
module('Integration | Component | topbar-account-panel', function(hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test('unknown user without wallet (or no permission to get wallet/account info)', async function(assert) {
|
test('Unknown user without wallet', async function(assert) {
|
||||||
await render(hbs`<TopbarAccountPanel />`);
|
await render(hbs`<TopbarAccountPanel />`);
|
||||||
|
|
||||||
assert.ok(this.element.textContent.trim().match(/^Anonymous/));
|
assert.ok(
|
||||||
|
this.element.textContent.trim().match(/^Anonymous/),
|
||||||
|
'shows current user as anonymous'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
this.element.querySelectorAll('button#signup').length, 1,
|
||||||
|
'signup button is visible'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
this.element.querySelectorAll('button#connect').length, 0,
|
||||||
|
'connect button is not visible'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('unknown user with Ethereum wallet', async function(assert) {
|
test('Unknown user with disconnected wallet', async function(assert) {
|
||||||
|
stubWalletApi();
|
||||||
|
let service = this.owner.lookup('service:kredits');
|
||||||
|
service.set('currentUserAccounts', []);
|
||||||
|
await render(hbs`<TopbarAccountPanel />`);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
this.element.textContent.trim().match(/^Anonymous/),
|
||||||
|
'shows current user as anonymous'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
this.element.querySelectorAll('button#signup').length, 1,
|
||||||
|
'signup button is visible'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
this.element.querySelectorAll('button#connect').length, 1,
|
||||||
|
'connect button is visible'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Unknown user with connected wallet', async function(assert) {
|
||||||
|
stubWalletApi();
|
||||||
let service = this.owner.lookup('service:kredits');
|
let service = this.owner.lookup('service:kredits');
|
||||||
service.set('currentUserAccounts', [{ foo: 'bar' }]);
|
service.set('currentUserAccounts', [{ foo: 'bar' }]);
|
||||||
await render(hbs`<TopbarAccountPanel />`);
|
await render(hbs`<TopbarAccountPanel />`);
|
||||||
|
|
||||||
assert.ok(this.element.textContent.trim().match(/^Anonymous/));
|
assert.ok(
|
||||||
|
this.element.textContent.trim().match(/^Anonymous/),
|
||||||
|
'shows current user as anonymous'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
this.element.querySelectorAll('button#signup').length, 1,
|
||||||
|
'signup button is visible'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
this.element.querySelectorAll('button#connect').length, 0,
|
||||||
|
'connect button is not visible'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('known contributor', async function(assert) {
|
test('Known contributor', async function(assert) {
|
||||||
|
stubWalletApi();
|
||||||
let service = this.owner.lookup('service:kredits');
|
let service = this.owner.lookup('service:kredits');
|
||||||
service.set('currentUserAccounts', [{ foo: 'bar' }]);
|
service.set('currentUserAccounts', [{ foo: 'bar' }]);
|
||||||
service.set('currentUser', {
|
service.set('currentUser', { name: 'Dorian Nakamoto', isCore: false });
|
||||||
name: 'Dorian Nakamoto',
|
|
||||||
isCore: false
|
|
||||||
});
|
|
||||||
await render(hbs`<TopbarAccountPanel />`);
|
await render(hbs`<TopbarAccountPanel />`);
|
||||||
|
|
||||||
assert.dom(this.element).hasText('Dorian Nakamoto');
|
assert.dom(this.element).hasText(
|
||||||
|
'Dorian Nakamoto', 'shows current user\'s name'
|
||||||
service.set('currentUser.isCore', true);
|
);
|
||||||
await render(hbs`<TopbarAccountPanel />`);
|
assert.equal(
|
||||||
|
this.element.querySelectorAll('button#signup').length, 0,
|
||||||
assert.equal(this.element.querySelectorAll('span.core-flag').length, 1);
|
'signup button is not visible'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
this.element.querySelectorAll('button#connect').length, 0,
|
||||||
|
'connect button is not visible'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
import { module, test } from 'qunit';
|
import { module, test } from 'qunit';
|
||||||
import { setupTest } from 'ember-qunit';
|
import { setupTest } from 'ember-qunit';
|
||||||
|
|
||||||
module('Unit | Route | signup/eth-account', function(hooks) {
|
module('Unit | Route | signup/account', function(hooks) {
|
||||||
setupTest(hooks);
|
setupTest(hooks);
|
||||||
|
|
||||||
test('it exists', function(assert) {
|
test('it exists', function(assert) {
|
||||||
let route = this.owner.lookup('route:signup/eth-account');
|
let route = this.owner.lookup('route:signup/account');
|
||||||
assert.ok(route);
|
assert.ok(route);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user