diff --git a/global.d.ts b/global.d.ts new file mode 100644 index 00000000..98ff0d33 --- /dev/null +++ b/global.d.ts @@ -0,0 +1,5 @@ +declare global { + interface Window { + ethereum: any + } +} diff --git a/package.json b/package.json index 8016a9f9..36fe40df 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,8 @@ "@types/feather-icons": "^4.7.0", "anchor-link": "^3.3.0", "anchor-link-browser-transport": "^3.2.0", + "bn.js": "^5.2.1", + "ethers": "^5.6.9", "feather-icons": "^4.28.0", "idb": "^7.0.1", "inter-ui": "^3.15.0", @@ -37,6 +39,7 @@ "@snowpack/plugin-svelte": "^3.4.0", "@snowpack/plugin-typescript": "^1.1.1", "@snowpack/plugin-webpack": "^3.0.0", + "@types/bn.js": "^5.1.1", "@types/pako": "^1.0.1", "@types/snowpack-env": "^2.3.2", "@typescript-eslint/eslint-plugin": "^4.22.1", diff --git a/src/abi-types.ts b/src/abi-types.ts index c881898e..7770a8fa 100644 --- a/src/abi-types.ts +++ b/src/abi-types.ts @@ -11,6 +11,7 @@ import { UInt16, UInt32, UInt64, + Checksum160, } from 'anchor-link' @Struct.type('buyrambytes') @@ -170,3 +171,25 @@ export class Transfer extends Struct { @Struct.field('asset') quantity!: Asset @Struct.field('string') memo!: string } + +@Struct.type('withdraw') +export class TelosEvmWithdraw extends Struct { + @Struct.field('name') to!: Name + @Struct.field('asset') quantity!: Asset +} + +@Struct.type('openwallet') +export class TelosEvmOpenWallet extends Struct { + @Struct.field('name') account!: Name + @Struct.field('checksum160') address!: Checksum160 + @Struct.field('name') actor!: Name + @Struct.field('name') permission!: Name +} + +@Struct.type('create') +export class TelosEvmCreate extends Struct { + @Struct.field('name') account!: Name + @Struct.field('string') data!: string + @Struct.field('name') actor!: Name + @Struct.field('name') permission!: Name +} diff --git a/src/app.svelte b/src/app.svelte index b4b49392..b6c8a310 100644 --- a/src/app.svelte +++ b/src/app.svelte @@ -9,7 +9,7 @@ import Login from '~/pages/login.svelte' import Dashboard from '~/pages/dashboard/index.svelte' import Request from '~/pages/request/index.svelte' - import Transfer from '~/pages/transfer/index.svelte' + import Send from '~/pages/send/index.svelte' import TokensPurchase from '~/pages/tokens/purchase/index.svelte' import Resources from '~/pages/resources/index.svelte' import Components from '~/pages/_components/index.svelte' @@ -17,6 +17,7 @@ import Toasts from '~/components/elements/toasts.svelte' import BanxaSuccess from '~/pages/banxa/success.svelte' import BanxaFailure from '~/pages/banxa/failure.svelte' + import Transfer from '~/pages/transfer/index.svelte' $: { document.body.classList.toggle('darkmode', $darkMode) @@ -177,14 +178,14 @@ - - + + - - + + @@ -198,6 +199,9 @@ + + +

You shouldn't be here. Get out before it's too late.

diff --git a/src/auth.ts b/src/auth.ts index cc458aaa..14364a7b 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -5,7 +5,8 @@ import {get} from 'svelte/store' import {storeAccount} from './stores/account-provider' import {getClient} from './api-client' import {appId, chains} from './config' -import {activeSession, availableSessions} from './store' +import {activeEvmSession, activeSession, availableSessions} from './store' +import {startEvmSession} from './lib/evm' const transport = new Transport({ requestStatus: false, @@ -97,4 +98,9 @@ export async function activate(id: SessionLike) { throw new Error('No such session') } activeSession.set(session) + + if (get(activeEvmSession)) { + activeEvmSession.set(undefined) + startEvmSession() + } } diff --git a/src/components/elements/button.svelte b/src/components/elements/button.svelte index 7a3df3a5..71fde25b 100644 --- a/src/components/elements/button.svelte +++ b/src/components/elements/button.svelte @@ -31,6 +31,7 @@ if (href === undefined) { event.preventDefault() } + if (!formValidation || (!$formDisabled && !disabled)) { dispatch('action', event) } @@ -195,6 +196,7 @@ display: flex; flex-direction: column; align-items: center; + width: 100%; } &.loading { :global(.content .icon:not(.loading)) { diff --git a/src/components/elements/form/transaction.svelte b/src/components/elements/form/transaction.svelte index 266ad9f3..98a67e6d 100644 --- a/src/components/elements/form/transaction.svelte +++ b/src/components/elements/form/transaction.svelte @@ -19,7 +19,7 @@ let error: boolean = false let errorMessage: string = '' let transaction_id = writable(undefined) - let refreshInterval: number + let refreshInterval: NodeJS.Timeout function refreshAccount(account_name: Name) { // Refresh the account data @@ -61,7 +61,6 @@ }, clear: () => { error = false - console.log('clearing') transaction_id.set(undefined) }, retryTransaction: () => { @@ -73,7 +72,6 @@ } }, setTransaction: (id: string) => { - console.log('setting') transaction_id.set(id) }, setTransactionError: (err: any) => { diff --git a/src/components/elements/input.svelte b/src/components/elements/input.svelte index 05e3ae86..1a8c6276 100644 --- a/src/components/elements/input.svelte +++ b/src/components/elements/input.svelte @@ -3,14 +3,17 @@ import type {InputResponse} from 'src/ui-types' import type {Form} from '~/ui-types' import {createEventDispatcher} from 'svelte' + import type {inputType} from '~/ui-types' export let disabled: boolean = false export let focus: boolean = false - export let inputmode: string = '' + export let inputmode: inputType = undefined export let name: string = '' export let placeholder: string = '' export let value: string = '' + const inputmodeParam = inputmode as any + /** Whether or not the button should go full width */ export let fluid: boolean = false @@ -19,7 +22,7 @@ export let isValid: any = () => true export let assumeValid: boolean = false - let timer: number | undefined + let timer: NodeJS.Timeout | undefined let delay: number = 300 // Get parent form context (if exists) @@ -59,7 +62,7 @@ type HTMLInputFormEvent = Event & {currentTarget: EventTarget & HTMLInputElement} const debounce = (e: HTMLInputFormEvent) => { - clearTimeout(timer) + timer && clearTimeout(timer) value = e.currentTarget.value // Immediately invalidate invalidate(name, value) @@ -78,6 +81,10 @@ }, delay) } const handleInput = (e: HTMLInputFormEvent): void => debounce(e) + + $: { + isValid(value) + } -
+
diff --git a/src/components/elements/input/labelled.svelte b/src/components/elements/input/labelled.svelte index 87d93f34..53fa6e4b 100644 --- a/src/components/elements/input/labelled.svelte +++ b/src/components/elements/input/labelled.svelte @@ -1,13 +1,14 @@ @@ -100,6 +105,33 @@ } } } + + .placeholder { + padding: 10px 12px; + border-radius: 12px; + max-width: 400px; + border: 1px solid var(--divider-grey); + display: flex; + align-items: center; + cursor: pointer; + + .text-container { + flex: 1; + font-family: Inter; + font-style: normal; + font-weight: 500; + font-size: 14px; + letter-spacing: -0.04px; + color: var(--main-black); + display: inline; + text-align: left; + } + + .arrow-container { + display: flex; + width: 20px; + } + } @@ -107,16 +139,18 @@

Select Token

-
- -
+ {#if !tokenOptions} +
+ +
+ {/if}
@@ -147,4 +181,16 @@ - ($displayModal = true)} token={selectedToken} /> +{#if selectedToken} + ($displayModal = true)} + token={selectedToken || defaultToken} + /> +{:else} +
($displayModal = true)}> + Select Token +
+ +
+
+{/if} diff --git a/src/components/elements/input/token/selector/row.svelte b/src/components/elements/input/token/selector/row.svelte index f6215389..3d53ab4d 100644 --- a/src/components/elements/input/token/selector/row.svelte +++ b/src/components/elements/input/token/selector/row.svelte @@ -14,11 +14,18 @@ let balance $: { - balance = $balances && $balances.find((balance) => balance.tokenKey === token.key) + if (token.balance) { + balance = token.balance + } else { + balance = + $balances && $balances.find((balance) => balance.tokenKey === token.key)?.quantity + } - if (balance) { - const tokenPrecision = balance.quantity.symbol.precision - const unitValue = balance.quantity.units.value + if (typeof balance === 'string') { + formattedTokenBalance = balance + } else if (balance) { + const tokenPrecision = balance.symbol.precision + const unitValue = balance.units.value const fullTokenBalanceString = ( Number(unitValue) / Math.pow(10, tokenPrecision) ).toFixed(tokenPrecision) diff --git a/src/components/elements/select.svelte b/src/components/elements/select.svelte new file mode 100644 index 00000000..8662fd7b --- /dev/null +++ b/src/components/elements/select.svelte @@ -0,0 +1,47 @@ + + + + + diff --git a/src/components/evm-tx-follower/index.svelte b/src/components/evm-tx-follower/index.svelte new file mode 100644 index 00000000..65ea590c --- /dev/null +++ b/src/components/evm-tx-follower/index.svelte @@ -0,0 +1,119 @@ + + + + + +
+ +

{title}

+ {txId} +
+
+
+ + + +
+
+ +
+
+
diff --git a/src/components/layout/navigation/index.svelte b/src/components/layout/navigation/index.svelte index 92425bd2..4f77dd0c 100644 --- a/src/components/layout/navigation/index.svelte +++ b/src/components/layout/navigation/index.svelte @@ -23,6 +23,11 @@ { icon: 'arrow-right', name: 'Send & Receive', + path: '/send', + }, + { + icon: 'repeat', + name: 'Transfer', path: '/transfer', }, ...(banxaIsAvailable($activeBlockchain) diff --git a/src/components/tx-follower/index.svelte b/src/components/tx-follower/index.svelte index a7ec81eb..ff1292a9 100644 --- a/src/components/tx-follower/index.svelte +++ b/src/components/tx-follower/index.svelte @@ -13,12 +13,18 @@ import Summary from './summary.svelte' import Advanced from './advanced.svelte' - /** The transaction id to follow. */ + /** The transaction id to follow */ export let id: Checksum256Type - /** The chain where the transaction was submitted. */ + /** The chain where the transaction was submitted */ export let chain: ChainConfig - /** Title, e.g. Tokens sent. */ + /** Title, e.g. Tokens sent */ export let title = 'Transaction sent' + /** The text of the primary button at the bottom of the page */ + export let primaryButtonText = 'Done' + /** The function to call when the primary button is clicked */ + export let handlePrimaryButtonClick: () => void = () => { + router.goto('/') + } let txId: Checksum256 $: { @@ -130,8 +136,8 @@
- {primaryButtonText}
diff --git a/src/config.ts b/src/config.ts index 760d1074..d46f79e1 100644 --- a/src/config.ts +++ b/src/config.ts @@ -203,7 +203,7 @@ export const chains: ChainConfig[] = [ resourceSampleAccount: 'greymassfuel', resourceSampleMilliseconds: 1000, testnet: false, - bloksUrl: 'https://telos.bloks.io', + bloksUrl: 'https://explorer.telos.net', balanceProviders: new Set([BalanceProviders.LightAPI]), }, { diff --git a/src/lib/evm.ts b/src/lib/evm.ts new file mode 100644 index 00000000..ce0063cb --- /dev/null +++ b/src/lib/evm.ts @@ -0,0 +1,292 @@ +import {get} from 'svelte/store' +import BN from 'bn.js' +import {activeBlockchain, activeEvmSession, activeSession} from '~/store' +import {wait} from '~/helpers' + +import {Asset, Name, NameType} from 'anchor-link' +import {BigNumber, ethers} from 'ethers' +import {getClient} from '~/api-client' + +export type AvailableEvms = 'eos-mainnet' | 'telos' +export interface EvmChainConfig { + chainId: string + chainName: string + nativeCurrency: {name: string; symbol: string; decimals: number} + rpcUrls: string[] + blockExplorerUrls: string[] +} + +let evmProvider: ethers.providers.Web3Provider + +declare global { + interface Window { + ethereum: any + } +} + +export const evmChainConfigs: {[key: string]: EvmChainConfig} = { + eos: { + chainId: '0x4571', + chainName: 'EOS EVM Network', + nativeCurrency: {name: 'EOS', symbol: '4,EOS', decimals: 18}, + rpcUrls: ['https://api.evm.eosnetwork.com/'], + blockExplorerUrls: ['https://explorer.evm.eosnetwork.com'], + }, + telos: { + chainId: '0x28', + chainName: 'Telos EVM Mainnet', + nativeCurrency: {name: 'Telos', symbol: '4,TLOS', decimals: 18}, + rpcUrls: ['https://mainnet.telos.net/evm'], + blockExplorerUrls: ['https://teloscan.io'], + }, +} + +export interface EvmSessionParams { + signer: ethers.providers.JsonRpcSigner + address: string + chainName: string + nativeAccountName?: NameType +} + +export interface EvmSessionFromParams { + chainName: string + nativeAccountName?: NameType +} + +export class EvmSession { + address: string + signer: ethers.providers.JsonRpcSigner + chainName: string + nativeAccountName?: NameType + + constructor({address, signer, chainName, nativeAccountName}: EvmSessionParams) { + this.address = address + this.signer = signer + this.chainName = chainName + this.nativeAccountName = nativeAccountName + } + + get checksumAddress() { + return this.address.replace('0x', '').toLowerCase() + } + + get chainConfig() { + return evmChainConfigs[this.chainName] + } + + static async from({chainName, nativeAccountName}: EvmSessionFromParams) { + if (window.ethereum) { + const evmChainConfig = evmChainConfigs[chainName] + const provider = getProvider() + let network = await provider.getNetwork() + if (network.chainId !== Number(evmChainConfig.chainId.replace('0x', ''))) { + await switchNetwork(evmChainConfig) + network = await provider.detectNetwork() + } + + await window.ethereum.request({method: 'eth_requestAccounts'}) + const signer = provider.getSigner() + + await window.ethereum.get_currency_balance + + return new EvmSession({ + address: await signer.getAddress(), + signer, + chainName, + nativeAccountName, + }) + } else { + throw new Error('You need to install Metamask in order to use this feature.') + } + } + + async sendTransaction(tx: ethers.providers.TransactionRequest) { + return this.signer.sendTransaction(tx) + } + + async getBalance() { + if (this.chainName === 'telos') { + return this.getTelosEvmBalance() + } + + const wei = await this.signer.getBalance() + + const tokenName = evmChainConfigs[this.chainName].nativeCurrency.name + + return Asset.from(formatToken(ethers.utils.formatEther(wei), tokenName)) + } + + async getTelosEvmBalance() { + if (!this.nativeAccountName) { + throw new Error('Native account name is necessary to fetch Telos balance.') + } + + const account = await getTelosEvmAccount(this.nativeAccountName) + + if (!account) { + return Asset.from(0, this.chainConfig.nativeCurrency.symbol) + } + + const bn = BigNumber.from(`0x${account.balance}`) + + return Asset.from( + Number(ethers.utils.formatEther(bn)), + this.chainConfig.nativeCurrency.symbol + ) + } +} + +export async function getTelosEvmAccount(nativeAccountName: NameType) { + const chain = get(activeBlockchain) + const client = getClient(chain.chainId) + + if (!client) { + throw new Error('API client could not be instantiated') + } + + const {rows} = await client.v1.chain.get_table_rows({ + code: 'eosio.evm', + scope: 'eosio.evm', + table: 'account', + index_position: 'tertiary', + lower_bound: Name.from(nativeAccountName), + upper_bound: Name.from(nativeAccountName), + }) + + return rows[0] +} + +export function getProvider() { + if (evmProvider) { + return evmProvider + } + + if (window.ethereum) { + evmProvider = new ethers.providers.Web3Provider(window.ethereum, 'any') + return evmProvider + } + + throw new Error('No provider found') +} + +export function convertToEvmAddress(eosAccountName: string): string { + const blockList = ['binancecleos', 'huobideposit', 'okbtothemoon'] + if (blockList.includes(eosAccountName)) { + throw new Error('This CEX has not fully support the EOS-EVM bridge yet.') + } + return convertToEthAddress(eosAccountName) +} + +function formatToken(amount: string, tokenSymbol: string) { + return `${Number(amount).toFixed(4)} ${tokenSymbol}` +} + +export async function switchNetwork(evmChainConfig: EvmChainConfig) { + await window.ethereum + .request({ + method: 'wallet_switchEthereumChain', + params: [{chainId: evmChainConfig.chainId}], + }) + .catch(async (e: {code: number}) => { + if (e.code === 4902) { + await window.ethereum.request({ + method: 'wallet_addEthereumChain', + params: [evmChainConfig], + }) + } + }) +} + +function convertToEthAddress(eosAddress: string) { + try { + return uint64ToAddr(strToUint64(eosAddress)) + } catch (err) { + return err + } +} + +function charToSymbol(c: string) { + const a = 'a'.charCodeAt(0) + const z = 'z'.charCodeAt(0) + const one = '1'.charCodeAt(0) + const five = '5'.charCodeAt(0) + const charCode = c.charCodeAt(0) + if (charCode >= a && charCode <= z) { + return charCode - a + 6 + } + if (charCode >= one && charCode <= five) { + return charCode - one + 1 + } + if (c === '.') { + return 0 + } + throw new Error('Address include illegal character') +} + +function strToUint64(str: string) { + var n = new BN(0) + var i = str.length + if (i >= 13) { + // Only the first 12 characters can be full-range ([.1-5a-z]). + i = 12 + + // The 13th character must be in the range [.1-5a-j] because it needs to be encoded + // using only four bits (64_bits - 5_bits_per_char * 12_chars). + n = new BN(charToSymbol(str[12])) + if (n.gte(new BN(16))) { + throw new Error('Invalid 13th character') + } + } + // Encode full-range characters. + + while (--i >= 0) { + n = n.or(new BN(charToSymbol(str[i])).shln(64 - 5 * (i + 1))) + } + return n.toString(16, 16) +} + +function uint64ToAddr(str: string) { + return '0xbbbbbbbbbbbbbbbbbbbbbbbb' + str +} + +let connectingToEvm = false + +export async function startEvmSession(): Promise { + let evmSession: EvmSession + + if (connectingToEvm) { + await wait(5000) + return startEvmSession() + } + + connectingToEvm = true + + const blockchain = get(activeBlockchain) + const nativeSession = get(activeSession) + + try { + evmSession = await EvmSession.from({ + chainName: blockchain.id, + nativeAccountName: nativeSession?.auth.actor, + }) + } catch (e) { + if (e.code === -32002) { + await wait(5000) + return startEvmSession() + } + + if (!e.message) { + connectingToEvm = false + return + } + + throw new Error(`Could not connect to EVM. Error: ${e.message}`) + } + + if (evmSession) { + activeEvmSession.set(evmSession) + connectingToEvm = false + } + + return evmSession +} diff --git a/src/lib/fiat.ts b/src/lib/fiat.ts new file mode 100644 index 00000000..4daf8fe7 --- /dev/null +++ b/src/lib/fiat.ts @@ -0,0 +1,8 @@ +const currencyFormatter = new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD'}) +export function fiatFormat(value: number) { + return currencyFormatter.format(value) +} + +export function valueInFiat(value: number, price: number) { + return fiatFormat(value * price) +} diff --git a/src/pages/dashboard/index.svelte b/src/pages/dashboard/index.svelte index 4daf35c3..15256552 100644 --- a/src/pages/dashboard/index.svelte +++ b/src/pages/dashboard/index.svelte @@ -6,6 +6,7 @@ import {getClient} from '~/api-client' import {DelegatedBandwidth} from '~/abi-types' import {ChainFeatures} from '~/config' + import {fiatFormat} from '~/lib/fiat' import {activeSession, activeBlockchain, currentAccount, activePriceTicker} from '~/store' import {balances, fetchBalances} from '~/stores/balances' @@ -130,11 +131,6 @@ } ) - const currencyFormatter = new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD'}) - function fiatFormat(value: number) { - return currencyFormatter.format(value) - } - function refresh() { if ($activeSession) { fetchBalances($activeSession, true) diff --git a/src/pages/transfer/field-container/index.svelte b/src/pages/send/field-container/index.svelte similarity index 100% rename from src/pages/transfer/field-container/index.svelte rename to src/pages/send/field-container/index.svelte diff --git a/src/pages/transfer/field-container/status-icon.svelte b/src/pages/send/field-container/status-icon.svelte similarity index 100% rename from src/pages/transfer/field-container/status-icon.svelte rename to src/pages/send/field-container/status-icon.svelte diff --git a/src/pages/transfer/fio.ts b/src/pages/send/fio.ts similarity index 100% rename from src/pages/transfer/fio.ts rename to src/pages/send/fio.ts diff --git a/src/pages/send/index.svelte b/src/pages/send/index.svelte new file mode 100644 index 00000000..608f6c72 --- /dev/null +++ b/src/pages/send/index.svelte @@ -0,0 +1,174 @@ + + + + + + +
+ ($transferData.step = Step.Recipient)} + > + ↑ Send + + ($transferData.step = Step.Receive)} + > + ↓ Receive + +
+
+ +
+ +
+
+
diff --git a/src/pages/transfer/main.svelte b/src/pages/send/main.svelte similarity index 95% rename from src/pages/transfer/main.svelte rename to src/pages/send/main.svelte index 1a37e1a6..d694a002 100644 --- a/src/pages/transfer/main.svelte +++ b/src/pages/send/main.svelte @@ -9,17 +9,17 @@ import type {Balance} from '~/stores/balances' import type {Token} from '~/stores/tokens' import {txFee} from './fio' - import {transferData, Step} from '~/pages/transfer/transfer' + import {transferData, Step} from '~/pages/send/transfer' import Button from '~/components/elements/button.svelte' import Icon from '~/components/elements/icon.svelte' import type {FormTransaction} from '~/ui-types' - import TransferRecipient from '~/pages/transfer/step/recipient.svelte' - import TransferAmount from '~/pages/transfer/step/amount.svelte' - import TransferConfirm from '~/pages/transfer/step/confirm.svelte' - import TransferReceive from '~/pages/transfer/step/receive.svelte' - import TransferSending from '~/pages/transfer/step/sending.svelte' + import TransferRecipient from '~/pages/send/step/recipient.svelte' + import TransferAmount from '~/pages/send/step/amount.svelte' + import TransferConfirm from '~/pages/send/step/confirm.svelte' + import TransferReceive from '~/pages/send/step/receive.svelte' + import TransferSending from '~/pages/send/step/sending.svelte' export let balance: Readable export let token: Readable diff --git a/src/pages/transfer/status/account.svelte b/src/pages/send/status/account.svelte similarity index 76% rename from src/pages/transfer/status/account.svelte rename to src/pages/send/status/account.svelte index 40bd0d1f..3c6a4e9f 100644 --- a/src/pages/transfer/status/account.svelte +++ b/src/pages/send/status/account.svelte @@ -1,7 +1,7 @@ diff --git a/src/pages/transfer/step/token.svelte b/src/pages/send/step/token.svelte similarity index 98% rename from src/pages/transfer/step/token.svelte rename to src/pages/send/step/token.svelte index e5971bc9..70788dac 100644 --- a/src/pages/transfer/step/token.svelte +++ b/src/pages/send/step/token.svelte @@ -8,7 +8,7 @@ import {activeSession, currentAccount} from '~/store' import {balances} from '~/stores/balances' import {tokens} from '~/stores/tokens' - import {Step, transferData} from '~/pages/transfer/transfer' + import {Step, transferData} from '~/pages/send/transfer' import Form from '~/components/elements/form.svelte' import Input from '~/components/elements/input.svelte' diff --git a/src/pages/transfer/transfer.ts b/src/pages/send/transfer.ts similarity index 100% rename from src/pages/transfer/transfer.ts rename to src/pages/send/transfer.ts diff --git a/src/pages/transfer/confirm.svelte b/src/pages/transfer/confirm.svelte new file mode 100644 index 00000000..42b3dca6 --- /dev/null +++ b/src/pages/transfer/confirm.svelte @@ -0,0 +1,194 @@ + + + + +
+
+

Transfer

+

Review and Sign

+
+ +
+ + + + + + + + + + + + + + + + + + + + +
From {transferManager.fromDisplayString}{transferManager.fromAddress}
To {transferManager.toDisplayString}{transferManager.toAddress}
Deposit Amount +
+
+ +
+ {depositAmount} +
+
+ {depositAmountInUsd ? `~ ${depositAmountInUsd}` : ''} +
+
Fee Amount +
+
+ +
+ {feeAmount || `0.0000 ${$systemTokenKey}`} +
+
+ {feeAmountInUsd ? `~ ${feeAmountInUsd}` : ''} +
+
Received Amount +
+
+ +
+ {receivedAmount} +
+
+ {receivedAmountInUsd ? `~ ${receivedAmountInUsd}` : ''} +
+
+
+ +
+ +
+
diff --git a/src/pages/transfer/error.svelte b/src/pages/transfer/error.svelte new file mode 100644 index 00000000..7db1791c --- /dev/null +++ b/src/pages/transfer/error.svelte @@ -0,0 +1,59 @@ + + + + +
+
+

Transfer Failed

+
+ +
+

+ {error} +

+
+ +
+ +
+
diff --git a/src/pages/transfer/form.svelte b/src/pages/transfer/form.svelte new file mode 100644 index 00000000..cf8a9b78 --- /dev/null +++ b/src/pages/transfer/form.svelte @@ -0,0 +1,284 @@ + + + + +
+
+

Transfer

+

Transfer tokens between your accounts

+
+
+
+
+ +
+ +
+ + + {#if from && to} + + {/if} +
+
+ +
+ +
+ {#if receivedAmount && receivedAmount.value > 0 && feeAmount && feeAmount.value > 0} +
+ +
+
+ +
+
+ +
+ {/if} +
+
+
+ + {#if !$activeEvmSession} +

Connect to metamask wallet to continue

+ {/if} +
+
+
diff --git a/src/pages/transfer/index.svelte b/src/pages/transfer/index.svelte index b353c3f5..9bcc4a09 100644 --- a/src/pages/transfer/index.svelte +++ b/src/pages/transfer/index.svelte @@ -1,174 +1,193 @@ - - -
- ($transferData.step = Step.Recipient)} - > - ↑ Send - - ($transferData.step = Step.Receive)} - > - ↓ Receive - -
-
- -
- -
-
+
+ {#if errorMessage} + + {:else if step === 'form' || !transferManager || !deposit || !received} +
+ {:else if step === 'confirm' && receivedAmount} + + {:else if step === 'success' && transactResult} + + {/if} +
diff --git a/src/pages/transfer/managers/eosEvmBridge.ts b/src/pages/transfer/managers/eosEvmBridge.ts new file mode 100644 index 00000000..73f6c773 --- /dev/null +++ b/src/pages/transfer/managers/eosEvmBridge.ts @@ -0,0 +1,81 @@ +import {Asset, Name} from 'anchor-link' +import {get} from 'svelte/store' + +import {Transfer} from '~/abi-types' +import {getClient} from '~/api-client' +import {TransferManager} from './transferManager' +import {currentAccountBalance, evmBalance} from '~/store' +import {updateActiveAccount} from '~/stores/account-provider' +import {updateEvmBalance} from '~/stores/balances-provider' + +export class EosEvmBridge extends TransferManager { + static from = 'eos' + static fromDisplayString = 'EOS' + static to = 'evm' + static toDisplayString = 'EOS (EVM)' + static supportedChains = ['eos'] + static evmRequired = true + + get fromAddress() { + return String(this.nativeSession.auth.actor) + } + + get toAddress() { + return this.evmSession.address + } + + async transferFee() { + const apiClient = getClient(this.nativeSession.chainId) + + let apiResponse + + try { + apiResponse = await apiClient.v1.chain.get_table_rows({ + code: 'eosio.evm', + scope: 'eosio.evm', + table: 'config', + }) + } catch (err) { + throw new Error('Failed to get config table from eosio.evm. Full error: ' + err) + } + + const config = apiResponse.rows[0] + + return Asset.from(config.ingress_bridge_fee || '0.0000 EOS') + } + + transfer(amount: string) { + const action = Transfer.from({ + from: this.nativeSession.auth.actor, + to: 'eosio.evm', + quantity: String(Asset.fromFloat(Number(amount), '4,EOS')), + memo: this.evmSession.address, + }) + + return this.nativeSession.transact({ + action: { + authorization: [this.nativeSession.auth], + account: Name.from('eosio.token'), + name: Name.from('transfer'), + data: action, + }, + }) + } + + async balance() { + return get(currentAccountBalance) + } + + async receivingBalance() { + return get(evmBalance) + } + + async updateBalances() { + updateEvmBalance() + updateActiveAccount() + } + + updateMainBalance() { + return updateEvmBalance() + } +} diff --git a/src/pages/transfer/managers/evmEosBridge.ts b/src/pages/transfer/managers/evmEosBridge.ts new file mode 100644 index 00000000..184405de --- /dev/null +++ b/src/pages/transfer/managers/evmEosBridge.ts @@ -0,0 +1,90 @@ +import {Asset} from 'anchor-link' +import {ethers} from 'ethers' + +import {convertToEvmAddress, getProvider} from '~/lib/evm' + +import {TransferManager} from './transferManager' +import {updateEvmBalance} from '~/stores/balances-provider' +import {updateActiveAccount} from '~/stores/account-provider' +import {get} from 'svelte/store' +import {currentAccountBalance, evmBalance} from '~/store' + +export class EvmEosBridge extends TransferManager { + static from = 'evm' + static fromDisplayString = 'EOS (EVM)' + static to = 'eos' + static toDisplayString = 'EOS' + static supportedChains = ['eos'] + static evmRequired = true + + get fromAddress() { + return this.evmSession.address + } + + get toAddress() { + return String(this.nativeSession.auth.actor) + } + + async transferFee(amount: string) { + const {gas, gasPrice} = await this.estimateGas(amount) + + const eosAmount = ethers.utils.formatEther(Number(gas) * Number(gasPrice)) + + return Asset.fromFloat(Number(eosAmount), this.evmSession.chainConfig.nativeCurrency.symbol) + } + + async transfer(amount: string, amountReceived?: string) { + const targetEvmAddress = convertToEvmAddress(String(this.nativeSession.auth.actor)) + + const amountToTransfer = amountReceived || amount + + const {gas} = await this.estimateGas(amountToTransfer) + + return this.evmSession.sendTransaction({ + from: this.evmSession.address, + to: targetEvmAddress, + value: ethers.utils.parseEther(amountToTransfer), + gasPrice: await getProvider().getGasPrice(), + gasLimit: gas, + data: ethers.utils.formatBytes32String(''), + }) + } + + private async estimateGas(amount: string) { + const provider = getProvider() + + const targetEvmAddress = convertToEvmAddress(String(this.nativeSession.auth.actor)) + + const gasPrice = await provider.getGasPrice() + + // Reducing the amount by 0.005 EOS to avoid getting an error when entire balance is sent. Proper amount is calculated once the gas fee is known. + const reducedAmount = String(Number(amount) - 0.005) + + const gas = await provider.estimateGas({ + from: this.evmSession.address, + to: targetEvmAddress, + value: ethers.utils.parseEther(reducedAmount), + gasPrice, + data: ethers.utils.formatBytes32String(''), + }) + + return {gas, gasPrice} + } + + async balance() { + return get(evmBalance) + } + + async receivingBalance() { + return get(currentAccountBalance) + } + + async updateBalances() { + updateActiveAccount() + updateEvmBalance() + } + + updateMainBalance() { + return updateEvmBalance() + } +} diff --git a/src/pages/transfer/managers/evmTelosBridge.ts b/src/pages/transfer/managers/evmTelosBridge.ts new file mode 100644 index 00000000..112e4c6e --- /dev/null +++ b/src/pages/transfer/managers/evmTelosBridge.ts @@ -0,0 +1,65 @@ +import {get} from 'svelte/store' + +import {currentAccountBalance, evmBalance} from '~/store' +import {TransferManager} from './transferManager' +import {Asset, Name} from 'anchor-link' +import {TelosEvmWithdraw} from '~/abi-types' +import {systemToken} from '~/stores/tokens' +import {updateActiveAccount} from '~/stores/account-provider' +import {updateEvmBalance} from '~/stores/balances-provider' + +export class EvmTelosBridge extends TransferManager { + static from = 'evm' + static fromDisplayString = 'TLOS (EVM)' + static to = 'telos' + static toDisplayString = 'TLOS' + static supportedChains = ['telos'] + static evmRequired = true + + get fromAddress() { + return this.evmSession.address! + } + + get toAddress() { + return String(this.nativeSession.auth.actor) + } + + async transfer(amount: string) { + const systemTokenSymbol = get(systemToken)?.symbol + + if (!systemTokenSymbol) { + throw new Error('No system token symbol found') + } + + const action = TelosEvmWithdraw.from({ + to: this.nativeSession.auth.actor, + quantity: String(Asset.fromFloat(Number(amount), systemTokenSymbol)), + }) + + return this.nativeSession.transact({ + action: { + authorization: [this.nativeSession.auth], + account: Name.from('eosio.evm'), + name: Name.from('withdraw'), + data: action, + }, + }) + } + + async balance() { + return get(evmBalance) + } + + async receivingBalance() { + return get(currentAccountBalance) + } + + async updateBalances(): Promise { + updateActiveAccount() + updateEvmBalance() + } + + updateMainBalance() { + return updateEvmBalance() + } +} diff --git a/src/pages/transfer/managers/index.ts b/src/pages/transfer/managers/index.ts new file mode 100644 index 00000000..f09345c2 --- /dev/null +++ b/src/pages/transfer/managers/index.ts @@ -0,0 +1,12 @@ +import {EvmTelosBridge} from './evmTelosBridge' +import {EosEvmBridge} from './eosEvmBridge' +import {EvmEosBridge} from './evmEosBridge' +import {TelosEvmBridge} from './telosEvmBridge' +import type {TransferManager} from './transferManager' + +export const transferManagers: {[key: string]: typeof TransferManager} = { + 'EOS - EOS (EVM)': EosEvmBridge, + 'EOS (EVM) - EOS': EvmEosBridge, + 'TLOS - TLOS (EVM)': TelosEvmBridge, + 'TLOS (EVM) - TLOS': EvmTelosBridge, +} diff --git a/src/pages/transfer/managers/telosEvmBridge.ts b/src/pages/transfer/managers/telosEvmBridge.ts new file mode 100644 index 00000000..ed0f4dcf --- /dev/null +++ b/src/pages/transfer/managers/telosEvmBridge.ts @@ -0,0 +1,103 @@ +import {get} from 'svelte/store' + +import {currentAccountBalance, evmBalance} from '~/store' +import {TransferManager} from './transferManager' +import {TelosEvmCreate, TelosEvmOpenWallet, Transfer} from '~/abi-types' +import {Asset, Name} from 'anchor-link' +import {updateActiveAccount} from '~/stores/account-provider' +import {updateEvmBalance} from '~/stores/balances-provider' +import {getTelosEvmAccount} from '~/lib/evm' + +export class TelosEvmBridge extends TransferManager { + static from = 'telos' + static fromDisplayString = 'TLOS' + static to = 'evm' + static toDisplayString = 'TLOS (EVM)' + static supportedChains = ['telos'] + static evmRequired = true + + get fromAddress() { + return String(this.nativeSession.auth.actor) + } + + get toAddress() { + return this.evmSession.address + } + + async transfer(amount: string) { + const telosEvmAccount = await getTelosEvmAccount(this.nativeSession.auth.actor) + + const actions = [] + + if (!telosEvmAccount) { + actions.push(this.telosEvmCreate()) + } + + const transfer = Transfer.from({ + from: this.nativeSession.auth.actor, + to: 'eosio.evm', + quantity: String(Asset.fromFloat(Number(amount), '4,TLOS')), + memo: this.evmSession.checksumAddress || '', + }) + + actions.push({ + authorization: [this.nativeSession.auth], + account: Name.from('eosio.token'), + name: Name.from('transfer'), + data: transfer, + }) + + return this.nativeSession.transact({ + actions, + }) + } + + async balance() { + return get(currentAccountBalance) + } + + async receivingBalance() { + return get(evmBalance) + } + + async updateMainBalance() { + return updateEvmBalance() + } + + async updateBalances(): Promise { + updateActiveAccount() + updateEvmBalance() + } + + telosEvmOpenWalletAction() { + const action = TelosEvmOpenWallet.from({ + account: this.nativeSession.auth.actor, + address: this.evmSession.checksumAddress, + actor: this.nativeSession.auth.actor, + permission: this.nativeSession.auth.permission, + }) + + return { + authorization: [this.nativeSession.auth], + account: Name.from('eosio.evm'), + name: Name.from('openwallet'), + data: action, + } + } + + telosEvmCreate() { + const action = TelosEvmCreate.from({ + account: this.nativeSession.auth.actor, + data: this.evmSession.checksumAddress, + actor: this.nativeSession.auth.actor, + permission: this.nativeSession.auth.permission, + }) + + return { + authorization: [this.nativeSession.auth], + account: Name.from('eosio.evm'), + name: Name.from('create'), + data: action, + } + } +} diff --git a/src/pages/transfer/managers/transferManager.ts b/src/pages/transfer/managers/transferManager.ts new file mode 100644 index 00000000..082964d1 --- /dev/null +++ b/src/pages/transfer/managers/transferManager.ts @@ -0,0 +1,100 @@ +import {Asset} from 'anchor-link' +import type {LinkSession, TransactResult} from 'anchor-link' +import type {ethers} from 'ethers' +import {get} from 'svelte/store' + +import type {EvmSession} from '~/lib/evm' +import {valueInFiat} from '~/lib/fiat' +import {activePriceTicker, waitForStoreValue} from '~/store' +import {systemToken} from '~/stores/tokens' + +export abstract class TransferManager { + self: typeof TransferManager + static from: string + static to: string + static fromDisplayString: string + static toDisplayString: string + static supportedChains: string[] + static evmRequired: boolean = false + + readonly nativeSession: LinkSession + readonly evmSession: EvmSession + + constructor(nativeSession: LinkSession, evmSession: EvmSession) { + this.nativeSession = nativeSession + this.evmSession = evmSession + this.self = this.constructor as typeof TransferManager + } + + /* eslint-disable @typescript-eslint/no-unused-vars */ + transfer( + _amount: string, + _amountReceived?: string + ): Promise { + throw new Error('transfer() not implemented') + } + + transferFee(_amount?: string): Promise { + return Promise.resolve(Asset.from(0, get(systemToken)?.symbol || '4,EOS')) + } + /* eslint-enable @typescript-eslint/no-unused-vars */ + + balance(): Promise { + throw new Error('balance() not implemented') + } + + receivingBalance(): Promise { + throw new Error('receivingBalance() not implemented') + } + + updateBalances(): Promise { + throw new Error('updateBalances() not implemented') + } + + updateMainBalance(): Promise { + throw new Error('updateMainBalance() not implemented') + } + + async convertToUsd(amount: number): Promise { + const systemTokenPrice = await waitForStoreValue(activePriceTicker) + + return valueInFiat(amount, systemTokenPrice) + } + + // onSelect(): Promise { + // // This may be needed in the future + // throw new Error('onSelect() not implemented') + // } + + get fromAddress(): string { + throw new Error('fromAddress() not implemented') + } + + get toAddress(): string { + throw new Error('toAddress() not implemented') + } + + get from() { + return this.self.from + } + + get to() { + return this.self.to + } + + get fromDisplayString() { + return this.self.fromDisplayString + } + + get toDisplayString() { + return this.self.toDisplayString + } + + get supportedChains() { + return this.self.supportedChains + } + + get evmRequired() { + return this.self.evmRequired + } +} diff --git a/src/pages/transfer/success.svelte b/src/pages/transfer/success.svelte new file mode 100644 index 00000000..89f79f96 --- /dev/null +++ b/src/pages/transfer/success.svelte @@ -0,0 +1,68 @@ + + +{#if 'payload' in transactResult} + +{:else} + +{/if} diff --git a/src/store.ts b/src/store.ts index c995e2e6..08820235 100644 --- a/src/store.ts +++ b/src/store.ts @@ -6,6 +6,7 @@ import {ChainConfig, chainConfig, chains} from './config' import {Preferences} from './preferences' import {priceTicker} from './price-ticker' import {accountProvider} from './stores/account-provider' +import type {EvmSession} from '~/lib/evm' /** Set to true when app initialization completes. */ export const appReady = writable(false) @@ -13,6 +14,12 @@ export const appReady = writable(false) /** Active anchor link session, aka logged in user. */ export const activeSession = writable(undefined) +/** Active EVM session, aka logged in user. */ +export const activeEvmSession = writable(undefined) + +/** EVM session balance */ +export const evmBalance = writable(undefined) + /** Configuration of the currently selected blockchain */ export const activeBlockchain: Readable = derived(activeSession, (session) => { if (session) { @@ -75,3 +82,18 @@ export const darkMode = derived( } } ) + +export const waitForStoreValue = ( + store: Readable +): Promise => { + let unsubscribe: (() => void) | undefined + return new Promise((resolve) => { + unsubscribe = store.subscribe((value) => { + if (value) { + // Replace this condition with whatever means "populated" for you + resolve(value) + unsubscribe && unsubscribe() + } + }) + }) +} diff --git a/src/stores/account-provider.ts b/src/stores/account-provider.ts index 1c71e958..2562596e 100644 --- a/src/stores/account-provider.ts +++ b/src/stores/account-provider.ts @@ -60,6 +60,12 @@ export async function updateAccount(name: Name, chainId: ChainId, refresh: boole isLoading.set(false) } +export function updateActiveAccount() { + const session = get(activeSession) + if (!session) return + updateAccount(session.auth.actor, session.chainId) +} + function fetchBalance(name: Name, chainId: ChainId) { const chain = chainConfig(chainId) return getClient(chainId).v1.chain.get_currency_balance(chain.coreTokenContract, name) diff --git a/src/stores/balances-provider.ts b/src/stores/balances-provider.ts index 117c01d3..83f4a471 100644 --- a/src/stores/balances-provider.ts +++ b/src/stores/balances-provider.ts @@ -1,9 +1,9 @@ -import type {LinkSession} from 'anchor-link' +import {Asset, LinkSession} from 'anchor-link' import {get, writable} from 'svelte/store' import type {Writable} from 'svelte/store' import {chainConfig} from '~/config' -import {activeSession} from '~/store' +import {activeEvmSession, activeSession, evmBalance, waitForStoreValue} from '~/store' import type {Balance} from '~/stores/balances' import {getBalanceProvider} from '~/lib/balance-providers/utils' @@ -56,3 +56,12 @@ export async function updateBalances(session: LinkSession) { } isLoading.set(false) } + +export async function updateEvmBalance() { + const evmSession = await waitForStoreValue(activeEvmSession) + + if (evmSession) { + const balance = await evmSession.getBalance() + evmBalance.set(Asset.from(balance)) + } +} diff --git a/src/stores/tokens.ts b/src/stores/tokens.ts index 03d39acf..85a58358 100644 --- a/src/stores/tokens.ts +++ b/src/stores/tokens.ts @@ -17,6 +17,7 @@ export interface Token { name: NameType price?: number logo?: string + balance?: Asset | string } export interface TokenKeyParams { diff --git a/src/ui-types.ts b/src/ui-types.ts index 26beecbb..9952bacf 100644 --- a/src/ui-types.ts +++ b/src/ui-types.ts @@ -23,3 +23,15 @@ export interface NavigationItem { name: string path: string } + +export type inputType = + | 'text' + | 'search' + | 'none' + | 'tel' + | 'url' + | 'email' + | 'numeric' + | 'decimal' + | null + | undefined diff --git a/yarn.lock b/yarn.lock index 77f4be47..e6294e2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -909,6 +909,348 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@greymass/antelope-tokens@^0.0.1": version "0.0.1" resolved "https://registry.yarnpkg.com/@greymass/antelope-tokens/-/antelope-tokens-0.0.1.tgz#a245368adbad4e877d86f3fada0f22204fb6deb8" @@ -1063,6 +1405,13 @@ resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@types/bn.js@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + "@types/eslint-scope@^3.7.3": version "3.7.3" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" @@ -1355,6 +1704,11 @@ acorn@8.0.1, acorn@^7.1.1, acorn@^7.4.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5. resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.0.1.tgz#d7e8eca9b71d5840db0e7e415b3b2b20e250f938" integrity sha512-dmKn4pqZ29iQl2Pvze1zTrps2luvls2PBY//neO2WJ0s10B3AxJXshN+Ph7B4GrhfGhHXrl4dnUwyNNXQcnWGQ== +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -1433,10 +1787,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -"antelope-tokens@git+https://github.com/greymass/antelope-tokens.json.git": - version "0.0.1" - resolved "git+https://github.com/greymass/antelope-tokens.json.git#8ec8fbe55ffa670c95c491abbc120312c6f3b8f3" - anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -1525,6 +1875,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + big-integer@^1.6.7: version "1.6.51" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" @@ -1545,6 +1900,11 @@ bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -2018,7 +2378,7 @@ electron-to-chromium@^1.4.118: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.121.tgz#e2fa3b7bd592643c6b12ae6de2882550a29b7799" integrity sha512-N7OXhMr1p2oa9EkOhmHpmOm43DHzs55dep2FF6M7y6px5QJBheqEE3nwwZ+xJowlff+AEmMOdg3ARYGB+0kzbA== -elliptic@^6.5.4: +elliptic@6.5.4, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -2254,6 +2614,42 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +ethers@^5.6.9: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + events@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -2506,7 +2902,7 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hash.js@^1.0.0, hash.js@^1.0.3: +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== @@ -2719,6 +3115,11 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -3735,6 +4136,11 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" +scrypt-js@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + semver@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" @@ -4333,6 +4739,11 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + ws@^7.4.6: version "7.5.7" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67"