Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Telos Cloud Wallet (powered by Metakeep) #728

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ yarn-error.log*
*.ntvs*
*.njsproj
*.sln

.vscode
.env
7 changes: 3 additions & 4 deletions env.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ const sharedEnv = {
IMGUR_CLIENT_ID: 'b6f46df9d1da9d9',
EVM_CONTRACT: 'eosio.evm',
PROJECT_ID: '2392473d6d98499c7138cd2d705a791f',
METAKEEP_APP_ID_NATIVE: 'ad5e05fb-280a-41ae-b186-5a2654567b92',
METAKEEP_APP_ID_EVM: 'd190c88f-1bb5-4e16-bc48-96dbf33b77e0',
GOOGLE_APP_ID: '56634824599-ff3iu788c32c3s7ec65cs4bieop9gpgv.apps.googleusercontent.com',
};

const TESTNET = {
Expand All @@ -22,8 +25,6 @@ const TESTNET = {
HYPERION_ENDPOINT: 'https://testnet.telos.net',
NETWORK_EXPLORER: 'https://explorer-test.telos.net',
CHAIN_NAME: 'telos-testnet',
OREID_APP_ID: 't_75a4d9233ec441d18c4221e92b379197',
OREID_APP_ID_NATIVE: 't_a61e9926d5204387a9ac113dfce7cbc5',
};

const MAINNET = {
Expand All @@ -37,8 +38,6 @@ const MAINNET = {
HYPERION_ENDPOINT: 'https://mainnet.telos.net',
NETWORK_EXPLORER: 'https://explorer.telos.net',
CHAIN_NAME: 'telos',
OREID_APP_ID: 'p_e5b81fcc20a04339993b0cc80df7e3fd',
OREID_APP_ID_NATIVE: 'p_751f87258d5b40998b55c626d612fd4e',
};

const env = process.env.NETWORK === 'mainnet' ? MAINNET : TESTNET;
Expand Down
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,19 @@
"eosjs": "^21.0.3",
"eosjs-ecc": "^4.0.7",
"erc-20-abi": "^1.0.0",
"ethers": "^5.5.1",
"ethers": "5.7.0",
"jdenticon": "^3.1.1",
"metakeep": "^2.2.0",
"mitt": "^3.0.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"numeral": "^2.0.6",
"oreid-js": "^4.7.1",
"oreid-webpopup": "^2.4.0",
"pinia": "^2.0.33",
"ptokens": "^0.14.0",
"qrcanvas-vue": "^3.0.0",
"qrious": "4.0.2",
"quasar": "2",
"rxjs": "^7.8.0",
"ual-anchor": "^1.1.2",
"ual-oreid": "^1.0.0",
"ual-wombat": "^0.3.3",
"universal-authenticator-library": "^0.3.0",
"vue": "3",
Expand Down
23 changes: 10 additions & 13 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
<script lang="ts">
import { getAntelope, useChainStore } from 'src/antelope';
import { useChainStore } from 'src/antelope';
import EVMChainSettings from 'src/antelope/chains/EVMChainSettings';
import { TELOS_CHAIN_IDS } from 'src/antelope/chains/chain-constants';
import packageInfo from '../package.json';
import { defineComponent } from 'vue';

export const isTodayBeforeTelosCloudDown = new Date().getTime() < new Date('2023-12-31').getTime();

export default defineComponent({
name: 'App',
created() {
Expand Down Expand Up @@ -44,16 +42,15 @@ export default defineComponent({
}
},
mounted() {
const chainSettings = useChainStore().currentChain.settings as EVMChainSettings;
// if the organization using this application is Telos, import Fathom analytics
if (TELOS_CHAIN_IDS.includes(chainSettings.getChainId())) {
const script = document.createElement('script');
script.src = 'https://cdn.usefathom.com/script.js';
script.dataset.site = 'ISPYEAKT';
script.dataset.spa = 'auto';
script.defer = true;
document.body.appendChild(script);
}

// Telos Wallet allows users to switch between Telos Zero and Telos EVM.
// The loading of this script should be independent of the chain the user is on.
const script = document.createElement('script');
script.src = 'https://cdn.usefathom.com/script.js';
script.dataset.site = 'ISPYEAKT';
script.dataset.spa = 'auto';
script.defer = true;
document.body.appendChild(script);
Comment on lines +48 to +53
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ezra-sg, this code was inside an if and the condition was that the chain used is EVM.

I had a lot of problems related to the chain being set (especially on auto-login situations where telos-evm is set because of the UI and then the telos-zero is set because the user was previously logged in telos zero).

What I need to know is if it is safe to remove that condition and have this code executed always.

},
});
</script>
Expand Down
2 changes: 0 additions & 2 deletions src/antelope/chains/chain-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ export const TELOS_ANALYTICS_EVENT_NAMES = {
loginFailedMetamask: 'Login Failed - Metamask',
loginSuccessfulSafepal: 'Login Successful - Safepal',
loginFailedSafepal: 'Login Failed - Safepal',
loginSuccessfulOreId: 'Login Successful - OreId',
loginFailedOreId: 'Login Failed - OreId',
loginFailedWalletConnect: 'Login Failed - WalletConnect',
loginSuccessfulWalletConnect: 'Login Successful - WalletConnect',
loginSuccessfulBrave: 'Login Successful - Brave',
Expand Down
5 changes: 0 additions & 5 deletions src/antelope/config/AntelopeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ export interface ComplexMessage {
text: string,
}

export const chainNetworkNames: Record<string, string> = {
telos: 'telos-evm',
'telos-testnet': 'telos-evm-testnet',
};

export const errorToString = (error: unknown) =>
getAntelope().config.errorToStringHandler(error);

Expand Down
13 changes: 1 addition & 12 deletions src/antelope/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { App, toRaw } from 'vue';
import { BehaviorSubject, Subject } from 'rxjs';
import { Store } from 'pinia';

import { AntelopeConfig, AntelopeDebug, chainNetworkNames } from 'src/antelope/config';
import { AntelopeConfig, AntelopeDebug } from 'src/antelope/config';
import installPinia from 'src/antelope/stores';

import { ChainModel } from 'src/antelope/stores/chain';
Expand Down Expand Up @@ -75,17 +75,6 @@ export class Antelope {
}
});

const chainStore = useChainStore();

if (!chainStore.currentChain) {
if (!process.env.CHAIN_NAME) {
console.error('No chain name specified in environment config; the application will not run correctly');
} else {
const network: string = chainNetworkNames[process.env.CHAIN_NAME];
chainStore.setChain(CURRENT_CONTEXT, network);
}
}

// Initializing store
stores.user.loadUsers();
}
Expand Down
22 changes: 6 additions & 16 deletions src/antelope/stores/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { initFuelUserWrapper } from 'src/api/fuel';
import { createTraceFunction, errorToString } from 'src/antelope/config';
import NativeChainSettings from 'src/antelope/chains/NativeChainSettings';
import {
Action,
Label,
NativeTransactionResponse,
addressString,
Expand All @@ -29,7 +28,6 @@ import { EVMAuthenticator } from 'src/antelope/wallets';
import { truncateAddress } from 'src/antelope/stores/utils/text-utils';
import { toRaw } from 'vue';
import { getAddress } from 'ethers/lib/utils';
import { OreIdAuthenticator } from 'ual-oreid';

// dependencies --
import {
Expand Down Expand Up @@ -119,8 +117,7 @@ export const useAccountStore = defineStore(store_name, {
await authenticator.init();
const ualUsers = await authenticator.login();
if (ualUsers?.length) {
// OreId has it's own authorization service, only init fuel service for other ual users
const ualUser = ualUsers[0] instanceof OreIdAuthenticator ? ualUsers[0] : await initFuelUserWrapper(ualUsers[0]);
const ualUser = await initFuelUserWrapper(ualUsers[0]);
const permission = (ualUser as unknown as { requestPermission: string })
.requestPermission ?? 'active';
const account = await ualUser.getAccountName();
Expand Down Expand Up @@ -244,8 +241,10 @@ export const useAccountStore = defineStore(store_name, {
const account = localStorage.getItem('account');
const isNative = localStorage.getItem('isNative') === 'true';
const autoLogin = localStorage.getItem('autoLogin');
this.trace('autoLogin', account, isNative, autoLogin);
this.trace('autoLogin', account, network, autoLogin, isNative, this.__accounts[label]);
if (account && network && autoLogin && !this.__accounts[label]) {
// Ensure we are working with the correct network
useChainStore().setChain(label, network);
if (isNative) {
const authenticators = getAntelope().config.authenticatorsGetter();
const authenticator = authenticators.find(
Expand All @@ -270,6 +269,8 @@ export const useAccountStore = defineStore(store_name, {
network,
});
}
} else {
this.trace('autoLogin', 'canceled!', account, network, autoLogin, !this.__accounts[label]);
}
} catch (error) {
console.error('Error: ', errorToString(error));
Expand Down Expand Up @@ -297,7 +298,6 @@ export const useAccountStore = defineStore(store_name, {
this.trace('sendAction', account, data, name, actor, permission);
try {
useFeedbackStore().setLoading('account.sendAction');
console.error('Account.sendAction() not implemented', account, data, name, actor, permission);
return Promise.resolve({ hash: '0x0' } as NativeTransactionResponse);
} catch (error) {
console.error('Error: ', errorToString(error));
Expand All @@ -307,16 +307,6 @@ export const useAccountStore = defineStore(store_name, {
}
},

async sendTransaction(actions: Action[]) {
this.trace('sendTransaction', actions);
try {
useFeedbackStore().setLoading('account.sendTransaction');
console.error('Account.sendTransaction() not implemented', actions);
} catch (error) {
console.error('Error: ', errorToString(error));
}
},

async fetchAccountDataFor(label: string, account: AccountModel) {
this.trace('fetchAccountDataFor', account);
try {
Expand Down
5 changes: 5 additions & 0 deletions src/antelope/stores/allowances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,11 @@ export const useAllowancesStore = defineStore(store_name, {

const chainSettings = useChainStore().currentChain.settings as EVMChainSettings;

if (chainSettings.isNative()) {
this.trace('fetchAllowancesForAccount', 'Native chain does not have allowances');
return;
}

Comment on lines +242 to +246
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This avoids trying to fetch allowances data from a native chain

const erc20AllowancesPromise = chainSettings.fetchErc20Allowances(account, { limit: ALLOWANCES_LIMIT });
const erc721AllowancesPromise = chainSettings.fetchErc721Allowances(account, { limit: ALLOWANCES_LIMIT });
const erc1155AllowancesPromise = chainSettings.fetchErc1155Allowances(account, { limit: ALLOWANCES_LIMIT });
Expand Down
86 changes: 61 additions & 25 deletions src/antelope/stores/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,23 +180,31 @@ export const useChainStore = defineStore(store_name, {
},
async updateStakedRatio(label: string): Promise<void> {
// first we need the contract instance to be able to execute queries
this.trace('actualUpdateStakedRatio', label);
useFeedbackStore().setLoading('actualUpdateStakedRatio');
const chain_settings = useChainStore().getChain(label).settings as EVMChainSettings;
const sysToken = chain_settings.getSystemToken();
const stkToken = chain_settings.getStakedSystemToken();
this.trace('updateStakedRatio', label);
const chain = this.getChain(label);
try {
useFeedbackStore().setLoading('updateStakedRatio');
if (!chain.settings.isNative()) {
const chain_settings = chain.settings as EVMChainSettings;
const sysToken = chain_settings.getSystemToken();
const stkToken = chain_settings.getStakedSystemToken();
Comment on lines +187 to +190
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this avoids fetching the staking ratio data from a non-evm chain


const abi = [stlosAbiPreviewDeposit[0], stlosAbiPreviewRedeem[0]];
const provider = await getAntelope().wallets.getWeb3Provider();
const contractInstance = new ethers.Contract(stkToken.address, abi, provider);
// Now we preview a deposit of 1 SYS to get the ratio
const oneSys = ethers.utils.parseUnits('1.0', sysToken.decimals);
const stakedRatio = await contractInstance.previewDeposit(oneSys.toString());
const unstakedRatio:ethers.BigNumber = await contractInstance.previewRedeem(oneSys);
// Finally we update the store
this.setStakedRatio(label, stakedRatio);
this.setUnstakedRatio(label, unstakedRatio);
useFeedbackStore().unsetLoading('actualUpdateStakedRatio');
const abi = [stlosAbiPreviewDeposit[0], stlosAbiPreviewRedeem[0]];
const provider = await getAntelope().wallets.getWeb3Provider();
const contractInstance = new ethers.Contract(stkToken.address, abi, provider);
// Now we preview a deposit of 1 SYS to get the ratio
const oneSys = ethers.utils.parseUnits('1.0', sysToken.decimals);
const stakedRatio = await contractInstance.previewDeposit(oneSys.toString());
const unstakedRatio:ethers.BigNumber = await contractInstance.previewRedeem(oneSys);
// Finally we update the store
this.setStakedRatio(label, stakedRatio);
this.setUnstakedRatio(label, unstakedRatio);
}
} catch (error) {
console.error(error);
} finally {
useFeedbackStore().unsetLoading('updateStakedRatio');
}
},
async updateGasPrice(label: string): Promise<void> {
useFeedbackStore().setLoading('updateGasPrice');
Expand All @@ -206,6 +214,8 @@ export const useChainStore = defineStore(store_name, {
if (!chain.settings.isNative()) {
const wei = await (chain.settings as EVMChainSettings).getGasPrice();
(chain as EvmChainModel).gasPrice = wei;
} else {
this.trace('updateGasPrice', label, 'Native chain has no gas costs');
}
} catch (error) {
console.error(error);
Expand Down Expand Up @@ -237,7 +247,6 @@ export const useChainStore = defineStore(store_name, {
// make the change only if they are different
if (network !== this.__chains[label]?.settings.getNetwork()) {
this.__chains[label] = newChainModel(network, settings[network].isNative());
this.trace('setChain', label, network, '--> void this.updateChainData(label);');
void this.updateChainData(label);
getAntelope().events.onNetworkChanged.next(
{ label, chain: this.__chains[label] },
Expand All @@ -248,16 +257,43 @@ export const useChainStore = defineStore(store_name, {
}
},
setStakedRatio(label: string, ratio: ethers.BigNumber) {
const decimals = (this.getChain(label).settings as EVMChainSettings).getStakedSystemToken().decimals;
const ratioNumber = parseFloat(ethers.utils.formatUnits(ratio, decimals));
this.trace('setStakedRatio', label, ratio.toString(), ratioNumber);
(this.__chains[label] as EvmChainModel).stakeRatio = ratio;
this.trace('setStakedRatio', label, ratio.toString());
const chain = this.getChain(label);
try {
if (!chain.settings.isNative()) {
const decimals = (this.getChain(label).settings as EVMChainSettings).getStakedSystemToken().decimals;
const ratioNumber = parseFloat(ethers.utils.formatUnits(ratio, decimals));
this.trace('setStakedRatio', label, ratio.toString(), ratioNumber);
(this.__chains[label] as EvmChainModel).stakeRatio = ratio;
} else {
this.trace('setStakedRatio', label, 'Native chain has no staked ratio');
}
Comment on lines +263 to +270
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensuring the correct chain

} catch (error) {
console.error(error);
throw new Error('antelope.chain.error_token_list');
} finally {
useFeedbackStore().unsetLoading('updateTokenList');
}

},
setUnstakedRatio(label: string, ratio: ethers.BigNumber) {
const decimals = (this.getChain(label).settings as EVMChainSettings).getStakedSystemToken().decimals;
const ratioNumber = parseFloat(ethers.utils.formatUnits(ratio, decimals));
this.trace('setUnstakedRatio', label, ratio.toString(), ratioNumber);
(this.__chains[label] as EvmChainModel).unstakeRatio = ratio;
this.trace('setUnstakedRatio', label, ratio.toString());
const chain = this.getChain(label);
try {
if (!chain.settings.isNative()) {
const decimals = (this.getChain(label).settings as EVMChainSettings).getStakedSystemToken().decimals;
const ratioNumber = parseFloat(ethers.utils.formatUnits(ratio, decimals));
this.trace('setUnstakedRatio', label, ratio.toString(), ratioNumber);
(this.__chains[label] as EvmChainModel).unstakeRatio = ratio;
} else {
this.trace('setUnstakedRatio', label, 'Native chain has no unstaked ratio');
}
Comment on lines +283 to +290
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensuring the correct chain

} catch (error) {
console.error(error);
throw new Error('antelope.chain.error_token_list');
} finally {
useFeedbackStore().unsetLoading('updateTokenList');
}
},
},
});
Expand Down
9 changes: 6 additions & 3 deletions src/antelope/stores/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,14 @@ export const useHistoryStore = defineStore(store_name, {
const contractStore = useContractStore();

this.trace('fetchEvmNftTransfersForAccount', label);

feedbackStore.setLoading('history.fetchEvmNftTransfersForAccount');

const chainSettings = useChainStore().getChain(label).settings as EVMChainSettings;

if (chainSettings.isNative()) {
this.trace('fetchEvmNftTransfersForAccount', 'Native networks not supported yet');
return;
}
Comment on lines +195 to +198
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fetching history only for EVM (for now)


feedbackStore.setLoading('history.fetchEvmNftTransfersForAccount');
try {
// get all erc721 and erc1155 transfers for the given account
const [
Expand Down
Loading
Loading