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

#812 | multichain support #813

Merged
merged 3 commits into from
Jun 17, 2024
Merged
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 quasar.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ module.exports = function(/* ctx */) {
// app boot file (/src/boot)
// --> boot files are part of "main.js"
// https://quasar.dev/quasar-cli/boot-files
boot: ['ual', 'hyperion', 'i18n', 'fuel', 'api', 'errorHandling', 'helpers', 'mixin', 'emitter', 'telosApi', 'wagmi', 'antelope'],
boot: ['ual', 'i18n', 'fuel', 'api', 'errorHandling', 'helpers', 'mixin', 'emitter', 'telosApi', 'wagmi', 'antelope'],

// https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css
css: ['index.scss'],
Expand Down
21 changes: 9 additions & 12 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ 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);
},
});
</script>
Expand Down
2 changes: 1 addition & 1 deletion src/antelope/chains/evm/telos-evm-testnet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getFiatPriceFromIndexer } from 'src/api/price';
const LOGO = 'https://raw.githubusercontent.com/telosnetwork/token-list/main/logos/telos.png';
const CHAIN_ID = '41';
export const NETWORK = 'telos-evm-testnet';
const DISPLAY = 'Telos EVM Testnet';
const DISPLAY = 'Telos EVM (Testnet)';
const TOKEN = new TokenClass({
name: 'Telos',
symbol: 'TLOS',
Expand Down
2 changes: 1 addition & 1 deletion src/antelope/chains/evm/telos-evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getFiatPriceFromIndexer } from 'src/api/price';
const LOGO = 'https://raw.githubusercontent.com/telosnetwork/token-list/main/logos/telos.png';
const CHAIN_ID = '40';
export const NETWORK = 'telos-evm';
const DISPLAY = 'Telos EVM Mainnet';
const DISPLAY = 'Telos EVM';
const TOKEN = new TokenClass({
name: 'Telos',
symbol: 'TLOS',
Expand Down
7 changes: 4 additions & 3 deletions src/antelope/chains/native/telos-testnet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { RpcEndpoint } from 'universal-authenticator-library';
import { api } from 'src/api';
import { TokenClass, TokenSourceInfo, PriceChartData, Theme } from 'src/antelope/types';

const LOGO = 'https://raw.githubusercontent.com/telosnetwork/token-list/main/logos/telos.png';
const CHAIN_ID =
'1eaa0824707c8c16bd25145493bf062aecddfeb56c736f6ba6397f3195f33c9f';
const NETWORK = 'telos-testnet';
const DISPLAY = 'Telos';
const DISPLAY = 'Telos Zero (Testnet)';
const TOKEN = new TokenClass({
symbol: 'TLOS',
precision: 4,
Expand Down Expand Up @@ -95,11 +96,11 @@ export default class TelosTestnet extends NativeChainSettings {
}

getLargeLogoPath(): string {
return 'chains/telos/telos_logo.svg';
return LOGO;
}

getSmallLogoPath(): string {
return 'chains/telos/tlos.png';
return LOGO;
}

getMapDisplay(): boolean {
Expand Down
7 changes: 4 additions & 3 deletions src/antelope/chains/native/telos/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { RpcEndpoint } from 'universal-authenticator-library';
import { api } from 'src/api';
import { TokenClass, TokenSourceInfo, PriceChartData, Theme } from 'src/antelope/types';

const LOGO = 'https://raw.githubusercontent.com/telosnetwork/token-list/main/logos/telos.png';
const CHAIN_ID =
'4667b205c6838ef70ff7988f6e8257e8be0e1284a2f59699054a018f743b1d11';
const NETWORK = 'telos';
const DISPLAY = 'Telos';
const DISPLAY = 'Telos Zero';
const TOKEN = new TokenClass({
symbol: 'TLOS',
precision: 4,
Expand Down Expand Up @@ -98,11 +99,11 @@ export default class Telos extends NativeChainSettings {
}

getLargeLogoPath(): string {
return 'chains/telos/telos_logo.svg';
return LOGO;
}

getSmallLogoPath(): string {
return 'chains/telos/tlos.png';
return LOGO;
}

getMapDisplay(): boolean {
Expand Down
7 changes: 7 additions & 0 deletions src/antelope/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ export class Antelope {
this.config.init(app);
this.wallets.init();

// each time the user changes the network,
// we need to reset the current web3 provider instance
events.onNetworkChanged.subscribe(() => {
this.wallets.resetWeb3Provider();
});


// call for the first time useXStore for all X stores in Antelope library
const stores = this.stores;

Expand Down
34 changes: 13 additions & 21 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 All @@ -40,7 +38,7 @@ import {
} from 'src/antelope';


export interface LoginNativeActionData {
export interface loginZeroActionData {
authenticator: Authenticator,
network: string,
}
Expand Down Expand Up @@ -113,15 +111,17 @@ export const useAccountStore = defineStore(store_name, {
},
actions: {
trace: createTraceFunction(store_name),
async loginNative({ authenticator, network }: LoginNativeActionData): Promise<boolean> {
this.trace('loginNative', authenticator, network);
async loginZero({ authenticator, network }: loginZeroActionData): Promise<boolean> {
this.trace('loginZero', authenticator, network);
let success = false;
try {
this.trace('loginZero', 'authenticator.init()...');
await authenticator.init();
this.trace('loginZero', 'authenticator.login()...');
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]);
this.trace('loginZero', 'authenticator.login() OK! ualUsers:', ualUsers);
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 @@ -246,8 +246,10 @@ export const useAccountStore = defineStore(store_name, {
const rawAddress = localStorage.getItem('rawAddress');
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 @@ -257,7 +259,7 @@ export const useAccountStore = defineStore(store_name, {
console.error(authenticators.map(a => a.getName()).join(', '));
throw new Error('antelope.account.error_auto_login');
}
this.loginNative({
this.loginZero({
authenticator,
network,
});
Expand All @@ -274,6 +276,8 @@ export const useAccountStore = defineStore(store_name, {
autoLogAccount,
});
}
} else {
this.trace('autoLogin', 'canceled!', account, network, autoLogin, !this.__accounts[label]);
}
} catch (error) {
console.error('Error: ', errorToString(error));
Expand Down Expand Up @@ -326,7 +330,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 @@ -336,16 +339,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 Expand Up @@ -395,4 +388,3 @@ export const useAccountStore = defineStore(store_name, {
const accountInitialState: AccountState = {
__accounts: {},
};

22 changes: 15 additions & 7 deletions src/antelope/stores/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import {
} from 'src/antelope';


export const settings: { [key: string]: ChainSettings } = {
export const settings: { [network: string]: ChainSettings } = {
// Native chains
'eos': new EOS('eos'),
'telos': new Telos('telos'),
Expand All @@ -66,6 +66,8 @@ export const settings: { [key: string]: ChainSettings } = {
'telos-evm-testnet': new TelosEVMTestnet('telos-evm-testnet'),
};

export const chains: { [network: string]: ChainModel } = {};

export interface ChainModel {
lastUpdate: number;
apy: string;
Expand Down Expand Up @@ -167,7 +169,7 @@ export const useChainStore = defineStore(store_name, {
async updateSettings(label: string): Promise<void> {
this.trace('updateSettings', label);
try {
const settings = this.getChain(label).settings as EVMChainSettings;
const settings = useChainStore().getChain(label).settings as EVMChainSettings;
settings.init().then(() => {
this.trace('updateSettings', label, '-> onChainIndexerReady.next()');
getAntelope().events.onChainIndexerReady.next({ label, ready: true });
Expand All @@ -183,7 +185,7 @@ export const useChainStore = defineStore(store_name, {
async updateApy(label: string): Promise<void> {
useFeedbackStore().setLoading('updateApy');
this.trace('updateApy', label);
const chain = this.getChain(label);
const chain = useChainStore().getChain(label);
try {
chain.apy = await chain.settings.getApy();
} catch (error) {
Expand All @@ -205,7 +207,7 @@ export const useChainStore = defineStore(store_name, {
const stkToken = chain_settings.getStakedSystemToken();

const abi = [stlosAbiPreviewDeposit[0], stlosAbiPreviewRedeem[0]];
const provider = await getAntelope().wallets.getWeb3Provider();
const provider = await getAntelope().wallets.getWeb3Provider(label);
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);
Expand All @@ -224,7 +226,7 @@ export const useChainStore = defineStore(store_name, {
async updateGasPrice(label: string): Promise<void> {
useFeedbackStore().setLoading('updateGasPrice');
this.trace('updateGasPrice');
const chain = this.getChain(label);
const chain = useChainStore().getChain(label);
try {
if (!chain.settings.isNative()) {
const wei = await (chain.settings as EVMChainSettings).getGasPrice();
Expand All @@ -241,7 +243,7 @@ export const useChainStore = defineStore(store_name, {
async updateTokenList(label: string): Promise<void> {
useFeedbackStore().setLoading('updateTokenList');
this.trace('updateTokenList');
const chain = this.getChain(label);
const chain = useChainStore().getChain(label);
try {
if (chain.settings.isNative()) {
chain.tokens = await (chain.settings as NativeChainSettings).getTokenList();
Expand All @@ -259,9 +261,15 @@ export const useChainStore = defineStore(store_name, {
setChain(label: string, network: string) {
this.trace('setChain', label, network);
if (network in settings) {

// create the chain model if it doesn't exist
if (!chains[network]) {
chains[network] = newChainModel(network, settings[network].isNative());
}

// make the change only if they are different
if (network !== this.__chains[label]?.settings.getNetwork()) {
this.__chains[label] = newChainModel(network, settings[network].isNative());
this.__chains[label] = chains[network];
this.trace('setChain', label, network, '--> void this.updateChainData(label);');
void this.updateChainData(label);
getAntelope().events.onNetworkChanged.next(
Expand Down
2 changes: 2 additions & 0 deletions src/antelope/stores/rex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export const useRexStore = defineStore(store_name, {
async getStakedSystemContractInstance(label: string) {
this.trace('getStakedSystemContractInstance', label);
const address = (useChainStore().getChain(label).settings as EVMChainSettings).getStakedSystemToken().address;
this.trace('getStakedSystemContractInstance', label, address);
return this.getContractInstance(label, address);
},
/**
Expand All @@ -118,6 +119,7 @@ export const useRexStore = defineStore(store_name, {
async getEscrowContractInstance(label: string) {
this.trace('getEscrowContractInstance', label);
const address = (useChainStore().getChain(label).settings as EVMChainSettings).getEscrowContractAddress();
this.trace('getEscrowContractInstance', label, address);
return this.getContractInstance(label, address);
},
/**
Expand Down
11 changes: 11 additions & 0 deletions src/antelope/wallets/AntelopeWallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export class AntelopeWallets {

init() {
this.trace('init');


}

addEVMAuthenticator(authenticator: EVMAuthenticator) {
Expand All @@ -42,11 +44,13 @@ export class AntelopeWallets {

// If a provider instance already exists, return it immediately.
if (this.web3Provider) {
this.trace('getWeb3Provider', 'Returning existing provider instance');
return this.web3Provider;
}

// If an initialization is already underway, wait for it to complete.
if (this.web3ProviderInitializationPromise) {
this.trace('getWeb3Provider', 'Waiting for existing initialization to complete');
return this.web3ProviderInitializationPromise;
}

Expand All @@ -58,6 +62,7 @@ export class AntelopeWallets {
const jsonRpcProvider = new ethers.providers.JsonRpcProvider(url);
await jsonRpcProvider.ready;
this.web3Provider = jsonRpcProvider as ethers.providers.Web3Provider;
this.trace('getWeb3Provider', 'Initialized provider instance', url, this.web3Provider);
return this.web3Provider;
} catch (e) {
this.trace('getWeb3Provider authenticator.web3Provider() Failed!', e);
Expand All @@ -69,4 +74,10 @@ export class AntelopeWallets {
return this.web3ProviderInitializationPromise;
}

resetWeb3Provider() {
this.trace('resetWeb3Provider');
this.web3Provider = null;
this.web3ProviderInitializationPromise = null;
}

}
Loading
Loading