From c23654d100a72695e2def556b7b228525fced6f2 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Tue, 11 Jun 2024 17:52:33 +0530 Subject: [PATCH 01/61] feat: adding pluggable section to confirmation page (#25061) --- .../confirm/pluggable-section/index.ts | 1 + .../pluggable-section.test.tsx | 26 +++++++++++++++++++ .../pluggable-section/pluggable-section.tsx | 22 ++++++++++++++++ ui/pages/confirmations/confirm/confirm.tsx | 18 +++++++------ 4 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 ui/pages/confirmations/components/confirm/pluggable-section/index.ts create mode 100644 ui/pages/confirmations/components/confirm/pluggable-section/pluggable-section.test.tsx create mode 100644 ui/pages/confirmations/components/confirm/pluggable-section/pluggable-section.tsx diff --git a/ui/pages/confirmations/components/confirm/pluggable-section/index.ts b/ui/pages/confirmations/components/confirm/pluggable-section/index.ts new file mode 100644 index 000000000000..a99bc86297c4 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/pluggable-section/index.ts @@ -0,0 +1 @@ +export { default as PluggableSection } from './pluggable-section'; diff --git a/ui/pages/confirmations/components/confirm/pluggable-section/pluggable-section.test.tsx b/ui/pages/confirmations/components/confirm/pluggable-section/pluggable-section.test.tsx new file mode 100644 index 000000000000..085e8392c2b1 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/pluggable-section/pluggable-section.test.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +import mockState from '../../../../../../test/data/mock-state.json'; +import { renderWithProvider } from '../../../../../../test/jest'; +import { unapprovedPersonalSignMsg } from '../../../../../../test/data/confirmations/personal_sign'; +import configureStore from '../../../../../store/store'; +import PluggableSection from './pluggable-section'; + +const render = () => { + const store = configureStore({ + metamask: { + ...mockState.metamask, + }, + confirm: { + currentConfirmation: unapprovedPersonalSignMsg, + }, + }); + + return renderWithProvider(, store); +}; + +describe('PluggableSection', () => { + it('should render correctly', () => { + expect(() => render()).not.toThrow(); + }); +}); diff --git a/ui/pages/confirmations/components/confirm/pluggable-section/pluggable-section.tsx b/ui/pages/confirmations/components/confirm/pluggable-section/pluggable-section.tsx new file mode 100644 index 000000000000..c167cdb83c0f --- /dev/null +++ b/ui/pages/confirmations/components/confirm/pluggable-section/pluggable-section.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { ReactComponentLike } from 'prop-types'; +import { useSelector } from 'react-redux'; + +import { currentConfirmationSelector } from '../../../selectors'; + +// Components to be plugged into confirmation page can be added to the array below +const pluggedInSections: ReactComponentLike[] = []; + +const PluggableSection = () => { + const currentConfirmation = useSelector(currentConfirmationSelector); + + return ( + <> + {pluggedInSections.map((Section, index) => ( +
+ ))} + + ); +}; + +export default PluggableSection; diff --git a/ui/pages/confirmations/confirm/confirm.tsx b/ui/pages/confirmations/confirm/confirm.tsx index 8dd75a692def..505cda5e3042 100644 --- a/ui/pages/confirmations/confirm/confirm.tsx +++ b/ui/pages/confirmations/confirm/confirm.tsx @@ -1,21 +1,22 @@ import React from 'react'; import { AlertActionHandlerProvider } from '../../../components/app/alert-system/contexts/alertActionHandler'; -import ScrollToBottom from '../components/confirm/scroll-to-bottom'; -import { Footer } from '../components/confirm/footer'; -import { Header } from '../components/confirm/header'; -import { Info } from '../components/confirm/info'; +import { Page } from '../../../components/multichain/pages/page'; ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) import { MMISignatureMismatchBanner } from '../../../components/app/mmi-signature-mismatch-banner'; ///: END:ONLY_INCLUDE_IF -import { Nav } from '../components/confirm/nav'; -import { Title } from '../components/confirm/title'; -import { Page } from '../../../components/multichain/pages/page'; +import ScrollToBottom from '../components/confirm/scroll-to-bottom'; import setCurrentConfirmation from '../hooks/setCurrentConfirmation'; import syncConfirmPath from '../hooks/syncConfirmPath'; -import { LedgerInfo } from '../components/confirm/ledger-info'; import setConfirmationAlerts from '../hooks/setConfirmationAlerts'; import useConfirmationAlertActions from '../hooks/useConfirmationAlertActions'; +import { Footer } from '../components/confirm/footer'; +import { Header } from '../components/confirm/header'; +import { Info } from '../components/confirm/info'; +import { LedgerInfo } from '../components/confirm/ledger-info'; +import { Nav } from '../components/confirm/nav'; +import { Title } from '../components/confirm/title'; +import { PluggableSection } from '../components/confirm/pluggable-section'; const Confirm = () => { setCurrentConfirmation(); @@ -37,6 +38,7 @@ const Confirm = () => { <Info /> + <PluggableSection /> </ScrollToBottom> <Footer /> </Page> From 832ae1cb0a794f37ebf65304449d217a6adc178e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Regadas?= <apregadas@gmail.com> Date: Tue, 11 Jun 2024 14:43:40 +0100 Subject: [PATCH 02/61] fix: updates MMI e2e confirm transaction flow (#25053) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Updates MMI e2e tests for the transaction confirmation flow. ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- test/e2e/mmi/pageObjects/mmi-main-page.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/test/e2e/mmi/pageObjects/mmi-main-page.ts b/test/e2e/mmi/pageObjects/mmi-main-page.ts index 6d3ab315488f..8d78ceafd39d 100644 --- a/test/e2e/mmi/pageObjects/mmi-main-page.ts +++ b/test/e2e/mmi/pageObjects/mmi-main-page.ts @@ -69,17 +69,16 @@ export class MMIMainPage { } async sendFunds(account: string, amount: string) { - await this.page - .getByTestId('recipient-group') - .locator(`text="${account}"`) - .click(); + await this.page.locator(`text="${account}"`).click(); await expect( this.page.locator('.ens-input__selected-input__title'), - ).toHaveText(`${account}`); - await this.page.locator('input.unit-input__input').type(`${amount}`); - await this.page.locator('text="Next"').click(); + ).toContainText(`${account}`); + await this.page + .locator('[data-testid="currency-input"]') + .first() + .type(`${amount}`); + await this.page.locator('text="Continue"').click(); await this.page.locator('text="Confirm"').click(); - await this.page.locator('text="Approve"').click(); } async mainPageScreenshot(screenshotName: string, accountName: string) { From b3c810e18ff79cd41e2a15a868ddd703d5a00780 Mon Sep 17 00:00:00 2001 From: Charly Chevalier <charly.chevalier@consensys.net> Date: Tue, 11 Jun 2024 16:11:30 +0200 Subject: [PATCH 03/61] feat(multichain): add new selectors (#25205) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Adds new selectors for multichain context (and more specifically, for non-EVM networks for now). Those selectors follow the same naming than some existing selectors (that are EVM only). [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25205?quickstart=1) ## **Related issues** None ## **Manual testing steps** 1. This PR rely only on unit tests ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- app/images/bitcoin-logo.svg | 14 ++ shared/constants/multichain/networks.ts | 38 +++++ test/data/mock-accounts.ts | 59 +++++++ ui/selectors/accounts.test.ts | 63 +------ ui/selectors/multichain.test.ts | 212 ++++++++++++++++++++++++ ui/selectors/multichain.ts | 154 +++++++++++++++++ 6 files changed, 483 insertions(+), 57 deletions(-) create mode 100644 app/images/bitcoin-logo.svg create mode 100644 shared/constants/multichain/networks.ts create mode 100644 test/data/mock-accounts.ts create mode 100644 ui/selectors/multichain.test.ts create mode 100644 ui/selectors/multichain.ts diff --git a/app/images/bitcoin-logo.svg b/app/images/bitcoin-logo.svg new file mode 100644 index 000000000000..4306787921c7 --- /dev/null +++ b/app/images/bitcoin-logo.svg @@ -0,0 +1,14 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<g clip-path="url(#clip0_491_4015)"> +<rect width="16" height="16" fill="url(#pattern0_491_4015)"/> +</g> +<defs> +<pattern id="pattern0_491_4015" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image0_491_4015" transform="scale(0.0123457)"/> +</pattern> +<clipPath id="clip0_491_4015"> +<rect width="16" height="16" fill="white"/> +</clipPath> +<image id="image0_491_4015" width="81" height="81" xlink:href="data:image/png;base64,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"/> +</defs> +</svg> diff --git a/shared/constants/multichain/networks.ts b/shared/constants/multichain/networks.ts new file mode 100644 index 000000000000..92b9d7a89452 --- /dev/null +++ b/shared/constants/multichain/networks.ts @@ -0,0 +1,38 @@ +import { ProviderConfig } from '@metamask/network-controller'; +import { CaipChainId } from '@metamask/utils'; + +type ProviderConfigWithImageUrl = Omit<ProviderConfig, 'chainId'> & { + rpcPrefs?: { imageUrl?: string }; +}; + +export type MultichainProviderConfig = ProviderConfigWithImageUrl & { + chainId: CaipChainId; +}; + +export enum MultichainNetworks { + BITCOIN = 'bip122:000000000019d6689c085ae165831e93', + BITCOIN_TESTNET = 'bip122:000000000933ea01ad0ee984209779ba', +} + +export const BITCOIN_TOKEN_IMAGE_URL = './images/bitcoin-logo.svg'; + +export const MULTICHAIN_TOKEN_IMAGE_MAP = { + [MultichainNetworks.BITCOIN]: BITCOIN_TOKEN_IMAGE_URL, +} as const; + +export const MULTICHAIN_PROVIDER_CONFIGS: Record< + CaipChainId, + MultichainProviderConfig +> = { + [MultichainNetworks.BITCOIN]: { + chainId: MultichainNetworks.BITCOIN, + rpcUrl: '', // not used + ticker: 'BTC', + nickname: 'Bitcoin', + id: 'btc-mainnet', + type: 'rpc', + rpcPrefs: { + imageUrl: MULTICHAIN_TOKEN_IMAGE_MAP[MultichainNetworks.BITCOIN], + }, + }, +}; diff --git a/test/data/mock-accounts.ts b/test/data/mock-accounts.ts new file mode 100644 index 000000000000..ff6009ebd555 --- /dev/null +++ b/test/data/mock-accounts.ts @@ -0,0 +1,59 @@ +import { KeyringTypes } from '@metamask/keyring-controller'; +import { + InternalAccount, + EthAccountType, + BtcMethod, + BtcAccountType, +} from '@metamask/keyring-api'; +import { + ETH_EOA_METHODS, + ETH_4337_METHODS, +} from '../../shared/constants/eth-methods'; + +export const MOCK_ACCOUNT_EOA: InternalAccount = { + id: '4974fc00-c0fb-4a18-8535-8407ec6d1952', + address: '0x123', + options: {}, + methods: ETH_EOA_METHODS, + type: EthAccountType.Eoa, + metadata: { + name: 'Account 1', + keyring: { type: KeyringTypes.hd }, + importTime: 1691565967600, + lastSelected: 1691565967656, + }, +}; + +export const MOCK_ACCOUNT_ERC4337: InternalAccount = { + id: '4d5921f2-2022-44ce-a84f-9f6a0f142a5c', + address: '0x123', + options: {}, + methods: ETH_EOA_METHODS.concat(ETH_4337_METHODS), + type: EthAccountType.Erc4337, + metadata: { + name: 'Account 2', + keyring: { type: KeyringTypes.snap }, + importTime: 1691565967600, + lastSelected: 1691565967656, + }, +}; + +export const MOCK_ACCOUNT_BIP122_P2WPKH: InternalAccount = { + id: 'ae247df6-3911-47f7-9e36-28e6a7d96078', + address: 'bc1qaabb', + options: {}, + methods: [BtcMethod.SendMany], + type: BtcAccountType.P2wpkh, + metadata: { + name: 'Bitcoin Account', + keyring: { type: KeyringTypes.snap }, + importTime: 1691565967600, + lastSelected: 1955565967656, + }, +}; + +export const MOCK_ACCOUNTS = { + [MOCK_ACCOUNT_EOA.id]: MOCK_ACCOUNT_EOA, + [MOCK_ACCOUNT_ERC4337.id]: MOCK_ACCOUNT_ERC4337, + [MOCK_ACCOUNT_BIP122_P2WPKH.id]: MOCK_ACCOUNT_BIP122_P2WPKH, +}; diff --git a/ui/selectors/accounts.test.ts b/ui/selectors/accounts.test.ts index bf9e9038b655..8f6bc4e14b17 100644 --- a/ui/selectors/accounts.test.ts +++ b/ui/selectors/accounts.test.ts @@ -1,67 +1,16 @@ -import { KeyringTypes } from '@metamask/keyring-controller'; import { - InternalAccount, - EthAccountType, - BtcMethod, - BtcAccountType, -} from '@metamask/keyring-api'; -import { - ETH_EOA_METHODS, - ETH_4337_METHODS, -} from '../../shared/constants/eth-methods'; + MOCK_ACCOUNTS, + MOCK_ACCOUNT_EOA, + MOCK_ACCOUNT_ERC4337, + MOCK_ACCOUNT_BIP122_P2WPKH, +} from '../../test/data/mock-accounts'; import { AccountsState, isSelectedInternalAccountEth } from './accounts'; -const MOCK_ACCOUNT_EOA: InternalAccount = { - id: '4974fc00-c0fb-4a18-8535-8407ec6d1952', - address: '0x123', - options: {}, - methods: ETH_EOA_METHODS, - type: EthAccountType.Eoa, - metadata: { - name: 'Account 1', - keyring: { type: KeyringTypes.hd }, - importTime: 1691565967600, - lastSelected: 1691565967656, - }, -}; - -const MOCK_ACCOUNT_ERC4337: InternalAccount = { - id: '4d5921f2-2022-44ce-a84f-9f6a0f142a5c', - address: '0x123', - options: {}, - methods: ETH_EOA_METHODS.concat(ETH_4337_METHODS), - type: EthAccountType.Erc4337, - metadata: { - name: 'Account 2', - keyring: { type: KeyringTypes.snap }, - importTime: 1691565967600, - lastSelected: 1691565967656, - }, -}; - -const MOCK_ACCOUNT_BIP122_P2WPKH: InternalAccount = { - id: 'ae247df6-3911-47f7-9e36-28e6a7d96078', - address: 'bc1qaabb', - options: {}, - methods: [BtcMethod.SendMany], - type: BtcAccountType.P2wpkh, - metadata: { - name: 'Bitcoin Account', - keyring: { type: KeyringTypes.snap }, - importTime: 1691565967600, - lastSelected: 1955565967656, - }, -}; - const MOCK_STATE: AccountsState = { metamask: { internalAccounts: { selectedAccount: MOCK_ACCOUNT_EOA.id, - accounts: { - [MOCK_ACCOUNT_EOA.id]: MOCK_ACCOUNT_EOA, - [MOCK_ACCOUNT_ERC4337.id]: MOCK_ACCOUNT_ERC4337, - [MOCK_ACCOUNT_BIP122_P2WPKH.id]: MOCK_ACCOUNT_BIP122_P2WPKH, - }, + accounts: MOCK_ACCOUNTS, }, }, }; diff --git a/ui/selectors/multichain.test.ts b/ui/selectors/multichain.test.ts new file mode 100644 index 000000000000..582ba681403a --- /dev/null +++ b/ui/selectors/multichain.test.ts @@ -0,0 +1,212 @@ +import { + getNativeCurrency, + getProviderConfig, +} from '../ducks/metamask/metamask'; +import { + MULTICHAIN_PROVIDER_CONFIGS, + MultichainNetworks, + MultichainProviderConfig, +} from '../../shared/constants/multichain/networks'; +import { + MOCK_ACCOUNTS, + MOCK_ACCOUNT_EOA, + MOCK_ACCOUNT_BIP122_P2WPKH, +} from '../../test/data/mock-accounts'; +import { AccountsState } from './accounts'; +import { + getMultichainCurrentCurrency, + getMultichainDefaultToken, + getMultichainIsEvm, + getMultichainNativeCurrency, + getMultichainNetwork, + getMultichainNetworkProviders, + getMultichainProviderConfig, + getMultichainShouldShowFiat, +} from './multichain'; +import { getCurrentCurrency, getShouldShowFiat } from '.'; + +type TestState = AccountsState & { + metamask: { + preferences: { showFiatInTestnets: boolean }; + providerConfig: { ticker: string; chainId: string }; + currentCurrency: string; + currencyRates: Record<string, { conversionRate: string }>; + }; +}; + +const MOCK_EVM_STATE: TestState = { + metamask: { + preferences: { + showFiatInTestnets: false, + }, + providerConfig: { + ticker: 'ETH', + chainId: '0x1', + }, + currentCurrency: 'ETH', + currencyRates: { + ETH: { + conversionRate: 'usd', + }, + }, + internalAccounts: { + selectedAccount: MOCK_ACCOUNT_EOA.id, + accounts: MOCK_ACCOUNTS, + }, + }, +}; + +const MOCK_NON_EVM_STATE: AccountsState = { + metamask: { + ...MOCK_EVM_STATE.metamask, + internalAccounts: { + selectedAccount: MOCK_ACCOUNT_BIP122_P2WPKH.id, + accounts: MOCK_ACCOUNTS, + }, + }, +}; + +function getBip122ProviderConfig(): MultichainProviderConfig { + // For now, we only have Bitcoin non-EVM network, so we are expecting to have + // this one with `bip122:*` account type + return MULTICHAIN_PROVIDER_CONFIGS[MultichainNetworks.BITCOIN]; +} + +describe('Multichain Selectors', () => { + describe('getMultichainNetworkProviders', () => { + it('has some providers', () => { + const state = MOCK_EVM_STATE; + + const networkProviders = getMultichainNetworkProviders(state); + expect(Array.isArray(networkProviders)).toBe(true); + expect(networkProviders.length).toBeGreaterThan(0); + }); + }); + + describe('getMultichainNetwork', () => { + it('returns an EVM network provider if account is EVM', () => { + const state = MOCK_EVM_STATE; + + const network = getMultichainNetwork(state); + expect(network.isEvmNetwork).toBe(true); + }); + + it('returns an non-EVM network provider if account is non-EVM', () => { + const state = MOCK_NON_EVM_STATE; + + const network = getMultichainNetwork(state); + expect(network.isEvmNetwork).toBe(false); + }); + }); + + describe('getMultichainIsEvm', () => { + it('returns true if selected account is EVM compatible', () => { + const state = MOCK_EVM_STATE; + + expect(getMultichainIsEvm(state)).toBe(true); + }); + + it('returns false if selected account is not EVM compatible', () => { + const state = MOCK_NON_EVM_STATE; + + expect(getMultichainIsEvm(state)).toBe(false); + }); + }); + + describe('getMultichain{ProviderConfig,CurrentNetwork}', () => { + it('returns a ProviderConfig if account is EVM', () => { + const state = MOCK_EVM_STATE; + + expect(getMultichainProviderConfig(state)).toBe(getProviderConfig(state)); + }); + + it('returns a MultichainProviderConfig if account is non-EVM (bip122:*)', () => { + const state = MOCK_NON_EVM_STATE; + + const bip122ProviderConfig = getBip122ProviderConfig(); + expect(getMultichainProviderConfig(state)).toBe(bip122ProviderConfig); + }); + }); + + describe('getMultichainNativeCurrency', () => { + it('returns same native currency if account is EVM', () => { + const state = MOCK_EVM_STATE; + + expect(getMultichainNativeCurrency(state)).toBe(getNativeCurrency(state)); + }); + + it('returns MultichainProviderConfig.ticker if account is non-EVM (bip122:*)', () => { + const state = MOCK_NON_EVM_STATE; + + const bip122ProviderConfig = getBip122ProviderConfig(); + expect(getMultichainNativeCurrency(state)).toBe( + bip122ProviderConfig.ticker, + ); + }); + }); + + describe('getMultichainCurrentCurrency', () => { + it('returns same currency currency if account is EVM', () => { + const state = MOCK_EVM_STATE; + + expect(getMultichainCurrentCurrency(state)).toBe( + getCurrentCurrency(state), + ); + }); + + // @ts-expect-error This is missing from the Mocha type definitions + it.each(['usd', 'ETH'])( + "returns current currency '%s' if account is EVM", + (currency: string) => { + const state = MOCK_EVM_STATE; + + state.metamask.currentCurrency = currency; + expect(getCurrentCurrency(state)).toBe(currency); + expect(getMultichainCurrentCurrency(state)).toBe(currency); + }, + ); + + it('fallbacks to ticker as currency if account is non-EVM (bip122:*)', () => { + const state = MOCK_NON_EVM_STATE; // .currentCurrency = 'ETH' + + const bip122ProviderConfig = getBip122ProviderConfig(); + expect(getCurrentCurrency(state).toLowerCase()).not.toBe('usd'); + expect(getMultichainCurrentCurrency(state)).toBe( + bip122ProviderConfig.ticker, + ); + }); + }); + + describe('getMultichainShouldShowFiat', () => { + it('returns same value as getShouldShowFiat if account is EVM', () => { + const state = MOCK_EVM_STATE; + + expect(getMultichainShouldShowFiat(state)).toBe(getShouldShowFiat(state)); + }); + + it('returns true if account is non-EVM', () => { + const state = MOCK_NON_EVM_STATE; + + expect(getMultichainShouldShowFiat(state)).toBe(true); + }); + }); + + describe('getMultichainDefaultToken', () => { + it('returns ETH if account is EVM', () => { + const state = MOCK_EVM_STATE; + + expect(getMultichainDefaultToken(state)).toEqual({ + symbol: 'ETH', + }); + }); + + it('returns true if account is non-EVM (bip122:*)', () => { + const state = MOCK_NON_EVM_STATE; + + const bip122ProviderConfig = getBip122ProviderConfig(); + expect(getMultichainDefaultToken(state)).toEqual({ + symbol: bip122ProviderConfig.ticker, + }); + }); + }); +}); diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts new file mode 100644 index 000000000000..e97b08b85030 --- /dev/null +++ b/ui/selectors/multichain.ts @@ -0,0 +1,154 @@ +import { isEvmAccountType } from '@metamask/keyring-api'; +import { ProviderConfig } from '@metamask/network-controller'; +import { + CaipChainId, + KnownCaipNamespace, + parseCaipChainId, +} from '@metamask/utils'; +import { + MultichainProviderConfig, + MULTICHAIN_PROVIDER_CONFIGS, +} from '../../shared/constants/multichain/networks'; +import { + getNativeCurrency, + getProviderConfig, +} from '../ducks/metamask/metamask'; +import { AccountsState } from './accounts'; +import { + getAllNetworks, + getCurrentCurrency, + getNativeCurrencyImage, + getSelectedInternalAccount, + getShouldShowFiat, +} from '.'; + +export type MultichainState = AccountsState & { + metamask: { + // TODO: Use states from new {Rates,Balances,Chain}Controller + }; +}; + +export type MultichainNetwork = { + nickname: string; + isEvmNetwork: boolean; + chainId?: CaipChainId; + network?: ProviderConfig | MultichainProviderConfig; +}; + +export function getMultichainNetworkProviders( + _state: MultichainState, +): MultichainProviderConfig[] { + // TODO: need state from the ChainController? + return Object.values(MULTICHAIN_PROVIDER_CONFIGS); +} + +export function getMultichainNetwork( + state: MultichainState, +): MultichainNetwork { + const selectedAccount = getSelectedInternalAccount(state); + const isEvm = isEvmAccountType(selectedAccount.type); + + // EVM networks + const evmNetworks: ProviderConfig[] = getAllNetworks(state); + const evmProvider: ProviderConfig = getProviderConfig(state); + + if (isEvm) { + const evmChainId = + `${KnownCaipNamespace.Eip155}:${evmProvider.chainId}` as CaipChainId; + const evmNetwork = evmNetworks.find( + (network) => network.chainId === evmProvider.chainId, + ); + + return { + nickname: 'Ethereum', + isEvmNetwork: true, + chainId: evmChainId, + network: evmNetwork, + }; + } + + // Non-EVM networks + // (Hardcoded for testing) + // HACK: For now, we rely on the account type being "sort-of" CAIP compliant, so use + // this as a CAIP-2 namespace and apply our filter with it + const nonEvmNetworks = getMultichainNetworkProviders(state); + const nonEvmNetwork = nonEvmNetworks.find((provider) => { + const { namespace } = parseCaipChainId(provider.chainId); + return selectedAccount.type.startsWith(namespace); + }); + + return { + // TODO: Adapt this for other non-EVM networks + // TODO: We need to have a way of setting nicknames of other non-EVM networks + nickname: 'Bitcoin', + isEvmNetwork: false, + // FIXME: We should use CAIP-2 chain ID here, and not only the reference part + chainId: nonEvmNetwork?.chainId, + network: nonEvmNetwork, + }; +} + +// FIXME: All the following might have side-effect, like if the current account is a bitcoin one and that +// a popup (for ethereum related stuffs) is being shown (and uses this function), then the native +// currency will be BTC.. + +export function getMultichainIsEvm(state: MultichainState) { + const selectedAccount = getSelectedInternalAccount(state); + + // There are no selected account during onboarding. we default to the current EVM provider. + return !selectedAccount || isEvmAccountType(selectedAccount.type); +} + +export function getMultichainProviderConfig( + state: MultichainState, +): ProviderConfig | MultichainProviderConfig { + return getMultichainIsEvm(state) + ? getProviderConfig(state) + : getMultichainNetwork(state).network; +} + +export function getMultichainCurrentNetwork(state: MultichainState) { + return getMultichainProviderConfig(state); +} + +export function getMultichainNativeCurrency(state: MultichainState) { + return getMultichainIsEvm(state) + ? getNativeCurrency(state) + : getMultichainProviderConfig(state).ticker; +} + +export function getMultichainCurrentCurrency(state: MultichainState) { + const currentCurrency = getCurrentCurrency(state).toLowerCase(); + + // To mimic `getCurrentCurrency` we only consider fiat values, otherwise we + // fallback to the current ticker symbol value + return currentCurrency === 'usd' + ? 'usd' + : getMultichainProviderConfig(state).ticker; +} + +export function getMultichainCurrencyImage(state: MultichainState) { + if (getMultichainIsEvm(state)) { + return getNativeCurrencyImage(state); + } + + const provider = getMultichainProviderConfig( + state, + ) as MultichainProviderConfig; + return provider.rpcPrefs?.imageUrl; +} + +export function getMultichainShouldShowFiat(state: MultichainState) { + return getMultichainIsEvm(state) + ? getShouldShowFiat(state) + : // For now we force this for non-EVM + true; +} + +export function getMultichainDefaultToken(state: MultichainState) { + const symbol = getMultichainIsEvm(state) + ? getProviderConfig(state).ticker + : getMultichainProviderConfig(state).ticker; + + return { symbol }; +} From 2b2ee43178173ecb8beccd0e902a11aca7f158e7 Mon Sep 17 00:00:00 2001 From: Victor Thomas <10986371+vthomas13@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:54:55 -0400 Subject: [PATCH 04/61] fix: Swap-Send flaky test fix (#25041) --- .../tests/swap-send/swap-send-test-utils.ts | 6 +++--- test/e2e/webdriver/driver.js | 20 +++++++++++++------ .../app/currency-input/currency-input.js | 3 +-- .../swappable-currency-input.tsx | 2 +- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/test/e2e/tests/swap-send/swap-send-test-utils.ts b/test/e2e/tests/swap-send/swap-send-test-utils.ts index 0cfff6449b7f..4140d6bb92be 100644 --- a/test/e2e/tests/swap-send/swap-send-test-utils.ts +++ b/test/e2e/tests/swap-send/swap-send-test-utils.ts @@ -106,13 +106,13 @@ export class SwapSendPage { // eslint-disable-next-line @typescript-eslint/no-explicit-any inputAmounts.map(async (e: any, index: number) => { await this.driver.delay(delayInMs); - const i = await e.nestedFindElement('input'); + const i = await this.driver.findNestedElement(e, 'input'); assert.ok(i); const v = await i.getProperty('value'); assert.equal(v, expectedInputValues[index]); - const isDisabled = !(await i.isEnabled()); if (index > 0) { - assert.ok(isDisabled); + const isDisabled = await i.getProperty('disabled'); + assert.equal(isDisabled, true); } }), ); diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 00ed3c0e74b2..6815460f3091 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -64,12 +64,6 @@ function wrapElementWithAPI(element, driver) { } }; - element.nestedFindElement = async (rawLocator) => { - const locator = driver.buildLocator(rawLocator); - const newElement = await element.findElement(locator); - return wrapElementWithAPI(newElement, driver); - }; - // We need to hold a pointer to the original click() method so that we can call it in the replaced click() method if (!element.originalClick) { element.originalClick = element.click; @@ -466,6 +460,20 @@ class Driver { return wrapElementWithAPI(element, this); } + /** + * Finds a nested element within a parent element using the given locator. + * This is useful when the parent element is already known and you want to find an element within it. + * + * @param {WebElement} element - Parent element + * @param {string | object} nestedLocator - Nested element locator + * @returns {Promise<WebElement>} A promise that resolves to the found nested element. + */ + async findNestedElement(element, nestedLocator) { + const locator = this.buildLocator(nestedLocator); + const nestedElement = await element.findElement(locator); + return wrapElementWithAPI(nestedElement, this); + } + /** * Finds a visible element on the page using the given locator. * diff --git a/ui/components/app/currency-input/currency-input.js b/ui/components/app/currency-input/currency-input.js index 187ca7fd060f..71425f797e9f 100644 --- a/ui/components/app/currency-input/currency-input.js +++ b/ui/components/app/currency-input/currency-input.js @@ -96,8 +96,7 @@ export default function CurrencyInput({ tokenToFiatConversionRate, ); - const isDisabled = !onChange; - + const isDisabled = onChange === undefined; const swap = async () => { await onPreferenceToggle(); }; diff --git a/ui/components/multichain/asset-picker-amount/swappable-currency-input/swappable-currency-input.tsx b/ui/components/multichain/asset-picker-amount/swappable-currency-input/swappable-currency-input.tsx index 543a6ab84b82..ff587fe6c1c1 100644 --- a/ui/components/multichain/asset-picker-amount/swappable-currency-input/swappable-currency-input.tsx +++ b/ui/components/multichain/asset-picker-amount/swappable-currency-input/swappable-currency-input.tsx @@ -87,7 +87,7 @@ export function SwappableCurrencyInput({ <CurrencyInput className="asset-picker-amount__input" isFiatPreferred={isFiatPrimary} - onChange={onAmountChange} + onChange={onAmountChange} // onChange controls disabled state, disabled if undefined hexValue={value} swapIcon={(onClick: React.MouseEventHandler) => ( <SwapIcon onClick={onClick} /> From 8a04980c9467ec4c9b397e6e3fa590bc6f324666 Mon Sep 17 00:00:00 2001 From: George Marshall <george.marshall@consensys.net> Date: Tue, 11 Jun 2024 10:37:36 -0700 Subject: [PATCH 05/61] chore: upgrading to design tokens v4 (#24953) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This pull request aims to upgrade the extension to [design tokens v4](https://github.com/MetaMask/design-tokens/blob/main/MIGRATION.md#from-version-300-to-400). This upgrade ensures the most up-to-date colors are being used that align with design and primes the extension for the upcoming brand evolution. Included in this PR are third-party network color CSS variables that have been removed from the design tokens package and renamed CSS variables for shadow. This PR is the final update from a series of PRs that replace deprecated CSS colors that have been removed in v4. **Dependency PRs that should be merged before this one:** - https://github.com/MetaMask/metamask-extension/pull/24970 - https://github.com/MetaMask/metamask-extension/pull/24970 - https://github.com/MetaMask/metamask-extension/pull/25125 - https://github.com/MetaMask/metamask-extension/pull/25124 - https://github.com/MetaMask/metamask-extension/pull/25122 - https://github.com/MetaMask/metamask-extension/pull/25011 - https://github.com/MetaMask/metamask-extension/pull/25010 - https://github.com/MetaMask/metamask-extension/pull/25083 - https://github.com/MetaMask/metamask-extension/pull/24971 - https://github.com/MetaMask/metamask-extension/pull/25158 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/24953?quickstart=1) ![image](https://github.com/MetaMask/metamask-extension/assets/8112138/3c5cb96b-e473-4f3a-9b9c-5aa8020c2610) ![image (1)](https://github.com/MetaMask/metamask-extension/assets/8112138/c16d28f7-f05c-4132-8268-b3c48fe9bd4a) ## **Related issues** Fixes: https://github.com/MetaMask/metamask-extension/issues/24916 ## **Manual testing steps** Check all [removed and changed](https://github.com/MetaMask/design-tokens/blob/main/MIGRATION.md#from-version-300-to-400) CSS variables are no longer in the codebase: 1. Pull this branch. 2. Copy [this script](https://gist.github.com/georgewrmarshall/1ca0d7044bfa3c91343cadbf2bd5c828) that checks for all deprecated colors to the root of the extension. 3. Run `node searchDeprecatedTokens.js`. 4. Ensure there are no results. Check shadows and network colors work as expected: 1. Navigate to stories that use primary and error shadows (`ButtonPrimary`, `ButtonSecondary`, `Button` (deprecated)) as well as network colors (`Box` BackgroundColors story). 2. Verify that shadows and network colors work as expected. Run the extension and navigate around to ensure colors work as expected: 1. Pull this branch. 2. Run `yarn start`. 3. Navigate around the extension in light and dark mode to ensure colors work as expected. ## **Screenshots/Recordings** ### **Before** Checking the codebase for any existing deprecated colors returns many results in the `develop` branch. https://github.com/MetaMask/metamask-extension/assets/8112138/8ad23392-a0cc-4be5-8a50-12a126f5b71c ### **After** Checking the codebase for any deprecated removed colors that could break the UI using the provided script, after removing network colors, returns no results. https://github.com/MetaMask/metamask-extension/assets/8112138/3b82862d-5302-466f-bc55-bbb05a924ac0 Checking components that use updated CSS variables and newly added still work as expected https://github.com/MetaMask/metamask-extension/assets/8112138/b70279b9-07f3-4315-abcd-83090ca03eef Checking extension colors are working as expected in light and dark mode. In dark mode primary and error are a shade lighter in v4 https://github.com/MetaMask/metamask-extension/assets/8112138/d748f8cb-f2f2-4bd5-b9f4-f3bb376f22cd ## **Pre-merge author checklist** - [x] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .storybook/3.COLORS.stories.mdx | 10 ++--- .storybook/4.SHADOW.stories.mdx | 16 ++++---- package.json | 2 +- .../incoming-transaction-toggle.test.js.snap | 14 +++---- .../button-primary/button-primary.scss | 4 +- .../button-secondary/button-secondary.scss | 4 +- .../multichain/address-copy-button/index.scss | 2 +- .../multichain/ramps-card/index.scss | 6 +-- ui/components/ui/button/buttons.scss | 8 ++-- ui/css/base-styles.scss | 2 +- ui/css/utilities/colors.scss | 14 +++++-- .../advanced-tab.component.test.js.snap | 16 ++++---- .../developer-options-tab.test.tsx.snap | 4 +- .../__snapshots__/security-tab.test.js.snap | 40 +++++++++---------- ui/pages/unlock-page/index.scss | 5 +-- yarn.lock | 10 ++--- 16 files changed, 82 insertions(+), 75 deletions(-) diff --git a/.storybook/3.COLORS.stories.mdx b/.storybook/3.COLORS.stories.mdx index 506983c34df5..04f3c980d38c 100644 --- a/.storybook/3.COLORS.stories.mdx +++ b/.storybook/3.COLORS.stories.mdx @@ -18,7 +18,7 @@ We follow a 3 tiered system for color design tokens and css variables. <div style={{ textAlign: 'center', - backgroundColor: 'var(--brand-colors-white-white000)', + backgroundColor: 'var(--brand-colors-white)', padding: 32, }} > @@ -36,9 +36,9 @@ These colors **SHOULD NOT** be used in your styles directly. They are used as a ```css /** !!!DO NOT USE BRAND COLORS DIRECTLY IN YOUR CODE!!! */ -var(--brand-colors-white-white000) -var(--brand-colors-white-white010) -var(--brand-colors-grey-grey030) +var(--brand-colors-white) +var(--brand-colors-black) +var(--brand-colors-grey-grey800) ``` ### **Theme colors** (tier 2) @@ -168,7 +168,7 @@ Don't use static hex values or brand color tokens in your code. * Not theme compatible and will break UI when using dark theme **/ .card { - background-color: var(--brand-colors-white-white000); + background-color: var(--brand-colors-white); color: var(--brand-colors-grey-grey800); } ``` diff --git a/.storybook/4.SHADOW.stories.mdx b/.storybook/4.SHADOW.stories.mdx index 3401b8b0d964..95ecac5c3f15 100644 --- a/.storybook/4.SHADOW.stories.mdx +++ b/.storybook/4.SHADOW.stories.mdx @@ -115,7 +115,7 @@ As well as the neutral colors for shadow 2 other colors exist that are used for style={{ height: 100, backgroundColor: 'var(--color-primary-default)', - boxShadow: 'var(--shadow-size-lg) var(--color-primary-shadow)', + boxShadow: 'var(--shadow-size-lg) var(--color-shadow-primary)', borderRadius: '4px', display: 'grid', alignContent: 'center', @@ -129,7 +129,7 @@ As well as the neutral colors for shadow 2 other colors exist that are used for style={{ height: 100, backgroundColor: 'var(--color-error-default)', - boxShadow: 'var(--shadow-size-lg) var(--color-error-shadow)', + boxShadow: 'var(--shadow-size-lg) var(--color-shadow-error)', borderRadius: '4px', display: 'grid', alignContent: 'center', @@ -144,8 +144,8 @@ As well as the neutral colors for shadow 2 other colors exist that are used for | Color | CSS | | ----------- | ----------------------------- | | **neutral** | `var(--color-shadow-default)` | -| **primary** | `var(--color-primary-shadow)` | -| **danger** | `var(--color-error-shadow)` | +| **primary** | `var(--color-shadow-primary)` | +| **danger** | `var(--color-shadow-error)` | ## Example usage @@ -232,7 +232,7 @@ Using both size and color tokens, different shadows can be applied to components justifyContent: 'center', height: 100, textAlign: 'center', - boxShadow: 'var(--shadow-size-sm) var(--color-primary-shadow)', + boxShadow: 'var(--shadow-size-sm) var(--color-shadow-primary)', backgroundColor: 'var(--color-primary-default)', color: 'var(--color-primary-inverse)', }} @@ -247,7 +247,7 @@ Using both size and color tokens, different shadows can be applied to components justifyContent: 'center', height: 100, textAlign: 'center', - boxShadow: 'var(--shadow-size-sm) var(--color-error-shadow)', + boxShadow: 'var(--shadow-size-sm) var(--color-shadow-error)', backgroundColor: 'var(--color-error-default)', color: 'var(--color-error-inverse)', }} @@ -263,8 +263,8 @@ Using both size and color tokens, different shadows can be applied to components | **Dropdown** | `box-shadow: var(--shadow-size-sm) var(--color-shadow-default);` | | **Toast** | `box-shadow: var(--shadow-size-md) var(--color-shadow-default);` | | **Modal** | `box-shadow: var(--shadow-size-lg) var(--color-shadow-default);` | -| **Button Primary Hover** | `box-shadow: var(--shadow-size-sm) var(--color-primary-shadow);` | -| **Button Danger Hover** | `box-shadow: var(--shadow-size-sm) var(--color-error-shadow);` | +| **Button Primary Hover** | `box-shadow: var(--shadow-size-sm) var(--color-shadow-primary);` | +| **Button Danger Hover** | `box-shadow: var(--shadow-size-sm) var(--color-shadow-error);` | ## Takeaways diff --git a/package.json b/package.json index b4ece58b2e55..2d9836b3c06e 100644 --- a/package.json +++ b/package.json @@ -290,7 +290,7 @@ "@metamask/browser-passworder": "^4.3.0", "@metamask/contract-metadata": "^2.5.0", "@metamask/controller-utils": "^10.0.0", - "@metamask/design-tokens": "^3.0.0", + "@metamask/design-tokens": "^4.0.0", "@metamask/ens-controller": "^10.0.1", "@metamask/eth-json-rpc-filters": "^7.0.0", "@metamask/eth-json-rpc-middleware": "^12.1.1", diff --git a/ui/components/app/incoming-trasaction-toggle/__snapshots__/incoming-transaction-toggle.test.js.snap b/ui/components/app/incoming-trasaction-toggle/__snapshots__/incoming-transaction-toggle.test.js.snap index 0f6521e00795..faf8faf6dedf 100644 --- a/ui/components/app/incoming-trasaction-toggle/__snapshots__/incoming-transaction-toggle.test.js.snap +++ b/ui/components/app/incoming-trasaction-toggle/__snapshots__/incoming-transaction-toggle.test.js.snap @@ -63,7 +63,7 @@ exports[`IncomingTransactionToggle should render existing incoming transaction p style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -150,7 +150,7 @@ exports[`IncomingTransactionToggle should render existing incoming transaction p style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -233,7 +233,7 @@ exports[`IncomingTransactionToggle should render existing incoming transaction p style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -316,7 +316,7 @@ exports[`IncomingTransactionToggle should render existing incoming transaction p style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -399,7 +399,7 @@ exports[`IncomingTransactionToggle should render existing incoming transaction p style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -486,7 +486,7 @@ exports[`IncomingTransactionToggle should render existing incoming transaction p style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -573,7 +573,7 @@ exports[`IncomingTransactionToggle should render existing incoming transaction p style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" diff --git a/ui/components/component-library/button-primary/button-primary.scss b/ui/components/component-library/button-primary/button-primary.scss index 2ffe80992027..ef3eb3e7947c 100644 --- a/ui/components/component-library/button-primary/button-primary.scss +++ b/ui/components/component-library/button-primary/button-primary.scss @@ -3,7 +3,7 @@ color: var(--color-primary-inverse); box-shadow: var(--shadow-size-sm) - var(--color-primary-shadow); + var(--color-shadow-primary); } &:active { @@ -17,7 +17,7 @@ color: var(--color-error-inverse); box-shadow: var(--shadow-size-sm) - var(--color-error-shadow); + var(--color-shadow-error); } &:active { diff --git a/ui/components/component-library/button-secondary/button-secondary.scss b/ui/components/component-library/button-secondary/button-secondary.scss index 3a0c43d17526..89530f3eb0a5 100644 --- a/ui/components/component-library/button-secondary/button-secondary.scss +++ b/ui/components/component-library/button-secondary/button-secondary.scss @@ -4,7 +4,7 @@ background-color: var(--color-primary-default); box-shadow: var(--shadow-size-sm) - var(--color-primary-shadow);; + var(--color-shadow-primary);; } &:active { @@ -24,7 +24,7 @@ background-color: var(--color-error-default); box-shadow: var(--shadow-size-sm) - var(--color-error-shadow); + var(--color-shadow-error); } &:active { diff --git a/ui/components/multichain/address-copy-button/index.scss b/ui/components/multichain/address-copy-button/index.scss index 4d1b84b2898c..ceb47dbdc5bc 100644 --- a/ui/components/multichain/address-copy-button/index.scss +++ b/ui/components/multichain/address-copy-button/index.scss @@ -8,7 +8,7 @@ .custody-logo { height: 20px; - background-color: var(--brand-colors-white-white000); + background-color: var(--brand-colors-white); padding: 1px; border-radius: 5px; } diff --git a/ui/components/multichain/ramps-card/index.scss b/ui/components/multichain/ramps-card/index.scss index a394311eeda9..d46a317e9357 100644 --- a/ui/components/multichain/ramps-card/index.scss +++ b/ui/components/multichain/ramps-card/index.scss @@ -4,15 +4,15 @@ &__cta-button { width: fit-content; color: var(--brand-colors-grey-grey800); - background-color: var(--brand-colors-white-white000); + background-color: var(--brand-colors-white); } &__title { - color: var(--brand-colors-white-white000); + color: var(--brand-colors-white); } &__body { - color: var(--brand-colors-white-white000); + color: var(--brand-colors-white); width: 80%; } } diff --git a/ui/components/ui/button/buttons.scss b/ui/components/ui/button/buttons.scss index 6c6fe36bd8e7..8594cb04f4da 100644 --- a/ui/components/ui/button/buttons.scss +++ b/ui/components/ui/button/buttons.scss @@ -196,7 +196,7 @@ input[type="submit"][disabled] { border: 1px solid var(--color-primary-default); &:hover { - box-shadow: var(--shadow-size-sm) var(--color-primary-shadow); + box-shadow: var(--shadow-size-sm) var(--color-shadow-primary); } &:active { @@ -220,7 +220,7 @@ input[type="submit"][disabled] { border: 1px solid var(--color-error-default); &:hover { - box-shadow: var(--shadow-size-sm) var(--color-error-shadow); + box-shadow: var(--shadow-size-sm) var(--color-shadow-error); } &:active { @@ -250,7 +250,7 @@ input[type="submit"][disabled] { background-color: var(--color-primary-default); &:hover { - box-shadow: var(--shadow-size-sm) var(--color-primary-shadow); + box-shadow: var(--shadow-size-sm) var(--color-shadow-primary); } &:active { @@ -262,7 +262,7 @@ input[type="submit"][disabled] { background-color: var(--color-error-default); &:hover { - box-shadow: var(--shadow-size-sm) var(--color-error-shadow); + box-shadow: var(--shadow-size-sm) var(--color-shadow-error); } &:active { diff --git a/ui/css/base-styles.scss b/ui/css/base-styles.scss index 048a0d69040b..a98e965e74b8 100644 --- a/ui/css/base-styles.scss +++ b/ui/css/base-styles.scss @@ -31,7 +31,7 @@ html { */ @media (prefers-color-scheme: dark) { &:not([data-theme]) { - color: var(--brand-colors-white-white000); + color: var(--brand-colors-white); background-color: var(--brand-colors-grey-grey900); } diff --git a/ui/css/utilities/colors.scss b/ui/css/utilities/colors.scss index facb925e431c..634a484d736a 100644 --- a/ui/css/utilities/colors.scss +++ b/ui/css/utilities/colors.scss @@ -9,13 +9,21 @@ Before adding a color here make sure that there isn't a design token available. --mainnet: #29b6af; --inherit: inherit; --transparent: transparent; + // DO NOT CHANGE + // Required for the QR reader to work properly + --qr-code-white-background: #fff; + // DEPRECATED + // These third party network colors have been deprecated and should be removed once they are no longer in use. We should be using images to represent these networks instead. + --color-network-goerli-default: #1098fc; + --color-network-sepolia-default: #cfb5f0; + --color-network-goerli-inverse: #fcfcfc; + --color-network-sepolia-inverse: #fcfcfc; + --color-network-localhost-default: #bbc0c5; + --color-network-localhost-inverse: #fcfcfc; --color-network-linea-goerli-default: #61dfff; --color-network-linea-goerli-inverse: #fcfcfc; --color-network-linea-sepolia-default: #61dfff; --color-network-linea-sepolia-inverse: #fcfcfc; --color-network-linea-mainnet-default: #121212; --color-network-linea-mainnet-inverse: #fcfcfc; - // DO NOT CHANGE - // Required for the QR reader to work properly - --qr-code-white-background: #fff; } diff --git a/ui/pages/settings/advanced-tab/__snapshots__/advanced-tab.component.test.js.snap b/ui/pages/settings/advanced-tab/__snapshots__/advanced-tab.component.test.js.snap index 39f2a38c9f88..72c46529b4db 100644 --- a/ui/pages/settings/advanced-tab/__snapshots__/advanced-tab.component.test.js.snap +++ b/ui/pages/settings/advanced-tab/__snapshots__/advanced-tab.component.test.js.snap @@ -105,7 +105,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -172,7 +172,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -238,7 +238,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -304,7 +304,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -370,7 +370,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -436,7 +436,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -622,7 +622,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -688,7 +688,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" diff --git a/ui/pages/settings/developer-options-tab/__snapshots__/developer-options-tab.test.tsx.snap b/ui/pages/settings/developer-options-tab/__snapshots__/developer-options-tab.test.tsx.snap index ad9599831cd8..ff16d1cf726d 100644 --- a/ui/pages/settings/developer-options-tab/__snapshots__/developer-options-tab.test.tsx.snap +++ b/ui/pages/settings/developer-options-tab/__snapshots__/developer-options-tab.test.tsx.snap @@ -127,7 +127,7 @@ exports[`Develop options tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -197,7 +197,7 @@ exports[`Develop options tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" diff --git a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap index ab4fc6467faa..d2d94434223a 100644 --- a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap +++ b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap @@ -44,7 +44,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -155,7 +155,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -248,7 +248,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -327,7 +327,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -404,7 +404,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -507,7 +507,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -607,7 +607,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -694,7 +694,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -777,7 +777,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -860,7 +860,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -947,7 +947,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -1026,7 +1026,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -1152,7 +1152,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -1223,7 +1223,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -1337,7 +1337,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -1427,7 +1427,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -1493,7 +1493,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" @@ -1560,7 +1560,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -1626,7 +1626,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(16, 152, 252);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(67, 174, 252);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;" @@ -1707,7 +1707,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" diff --git a/ui/pages/unlock-page/index.scss b/ui/pages/unlock-page/index.scss index 44081cc81b05..abb1f837bdef 100644 --- a/ui/pages/unlock-page/index.scss +++ b/ui/pages/unlock-page/index.scss @@ -23,9 +23,8 @@ position: relative; &__beta { - /* these colors should be used on both light and dark mode */ - background: var(--brand-colors-blue-blue500); - color: var(--brand-colors-white-white000); + background: var(--color-primary-default); + color: var(--color-primary-inverse); padding: 3px 6px; font-size: 16px; position: absolute; diff --git a/yarn.lock b/yarn.lock index c332e4141c2b..cf50e0a9db6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4975,10 +4975,10 @@ __metadata: languageName: node linkType: hard -"@metamask/design-tokens@npm:^3.0.0": - version: 3.0.0 - resolution: "@metamask/design-tokens@npm:3.0.0" - checksum: 10/65c809fb5877398a0e45f3a22c09c8f7b64972961497f465a4c85eb6492e7e7d1168d4718cd21442dfb54a1f4b79d0287c6d5f5f5faa652dfcc5ababb1894095 +"@metamask/design-tokens@npm:^4.0.0": + version: 4.0.0 + resolution: "@metamask/design-tokens@npm:4.0.0" + checksum: 10/337968d86bf963ccdf7ab416cc8f87ec1d35d9fb56f686dea954964edd6f5cb0067a920cb2c1f9008150d3decac51cb1b392b3e67dc1d46ca308b503ffe7eabd languageName: node linkType: hard @@ -24877,7 +24877,7 @@ __metadata: "@metamask/build-utils": "npm:^1.0.0" "@metamask/contract-metadata": "npm:^2.5.0" "@metamask/controller-utils": "npm:^10.0.0" - "@metamask/design-tokens": "npm:^3.0.0" + "@metamask/design-tokens": "npm:^4.0.0" "@metamask/ens-controller": "npm:^10.0.1" "@metamask/eslint-config": "npm:^9.0.0" "@metamask/eslint-config-jest": "npm:^9.0.0" From 4f7f8f0322927d9968d0608e9ef7ca4e338d2973 Mon Sep 17 00:00:00 2001 From: salimtb <salim.toubal@outlook.com> Date: Tue, 11 Jun 2024 20:09:03 +0200 Subject: [PATCH 06/61] feat: add popular network list modal (#25160) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR introduces the addition of a Popular Networks list to the Add Network modal. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25160?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** 1. Run `yarn && ENABLE_NETWORK_UI_REDESIGN=1 yarn start` 2. Go to Settings -> Developer Options 3. Tun on the network new toggle 4. Go to the wallet page 5. Click on the network button ( see the video below ) 6. you should see the list of popular network 7. you should be able to add a network from the modal ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** https://github.com/MetaMask/metamask-extension/assets/26223211/bde545ef-c5a3-4cc5-9508-16edfd8507dd ### **After** https://github.com/MetaMask/metamask-extension/assets/26223211/114076c2-e336-4b96-b061-defd6d886380 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: David Walsh <davidwalsh83@gmail.com> --- app/_locales/en/messages.json | 3 + shared/constants/metametrics.ts | 1 + ...network-confirmation-popover.test.tsx.snap | 3 + .../network-confirmation-popover.test.tsx | 45 +++++++ .../network-confirmation-popover.tsx | 40 ++++++ .../network-list-menu/network-list-menu.js | 72 +++++++--- .../network-list-menu.test.js | 10 ++ .../PopularNetworkList.stories.js | 85 ++++++++++++ .../popular-network-list.test.tsx.snap | 13 ++ .../popular-network-list.test.tsx | 113 ++++++++++++++++ .../popular-network-list.tsx | 125 ++++++++++++++++++ ui/pages/routes/routes.component.js | 4 + ui/pages/routes/routes.component.test.js | 5 + ui/pages/routes/routes.container.js | 2 + 14 files changed, 501 insertions(+), 20 deletions(-) create mode 100644 ui/components/multichain/network-list-menu/network-confirmation-popover/__snapshots__/network-confirmation-popover.test.tsx.snap create mode 100644 ui/components/multichain/network-list-menu/network-confirmation-popover/network-confirmation-popover.test.tsx create mode 100644 ui/components/multichain/network-list-menu/network-confirmation-popover/network-confirmation-popover.tsx create mode 100644 ui/components/multichain/network-list-menu/popular-network-list/PopularNetworkList.stories.js create mode 100644 ui/components/multichain/network-list-menu/popular-network-list/__snapshots__/popular-network-list.test.tsx.snap create mode 100644 ui/components/multichain/network-list-menu/popular-network-list/popular-network-list.test.tsx create mode 100644 ui/components/multichain/network-list-menu/popular-network-list/popular-network-list.tsx diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 4ac143e9554b..44434c77b44a 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -314,6 +314,9 @@ "addingTokens": { "message": "Adding tokens" }, + "additionalNetworks": { + "message": "Additional networks" + }, "address": { "message": "Address" }, diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts index 0e46bcf5046d..ed07ad3a4b58 100644 --- a/shared/constants/metametrics.ts +++ b/shared/constants/metametrics.ts @@ -793,6 +793,7 @@ export enum MetaMetricsNetworkEventSource { PopularNetworkList = 'popular_network_list', Dapp = 'dapp', DeprecatedNetworkModal = 'deprecated_network_modal', + NewAddNetworkFlow = 'new_add_network_flow', } export enum MetaMetricsSwapsEventSource { diff --git a/ui/components/multichain/network-list-menu/network-confirmation-popover/__snapshots__/network-confirmation-popover.test.tsx.snap b/ui/components/multichain/network-list-menu/network-confirmation-popover/__snapshots__/network-confirmation-popover.test.tsx.snap new file mode 100644 index 000000000000..193bbae014a2 --- /dev/null +++ b/ui/components/multichain/network-list-menu/network-confirmation-popover/__snapshots__/network-confirmation-popover.test.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NetworkConfirmationPopover renders popular list component 1`] = `<div />`; diff --git a/ui/components/multichain/network-list-menu/network-confirmation-popover/network-confirmation-popover.test.tsx b/ui/components/multichain/network-list-menu/network-confirmation-popover/network-confirmation-popover.test.tsx new file mode 100644 index 000000000000..8efca30b61fc --- /dev/null +++ b/ui/components/multichain/network-list-menu/network-confirmation-popover/network-confirmation-popover.test.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import { ApprovalType } from '@metamask/controller-utils'; +import { renderWithProvider } from '../../../../../test/lib/render-helpers'; +import mockState from '../../../../../test/data/mock-state.json'; +import NetworkConfirmationPopover from './network-confirmation-popover'; + +describe('NetworkConfirmationPopover', () => { + const mockUnapprovedConfirmations = [ + { + id: '1', + origin: 'metamask', + type: ApprovalType.AddEthereumChain, + }, + ]; + + const STATE_MOCK = { + ...mockState, + unapprovedConfirmations: mockUnapprovedConfirmations, + }; + const mockStore = configureMockStore([])(STATE_MOCK); + + it('renders popular list component', () => { + const { container } = renderWithProvider( + <NetworkConfirmationPopover />, + mockStore, + ); + + expect(container).toMatchSnapshot(); + }); + + it('does not render the popover when there are no unapproved AddEthereumChain confirmations', () => { + const emptyStateMock = { + ...mockState, + unapprovedConfirmations: [], + }; + const emptyMockStore = configureMockStore([])(emptyStateMock); + + const { queryByText } = renderWithProvider( + <NetworkConfirmationPopover />, + emptyMockStore, + ); + expect(queryByText('ConfirmationPage content')).not.toBeInTheDocument(); + }); +}); diff --git a/ui/components/multichain/network-list-menu/network-confirmation-popover/network-confirmation-popover.tsx b/ui/components/multichain/network-list-menu/network-confirmation-popover/network-confirmation-popover.tsx new file mode 100644 index 000000000000..520394fb8e03 --- /dev/null +++ b/ui/components/multichain/network-list-menu/network-confirmation-popover/network-confirmation-popover.tsx @@ -0,0 +1,40 @@ +import React, { useEffect, useState } from 'react'; +import { useSelector } from 'react-redux'; +import { ApprovalType } from '@metamask/controller-utils'; +import { ORIGIN_METAMASK } from '@metamask/approval-controller'; +import Popover from '../../../ui/popover'; +import ConfirmationPage from '../../../../pages/confirmations/confirmation/confirmation'; +import { getUnapprovedConfirmations } from '../../../../selectors'; + +const NetworkConfirmationPopover = () => { + const [showPopover, setShowPopover] = useState(false); + + const unapprovedConfirmations = useSelector(getUnapprovedConfirmations); + + useEffect(() => { + const anAddNetworkConfirmationFromMetaMaskExists = + unapprovedConfirmations?.find( + (confirmation) => + confirmation.origin === ORIGIN_METAMASK && + confirmation.type === ApprovalType.AddEthereumChain, + ); + + if (!showPopover && anAddNetworkConfirmationFromMetaMaskExists) { + setShowPopover(true); + } else if (showPopover && !anAddNetworkConfirmationFromMetaMaskExists) { + setShowPopover(false); + } + }, [unapprovedConfirmations, showPopover]); + + if (!showPopover) { + return null; + } + + return ( + <Popover data-testid="network-popover"> + <ConfirmationPage redirectToHomeOnZeroConfirmations={false} /> + </Popover> + ); +}; + +export default NetworkConfirmationPopover; diff --git a/ui/components/multichain/network-list-menu/network-list-menu.js b/ui/components/multichain/network-list-menu/network-list-menu.js index 26e6e3d94007..549164b7b21a 100644 --- a/ui/components/multichain/network-list-menu/network-list-menu.js +++ b/ui/components/multichain/network-list-menu/network-list-menu.js @@ -16,7 +16,10 @@ import { updateNetworksList, setNetworkClientIdForDomain, } from '../../../store/actions'; -import { TEST_CHAINS } from '../../../../shared/constants/network'; +import { + FEATURED_RPCS, + TEST_CHAINS, +} from '../../../../shared/constants/network'; import { getCurrentChainId, getCurrentNetwork, @@ -28,6 +31,7 @@ import { getShowNetworkBanner, getOriginOfCurrentTab, getUseRequestQueue, + getNetworkConfigurations, } from '../../../selectors'; import ToggleButton from '../../ui/toggle-button'; import { @@ -49,9 +53,9 @@ import { Text, BannerBase, IconName, + ModalContent, + ModalHeader, } from '../../component-library'; -import { ModalContent } from '../../component-library/modal-content/deprecated'; -import { ModalHeader } from '../../component-library/modal-header/deprecated'; import { TextFieldSearch } from '../../component-library/text-field-search/deprecated'; import { ADD_POPULAR_CUSTOM_NETWORK } from '../../../helpers/constants/routes'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; @@ -65,6 +69,8 @@ import { getCompletedOnboarding, getIsUnlocked, } from '../../../ducks/metamask/metamask'; +import { getLocalNetworkMenuRedesignFeatureFlag } from '../../../helpers/utils/feature-flags'; +import PopularNetworkList from './popular-network-list/popular-network-list'; export const NetworkListMenu = ({ onClose }) => { const t = useI18nContext(); @@ -73,9 +79,13 @@ export const NetworkListMenu = ({ onClose }) => { const testNetworks = useSelector(getTestNetworks); const showTestNetworks = useSelector(getShowTestNetworks); const currentChainId = useSelector(getCurrentChainId); + const networkMenuRedesign = useSelector( + getLocalNetworkMenuRedesignFeatureFlag, + ); const selectedTabOrigin = useSelector(getOriginOfCurrentTab); const useRequestQueue = useSelector(getUseRequestQueue); + const networkConfigurations = useSelector(getNetworkConfigurations); const dispatch = useDispatch(); const history = useHistory(); @@ -95,6 +105,17 @@ export const NetworkListMenu = ({ onClose }) => { const orderedNetworksList = useSelector(getOrderedNetworksList); + const networkConfigurationChainIds = Object.values(networkConfigurations).map( + (net) => net.chainId, + ); + + const sortedFeaturedNetworks = FEATURED_RPCS.sort((a, b) => + a.nickname > b.nickname ? 1 : -1, + ).slice(0, FEATURED_RPCS.length); + + const notExistingNetworkConfigurations = sortedFeaturedNetworks.filter( + ({ chainId }) => !networkConfigurationChainIds.includes(chainId), + ); const newOrderNetworks = () => { if (!orderedNetworksList || orderedNetworksList.length === 0) { return nonTestNetworks; @@ -153,6 +174,12 @@ export const NetworkListMenu = ({ onClose }) => { let searchResults = [...networksList].length === items.length ? items : [...networksList]; + + const searchAddNetworkResults = + [...notExistingNetworkConfigurations].length === items.length + ? items + : [...notExistingNetworkConfigurations]; + const isSearching = searchQuery !== ''; if (isSearching) { @@ -405,24 +432,29 @@ export const NetworkListMenu = ({ onClose }) => { </Droppable> </DragDropContext> )} - </Box> - <Box - padding={4} - display={Display.Flex} - justifyContent={JustifyContent.spaceBetween} - > - <Text>{t('showTestnetNetworks')}</Text> - <ToggleButton - value={showTestNetworks} - disabled={currentlyOnTestNetwork} - onToggle={handleToggle} - /> - </Box> - {showTestNetworks || currentlyOnTestNetwork ? ( - <Box className="multichain-network-list-menu"> - {generateMenuItems(testNetworks)} + {networkMenuRedesign ? ( + <PopularNetworkList + searchAddNetworkResults={searchAddNetworkResults} + /> + ) : null} + <Box + padding={4} + display={Display.Flex} + justifyContent={JustifyContent.spaceBetween} + > + <Text>{t('showTestnetNetworks')}</Text> + <ToggleButton + value={showTestNetworks} + disabled={currentlyOnTestNetwork} + onToggle={handleToggle} + /> </Box> - ) : null} + {showTestNetworks || currentlyOnTestNetwork ? ( + <Box className="multichain-network-list-menu"> + {generateMenuItems(testNetworks)} + </Box> + ) : null} + </Box> <Box padding={4}> <ButtonSecondary size={ButtonSecondarySize.Lg} diff --git a/ui/components/multichain/network-list-menu/network-list-menu.test.js b/ui/components/multichain/network-list-menu/network-list-menu.test.js index 83ebf8d03250..031ad257317c 100644 --- a/ui/components/multichain/network-list-menu/network-list-menu.test.js +++ b/ui/components/multichain/network-list-menu/network-list-menu.test.js @@ -13,6 +13,7 @@ import { NetworkListMenu } from '.'; const mockSetShowTestNetworks = jest.fn(); const mockSetProviderType = jest.fn(); const mockToggleNetworkMenu = jest.fn(); +const mockNetworkMenuRedesignToggle = jest.fn(); jest.mock('../../../store/actions.ts', () => ({ setShowTestNetworks: () => mockSetShowTestNetworks, @@ -20,6 +21,11 @@ jest.mock('../../../store/actions.ts', () => ({ toggleNetworkMenu: () => mockToggleNetworkMenu, })); +jest.mock('../../../helpers/utils/feature-flags', () => ({ + ...jest.requireActual('../../../helpers/utils/feature-flags'), + getLocalNetworkMenuRedesignFeatureFlag: () => mockNetworkMenuRedesignToggle, +})); + const render = ({ showTestNetworks = false, currentChainId = '0x5', @@ -51,6 +57,10 @@ const render = ({ }; describe('NetworkListMenu', () => { + beforeEach(() => { + mockNetworkMenuRedesignToggle.mockReturnValue(false); + }); + it('displays important controls', () => { const { getByText, getByPlaceholderText } = render(); diff --git a/ui/components/multichain/network-list-menu/popular-network-list/PopularNetworkList.stories.js b/ui/components/multichain/network-list-menu/popular-network-list/PopularNetworkList.stories.js new file mode 100644 index 000000000000..320e951b0679 --- /dev/null +++ b/ui/components/multichain/network-list-menu/popular-network-list/PopularNetworkList.stories.js @@ -0,0 +1,85 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import testData from '../../../../../.storybook/test-data'; +import configureStore from '../../../../store/store'; +import { + CHAIN_IDS, + CURRENCY_SYMBOLS, + OPTIMISM_DISPLAY_NAME, + OPTIMISM_TOKEN_IMAGE_URL, + ZK_SYNC_ERA_DISPLAY_NAME, + ZK_SYNC_ERA_TOKEN_IMAGE_URL, +} from '../../../../../shared/constants/network'; +import PopularNetworkList from './popular-network-list'; + +const customNetworkStore = configureStore({ + ...testData, + metamask: { + ...testData.metamask, + preferences: { + showTestNetworks: true, + }, + orderedNetworkList: [], + networkConfigurations: { + ...testData.metamask.networkConfigurations, + ...{ + 'test-networkConfigurationId-1': { + chainId: CHAIN_IDS.OPTIMISM, + nickname: OPTIMISM_DISPLAY_NAME, + rpcUrl: `https://optimism-mainnet.infura.io/v3`, + ticker: CURRENCY_SYMBOLS.ETH, + rpcPrefs: { + blockExplorerUrl: 'https://optimistic.etherscan.io/', + imageUrl: OPTIMISM_TOKEN_IMAGE_URL, + }, + }, + 'test-networkConfigurationId-2': { + chainId: CHAIN_IDS.ZKSYNC_ERA, + nickname: ZK_SYNC_ERA_DISPLAY_NAME, + rpcUrl: `https://mainnet.era.zksync.io`, + ticker: CURRENCY_SYMBOLS.ETH, + rpcPrefs: { + blockExplorerUrl: 'https://explorer.zksync.io/', + imageUrl: ZK_SYNC_ERA_TOKEN_IMAGE_URL, + }, + }, + }, + }, + }, +}); + +export default { + title: 'Components/PopularNetworkList', + component: PopularNetworkList, +}; + +export const Default = (args) => ( + <Provider store={customNetworkStore}> + <PopularNetworkList {...args} /> + </Provider> +); + +Default.args = { + searchAddNetworkResults: [ + { + nickname: OPTIMISM_DISPLAY_NAME, + rpcPrefs: { + imageUrl: OPTIMISM_TOKEN_IMAGE_URL, + }, + }, + { + nickname: ZK_SYNC_ERA_DISPLAY_NAME, + rpcPrefs: { + imageUrl: ZK_SYNC_ERA_TOKEN_IMAGE_URL, + }, + }, + ], +}; + +Default.decorators = [ + (Story) => ( + <Provider store={customNetworkStore}> + <Story /> + </Provider> + ), +]; diff --git a/ui/components/multichain/network-list-menu/popular-network-list/__snapshots__/popular-network-list.test.tsx.snap b/ui/components/multichain/network-list-menu/popular-network-list/__snapshots__/popular-network-list.test.tsx.snap new file mode 100644 index 000000000000..41085f19a48c --- /dev/null +++ b/ui/components/multichain/network-list-menu/popular-network-list/__snapshots__/popular-network-list.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PopularNetworkList renders popular list component 1`] = ` +<div> + <div + class="mm-box new-network-list__networks-container" + > + <div + class="mm-box mm-box--margin-top-4 mm-box--margin-bottom-1 mm-box--padding-right-4 mm-box--padding-left-4" + /> + </div> +</div> +`; diff --git a/ui/components/multichain/network-list-menu/popular-network-list/popular-network-list.test.tsx b/ui/components/multichain/network-list-menu/popular-network-list/popular-network-list.test.tsx new file mode 100644 index 000000000000..f7354e0acefc --- /dev/null +++ b/ui/components/multichain/network-list-menu/popular-network-list/popular-network-list.test.tsx @@ -0,0 +1,113 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import { useDispatch, useSelector } from 'react-redux'; +import configureStore from 'redux-mock-store'; +import { renderWithProvider } from '../../../../../test/lib/render-helpers'; +import { getUnapprovedConfirmations } from '../../../../selectors'; +import { + CHAIN_IDS, + RPCDefinition, +} from '../../../../../shared/constants/network'; +import PopularNetworkList from './popular-network-list'; + +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useDispatch: jest.fn(), + useSelector: jest.fn(), +})); + +const STATE_MOCK = { + metamask: { + providerConfig: { + chainId: '0x1', + }, + }, +}; + +describe('PopularNetworkList', () => { + const store = configureStore()(STATE_MOCK); + const useDispatchMock = useDispatch as jest.Mock; + const useSelectorMock = useSelector as jest.Mock; + const mockDispatch = jest.fn(); + + beforeEach(() => { + jest.resetAllMocks(); + useDispatchMock.mockReturnValue(mockDispatch); + + useSelectorMock.mockImplementation((selector) => { + if (selector === getUnapprovedConfirmations) { + return []; + } + return undefined; + }); + }); + + const defaultProps = { + searchAddNetworkResults: [], + }; + + it('renders popular list component', () => { + const { container } = renderWithProvider( + <PopularNetworkList {...defaultProps} />, + store, + ); + + expect(container).toMatchSnapshot(); + }); + + it('displays the network list when networks are provided', () => { + const props = { + ...defaultProps, + searchAddNetworkResults: [ + { + chainId: CHAIN_IDS.MAINNET, + nickname: 'Network 1', + rpcPrefs: { + blockExplorerUrl: 'https://etherscan.com/', + imageUrl: 'https://example.com/image1.png', + }, + ticker: 'ETH', + rpcUrl: 'https://exampleEth.org/', + }, + { + chainId: CHAIN_IDS.BSC_TESTNET, + nickname: 'Network 2', + rpcPrefs: { + blockExplorerUrl: 'https://examplescan.com/', + imageUrl: 'https://example.com/image2.png', + }, + ticker: 'TST', + rpcUrl: 'https://example.org/', + }, + ] as RPCDefinition[], + }; + + render(<PopularNetworkList {...props} />); + expect(screen.getByText('Network 1')).toBeInTheDocument(); + expect(screen.getByText('Network 2')).toBeInTheDocument(); + }); + it('calls the dispatch function when the add button is clicked', async () => { + const props = { + ...defaultProps, + searchAddNetworkResults: [ + { + chainId: CHAIN_IDS.BSC_TESTNET, + nickname: 'Network 2', + rpcPrefs: { + blockExplorerUrl: 'https://examplescan.com/', + imageUrl: 'https://example.com/image2.png', + }, + ticker: 'TST', + rpcUrl: 'https://example.org/', + }, + ] as RPCDefinition[], + }; + + render(<PopularNetworkList {...props} />); + const addButton = screen.getByTestId('test-add-button'); + fireEvent.click(addButton); + + expect(useDispatchMock).toHaveBeenCalled(); + }); +}); diff --git a/ui/components/multichain/network-list-menu/popular-network-list/popular-network-list.tsx b/ui/components/multichain/network-list-menu/popular-network-list/popular-network-list.tsx new file mode 100644 index 000000000000..6d2cd02f5170 --- /dev/null +++ b/ui/components/multichain/network-list-menu/popular-network-list/popular-network-list.tsx @@ -0,0 +1,125 @@ +import React from 'react'; +import { ApprovalType } from '@metamask/controller-utils'; +import { useDispatch } from 'react-redux'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; +import { + Box, + Text, + AvatarNetwork, + Button, + AvatarNetworkSize, + ButtonVariant, +} from '../../../component-library'; +import { MetaMetricsNetworkEventSource } from '../../../../../shared/constants/metametrics'; +import { + ENVIRONMENT_TYPE_POPUP, + ORIGIN_METAMASK, +} from '../../../../../shared/constants/app'; +import { + requestUserApproval, + toggleNetworkMenu, +} from '../../../../store/actions'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import { + AlignItems, + BackgroundColor, + Display, + JustifyContent, + TextColor, +} from '../../../../helpers/constants/design-system'; +import { RPCDefinition } from '../../../../../shared/constants/network'; + +const PopularNetworkList = ({ + searchAddNetworkResults, +}: { + searchAddNetworkResults: RPCDefinition[]; +}) => { + const t = useI18nContext(); + const isPopUp = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP; + const dispatch = useDispatch(); + + return ( + <Box className="new-network-list__networks-container"> + <Box + marginTop={isPopUp ? 0 : 4} + marginBottom={1} + paddingLeft={4} + paddingRight={4} + > + {Object.keys(searchAddNetworkResults).length === 0 ? null : ( + <Box + marginTop={4} + marginBottom={8} + display={Display.Flex} + justifyContent={JustifyContent.spaceBetween} + > + <Text> {t('additionalNetworks')}</Text> + </Box> + )} + + {searchAddNetworkResults.map((item: RPCDefinition, index: number) => ( + <Box + key={index} + display={Display.Flex} + alignItems={AlignItems.center} + justifyContent={JustifyContent.spaceBetween} + marginBottom={6} + className="new-network-list__list-of-networks" + > + <Box display={Display.Flex} alignItems={AlignItems.center}> + <AvatarNetwork + size={AvatarNetworkSize.Md} + src={item.rpcPrefs?.imageUrl} + name={item.nickname} + /> + <Box marginLeft={2}> + <Text + color={TextColor.textDefault} + backgroundColor={BackgroundColor.transparent} + ellipsis + > + {item.nickname} + </Text> + </Box> + </Box> + <Box + display={Display.Flex} + alignItems={AlignItems.center} + marginLeft={1} + > + <Button + type={ButtonVariant.Link} + className="add-network__add-button" + variant={ButtonVariant.Link} + data-testid="test-add-button" + onClick={async () => { + dispatch(toggleNetworkMenu()); + await dispatch( + requestUserApproval({ + origin: ORIGIN_METAMASK, + type: ApprovalType.AddEthereumChain, + requestData: { + chainId: item.chainId, + rpcUrl: item.rpcUrl, + ticker: item.ticker, + rpcPrefs: item.rpcPrefs, + imageUrl: item.rpcPrefs?.imageUrl, + chainName: item.nickname, + referrer: ORIGIN_METAMASK, + source: MetaMetricsNetworkEventSource.NewAddNetworkFlow, + }, + }), + ); + }} + > + {t('add')} + </Button> + </Box> + </Box> + ))} + </Box> + </Box> + ); +}; + +export default PopularNetworkList; diff --git a/ui/pages/routes/routes.component.js b/ui/pages/routes/routes.component.js index e93b417c83fd..f33aed54aa12 100644 --- a/ui/pages/routes/routes.component.js +++ b/ui/pages/routes/routes.component.js @@ -129,6 +129,7 @@ import { getURLHost } from '../../helpers/utils/util'; import { BorderColor, IconColor } from '../../helpers/constants/design-system'; import { MILLISECOND } from '../../../shared/constants/time'; import { MultichainMetaFoxLogo } from '../../components/multichain/app-header/multichain-meta-fox-logo'; +import NetworkConfirmationPopover from '../../components/multichain/network-list-menu/network-confirmation-popover/network-confirmation-popover'; const isConfirmTransactionRoute = (pathname) => Boolean( @@ -199,6 +200,7 @@ export default class Routes extends Component { currentExtensionPopupId: PropTypes.number, useRequestQueue: PropTypes.bool, showSurveyToast: PropTypes.bool.isRequired, + networkMenuRedesign: PropTypes.bool.isRequired, showPrivacyPolicyToast: PropTypes.bool.isRequired, newPrivacyPolicyToastShownDate: PropTypes.number, setSurveyLinkLastClickedOrClosed: PropTypes.func.isRequired, @@ -782,6 +784,7 @@ export default class Routes extends Component { hideDeprecatedNetworkModal, switchedNetworkDetails, clearSwitchedNetworkDetails, + networkMenuRedesign, ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) isShowKeyringSnapRemovalResultModal, hideShowKeyringSnapRemovalResultModal, @@ -864,6 +867,7 @@ export default class Routes extends Component { {isNetworkMenuOpen ? ( <NetworkListMenu onClose={() => toggleNetworkMenu()} /> ) : null} + {networkMenuRedesign ? <NetworkConfirmationPopover /> : null} {accountDetailsAddress ? ( <AccountDetails address={accountDetailsAddress} /> ) : null} diff --git a/ui/pages/routes/routes.component.test.js b/ui/pages/routes/routes.component.test.js index 79941ea87fd3..e6274bfc3223 100644 --- a/ui/pages/routes/routes.component.test.js +++ b/ui/pages/routes/routes.component.test.js @@ -63,6 +63,11 @@ jest.mock( '../../components/app/metamask-template-renderer/safe-component-list', ); +jest.mock('../../helpers/utils/feature-flags', () => ({ + ...jest.requireActual('../../helpers/utils/feature-flags'), + getLocalNetworkMenuRedesignFeatureFlag: () => false, +})); + const render = async (route, state) => { const store = configureMockStore()({ ...mockSendState, diff --git a/ui/pages/routes/routes.container.js b/ui/pages/routes/routes.container.js index da708e147bcc..efa7afad4908 100644 --- a/ui/pages/routes/routes.container.js +++ b/ui/pages/routes/routes.container.js @@ -27,6 +27,7 @@ import { getShowPrivacyPolicyToast, getUseRequestQueue, } from '../../selectors'; +import { getLocalNetworkMenuRedesignFeatureFlag } from '../../helpers/utils/feature-flags'; import { getSmartTransactionsOptInStatus } from '../../../shared/modules/selectors'; import { lockMetamask, @@ -132,6 +133,7 @@ function mapStateToProps(state) { newPrivacyPolicyToastShownDate: getNewPrivacyPolicyToastShownDate(state), showPrivacyPolicyToast: getShowPrivacyPolicyToast(state), showSurveyToast: getShowSurveyToast(state), + networkMenuRedesign: getLocalNetworkMenuRedesignFeatureFlag(state), ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) isShowKeyringSnapRemovalResultModal: state.appState.showKeyringRemovalSnapModal, From fbd9bbdb9f90217e2bfdc149ca8358eb10c5a858 Mon Sep 17 00:00:00 2001 From: Danica Shen <zhaodanica@gmail.com> Date: Tue, 11 Jun 2024 20:11:00 +0100 Subject: [PATCH 07/61] fix: add deprecated tag back to callBackgroundMethod (#25216) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Removed wrongly in https://github.com/MetaMask/metamask-extension/pull/21410, this PR aims to add `deprecated` tag back to `callBackgroundMethod` for migration purpose. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25216?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- ui/store/background-connection.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/store/background-connection.ts b/ui/store/background-connection.ts index 5c7222c040e6..3928675419a8 100644 --- a/ui/store/background-connection.ts +++ b/ui/store/background-connection.ts @@ -41,6 +41,7 @@ type CallbackMethod<R = unknown> = (error?: unknown, result?: R) => void; * [Deprecated] Callback-style call to background method * invokes promisifiedBackground method directly. * + * @deprecated Use async `submitRequestToBackground` function instead. * @param method - name of the background method * @param [args] - arguments to that method, if any * @param callback - Node style (error, result) callback for finishing the operation From c67aa3feb9949526735db30a45078a60b53b3e18 Mon Sep 17 00:00:00 2001 From: David Walsh <davidwalsh83@gmail.com> Date: Tue, 11 Jun 2024 17:38:26 -0500 Subject: [PATCH 08/61] fix: UX: NetworkList: Consolidate NetworkListItem usages (#25195) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR removes duplicate code for NetworkListItem creation, instead using a helper function to create a single item. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25195?quickstart=1) ## **Related issues** Fixes: N/A ## **Manual testing steps** 1. Click "Polygon" and see chain switch to Polygon 2. Click "Ethereum Mainnet" and see chain switch to Ethereum Mainnet 3. Drag and drop networks around -- should work 4. Click the toggle to view test networks 5. Click a test network -- should change to correct network ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. Co-authored-by: Brian Bergeron <brian.e.bergeron@gmail.com> Co-authored-by: Nidhi Kumari <nidhi.kumari@consensys.net> --- .../network-list-menu/network-list-menu.js | 163 ++++++++---------- 1 file changed, 68 insertions(+), 95 deletions(-) diff --git a/ui/components/multichain/network-list-menu/network-list-menu.js b/ui/components/multichain/network-list-menu/network-list-menu.js index 549164b7b21a..da7f145e7389 100644 --- a/ui/components/multichain/network-list-menu/network-list-menu.js +++ b/ui/components/multichain/network-list-menu/network-list-menu.js @@ -200,6 +200,62 @@ export const NetworkListMenu = ({ onClose }) => { ); } + const generateNetworkListItem = ({ + network, + isCurrentNetwork, + canDeleteNetwork, + }) => { + return ( + <NetworkListItem + name={network.nickname} + iconSrc={network?.rpcPrefs?.imageUrl} + key={network.id} + selected={isCurrentNetwork} + focus={isCurrentNetwork && !showSearch} + onClick={() => { + dispatch(toggleNetworkMenu()); + if (network.providerType) { + dispatch(setProviderType(network.providerType)); + } else { + dispatch(setActiveNetwork(network.id)); + } + + // If presently on a dapp, communicate a change to + // the dapp via silent switchEthereumChain that the + // network has changed due to user action + if (useRequestQueue && selectedTabOrigin) { + setNetworkClientIdForDomain(selectedTabOrigin, network.id); + } + + trackEvent({ + event: MetaMetricsEventName.NavNetworkSwitched, + category: MetaMetricsEventCategory.Network, + properties: { + location: 'Network Menu', + chain_id: currentChainId, + from_network: currentChainId, + to_network: network.chainId, + }, + }); + }} + onDeleteClick={ + canDeleteNetwork + ? () => { + dispatch(toggleNetworkMenu()); + dispatch( + showModal({ + name: 'CONFIRM_DELETE_NETWORK', + target: network.id, + onConfirm: () => undefined, + }), + ); + } + : null + } + /> + ); + }; + const generateMenuItems = (desiredNetworks) => { return desiredNetworks.map((network) => { const isCurrentNetwork = @@ -209,47 +265,11 @@ export const NetworkListMenu = ({ onClose }) => { const canDeleteNetwork = isUnlocked && !isCurrentNetwork && network.removable; - return ( - <NetworkListItem - name={network.nickname} - iconSrc={network?.rpcPrefs?.imageUrl} - key={network.id} - selected={isCurrentNetwork} - focus={isCurrentNetwork && !showSearch} - onClick={() => { - dispatch(toggleNetworkMenu()); - if (network.providerType) { - dispatch(setProviderType(network.providerType)); - } else { - dispatch(setActiveNetwork(network.id)); - } - trackEvent({ - event: MetaMetricsEventName.NavNetworkSwitched, - category: MetaMetricsEventCategory.Network, - properties: { - location: 'Network Menu', - chain_id: currentChainId, - from_network: currentChainId, - to_network: network.chainId, - }, - }); - }} - onDeleteClick={ - canDeleteNetwork - ? () => { - dispatch(toggleNetworkMenu()); - dispatch( - showModal({ - name: 'CONFIRM_DELETE_NETWORK', - target: network.id, - onConfirm: () => undefined, - }), - ); - } - : null - } - /> - ); + return generateNetworkListItem({ + network, + isCurrentNetwork, + canDeleteNetwork, + }); }); }; @@ -355,6 +375,12 @@ export const NetworkListMenu = ({ onClose }) => { const canDeleteNetwork = isUnlocked && !isCurrentNetwork && network.removable; + const networkListItem = generateNetworkListItem({ + network, + isCurrentNetwork, + canDeleteNetwork, + }); + return ( <Draggable key={network.id} @@ -367,60 +393,7 @@ export const NetworkListMenu = ({ onClose }) => { {...providedDrag.draggableProps} {...providedDrag.dragHandleProps} > - <NetworkListItem - name={network.nickname} - iconSrc={network?.rpcPrefs?.imageUrl} - key={network.id} - selected={isCurrentNetwork} - focus={isCurrentNetwork && !showSearch} - onClick={() => { - dispatch(toggleNetworkMenu()); - if (network.providerType) { - dispatch( - setProviderType(network.providerType), - ); - } else { - dispatch(setActiveNetwork(network.id)); - } - - // If presently on a dapp, communicate a change to - // the dapp via silent switchEthereumChain that the - // network has changed due to user action - if (useRequestQueue && selectedTabOrigin) { - setNetworkClientIdForDomain( - selectedTabOrigin, - network.id, - ); - } - - trackEvent({ - event: - MetaMetricsEventName.NavNetworkSwitched, - category: - MetaMetricsEventCategory.Network, - properties: { - location: 'Network Menu', - chain_id: currentChainId, - from_network: currentChainId, - to_network: network.chainId, - }, - }); - }} - onDeleteClick={ - canDeleteNetwork - ? () => { - dispatch(toggleNetworkMenu()); - dispatch( - showModal({ - name: 'CONFIRM_DELETE_NETWORK', - target: network.id, - onConfirm: () => undefined, - }), - ); - } - : null - } - /> + {networkListItem} </Box> )} </Draggable> From 9a5aeae1944814bdc7a3db28bf5bf60cba55aa41 Mon Sep 17 00:00:00 2001 From: Ariella Vu <20778143+digiwand@users.noreply.github.com> Date: Wed, 12 Jun 2024 10:02:41 +0900 Subject: [PATCH 09/61] feat: Support various redesign signatures in ConfirmPage Storybook (#25054) --- .../confirmations/confirm/confirm.stories.tsx | 99 ++++++++++++++++--- 1 file changed, 84 insertions(+), 15 deletions(-) diff --git a/ui/pages/confirmations/confirm/confirm.stories.tsx b/ui/pages/confirmations/confirm/confirm.stories.tsx index 7062fb49201f..3e428eba997f 100644 --- a/ui/pages/confirmations/confirm/confirm.stories.tsx +++ b/ui/pages/confirmations/confirm/confirm.stories.tsx @@ -1,27 +1,96 @@ import React from 'react'; import { Provider } from 'react-redux'; -import configureStore from '../../../store/store'; +import { cloneDeep } from 'lodash'; +import { unapprovedPersonalSignMsg, signatureRequestSIWE } from '../../../../test/data/confirmations/personal_sign'; +import { unapprovedTypedSignMsgV1, unapprovedTypedSignMsgV4, permitSignatureMsg } from '../../../../test/data/confirmations/typed_sign'; import mockState from '../../../../test/data/mock-state.json'; +import configureStore from '../../../store/store'; import ConfirmPage from './confirm'; -const store = configureStore({ - confirm: { - currentConfirmation: { - type: 'personal_sign', - }, - }, - metamask: { - ...mockState.metamask, - }, -}); - +/** + * @note When we extend this storybook page to support more confirmation types, + * consider creating a new storybook pages. + */ const ConfirmPageStory = { title: 'Pages/Confirm/ConfirmPage', - decorators: [(story) => <Provider store={store}>{story()}</Provider>], + decorators: [(story) => <div style={{ height: '600px' }}>{story()}</div>], +} + +const ARGS_SIGNATURE = { + msgParams: { ...unapprovedPersonalSignMsg.msgParams }, +} + +const ARG_TYPES_SIGNATURE = { + msgParams: { + control: 'object', + description: '(non-param) overrides currentConfirmation.msgParams', + }, +} + +function SignatureStoryTemplate(args, confirmation) { + const mockConfirmation = cloneDeep(confirmation); + mockConfirmation.msgParams = args.msgParams; + + const store = configureStore({ + confirm: { + currentConfirmation: mockConfirmation, + }, + metamask: { ...mockState.metamask }, + }); + + return <Provider store={store}><ConfirmPage /></Provider>; +} + +export const PersonalSignStory = (args) => { + return SignatureStoryTemplate(args, unapprovedPersonalSignMsg); }; -export const DefaultStory = (args) => <ConfirmPage {...args} />; +PersonalSignStory.storyName = 'Personal Sign'; +PersonalSignStory.argTypes = ARG_TYPES_SIGNATURE; +PersonalSignStory.args = ARGS_SIGNATURE; -DefaultStory.storyName = 'Default'; +export const SignInWithEthereumSIWEStory = (args) => { + return SignatureStoryTemplate(args, signatureRequestSIWE); +}; + +SignInWithEthereumSIWEStory.storyName = 'Sign-in With Ethereum (SIWE)'; +SignInWithEthereumSIWEStory.argTypes = ARG_TYPES_SIGNATURE; +SignInWithEthereumSIWEStory.args = { + ...ARGS_SIGNATURE, + msgParams: signatureRequestSIWE.msgParams, +}; + +export const SignTypedDataStory = (args) => { + return SignatureStoryTemplate(args, unapprovedTypedSignMsgV1); +}; + +SignTypedDataStory.storyName = 'SignTypedData'; +SignTypedDataStory.argTypes = ARG_TYPES_SIGNATURE; +SignTypedDataStory.args = { + ...ARGS_SIGNATURE, + msgParams: unapprovedTypedSignMsgV1.msgParams, +}; + +export const PermitStory = (args) => { + return SignatureStoryTemplate(args, permitSignatureMsg); +}; + +PermitStory.storyName = 'SignTypedData Permit'; +PermitStory.argTypes = ARG_TYPES_SIGNATURE; +PermitStory.args = { + ...ARGS_SIGNATURE, + msgParams: permitSignatureMsg.msgParams, +}; + +export const SignTypedDataV4Story = (args) => { + return SignatureStoryTemplate(args, unapprovedTypedSignMsgV4); +}; + +SignTypedDataV4Story.storyName = 'SignTypedData V4'; +SignTypedDataV4Story.argTypes = ARG_TYPES_SIGNATURE; +SignTypedDataV4Story.args = { + ...ARGS_SIGNATURE, + msgParams: unapprovedTypedSignMsgV4.msgParams, +}; export default ConfirmPageStory; From 57b9c82a30551ec3798357e9c0bdc66c4f0eff55 Mon Sep 17 00:00:00 2001 From: Jyoti Puri <jyotipuri@gmail.com> Date: Wed, 12 Jun 2024 17:37:31 +0530 Subject: [PATCH 10/61] feat: permit signature simulation info (#24862) --- app/_locales/en/messages.json | 3 + .../permit-simulation.test.tsx.snap | 98 +++++++++++++++++++ .../typed-sign/permit-simulation/index.ts | 1 + .../permit-simulation.test.tsx | 21 ++++ .../permit-simulation/permit-simulation.tsx | 82 ++++++++++++++++ .../info/typed-sign/typed-sign.test.tsx | 12 +++ .../confirm/info/typed-sign/typed-sign.tsx | 10 +- 7 files changed, 223 insertions(+), 4 deletions(-) create mode 100644 ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap create mode 100644 ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/index.ts create mode 100644 ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx create mode 100644 ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 44434c77b44a..df4e33085230 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -3787,6 +3787,9 @@ "permissionsPageTourTitle": { "message": "Connected sites are now permissions" }, + "permitSimulationDetailInfo": { + "message": "This transaction gives permission to withdraw your tokens" + }, "personalAddressDetected": { "message": "Personal address detected. Input the token contract address." }, diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap new file mode 100644 index 000000000000..e96dce4d0201 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap @@ -0,0 +1,98 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PermitSimulation renders component correctly 1`] = ` +<div> + <div + class="mm-box mm-box--margin-bottom-4 mm-box--padding-2 mm-box--background-color-background-default mm-box--rounded-md" + > + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Estimated changes + </p> + <div> + <div + aria-describedby="tippy-tooltip-1" + class="" + data-original-title="Estimated changes are what might happen if you go through with this transaction. This is just a prediction, not a guarantee." + data-tooltipped="" + style="display: flex;" + tabindex="0" + > + <span + class="mm-box mm-icon mm-icon--size-sm mm-box--margin-left-1 mm-box--display-inline-block mm-box--color-icon-muted" + style="mask-image: url('./images/icons/question.svg');" + /> + </div> + </div> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + This transaction gives permission to withdraw your tokens + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Approve spend limit + </p> + </div> + <div + class="mm-box" + > + <div + class="mm-box mm-box--display-flex" + > + <div + class="mm-box mm-box--margin-inline-end-1 mm-box--display-inline" + > + <p + class="mm-box mm-text mm-text--body-md mm-text--text-align-center mm-box--padding-inline-2 mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-xl" + > + 3000 + </p> + </div> + <div> + <div + class="name name__missing" + > + <span + class="mm-box name__icon mm-icon mm-icon--size-md mm-box--display-inline-block mm-box--color-inherit" + style="mask-image: url('./images/icons/question.svg');" + /> + <p + class="mm-box mm-text name__value mm-text--body-md mm-box--color-text-default" + > + 0xCcCCc...ccccC + </p> + </div> + </div> + </div> + <div + class="mm-box" + /> + </div> + </div> + </div> +</div> +`; diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/index.ts b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/index.ts new file mode 100644 index 000000000000..20c43d2613ca --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/index.ts @@ -0,0 +1 @@ +export { default as PermitSimulation } from './permit-simulation'; diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx new file mode 100644 index 000000000000..ea0ffcc47bc1 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; + +import mockState from '../../../../../../../../test/data/mock-state.json'; +import { renderWithProvider } from '../../../../../../../../test/lib/render-helpers'; +import { permitSignatureMsg } from '../../../../../../../../test/data/confirmations/typed_sign'; +import PermitSimulation from './permit-simulation'; + +describe('PermitSimulation', () => { + it('renders component correctly', () => { + const state = { + ...mockState, + confirm: { + currentConfirmation: permitSignatureMsg, + }, + }; + const mockStore = configureMockStore([])(state); + const { container } = renderWithProvider(<PermitSimulation />, mockStore); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx new file mode 100644 index 000000000000..fe43dd17183a --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx @@ -0,0 +1,82 @@ +import React, { useMemo } from 'react'; +import { useSelector } from 'react-redux'; +import { NameType } from '@metamask/name-controller'; + +import { Numeric } from '../../../../../../../../shared/modules/Numeric'; +import Name from '../../../../../../../components/app/name/name'; +import { + ConfirmInfoRow, + ConfirmInfoRowText, +} from '../../../../../../../components/app/confirm/info/row'; +import { useI18nContext } from '../../../../../../../hooks/useI18nContext'; +import { currentConfirmationSelector } from '../../../../../../../selectors'; +import { Box, Text } from '../../../../../../../components/component-library'; +import { + BackgroundColor, + BorderRadius, + Display, + TextAlign, +} from '../../../../../../../helpers/constants/design-system'; +import { parseTypedDataMessage } from '../../../../../utils'; +import { SignatureRequestType } from '../../../../../types/confirm'; +import useTokenExchangeRate from '../../../../../../../components/app/currency-input/hooks/useTokenExchangeRate'; +import { IndividualFiatDisplay } from '../../../../simulation-details/fiat-display'; + +const PermitSimulation: React.FC = () => { + const t = useI18nContext(); + const currentConfirmation = useSelector( + currentConfirmationSelector, + ) as SignatureRequestType; + + const { + domain: { verifyingContract }, + message: { value }, + } = parseTypedDataMessage(currentConfirmation.msgParams?.data as string); + + const exchangeRate = useTokenExchangeRate(verifyingContract); + + const fiatValue = useMemo(() => { + if (exchangeRate && value) { + return exchangeRate.times(new Numeric(value, 10)).toNumber(); + } + return undefined; + }, [exchangeRate, value]); + + return ( + <Box + backgroundColor={BackgroundColor.backgroundDefault} + borderRadius={BorderRadius.MD} + padding={2} + marginBottom={4} + > + <ConfirmInfoRow + label={t('simulationDetailsTitle')} + tooltip={t('simulationDetailsTitleTooltip')} + > + <ConfirmInfoRowText text={t('permitSimulationDetailInfo')} /> + </ConfirmInfoRow> + <ConfirmInfoRow label={t('approve')}> + <Box> + <Box display={Display.Flex}> + <Box display={Display.Inline} marginInlineEnd={1}> + <Text + backgroundColor={BackgroundColor.backgroundAlternative} + borderRadius={BorderRadius.XL} + paddingInline={2} + textAlign={TextAlign.Center} + > + {value} + </Text> + </Box> + <Name value={verifyingContract} type={NameType.ETHEREUM_ADDRESS} /> + </Box> + <Box> + {fiatValue && <IndividualFiatDisplay fiatAmount={fiatValue} />} + </Box> + </Box> + </ConfirmInfoRow> + </Box> + ); +}; + +export default PermitSimulation; diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx index 1f337f5a9dc2..dc1d093d57bb 100644 --- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx @@ -64,6 +64,18 @@ describe('TypedSignInfo', () => { expect(container).toMatchSnapshot(); }); + it('display simulation details for permit signature', () => { + const state = { + ...mockState, + confirm: { + currentConfirmation: permitSignatureMsg, + }, + }; + const mockStore = configureMockStore([])(state); + const { getByText } = renderWithProvider(<TypedSignInfo />, mockStore); + expect(getByText('Estimated changes')).toBeDefined(); + }); + it('displays "Approving to" for permit signature type', () => { const state = { ...mockState, diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx index adf66ae16f9d..ed4cb30f3360 100644 --- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx @@ -19,6 +19,7 @@ import { EIP712_PRIMARY_TYPE_PERMIT } from '../../../../constants'; import { SignatureRequestType } from '../../../../types/confirm'; import { parseTypedDataMessage } from '../../../../utils'; import { ConfirmInfoRowTypedSignData } from '../../row/typed-sign-data/typedSignData'; +import { PermitSimulation } from './permit-simulation'; const TypedSignInfo: React.FC = () => { const t = useI18nContext(); @@ -31,13 +32,14 @@ const TypedSignInfo: React.FC = () => { } const { - domain, domain: { verifyingContract }, primaryType, + message: { spender }, } = parseTypedDataMessage(currentConfirmation.msgParams.data as string); return ( <> + {primaryType === EIP712_PRIMARY_TYPE_PERMIT && <PermitSimulation />} <Box backgroundColor={BackgroundColor.backgroundDefault} borderRadius={BorderRadius.MD} @@ -48,7 +50,7 @@ const TypedSignInfo: React.FC = () => { <> <Box padding={2}> <ConfirmInfoRow label={t('approvingTo')}> - <ConfirmInfoRowAddress address={verifyingContract} /> + <ConfirmInfoRowAddress address={spender} /> </ConfirmInfoRow> </Box> <ConfirmInfoRowDivider /> @@ -62,10 +64,10 @@ const TypedSignInfo: React.FC = () => { <ConfirmInfoRowUrl url={currentConfirmation.msgParams.origin} /> </ConfirmInfoRow> </Box> - {isValidAddress(domain.verifyingContract) && ( + {isValidAddress(verifyingContract) && ( <Box padding={2}> <ConfirmInfoRow label={t('interactingWith')}> - <ConfirmInfoRowAddress address={domain.verifyingContract} /> + <ConfirmInfoRowAddress address={verifyingContract} /> </ConfirmInfoRow> </Box> )} From 32af8896856b2fcbdd2fd0ff8507306ddb711d8e Mon Sep 17 00:00:00 2001 From: Mark Stacey <markjstacey@gmail.com> Date: Wed, 12 Jun 2024 10:08:54 -0230 Subject: [PATCH 11/61] fix: Capture Segment errors during initialization (#25253) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** We were submitting Segment events in the MetaMetrics constructor without cathing errors. This was the sole place where we failed to catch errors resulting from Segment calls. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25253?quickstart=1) ## **Related issues** Mitigates #25244 ## **Manual testing steps** Sure of exact reproduction steps at this time. ## **Screenshots/Recordings** N./A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- app/scripts/controllers/metametrics.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index 2f6501861a9d..fca239a25394 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -188,7 +188,11 @@ export default class MetaMetricsController { // Code below submits any pending segmentApiCalls to Segment if/when the controller is re-instantiated if (isManifestV3) { Object.values(segmentApiCalls).forEach(({ eventType, payload }) => { - this._submitSegmentAPICall(eventType, payload); + try { + this._submitSegmentAPICall(eventType, payload); + } catch (error) { + this._captureException(error); + } }); } From 85cf4306af7cd050fe877400074b2a9f7af9c361 Mon Sep 17 00:00:00 2001 From: Jyoti Puri <jyotipuri@gmail.com> Date: Wed, 12 Jun 2024 18:57:30 +0530 Subject: [PATCH 12/61] feat: permit signature copy changes (#24975) --- app/_locales/en/messages.json | 14 ++-- .../permit-simulation.test.tsx.snap | 2 +- .../info/typed-sign/typed-sign.test.tsx | 4 +- .../confirm/info/typed-sign/typed-sign.tsx | 15 ++-- .../components/confirm/title/title.test.tsx | 19 ++++- .../components/confirm/title/title.tsx | 70 +++++++++++-------- ui/pages/confirmations/constants/index.ts | 6 ++ ui/pages/confirmations/utils/confirm.test.ts | 21 ++++++ ui/pages/confirmations/utils/confirm.ts | 19 +++++ 9 files changed, 127 insertions(+), 43 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index df4e33085230..fcc425becf68 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -521,9 +521,6 @@ "message": "Approved on $1 for $2", "description": "$1 is the approval date for a permission. $2 is the AvatarGroup component displaying account images." }, - "approvingTo": { - "message": "Approving to" - }, "areYouSure": { "message": "Are you sure?" }, @@ -906,9 +903,15 @@ "confirmTitleDescContractInteractionTransaction": { "message": "Only confirm this transaction if you fully understand the content and trust the requesting site." }, + "confirmTitleDescPermitSignature": { + "message": "This site wants permission to spend your tokens." + }, "confirmTitleDescSignature": { "message": "Only confirm this message if you approve the content and trust the requesting site." }, + "confirmTitlePermitSignature": { + "message": "Spending cap request" + }, "confirmTitleSignature": { "message": "Signature request" }, @@ -3788,7 +3791,7 @@ "message": "Connected sites are now permissions" }, "permitSimulationDetailInfo": { - "message": "This transaction gives permission to withdraw your tokens" + "message": "You're giving the spender permission to spend this many tokens from your account." }, "personalAddressDetected": { "message": "Personal address detected. Input the token contract address." @@ -4911,6 +4914,9 @@ "spendLimitTooLarge": { "message": "Spend limit too large" }, + "spender": { + "message": "Spender" + }, "spendingCap": { "message": "Spending cap" }, diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap index e96dce4d0201..b5deeb02f612 100644 --- a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap @@ -40,7 +40,7 @@ exports[`PermitSimulation renders component correctly 1`] = ` class="mm-box mm-text mm-text--body-md mm-box--color-inherit" style="white-space: pre-wrap;" > - This transaction gives permission to withdraw your tokens + You're giving the spender permission to spend this many tokens from your account. </p> </div> </div> diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx index dc1d093d57bb..dd6782af6644 100644 --- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx @@ -76,7 +76,7 @@ describe('TypedSignInfo', () => { expect(getByText('Estimated changes')).toBeDefined(); }); - it('displays "Approving to" for permit signature type', () => { + it('displays "Spender" for permit signature type', () => { const state = { ...mockState, confirm: { @@ -85,6 +85,6 @@ describe('TypedSignInfo', () => { }; const mockStore = configureMockStore([])(state); const { getByText } = renderWithProvider(<TypedSignInfo />, mockStore); - expect(getByText('Approving to')).toBeDefined(); + expect(getByText('Spender')).toBeDefined(); }); }); diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx index ed4cb30f3360..5ff582bde243 100644 --- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx @@ -15,9 +15,11 @@ import { BackgroundColor, BorderRadius, } from '../../../../../../helpers/constants/design-system'; -import { EIP712_PRIMARY_TYPE_PERMIT } from '../../../../constants'; import { SignatureRequestType } from '../../../../types/confirm'; -import { parseTypedDataMessage } from '../../../../utils'; +import { + isPermitSignatureRequest, + parseTypedDataMessage, +} from '../../../../utils'; import { ConfirmInfoRowTypedSignData } from '../../row/typed-sign-data/typedSignData'; import { PermitSimulation } from './permit-simulation'; @@ -33,23 +35,24 @@ const TypedSignInfo: React.FC = () => { const { domain: { verifyingContract }, - primaryType, message: { spender }, } = parseTypedDataMessage(currentConfirmation.msgParams.data as string); + const isPermit = isPermitSignatureRequest(currentConfirmation); + return ( <> - {primaryType === EIP712_PRIMARY_TYPE_PERMIT && <PermitSimulation />} + {isPermit && <PermitSimulation />} <Box backgroundColor={BackgroundColor.backgroundDefault} borderRadius={BorderRadius.MD} marginBottom={4} padding={0} > - {primaryType === EIP712_PRIMARY_TYPE_PERMIT && ( + {isPermit && ( <> <Box padding={2}> - <ConfirmInfoRow label={t('approvingTo')}> + <ConfirmInfoRow label={t('spender')}> <ConfirmInfoRowAddress address={spender} /> </ConfirmInfoRow> </Box> diff --git a/ui/pages/confirmations/components/confirm/title/title.test.tsx b/ui/pages/confirmations/components/confirm/title/title.test.tsx index dfd94d6f6617..f0f330653e5c 100644 --- a/ui/pages/confirmations/components/confirm/title/title.test.tsx +++ b/ui/pages/confirmations/components/confirm/title/title.test.tsx @@ -1,6 +1,11 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; import { TransactionType } from '@metamask/transaction-controller'; + +import { + permitSignatureMsg, + unapprovedTypedSignMsgV4, +} from '../../../../../../test/data/confirmations/typed_sign'; import { renderWithProvider } from '../../../../../../test/lib/render-helpers'; import { Confirmation } from '../../../types/confirm'; import { Severity } from '../../../../../helpers/constants/design-system'; @@ -38,9 +43,21 @@ describe('ConfirmTitle', () => { ).toBeInTheDocument(); }); + it('should render the title and description for a permit signature', () => { + const mockStore = configureMockStore([])( + genMockState(permitSignatureMsg as Confirmation), + ); + const { getByText } = renderWithProvider(<ConfirmTitle />, mockStore); + + expect(getByText('Spending cap request')).toBeInTheDocument(); + expect( + getByText('This site wants permission to spend your tokens.'), + ).toBeInTheDocument(); + }); + it('should render the title and description for typed signature', () => { const mockStore = configureMockStore([])( - genMockState({ type: TransactionType.signTypedData }), + genMockState(unapprovedTypedSignMsgV4 as Confirmation), ); const { getByText } = renderWithProvider(<ConfirmTitle />, mockStore); diff --git a/ui/pages/confirmations/components/confirm/title/title.tsx b/ui/pages/confirmations/components/confirm/title/title.tsx index ea18fcbadd63..a38abbb55433 100644 --- a/ui/pages/confirmations/components/confirm/title/title.tsx +++ b/ui/pages/confirmations/components/confirm/title/title.tsx @@ -9,10 +9,11 @@ import { } from '../../../../../helpers/constants/design-system'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { currentConfirmationSelector } from '../../../../../selectors'; -import { Confirmation } from '../../../types/confirm'; import useAlerts from '../../../../../hooks/useAlerts'; import { getHighestSeverity } from '../../../../../components/app/alert-system/utils'; import GeneralAlert from '../../../../../components/app/alert-system/general-alert/general-alert'; +import { Confirmation, SignatureRequestType } from '../../../types/confirm'; +import { isPermitSignatureRequest } from '../../../utils'; function ConfirmBannerAlert({ ownerId }: { ownerId: string }) { const t = useI18nContext(); @@ -49,45 +50,56 @@ function ConfirmBannerAlert({ ownerId }: { ownerId: string }) { ); } +type IntlFunction = (str: string) => string; + +const getTitle = (t: IntlFunction, confirmation?: Confirmation) => { + switch (confirmation?.type) { + case TransactionType.contractInteraction: + return t('confirmTitleTransaction'); + case TransactionType.personalSign: + return t('confirmTitleSignature'); + case TransactionType.signTypedData: + return isPermitSignatureRequest(confirmation as SignatureRequestType) + ? t('confirmTitlePermitSignature') + : t('confirmTitleSignature'); + default: + return ''; + } +}; + +const getDescription = (t: IntlFunction, confirmation?: Confirmation) => { + switch (confirmation?.type) { + case TransactionType.contractInteraction: + return t('confirmTitleDescContractInteractionTransaction'); + case TransactionType.personalSign: + return t('confirmTitleDescSignature'); + case TransactionType.signTypedData: + return isPermitSignatureRequest(confirmation as SignatureRequestType) + ? t('confirmTitleDescPermitSignature') + : t('confirmTitleDescSignature'); + default: + return ''; + } +}; + const ConfirmTitle: React.FC = memo(() => { const t = useI18nContext(); - const currentConfirmation = useSelector( - currentConfirmationSelector, - ) as Confirmation; + const currentConfirmation = useSelector(currentConfirmationSelector); - const typeToTitleTKey: Partial<Record<TransactionType, string>> = useMemo( - () => ({ - [TransactionType.personalSign]: t('confirmTitleSignature'), - [TransactionType.signTypedData]: t('confirmTitleSignature'), - [TransactionType.contractInteraction]: t('confirmTitleTransaction'), - }), - [], + const title = useMemo( + () => getTitle(t as IntlFunction, currentConfirmation), + [currentConfirmation], ); - const typeToDescTKey: Partial<Record<TransactionType, string>> = useMemo( - () => ({ - [TransactionType.personalSign]: t('confirmTitleDescSignature'), - [TransactionType.signTypedData]: t('confirmTitleDescSignature'), - [TransactionType.contractInteraction]: t( - 'confirmTitleDescContractInteractionTransaction', - ), - }), - [], + const description = useMemo( + () => getDescription(t as IntlFunction, currentConfirmation), + [currentConfirmation], ); if (!currentConfirmation) { return null; } - const title = - typeToTitleTKey[ - currentConfirmation.type || TransactionType.contractInteraction - ]; - const description = - typeToDescTKey[ - currentConfirmation.type || TransactionType.contractInteraction - ]; - return ( <> <ConfirmBannerAlert ownerId={currentConfirmation.id} /> diff --git a/ui/pages/confirmations/constants/index.ts b/ui/pages/confirmations/constants/index.ts index 88af9e200997..055fcea53f6f 100644 --- a/ui/pages/confirmations/constants/index.ts +++ b/ui/pages/confirmations/constants/index.ts @@ -3,3 +3,9 @@ import { CHAINLIST_CHAIN_IDS_MAP } from '../../../../shared/constants/network'; export const EIP712_PRIMARY_TYPE_PERMIT = 'Permit'; export const IGNORE_GAS_LIMIT_CHAIN_IDS = [CHAINLIST_CHAIN_IDS_MAP.MANTLE]; + +export const TYPED_SIGNATURE_VERSIONS = { + V1: 'V1', + V3: 'V3', + V4: 'V4', +}; diff --git a/ui/pages/confirmations/utils/confirm.test.ts b/ui/pages/confirmations/utils/confirm.test.ts index e358a6076408..4e2edbaad6e8 100644 --- a/ui/pages/confirmations/utils/confirm.test.ts +++ b/ui/pages/confirmations/utils/confirm.test.ts @@ -3,6 +3,12 @@ import { ApprovalType } from '@metamask/controller-utils'; import { TransactionType } from '@metamask/transaction-controller'; import { + permitSignatureMsg, + unapprovedTypedSignMsgV4, +} from '../../../../test/data/confirmations/typed_sign'; +import { SignatureRequestType } from '../types/confirm'; +import { + isPermitSignatureRequest, isSignatureApprovalRequest, isSignatureTransactionType, parseSanitizeTypedDataMessage, @@ -71,4 +77,19 @@ describe('confirm util', () => { expect(result).toStrictEqual(false); }); }); + + describe('isPermitSignatureRequest', () => { + it('returns true for permit signature requests', () => { + const result = isPermitSignatureRequest( + permitSignatureMsg as SignatureRequestType, + ); + expect(result).toStrictEqual(true); + }); + it('returns false for request not of type permit signature', () => { + const result = isPermitSignatureRequest( + unapprovedTypedSignMsgV4 as SignatureRequestType, + ); + expect(result).toStrictEqual(false); + }); + }); }); diff --git a/ui/pages/confirmations/utils/confirm.ts b/ui/pages/confirmations/utils/confirm.ts index 6eddab209e67..abc57fa02483 100644 --- a/ui/pages/confirmations/utils/confirm.ts +++ b/ui/pages/confirmations/utils/confirm.ts @@ -5,6 +5,10 @@ import { Json } from '@metamask/utils'; import { sanitizeMessage } from '../../../helpers/utils/util'; import { SignatureRequestType } from '../types/confirm'; +import { + EIP712_PRIMARY_TYPE_PERMIT, + TYPED_SIGNATURE_VERSIONS, +} from '../constants'; export const REDESIGN_APPROVAL_TYPES = [ ApprovalType.EthSignTypedData, @@ -47,3 +51,18 @@ export const parseSanitizeTypedDataMessage = (dataToParse: string) => { export const isSIWESignatureRequest = (request: SignatureRequestType) => request.msgParams?.siwe?.isSIWEMessage; + +export const isPermitSignatureRequest = (request: SignatureRequestType) => { + if ( + !request || + !isSignatureTransactionType(request) || + request.type !== 'eth_signTypedData' || + request.msgParams?.version?.toUpperCase() === TYPED_SIGNATURE_VERSIONS.V1 + ) { + return false; + } + const { primaryType } = parseTypedDataMessage( + request.msgParams?.data as string, + ); + return primaryType === EIP712_PRIMARY_TYPE_PERMIT; +}; From 35950523128fc06d76d8d385120a7d3cb214ce2a Mon Sep 17 00:00:00 2001 From: Monte Lai <monte.lai@consensys.net> Date: Wed, 12 Jun 2024 21:35:58 +0800 Subject: [PATCH 13/61] refactor: app header (#25143) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR refactors the app header into smaller components and adds multichain selectors. ## **Related issues** Related to https://github.com/MetaMask/accounts-planning/issues/425 ## **Manual testing steps** ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Charly Chevalier <charly.chevalier@consensys.net> --- shared/constants/multichain/networks.ts | 2 +- .../connected-status-indicator.js | 4 +- .../app-header/app-header-container.tsx | 42 ++ .../app-header/app-header-locked-content.tsx | 57 +++ .../app-header-unlocked-content.tsx | 286 +++++++++++++ .../multichain/app-header/app-header.js | 379 +++--------------- .../connected-site-menu.js | 10 +- .../multichain/connected-site-menu/index.scss | 6 + ui/selectors/multichain.test.ts | 11 + ui/selectors/multichain.ts | 8 +- 10 files changed, 487 insertions(+), 318 deletions(-) create mode 100644 ui/components/multichain/app-header/app-header-container.tsx create mode 100644 ui/components/multichain/app-header/app-header-locked-content.tsx create mode 100644 ui/components/multichain/app-header/app-header-unlocked-content.tsx diff --git a/shared/constants/multichain/networks.ts b/shared/constants/multichain/networks.ts index 92b9d7a89452..de5e50639374 100644 --- a/shared/constants/multichain/networks.ts +++ b/shared/constants/multichain/networks.ts @@ -1,7 +1,7 @@ import { ProviderConfig } from '@metamask/network-controller'; import { CaipChainId } from '@metamask/utils'; -type ProviderConfigWithImageUrl = Omit<ProviderConfig, 'chainId'> & { +export type ProviderConfigWithImageUrl = Omit<ProviderConfig, 'chainId'> & { rpcPrefs?: { imageUrl?: string }; }; diff --git a/ui/components/app/connected-status-indicator/connected-status-indicator.js b/ui/components/app/connected-status-indicator/connected-status-indicator.js index 6cbcb5c8787d..55d5b646ef9e 100644 --- a/ui/components/app/connected-status-indicator/connected-status-indicator.js +++ b/ui/components/app/connected-status-indicator/connected-status-indicator.js @@ -20,7 +20,7 @@ import { } from '../../../selectors'; import { ConnectedSiteMenu } from '../../multichain'; -export default function ConnectedStatusIndicator({ onClick }) { +export default function ConnectedStatusIndicator({ onClick, disabled }) { const t = useI18nContext(); const { address: selectedAddress } = useSelector(getSelectedInternalAccount); @@ -69,10 +69,12 @@ export default function ConnectedStatusIndicator({ onClick }) { text={tooltipText} as="button" onClick={onClick} + disabled={disabled} /> ); } ConnectedStatusIndicator.propTypes = { onClick: PropTypes.func, + disabled: PropTypes.bool, }; diff --git a/ui/components/multichain/app-header/app-header-container.tsx b/ui/components/multichain/app-header/app-header-container.tsx new file mode 100644 index 000000000000..8acda149d6eb --- /dev/null +++ b/ui/components/multichain/app-header/app-header-container.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import classnames from 'classnames'; +import { + AlignItems, + BackgroundColor, + BlockSize, + Display, +} from '../../../helpers/constants/design-system'; +import { Box, BoxProps } from '../../component-library'; + +type AppHeaderContainerProps = { + isUnlocked: boolean; + popupStatus: boolean; + headerBottomMargin: BoxProps<typeof Box>['marginBottom']; +}; + +export const AppHeaderContainer = ({ + isUnlocked, + popupStatus, + headerBottomMargin, + children, +}: React.PropsWithChildren<AppHeaderContainerProps>) => { + const backgroundColor = + !isUnlocked || popupStatus + ? BackgroundColor.backgroundDefault + : BackgroundColor.backgroundAlternative; + + return ( + <Box + display={Display.Flex} + className={classnames('multichain-app-header', { + 'multichain-app-header-shadow': !isUnlocked || popupStatus, + })} + marginBottom={headerBottomMargin} + alignItems={AlignItems.center} + width={BlockSize.Full} + backgroundColor={backgroundColor} + > + {children} + </Box> + ); +}; diff --git a/ui/components/multichain/app-header/app-header-locked-content.tsx b/ui/components/multichain/app-header/app-header-locked-content.tsx new file mode 100644 index 000000000000..9285529c8d39 --- /dev/null +++ b/ui/components/multichain/app-header/app-header-locked-content.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { useSelector } from 'react-redux'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import MetafoxLogo from '../../ui/metafox-logo'; +import { PickerNetwork } from '../../component-library'; +import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; +import { getTestNetworkBackgroundColor } from '../../../selectors'; +import { + MultichainProviderConfig, + ProviderConfigWithImageUrl, +} from '../../../../shared/constants/multichain/networks'; + +type AppHeaderLockedContentProps = { + currentNetwork: ProviderConfigWithImageUrl | MultichainProviderConfig; + networkOpenCallback: () => void; +}; + +export const AppHeaderLockedContent = ({ + currentNetwork, + networkOpenCallback, +}: AppHeaderLockedContentProps) => { + const t = useI18nContext(); + const history = useHistory(); + + const testNetworkBackgroundColor = useSelector(getTestNetworkBackgroundColor); + + return ( + <> + <div> + <PickerNetwork + avatarNetworkProps={{ + backgroundColor: testNetworkBackgroundColor, + role: 'img', + name: currentNetwork?.nickname ?? '', + }} + aria-label={`${t('networkMenu')} ${currentNetwork?.nickname}`} + label={currentNetwork?.nickname ?? ''} + src={currentNetwork?.rpcPrefs?.imageUrl} + onClick={(e: React.MouseEvent<HTMLElement>) => { + e.stopPropagation(); + e.preventDefault(); + networkOpenCallback(); + }} + className="multichain-app-header__contents__network-picker" + data-testid="network-display" + /> + </div> + <MetafoxLogo + unsetIconHeight + onClick={async () => { + history.push(DEFAULT_ROUTE); + }} + /> + </> + ); +}; diff --git a/ui/components/multichain/app-header/app-header-unlocked-content.tsx b/ui/components/multichain/app-header/app-header-unlocked-content.tsx new file mode 100644 index 000000000000..240104ccb790 --- /dev/null +++ b/ui/components/multichain/app-header/app-header-unlocked-content.tsx @@ -0,0 +1,286 @@ +import React, { useContext, useState } from 'react'; +import browser from 'webextension-polyfill'; + +import { InternalAccount } from '@metamask/keyring-api'; +import { useDispatch, useSelector } from 'react-redux'; +import { + AlignItems, + BackgroundColor, + BlockSize, + BorderRadius, + Display, + FlexDirection, + FontWeight, + IconColor, + JustifyContent, + TextColor, + TextVariant, +} from '../../../helpers/constants/design-system'; +import { + Box, + ButtonBase, + ButtonBaseSize, + ButtonIcon, + ButtonIconSize, + IconName, + IconSize, + PickerNetwork, + Text, +} from '../../component-library'; +import Tooltip from '../../ui/tooltip'; +import { + MetaMetricsEventName, + MetaMetricsEventCategory, +} from '../../../../shared/constants/metametrics'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { toggleAccountMenu } from '../../../store/actions'; +import ConnectedStatusIndicator from '../../app/connected-status-indicator'; +import { AccountPicker } from '../account-picker'; +import { GlobalMenu } from '../global-menu'; +import { + getSelectedInternalAccount, + getTestNetworkBackgroundColor, +} from '../../../selectors'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { normalizeSafeAddress } from '../../../../app/scripts/lib/multichain/address'; +import { shortenAddress } from '../../../helpers/utils/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; +import { MetaMetricsContext } from '../../../contexts/metametrics'; +import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; +import { MINUTE } from '../../../../shared/constants/time'; +import { NotificationsTagCounter } from '../notifications-tag-counter'; +import { + MultichainProviderConfig, + ProviderConfigWithImageUrl, +} from '../../../../shared/constants/multichain/networks'; + +type AppHeaderUnlockedContentProps = { + popupStatus: boolean; + isEvmNetwork: boolean; + currentNetwork: ProviderConfigWithImageUrl | MultichainProviderConfig; + networkOpenCallback: () => void; + disableNetworkPicker: boolean; + disableAccountPicker: boolean; + menuRef: React.RefObject<HTMLButtonElement>; + internalAccount: InternalAccount; +}; + +export const AppHeaderUnlockedContent = ({ + popupStatus, + isEvmNetwork, + currentNetwork, + networkOpenCallback, + disableNetworkPicker, + disableAccountPicker, + menuRef, +}: AppHeaderUnlockedContentProps) => { + const trackEvent = useContext(MetaMetricsContext); + const t = useI18nContext(); + const dispatch = useDispatch(); + const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false); + const testNetworkBackgroundColor = useSelector(getTestNetworkBackgroundColor); + + // Used for account picker + const internalAccount = useSelector(getSelectedInternalAccount); + const shortenedAddress = + internalAccount && + shortenAddress(normalizeSafeAddress(internalAccount.address)); + + // During onboarding there is no selected internal account + const currentAddress = internalAccount?.address; + + // Passing non-evm address to checksum function will throw an error + const normalizedCurrentAddress = normalizeSafeAddress(currentAddress); + const [copied, handleCopy] = useCopyToClipboard(MINUTE) as [ + boolean, + (text: string) => void, + ]; + + const showConnectedStatus = + getEnvironmentType() === ENVIRONMENT_TYPE_POPUP && + origin && + origin !== browser.runtime.id; + + const handleMainMenuOpened = () => { + trackEvent({ + event: MetaMetricsEventName.NavMainMenuOpened, + category: MetaMetricsEventCategory.Navigation, + properties: { + location: 'Home', + }, + }); + setAccountOptionsMenuOpen(true); + }; + + return ( + <> + {popupStatus ? ( + <Box className="multichain-app-header__contents__container"> + <Tooltip title={currentNetwork?.nickname} position="right"> + <PickerNetwork + avatarNetworkProps={{ + backgroundColor: testNetworkBackgroundColor, + role: 'img', + name: currentNetwork?.nickname ?? '', + }} + className="multichain-app-header__contents--avatar-network" + ref={menuRef} + as="button" + src={currentNetwork?.rpcPrefs?.imageUrl ?? ''} + label={currentNetwork?.nickname ?? ''} + aria-label={`${t('networkMenu')} ${currentNetwork?.nickname}`} + labelProps={{ + display: Display.None, + }} + onClick={(e: React.MouseEvent<HTMLElement>) => { + e.stopPropagation(); + e.preventDefault(); + networkOpenCallback(); + }} + display={[Display.Flex, Display.None]} // show on popover hide on desktop + disabled={disableNetworkPicker} + /> + </Tooltip> + </Box> + ) : ( + <div> + <PickerNetwork + avatarNetworkProps={{ + backgroundColor: testNetworkBackgroundColor, + role: 'img', + name: currentNetwork?.nickname ?? '', + }} + margin={2} + aria-label={`${t('networkMenu')} ${currentNetwork?.nickname}`} + label={currentNetwork?.nickname ?? ''} + src={currentNetwork?.rpcPrefs?.imageUrl} + onClick={(e: React.MouseEvent<HTMLElement>) => { + e.stopPropagation(); + e.preventDefault(); + networkOpenCallback(); + }} + display={[Display.None, Display.Flex]} // show on desktop hide on popover + className="multichain-app-header__contents__network-picker" + disabled={disableNetworkPicker} + data-testid="network-display" + /> + </div> + )} + + {internalAccount && ( + <Text + as="div" + display={Display.Flex} + flexDirection={FlexDirection.Column} + alignItems={AlignItems.center} + ellipsis + > + <AccountPicker + address={internalAccount.address} + name={internalAccount.metadata.name} + onClick={() => { + dispatch(toggleAccountMenu()); + + trackEvent({ + event: MetaMetricsEventName.NavAccountMenuOpened, + category: MetaMetricsEventCategory.Navigation, + properties: { + location: 'Home', + }, + }); + }} + disabled={disableAccountPicker} + labelProps={{ fontWeight: FontWeight.Bold }} + paddingLeft={2} + paddingRight={2} + /> + <Tooltip + position="left" + title={copied ? t('addressCopied') : t('copyToClipboard')} + > + <ButtonBase + className="multichain-app-header__address-copy-button" + onClick={() => handleCopy(normalizedCurrentAddress)} + size={ButtonBaseSize.Sm} + backgroundColor={BackgroundColor.transparent} + borderRadius={BorderRadius.LG} + endIconName={copied ? IconName.CopySuccess : IconName.Copy} + endIconProps={{ + color: IconColor.iconAlternative, + size: IconSize.Sm, + }} + ellipsis + textProps={{ + display: Display.Flex, + alignItems: AlignItems.center, + gap: 2, + }} + style={{ height: 'auto' }} // ButtonBase doesn't have auto size + data-testid="app-header-copy-button" + > + <Text + color={TextColor.textAlternative} + variant={TextVariant.bodySm} + ellipsis + as="span" + > + {shortenedAddress} + </Text> + </ButtonBase> + </Tooltip> + </Text> + )} + <Box + display={Display.Flex} + alignItems={AlignItems.center} + justifyContent={JustifyContent.flexEnd} + style={{ marginLeft: 'auto' }} + > + <Box display={Display.Flex} gap={4}> + {showConnectedStatus && ( + <Box ref={menuRef}> + <ConnectedStatusIndicator + onClick={() => { + if (!isEvmNetwork) { + return; + } + handleMainMenuOpened(); + }} + disabled={!isEvmNetwork} + /> + </Box> + )}{' '} + <Box + ref={menuRef} + display={Display.Flex} + justifyContent={JustifyContent.flexEnd} + width={BlockSize.Full} + > + {!accountOptionsMenuOpen && ( + <Box + style={{ position: 'relative' }} + onClick={() => handleMainMenuOpened()} + > + <NotificationsTagCounter noLabel /> + </Box> + )} + <ButtonIcon + iconName={IconName.MoreVertical} + data-testid="account-options-menu-button" + ariaLabel={t('accountOptions')} + onClick={() => { + handleMainMenuOpened(); + }} + size={ButtonIconSize.Sm} + /> + </Box> + </Box> + <GlobalMenu + anchorElement={menuRef.current} + isOpen={accountOptionsMenuOpen} + closeMenu={() => setAccountOptionsMenuOpen(false)} + /> + </Box> + </> + ); +}; diff --git a/ui/components/multichain/app-header/app-header.js b/ui/components/multichain/app-header/app-header.js index dc248ab80c78..b3d0207e6663 100644 --- a/ui/components/multichain/app-header/app-header.js +++ b/ui/components/multichain/app-header/app-header.js @@ -1,9 +1,8 @@ -import React, { useCallback, useContext, useRef, useState } from 'react'; +import React, { useCallback, useContext, useRef } from 'react'; import classnames from 'classnames'; import PropTypes from 'prop-types'; -import browser from 'webextension-polyfill'; import { useDispatch, useSelector } from 'react-redux'; -import { matchPath, useHistory } from 'react-router-dom'; +import { matchPath } from 'react-router-dom'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { MetaMetricsEventCategory, @@ -12,8 +11,6 @@ import { import { BUILD_QUOTE_ROUTE, CONFIRM_TRANSACTION_ROUTE, - CONNECTIONS, - DEFAULT_ROUTE, SWAPS_ROUTE, } from '../../../helpers/constants/routes'; @@ -21,85 +18,39 @@ import { AlignItems, BackgroundColor, BlockSize, - BorderRadius, Display, - FlexDirection, - FontWeight, - IconColor, JustifyContent, - Size, - TextColor, - TextVariant, } from '../../../helpers/constants/design-system'; -import { - Box, - ButtonBase, - ButtonBaseSize, - ButtonIcon, - ButtonIconSize, - IconName, - PickerNetwork, - Text, -} from '../../component-library'; -import { - getCurrentChainId, - getCurrentNetwork, - getOriginOfCurrentTab, - getTestNetworkBackgroundColor, - getSelectedInternalAccount, - getUnapprovedTransactions, -} from '../../../selectors'; -import { AccountPicker, GlobalMenu } from '..'; +import { Box } from '../../component-library'; +import { getUnapprovedTransactions } from '../../../selectors'; -import { toggleAccountMenu, toggleNetworkMenu } from '../../../store/actions'; -import MetafoxLogo from '../../ui/metafox-logo'; +import { toggleNetworkMenu } from '../../../store/actions'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; -import ConnectedStatusIndicator from '../../app/connected-status-indicator'; -import { useI18nContext } from '../../../hooks/useI18nContext'; import { getIsUnlocked } from '../../../ducks/metamask/metamask'; import { SEND_STAGES, getSendStage } from '../../../ducks/send'; -import Tooltip from '../../ui/tooltip'; -import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; -import { MINUTE } from '../../../../shared/constants/time'; -import { shortenAddress } from '../../../helpers/utils/util'; -import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; -import { NotificationsTagCounter } from '../notifications-tag-counter'; +import { getMultichainNetwork } from '../../../selectors/multichain'; import { MultichainMetaFoxLogo } from './multichain-meta-fox-logo'; +import { AppHeaderContainer } from './app-header-container'; +import { AppHeaderUnlockedContent } from './app-header-unlocked-content'; +import { AppHeaderLockedContent } from './app-header-locked-content'; export const AppHeader = ({ location }) => { const trackEvent = useContext(MetaMetricsContext); - const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false); const menuRef = useRef(null); - const origin = useSelector(getOriginOfCurrentTab); - const history = useHistory(); const isUnlocked = useSelector(getIsUnlocked); - const t = useI18nContext(); - const chainId = useSelector(getCurrentChainId); - - // Used for account picker - const internalAccount = useSelector(getSelectedInternalAccount); - const shortenedAddress = - internalAccount && - shortenAddress(toChecksumHexAddress(internalAccount.address)); - const dispatch = useDispatch(); - - // Used for network icon / dropdown - const currentNetwork = useSelector(getCurrentNetwork); - const testNetworkBackgroundColor = useSelector(getTestNetworkBackgroundColor); - // Used for copy button + const { + chainId, + // Used for network icon / dropdown + network: currentNetwork, + // Used for network icon / dropdown + isEvmNetwork, + } = useSelector(getMultichainNetwork); - // During onboarding there is no selected internal account - const currentAddress = internalAccount?.address; - const checksummedCurrentAddress = toChecksumHexAddress(currentAddress); - const [copied, handleCopy] = useCopyToClipboard(MINUTE); + const dispatch = useDispatch(); const popupStatus = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP; - const showConnectedStatus = - getEnvironmentType() === ENVIRONMENT_TYPE_POPUP && - origin && - origin !== browser.runtime.id; // Disable the network and account pickers if the user is in // a critical flow @@ -134,7 +85,8 @@ export const AppHeader = ({ location }) => { isSwapsPage || isTransactionEditPage || isConfirmationPage || - hasUnapprovedTransactions; + hasUnapprovedTransactions || + !isEvmNetwork; // Callback for network dropdown const networkOpenCallback = useCallback(() => { @@ -149,263 +101,64 @@ export const AppHeader = ({ location }) => { }); }, [chainId, dispatch, trackEvent]); - const handleConnectionsRoute = () => { - history.push(`${CONNECTIONS}/${encodeURIComponent(origin)}`); - }; - - const handleMainMenuOpened = () => { - trackEvent({ - event: MetaMetricsEventName.NavMainMenuOpened, - category: MetaMetricsEventCategory.Navigation, - properties: { - location: 'Home', - }, - }); - setAccountOptionsMenuOpen(true); - }; - // This is required to ensure send and confirmation screens // look as desired const headerBottomMargin = !popupStatus && disableNetworkPicker ? 4 : 0; + const unlockedStyling = { + alignItems: AlignItems.center, + width: BlockSize.Full, + backgroundColor: BackgroundColor.backgroundDefault, + padding: 2, + paddingLeft: 4, + paddingRight: 4, + gap: 2, + }; + + const lockStyling = { + display: Display.Flex, + alignItems: AlignItems.center, + width: BlockSize.Full, + justifyContent: JustifyContent.spaceBetween, + backgroundColor: BackgroundColor.backgroundDefault, + padding: 2, + gap: 2, + }; + return ( <> {isUnlocked && !popupStatus ? <MultichainMetaFoxLogo /> : null} - <Box - display={Display.Flex} - className={classnames('multichain-app-header', { - 'multichain-app-header-shadow': !isUnlocked || popupStatus, - })} - marginBottom={headerBottomMargin} - alignItems={AlignItems.center} - width={BlockSize.Full} - backgroundColor={ - !isUnlocked || popupStatus - ? BackgroundColor.backgroundDefault - : BackgroundColor.backgroundAlternative - } + <AppHeaderContainer + isUnlocked={isUnlocked} + popupStatus={popupStatus} + headerBottomMargin={headerBottomMargin} > <> - {isUnlocked ? ( - <Box - className={classnames('multichain-app-header__contents', { - 'multichain-app-header-shadow': isUnlocked && !popupStatus, - })} - alignItems={AlignItems.center} - width={BlockSize.Full} - backgroundColor={BackgroundColor.backgroundDefault} - padding={2} - paddingLeft={4} - paddingRight={4} - gap={2} - > - {popupStatus ? ( - <Box className="multichain-app-header__contents__container"> - <Tooltip title={currentNetwork?.nickname} position="right"> - <PickerNetwork - avatarNetworkProps={{ - backgroundColor: testNetworkBackgroundColor, - role: 'img', - }} - className="multichain-app-header__contents--avatar-network" - ref={menuRef} - as="button" - src={currentNetwork?.rpcPrefs?.imageUrl} - label={currentNetwork?.nickname} - aria-label={`${t('networkMenu')} ${ - currentNetwork?.nickname - }`} - labelProps={{ - display: Display.None, - }} - onClick={(e) => { - e.stopPropagation(); - e.preventDefault(); - networkOpenCallback(); - }} - display={[Display.Flex, Display.None]} // show on popover hide on desktop - disabled={disableNetworkPicker} - /> - </Tooltip> - </Box> - ) : ( - <div> - <PickerNetwork - avatarNetworkProps={{ - backgroundColor: testNetworkBackgroundColor, - role: 'img', - }} - margin={2} - aria-label={`${t('networkMenu')} ${ - currentNetwork?.nickname - }`} - label={currentNetwork?.nickname} - src={currentNetwork?.rpcPrefs?.imageUrl} - onClick={(e) => { - e.stopPropagation(); - e.preventDefault(); - networkOpenCallback(); - }} - display={[Display.None, Display.Flex]} // show on desktop hide on popover - className="multichain-app-header__contents__network-picker" - disabled={disableNetworkPicker} - data-testid="network-display" - /> - </div> - )} - - {internalAccount ? ( - <Text - as="div" - display={Display.Flex} - flexDirection={FlexDirection.Column} - alignItems={AlignItems.center} - ellipsis - > - <AccountPicker - address={internalAccount.address} - name={internalAccount.metadata.name} - onClick={() => { - dispatch(toggleAccountMenu()); - - trackEvent({ - event: MetaMetricsEventName.NavAccountMenuOpened, - category: MetaMetricsEventCategory.Navigation, - properties: { - location: 'Home', - }, - }); - }} - disabled={disableAccountPicker} - labelProps={{ fontWeight: FontWeight.Bold }} - paddingLeft={2} - paddingRight={2} - /> - <Tooltip - position="left" - title={copied ? t('addressCopied') : t('copyToClipboard')} - > - <ButtonBase - className="multichain-app-header__address-copy-button" - onClick={() => handleCopy(checksummedCurrentAddress)} - size={ButtonBaseSize.Sm} - backgroundColor={BackgroundColor.transparent} - borderRadius={BorderRadius.LG} - endIconName={ - copied ? IconName.CopySuccess : IconName.Copy - } - endIconProps={{ - color: IconColor.iconAlternative, - size: Size.SM, - }} - ellipsis - textProps={{ - display: Display.Flex, - alignItems: AlignItems.center, - gap: 2, - }} - style={{ height: 'auto' }} // ButtonBase doesn't have auto size - data-testid="app-header-copy-button" - > - <Text - color={TextColor.textAlternative} - variant={TextVariant.bodySm} - ellipsis - as="span" - > - {shortenedAddress} - </Text> - </ButtonBase> - </Tooltip> - </Text> - ) : null} - <Box - display={Display.Flex} - alignItems={AlignItems.center} - justifyContent={JustifyContent.flexEnd} - style={{ marginLeft: 'auto' }} - > - <Box display={Display.Flex} gap={4}> - {showConnectedStatus ? ( - <Box ref={menuRef}> - <ConnectedStatusIndicator - onClick={() => { - handleConnectionsRoute(); - }} - /> - </Box> - ) : null}{' '} - <Box - ref={menuRef} - display={Display.Flex} - justifyContent={JustifyContent.flexEnd} - width={BlockSize.Full} - > - {!accountOptionsMenuOpen && ( - <Box - style={{ position: 'relative' }} - onClick={() => handleMainMenuOpened()} - > - <NotificationsTagCounter noLabel /> - </Box> - )} - <ButtonIcon - iconName={IconName.MoreVertical} - data-testid="account-options-menu-button" - ariaLabel={t('accountOptions')} - onClick={() => handleMainMenuOpened()} - size={ButtonIconSize.Sm} - /> - </Box> - </Box> - <GlobalMenu - anchorElement={menuRef.current} - isOpen={accountOptionsMenuOpen} - closeMenu={() => setAccountOptionsMenuOpen(false)} - /> - </Box> - </Box> - ) : ( - <Box - display={Display.Flex} - className={classnames('multichain-app-header__lock-contents', { - 'multichain-app-header-shadow': isUnlocked && !popupStatus, - })} - alignItems={AlignItems.center} - width={BlockSize.Full} - justifyContent={JustifyContent.spaceBetween} - backgroundColor={BackgroundColor.backgroundDefault} - padding={2} - gap={2} - > - <div> - <PickerNetwork - avatarNetworkProps={{ - backgroundColor: testNetworkBackgroundColor, - role: 'img', - }} - aria-label={`${t('networkMenu')} ${currentNetwork?.nickname}`} - label={currentNetwork?.nickname} - src={currentNetwork?.rpcPrefs?.imageUrl} - onClick={(e) => { - e.stopPropagation(); - e.preventDefault(); - networkOpenCallback(); - }} - className="multichain-app-header__contents__network-picker" - data-testid="network-display" - /> - </div> - <MetafoxLogo - unsetIconHeight - onClick={async () => { - history.push(DEFAULT_ROUTE); - }} + <Box + className={classnames('multichain-app-header__contents', { + 'multichain-app-header-shadow': isUnlocked && !popupStatus, + })} + {...(isUnlocked ? unlockedStyling : lockStyling)} + > + {isUnlocked ? ( + <AppHeaderUnlockedContent + popupStatus={popupStatus} + isEvmNetwork={isEvmNetwork} + currentNetwork={currentNetwork} + networkOpenCallback={networkOpenCallback} + disableNetworkPicker={disableNetworkPicker} + disableAccountPicker={disableAccountPicker} + menuRef={menuRef} + /> + ) : ( + <AppHeaderLockedContent + currentNetwork={currentNetwork} + networkOpenCallback={networkOpenCallback} /> - </Box> - )} + )} + </Box> </> - </Box> + </AppHeaderContainer> </> ); }; diff --git a/ui/components/multichain/connected-site-menu/connected-site-menu.js b/ui/components/multichain/connected-site-menu/connected-site-menu.js index 734ab1b996c6..c7811b3e819c 100644 --- a/ui/components/multichain/connected-site-menu/connected-site-menu.js +++ b/ui/components/multichain/connected-site-menu/connected-site-menu.js @@ -39,6 +39,7 @@ export const ConnectedSiteMenu = ({ status, text, onClick, + disabled, }) => { const t = useI18nContext(); const selectedAccount = useSelector(getSelectedInternalAccount); @@ -50,7 +51,10 @@ export const ConnectedSiteMenu = ({ status === STATUS_CONNECTED_TO_SNAP; return ( <Box - className={classNames('multichain-connected-site-menu', className)} + className={classNames( + `multichain-connected-site-menu${disabled ? '--disabled' : ''}`, + className, + )} data-testid="connection-menu" as="button" onClick={onClick} @@ -130,4 +134,8 @@ ConnectedSiteMenu.propTypes = { * onClick handler to be passed */ onClick: PropTypes.func, + /** + * Disable the connected site menu if the account is non-evm + */ + disabled: PropTypes.boolean, }; diff --git a/ui/components/multichain/connected-site-menu/index.scss b/ui/components/multichain/connected-site-menu/index.scss index c3e339477ca7..d1b05f7d3125 100644 --- a/ui/components/multichain/connected-site-menu/index.scss +++ b/ui/components/multichain/connected-site-menu/index.scss @@ -3,6 +3,12 @@ width: 24px; padding: 0; + &--disabled, + &:disabled { + opacity: var(--opacity-disabled); + cursor: not-allowed; + } + &__badge { height: 12px; width: 12px; diff --git a/ui/selectors/multichain.test.ts b/ui/selectors/multichain.test.ts index 582ba681403a..2b01bf105e82 100644 --- a/ui/selectors/multichain.test.ts +++ b/ui/selectors/multichain.test.ts @@ -31,6 +31,7 @@ type TestState = AccountsState & { providerConfig: { ticker: string; chainId: string }; currentCurrency: string; currencyRates: Record<string, { conversionRate: string }>; + completedOnboarding: boolean; }; }; @@ -49,6 +50,7 @@ const MOCK_EVM_STATE: TestState = { conversionRate: 'usd', }, }, + completedOnboarding: true, internalAccounts: { selectedAccount: MOCK_ACCOUNT_EOA.id, accounts: MOCK_ACCOUNTS, @@ -97,6 +99,15 @@ describe('Multichain Selectors', () => { const network = getMultichainNetwork(state); expect(network.isEvmNetwork).toBe(false); }); + + it('returns an EVM network provider if user is not onboarded', () => { + const state = MOCK_EVM_STATE; + state.metamask.completedOnboarding = false; + state.metamask.internalAccounts.selectedAccount = ''; + + const network = getMultichainNetwork(state); + expect(network.isEvmNetwork).toBe(true); + }); }); describe('getMultichainIsEvm', () => { diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index e97b08b85030..87598561c406 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -10,6 +10,7 @@ import { MULTICHAIN_PROVIDER_CONFIGS, } from '../../shared/constants/multichain/networks'; import { + getCompletedOnboarding, getNativeCurrency, getProviderConfig, } from '../ducks/metamask/metamask'; @@ -45,14 +46,17 @@ export function getMultichainNetworkProviders( export function getMultichainNetwork( state: MultichainState, ): MultichainNetwork { + const isOnboarded = getCompletedOnboarding(state); + // Selected account is not available during onboarding + // This is used in the app header const selectedAccount = getSelectedInternalAccount(state); - const isEvm = isEvmAccountType(selectedAccount.type); + const isEvm = isEvmAccountType(selectedAccount?.type); // EVM networks const evmNetworks: ProviderConfig[] = getAllNetworks(state); const evmProvider: ProviderConfig = getProviderConfig(state); - if (isEvm) { + if (!isOnboarded || isEvm) { const evmChainId = `${KnownCaipNamespace.Eip155}:${evmProvider.chainId}` as CaipChainId; const evmNetwork = evmNetworks.find( From ab695aa17e5616ba294d10cdd67513c68bc5cae6 Mon Sep 17 00:00:00 2001 From: Jony Bursztyn <jony.bursztyn@consensys.net> Date: Wed, 12 Jun 2024 16:38:05 +0200 Subject: [PATCH 14/61] feat: adds "data collection for marketing" toggles (#24605) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds data collection for marketing toggles (and toasts/warnings) on: - Onboarding - Toast in Wallet - Settings page <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/24605?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/MetaMask-planning/issues/2437 https://github.com/MetaMask/MetaMask-planning/issues/2438 https://github.com/MetaMask/MetaMask-planning/issues/2526 ## **Manual testing steps** Onboarding checkbox: Make the `metametrics.js` to return `renderOnboarding` instead of `renderLegacyOnboarding` 1. Start a new account 2. There should be a new checkbox that asks for marketing consent 3. Checking it should set the marketing consent to true (check at Settings, Securty tab page) Security tab: 1. Go to Security tab 2. When checking the "Data collection for marketing" to `true`, the "Participate in MetaMetrics" toggle should turn to `true` 3. When checking "Participate in MetaMetrics" to `false`, "Data collection for marketing" should be set to `false` 4. When "Participate in Metametrics" is `true` and "Data collection for marketing" is `true`, and the latter is set to `false`, a warning message should appear. Toast: An already onboarded user will have the "dataCollectionForMarketing" value as `null` (neither `true` or `false`). This will trigger the toast. 1. By clicking on "I accept", it should set the "Data collection for marketing" to `true`. 2. By closing the toast or clicking on "No thanks", it should set the "Data collection for marketing" to `false`. All of these actions should trigger subsequent Segment events. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <img width="646" alt="Screenshot 2024-05-20 at 14 19 53" src="https://github.com/MetaMask/metamask-extension/assets/11148144/a13b70ec-1d89-4e9f-8df1-2096dd56e642"> https://github.com/MetaMask/metamask-extension/assets/11148144/5eb59902-768d-4d07-a112-5aeb5471587d ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Mircea Nistor <mirceanis@gmail.com> Co-authored-by: NidhiKJha <menidhikjha@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com> Co-authored-by: Nidhi Kumari <nidhi.kumari@consensys.net> --- app/_locales/en/messages.json | 46 ++++++ app/scripts/controllers/metametrics.js | 11 ++ app/scripts/lib/setupSentry.js | 1 + app/scripts/metamask-controller.js | 4 + shared/constants/metametrics.ts | 9 ++ test/e2e/default-fixture.js | 1 + ...rs-after-init-opt-in-background-state.json | 1 + .../errors-after-init-opt-in-ui-state.json | 1 + ...s-before-init-opt-in-background-state.json | 1 + .../errors-before-init-opt-in-ui-state.json | 1 + ui/components/ui/popover/index.scss | 4 + ui/components/ui/popover/popover.component.js | 6 + ui/ducks/metamask/metamask.js | 7 + ui/helpers/constants/common.ts | 3 + ui/pages/home/home.component.js | 116 +++++++++++++- ui/pages/home/home.container.js | 7 + ui/pages/home/index.scss | 8 + .../__snapshots__/metametrics.test.js.snap | 151 ++++++++++++++++++ .../metametrics/metametrics.js | 42 ++++- .../metametrics/metametrics.test.js | 40 ++++- .../__snapshots__/security-tab.test.js.snap | 68 ++++++++ .../metametrics-toggle.test.tsx | 18 ++- .../metametrics-toggle/metametrics-toggle.tsx | 22 ++- .../security-tab/security-tab.component.js | 132 ++++++++++++++- .../security-tab/security-tab.container.js | 5 + ui/selectors/metametrics.js | 6 + ui/store/actionConstants.ts | 2 + ui/store/actions.ts | 20 +++ 28 files changed, 723 insertions(+), 10 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index fcc425becf68..05f3a7cd53b4 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1310,6 +1310,18 @@ "dataBackupSeemsCorrupt": { "message": "Can not restore your data. The file appears to be corrupt." }, + "dataCollectionForMarketing": { + "message": "Data collection for marketing" + }, + "dataCollectionForMarketingDescription": { + "message": "We'll use MetaMetrics to learn how you interact with our marketing communications. We may share relevant news (like product features and other materials)." + }, + "dataCollectionWarningPopoverButton": { + "message": "Okay" + }, + "dataCollectionWarningPopoverDescription": { + "message": "You turned off data collection for our marketing purposes. This only applies to this device. If you use MetaMask on other devices, make sure to opt out there as well." + }, "dataHex": { "message": "Hex" }, @@ -3254,6 +3266,37 @@ "on": { "message": "On" }, + "onboardedMetametricsAccept": { + "message": "I agree" + }, + "onboardedMetametricsDisagree": { + "message": "No thanks" + }, + "onboardedMetametricsKey1": { + "message": "Latest developments" + }, + "onboardedMetametricsKey2": { + "message": "Product features" + }, + "onboardedMetametricsKey3": { + "message": "Other relevant promotional materials" + }, + "onboardedMetametricsLink": { + "message": "MetaMetrics" + }, + "onboardedMetametricsParagraph1": { + "message": "In addition to $1, we'd like to use data to understand how you interact with marketing communications.", + "description": "$1 represents the 'onboardedMetametricsLink' locale string" + }, + "onboardedMetametricsParagraph2": { + "message": "This helps us personalize what we share with you, like:" + }, + "onboardedMetametricsParagraph3": { + "message": "Remember, we never sell the data you provide and you can opt out any time." + }, + "onboardedMetametricsTitle": { + "message": "Help us enhance your experience" + }, "onboarding": { "message": "Onboarding" }, @@ -3370,6 +3413,9 @@ "onboardingMetametricsTitle": { "message": "Help us improve MetaMask" }, + "onboardingMetametricsUseDataCheckbox": { + "message": "We’ll use this data to learn how you interact with our marketing communications. We may share relevant news (like product features)." + }, "onboardingPinExtensionBillboardAccess": { "message": "Full access" }, diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index fca239a25394..c7bd148e62d3 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -154,6 +154,7 @@ export default class MetaMetricsController { this.store = new ObservableStore({ participateInMetaMetrics: null, metaMetricsId: null, + dataCollectionForMarketing: null, eventsBeforeMetricsOptIn: [], traits: {}, previousUserTraits: {}, @@ -475,6 +476,12 @@ export default class MetaMetricsController { return metaMetricsId; } + setDataCollectionForMarketing(dataCollectionForMarketing) { + const { metaMetricsId } = this.state; + this.store.updateState({ dataCollectionForMarketing }); + return metaMetricsId; + } + get state() { return this.store.getState(); } @@ -824,6 +831,10 @@ export default class MetaMetricsController { metamaskState.securityAlertsEnabled ? ['blockaid'] : [], [MetaMetricsUserTrait.PetnameAddressCount]: this._getPetnameAddressCount(metamaskState), + [MetaMetricsUserTrait.IsMetricsOptedIn]: + metamaskState.participateInMetaMetrics, + [MetaMetricsUserTrait.HasMarketingConsent]: + metamaskState.dataCollectionForMarketing, }; if (!previousUserTraits) { diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 179df5ba8668..94843c2e9a98 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -169,6 +169,7 @@ export const SENTRY_BACKGROUND_STATE = { previousUserTraits: false, segmentApiCalls: false, traits: false, + dataCollectionForMarketing: false, }, NameController: { names: false, diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index e93a4a001865..12c209020403 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -3050,6 +3050,10 @@ export default class MetamaskController extends EventEmitter { metaMetricsController.setParticipateInMetaMetrics.bind( metaMetricsController, ), + setDataCollectionForMarketing: + metaMetricsController.setDataCollectionForMarketing.bind( + metaMetricsController, + ), setCurrentLocale: preferencesController.setCurrentLocale.bind( preferencesController, ), diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts index ed07ad3a4b58..13b91135446d 100644 --- a/shared/constants/metametrics.ts +++ b/shared/constants/metametrics.ts @@ -379,6 +379,14 @@ export type MetaMetricsUserTraits = { }; export enum MetaMetricsUserTrait { + /** + * Identifies if the user has opted in for MetaMetrics + */ + IsMetricsOptedIn = 'is_metrics_opted_in', + /** + * Identifies is the user has given marketing consent + */ + HasMarketingConsent = 'has_marketing_consent', /** * Identified when the user adds or modifies addresses in the address book. */ @@ -497,6 +505,7 @@ export enum MetaMetricsEventName { AccountRenamed = 'Account Renamed', ActivityDetailsOpened = 'Activity Details Opened', ActivityDetailsClosed = 'Activity Details Closed', + AnalyticsPreferenceSelected = 'Analytics Preference Selected', AppInstalled = 'App Installed', AppUnlocked = 'App Unlocked', AppUnlockedFailed = 'App Unlocked Failed', diff --git a/test/e2e/default-fixture.js b/test/e2e/default-fixture.js index 1c6a2d77433b..98413671caca 100644 --- a/test/e2e/default-fixture.js +++ b/test/e2e/default-fixture.js @@ -139,6 +139,7 @@ function defaultFixture(inputChainId = CHAIN_IDS.LOCALHOST) { fragments: {}, metaMetricsId: null, participateInMetaMetrics: false, + dataCollectionForMarketing: false, traits: {}, }, NetworkController: { diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json index d7f940573fe8..e6a62e19d994 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json @@ -103,6 +103,7 @@ "traits": "object", "previousUserTraits": "object", "fragments": "object", + "dataCollectionForMarketing": "boolean", "segmentApiCalls": "object" }, "MetamaskNotificationsController": { diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json index 91ab85dc3fb0..11d99c406b31 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json @@ -40,6 +40,7 @@ "knownMethodData": "object", "use4ByteResolution": true, "participateInMetaMetrics": true, + "dataCollectionForMarketing": "boolean", "nextNonce": null, "currencyRates": { "ETH": { diff --git a/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-background-state.json index c191ad287761..60379a1d0811 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-background-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-background-state.json @@ -69,6 +69,7 @@ "fragments": "object", "metaMetricsId": "fake-metrics-id", "participateInMetaMetrics": true, + "dataCollectionForMarketing": "boolean", "traits": "object" }, "NetworkController": { diff --git a/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-ui-state.json index 84ca7297d46c..48392c6b4db3 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-ui-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-ui-state.json @@ -69,6 +69,7 @@ "fragments": "object", "metaMetricsId": "fake-metrics-id", "participateInMetaMetrics": true, + "dataCollectionForMarketing": "boolean", "traits": "object" }, "NetworkController": { diff --git a/ui/components/ui/popover/index.scss b/ui/components/ui/popover/index.scss index c657ef2f3764..a935508e7476 100644 --- a/ui/components/ui/popover/index.scss +++ b/ui/components/ui/popover/index.scss @@ -28,6 +28,10 @@ &__title--center { flex: 1; } + + &__title-wrap { + white-space: normal; + } } &-bg { diff --git a/ui/components/ui/popover/popover.component.js b/ui/components/ui/popover/popover.component.js index 261883c5666c..385f2896bb15 100644 --- a/ui/components/ui/popover/popover.component.js +++ b/ui/components/ui/popover/popover.component.js @@ -75,6 +75,7 @@ const Popover = ({ showScrollDown, onScrollDownButtonClick, centerTitle, + wrapTitle, headerProps = defaultHeaderProps, contentProps = defaultContentProps, footerProps = defaultFooterProps, @@ -106,6 +107,7 @@ const Popover = ({ ) : null} <Text textAlign={centerTitle ? TextAlign.Center : TextAlign.Start} + className={wrapTitle ? 'popover-header__title-wrap' : null} ellipsis variant={TextVariant.headingSm} as="h2" @@ -184,6 +186,10 @@ const Popover = ({ }; Popover.propTypes = { + /** + * Avoid wrapping title + */ + wrapTitle: PropTypes.bool, /** * Show title of the popover */ diff --git a/ui/ducks/metamask/metamask.js b/ui/ducks/metamask/metamask.js index 442bb97db93d..1704444447f6 100644 --- a/ui/ducks/metamask/metamask.js +++ b/ui/ducks/metamask/metamask.js @@ -56,6 +56,7 @@ const initialState = { knownMethodData: {}, use4ByteResolution: true, participateInMetaMetrics: null, + dataCollectionForMarketing: null, nextNonce: null, currencyRates: { ETH: { @@ -162,6 +163,12 @@ export default function reduceMetamask(state = initialState, action) { participateInMetaMetrics: action.value, }; + case actionConstants.SET_DATA_COLLECTION_FOR_MARKETING: + return { + ...metamaskState, + dataCollectionForMarketing: action.value, + }; + case actionConstants.CLOSE_WELCOME_SCREEN: return { ...metamaskState, diff --git a/ui/helpers/constants/common.ts b/ui/helpers/constants/common.ts index 09b2ef377259..8170536690b0 100644 --- a/ui/helpers/constants/common.ts +++ b/ui/helpers/constants/common.ts @@ -9,6 +9,9 @@ const _mmiWebSite = 'https://metamask.io/institutions/'; export const MMI_WEB_SITE = _mmiWebSite; ///: END:ONLY_INCLUDE_IF +// eslint-disable-next-line prefer-destructuring +export const METAMETRICS_SETTINGS_LINK = + 'https://support.metamask.io/privacy-and-security/how-to-manage-your-metametrics-settings'; // eslint-disable-next-line prefer-destructuring export const SUPPORT_REQUEST_LINK = process.env.SUPPORT_REQUEST_LINK; export const CONTRACT_ADDRESS_LINK = _contractAddressLink; diff --git a/ui/pages/home/home.component.js b/ui/pages/home/home.component.js index 45419b646600..e8767bd816da 100644 --- a/ui/pages/home/home.component.js +++ b/ui/pages/home/home.component.js @@ -18,8 +18,9 @@ import AutoDetectTokenModal from '../../components/app/auto-detect-token/auto-de ///: END:ONLY_INCLUDE_IF import HomeNotification from '../../components/app/home-notification'; import MultipleNotifications from '../../components/app/multiple-notifications'; -import Popover from '../../components/ui/popover'; +import Typography from '../../components/ui/typography/typography'; import Button from '../../components/ui/button'; +import Popover from '../../components/ui/popover'; import ConnectedSites from '../connected-sites'; import ConnectedAccounts from '../connected-accounts'; import { isMv3ButOffscreenDocIsMissing } from '../../../shared/modules/mv3.utils'; @@ -30,6 +31,10 @@ import { Display, TextColor, TextVariant, + FlexDirection, + BlockSize, + AlignItems, + JustifyContent, } from '../../helpers/constants/design-system'; import { SECOND } from '../../../shared/constants/time'; import { @@ -39,6 +44,12 @@ import { Box, Text, Icon, + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, } from '../../components/component-library'; import { RESTORE_VAULT_ROUTE, @@ -61,6 +72,7 @@ import { ///: END:ONLY_INCLUDE_IF } from '../../helpers/constants/routes'; import ZENDESK_URLS from '../../helpers/constants/zendesk-url'; +import { METAMETRICS_SETTINGS_LINK } from '../../helpers/constants/common'; import { ///: BEGIN:ONLY_INCLUDE_IF(build-main) SUPPORT_LINK, @@ -146,9 +158,12 @@ export default class Home extends PureComponent { // eslint-disable-next-line react/no-unused-prop-types totalUnapprovedCount: PropTypes.number.isRequired, defaultHomeActiveTabName: PropTypes.string, + participateInMetaMetrics: PropTypes.bool.isRequired, onTabClick: PropTypes.func.isRequired, haveSwapsQuotes: PropTypes.bool.isRequired, showAwaitingSwapScreen: PropTypes.bool.isRequired, + setDataCollectionForMarketing: PropTypes.func.isRequired, + dataCollectionForMarketing: PropTypes.bool, swapsFetchParams: PropTypes.object, location: PropTypes.object, shouldShowWeb3ShimUsageNotification: PropTypes.bool.isRequired, @@ -756,6 +771,99 @@ export default class Home extends PureComponent { ); } + renderOnboardingPopover = () => { + const { t } = this.context; + const { setDataCollectionForMarketing } = this.props; + + const handleClose = () => { + setDataCollectionForMarketing(false); + this.context.trackEvent({ + category: MetaMetricsEventCategory.Home, + event: MetaMetricsEventName.AnalyticsPreferenceSelected, + properties: { + has_marketing_consent: false, + location: 'marketing_consent_modal', + }, + }); + }; + + const handleConsent = (consent) => { + setDataCollectionForMarketing(consent); + this.context.trackEvent({ + category: MetaMetricsEventCategory.Home, + event: MetaMetricsEventName.AnalyticsPreferenceSelected, + properties: { + has_marketing_consent: consent, + location: 'marketing_consent_modal', + }, + }); + }; + + return ( + <Modal isOpen onClose={handleClose}> + <ModalOverlay /> + <ModalContent> + <ModalHeader + onClose={handleClose} + display={Display.Flex} + flexDirection={FlexDirection.Row} + fontWeight={FontWeight.Bold} + alignItems={AlignItems.center} + justifyContent={JustifyContent.center} + gap={4} + size={18} + paddingBottom={0} + > + {t('onboardedMetametricsTitle')} + </ModalHeader> + <ModalBody> + <Box + display={Display.Flex} + flexDirection={FlexDirection.Column} + gap={2} + margin={4} + > + <Typography> + {t('onboardedMetametricsParagraph1', [ + <a + href={METAMETRICS_SETTINGS_LINK} + target="_blank" + rel="noopener noreferrer" + key="retention-link" + > + {t('onboardedMetametricsLink')} + </a>, + ])} + </Typography> + <Typography>{t('onboardedMetametricsParagraph2')}</Typography> + <ul className="home__onboarding_list"> + <li>{t('onboardedMetametricsKey1')}</li> + <li>{t('onboardedMetametricsKey2')}</li> + <li>{t('onboardedMetametricsKey3')}</li> + </ul> + <Typography>{t('onboardedMetametricsParagraph3')}</Typography> + </Box> + </ModalBody> + <ModalFooter> + <Box + display={Display.Flex} + flexDirection={FlexDirection.Row} + gap={2} + width={BlockSize.Full} + > + <Button type="secondary" onClick={() => handleConsent(false)}> + {t('onboardedMetametricsDisagree')} + </Button> + <Button type="primary" onClick={() => handleConsent(true)}> + {t('onboardedMetametricsAccept')} + </Button> + </Box> + </ModalFooter> + </ModalContent> + </Modal> + ); + }; + renderPopover = () => { const { setConnectedStatusPopoverHasBeenShown } = this.props; const { t } = this.context; @@ -809,6 +917,8 @@ export default class Home extends PureComponent { useExternalServices, setBasicFunctionalityModalOpen, forgottenPassword, + participateInMetaMetrics, + dataCollectionForMarketing, ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) connectedStatusPopoverHasBeenShown, isPopup, @@ -871,6 +981,10 @@ export default class Home extends PureComponent { exact /> <div className="home__container"> + {dataCollectionForMarketing === null && + participateInMetaMetrics === true + ? this.renderOnboardingPopover() + : null} { ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) } diff --git a/ui/pages/home/home.container.js b/ui/pages/home/home.container.js index f5aaa584a4b5..91f37b9aff03 100644 --- a/ui/pages/home/home.container.js +++ b/ui/pages/home/home.container.js @@ -71,6 +71,7 @@ import { setNewTokensImported, setActiveNetwork, setNewTokensImportedError, + setDataCollectionForMarketing, setShowTokenAutodetectModal, setShowTokenAutodetectModalOnUpgrade, } from '../../store/actions'; @@ -103,6 +104,8 @@ const mapStateToProps = (state) => { connectedStatusPopoverHasBeenShown, defaultHomeActiveTabName, swapsState, + dataCollectionForMarketing, + participateInMetaMetrics, firstTimeFlowType, completedOnboarding, } = metamask; @@ -166,9 +169,11 @@ const mapStateToProps = (state) => { shouldShowSeedPhraseReminder: getShouldShowSeedPhraseReminder(state), isPopup, isNotification, + dataCollectionForMarketing, selectedAddress, firstPermissionsRequestId, totalUnapprovedCount, + participateInMetaMetrics, hasApprovalFlows: getApprovalFlows(state)?.length > 0, connectedStatusPopoverHasBeenShown, defaultHomeActiveTabName, @@ -220,6 +225,8 @@ const mapDispatchToProps = (dispatch) => { ///: END:ONLY_INCLUDE_IF return { + setDataCollectionForMarketing: (val) => + dispatch(setDataCollectionForMarketing(val)), closeNotificationPopup: () => closeNotificationPopup(), setConnectedStatusPopoverHasBeenShown: () => dispatch(setConnectedStatusPopoverHasBeenShown()), diff --git a/ui/pages/home/index.scss b/ui/pages/home/index.scss index 471a3b35d7fa..03b4cd5d7cf9 100644 --- a/ui/pages/home/index.scss +++ b/ui/pages/home/index.scss @@ -1,6 +1,14 @@ @use "design-system"; .home { + &__onboarding_list { + list-style: initial; + margin-inline-start: 20px; + display: flex; + flex-direction: column; + gap: 10px; + } + &__container { display: flex; min-height: 100%; diff --git a/ui/pages/onboarding-flow/metametrics/__snapshots__/metametrics.test.js.snap b/ui/pages/onboarding-flow/metametrics/__snapshots__/metametrics.test.js.snap index 8425fda35aa4..f669f81f59d7 100644 --- a/ui/pages/onboarding-flow/metametrics/__snapshots__/metametrics.test.js.snap +++ b/ui/pages/onboarding-flow/metametrics/__snapshots__/metametrics.test.js.snap @@ -150,3 +150,154 @@ exports[`Onboarding Metametrics Component should match snapshot 1`] = ` </div> </div> `; + +exports[`Onboarding Metametrics Component should match snapshot after new policy date 1`] = ` +<div> + <div + class="onboarding-metametrics" + data-testid="onboarding-legacy-metametrics" + > + <h2 + class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography typography--h2 typography--weight-bold typography--style-normal typography--align-center typography--color-text-default" + > + Help us improve MetaMask + </h2> + <p + class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography onboarding-metametrics__desc typography--p typography--weight-normal typography--style-normal typography--align-center typography--color-text-default" + > + MetaMask would like to gather usage data to better understand how our users interact with MetaMask. This data will be used to provide the service, which includes improving the service based on your use. + </p> + <p + class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography onboarding-metametrics__desc typography--p typography--weight-normal typography--style-normal typography--align-center typography--color-text-default" + > + MetaMask will... + </p> + <ul> + <li> + <span + class="mm-box mm-icon mm-icon--size-md mm-box--margin-inline-end-3 mm-box--display-inline-block mm-box--color-success-default" + style="mask-image: url('./images/icons/check.svg');" + /> + Always allow you to opt-out via Settings + </li> + <li> + <span + class="mm-box mm-icon mm-icon--size-md mm-box--margin-inline-end-3 mm-box--display-inline-block mm-box--color-success-default" + style="mask-image: url('./images/icons/check.svg');" + /> + Send anonymized click and pageview events + </li> + <li> + <div + class="box box--flex-direction-row" + > + <span + class="mm-box mm-icon mm-icon--size-sm mm-box--margin-inline-end-2 mm-box--display-inline-block mm-box--color-error-default" + style="mask-image: url('./images/icons/close.svg');" + /> + <span> + + + <span + class="box box--margin-bottom-1 box--flex-direction-row typography typography--span typography--weight-bold typography--style-normal typography--color-text-default" + > + Never + </span> + collect information we don’t need to provide the service (such as keys, addresses, transaction hashes, or balances) + + </span> + </div> + </li> + <li> + <div + class="box box--flex-direction-row" + > + <span + class="mm-box mm-icon mm-icon--size-sm mm-box--margin-inline-end-2 mm-box--display-inline-block mm-box--color-error-default" + style="mask-image: url('./images/icons/close.svg');" + /> + <span> + + + <span + class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography typography--span typography--weight-bold typography--style-normal typography--color-text-default" + > + Never + </span> + collect your full IP address* + + </span> + </div> + </li> + <li> + <div + class="box box--flex-direction-row" + > + <span + class="mm-box mm-icon mm-icon--size-sm mm-box--margin-inline-end-2 mm-box--display-inline-block mm-box--color-error-default" + style="mask-image: url('./images/icons/close.svg');" + /> + <span> + + + <span + class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography typography--span typography--weight-bold typography--style-normal typography--color-text-default" + > + Never + </span> + sell data. Ever! + + </span> + </div> + + </li> + </ul> + <h6 + class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography onboarding-metametrics__terms typography--h6 typography--weight-normal typography--style-normal typography--align-center typography--color-text-alternative" + > + This data is aggregated and is therefore anonymous for the purposes of General Data Protection Regulation (EU) 2016/679. + </h6> + <h6 + class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography onboarding-metametrics__terms typography--h6 typography--weight-normal typography--style-normal typography--align-center typography--color-text-alternative" + > + <span> + + * When you use Infura as your default RPC provider in MetaMask, Infura will collect your IP address and your Ethereum wallet address when you send a transaction. We don’t store this information in a way that allows our systems to associate those two pieces of data. For more information on how MetaMask and Infura interact from a data collection perspective, see our update + <a + href="https://consensys.io/blog/consensys-data-retention-update" + rel="noopener noreferrer" + target="_blank" + > + here + </a> + . For more information on our privacy practices in general, see our + <a + href="https://metamask.io/privacy.html" + rel="noopener noreferrer" + target="_blank" + > + Privacy Policy here + </a> + . + + </span> + </h6> + <div + class="onboarding-metametrics__buttons" + > + <button + class="button btn--rounded btn-primary btn--large" + data-testid="metametrics-i-agree" + > + I agree + </button> + <button + class="button btn--rounded btn-secondary btn--large" + data-testid="metametrics-no-thanks" + > + No thanks + </button> + </div> + </div> +</div> +`; diff --git a/ui/pages/onboarding-flow/metametrics/metametrics.js b/ui/pages/onboarding-flow/metametrics/metametrics.js index 60cc82975ae2..f874c99ca5e0 100644 --- a/ui/pages/onboarding-flow/metametrics/metametrics.js +++ b/ui/pages/onboarding-flow/metametrics/metametrics.js @@ -11,8 +11,13 @@ import { } from '../../../helpers/constants/design-system'; import Button from '../../../components/ui/button'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { setParticipateInMetaMetrics } from '../../../store/actions'; import { + setParticipateInMetaMetrics, + setDataCollectionForMarketing, +} from '../../../store/actions'; +import { + getParticipateInMetaMetrics, + getDataCollectionForMarketing, getFirstTimeFlowType, getFirstTimeFlowTypeRouteAfterMetaMetricsOptIn, } from '../../../selectors'; @@ -25,6 +30,7 @@ import { import { MetaMetricsContext } from '../../../contexts/metametrics'; import { + Checkbox, Icon, IconName, IconSize, @@ -45,9 +51,16 @@ export default function OnboardingMetametrics() { const nextRoute = useSelector(getFirstTimeFlowTypeRouteAfterMetaMetricsOptIn); const firstTimeFlowType = useSelector(getFirstTimeFlowType); + const dataCollectionForMarketing = useSelector(getDataCollectionForMarketing); + const participateInMetaMetrics = useSelector(getParticipateInMetaMetrics); + const trackEvent = useContext(MetaMetricsContext); const onConfirm = async () => { + if (dataCollectionForMarketing === null) { + await dispatch(setDataCollectionForMarketing(false)); + } + const [, metaMetricsId] = await dispatch(setParticipateInMetaMetrics(true)); try { trackEvent( @@ -67,6 +80,23 @@ export default function OnboardingMetametrics() { flushImmediately: true, }, ); + + if (participateInMetaMetrics) { + trackEvent({ + category: MetaMetricsEventCategory.Onboarding, + event: MetaMetricsEventName.AppInstalled, + }); + + trackEvent({ + category: MetaMetricsEventCategory.Onboarding, + event: MetaMetricsEventName.AnalyticsPreferenceSelected, + properties: { + is_metrics_opted_in: true, + has_marketing_consent: Boolean(dataCollectionForMarketing), + location: 'onboarding_metametrics', + }, + }); + } } finally { history.push(nextRoute); } @@ -74,6 +104,7 @@ export default function OnboardingMetametrics() { const onCancel = async () => { await dispatch(setParticipateInMetaMetrics(false)); + await dispatch(setDataCollectionForMarketing(false)); history.push(nextRoute); }; @@ -319,6 +350,15 @@ export default function OnboardingMetametrics() { </Box>{' '} </li> </ul> + <Checkbox + id="metametrics-opt-in" + isChecked={dataCollectionForMarketing} + onClick={() => + dispatch(setDataCollectionForMarketing(!dataCollectionForMarketing)) + } + label={t('onboardingMetametricsUseDataCheckbox')} + paddingBottom={3} + /> <Typography color={TextColor.textAlternative} align={TEXT_ALIGN.LEFT} diff --git a/ui/pages/onboarding-flow/metametrics/metametrics.test.js b/ui/pages/onboarding-flow/metametrics/metametrics.test.js index 25723361b8f5..487987a0f5f5 100644 --- a/ui/pages/onboarding-flow/metametrics/metametrics.test.js +++ b/ui/pages/onboarding-flow/metametrics/metametrics.test.js @@ -8,7 +8,10 @@ import { onboardingMetametricsAgree, onboardingMetametricsDisagree, } from '../../../../app/_locales/en/messages.json'; -import { setParticipateInMetaMetrics } from '../../../store/actions'; +import { + setParticipateInMetaMetrics, + setDataCollectionForMarketing, +} from '../../../store/actions'; import { FirstTimeFlowType } from '../../../../shared/constants/onboarding'; import OnboardingMetametrics from './metametrics'; @@ -29,6 +32,9 @@ jest.mock('../../../store/actions.ts', () => ({ setParticipateInMetaMetrics: jest .fn() .mockReturnValue(jest.fn((val) => Promise.resolve([val]))), + setDataCollectionForMarketing: jest + .fn() + .mockReturnValue(jest.fn((val) => Promise.resolve([val]))), })); describe('Onboarding Metametrics Component', () => { @@ -58,6 +64,20 @@ describe('Onboarding Metametrics Component', () => { expect(container).toMatchSnapshot(); }); + it('should match snapshot after new policy date', () => { + // TODO: merge this with the previous test once this date is reached + jest.useFakeTimers().setSystemTime(new Date('2024-06-05')); + + const { container } = renderWithProvider( + <OnboardingMetametrics />, + mockStore, + ); + + expect(container).toMatchSnapshot(); + + jest.useRealTimers(); + }); + it('should set setParticipateInMetaMetrics to true when clicking agree', async () => { const { queryByText } = renderWithProvider( <OnboardingMetametrics />, @@ -94,6 +114,24 @@ describe('Onboarding Metametrics Component', () => { }); }); + it('should set setDataCollectionForMarketing to false when clicking cancel', async () => { + const { queryByText } = renderWithProvider( + <OnboardingMetametrics />, + mockStore, + ); + + const confirmCancel = queryByText(onboardingMetametricsDisagree.message); + + fireEvent.click(confirmCancel); + + await waitFor(() => { + expect(setDataCollectionForMarketing).toHaveBeenCalledWith(false); + expect(mockPushHistory).toHaveBeenCalledWith( + ONBOARDING_CREATE_PASSWORD_ROUTE, + ); + }); + }); + it('should render the Onboarding component when the current date is after the new privacy policy date', () => { jest.useFakeTimers().setSystemTime(new Date('2099-11-11')); const { queryByTestId } = renderWithProvider( diff --git a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap index d2d94434223a..84eec8af8167 100644 --- a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap +++ b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap @@ -1748,6 +1748,74 @@ exports[`Security Tab should match snapshot 1`] = ` </div> </div> </div> + <div + class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between" + > + <div + class="settings-page__content-item" + > + <span> + Data collection for marketing + </span> + <div + class="settings-page__content-description" + > + <span> + We'll use MetaMetrics to learn how you interact with our marketing communications. We may share relevant news (like product features and other materials). + </span> + </div> + </div> + <div + class="settings-page__content-item-col" + data-testid="dataCollectionForMarketing" + > + <label + class="toggle-button toggle-button--off" + tabindex="0" + > + <div + style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" + > + <div + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + > + <div + style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" + /> + <div + style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 1;" + /> + </div> + <div + style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;" + > + <div + style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: var(--shadow-size-xs) var(--color-shadow-default); border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(255, 255, 255); left: 3px;" + /> + </div> + <input + style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;" + type="checkbox" + value="false" + /> + </div> + <div + class="toggle-button__status" + > + <span + class="toggle-button__label-off" + > + Off + </span> + <span + class="toggle-button__label-on" + > + On + </span> + </div> + </label> + </div> + </div> </div> </div> </div> diff --git a/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.test.tsx b/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.test.tsx index 04a851797097..5e93bc9feaab 100644 --- a/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.test.tsx +++ b/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.test.tsx @@ -46,7 +46,11 @@ describe('MetametricsToggle', () => { mockUseSelectorReturnValue = false; const { getByTestId } = render( <Provider store={store}> - <MetametricsToggle /> + <MetametricsToggle + dataCollectionForMarketing={false} + // eslint-disable-next-line no-empty-function + setDataCollectionForMarketing={() => {}} + /> </Provider>, ); expect(getByTestId('profileSyncToggle')).toBeInTheDocument(); @@ -56,7 +60,11 @@ describe('MetametricsToggle', () => { mockUseSelectorReturnValue = false; const { getByTestId } = render( <Provider store={store}> - <MetametricsToggle /> + <MetametricsToggle + dataCollectionForMarketing={false} + // eslint-disable-next-line no-empty-function + setDataCollectionForMarketing={() => {}} + /> </Provider>, ); fireEvent.click(getByTestId('toggleButton')); @@ -67,7 +75,11 @@ describe('MetametricsToggle', () => { mockUseSelectorReturnValue = true; const { getByTestId } = render( <Provider store={store}> - <MetametricsToggle /> + <MetametricsToggle + dataCollectionForMarketing={false} + // eslint-disable-next-line no-empty-function + setDataCollectionForMarketing={() => {}} + /> </Provider>, ); fireEvent.click(getByTestId('toggleButton')); diff --git a/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx b/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx index 60c208df8ccd..661dd7f974b4 100644 --- a/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx +++ b/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx @@ -22,7 +22,13 @@ import { TextVariant, } from '../../../../helpers/constants/design-system'; -const MetametricsToggle = () => { +const MetametricsToggle = ({ + dataCollectionForMarketing, + setDataCollectionForMarketing, +}: { + dataCollectionForMarketing: boolean; + setDataCollectionForMarketing: (value: boolean) => void; +}) => { const t = useI18nContext(); const trackEvent = useContext(MetaMetricsContext); const { enableMetametrics, error: enableMetametricsError } = @@ -46,6 +52,16 @@ const MetametricsToggle = () => { participateInMetaMetrics, }, }); + + trackEvent({ + category: MetaMetricsEventCategory.Settings, + event: MetaMetricsEventName.AnalyticsPreferenceSelected, + properties: { + is_metrics_opted_in: false, + has_marketing_consent: false, + location: 'Settings', + }, + }); } else { await enableMetametrics(); trackEvent({ @@ -57,6 +73,10 @@ const MetametricsToggle = () => { }, }); } + + if (dataCollectionForMarketing) { + setDataCollectionForMarketing(false); + } }; return ( diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js index fc2db3b0f93d..b20435e4b258 100644 --- a/ui/pages/settings/security-tab/security-tab.component.js +++ b/ui/pages/settings/security-tab/security-tab.component.js @@ -25,17 +25,23 @@ import SRPQuiz from '../../../components/app/srp-quiz-modal/SRPQuiz'; import { Button, BUTTON_SIZES, + Icon, + IconSize, + IconName, Box, Text, } from '../../../components/component-library'; import TextField from '../../../components/ui/text-field'; import ToggleButton from '../../../components/ui/toggle-button'; +import Popover from '../../../components/ui/popover'; import { Display, + BlockSize, FlexDirection, JustifyContent, TextColor, TextVariant, + IconColor, } from '../../../helpers/constants/design-system'; import { ADD_POPULAR_CUSTOM_NETWORK } from '../../../helpers/constants/routes'; import { @@ -60,6 +66,10 @@ export default class SecurityTab extends PureComponent { setOpenSeaEnabled: PropTypes.func, useNftDetection: PropTypes.bool, setUseNftDetection: PropTypes.func, + dataCollectionForMarketing: PropTypes.bool, + setDataCollectionForMarketing: PropTypes.func.isRequired, + participateInMetaMetrics: PropTypes.bool.isRequired, + setParticipateInMetaMetrics: PropTypes.func.isRequired, incomingTransactionsPreferences: PropTypes.object.isRequired, allNetworks: PropTypes.array.isRequired, setIncomingTransactionsPreferences: PropTypes.func.isRequired, @@ -98,6 +108,7 @@ export default class SecurityTab extends PureComponent { ipfsGateway: this.props.ipfsGateway || IPFS_DEFAULT_GATEWAY_URL, ipfsGatewayError: '', srpQuizModalVisible: false, + showDataCollectionDisclaimer: false, ipfsToggle: this.props.ipfsGateway.length > 0, }; @@ -114,9 +125,17 @@ export default class SecurityTab extends PureComponent { return React.createRef(); }); - componentDidUpdate() { + componentDidUpdate(prevProps) { const { t } = this.context; handleSettingsRefs(t, t('securityAndPrivacy'), this.settingsRefs); + + if ( + prevProps.dataCollectionForMarketing === true && + this.props.participateInMetaMetrics === true && + this.props.dataCollectionForMarketing === false + ) { + this.setState({ showDataCollectionDisclaimer: true }); + } } componentDidMount() { @@ -325,6 +344,61 @@ export default class SecurityTab extends PureComponent { ); } + renderDataCollectionForMarketing() { + const { t } = this.context; + const { + dataCollectionForMarketing, + participateInMetaMetrics, + setDataCollectionForMarketing, + setParticipateInMetaMetrics, + } = this.props; + + return ( + <Box + ref={this.settingsRefs[4]} + className="settings-page__content-row" + display={Display.Flex} + flexDirection={FlexDirection.Row} + justifyContent={JustifyContent.spaceBetween} + gap={4} + > + <div className="settings-page__content-item"> + <span>{t('dataCollectionForMarketing')}</span> + <div className="settings-page__content-description"> + <span>{t('dataCollectionForMarketingDescription')}</span> + </div> + </div> + + <div + className="settings-page__content-item-col" + data-testid="dataCollectionForMarketing" + > + <ToggleButton + value={dataCollectionForMarketing} + onToggle={(value) => { + setDataCollectionForMarketing(!value); + if (participateInMetaMetrics) { + this.context.trackEvent({ + category: MetaMetricsEventCategory.Settings, + event: MetaMetricsEventName.AnalyticsPreferenceSelected, + properties: { + is_metrics_opted_in: true, + has_marketing_consent: false, + location: 'Settings', + }, + }); + } else { + setParticipateInMetaMetrics(true); + } + }} + offLabel={t('off')} + onLabel={t('on')} + /> + </div> + </Box> + ); + } + renderChooseYourNetworkButton() { const { t } = this.context; @@ -998,12 +1072,60 @@ export default class SecurityTab extends PureComponent { ); } + renderDataCollectionWarning = () => { + const { t } = this.context; + + return ( + <Popover + wrapTitle + centerTitle + onClose={() => this.setState({ showDataCollectionDisclaimer: false })} + title={ + <Icon + size={IconSize.Xl} + name={IconName.Danger} + color={IconColor.warningDefault} + /> + } + footer={ + <Button + width={BlockSize.Full} + type="primary" + onClick={() => + this.setState({ showDataCollectionDisclaimer: false }) + } + > + {t('dataCollectionWarningPopoverButton')} + </Button> + } + > + <Box + display={Display.Flex} + flexDirection={FlexDirection.Column} + gap={2} + margin={4} + > + <Text>{t('dataCollectionWarningPopoverDescription')}</Text> + </Box> + </Popover> + ); + }; + render() { - const { warning, petnamesEnabled } = this.props; + const { + warning, + petnamesEnabled, + dataCollectionForMarketing, + setDataCollectionForMarketing, + } = this.props; + const { showDataCollectionDisclaimer } = this.state; return ( <div className="settings-page__body"> {this.renderUseExternalServices()} + {showDataCollectionDisclaimer + ? this.renderDataCollectionWarning() + : null} {warning && <div className="settings-tab__error">{warning}</div>} <span className="settings-page__security-tab-sub-header__bold"> @@ -1085,7 +1207,11 @@ export default class SecurityTab extends PureComponent { {this.context.t('metrics')} </span> <div className="settings-page__content-padded"> - <MetametricsToggle /> + <MetametricsToggle + dataCollectionForMarketing={dataCollectionForMarketing} + setDataCollectionForMarketing={setDataCollectionForMarketing} + /> + {this.renderDataCollectionForMarketing()} </div> </div> ); diff --git a/ui/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js index f411e1ceb1f2..98a2c7c9c3f5 100644 --- a/ui/pages/settings/security-tab/security-tab.container.js +++ b/ui/pages/settings/security-tab/security-tab.container.js @@ -6,6 +6,7 @@ import { setIpfsGateway, setIsIpfsGatewayEnabled, setParticipateInMetaMetrics, + setDataCollectionForMarketing, setUseCurrencyRateCheck, setUseMultiAccountBalanceChecker, setUsePhishDetect, @@ -43,6 +44,7 @@ const mapStateToProps = (state) => { const { incomingTransactionsPreferences, participateInMetaMetrics, + dataCollectionForMarketing, usePhishDetect, useTokenDetection, ipfsGateway, @@ -64,6 +66,7 @@ const mapStateToProps = (state) => { incomingTransactionsPreferences, allNetworks, participateInMetaMetrics, + dataCollectionForMarketing, usePhishDetect, useTokenDetection, ipfsGateway, @@ -90,6 +93,8 @@ const mapDispatchToProps = (dispatch) => { dispatch(setIncomingTransactionsPreferences(chainId, value)), setParticipateInMetaMetrics: (val) => dispatch(setParticipateInMetaMetrics(val)), + setDataCollectionForMarketing: (val) => + dispatch(setDataCollectionForMarketing(val)), setUsePhishDetect: (val) => dispatch(setUsePhishDetect(val)), setUseCurrencyRateCheck: (val) => dispatch(setUseCurrencyRateCheck(val)), setUseTokenDetection: (val) => dispatch(setUseTokenDetection(val)), diff --git a/ui/selectors/metametrics.js b/ui/selectors/metametrics.js index 377181a3e6a8..c623e378c003 100644 --- a/ui/selectors/metametrics.js +++ b/ui/selectors/metametrics.js @@ -2,6 +2,12 @@ import { createSelector } from 'reselect'; export const selectFragments = (state) => state.metamask.fragments; +export const getDataCollectionForMarketing = (state) => + state.metamask.dataCollectionForMarketing; + +export const getParticipateInMetaMetrics = (state) => + Boolean(state.metamask.participateInMetaMetrics); + export const selectFragmentBySuccessEvent = createSelector( selectFragments, (_, fragmentOptions) => fragmentOptions, diff --git a/ui/store/actionConstants.ts b/ui/store/actionConstants.ts index 539b9df3d985..57ab34e800a0 100644 --- a/ui/store/actionConstants.ts +++ b/ui/store/actionConstants.ts @@ -80,6 +80,8 @@ export const DEPRECATED_NETWORK_POPOVER_CLOSE = export const UPDATE_CUSTOM_NONCE = 'UPDATE_CUSTOM_NONCE'; export const SET_PARTICIPATE_IN_METAMETRICS = 'SET_PARTICIPATE_IN_METAMETRICS'; +export const SET_DATA_COLLECTION_FOR_MARKETING = + 'SET_DATA_COLLECTION_FOR_MARKETING'; // locale export const SET_CURRENT_LOCALE = 'SET_CURRENT_LOCALE'; diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 2aca2441e3e9..41d83f0be8d0 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -3258,6 +3258,26 @@ export function setParticipateInMetaMetrics( }; } +export function setDataCollectionForMarketing( + dataCollectionPreference: boolean, +): ThunkAction< + Promise<[boolean, string]>, + MetaMaskReduxState, + unknown, + AnyAction +> { + return async (dispatch: MetaMaskReduxDispatch) => { + log.debug(`background.setDataCollectionForMarketing`); + await submitRequestToBackground('setDataCollectionForMarketing', [ + dataCollectionPreference, + ]); + dispatch({ + type: actionConstants.SET_DATA_COLLECTION_FOR_MARKETING, + value: dataCollectionPreference, + }); + }; +} + export function setUseBlockie( val: boolean, ): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> { From a3cbcef95ce1cad638ea2af6cbdba43f6a6d7b1a Mon Sep 17 00:00:00 2001 From: Hassan Malik <41640681+hmalik88@users.noreply.github.com> Date: Wed, 12 Jun 2024 10:38:35 -0400 Subject: [PATCH 15/61] feat: Integrate SIP-12 update (#23697) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR brings the domain resolution integration up to specification. There's a lot going on in this PR so here's a quick breakdown of what's going on: - The `DomainInputResolutionCell` component is responsible for displaying a single resolution, it can properly display both ENS and snap provided resolutions. It also has logic to detect overflowing titles so that it can replace the title component with one that has an ellipsis and a tooltip showing the entire title. - The confusable component was modified to include an option to wrap the points in a text component instead of span and I added a prop to be able to assign a classname to the tooltip wrapper, I did this to allow for my use case of having a tooltip within a tooltip (an overflowing domain name with confusables). - The update to the `AddressListItem` component snapshot is because of the update to the confusable component. - ~~I had to update implementation of the `AddRecipient` components because the update in the name resolution api would break the existing implementation. Those components will be removed at some point by the extension team.~~ (These components have since been removed) - The `AddContact` component was updated to use the domain input resolution cell component. - The `AddressListItem` component was updated to accommodate overflowing titles (specifically when viewing all contacts). - The `ViewContact` & `EditContact` components were also updated to accommodate overflowing titles. - After the add/remove from address book actions, the old state would momentarily hang, so now I’m forcing the update for a cleaner UX where the old state won’t hang at all. **Previous `AddContact` screen**: https://github.com/MetaMask/metamask-extension/assets/41640681/ccaebf23-76c9-4ae8-99ee-f338d9da669d **New screens**: https://github.com/MetaMask/metamask-extension/assets/41640681/957def02-5859-4299-8c21-b561ea8f3c2f Note: The `AddContact` screen was re-done to accommodate for snap provided resolutions and to update the designs as it seemed the screen was largely undesigned. See previous design video. --------- Co-authored-by: Frederik Bolding <frederik.bolding@gmail.com> --- app/_locales/en/messages.json | 4 + test/e2e/snaps/test-snap-namelookup.spec.js | 4 +- test/e2e/tests/settings/address-book.spec.js | 9 +- test/e2e/tests/transaction/ens.spec.js | 6 +- .../badge-wrapper/badge-wrapper.tsx | 14 +- .../address-list-item.test.tsx.snap | 22 +- .../address-list-item/address-list-item.tsx | 3 + .../domain-input-resolution-cell.stories.tsx | 69 +++++ .../domain-input-resolution-cell.tsx | 244 ++++++++++++++++++ .../multichain/pages/send/components/index.ts | 1 + .../pages/send/components/recipient.tsx | 135 +++++----- .../multichain/pages/send/index.scss | 40 ++- .../ui/confusable/confusable.component.js | 17 +- ui/ducks/domains.js | 97 ++++--- ui/ducks/send/send.js | 8 +- ui/ducks/send/send.test.js | 28 +- .../add-recipient/domain-input.component.js | 2 +- .../add-contact/add-contact.component.js | 87 ++++--- .../add-contact/add-contact.container.js | 4 +- .../edit-contact/edit-contact.component.js | 34 ++- ui/pages/settings/contact-list-tab/index.scss | 32 ++- .../view-contact/view-contact.component.js | 3 + ui/store/actions.test.js | 1 + ui/store/actions.ts | 4 +- 24 files changed, 665 insertions(+), 203 deletions(-) create mode 100644 ui/components/multichain/pages/send/components/domain-input-resolution-cell.stories.tsx create mode 100644 ui/components/multichain/pages/send/components/domain-input-resolution-cell.tsx diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 05f3a7cd53b4..25ad96fce540 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -5190,6 +5190,10 @@ "submitted": { "message": "Submitted" }, + "suggestedBySnap": { + "message": "Suggested by $1", + "description": "$1 is the snap name" + }, "suggestedTokenSymbol": { "message": "Suggested ticker symbol:" }, diff --git a/test/e2e/snaps/test-snap-namelookup.spec.js b/test/e2e/snaps/test-snap-namelookup.spec.js index 5448271bd72e..4e58231256dd 100644 --- a/test/e2e/snaps/test-snap-namelookup.spec.js +++ b/test/e2e/snaps/test-snap-namelookup.spec.js @@ -80,8 +80,8 @@ describe('Test Snap Name Lookup', function () { // verify name output from snap await driver.waitForSelector({ - text: '0xc0ffe...54979', - tag: 'div', + text: '0xc0ff...4979', + tag: 'p', }); }, ); diff --git a/test/e2e/tests/settings/address-book.spec.js b/test/e2e/tests/settings/address-book.spec.js index fdf20fcc9e2c..c784ce3daa3b 100644 --- a/test/e2e/tests/settings/address-book.spec.js +++ b/test/e2e/tests/settings/address-book.spec.js @@ -1,4 +1,5 @@ const { strict: assert } = require('assert'); +const { By } = require('selenium-webdriver'); const { defaultGanacheOptions, withFixtures, @@ -166,12 +167,12 @@ describe('Address Book', function () { await driver.clickElement({ text: '0x2f318...5C970', tag: 'div' }); await driver.clickElement({ text: 'Edit', tag: 'button' }); - await driver.clickElement({ text: 'Delete contact', tag: 'a' }); - - const contact = await driver.findElement('.address-list-item__label'); + await driver.clickElement('.settings-page__address-book-button'); // it checks if account is deleted - const exists = await driver.isElementPresent(contact); + const exists = await driver.isElementPresent( + By.css('.address-list-item__label'), + ); assert.equal(exists, false, 'Contact is not deleted'); }, ); diff --git a/test/e2e/tests/transaction/ens.spec.js b/test/e2e/tests/transaction/ens.spec.js index 5ef8444cd0aa..9497fe3ef60c 100644 --- a/test/e2e/tests/transaction/ens.spec.js +++ b/test/e2e/tests/transaction/ens.spec.js @@ -86,16 +86,16 @@ describe('ENS', function () { await openActionMenuAndStartSendFlow(driver); await driver.pasteIntoField( - 'input[placeholder="Enter public address (0x) or ENS name"]', + '.ens-input__wrapper__input', sampleEnsDomain, ); await driver.waitForSelector({ text: sampleEnsDomain, - css: '[data-testid="address-list-item-label"]', + css: '[data-testid="multichain-send-page__recipient__item__title"]', }); - await driver.clickElement('.address-list-item'); + await driver.clickElement('.multichain-send-page__recipient__item'); await driver.findElement({ css: '.ens-input__selected-input__title', diff --git a/ui/components/component-library/badge-wrapper/badge-wrapper.tsx b/ui/components/component-library/badge-wrapper/badge-wrapper.tsx index 6723856e3cf8..8ccd69d7cf9a 100644 --- a/ui/components/component-library/badge-wrapper/badge-wrapper.tsx +++ b/ui/components/component-library/badge-wrapper/badge-wrapper.tsx @@ -35,12 +35,16 @@ export const BadgeWrapper: BadgeWrapperComponent = React.forwardRef( {/* Generally the AvatarAccount or AvatarToken */} {children} <Box - className={classnames('mm-badge-wrapper__badge-container', { - [`mm-badge-wrapper__badge-container--${anchorElementShape}-${position}`]: - !positionObj, - })} - style={{ ...positionObj }} {...badgeContainerProps} + className={classnames( + 'mm-badge-wrapper__badge-container', + { + [`mm-badge-wrapper__badge-container--${anchorElementShape}-${position}`]: + !positionObj, + }, + badgeContainerProps?.className || '', + )} + style={{ ...positionObj }} > {/* Generally the AvatarNetwork at SIZES.XS */} {badge} diff --git a/ui/components/multichain/address-list-item/__snapshots__/address-list-item.test.tsx.snap b/ui/components/multichain/address-list-item/__snapshots__/address-list-item.test.tsx.snap index b6b4e25deaef..8d840ba595ce 100644 --- a/ui/components/multichain/address-list-item/__snapshots__/address-list-item.test.tsx.snap +++ b/ui/components/multichain/address-list-item/__snapshots__/address-list-item.test.tsx.snap @@ -53,13 +53,14 @@ exports[`AddressListItem renders the address and label 1`] = ` style="overflow: hidden;" > <p - class="mm-box mm-text address-list-item__label mm-text--body-md-medium mm-text--text-align-left mm-box--padding-0 mm-box--width-full mm-box--color-text-default" + class="mm-box mm-text address-list-item__label mm-text--body-md-medium mm-text--ellipsis mm-text--text-align-left mm-box--padding-0 mm-box--width-full mm-box--color-text-default" data-testid="address-list-item-label" + style="overflow: hidden;" > metamask.eth </p> <div - class="mm-box mm-text mm-text--body-sm mm-text--ellipsis mm-box--color-text-alternative" + class="mm-box mm-text mm-text--body-sm mm-text--ellipsis mm-box--display-flex mm-box--color-text-alternative" data-testid="address-list-item-address" > <div> @@ -133,10 +134,13 @@ exports[`AddressListItem uses a confusable when it should 1`] = ` style="overflow: hidden;" > <p - class="mm-box mm-text address-list-item__label mm-text--body-md-medium mm-text--text-align-left mm-box--padding-0 mm-box--width-full mm-box--color-text-default" + class="mm-box mm-text address-list-item__label mm-text--body-md-medium mm-text--ellipsis mm-text--text-align-left mm-box--padding-0 mm-box--width-full mm-box--color-text-default" data-testid="address-list-item-label" + style="overflow: hidden;" > - <span> + <span + class="" + > <div aria-describedby="tippy-tooltip-2" class="" @@ -146,7 +150,7 @@ exports[`AddressListItem uses a confusable when it should 1`] = ` tabindex="0" > <span - class="confusable__point" + class="mm-box mm-text confusable__point mm-text--body-md mm-box--color-text-default" > m </span> @@ -155,7 +159,9 @@ exports[`AddressListItem uses a confusable when it should 1`] = ` e t a - <span> + <span + class="" + > <div aria-describedby="tippy-tooltip-3" class="" @@ -165,7 +171,7 @@ exports[`AddressListItem uses a confusable when it should 1`] = ` tabindex="0" > <span - class="confusable__point" + class="mm-box mm-text confusable__point mm-text--body-md mm-box--color-text-default" > m </span> @@ -180,7 +186,7 @@ exports[`AddressListItem uses a confusable when it should 1`] = ` h </p> <div - class="mm-box mm-text mm-text--body-sm mm-text--ellipsis mm-box--color-text-alternative" + class="mm-box mm-text mm-text--body-sm mm-text--ellipsis mm-box--display-flex mm-box--color-text-alternative" data-testid="address-list-item-address" > <div> diff --git a/ui/components/multichain/address-list-item/address-list-item.tsx b/ui/components/multichain/address-list-item/address-list-item.tsx index c3327fdbe897..52c5040bcb02 100644 --- a/ui/components/multichain/address-list-item/address-list-item.tsx +++ b/ui/components/multichain/address-list-item/address-list-item.tsx @@ -82,6 +82,8 @@ export const AddressListItem = ({ textAlign={TextAlign.Left} className="address-list-item__label" data-testid="address-list-item-label" + style={{ overflow: 'hidden' }} + ellipsis > {displayName} </Text> @@ -91,6 +93,7 @@ export const AddressListItem = ({ ellipsis data-testid="address-list-item-address" as="div" + display={Display.Flex} > <Tooltip title={address} position="bottom"> {shortenAddress(address)} diff --git a/ui/components/multichain/pages/send/components/domain-input-resolution-cell.stories.tsx b/ui/components/multichain/pages/send/components/domain-input-resolution-cell.stories.tsx new file mode 100644 index 000000000000..5fb788bfa1b3 --- /dev/null +++ b/ui/components/multichain/pages/send/components/domain-input-resolution-cell.stories.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import { DomainInputResolutionCell } from '.'; + + +export default { + title: 'Components/Multichain/DomainInputResolutionCell', + component: DomainInputResolutionCell, + argTypes: { + domainType: { + control: 'text', + }, + address: { + control: 'text', + }, + protocol: { + control: 'text', + }, + domainName: { + control: 'text', + }, + resolvingSnap: { + control: 'text', + }, + onClick: { + action: 'onClick', + }, + }, + args: { + domainType: 'ENS', + address: '0xc0ffee254729296a45a3885639AC7E10F9d54979', + protocol: 'Ethereum Name Service', + domainName: 'hamer.eth', + resolvingSnap: '', + onClick: () => undefined, + }, +}; + +export const DefaultStory = (args) => <DomainInputResolutionCell {...args} />; + +DefaultStory.storyName = 'ENS Resolution'; + +export const LensStory = (args) => <DomainInputResolutionCell {...args} />; +LensStory.args = { + domainType: 'Other', + address: '0xc0ffee254729296a45a3885639AC7E10F9d54979', + protocol: 'Lens Protocol', + domainName: 'm0nt0y4.lens', + resolvingSnap: 'Lens Resolver Snap', + onClick: () => undefined, +}; + +LensStory.storyName = 'Lens Resolution'; + +export const OverflowingTitleStory = (args) => ( + <div style={{ width: '308px', padding: '16px', border: '1px solid black', }}> + <DomainInputResolutionCell {...args} /> + </div> +); + +OverflowingTitleStory.args = { + domainType: 'Other', + address: '0xc0ffee254729296a45a3885639AC7E10F9d54979', + protocol: 'Test Protocol', + domainName: 'superduperlongnamethatisoverflowingthiscontainer.testprotocol', + resolvingSnap: 'Test Resolver Snap', + onClick: () => undefined, +} + +OverflowingTitleStory.storyName = 'Overflowing Domain Resolution'; diff --git a/ui/components/multichain/pages/send/components/domain-input-resolution-cell.tsx b/ui/components/multichain/pages/send/components/domain-input-resolution-cell.tsx new file mode 100644 index 000000000000..b320a4850cd8 --- /dev/null +++ b/ui/components/multichain/pages/send/components/domain-input-resolution-cell.tsx @@ -0,0 +1,244 @@ +import React, { + ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + useContext, + ///: END:ONLY_INCLUDE_IF + useRef, + useEffect, + useState, +} from 'react'; +import PropTypes from 'prop-types'; +///: BEGIN:ONLY_INCLUDE_IF(build-flask) +import { I18nContext } from '../../../../../contexts/i18n'; +///: END:ONLY_INCLUDE_IF +import Confusable from '../../../../ui/confusable'; +import { + AvatarAccount, + Box, + ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + AvatarIcon, + AvatarIconSize, + BadgeWrapper, + IconName, + ///: END:ONLY_INCLUDE_IF + Text, +} from '../../../../component-library'; +import { + AlignItems, + Display, + ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + BackgroundColor, + BorderColor, + IconColor, + ///: END:ONLY_INCLUDE_IF + TextColor, + TextVariant, +} from '../../../../../helpers/constants/design-system'; +import { ellipsify } from '../../../../../pages/confirmations/send/send.utils'; +import Tooltip from '../../../../ui/tooltip'; + +type DomainInputResolutionCellArgs = { + domainType: string; + address: string; + protocol?: string; + domainName: string; + resolvingSnap?: string; + onClick: () => void; +}; + +export const DomainInputResolutionCell = ({ + domainType, + address, + domainName, + ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + resolvingSnap = '', + ///: END:ONLY_INCLUDE_IF + onClick, + protocol, +}: DomainInputResolutionCellArgs) => { + ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + const t: (key: string, params: unknown[]) => string = useContext(I18nContext); + ///: END:ONLY_INCLUDE_IF + const titleRef = useRef<null | HTMLDivElement>(null); + const breakpointRef = useRef<null | number>(null); + const [isTitleOverflowing, setIsTitleOverflowing] = useState(false); + + useEffect(() => { + if (!titleRef.current) { + return; + } + + let isOverflowing = + titleRef.current.offsetWidth < titleRef.current.scrollWidth; + const breakpointLength = titleRef.current.textContent?.length; + + if (isOverflowing && !breakpointRef.current && breakpointLength) { + breakpointRef.current = breakpointLength; + } + + if (!isOverflowing) { + if (breakpointRef.current) { + if (domainName.length >= breakpointRef.current) { + isOverflowing = true; + } else { + isOverflowing = false; + breakpointRef.current = null; + } + } + } + + if (isOverflowing !== isTitleOverflowing) { + setIsTitleOverflowing(isOverflowing); + } + }, [domainName, isTitleOverflowing]); + + const OverflowingTitle = () => ( + <Tooltip + containerClassName="multichain-send-page__recipient__item__title-tooltip" + wrapperClassName="multichain-send-page__recipient__item__title-tooltip-container" + position="bottom" + title={domainName} + > + <Confusable + asText + input={domainName} + confusableWrapperName="multichain-send-page__recipient__item__title-confusable-wrapper" + /> + </Tooltip> + ); + + ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + if (domainType === 'Other') { + // Snap provided resolution. + return ( + <Box + key={address} + className="multichain-send-page__recipient__item" + onClick={() => onClick()} + display={Display.Flex} + alignItems={AlignItems.center} + paddingBottom={2} + style={{ cursor: 'pointer' }} + > + <Tooltip title={t('suggestedBySnap', [resolvingSnap])}> + <BadgeWrapper + badge={ + <AvatarIcon + iconName={IconName.Snaps} + size={AvatarIconSize.Xs} + className="multichain-send-page__recipient__item__avatar" + backgroundColor={BackgroundColor.infoDefault} + borderColor={BorderColor.backgroundDefault} + borderWidth={2} + iconProps={{ + color: IconColor.infoInverse, + style: { width: '12px', height: '12px' }, + name: IconName.Snaps, + }} + /> + } + positionObj={{ + bottom: '25%', + right: '10%', + }} + badgeContainerProps={{ + className: 'multichain-send-page__recipient__item__badge', + }} + > + <AvatarAccount address={address} /> + </BadgeWrapper> + </Tooltip> + <Box + className="multichain-send-page__recipient__item__content" + paddingLeft={4} + style={{ overflow: 'hidden' }} + > + <Box + ref={titleRef} + className="multichain-send-page__recipient__item__title" + data-testid="multichain-send-page__recipient__item__title" + display={Display.Flex} + > + {isTitleOverflowing ? ( + <OverflowingTitle /> + ) : ( + <Confusable asText input={domainName} /> + )} + </Box> + <Text color={TextColor.textAlternative}>{ellipsify(address)}</Text> + <Box className="multichain-send-page__recipient__item__subtitle"> + <Text + color={TextColor.textAlternative} + variant={TextVariant.bodySm} + > + {protocol} + </Text> + </Box> + </Box> + </Box> + ); + } + ///: END:ONLY_INCLUDE_IF + const getTitle = () => { + if (domainName && isTitleOverflowing) { + return <OverflowingTitle />; + } else if (domainName && !isTitleOverflowing) { + return <Confusable asText input={domainName} />; + } + return ellipsify(address); + }; + + return ( + <Box + key={address} + className="multichain-send-page__recipient__item" + onClick={() => onClick()} + display={Display.Flex} + alignItems={AlignItems.center} + paddingBottom={2} + style={{ cursor: 'pointer' }} + > + <Box + className="multichain-send-page__recipient__item__avatar-wrapper" + display={Display.Flex} + alignItems={AlignItems.center} + > + <AvatarAccount address={address} /> + </Box> + <Box + className="multichain-send-page__recipient__item__content" + paddingLeft={4} + style={{ overflow: 'hidden' }} + > + <Box + ref={titleRef} + className="multichain-send-page__recipient__item__title" + data-testid="multichain-send-page__recipient__item__title" + display={Display.Flex} + > + {getTitle()} + </Box> + {domainName && ( + <Box className="multichain-send-page__recipient__item__subtitle"> + <Text color={TextColor.textAlternative}>{ellipsify(address)}</Text> + </Box> + )} + {domainType === 'ENS' && ( + <Text color={TextColor.textAlternative} variant={TextVariant.bodySm}> + {protocol} + </Text> + )} + </Box> + </Box> + ); +}; + +DomainInputResolutionCell.propTypes = { + domainType: PropTypes.string.isRequired, + address: PropTypes.string.isRequired, + domainName: PropTypes.string.isRequired, + ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + resolvingSnap: PropTypes.string.isRequired, + ///: END:ONLY_INCLUDE_IF + onClick: PropTypes.func, + protocol: PropTypes.string, +}; diff --git a/ui/components/multichain/pages/send/components/index.ts b/ui/components/multichain/pages/send/components/index.ts index ef45cf4fbcdc..5db00149a2e3 100644 --- a/ui/components/multichain/pages/send/components/index.ts +++ b/ui/components/multichain/pages/send/components/index.ts @@ -8,3 +8,4 @@ export { SendPageRecipient } from './recipient'; export { SendPageRecipientContent } from './recipient-content'; export { SendHexData } from './hex'; export { QuoteCard } from './quote-card'; +export { DomainInputResolutionCell } from './domain-input-resolution-cell'; diff --git a/ui/components/multichain/pages/send/components/recipient.tsx b/ui/components/multichain/pages/send/components/recipient.tsx index 3433d51c2bc9..971f7ec41a72 100644 --- a/ui/components/multichain/pages/send/components/recipient.tsx +++ b/ui/components/multichain/pages/send/components/recipient.tsx @@ -10,7 +10,8 @@ import { } from '../../../../../ducks/send'; import { getDomainError, - getDomainResolution, + getDomainResolutions, + getDomainType, getDomainWarning, } from '../../../../../ducks/domains'; import { @@ -18,59 +19,18 @@ import { BannerAlertSeverity, Box, } from '../../../../component-library'; -import { getAddressBookEntry } from '../../../../../selectors'; import { Tab, Tabs } from '../../../../ui/tabs'; -import { AddressListItem } from '../../../address-list-item'; import { MetaMetricsEventCategory, MetaMetricsEventName, } from '../../../../../../shared/constants/metametrics'; -import { - MetaMetricsContext, - type UITrackEventMethod, -} from '../../../../../contexts/metametrics'; +import { MetaMetricsContext } from '../../../../../contexts/metametrics'; +import { DomainInputResolutionCell } from './domain-input-resolution-cell'; import { SendPageAddressBook, SendPageRow, SendPageYourAccounts } from '.'; const CONTACTS_TAB_KEY = 'contacts'; const ACCOUNTS_TAB_KEY = 'accounts'; -const ENS_RESOLUTION_TYPE = 'ENS resolution'; - -const renderExplicitAddress = ( - address: string, - nickname: string, - type: string, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - dispatch: any, - trackEvent: UITrackEventMethod, -) => { - return ( - <AddressListItem - address={address} - label={nickname} - useConfusable={type === ENS_RESOLUTION_TYPE} - onClick={() => { - dispatch( - addHistoryEntry( - `sendFlow - User clicked recipient from ${type}. address: ${address}, nickname ${nickname}`, - ), - ); - trackEvent({ - event: MetaMetricsEventName.sendRecipientSelected, - category: MetaMetricsEventCategory.Send, - properties: { - location: 'send page recipient screen', - inputType: type, - }, - }); - dispatch(updateRecipient({ address, nickname })); - dispatch(updateRecipientUserInput(address)); - }} - /> - ); -}; - export const SendPageRecipient = () => { const t = useContext(I18nContext); const dispatch = useDispatch(); @@ -79,44 +39,83 @@ export const SendPageRecipient = () => { const recipient = useSelector(getRecipient); const userInput = useSelector(getRecipientUserInput) || ''; - const domainResolution = useSelector(getDomainResolution); + const domainResolutions = useSelector(getDomainResolutions) || []; const domainError = useSelector(getDomainError); const domainWarning = useSelector(getDomainWarning); - - let addressBookEntryName = ''; - const entry = useSelector((state) => - getAddressBookEntry(state, domainResolution), - ); - if (domainResolution && entry?.name) { - addressBookEntryName = entry.name; - } + const domainType = useSelector(getDomainType); const showErrorBanner = domainError || (recipient.error && recipient.error !== 'required'); const showWarningBanner = !showErrorBanner && (domainWarning || recipient.warning); + type DomainResolution = { + resolvedAddress: string; + resolvingSnap?: string; + protocol: string; + addressBookEntryName?: string; + }; + + const onClick = ( + address: string, + nickname: string, + type: string = 'user input', + ) => { + dispatch( + addHistoryEntry( + `sendFlow - User clicked recipient from ${type}. address: ${address}, nickname ${nickname}`, + ), + ); + trackEvent({ + event: MetaMetricsEventName.sendRecipientSelected, + category: MetaMetricsEventCategory.Send, + properties: { + location: 'send page recipient screen', + inputType: type, + }, + }); + dispatch(updateRecipient({ address, nickname })); + dispatch(updateRecipientUserInput(address)); + }; + let contents; if (recipient.address) { - contents = renderExplicitAddress( - recipient.address, - recipient.nickname, - 'validated user input', - dispatch, - trackEvent, - ); - } else if (domainResolution && !recipient.error) { - contents = renderExplicitAddress( - domainResolution, - addressBookEntryName || userInput, - ENS_RESOLUTION_TYPE, - dispatch, - trackEvent, + contents = ( + <DomainInputResolutionCell + domainType={domainType} + address={recipient.address} + domainName={recipient.nickname} + onClick={() => onClick(recipient.address, recipient.nickname)} + /> ); + } else if (domainResolutions?.length > 0 && !recipient.error) { + contents = domainResolutions.map((domainResolution: DomainResolution) => { + const { resolvedAddress, resolvingSnap, addressBookEntryName, protocol } = + domainResolution; + return ( + <DomainInputResolutionCell + key={`${resolvedAddress}${resolvingSnap}${protocol}`} + domainType={domainType} + address={resolvedAddress} + domainName={addressBookEntryName ?? userInput} + onClick={() => + onClick( + resolvedAddress, + addressBookEntryName ?? userInput, + 'Domain resolution', + ) + } + protocol={protocol} + resolvingSnap={resolvingSnap} + /> + ); + }); } else { contents = ( <Tabs - defaultActiveTabKey={userInput ? CONTACTS_TAB_KEY : ACCOUNTS_TAB_KEY} + defaultActiveTabKey={ + userInput.length > 0 ? CONTACTS_TAB_KEY : ACCOUNTS_TAB_KEY + } > { // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/ui/components/multichain/pages/send/index.scss b/ui/components/multichain/pages/send/index.scss index 33326dbe931f..e5bc53e100a6 100644 --- a/ui/components/multichain/pages/send/index.scss +++ b/ui/components/multichain/pages/send/index.scss @@ -1,7 +1,7 @@ @use "design-system"; .multichain-send-page { - width: 408px; + width: 100%; &__account-picker { height: 62px; @@ -20,6 +20,8 @@ } &__recipient { + width: 100%; + .tabs__list { font-size: design-system.$font-size-h6; border-bottom: 0; @@ -30,5 +32,41 @@ width: 50%; } } + + &__item { + &__title-tooltip > * { + display: inline; + } + + &__title-tooltip { + white-space: nowrap; + } + + &__title-tooltip-container { + overflow: hidden; + text-overflow: ellipsis; + } + + &__title-confusable-wrapper { + display: inline-block; + } + + &__avatar { + width: 20px; + height: 20px; + max-width: 20px; + border-radius: 10px; + } + + &__badge { + transform: scale(1) translate(25%, 70%); + width: '20px'; + height: '20px'; + } + } + } + + &__recipient:last-child { + padding-bottom: 0; } } diff --git a/ui/components/ui/confusable/confusable.component.js b/ui/components/ui/confusable/confusable.component.js index 6e1ac6b406ff..452ec86cb57a 100644 --- a/ui/components/ui/confusable/confusable.component.js +++ b/ui/components/ui/confusable/confusable.component.js @@ -1,23 +1,25 @@ import React, { useMemo } from 'react'; import PropTypes from 'prop-types'; import { confusables } from 'unicode-confusables'; +import { v4 as uuidv4 } from 'uuid'; import Tooltip from '../tooltip'; import { useI18nContext } from '../../../hooks/useI18nContext'; +import { Text } from '../../component-library'; -const Confusable = ({ input }) => { +const Confusable = ({ input, asText, confusableWrapperName = '' }) => { const t = useI18nContext(); const confusableData = useMemo(() => { return confusables(input); }, [input]); - return confusableData.map(({ point, similarTo }, index) => { + return confusableData.map(({ point, similarTo }) => { const zeroWidth = similarTo === ''; if (similarTo === undefined) { - return point; + return asText ? <Text key={uuidv4()}>{point}</Text> : point; } return ( <Tooltip - key={index.toString()} + key={uuidv4()} tag="span" position="top" title={ @@ -25,8 +27,11 @@ const Confusable = ({ input }) => { ? t('confusableZeroWidthUnicode') : t('confusableUnicode', [point, similarTo]) } + wrapperClassName={confusableWrapperName} > - <span className="confusable__point">{zeroWidth ? '?' : point}</span> + <Text className="confusable__point" as={asText ? 'p' : 'span'}> + {zeroWidth ? '?' : point} + </Text> </Tooltip> ); }); @@ -34,6 +39,8 @@ const Confusable = ({ input }) => { Confusable.propTypes = { input: PropTypes.string.isRequired, + asText: PropTypes.bool, + confusableWrapperName: PropTypes.string, }; export default Confusable; diff --git a/ui/ducks/domains.js b/ui/ducks/domains.js index 6dd8ff63ba41..3a52365c019c 100644 --- a/ui/ducks/domains.js +++ b/ui/ducks/domains.js @@ -5,8 +5,12 @@ import { isConfusing } from 'unicode-confusables'; import { isHexString } from 'ethereumjs-util'; import { Web3Provider } from '@ethersproject/providers'; -import { getChainIdsCaveat } from '@metamask/snaps-rpc-methods'; import { + getChainIdsCaveat, + getLookupMatchersCaveat, +} from '@metamask/snaps-rpc-methods'; +import { + getAddressBookEntry, getCurrentChainId, getNameLookupSnapsIds, getPermissionSubjects, @@ -41,14 +45,12 @@ const ENS = 'ENS'; const initialState = { stage: 'UNINITIALIZED', - resolution: null, + resolutions: null, error: null, warning: null, chainId: null, domainType: null, domainName: null, - // TODO: This should be resolvingSnaps in the future when we allow for conflict resolution - resolvingSnap: null, }; export const domainInitialState = initialState; @@ -66,18 +68,18 @@ const slice = createSlice({ }, lookupEnd: (state, action) => { // first clear out the previous state - state.resolution = null; + state.resolutions = null; state.error = null; state.warning = null; state.domainType = null; state.domainName = null; - ///: BEGIN:ONLY_INCLUDE_IF(build-flask) - state.resolvingSnap = null; - ///: END:ONLY_INCLUDE_IF - const { address, error, chainId, domainType, domainName, resolvingSnap } = + const { resolutions, error, chainId, domainType, domainName } = action.payload; state.domainType = domainType; if (state.domainType === ENS) { + // currently ENS resolutions will only ever have one element since we do not do fuzzy matching for ENS. + // error handling logic will need to be updated to accommodate multiple results in the future when the ENS snap is built. + const address = resolutions[0]?.resolvedAddress; if (error) { if ( isValidDomainName(domainName) && @@ -99,7 +101,7 @@ const slice = createSlice({ } else if (address === ZERO_X_ERROR_ADDRESS) { state.error = ENS_REGISTRATION_ERROR; } else { - state.resolution = address; + state.resolutions = resolutions; } if (isValidDomainName(address) && isConfusing(address)) { state.warning = CONFUSING_ENS_ERROR; @@ -107,9 +109,8 @@ const slice = createSlice({ } else { state.error = ENS_NO_ADDRESS_FOR_NAME; } - } else if (address) { - state.resolution = address; - state.resolvingSnap = resolvingSnap; + } else if (resolutions.length > 0) { + state.resolutions = resolutions; } else if (domainName.length > 0) { state.error = NO_RESOLUTION_FOR_DOMAIN; } @@ -117,7 +118,7 @@ const slice = createSlice({ enableDomainLookup: (state, action) => { state.stage = 'INITIALIZED'; state.error = null; - state.resolution = null; + state.resolutions = null; state.warning = null; state.chainId = action.payload; }, @@ -125,22 +126,19 @@ const slice = createSlice({ state.stage = 'NO_NETWORK_SUPPORT'; state.error = null; state.warning = null; - state.resolution = null; + state.resolutions = null; state.chainId = null; }, domainNotSupported: (state) => { - state.resolution = null; + state.resolutions = null; state.warning = null; state.error = DOMAIN_NOT_SUPPORTED_ON_NETWORK; }, resetDomainResolution: (state) => { - state.resolution = null; + state.resolutions = null; state.warning = null; state.error = null; state.domainType = null; - ///: BEGIN:ONLY_INCLUDE_IF(build-flask) - state.resolvingSnap = null; - ///: END:ONLY_INCLUDE_IF }, }, extraReducers: (builder) => { @@ -194,7 +192,21 @@ export async function fetchResolutions({ domain, chainId, state }) { const filteredNameLookupSnapsIds = nameLookupSnaps.filter((snapId) => { const permission = subjects[snapId]?.permissions[NAME_LOOKUP_PERMISSION]; const chainIdCaveat = getChainIdsCaveat(permission); - return chainIdCaveat?.includes(chainId) ?? true; + const lookupMatchersCaveat = getLookupMatchersCaveat(permission); + + if (chainIdCaveat && !chainIdCaveat.includes(chainId)) { + return false; + } + + if (lookupMatchersCaveat) { + const { tlds, schemes } = lookupMatchersCaveat; + return ( + tlds?.some((tld) => domain.endsWith(`.${tld}`)) || + schemes?.some((scheme) => domain.startsWith(`${scheme}:`)) + ); + } + + return true; }); // previous logic would switch request args based on the domain property to determine @@ -230,7 +242,14 @@ export async function fetchResolutions({ domain, chainId, state }) { const resolutions = result.value.resolvedAddresses.map( (resolution) => ({ ...resolution, - snapId: filteredNameLookupSnapsIds[idx], + resolvingSnap: getSnapMetadata( + state, + filteredNameLookupSnapsIds[idx], + )?.name, + addressBookEntryName: getAddressBookEntry( + state, + resolution.resolvedAddress, + )?.name, }), ); return successfulResolutions.concat(resolutions); @@ -263,10 +282,11 @@ export function lookupDomainName(domainName) { } else { await dispatch(lookupStart(trimmedDomainName)); log.info(`Resolvers attempting to resolve name: ${trimmedDomainName}`); - let address; + let resolutions = []; let fetchedResolutions; let hasSnapResolution = false; let error; + let address; try { address = await web3Provider?.resolveName(trimmedDomainName); } catch (err) { @@ -274,24 +294,26 @@ export function lookupDomainName(domainName) { } const chainId = getCurrentChainId(state); const chainIdInt = parseInt(chainId, 16); - if (!address) { - // TODO: allow for conflict resolution in future iterations, we don't have designs - // for this currently, so just displaying the first result. + if (address) { + resolutions = [ + { + resolvedAddress: address, + protocol: 'Ethereum Name Service', + addressBookEntryName: getAddressBookEntry(state, address)?.name, + }, + ]; + } else { fetchedResolutions = await fetchResolutions({ domain: trimmedDomainName, chainId: `eip155:${chainIdInt}`, state, }); - const resolvedAddress = fetchedResolutions[0]?.resolvedAddress; - hasSnapResolution = Boolean(resolvedAddress); + hasSnapResolution = fetchedResolutions.length > 0; if (hasSnapResolution) { - address = resolvedAddress; + resolutions = fetchedResolutions; } } - const snapId = fetchedResolutions?.[0]?.snapId; - const snapName = getSnapMetadata(state, snapId)?.name; - // Due to the asynchronous nature of looking up domains, we could reach this point // while a new lookup has started, if so we don't use the found result. state = getState(); @@ -301,7 +323,7 @@ export function lookupDomainName(domainName) { await dispatch( lookupEnd({ - address, + resolutions, error, chainId, network: chainIdInt, @@ -310,19 +332,14 @@ export function lookupDomainName(domainName) { ? 'Other' : ENS, domainName: trimmedDomainName, - ...(hasSnapResolution ? { resolvingSnap: snapName } : {}), }), ); } }; } -export function getDomainResolution(state) { - return state[name].resolution; -} - -export function getResolvingSnap(state) { - return state[name].resolvingSnap; +export function getDomainResolutions(state) { + return state[name].resolutions; } export function getDomainError(state) { diff --git a/ui/ducks/send/send.js b/ui/ducks/send/send.js index 9c45334a9625..88d21467a8fd 100644 --- a/ui/ducks/send/send.js +++ b/ui/ducks/send/send.js @@ -2796,11 +2796,11 @@ export function resetRecipientInput() { const state = getState(); const chainId = getCurrentChainId(state); showLoadingIndication(); - await dispatch(addHistoryEntry(`sendFlow - user cleared recipient input`)); - await dispatch(updateRecipientUserInput('')); + dispatch(addHistoryEntry(`sendFlow - user cleared recipient input`)); + dispatch(resetDomainResolution()); + dispatch(updateRecipientUserInput('')); await dispatch(updateRecipient({ address: '', nickname: '' })); - await dispatch(resetDomainResolution()); - await dispatch(validateRecipientUserInput({ chainId })); + dispatch(validateRecipientUserInput({ chainId })); hideLoadingIndication(); }; } diff --git a/ui/ducks/send/send.test.js b/ui/ducks/send/send.test.js index 62d43eba56e6..9f07d4550e79 100644 --- a/ui/ducks/send/send.test.js +++ b/ui/ducks/send/send.test.js @@ -2676,35 +2676,29 @@ describe('Send Slice', () => { type: 'send/addHistoryEntry', payload: 'sendFlow - user cleared recipient input', }); - expect(actionResult[1].type).toStrictEqual( - 'send/updateRecipientWarning', - ); + expect(actionResult[1].type).toStrictEqual('DNS/resetDomainResolution'); expect(actionResult[2].type).toStrictEqual( - 'send/updateDraftTransactionStatus', + 'send/updateRecipientWarning', ); expect(actionResult[3].type).toStrictEqual( - 'send/updateRecipientUserInput', - ); - expect(actionResult[4].payload).toStrictEqual( - 'sendFlow - user typed into recipient input field', + 'send/updateDraftTransactionStatus', ); - expect(actionResult[5].type).toStrictEqual( + expect(actionResult[4].payload).toStrictEqual(''); + expect(actionResult[5].type).toStrictEqual('send/updateRecipient'); + expect(actionResult[6].type).toStrictEqual('send/addHistoryEntry'); + expect(actionResult[7].type).toStrictEqual( 'send/validateRecipientUserInput', ); - expect(actionResult[6].type).toStrictEqual('send/updateRecipient'); - expect(actionResult[7].type).toStrictEqual( + expect(actionResult[8].type).toStrictEqual( 'send/computeEstimatedGasLimit/pending', ); - expect(actionResult[8].type).toStrictEqual('GET_LAYER_1_GAS_FEE'); - expect(actionResult[9].type).toStrictEqual( - 'metamask/gas/SET_CUSTOM_GAS_LIMIT', - ); + expect(actionResult[9].type).toStrictEqual('GET_LAYER_1_GAS_FEE'); expect(actionResult[10].type).toStrictEqual( - 'send/computeEstimatedGasLimit/fulfilled', + 'metamask/gas/SET_CUSTOM_GAS_LIMIT', ); expect(actionResult[11].type).toStrictEqual( - 'DNS/resetDomainResolution', + 'send/computeEstimatedGasLimit/fulfilled', ); expect(actionResult[12].type).toStrictEqual( 'send/validateRecipientUserInput', diff --git a/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js b/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js index 419deb0cc7df..bb6e432f1a5d 100644 --- a/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js +++ b/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js @@ -179,7 +179,7 @@ export default class DomainInput extends Component { <ButtonIcon className="ens-input__wrapper__action-icon-button" onClick={() => { - if (userInput) { + if (userInput.length > 0) { this.props.onReset(); } else { this.props.scanQrCode(); diff --git a/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js b/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js index 9dc571c175f5..78c3054df933 100644 --- a/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js +++ b/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js @@ -1,10 +1,9 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { debounce } from 'lodash'; -import Identicon from '../../../../components/ui/identicon'; import TextField from '../../../../components/ui/text-field'; import { CONTACT_LIST_ROUTE } from '../../../../helpers/constants/routes'; -import { isValidDomainName } from '../../../../helpers/utils/util'; +import { IS_FLASK, isValidDomainName } from '../../../../helpers/utils/util'; import DomainInput from '../../../confirmations/send/send-content/add-recipient/domain-input'; import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer'; import { @@ -12,6 +11,7 @@ import { isValidHexAddress, } from '../../../../../shared/modules/hexstring-utils'; import { INVALID_RECIPIENT_ADDRESS_ERROR } from '../../../confirmations/send/send.constants'; +import { DomainInputResolutionCell } from '../../../../components/multichain/pages/send/components/domain-input-resolution-cell'; export default class AddContact extends PureComponent { static contextTypes = { @@ -25,14 +25,14 @@ export default class AddContact extends PureComponent { qrCodeData: PropTypes.object /* eslint-disable-line react/no-unused-prop-types */, qrCodeDetected: PropTypes.func, - domainResolution: PropTypes.string, + domainResolutions: PropTypes.arrayOf(PropTypes.object), domainError: PropTypes.string, resetDomainResolution: PropTypes.func, }; state = { newName: '', - ethAddress: '', + selectedAddress: '', error: '', input: '', }; @@ -45,11 +45,14 @@ export default class AddContact extends PureComponent { UNSAFE_componentWillReceiveProps(nextProps) { if (nextProps.qrCodeData) { if (nextProps.qrCodeData.type === 'address') { - const { domainResolution } = this.props; + const { domainResolutions } = this.props; const scannedAddress = nextProps.qrCodeData.values.address.toLowerCase(); - const currentAddress = domainResolution || this.state.ethAddress; - if (currentAddress.toLowerCase() !== scannedAddress) { + const addresses = [ + ...domainResolutions.map(({ resolvedAddress }) => resolvedAddress), + this.state.ethAddress, + ].map((address) => address.toLowerCase()); + if (!addresses.some((address) => address === scannedAddress)) { this.setState({ input: scannedAddress }); this.validate(scannedAddress); // Clean up QR code data after handling @@ -59,15 +62,13 @@ export default class AddContact extends PureComponent { } } - validate = (address) => { + validate = (input) => { const valid = - !isBurnAddress(address) && - isValidHexAddress(address, { mixedCaseUseChecksum: true }); - const validEnsAddress = isValidDomainName(address); + !isBurnAddress(input) && + isValidHexAddress(input, { mixedCaseUseChecksum: true }); + const validEnsAddress = isValidDomainName(input); - if (valid || validEnsAddress || address === '') { - this.setState({ error: '', ethAddress: address }); - } else { + if (!IS_FLASK && !validEnsAddress && !valid) { this.setState({ error: INVALID_RECIPIENT_ADDRESS_ERROR }); } }; @@ -84,36 +85,28 @@ export default class AddContact extends PureComponent { this.props.scanQrCode(); }} onChange={this.onChange} - onPaste={(text) => { - this.setState({ input: text }); - this.validate(text); + onPaste={(input) => { + this.setState({ input }); + this.validate(input); }} onReset={() => { this.props.resetDomainResolution(); - this.setState({ ethAddress: '', input: '' }); + this.setState({ input: '', selectedAddress: '' }); }} - userInput={this.state.input} + userInput={this.state.selectedAddress || this.state.input} /> ); } render() { const { t } = this.context; - const { history, addToAddressBook, domainError, domainResolution } = + const { history, addToAddressBook, domainError, domainResolutions } = this.props; const errorToRender = domainError || this.state.error; return ( <div className="settings-page__content-row address-book__add-contact"> - {domainResolution && ( - <div className="address-book__view-contact__group"> - <Identicon address={domainResolution} diameter={60} /> - <div className="address-book__view-contact__group__value"> - {domainResolution} - </div> - </div> - )} <div className="address-book__add-contact__content"> <div className="address-book__view-contact__group address-book__add-contact__content__username"> <div className="address-book__view-contact__group__label"> @@ -134,6 +127,40 @@ export default class AddContact extends PureComponent { {t('ethereumPublicAddress')} </div> {this.renderInput()} + <div + className={`address-book__view-contact__group__${ + domainResolutions?.length === 1 ? 'single-' : '' + }resolution-list`} + > + {domainResolutions?.map((resolution) => { + const { + resolvedAddress, + resolvingSnap, + addressBookEntryName, + protocol, + } = resolution; + const domainName = addressBookEntryName || this.state.input; + return ( + <DomainInputResolutionCell + key={`${resolvedAddress}${resolvingSnap}${protocol}`} + domainType={ + protocol === 'Ethereum Name Service' ? 'ENS' : 'Other' + } + address={resolvedAddress} + domainName={domainName} + onClick={() => { + this.setState({ + selectedAddress: resolvedAddress, + newName: this.state.newName || domainName, + }); + this.props.resetDomainResolution(); + }} + protocol={protocol} + resolvingSnap={resolvingSnap} + /> + ); + })} + </div> {errorToRender && ( <div className="address-book__add-contact__error"> {t(errorToRender)} @@ -145,12 +172,12 @@ export default class AddContact extends PureComponent { cancelText={this.context.t('cancel')} disabled={Boolean( this.state.error || - !this.state.ethAddress || + !this.state.selectedAddress || !this.state.newName.trim(), )} onSubmit={async () => { await addToAddressBook( - domainResolution || this.state.ethAddress, + this.state.selectedAddress, this.state.newName, ); history.push(CONTACT_LIST_ROUTE); diff --git a/ui/pages/settings/contact-list-tab/add-contact/add-contact.container.js b/ui/pages/settings/contact-list-tab/add-contact/add-contact.container.js index d13749d9a370..3b18ebdde8e0 100644 --- a/ui/pages/settings/contact-list-tab/add-contact/add-contact.container.js +++ b/ui/pages/settings/contact-list-tab/add-contact/add-contact.container.js @@ -9,7 +9,7 @@ import { import { getQrCodeData } from '../../../../ducks/app/app'; import { getDomainError, - getDomainResolution, + getDomainResolutions, resetDomainResolution, } from '../../../../ducks/domains'; import AddContact from './add-contact.component'; @@ -18,7 +18,7 @@ const mapStateToProps = (state) => { return { qrCodeData: getQrCodeData(state), domainError: getDomainError(state), - domainResolution: getDomainResolution(state), + domainResolutions: getDomainResolutions(state), }; }; diff --git a/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js index a53753ff34da..335c5166da05 100644 --- a/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js +++ b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js @@ -17,6 +17,7 @@ import { import { AlignItems, + BlockSize, Display, TextVariant, } from '../../../../helpers/constants/design-system'; @@ -74,27 +75,38 @@ export default class EditContact extends PureComponent { className="settings-page__header address-book__header--edit" paddingLeft={6} paddingRight={6} + width={BlockSize.Full} + alignItems={AlignItems.center} > - <Box display={Display.Flex} alignItems={AlignItems.center}> + <Box + display={Display.Flex} + alignItems={AlignItems.center} + style={{ overflow: 'hidden' }} + paddingRight={2} + > <AvatarAccount size={AvatarAccountSize.Lg} address={address} /> <Text className="address-book__header__name" variant={TextVariant.bodyLgMedium} marginInlineStart={4} + style={{ overflow: 'hidden' }} + ellipsis > {name || address} </Text> </Box> - <Button - type="link" - className="settings-page__address-book-button" - onClick={async () => { - await removeFromAddressBook(chainId, address); - history.push(listRoute); - }} - > - {t('deleteContact')} - </Button> + <Box className="settings-page__address-book-button"> + <Button + type="link" + onClick={async () => { + await removeFromAddressBook(chainId, address); + history.push(listRoute); + }} + style={{ display: 'contents' }} + > + {t('deleteContact')} + </Button> + </Box> </Box> <div className="address-book__edit-contact__content"> <div className="address-book__view-contact__group"> diff --git a/ui/pages/settings/contact-list-tab/index.scss b/ui/pages/settings/contact-list-tab/index.scss index e563c3255db4..8f4ed5795c0d 100644 --- a/ui/pages/settings/contact-list-tab/index.scss +++ b/ui/pages/settings/contact-list-tab/index.scss @@ -159,6 +159,35 @@ max-width: 100%; width: 100%; } + + &__resolution-list, + &__single-resolution-list { + background: var(--color-background-default); + box-sizing: border-box; + box-shadow: var(--shadow-size-sm) var(--color-shadow-default); + border-radius: 6px; + position: absolute; + width: 309px; + z-index: 10; + top: 338px; + max-height: 96px; + overflow-y: auto; + } + + &__resolution-list > *, + &__single-resolution-list > * { + padding: 8px; + } + + &__resolution-list > * { + padding-bottom: 0; + } + + &__resolution-list { + .multichain-send-page__recipient__item:last-child { + padding-bottom: 8px; + } + } } } @@ -179,8 +208,9 @@ &__add-contact { display: flex; - flex-flow: column nowrap; + flex-flow: column nowrap !important; padding-bottom: 0 !important; + width: 100%; height: 100%; padding-top: 0; diff --git a/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js b/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js index 40c3e410f7b0..be3280af3c9e 100644 --- a/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js +++ b/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js @@ -51,12 +51,15 @@ function ViewContact({ <Box className="settings-page__header address-book__header" paddingLeft={6} + paddingRight={6} > <AvatarAccount size={AvatarAccountSize.Lg} address={address} /> <Text className="address-book__header__name" variant={TextVariant.bodyLgMedium} marginInlineStart={4} + style={{ overflow: 'hidden' }} + ellipsis > {name || address} </Text> diff --git a/ui/store/actions.test.js b/ui/store/actions.test.js index 81b542937c8c..d153d1888018 100644 --- a/ui/store/actions.test.js +++ b/ui/store/actions.test.js @@ -1399,6 +1399,7 @@ describe('Actions', () => { background.getApi.returns({ setAddressBook: setAddressBookStub, + getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)), }); setBackgroundConnection(background.getApi()); diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 41d83f0be8d0..4025ec0a4bb1 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -2564,6 +2564,7 @@ export function addToAddressBook( chainId, memo, ]); + await forceUpdateMetamaskState(dispatch); } catch (error) { logErrorWithMessage(error); dispatch(displayWarning('Address book failed to update')); @@ -2586,11 +2587,12 @@ export function removeFromAddressBook( ): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> { log.debug(`background.removeFromAddressBook`); - return async () => { + return async (dispatch) => { await submitRequestToBackground('removeFromAddressBook', [ chainId, toChecksumHexAddress(addressToRemove), ]); + await forceUpdateMetamaskState(dispatch); }; } From 8fabd544b4d3e6d7cd2cb822510ab22dda8fb87c Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:06:21 -0400 Subject: [PATCH 16/61] chore: add Non-EVM feature flag (#25241) This PR adds a feature flag to be used during the development of the non-EVM initiative. To use the flag during development just change the value of the flag to `true` and access it using `process.env.BTC_BETA_SUPPORT`. --- builds.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builds.yml b/builds.yml index 577f851c4d2f..7f6dff152578 100644 --- a/builds.yml +++ b/builds.yml @@ -29,6 +29,7 @@ buildTypes: - REQUIRE_SNAPS_ALLOWLIST: true - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.3.0/index.html - ACCOUNT_SNAPS_DIRECTORY_URL: https://snaps.metamask.io/account-management + - BTC_BETA_SUPPORT: false # Main build uses the default browser manifest manifestOverrides: false # Build name used in multiple user-readable places @@ -70,6 +71,7 @@ buildTypes: - SEGMENT_WRITE_KEY_REF: SEGMENT_FLASK_WRITE_KEY - ACCOUNT_SNAPS_DIRECTORY_URL: https://metamask.github.io/snaps-directory-staging/main/account-management - EIP_4337_ENTRYPOINT: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789' + - BTC_BETA_SUPPORT: false isPrerelease: true manifestOverrides: ./app/build-types/flask/manifest/ buildNameOverride: MetaMask Flask From 9c87c1b0d6fc3276d728b87a4ea17503b02ef75a Mon Sep 17 00:00:00 2001 From: seaona <54408225+seaona@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:30:29 +0200 Subject: [PATCH 17/61] fix: flaky test `Change assets changes to native currency when switching accounts during a NFT send` (#25220) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** The problem with this flaky test is that we start a send flow (type 0x0 tx), and we are switching assets (from NFT to ETH) and proceeding to the next screen, if we click Continue before the gasLimit is updated the test will fail: once we land into the last confirmation screen, the gas limit is never updated there, so the test fails as the total value doesn't match with the expected one. This is a race condition that happens on the wallet level, but this PR intends to fix the flakiness on the test level to not wait for the fix on the wallet side. See bug [here](https://github.com/MetaMask/metamask-extension/issues/25243). To fix this, we could either add a delay, or in this case, we add some extra validation (making sure the hex data is cleared) and update the transaction values, to trigger again a gas update. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25220?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/metamask-extension/issues/25181 ## **Manual testing steps** 1. Check ci 2. Run test multiple times locally `FIREFOX_SNAP=true yarn test:e2e:single test/e2e/tests/transaction/change-assets.spec.js --browser=firefox --leave-running --retryUntilFailure --retries=10` ## **Screenshots/Recordings** https://github.com/MetaMask/metamask-extension/assets/54408225/113ea17f-020f-46d9-8516-66240f7bd1e2 ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../tests/transaction/change-assets.spec.js | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/test/e2e/tests/transaction/change-assets.spec.js b/test/e2e/tests/transaction/change-assets.spec.js index 5dcf4b357298..8b20c38fe065 100644 --- a/test/e2e/tests/transaction/change-assets.spec.js +++ b/test/e2e/tests/transaction/change-assets.spec.js @@ -1,3 +1,4 @@ +const { strict: assert } = require('assert'); const { defaultGanacheOptions, withFixtures, @@ -178,9 +179,6 @@ describe('Change assets', function () { async ({ driver, ganacheServer }) => { await logInWithBalanceValidation(driver, ganacheServer); - // Wait for balance to load - await driver.delay(500); - // Choose the nft await driver.clickElement('[data-testid="account-overview__nfts-tab"]'); await driver.clickElement('[data-testid="nft-default-image"]'); @@ -253,7 +251,14 @@ describe('Change assets', function () { await withFixtures( { dapp: true, - fixtures: new FixtureBuilder().withNftControllerERC721().build(), + fixtures: new FixtureBuilder() + .withNftControllerERC721() + .withPreferencesController({ + featureFlags: { + sendHexData: true, + }, + }) + .build(), ganacheOptions: defaultGanacheOptions, smartContract, title: this.test.fullTitle(), @@ -261,9 +266,6 @@ describe('Change assets', function () { async ({ driver, ganacheServer }) => { await logInWithBalanceValidation(driver, ganacheServer); - // Wait for balance to load - await driver.delay(500); - // Create second account await driver.clickElement('[data-testid="account-menu-icon"]'); await driver.clickElement( @@ -326,6 +328,25 @@ describe('Change assets', function () { // Populate an amount, continue await driver.clickElement('[data-testid="currency-input"]'); await driver.press('[data-testid="currency-input"]', '2'); + + // Make sure hex data is cleared after switching assets + const hexDataLocator = await driver.findElement( + '[data-testid="send-hex-textarea"]', + ); + const hexDataValue = await hexDataLocator.getProperty('value'); + assert.equal( + hexDataValue, + '', + 'Hex data has not been cleared after switching assets.', + ); + + // Make sure gas is updated by resetting amount and hex data + // Note: this is needed until the race condition is fixed on the wallet level (issue #25243) + await driver.fill('[data-testid="currency-input"]', '2'); + await hexDataLocator.fill('0x'); + await hexDataLocator.fill(''); + + // Go to the last confirmation screen await driver.clickElement({ text: 'Continue', css: 'button' }); // Validate the send amount From 5988cc5456ef12bf7ac0efe9bd3e3069efa7cfb1 Mon Sep 17 00:00:00 2001 From: seaona <54408225+seaona@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:31:57 +0200 Subject: [PATCH 18/61] test: add missing mocks for aggregator metadata, block list and include blocked tokens in all tests (#25206) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** The responses for the API Calls to aggregator metadata, block list and blocked tokens are not currently mocked on any tests, however the requests happen in the majority of tests. These request return a json back that takes in some occasions more than 1 second to return. With this PR we mock these responses, so they are immediate, mitigating any possible delay and flakiness due to real live requests. Note: We are returning the data, since it's been seen that if we return just an empty json, some tests fail as they rely on some data from that requests [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25206?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/MetaMask-planning/issues/2637 ## **Manual testing steps** 1. All tests should continue to pass in ci 2. Check screenshots with the real API requests and slow responses ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** See slow responses for the 3 API requests happening in tests: - blocklist: 1.20s ![Screenshot from 2024-06-11 12-04-47](https://github.com/MetaMask/metamask-extension/assets/54408225/bcd75c3d-b91e-4ebe-a3f1-b6a1f6811805) - aggregator metadata: 644ms ![Screenshot from 2024-06-11 11-24-24](https://github.com/MetaMask/metamask-extension/assets/54408225/0b899c47-0e87-4bc7-ad64-d670b0495d16) - includeBlockedTokens: 664ms ![Screenshot from 2024-06-11 12-04-56](https://github.com/MetaMask/metamask-extension/assets/54408225/a1ebb86a-7a87-416f-ac96-f6b2ae4c8914) ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- test/e2e/mock-e2e.js | 39 +- .../aggregator-metadata.json | 44 ++ .../mock-response-data/token-blocklist.json | 582 ++++++++++++++++++ 3 files changed, 660 insertions(+), 5 deletions(-) create mode 100644 test/e2e/mock-response-data/aggregator-metadata.json create mode 100644 test/e2e/mock-response-data/token-blocklist.json diff --git a/test/e2e/mock-e2e.js b/test/e2e/mock-e2e.js index fa1d89ab38ec..aa4572d842e3 100644 --- a/test/e2e/mock-e2e.js +++ b/test/e2e/mock-e2e.js @@ -1,6 +1,10 @@ const fs = require('fs'); -const { GAS_API_BASE_URL } = require('../../shared/constants/swaps'); +const { + GAS_API_BASE_URL, + SWAPS_API_V2_BASE_URL, + TOKEN_API_BASE_URL, +} = require('../../shared/constants/swaps'); const CDN_CONFIG_PATH = 'test/e2e/mock-cdn/cdn-config.txt'; const CDN_STALE_DIFF_PATH = 'test/e2e/mock-cdn/cdn-stale-diff.txt'; @@ -15,6 +19,10 @@ const CDN_STALE_DIFF_RES_HEADERS_PATH = const CDN_STALE_RES_HEADERS_PATH = 'test/e2e/mock-cdn/cdn-stale-res-headers.json'; +const AGGREGATOR_METADATA_PATH = + 'test/e2e/mock-response-data/aggregator-metadata.json'; +const TOKEN_BLOCKLIST_PATH = 'test/e2e/mock-response-data/token-blocklist.json'; + const blacklistedHosts = [ 'arbitrum-mainnet.infura.io', 'goerli.infura.io', @@ -239,7 +247,7 @@ async function setupMocking( .thenCallback(suggestedGasFeesCallbackMock); await server - .forGet('https://swap.api.cx.metamask.io/networks/1/token') + .forGet(`${SWAPS_API_V2_BASE_URL}/networks/1/token`) .withQuery({ address: '0x72c9Fb7ED19D3ce51cea5C56B3e023cd918baaDf' }) .thenCallback(() => { return { @@ -256,7 +264,7 @@ async function setupMocking( }); await server - .forGet('https://swap.api.cx.metamask.io/featureFlags') + .forGet(`${SWAPS_API_V2_BASE_URL}/featureFlags`) .thenCallback(() => { return { statusCode: 200, @@ -354,8 +362,29 @@ async function setupMocking( }; }); + const TOKEN_BLOCKLIST = fs.readFileSync(TOKEN_BLOCKLIST_PATH); + await server + .forGet(`${TOKEN_API_BASE_URL}/blocklist`) + .withQuery({ chainId: '1', region: 'global' }) + .thenCallback(() => { + return { + statusCode: 200, + json: JSON.parse(TOKEN_BLOCKLIST), + }; + }); + + const AGGREGATOR_METADATA = fs.readFileSync(AGGREGATOR_METADATA_PATH); + await server + .forGet(`${SWAPS_API_V2_BASE_URL}/networks/1/aggregatorMetadata`) + .thenCallback(() => { + return { + statusCode: 200, + json: JSON.parse(AGGREGATOR_METADATA), + }; + }); + await server - .forGet('https://swap.api.cx.metamask.io/networks/1/tokens') + .forGet(`${SWAPS_API_V2_BASE_URL}/networks/1/tokens`) .thenCallback(() => { return { statusCode: 200, @@ -439,7 +468,7 @@ async function setupMocking( }); await server - .forGet('https://swap.api.cx.metamask.io/networks/1/topAssets') + .forGet(`${SWAPS_API_V2_BASE_URL}/networks/1/topAssets`) .thenCallback(() => { return { statusCode: 200, diff --git a/test/e2e/mock-response-data/aggregator-metadata.json b/test/e2e/mock-response-data/aggregator-metadata.json new file mode 100644 index 000000000000..67511003e8ab --- /dev/null +++ b/test/e2e/mock-response-data/aggregator-metadata.json @@ -0,0 +1,44 @@ +{ + "airswapLight": { + "color": "#2B71FF", + "title": "AirSwap", + "icon": "data:image/svg+xml,%3csvg width='75' height='31' viewBox='0 0 75 31' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M31.4038 12.231H30.1152V19.3099H31.4038V12.231Z' fill='%23FDFDFD'/%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M42.8265 15.1959C44.1549 15.5074 44.9217 15.9477 45.1053 16.8178C45.1368 16.9625 45.1513 17.1103 45.1485 17.2582C45.1485 18.5793 44.2197 19.4171 42.7077 19.4171C41.5541 19.4075 40.4409 18.9929 39.5649 18.2463L40.3317 17.3548C41.0229 17.9456 41.8437 18.3215 42.7401 18.3215C43.6365 18.3215 43.8849 17.9241 43.8849 17.3763C43.8849 16.8285 43.5933 16.5922 42.2541 16.2915C40.7205 15.937 39.8349 15.4322 39.8349 14.1218C39.8349 12.8114 40.7529 12.1239 42.1785 12.1239C43.1717 12.1129 44.1403 12.4303 44.9325 13.0262L44.2521 13.9607C43.6041 13.488 42.8697 13.1658 42.2109 13.1658C41.5521 13.1658 41.0985 13.5418 41.0985 14.0144C41.0985 14.487 41.4549 14.8736 42.8265 15.1959Z' fill='%23FDFDFD'/%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M54.8897 12.231L53.1626 17.4487L51.3925 12.231H50.3305L48.5605 17.4487L46.8333 12.231H45.4709L47.9812 19.3099H49.0754L50.8454 14.2643L52.6155 19.3099H53.699L56.2092 12.231H54.8897Z' fill='%23FDFDFD'/%3e %3cpath d='M66.2502 13.3606H64.4545V15.8457H66.2502C67.2129 15.8457 67.8078 15.48 67.8078 14.5655C67.8078 13.651 67.202 13.3606 66.2502 13.3606ZM66.2069 16.9538H64.4545V19.3099H63.189V12.231H66.3583C68.0349 12.231 69.095 13.0809 69.095 14.5117C69.095 16.1039 67.916 16.9538 66.2069 16.9538Z' fill='%23FDFDFD'/%3e %3cpath d='M36.1129 13.3606H34.2841V15.835H36.1237C37.0273 15.835 37.6082 15.3078 37.6082 14.587C37.6082 13.8662 37.0488 13.3606 36.1129 13.3606ZM37.4253 19.3099L35.8547 16.9323H34.2841V19.3099H33.0146V12.231H36.2205C37.8664 12.231 38.8884 13.21 38.8884 14.587C38.8884 15.7489 38.1784 16.4482 37.1672 16.7279L38.9207 19.3099H37.4253Z' fill='%23FDFDFD'/%3e %3cpath d='M25.3908 13.7048L26.4171 16.3944C25.6372 16.3931 24.8666 16.562 24.1593 16.8893L25.3908 13.7048ZM21.7395 19.3099H23.0682C23.0682 19.3099 24.0297 17.2766 26.8492 17.5025L27.6054 19.3099H28.9341L25.9958 12.231H24.7535L21.7395 19.3099Z' fill='%23FDFDFD'/%3e %3cpath d='M60.0214 16.8893C59.315 16.5627 58.5456 16.3938 57.767 16.3944L58.7917 13.7048L60.0214 16.8893ZM59.4281 12.231H58.1877L55.2429 19.3099H56.5697L57.3355 17.5025C60.14 17.2766 61.1 19.3099 61.1 19.3099H62.4376L59.4281 12.231Z' fill='%23FDFDFD'/%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M16.021 18.988L12.332 22.6348L10.5039 20.8275C12.4754 20.7086 14.3794 20.0738 16.021 18.988Z' fill='%23FDFDFD'/%3e %3cpath d='M19.4724 15.2831L19.0194 14.8302L12.3431 8.15515L5.66685 14.8302L5.09521 15.4017L5.30014 15.585C5.53742 15.7791 5.77471 15.9624 6.02278 16.135C7.83476 17.4034 9.98616 18.0982 12.198 18.1289C14.4098 18.1597 16.5797 17.5251 18.4262 16.3075C18.6851 16.135 18.9439 15.9409 19.192 15.7468C19.4401 15.5527 19.4616 15.5203 19.5911 15.4017L19.4724 15.2831ZM14.1012 16.9545C12.1094 15.732 9.81597 15.0897 7.47883 15.0997C10.5312 13.7734 14.263 13.5901 17.6928 15.5634C16.597 16.2552 15.3771 16.7277 14.1012 16.9545Z' fill='%23FDFDFD'/%3e %3c/svg%3e", + "iconPng": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnEAAAECCAYAAACR04HKAAAACXBIWXMAAFxGAABcRgEUlENBAAAgAElEQVR42u3dCdi35Zw38NappJQWKUxF6Ukar33PDMYYM5axJ96QSKWiNCQjS3sSRcZSslQkM3plKSQabWSrUGhmpEUrSblb3vN3ODuO29PzPPd5Xtt/+3yO4zruJ+77Ws5r+X//53Uuyy0HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw4e68884Vb7/99k/ddtttOysNAIDJCXCfTsudKcTdIcgBAExQgLtrEeQAACYswAlyAAATGuAEOQCACQ1wghwAwIQGOEEOAGBCA5wgBwAwoQFOkAMAmNAAJ8gBAExogBPkAAAmNMAJcgAAExrgBDkAgAkNcIIcAMCEBjhBDgBgQgOcIAcAMKEBTpADAJjQACfIAQBMaIAT5AAAJjTACXIAABMa4AQ5AIAJDXCCHADAhAY4QQ4AYEIDnCAHAAhwExrgBDkAQICb8EWQAwAEOEEOAECAG0GQ28VZBgCmMcB9ZhoDnCAHAAhwghwAgAAnyAEACHCCHAAgwAlyAAACnCA3edfJGmlZu2BZfYz2eZ3CZY2G679XYZl0skzANbJ8WrZO99BO6X76YFq+kv59Tlp+mpYr03JDWq5Ly7Vp+UVazkq/c2JaDkn/fnn624fE86jDfakp35VHUF73mOD9umtZpeW2VqjY1kojvLZXGfJeH8V5R4AT5Kb3Olktlck1heX3i3gwj8E+36PivJ/SZBvpWC8bwfV5c4Si9O/T0nJY+vdL07FuOOKyflzalw+lfbmqg+O7Kc5H+vn6tN5N2oS4uBYrtrv30OWWtvlfBfv15hHs13dLyy15ZMttvaTiHL11VNd42vauI7jXw+VpOS/99wnp5z5zc3P/mMr8nj6VEOAEuZoH2Gtqyi89aJ4pxA1+vZ4fH/jpuNcfqozTeX5KSRBpeWzfiesvaj1r9y/9/bsrtnP+wNfn/eO8FezX9wber/uV7Ffet0s6eLacWXGOLh9VDdUoQtwyymEuLWdEjXe8SfAJJcBZBLmFHmA/rCy/U8bgGp+ZELfYdXtr+vmxdPx/3WPZrpm28amBj+v36eehNbWO6Xe3qNlG8sAB76k9K/ZrswH3a4+Kc/L2ltfRlqWBcd4XxBfMeohb7Bz8Mf08OpXlpj6pBDiLILek62WbBuV2e5tXYUJcZ2HuHakc/qrjct00rfvnIzyuW9LP95fWQKTf/37Fugd7dZlfkZXu1z4D7tdZFeFy8zbbilfwDc7/GULcUu+LA+K5J+UIcBZBbv6D9qSGZXeAEDcW1+8PugrUUVOV1vebMTmu6BzxhoU6QtTUeKXfPXega3PTmhqo9Ls/Gmi/NoovYIX7dE7Lba2R1nFjk3MfnWeEuKWelwtT+Wwl7QhwFkHurof6nxqW2W/T368qxI3F9Rvn4jEdfOhePIbHdlbatwctY783vO3PyaQ0IPT+WirtzlsaBJctB9iv3SrK/Q0tt7VLi/P+70LcsjsHzc3NPUPqEeAsMx7k0nHv37LMthPixub6vSGVyaNaXAtHj/OHVjq2hy1j379Rsa49BwgEFzQ4zncMsF/fLu01mcp7g5bb+nGbHtpDN+ifpBB31+vVFOSeJv0IcJYZDXIxLlLbISOi56IQN1bX75XR+7BBWW5d2wB9se1ek9umnZZ71V0QobLDYzt9WcPapG3tULGvZ/d8XW7esAx/2vN+bVD6KjXG/2uzrRQu/raDa3nPIZ8nkxbi5n1xWyQFCXCWGQxy6Ri376K8kkcIcWN1/X67dhy/GKOqwXYuTctey2r8nofZeGH6/Q+nn79ueDxXL9RjNYYnyb34iu7vPnv2pvXv2+Jeeug4hJT0u69oWcP/uQ6u48u6Ghh6WkNcLqfvGzhYgLPMYJCr6T03bu1Xxi3E5THcXthi2T4P/fCetPy/mPWg5fW7U0U53jv3fKsZw+pttR8cESzn5uaeGkOX5J61Rfdh+ptnFQaHkyuO4Y093lc/aXHu3t3jfp1ZWDZ/bDJm37zzfN+m7WyXMNzIs8cxxMVA1S3u9ZemZce07J7WdXBavhBfiFre729cDgHOMjtBLl0/j++wnP4QQWDGa+K+2PGxLZ/P0adLA88Saq9WLzzGl1es90/pg/W5HRzfhml9B8W1s8A2D694hff8iuP4bk/X5BYt76VLe3yVWtr544SWtXDv6PA5/LVxDHF91OTGWIExBE6T3uG5Y9MayyHAWWYjyKVjO77jctpdiOvtOB9cM03SvHOyR+G18NFRNb6PWpvoULGktlr5NdEqFetaNf3N9RWvVB/Qw331zg6aJzy8h4Cyc0Xt1z+3OJ8rNX1tvozyGGQ4jVGHuMWea++sbaOafv910pEAZ5mBIJdfd5S+zvpWaaPsqD0S4nq97z9aed3+pPAYzy1c3419DTQac7PG+FeL9UbdokGI+tgov3ikdV7UwTPnoB7264zCMrmuzeDRuf1j0bUZ4wAWlseRsxTi5u3PdtF0YVw67CDACXLjUwu3X2nbp6itiPkMC7/BP23g+2FmQty8+/9zlbUYWxcc4zWF6zu+5+NbJdqExSvbaCPYZB25zV3x+HMd7//fdPSs+e8uvxCldd2n4lXq0QOFxRiv7v2l07G1aaM3qSEuP6sPrvmMSvu1nqQkwFmmOMjFt+x0DFfUBJ+oGSj8/ZOFuN6POToh/LarV6oRFio+4A8Y6Bg3afG3K5S+zuv6lWrbMRcXCwmP6Wq/opNLxXaf1KLsF5W8Aoy3ABE2oifuUAMPT2qIi2dczevpUc07y8IncuUuumz3GG5+E1P/pOWb6b8/n1/7HJL++61p2XsJyz7p/z8wz6t3XPxNvLbLQxbcMgFBbqdJvZbSvr+s4oHw3Hz9bV74cL5tqIfbrIa4vE97Vhz3SQuU4aoV6zp8Eq7xtJ+HVdzPu3V4Xi7p8FlzWIfl8Y2KGsAVWmznqNprMnp1F+7bJW32bVJDXC7X943TgNFMaICLGzw+COPbZgysmT7gnx4f7n1MuxTV/9G4N23jOWlb/5p76P2gSS89Qe5uD6qzKwaNXXne35VOmv1OIa73496otNFzjJpfUMNfPODuhDwzH14zpl5H23xE4fZK5y39ny5eqaZ1rF9R03pgi+3cs3Se1PlDxsRQHRVfKp/R87NxLENcOu6/q7hHPy01CXDxAPnfeHWbJ5/eJi1rj0l5rBTzC0aDzzx46EVtRpmftSBX8+EWbTEWe8DtUFguV7RpGC3EFe/Xj0qnqypY1x8K1xU1rRtPyJeVC0tDVYTiDmpLDim8To4obayePKGDcnjdEAMNl4ax/HxYad49fK/S6y/GT5zFEJeH4yl9zn1lOcYqwJ00UCCJgQY/FK/a+uh233M5rRev/eJVT9r/nwtyy/ygOa7iIbVoCd+0f19YLi8R4no/l6dUnMuVFjjGmh6Vp/f9WqujD+R9K+7jXVteh9Gu8FeF52Kz9PPLhfv2/g6uk9MLy+DCIb5ULKldZQz+XNGGcfMZDHErV9S8n7UcYxFMeu3EcNuffSfap41qyqQey27T3PPptJru2dPe2SHCbsW0RN9ZygfCsaXDkghxvYe4Yyo+cNZcYF0nV173nxr3aX7S/j2w4oPvWy239diaISBiSquKWqsVW+zXuqXPwPgsaLGdbSquxbsNG1M5z+p7Zy3E5X27acjmAYxhDVxuT3ZKrm1bc0bKcv08Pco5AwS51495zcTbKo7nlR08rB86wPlVE1f2CnSFBY5xj4bzsy4a82v+uxWvVDdscS4Or+lEESPrl75CTAHnKS2Of8eKGq6NWxz/iW2+HOaazEsK13F9vBWYsZq41SruzVOlqCkKcPFwih6jcTOPYlqkMSvbh6QyObRieI2pCXJ5FPX/rRiTaY22D9u0fFCI6zWgfL90+q2CctysSdvS/MXw0C7alI36QzlmNGh4DRYNabJ4UCwNPtHMpUW4+lrfNZE186Sm33v1Ms7VPqOemWCMQ9wDdGyYsQAXD+5omB6vFJTs3QNN7vX6zVkJcmmfXlRxHB/pokYvh8E1ez6Xs9o7tXjw1opZG85sWct/XNQajVN7udyEoPR14hkNt/GkwnI6bf7f5Xa8pXNirtRgv9apOPbXtni2/FtpB5tlze2Ze1yXXtMX9jE7zBj3Tn2OIUZmJMBFt/T4kI3wFj1KhxjlesLLPYYFOL7LtnPjGOTi1VfFw+mxC5RZzcN2557P36yOE7dzxXF/rvCD4uldjRkZDfLzEESrjfraL+1EkGvK7ttg/UcWrv9Vi127f1U67VSTmVAqepP/KQJf3zX80YazoCy/VDHcyN/OSoiLL9YV999LfbJPcA3cAif3hjyYbnygnxADCKZ/7xXDdcQNkfbj/jN8DjbOvVtvmrYgl47tYRX7fXHhQ+Urheu7qM/5VGd0xoY1akZwr7kO80DdXT5zoiPN6THWY9rvR7VppN/ig3m7iv3dqfJcrJBD60LrvSX97lpLKO+PdlE73uYeTct/tqghekFF6HlywfqeX3F9ndzDtTKOMzasXTEt3p3j2rRBgBtuyIzro/FpHoNt1xhkMDoHzND52CDacpW28ZiEIFc5IfgbCx92L654qGwjxHV6Pj9UOX3TlhXlGb0Zf9nn8yX9/EL05h5qKKO0ndVLh8aJmQ0qQ0zpIKyfX8rfP7Ww3Kompc8f/LcWrvtFLa7F0pkgflnyZS7XTl5V0WFnky6vlTGdO/UDFffXRVLVwKIGbIhhMDp4+MYH2SeiYWo0gp6BMPegqK1sO5BwHiJgrREex9oVA7neWhrY88O2dP7OE4W4zj5k3lZ5/f2otiY0/f6D++r8s4QvOWen5U1pm/fr+YPwMxXB4D4V6z26zXyWNfO8pnU8s+I6eVXh8f4u7qGG996iiiFc9qko08MqrqMDO76/xirEpf3ZtmK2jSjnfaWq0QS5Z3X1Gm/IuVJzW7LXx7hsUxzmHl7R5mNJc/09aJT7H2M/dTXHZtNviPElpa8q/lkJcfEKNWrHG1yD2zXcXoy1ePGAz5P4IvvZtN0n9vSM/aeuez7m9mBXFazvxmW1DYxxzwr37diKe7N0MOFP9F1DlNsaPqDi2tui4lxd1zSEjnOIy+H+9ZUBbm7SBuqftrCwxZAPzR4ewjHFzYHxEO6zDdTA52TzinYli5fHmdEzbsT7v2LNq7Gab/p3BdyK8ni7ENfo+GKWjF3yvMXVtedtBuSNbaf1fHzoae1ixPloP9dxOa5cUXNcND9sul/+vovwFcdaWC43lsxTHTX/pa9S4xhaXJc39DUNVOn4fssa03ISQ1yEt3hFXzq/ddt2k/Tw6qumd84YB7qYwuuQdDyPn8RAFz16o0q/Sbu4/IF3WJMhAXqofXhexX7/ukmj8/R3FxSu//I+RvgfsxD35dwjvOmyXnyZiy9CecaRkyo+KO92Habz/w8dlfE2aX3nDfwMiUniP95lU4Ro61rxSnX9gvV9rDAoPaPgGvtZ4bqeXbCu7QuP86qmz6ma+Vij/WyD9e9Qsf4LJjHERZOU6BUcIyTkc/b+mg5LSxjOaWY7Jo5bgIhq1H0noZ1c6SvFPLXXfSag7FeN9jk1PYEWb7QdYz+Ny/GUNjrOy7saPvR2q6jpe/6Uh7hxWo7ooayfmGd8uWPI50fa7lYd7n/pdncsqNm7tmA9V5cEpfS7+5VOd1awrtKKgPe1CDs/LCzHa0tqD5dS0/e7ikD1hKFDXB7t4bqGy60d3yc7Sk/jFyie2OQVyhiHuajVOim+lY7b5Nn5gfzqGGOvxfGdN05tA6NHYkWj4zuaDgqdBxS9pcvXVEJc6+X0Jh+cFWW+ddrGQaUTvnfw7Ph9Fz2c82wjpc0LvrZALfezupzAvrQdWO6IsFoXr1KTRzcsxydVnL8PtPgS+vGK7ZwwdIgbo+X4aWnCNK2vV4+fliA370H0q7S8NY5vxOV7j7Qfb2gTlnPD0/eM22Tgpb3m8vL1ltv6XMU35ocIcb0uXxlqgN344EjLY6LpRNTM9FlDlxuwL+rgvti/opH4estYzycKr/fHVVxn3yus0f6XZazj/5Y2eWn6wV/zmRTtZgeqOZ3roofzBIa4b6TjXkVaGnPppv3npj0kxzzM/S5PDbbBwOFtw5iaJE9N1iqM9tWbruXxrVXT2zm6sbe8Pv9xVK/5hLi/WD48ygd6nuLqxXmMyZ/39Gp11Zb7uKhiezssZR2rlLRVzB1Llq+4zvZsO2RPXON9Ts0Uz+qK8ed+1EGouqjiGtlvxkLcF8dhRhTKb541Y5DPoXuKDRTmYlT3o2LWhJ7LcJsYxqDtQL75IXZADCI6jtdK2r89atrx1TwIosYxzlM0xo3yzMPjbFvxYL+hy3IT4v7c7irmVhzDZ9Z9c6g7MgJYR8e6dwf3xw8Kt/fVpXxpKZ3H8j21Xy5zh46FyuAP0WZsSZ8R+VlaUkP24IZlVzNO4cnRDjamDItXt9HEIwaTrtzeXhXXxpU1AyJPaojLb3/2G4fOczR7MD65tCfThLabO7bLsdXyMCH75R6zXezn17t4rdPj9bFC5QfmUctY17p5Wp13xSvT+Fbc0UwWO3Z4vDMb4nJN9oGjHEy68lzFIMJ7lr42XMaXgLVaflC/ueIV3bpLqO36TGFQ2qrBvp3RtMdn+t9eXvi35zY8fyu1aTc8b/u/zccZlRK75unYVlhGzd+fKtb9smkOcXHv1LyiZ3wfhtGL8i1Nhx+YgDB3ax6mY62G5RMjie+dlnM63KfLJ2Fi4YoG13drsxIP6fiSkP73d0dHjZJagYZleUGH98LMhbi4rtOye9S8TPAzLMYYPLbJNdZ0AON5296odLtLmLQ+nr03FvzdDxtea69tOm9ozIFaeEy7N3y2PK/Ha/q3efD4V0aN5GLH9YWK9Zw9jSEuXk2n5RXj1imQ9g/CdfMk9rdOaZiLb2w7L1RtHKPZ53ZZh3bdFidPWXXQpHxgxiugimP74bwPtb27+JZdER4fL8Q1aty/2ZQ9w/6mdKzBpjOLtKnxirH/FgsyLyg8V//asDyK5jyN16bzn0nxDCx5lZpnT9io4bPl9AHHCDwt/XxhNN+INuGVz5ZHt7gudh2jz7/rYizCmJpT79PpD3Ob5m8xd0xpmLtw/sClMbVI9NCKV0kxsncfY+rlB+L7hu500fbVceU18MXozdhXjVvb8a6EuCVel2+ZwudXBJBvVZTBtR2EuNeUNvFI+3fveUHms4VD9mzc4ovYKbWvDuPfXQydssCr8DtGcL3HHL4Hp583V/zdcZMW4iK4p+Un0WklXvdHr29t3mYzzD0yPphH9KE8xIV+QclchR28yj2yr7k+e66F+8AkvTLvYgDoMQtx0V5y08plUU3P8xiTL8Zpm8Jn1/0rB3ddv+X21i4d3/CuaZ3ykEQ3Ffz+d1oGzG1rp3krfeUYMwM0fLYcMQvPlsrBfl8WnTaaLrkt4Fa1nT2YjTD34NzN/+ZpDHM93fjxcP7gpE4gnGszbpywMn9LB8c98XOnxgO9ppYjele27YU3pl9CPlkR4rbuYHv/Ubi9L+Xr4CWF52fnttd0DHBcGFbunWc3uLnwFey9Gu7PdRP2bNmn7xDXx9ypsPjNt15u63S5oLbUm/3neVqwe0/yuZ7EkcZjkOUm87VOW4jLgeLYyvJ757Q9ryoa9d/ZRQ+9aHNV80q1pLYr92htXcOc1vXp0pq16HBVWG6fbVhOO07gs6XRXM1CHOMa5lbLE+x+Y1pftTYYZ+fkXKW9/BSc35hO6OJJPBclE3rPQoiLGpLK16pzbRpwL7Avq46iRjq3cy39AH1UF8dZ2sM//d4uhW82Tu2oLP6ptONFPMsK77XnNLz+vzehz/kXCnFMY6B7QB6e5KIZDG/nxuCR0f5mms5pejj//cDleEtafhMdTtJyVvQky73Jzk7L+ZWzi3xZiKv+4L7rPFzc9Yjt8YUgxkFL674m7c/TB66Je3HFB+gWXWwzreuYwrK+sfD3XtHReYj5nK8pqSUsfJV6XZPZPKIXeU1nsLT8OD8DzsjPha9HCIw5a4ceEitt70whjmkPdI+KBqvpwv3FFAe383Jvn02m9TzmXqa9TT4e4SeGTIhv8jEQ80KvQHMbndIajtvbDO48TSEun8tPVZ6jQzu+lt49v8Y62XeoXnIxj3HFB+gaHX0BenqXPdq7HIqocv7jBadkG+B63L/gfl07LU/IvYOP6nvg+hjCRohjVgLd5vkhemoeG21SQ9sNuYfuHtH7bwbO26ZdvyLPc8oeHtNqNWlXkh/+RwwRRKYtxKXjWScPq3BnRQjepqMQtf3SBhfuquZrgWvmk4XHfGWH90/McPLrju6dEzu+t7fpMMxs02D761f04J1r+oYjwlC0h4xevT18JnxUiGMWA92q+RXdgbk6/IYxDm035pqiN+X5PFecpXMVAajL1w8xKnsXPR9rxpWKcb+avhacthCXa4eeXXneftm2ZipP53fLAlPiHdGkd2Ph9qN39fWFx/wfHd9Dh3fUvvO5HZfJ8l2MURghtclI/9HsZsgBmO96bsRsPSVDuRQe+801ndaEOKY11C2fa+pi/KL3xod9niZlyLB2e57/NBrxviv9+0UxxtashbbFzsvqXXT9T+v4dowK3kPAPK1iH14pxP1F2Z1YeR6PanEdLSoNUFFLmJbd4trr+FrZv+Ja2a3j++iRHdxD1zdpc1ZQLgd38Pw8qEGZrBi9xysC7FM6PifrNxjkd2nnZi8hDpZ8o90zBiuMaVHyq9j3RshK//5mbtx6aQzOu6zXs1GTFkEkXpHENFAxJlNubBxBbZf4dpsHRVxdid/tgfO6lg+3a2P4gL566Ma5q9iX7wtxf3Fc69YMbB21nvNnNan5sIyavAbXTjS6f1eb9ozzyvc1FbW2t/cxEHda709bhoWP9PSM/T9DtwtrcO/+pK9nSJ6N6NSWz7nLSr/sC3Gw9Jtxhdyode1pHKh0RCHuxy0ebif3PTZe7bf5JsNGTGuIy9t9cYPXZmtXlF0MPXR2BzUd/5U7Dz2i5rVd7lj1+crtfamne+nfWr5K/bse7/MLW5ybixrWANbMwfzaAZ5127d5xVo6vIoQBwwiXn82fKjPRa3pUOPjVbarOUaIu9uH6UmV5/iYirK7Z8lcoLWvFeP1fNRMpZ9vzQ3Wt43mD1HrG/9bdGBo2isxhrzo6QvHA5vODRrD7fTZrCOt/+1DzoqSjmWziprR64d6S5Jf+zcdGut0IQ4YG6UDfC4+XEgKf88auAY2Xgv+sWJe0PWEuL84vvVyb+GaWod/qTy+HXPHhXHvff6pnr9wnNNwv97b8z3UKGDG3zQZWqmyo8dhAz9P1ormOg2/ADxUiANGLg/YfFvlAz0G+3zEiALnJyv2c08h7m7bf1ntEDG1E8RHDdc4z/qRXxWv3+d1WjNOXdezR/QRMKNGtEnNdmlnqbZjPLZ4/q0S93KDc3VUQTkLcUDvoeiAyof574b4oFnGQ/exFft6aWW7qqkPcQ1rXr/Q4Dytmv7uPeNWKxcdo/qaYmyx449OHnOV+3bpEE0T0nZ2b1BuOzXYzqtH3T6xIsh9tfZNxEJD5AhxQN8Pr9VKpuOZ/0qlyRyCPXwInVfxOvCZQtzdjvO+tcPJRMeIhtvaqmFNRy8BLl0PTx3wC9JXK/dxv4Hu+w1qat8jiEdThgbX+vkV9+k/jPhZuEZtp4+FhqcR4oC+w9CrKh9ab5/A/S4OQ7MS4vJ+bN9g7LLGw3Hk6ZHOGGGAu2zoJgAx92nlq9QtBwyYp/d5radjeVzFubmkyQDCPQS5zSsGiV5wv4U4GN8arE2jN94UhLjv10wuP1Qv1MIaxGsLH7S3pd/fWIhb4gd57ZhZp3Rw7h4RvV5LO6h0EN6iEf9HaoZL6bh25w+F+/m9ge/9V1eU4UsaXFvHjWrA5TaiI09lx59nCnEwOeHtHnkMqydPwbE8seIhe1OTnmk9B5BDKh62BwhxSzzeDWtqHtrMhrGEbUdP452iRqi27VhpQ/mYUitt5+Ejvk5P6KMTTgflv2ZJkM73/uoNzu0fu2pbNoJzVjNUzqlCHEyAPJPEhUO2qen5QfXveXaLkmWPcawNzbNElOz/z9Lvr1xYw3d1yRK9ZBuGuB+W7HNa/2eGqpGpuA5i+VUqp/t0fC7XSevdLh3z0THodA5gTafTOzct+47Lh2IMw1NQptc2nfC95TPg0wXX4UcaXFO7lF5Paf3vG8NnS7QZ/U3hMVyztGstzx5SVA6jOP8wK7Vvi6JWJH8j3UaJQO/33FrRpioHu/3ScmweqPi0HNLOz226/jMtR8Z8liksPa3vWUMAmJwPkvunD4gP51kJbupjUncAALoLb+um8HbgXW06coB7ipIBABjP8Ha/FNoOjoa289rY3NjX/IoAALQLbw+L7vCLjyyf/vuGmB1ACQEAjE9wW2lubu65Sxt8NA9s+mglBQAwHuFty9ze7YoFRqYX4AAARhzcYiLq3UpmJ8jjNT1cqQEAjCa4xUCwu+Vxpf5UOFBoDLj4SKUHADBcaFsnZlRIYeyoimmN5ge4q9M6tlaSAAD9hraoaXtFCmBHxOjtTafpyQHuqrS+hypVAIDuwtqGMZ1OfjX64fx69OoOJ8mOALeVkgYAqA9qf50C1f5pOSYtX0rB6oI8+fBtXYW1pQS4K2JeVGcAAKChPMn1nUMtKcBdGcONKHkAgPZB7h0DBbgrBDgAgA6lgLV3zwHuf1KAe5CSBgDoPsi9uccA90AlDADQX5Dbq+MA998CHADAMEHuTR0GuE2VKM2Ur88AAAFBSURBVADAcEHujS0D3GUpwG2iJAEAhg9yu6fljgYB7lcpwG2sBAEARhfkXlsT5NLv/jwFuPspOQCA0Qe5HUuCXPqdn6UAt5ESAwAYnyD3mmVNdp/+v5/GfKtKCgBg/ILcDksKcul/u1iAAwAY7yD3qvlBLge4+yoZAIDxD3Lb3vZnF6UAt4ESAQCYEHNzc89LAW5dJQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMpP8PV/R8PL52eskAAAAASUVORK5CYII=" + }, + "bancor": { + "color": "#c9c9c9", + "title": "Bancor", + "icon": "data:image/svg+xml,%3csvg width='117' height='29' viewBox='0 0 117 29' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M9.15211 0.0550469L16.2358 3.98013C16.5117 4.1333 16.5117 4.51305 16.2358 4.66622L9.15211 8.5913C9.02579 8.66151 8.86623 8.66151 8.73992 8.5913L1.65627 4.66622C1.38037 4.51305 1.38037 4.1333 1.65627 3.98013L8.73992 0.0550469C8.86956 -0.018349 9.02579 -0.018349 9.15211 0.0550469Z' fill='%230A2540'/%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M17.8737 6.17705V14.0304C17.8737 14.1708 17.7939 14.3017 17.6676 14.3751L10.4244 18.3799C10.1485 18.5331 9.80615 18.3416 9.80615 18.0353V10.1851C9.80615 10.0447 9.88593 9.91386 10.0122 9.84046L17.2521 5.82922C17.528 5.67924 17.8737 5.8707 17.8737 6.17705Z' fill='%230A2540'/%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M19.8715 14.9575L10.0122 20.4048C9.88593 20.475 9.80615 20.6058 9.80615 20.7494V28.6028C9.80615 28.9091 10.1485 29.0974 10.4244 28.9474L20.2804 23.497C20.4067 23.4268 20.4865 23.2959 20.4865 23.1523V15.299C20.4898 14.9958 20.1441 14.8043 19.8715 14.9575Z' fill='%230A2540'/%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 14.0244V6.1742C0 5.86785 0.342382 5.67958 0.618281 5.82956L7.85483 9.8408C7.98115 9.91101 8.06093 10.0418 8.06093 10.1854V18.0356C8.06093 18.342 7.71855 18.5302 7.44265 18.3802L0.206094 14.3658C0.0797783 14.2956 0 14.1648 0 14.0244Z' fill='%230A2540'/%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 16.7387V24.592C0 24.7324 0.0797783 24.8633 0.206094 24.9366L7.44265 28.9447C7.71855 29.0979 8.06093 28.9064 8.06093 28.6001V20.7499C8.06093 20.6095 7.98115 20.4786 7.85483 20.4053L0.618281 16.394C0.342382 16.244 0 16.4323 0 16.7387Z' fill='%230A2540'/%3e %3cpath d='M40.0036 16.4058C40.6736 17.2194 41.0086 18.1524 41.0086 19.2049C41.0086 20.1573 40.7674 20.9903 40.2817 21.7135C39.7959 22.4334 39.0958 22.9984 38.1813 23.4052C37.2634 23.812 36.1813 24.0154 34.9318 24.0154H26.9823V6.24902H34.5901C35.8396 6.24902 36.9183 6.44596 37.8262 6.83338C38.734 7.22403 39.4207 7.76641 39.8864 8.46376C40.352 9.16112 40.5865 9.94887 40.5865 10.8302C40.5865 11.8666 40.2984 12.7318 39.7289 13.4259C39.1561 14.1233 38.3957 14.614 37.4443 14.9014C38.4828 15.0918 39.337 15.5923 40.0036 16.4058ZM30.6807 13.5809H34.0608C34.9418 13.5809 35.6185 13.3904 36.0942 13.0095C36.5699 12.6285 36.8078 12.0797 36.8078 11.3662C36.8078 10.6527 36.5699 10.1038 36.0942 9.71319C35.6185 9.32254 34.9418 9.12883 34.0608 9.12883H30.6807V13.5809ZM36.5063 20.506C37.0088 20.0992 37.26 19.5213 37.26 18.7755C37.26 18.0136 36.9954 17.4131 36.4661 16.9805C35.9368 16.5479 35.2232 16.3316 34.3254 16.3316H30.6807V21.1162H34.4058C35.3036 21.1162 36.0038 20.9128 36.5063 20.506Z' fill='%230A2540'/%3e %3cpath d='M43.2303 13.1217C43.8199 12.0175 44.6206 11.1717 45.6323 10.5744C46.644 9.98037 47.7763 9.68335 49.0258 9.68335C50.1179 9.68335 51.0726 9.89643 51.8934 10.3194C52.7108 10.7423 53.3674 11.2782 53.8598 11.9239V9.9158H57.585V24.0178H53.8631V21.9548C53.3875 22.6167 52.7309 23.1655 51.8967 23.5981C51.0592 24.0307 50.0944 24.247 49.0057 24.247C47.7729 24.247 46.6507 23.9403 45.639 23.3301C44.6273 22.72 43.8266 21.858 43.237 20.7474C42.6474 19.6368 42.3527 18.3583 42.3527 16.9152C42.346 15.4882 42.6408 14.2258 43.2303 13.1217ZM53.3339 14.7392C52.9821 14.1193 52.5064 13.6447 51.9068 13.3122C51.3071 12.9796 50.6639 12.815 49.9772 12.815C49.2904 12.815 48.6573 12.9764 48.0744 13.2993C47.4949 13.6221 47.0225 14.0935 46.6607 14.7133C46.2989 15.3332 46.118 16.0661 46.118 16.9152C46.118 17.7642 46.2989 18.5068 46.6607 19.1428C47.0225 19.7788 47.4982 20.2663 48.0878 20.6053C48.6774 20.9443 49.3072 21.1154 49.9772 21.1154C50.6639 21.1154 51.3071 20.9508 51.9068 20.6182C52.5064 20.2857 52.9821 19.8111 53.3339 19.1912C53.6856 18.5714 53.8631 17.8288 53.8631 16.9636C53.8631 16.1016 53.6856 15.359 53.3339 14.7392Z' fill='%230A2540'/%3e %3cpath d='M72.8699 11.3028C73.9452 12.3618 74.4812 13.8436 74.4812 15.7452V24.0166H70.7829V16.2295C70.7829 15.1092 70.4914 14.2472 69.9119 13.6467C69.3323 13.043 68.5384 12.7427 67.5334 12.7427C66.5116 12.7427 65.7076 13.043 65.118 13.6467C64.5285 14.2504 64.2337 15.1092 64.2337 16.2295V24.0198H60.5353V9.9178H64.2337V11.6741C64.7261 11.0639 65.3559 10.5829 66.123 10.2342C66.8902 9.88552 67.731 9.71118 68.6456 9.71118C70.3876 9.71441 71.7945 10.2439 72.8699 11.3028Z' fill='%230A2540'/%3e %3cpath d='M77.2995 13.1346C77.9159 12.0401 78.7701 11.1911 79.8622 10.5873C80.9543 9.9836 82.2039 9.68335 83.6142 9.68335C85.4265 9.68335 86.9307 10.1192 88.1166 10.9941C89.3058 11.869 90.1031 13.0926 90.5084 14.6714H86.5186C86.3076 14.0612 85.9525 13.5801 85.45 13.2347C84.9475 12.886 84.3277 12.7117 83.5874 12.7117C82.5322 12.7117 81.6947 13.0797 81.0783 13.819C80.4619 14.5584 80.1537 15.6044 80.1537 16.9636C80.1537 18.3034 80.4619 19.343 81.0783 20.0823C81.6947 20.8216 82.5322 21.1897 83.5874 21.1897C85.0848 21.1897 86.0597 20.544 86.5186 19.2558H90.5084C90.1031 20.7829 89.3025 21.9968 88.1065 22.8943C86.9072 23.7951 85.4131 24.2438 83.6176 24.2438C82.2072 24.2438 80.9577 23.9436 79.8656 23.3398C78.7735 22.7361 77.9192 21.8902 77.3029 20.7926C76.6865 19.6981 76.3783 18.4229 76.3783 16.9604C76.3749 15.5075 76.6798 14.2291 77.2995 13.1346Z' fill='%230A2540'/%3e %3cpath d='M95.2474 23.3451C94.1185 22.7414 93.2341 21.889 92.5909 20.7881C91.9477 19.684 91.6261 18.412 91.6261 16.9688C91.6261 15.5257 91.9578 14.2537 92.6177 13.1495C93.2776 12.0454 94.1788 11.1931 95.3245 10.5926C96.4702 9.98885 97.7465 9.6886 99.1535 9.6886C100.564 9.6886 101.837 9.98885 102.983 10.5926C104.128 11.1963 105.029 12.0486 105.689 13.1495C106.349 14.2537 106.681 15.5257 106.681 16.9688C106.681 18.412 106.343 19.684 105.662 20.7881C104.986 21.8923 104.068 22.7446 102.916 23.3451C101.763 23.9488 100.473 24.2491 99.0463 24.2491C97.6426 24.2491 96.373 23.9456 95.2474 23.3451ZM100.939 20.6719C101.529 20.3587 102.001 19.8874 102.353 19.2611C102.704 18.6347 102.882 17.8696 102.882 16.9688C102.882 15.629 102.517 14.5991 101.787 13.8759C101.056 13.156 100.162 12.7944 99.1066 12.7944C98.0514 12.7944 97.1636 13.156 96.4534 13.8759C95.7399 14.5959 95.3848 15.629 95.3848 16.9688C95.3848 18.3087 95.7332 19.3418 96.4266 20.0617C97.1234 20.7817 97.9978 21.1433 99.053 21.1433C99.7196 21.1433 100.349 20.9851 100.939 20.6719Z' fill='%230A2540'/%3e %3cpath d='M114.297 10.3484C115.064 9.92548 115.938 9.7124 116.923 9.7124V13.4542H115.945C114.783 13.4542 113.908 13.719 113.319 14.242C112.729 14.7682 112.434 15.6851 112.434 16.9926V24.0178H108.736V9.9158H112.434V12.1047C112.91 11.3557 113.53 10.7713 114.297 10.3484Z' fill='%230A2540'/%3e %3c/svg%3e", + "iconPng": "data:image/png;base64,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" + }, + "curve": { + "color": "#24292E", + "title": "Curve", + "icon": "data:image/svg+xml,%3csvg width='74' height='30' viewBox='0 0 74 30' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3cpath d='M38.1738 15.9546C38.0552 16.9697 37.6794 17.7542 37.0466 18.3079C36.4182 18.8572 35.5811 19.1318 34.5352 19.1318C33.4014 19.1318 32.4917 18.7253 31.8062 17.9124C31.125 17.0994 30.7844 16.0117 30.7844 14.6494V13.7266C30.7844 12.8345 30.9426 12.05 31.259 11.3733C31.5798 10.6965 32.0325 10.178 32.6169 9.81763C33.2014 9.45288 33.8782 9.27051 34.6472 9.27051C35.6667 9.27051 36.4841 9.55615 37.0994 10.1274C37.7146 10.6943 38.0728 11.481 38.1738 12.4873H36.9016C36.7917 11.7227 36.5522 11.1689 36.1831 10.8262C35.8184 10.4834 35.3064 10.312 34.6472 10.312C33.8386 10.312 33.2036 10.6108 32.7422 11.2085C32.2852 11.8062 32.0566 12.6565 32.0566 13.7595V14.689C32.0566 15.7305 32.2742 16.5588 32.7092 17.1741C33.1443 17.7893 33.7529 18.0969 34.5352 18.0969C35.2383 18.0969 35.7766 17.9387 36.1501 17.6223C36.5281 17.3015 36.7786 16.7456 36.9016 15.9546H38.1738ZM44.1196 18.2947C43.645 18.8528 42.9485 19.1318 42.03 19.1318C41.2698 19.1318 40.6897 18.9121 40.2898 18.4727C39.8943 18.0288 39.6943 17.374 39.6899 16.5083V11.8677H40.9094V16.4753C40.9094 17.5564 41.3489 18.0969 42.2278 18.0969C43.1594 18.0969 43.7791 17.7498 44.0867 17.0554V11.8677H45.3062V19H44.146L44.1196 18.2947ZM50.6125 12.9619C50.428 12.9312 50.228 12.9158 50.0127 12.9158C49.2129 12.9158 48.6702 13.2563 48.3845 13.9375V19H47.165V11.8677H48.3516L48.3713 12.6917C48.7712 12.0544 49.3381 11.7358 50.072 11.7358C50.3093 11.7358 50.4895 11.7666 50.6125 11.8281V12.9619ZM54.2117 17.3455L55.9783 11.8677H57.2241L54.6665 19H53.7371L51.1531 11.8677H52.3989L54.2117 17.3455ZM61.2649 19.1318C60.2981 19.1318 59.5115 18.8154 58.905 18.1826C58.2986 17.5454 57.9954 16.6951 57.9954 15.6316V15.4075C57.9954 14.7 58.1294 14.0693 58.3975 13.5156C58.6699 12.9575 59.0479 12.5225 59.5312 12.2104C60.019 11.894 60.5464 11.7358 61.1133 11.7358C62.0405 11.7358 62.7612 12.0413 63.2754 12.6521C63.7896 13.2629 64.0466 14.1375 64.0466 15.2756V15.7832H59.2148C59.2324 16.4863 59.4368 17.0554 59.8279 17.4905C60.2234 17.9211 60.7244 18.1365 61.3308 18.1365C61.7615 18.1365 62.1262 18.0486 62.425 17.8728C62.7239 17.697 62.9854 17.4641 63.2095 17.1741L63.9543 17.7542C63.3567 18.6726 62.4602 19.1318 61.2649 19.1318ZM61.1133 12.7378C60.6211 12.7378 60.208 12.918 59.874 13.2783C59.54 13.6343 59.3335 14.1353 59.2544 14.7812H62.8271V14.689C62.792 14.0693 62.625 13.5903 62.3262 13.252C62.0273 12.9092 61.623 12.7378 61.1133 12.7378Z' fill='%23E6E6E6'/%3e %3cpath d='M16.2311 16.396L14.9332 16.6817L14.7722 16.0747L16.1506 15.8225L16.2311 16.396Z' fill='blue'/%3e %3cpath d='M14.9332 16.6814L13.8055 17.0642L13.5618 16.4305L14.7722 16.0743L14.9332 16.6814Z' fill='blue'/%3e %3cpath d='M16.1501 15.8226L14.7717 16.0747L14.6267 15.3663L16.0781 15.1522L16.1501 15.8226Z' fill='%230028FF'/%3e %3cpath d='M14.772 16.0744L13.5616 16.4305L13.3418 15.691L14.6271 15.366L14.772 16.0744Z' fill='%230018FF'/%3e %3cpath d='M16.3176 16.8586L15.106 17.1726L14.9329 16.6816L16.2308 16.3959L16.3176 16.8586Z' fill='%230000F1'/%3e %3cpath d='M15.1063 17.1724L14.0672 17.577L13.8054 17.0642L14.9332 16.6814L15.1063 17.1724Z' fill='%230000DA'/%3e %3cpath d='M16.0785 15.1524L14.6271 15.3664L14.5017 14.5736L16.0166 14.4012L16.0785 15.1524Z' fill='%230058FF'/%3e %3cpath d='M14.627 15.3659L13.3417 15.6909L13.1511 14.8631L14.5016 14.573L14.627 15.3659Z' fill='%230048FF'/%3e %3cpath d='M17.6493 16.2077L16.2308 16.3961L16.1504 15.8226L17.6439 15.6733L17.6493 16.2077Z' fill='%230014FF'/%3e %3cpath d='M16.4089 17.1991L15.2871 17.5354L15.106 17.1724L16.3176 16.8584L16.4089 17.1991Z' fill='%230000DA'/%3e %3cpath d='M13.8051 17.0646L12.8805 17.5388L12.5557 16.8863L13.5614 16.4309L13.8051 17.0646Z' fill='%230000E8'/%3e %3cpath d='M15.2872 17.5355L14.3404 17.9562L14.0669 17.577L15.106 17.1725L15.2872 17.5355Z' fill='%230000C4'/%3e %3cpath d='M17.6442 15.6732L16.1507 15.8225L16.0786 15.1521L17.6402 15.0465L17.6442 15.6732Z' fill='%23003CFF'/%3e %3cpath d='M13.5614 16.4308L12.5557 16.8863L12.2625 16.1237L13.3416 15.6913L13.5614 16.4308Z' fill='%230008FF'/%3e %3cpath d='M17.656 16.6367L16.3179 16.8586L16.231 16.3958L17.6494 16.2075L17.656 16.6367Z' fill='blue'/%3e %3cpath d='M14.0669 17.5773L13.2293 18.0654L12.8806 17.5387L13.8052 17.0646L14.0669 17.5773Z' fill='%230000C8'/%3e %3cpath d='M16.0164 14.4008L14.5015 14.5731L14.3987 13.7146L15.9662 13.5868L16.0164 14.4008Z' fill='%230090FF'/%3e %3cpath d='M14.5016 14.5736L13.1511 14.8637L12.9944 13.9673L14.3988 13.7151L14.5016 14.5736Z' fill='%230084FF'/%3e %3cpath d='M17.6399 15.0464L16.0782 15.1521L16.0164 14.4009L17.6373 14.3425L17.6399 15.0464Z' fill='%230068FF'/%3e %3cpath d='M13.3417 15.6913L12.2626 16.1237L12.0081 15.2691L13.1511 14.8635L13.3417 15.6913Z' fill='%23003CFF'/%3e %3cpath d='M17.6634 16.9501L16.4089 17.1993L16.3176 16.8586L17.6558 16.6367L17.6634 16.9501Z' fill='%230000F6'/%3e %3cpath d='M16.5024 17.4092L15.4719 17.7614L15.2871 17.5357L16.4089 17.1993L16.5024 17.4092Z' fill='%230000D1'/%3e %3cpath d='M14.3404 17.9563L13.5935 18.4533L13.2292 18.0652L14.0668 17.5771L14.3404 17.9563Z' fill='%230000AD'/%3e %3cpath d='M15.4721 17.7614L14.6194 18.1924L14.3406 17.9565L15.2873 17.5358L15.4721 17.7614Z' fill='%230000BB'/%3e %3cpath d='M17.6374 14.3424L16.0165 14.4008L15.9663 13.5869L17.6364 13.5782L17.6374 14.3424Z' fill='%23009CFF'/%3e %3cpath d='M13.1514 14.8634L12.0084 15.269L11.7988 14.3425L12.9946 13.967L13.1514 14.8634Z' fill='%230078FF'/%3e %3cpath d='M17.6719 17.1396L16.5024 17.4091L16.4089 17.1992L17.6634 16.9501L17.6719 17.1396Z' fill='%230000ED'/%3e %3cpath d='M15.9664 13.5869L14.3989 13.7148L14.3213 12.8112L15.9291 12.7296L15.9664 13.5869Z' fill='%2300CCFF'/%3e %3cpath d='M19.1245 16.1121L17.6492 16.2077L17.6438 15.6733L19.1861 15.6207L19.1245 16.1121Z' fill='%23002CFF'/%3e %3cpath d='M14.3985 13.7149L12.9941 13.9671L12.8752 13.0234L14.3209 12.8113L14.3985 13.7149Z' fill='%2300C4FF'/%3e %3cpath d='M19.0598 16.5039L17.656 16.6368L17.6494 16.2076L19.1248 16.1121L19.0598 16.5039Z' fill='%230014FF'/%3e %3cpath d='M19.1865 15.6206L17.6442 15.6732L17.6401 15.0465L19.2431 15.0416L19.1865 15.6206Z' fill='%230050FF'/%3e %3cpath d='M12.8805 17.5384L12.1747 18.0922L11.7742 17.43L12.5556 16.886L12.8805 17.5384Z' fill='%230000DA'/%3e %3cpath d='M12.5557 16.8862L11.7742 17.4302L11.4126 16.6537L12.2625 16.1237L12.5557 16.8862Z' fill='blue'/%3e %3cpath d='M14.6194 18.1922L13.9649 18.6929L13.5938 18.4533L14.3406 17.9563L14.6194 18.1922Z' fill='%230000A4'/%3e %3cpath d='M13.2291 18.0655L12.6044 18.6247L12.1746 18.0926L12.8804 17.5388L13.2291 18.0655Z' fill='%230000B6'/%3e %3cpath d='M16.5957 17.4821L15.6559 17.8432L15.4719 17.7611L16.5024 17.4089L16.5957 17.4821Z' fill='%230000D6'/%3e %3cpath d='M18.9927 16.7865L17.6634 16.9502L17.6558 16.6369L19.0596 16.5039L18.9927 16.7865Z' fill='%230004FF'/%3e %3cpath d='M19.243 15.0416L17.64 15.0464L17.6375 14.3425L19.2934 14.3889L19.243 15.0416Z' fill='%230078FF'/%3e %3cpath d='M15.6559 17.8435L14.8965 18.2784L14.6191 18.1924L15.4719 17.7615L15.6559 17.8435Z' fill='%230000BF'/%3e %3cpath d='M17.6362 13.5783L15.9662 13.587L15.929 12.7296L17.6367 12.7723L17.6362 13.5783Z' fill='%2300D8FF'/%3e %3cpath d='M12.2628 16.1236L11.4129 16.6537L11.0989 15.7812L12.0083 15.2689L12.2628 16.1236Z' fill='%230034FF'/%3e %3cpath d='M17.6811 17.2004L16.5958 17.4825L16.5024 17.4093L17.672 17.1399L17.6811 17.2004Z' fill='%230000F1'/%3e %3cpath d='M13.5935 18.4534L13.0534 19.0136L12.6045 18.6245L13.2292 18.0653L13.5935 18.4534Z' fill='%2300009F'/%3e %3cpath d='M12.994 13.9668L11.7982 14.3422L11.6389 13.3657L12.8751 13.0231L12.994 13.9668Z' fill='%2300BCFF'/%3e %3cpath d='M18.9259 16.9526L17.6721 17.1398L17.6636 16.9503L18.9929 16.7865L18.9259 16.9526Z' fill='blue'/%3e %3cpath d='M15.9291 12.7295L14.3213 12.8111L14.271 11.8841L15.9059 11.8496L15.9291 12.7295Z' fill='%2323FFD4'/%3e %3cpath d='M19.2932 14.3888L17.6373 14.3424L17.6362 13.5782L19.336 13.6783L19.2932 14.3888Z' fill='%2300ACFF'/%3e %3cpath d='M14.3211 12.8112L12.8755 13.0233L12.7976 12.055L14.2709 11.8843L14.3211 12.8112Z' fill='%231CFFDB'/%3e %3cpath d='M14.8966 18.2783L14.334 18.7774L13.9648 18.693L14.6193 18.1923L14.8966 18.2783Z' fill='%230000AD'/%3e %3cpath d='M12.0081 15.2687L11.0987 15.781L10.8401 14.833L11.7986 14.3422L12.0081 15.2687Z' fill='%230070FF'/%3e %3cpath d='M16.6868 17.416L15.8347 17.7786L15.656 17.8432L16.5958 17.4822L16.6868 17.416Z' fill='%230000E8'/%3e %3cpath d='M13.9648 18.6931L13.5108 19.2498L13.0535 19.0137L13.5936 18.4535L13.9648 18.6931Z' fill='%23000096'/%3e %3cpath d='M17.6365 12.7723L15.9288 12.7297L15.9055 11.8497L17.6385 11.9439L17.6365 12.7723Z' fill='%2326FFD1'/%3e %3cpath d='M18.8603 16.9972L17.6813 17.1999L17.6721 17.1394L18.926 16.9521L18.8603 16.9972Z' fill='blue'/%3e %3cpath d='M20.5826 16.1006L19.1245 16.1121L19.1861 15.6207L20.701 15.6547L20.5826 16.1006Z' fill='%230044FF'/%3e %3cpath d='M20.4573 16.4525L19.0598 16.5036L19.1248 16.1118L20.5829 16.1003L20.4573 16.4525Z' fill='%23002CFF'/%3e %3cpath d='M15.8348 17.7787L15.1658 18.2112L14.8967 18.2782L15.6561 17.8433L15.8348 17.7787Z' fill='%230000D1'/%3e %3cpath d='M19.336 13.6785L17.6362 13.5785L17.6367 12.7725L19.3701 12.9273L19.336 13.6785Z' fill='%2300E0FB'/%3e %3cpath d='M17.6909 17.1294L16.6869 17.4162L16.5959 17.4824L17.6813 17.2002L17.6909 17.1294Z' fill='blue'/%3e %3cpath d='M20.7014 15.6543L19.1865 15.6204L19.2432 15.0414L20.8095 15.1254L20.7014 15.6543Z' fill='%230064FF'/%3e %3cpath d='M12.8755 13.0234L11.6394 13.3661L11.5347 12.3631L12.7977 12.0551L12.8755 13.0234Z' fill='%2319FFDE'/%3e %3cpath d='M20.327 16.7024L18.9927 16.7865L19.0595 16.5039L20.4569 16.4528L20.327 16.7024Z' fill='%23001CFF'/%3e %3cpath d='M12.175 18.0925L11.6864 18.7086L11.2197 18.0462L11.7745 17.4303L12.175 18.0925Z' fill='%230000D1'/%3e %3cpath d='M12.6045 18.6246L12.1868 19.2371L11.686 18.7086L12.1747 18.0925L12.6045 18.6246Z' fill='%230000A8'/%3e %3cpath d='M15.9056 11.8497L14.2708 11.8842L14.2493 10.9565L15.8971 10.9688L15.9056 11.8497Z' fill='%235AFF9D'/%3e %3cpath d='M20.809 15.1256L19.2427 15.0416L19.293 14.3889L20.9043 14.5266L20.809 15.1256Z' fill='%23008CFF'/%3e %3cpath d='M11.7741 17.4301L11.2193 18.0459L10.7979 17.2652L11.4125 16.6536L11.7741 17.4301Z' fill='blue'/%3e %3cpath d='M11.7985 14.3425L10.84 14.8333L10.6433 13.8323L11.6393 13.366L11.7985 14.3425Z' fill='%2300B8FF'/%3e %3cpath d='M14.271 11.8842L12.7977 12.0549L12.7632 11.0855L14.2495 10.9565L14.271 11.8842Z' fill='%235AFF9D'/%3e %3cpath d='M20.1962 16.843L18.9258 16.9525L18.9928 16.7864L20.3272 16.7023L20.1962 16.843Z' fill='%230018FF'/%3e %3cpath d='M15.1657 18.2109L14.6921 18.703L14.334 18.7771L14.8966 18.278L15.1657 18.2109Z' fill='%230000BF'/%3e %3cpath d='M14.3338 18.7775L13.9655 19.3264L13.5107 19.2498L13.9647 18.6931L14.3338 18.7775Z' fill='%2300009B'/%3e %3cpath d='M13.0536 19.0134L12.7099 19.6185L12.187 19.2368L12.6047 18.6244L13.0536 19.0134Z' fill='%23000092'/%3e %3cpath d='M18.7975 16.9198L17.6905 17.1293L17.6809 17.2002L18.86 16.9975L18.7975 16.9198Z' fill='%23000CFF'/%3e %3cpath d='M11.4129 16.6536L10.7982 17.2653L10.4321 16.3846L11.0989 15.7811L11.4129 16.6536Z' fill='%23002CFF'/%3e %3cpath d='M17.6388 11.9436L15.9058 11.8494L15.8972 10.9685L17.6424 11.1134L17.6388 11.9436Z' fill='%235DFF9A'/%3e %3cpath d='M19.3703 12.9269L17.637 12.7721L17.639 11.9437L19.3949 12.1534L19.3703 12.9269Z' fill='%232CFFCA'/%3e %3cpath d='M20.9042 14.5269L19.293 14.3892L19.3357 13.6786L20.9841 13.8722L20.9042 14.5269Z' fill='%2300B8FF'/%3e %3cpath d='M16.7734 17.2111L16.0038 17.5677L15.835 17.7787L16.6871 17.4161L16.7734 17.2111Z' fill='blue'/%3e %3cpath d='M17.7008 16.928L16.7733 17.2111L16.687 17.4162L17.691 17.1294L17.7008 16.928Z' fill='%23000CFF'/%3e %3cpath d='M20.0676 16.871L18.8604 16.9974L18.9259 16.9523L20.1964 16.8429L20.0676 16.871Z' fill='%230018FF'/%3e %3cpath d='M16.0038 17.5679L15.4201 17.9915L15.166 18.2114L15.835 17.7789L16.0038 17.5679Z' fill='%230000F1'/%3e %3cpath d='M12.7976 12.0548L11.5346 12.3628L11.4875 11.3577L12.7631 11.0854L12.7976 12.0548Z' fill='%2356FFA0'/%3e %3cpath d='M13.5109 19.2497L13.2426 19.8438L12.71 19.6186L13.0536 19.0135L13.5109 19.2497Z' fill='%23000089'/%3e %3cpath d='M11.0987 15.781L10.4319 16.3845L10.1304 15.4246L10.84 14.833L11.0987 15.781Z' fill='%23006CFF'/%3e %3cpath d='M11.6394 13.366L10.6434 13.8323L10.5139 12.8023L11.5347 12.3629L11.6394 13.366Z' fill='%2316FFE1'/%3e %3cpath d='M20.9843 13.872L19.3359 13.6784L19.37 12.9271L21.0469 13.1778L20.9843 13.872Z' fill='%2306ECF1'/%3e %3cpath d='M15.8971 10.9687L14.2493 10.9564L14.2574 10.0511L15.9035 10.1087L15.8971 10.9687Z' fill='%2394FF63'/%3e %3cpath d='M18.7397 16.7205L17.7005 16.928L17.6907 17.1294L18.7976 16.9198L18.7397 16.7205Z' fill='%230024FF'/%3e %3cpath d='M14.6918 18.7034L14.4064 19.2403L13.9653 19.3263L14.3337 18.7774L14.6918 18.7034Z' fill='%230000AD'/%3e %3cpath d='M21.7696 16.4731L20.457 16.4525L20.5827 16.1003L21.9438 16.1614L21.7696 16.4731Z' fill='%230044FF'/%3e %3cpath d='M21.9436 16.1613L20.5825 16.1003L20.7009 15.6543L22.1073 15.7615L21.9436 16.1613Z' fill='%23005CFF'/%3e %3cpath d='M19.3948 12.1537L17.6389 11.944L17.6424 11.1138L19.4091 11.377L19.3948 12.1537Z' fill='%235DFF9A'/%3e %3cpath d='M14.2492 10.9564L12.7629 11.0854L12.773 10.1391L14.2573 10.0511L14.2492 10.9564Z' fill='%2394FF63'/%3e %3cpath d='M19.944 16.7853L18.7976 16.9198L18.8601 16.9975L20.0674 16.8711L19.944 16.7853Z' fill='%230028FF'/%3e %3cpath d='M15.4202 17.9912L15.0305 18.4711L14.6924 18.7032L15.1661 18.2111L15.4202 17.9912Z' fill='%230000DF'/%3e %3cpath d='M21.5893 16.6891L20.3271 16.7021L20.4571 16.4525L21.7696 16.4731L21.5893 16.6891Z' fill='%230038FF'/%3e %3cpath d='M22.1074 15.7619L20.7009 15.6546L20.8091 15.1257L22.2567 15.2839L22.1074 15.7619Z' fill='%230078FF'/%3e %3cpath d='M17.6424 11.1135L15.8972 10.9686L15.9036 10.1086L17.6473 10.3022L17.6424 11.1135Z' fill='%2390FF66'/%3e %3cpath d='M13.9655 19.3263L13.7719 19.9063L13.2424 19.8438L13.5108 19.2498L13.9655 19.3263Z' fill='%2300008D'/%3e %3cpath d='M16.8524 16.8708L16.1582 17.214L16.0034 17.5676L16.7729 17.211L16.8524 16.8708Z' fill='%23001CFF'/%3e %3cpath d='M21.4072 16.804L20.196 16.843L20.327 16.7022L21.5892 16.6892L21.4072 16.804Z' fill='%230034FF'/%3e %3cpath d='M17.7105 16.5997L16.8526 16.8708L16.7732 17.2109L17.7007 16.9278L17.7105 16.5997Z' fill='%230030FF'/%3e %3cpath d='M22.2567 15.2839L20.8091 15.1257L20.9043 14.5267L22.3878 14.7393L22.2567 15.2839Z' fill='%2300A0FF'/%3e %3cpath d='M21.047 13.1775L19.3701 12.9269L19.3947 12.1533L21.0906 12.4607L21.047 13.1775Z' fill='%2333FFC4'/%3e %3cpath d='M10.8404 14.8331L10.1307 15.4247L9.90137 14.4083L10.6437 13.8322L10.8404 14.8331Z' fill='%2300B0FF'/%3e %3cpath d='M11.6861 18.7086L11.3977 19.3644L10.8779 18.7114L11.2194 18.0461L11.6861 18.7086Z' fill='%230000C8'/%3e %3cpath d='M12.1869 19.2369L11.9553 19.8799L11.3977 19.3643L11.6861 18.7085L12.1869 19.2369Z' fill='%230000A4'/%3e %3cpath d='M16.1584 17.2144L15.6526 17.6227L15.4199 17.9916L16.0036 17.5679L16.1584 17.2144Z' fill='%230008FF'/%3e %3cpath d='M11.2196 18.0461L10.8782 18.7114L10.4087 17.9365L10.7982 17.2654L11.2196 18.0461Z' fill='blue'/%3e %3cpath d='M12.7633 11.0856L11.4878 11.3579L11.5001 10.3756L12.7734 10.1393L12.7633 11.0856Z' fill='%2394FF63'/%3e %3cpath d='M21.2284 16.8148L20.0676 16.8712L20.1964 16.8431L21.4075 16.8042L21.2284 16.8148Z' fill='%230034FF'/%3e %3cpath d='M19.8293 16.5872L18.74 16.7206L18.7979 16.92L19.9442 16.7854L19.8293 16.5872Z' fill='%23003CFF'/%3e %3cpath d='M11.5345 12.3629L10.5138 12.8023L10.4553 11.7683L11.4874 11.3578L11.5345 12.3629Z' fill='%2356FFA0'/%3e %3cpath d='M12.7098 19.6184L12.5374 20.2456L11.9553 19.8797L12.1869 19.2367L12.7098 19.6184Z' fill='%23000089'/%3e %3cpath d='M18.6882 16.4033L17.7105 16.5997L17.7007 16.9278L18.7399 16.7203L18.6882 16.4033Z' fill='%230044FF'/%3e %3cpath d='M22.388 14.7392L20.9045 14.5267L20.9845 13.8721L22.4976 14.1413L22.388 14.7392Z' fill='%2300C8FF'/%3e %3cpath d='M19.409 11.3768L17.6423 11.1135L17.6473 10.3022L19.4127 10.6165L19.409 11.3768Z' fill='%2390FF66'/%3e %3cpath d='M15.9037 10.1088L14.2576 10.0513L14.2954 9.19141L15.925 9.29178L15.9037 10.1088Z' fill='%23CAFF2C'/%3e %3cpath d='M15.0299 18.4711L14.823 18.9922L14.4065 19.2401L14.6918 18.7032L15.0299 18.4711Z' fill='%230000CD'/%3e %3cpath d='M10.798 17.2652L10.4085 17.9362L10.0007 17.0576L10.4319 16.3845L10.798 17.2652Z' fill='%230028FF'/%3e %3cpath d='M14.2575 10.0511L12.7732 10.139L12.8281 9.2398L14.2953 9.19128L14.2575 10.0511Z' fill='%23CEFF29'/%3e %3cpath d='M17.6473 10.3026L15.9036 10.109L15.925 9.29199L17.6535 9.53097L17.6473 10.3026Z' fill='%23C7FF30'/%3e %3cpath d='M14.4069 19.2402L14.2858 19.8033L13.7722 19.9062L13.9658 19.3262L14.4069 19.2402Z' fill='%2300009F'/%3e %3cpath d='M21.0904 12.4609L19.3945 12.1535L19.4088 11.3768L21.1138 11.7395L21.0904 12.4609Z' fill='%2360FF97'/%3e %3cpath d='M21.0566 16.7205L19.9443 16.7854L20.0677 16.8713L21.2285 16.8148L21.0566 16.7205Z' fill='%230040FF'/%3e %3cpath d='M15.6527 17.6224L15.3398 18.085L15.0303 18.4711L15.42 17.9912L15.6527 17.6224Z' fill='blue'/%3e %3cpath d='M13.2424 19.8436L13.1301 20.4526L12.5374 20.2456L12.7098 19.6184L13.2424 19.8436Z' fill='navy'/%3e %3cpath d='M10.6432 13.8322L9.90096 14.4083L9.75 13.3597L10.5137 12.8021L10.6432 13.8322Z' fill='%2316FFE1'/%3e %3cpath d='M22.4975 14.1412L20.9844 13.8719L21.047 13.1777L22.5827 13.5047L22.4975 14.1412Z' fill='%230FF8E7'/%3e %3cpath d='M17.7199 16.1522L16.923 16.403L16.8525 16.8709L17.7104 16.5998L17.7199 16.1522Z' fill='%230058FF'/%3e %3cpath d='M16.9229 16.4028L16.2948 16.7251L16.1582 17.2139L16.8524 16.8708L16.9229 16.4028Z' fill='%230048FF'/%3e %3cpath d='M19.7258 16.2806L18.6882 16.4036L18.74 16.7206L19.8293 16.5871L19.7258 16.2806Z' fill='%230058FF'/%3e %3cpath d='M10.4319 16.3849L10.0007 17.058L9.66479 16.0962L10.1304 15.425L10.4319 16.3849Z' fill='%230068FF'/%3e %3cpath d='M22.9183 16.5539L21.7695 16.4732L21.9437 16.1615L23.1284 16.2819L22.9183 16.5539Z' fill='%230060FF'/%3e %3cpath d='M22.701 16.7369L21.5896 16.6892L21.7699 16.4731L22.9186 16.5538L22.701 16.7369Z' fill='%230054FF'/%3e %3cpath d='M23.1283 16.2818L21.9436 16.1615L22.1074 15.7617L23.3257 15.9276L23.1283 16.2818Z' fill='%230074FF'/%3e %3cpath d='M18.6436 15.9758L17.7197 16.1522L17.7102 16.5998L18.6879 16.4034L18.6436 15.9758Z' fill='%23006CFF'/%3e %3cpath d='M16.295 16.7253L15.8577 17.1123L15.6526 17.6225L16.1584 17.2141L16.295 16.7253Z' fill='%230038FF'/%3e %3cpath d='M20.896 16.5228L19.8291 16.587L19.944 16.7853L21.0563 16.7203L20.896 16.5228Z' fill='%230054FF'/%3e %3cpath d='M19.4124 10.6168L17.647 10.3025L17.6532 9.53088L19.4051 9.89236L19.4124 10.6168Z' fill='%23C1FF36'/%3e %3cpath d='M13.772 19.9065L13.7193 20.4952L13.1301 20.453L13.2424 19.844L13.772 19.9065Z' fill='%23000084'/%3e %3cpath d='M11.4875 11.3575L10.4553 11.768L10.4701 10.7557L11.4998 10.3752L11.4875 11.3575Z' fill='%2397FF60'/%3e %3cpath d='M22.4812 16.8263L21.4075 16.8039L21.5894 16.6891L22.7009 16.7368L22.4812 16.8263Z' fill='%23004CFF'/%3e %3cpath d='M12.773 10.1393L11.4998 10.3756L11.5718 9.44116L12.8279 9.24011L12.773 10.1393Z' fill='%23D1FF26'/%3e %3cpath d='M23.326 15.9275L22.1077 15.7617L22.2569 15.2837L23.5057 15.4996L23.326 15.9275Z' fill='%230090FF'/%3e %3cpath d='M22.5828 13.5045L21.0471 13.1776L21.0907 12.4608L22.6415 12.845L22.5828 13.5045Z' fill='%2336FFC1'/%3e %3cpath d='M21.1139 11.7395L19.4089 11.3768L19.4126 10.6166L21.1162 11.0315L21.1139 11.7395Z' fill='%238DFF6A'/%3e %3cpath d='M15.9249 9.29178L14.2952 9.19141L14.362 8.39941L15.9609 8.53893L15.9249 9.29178Z' fill='%23FFEA00'/%3e %3cpath d='M15.3394 18.0851L15.2042 18.5868L14.823 18.9923L15.03 18.4712L15.3394 18.0851Z' fill='blue'/%3e %3cpath d='M22.2647 16.8201L21.2283 16.8149L21.4074 16.8043L22.4811 16.8266L22.2647 16.8201Z' fill='%230050FF'/%3e %3cpath d='M14.8232 18.9924L14.7705 19.5361L14.2856 19.8034L14.4067 19.2403L14.8232 18.9924Z' fill='%230000C4'/%3e %3cpath d='M23.5058 15.4997L22.2571 15.2837L22.3882 14.7391L23.6634 15.0087L23.5058 15.4997Z' fill='%2300B0FF'/%3e %3cpath d='M17.6536 9.53087L15.925 9.29189L15.9611 8.53906L17.6611 8.81903L17.6536 9.53087Z' fill='%23FBF100'/%3e %3cpath d='M19.6365 15.8729L18.644 15.976L18.6883 16.4036L19.7258 16.2807L19.6365 15.8729Z' fill='%230080FF'/%3e %3cpath d='M14.2953 9.19128L12.8281 9.23979L12.927 8.41112L14.3622 8.39929L14.2953 9.19128Z' fill='%23FFE200'/%3e %3cpath d='M10.5137 12.8022L9.74995 13.3598L9.68188 12.3046L10.4553 11.7682L10.5137 12.8022Z' fill='%2353FFA4'/%3e %3cpath d='M10.1304 15.4247L9.66486 16.0958L9.40942 15.0737L9.90108 14.4083L10.1304 15.4247Z' fill='%2300B0FF'/%3e %3cpath d='M15.8576 17.1122L15.6123 17.5528L15.3396 18.085L15.6525 17.6224L15.8576 17.1122Z' fill='%23002CFF'/%3e %3cpath d='M20.7512 16.2266L19.7253 16.2804L19.8288 16.5869L20.8958 16.5227L20.7512 16.2266Z' fill='%230070FF'/%3e %3cpath d='M11.9556 19.8803L11.9063 20.503L11.3254 19.996L11.398 19.3646L11.9556 19.8803Z' fill='%2300009F'/%3e %3cpath d='M11.3976 19.3641L11.325 19.9955L10.7834 19.3496L10.8778 18.7112L11.3976 19.3641Z' fill='%230000C8'/%3e %3cpath d='M17.729 15.5952L16.9827 15.8177L16.9231 16.4028L17.72 16.1521L17.729 15.5952Z' fill='%23008CFF'/%3e %3cpath d='M22.057 16.7172L21.0564 16.7201L21.2283 16.8145L22.2647 16.8198L22.057 16.7172Z' fill='%23005CFF'/%3e %3cpath d='M16.9827 15.818L16.4096 16.1125L16.2949 16.7255L16.9231 16.4032L16.9827 15.818Z' fill='%23007CFF'/%3e %3cpath d='M23.6634 15.0087L22.3882 14.7391L22.4977 14.1412L23.7947 14.4666L23.6634 15.0087Z' fill='%2300D8FF'/%3e %3cpath d='M12.5374 20.2456L12.5123 20.8585L11.906 20.5025L11.9553 19.8798L12.5374 20.2456Z' fill='%23000089'/%3e %3cpath d='M14.2854 19.8035L14.2906 20.3706L13.7192 20.4951L13.7719 19.9064L14.2854 19.8035Z' fill='%2300009B'/%3e %3cpath d='M22.6413 12.8453L21.0906 12.4611L21.1139 11.7396L22.6717 12.1794L22.6413 12.8453Z' fill='%2363FF94'/%3e %3cpath d='M10.878 18.7115L10.7836 19.3498L10.2944 18.5803L10.4085 17.9365L10.878 18.7115Z' fill='%230000FA'/%3e %3cpath d='M18.6083 15.4476L17.729 15.5954L17.72 16.1523L18.6439 15.9759L18.6083 15.4476Z' fill='%23009CFF'/%3e %3cpath d='M19.4055 9.89242L17.6536 9.53094L17.661 8.81909L19.3874 9.22278L19.4055 9.89242Z' fill='%23F1FC06'/%3e %3cpath d='M21.1164 11.0314L19.4128 10.6165L19.4055 9.89209L21.0976 10.3552L21.1164 11.0314Z' fill='%23BEFF39'/%3e %3cpath d='M16.4099 16.1125L16.0298 16.4723L15.8579 17.1125L16.2952 16.7256L16.4099 16.1125Z' fill='%230070FF'/%3e %3cpath d='M13.1303 20.4528L13.1297 21.0547L12.5125 20.8587L12.5376 20.2458L13.1303 20.4528Z' fill='navy'/%3e %3cpath d='M21.8634 16.5206L20.8962 16.5226L21.0565 16.7201L22.0571 16.7171L21.8634 16.5206Z' fill='%23006CFF'/%3e %3cpath d='M11.4998 10.3755L10.4702 10.756L10.5588 9.79116L11.5719 9.44104L11.4998 10.3755Z' fill='%23D4FF23'/%3e %3cpath d='M23.7945 14.4668L22.4976 14.1415L22.5828 13.5049L23.8963 13.887L23.7945 14.4668Z' fill='%2319FFDE'/%3e %3cpath d='M12.8279 9.23967L11.5718 9.44072L11.7025 8.57845L12.9267 8.41101L12.8279 9.23967Z' fill='%23FFDB00'/%3e %3cpath d='M10.4086 17.9363L10.2945 18.58L9.86963 17.7048L10.0008 17.0576L10.4086 17.9363Z' fill='%230024FF'/%3e %3cpath d='M20.6261 15.8385L19.636 15.8727L19.7254 16.2804L20.7512 16.2266L20.6261 15.8385Z' fill='%230094FF'/%3e %3cpath d='M19.5633 15.3733L18.6082 15.4476L18.6437 15.9758L19.6361 15.8727L19.5633 15.3733Z' fill='%2300ACFF'/%3e %3cpath d='M15.9612 8.53908L14.3623 8.39956L14.4569 7.69666L16.011 7.87059L15.9612 8.53908Z' fill='%23FFB200'/%3e %3cpath d='M9.90084 14.4086L9.40918 15.074L9.24121 14.016L9.74989 13.3601L9.90084 14.4086Z' fill='%2313FCE4'/%3e %3cpath d='M15.2044 18.5868L15.2144 19.1093L14.7705 19.5359L14.8232 18.9923L15.2044 18.5868Z' fill='%230000F1'/%3e %3cpath d='M17.6609 8.81882L15.9609 8.53885L16.0108 7.87036L17.6693 8.18577L17.6609 8.81882Z' fill='%23FFBD00'/%3e %3cpath d='M15.6123 17.5527L15.5404 18.032L15.2043 18.5867L15.3396 18.0849L15.6123 17.5527Z' fill='%230020FF'/%3e %3cpath d='M22.6718 12.1791L21.114 11.7393L21.1164 11.0314L22.6729 11.5237L22.6718 12.1791Z' fill='%238DFF6A'/%3e %3cpath d='M23.5883 16.8344L22.7009 16.737L22.9185 16.554L23.8307 16.6826L23.5883 16.8344Z' fill='%23006CFF'/%3e %3cpath d='M23.8306 16.6828L22.9185 16.5541L23.1286 16.2821L24.0644 16.4485L23.8306 16.6828Z' fill='%230078FF'/%3e %3cpath d='M10.4555 11.7682L9.68213 12.3046L9.69959 11.269L10.4703 10.7559L10.4555 11.7682Z' fill='%2397FF60'/%3e %3cpath d='M23.3433 16.9001L22.481 16.8265L22.7007 16.7371L23.588 16.8345L23.3433 16.9001Z' fill='%230068FF'/%3e %3cpath d='M24.0643 16.448L23.1284 16.2816L23.3258 15.9274L24.2839 16.137L24.0643 16.448Z' fill='%23008CFF'/%3e %3cpath d='M14.3622 8.39923L12.927 8.41106L13.0678 7.67517L14.4568 7.69631L14.3622 8.39923Z' fill='%23FFA700'/%3e %3cpath d='M17.7371 14.9423L17.0298 15.129L16.9827 15.8177L17.7289 15.5952L17.7371 14.9423Z' fill='%2300C4FF'/%3e %3cpath d='M13.7194 20.495L13.7431 21.0854L13.1296 21.0547L13.1302 20.4528L13.7194 20.495Z' fill='%23000084'/%3e %3cpath d='M14.7703 19.536L14.8299 20.0807L14.2905 20.3704L14.2854 19.8033L14.7703 19.536Z' fill='%230000BB'/%3e %3cpath d='M21.6881 16.2348L20.7512 16.2266L20.8958 16.5227L21.8629 16.5207L21.6881 16.2348Z' fill='%230084FF'/%3e %3cpath d='M16.0295 16.4723L15.8409 16.8865L15.6123 17.553L15.8576 17.1124L16.0295 16.4723Z' fill='%230068FF'/%3e %3cpath d='M23.8963 13.8867L22.5828 13.5046L22.6414 12.8451L23.9658 13.2836L23.8963 13.8867Z' fill='%233CFFBA'/%3e %3cpath d='M18.5823 14.8315L17.737 14.9426L17.7288 15.5956L18.6081 15.4478L18.5823 14.8315Z' fill='%2300D0FF'/%3e %3cpath d='M10.001 17.0576L9.86982 17.7048L9.51978 16.7445L9.66509 16.0958L10.001 17.0576Z' fill='%230064FF'/%3e %3cpath d='M23.1022 16.8775L22.2646 16.8198L22.4811 16.8263L23.3434 16.8999L23.1022 16.8775Z' fill='%230068FF'/%3e %3cpath d='M17.0296 15.1293L16.499 15.3895L16.4094 16.1124L16.9825 15.8179L17.0296 15.1293Z' fill='%2300B8FF'/%3e %3cpath d='M24.2838 16.1372L23.3257 15.9275L23.5054 15.4996L24.4836 15.7571L24.2838 16.1372Z' fill='%2300A4FF'/%3e %3cpath d='M21.0975 10.3554L19.4055 9.8923L19.3875 9.22266L21.0578 9.72855L21.0975 10.3554Z' fill='%23EBFF0C'/%3e %3cpath d='M19.3873 9.22253L17.6609 8.81884L17.6693 8.18579L19.3589 8.62552L19.3873 9.22253Z' fill='%23FFC800'/%3e %3cpath d='M20.5241 15.368L19.5635 15.3735L19.6363 15.873L20.6264 15.8388L20.5241 15.368Z' fill='%2300BCFF'/%3e %3cpath d='M22.8707 16.7676L22.0569 16.7173L22.2646 16.8199L23.1022 16.8776L22.8707 16.7676Z' fill='%230074FF'/%3e %3cpath d='M24.4836 15.7573L23.5054 15.4998L23.6629 15.0088L24.6585 15.3175L24.4836 15.7573Z' fill='%2300C4FF'/%3e %3cpath d='M19.5092 14.7942L18.5825 14.8313L18.6084 15.4476L19.5635 15.3733L19.5092 14.7942Z' fill='%2300DCFE'/%3e %3cpath d='M16.4993 15.3893L16.1635 15.7167L16.0295 16.472L16.4096 16.1122L16.4993 15.3893Z' fill='%2300B0FF'/%3e %3cpath d='M22.6727 11.524L21.1162 11.0317L21.0974 10.3555L22.6443 10.896L22.6727 11.524Z' fill='%23B7FF40'/%3e %3cpath d='M21.5367 15.8665L20.6262 15.8387L20.7514 16.2268L21.6882 16.2351L21.5367 15.8665Z' fill='%2300A4FF'/%3e %3cpath d='M23.9655 13.2838L22.6411 12.8453L22.6714 12.1794L24.0007 12.6726L23.9655 13.2838Z' fill='%2363FF94'/%3e %3cpath d='M14.2908 20.3704L14.3381 20.949L13.7432 21.0854L13.7195 20.4949L14.2908 20.3704Z' fill='%23000096'/%3e %3cpath d='M9.74991 13.3597L9.24123 14.0156L9.16577 12.9476L9.68184 12.3046L9.74991 13.3597Z' fill='%2353FFA4'/%3e %3cpath d='M11.572 9.44114L10.5588 9.79126L10.7199 8.8991L11.7027 8.57886L11.572 9.44114Z' fill='gold'/%3e %3cpath d='M16.0107 7.87056L14.4565 7.69662L14.5767 7.10217L16.0733 7.3048L16.0107 7.87056Z' fill='%23FF7A00'/%3e %3cpath d='M12.9269 8.41107L11.7026 8.57851L11.8894 7.81158L13.0677 7.67517L12.9269 8.41107Z' fill='%23FF9C00'/%3e %3cpath d='M17.6695 8.18608L16.011 7.87067L16.0735 7.30493L17.6788 7.64922L17.6695 8.18608Z' fill='%23FF8900'/%3e %3cpath d='M22.655 16.5723L21.8633 16.5206L22.057 16.7171L22.8709 16.7674L22.655 16.5723Z' fill='%230084FF'/%3e %3cpath d='M11.9058 20.5028L11.9763 21.0714L11.3966 20.5653L11.325 19.9957L11.9058 20.5028Z' fill='%2300009F'/%3e %3cpath d='M24.6587 15.3175L23.6631 15.0088L23.7945 14.4667L24.8043 14.8288L24.6587 15.3175Z' fill='%2300E4F8'/%3e %3cpath d='M11.3252 19.9959L11.3968 20.5654L10.8564 19.9211L10.7837 19.35L11.3252 19.9959Z' fill='%230000C8'/%3e %3cpath d='M15.5406 18.0323L15.606 18.5322L15.2146 19.1095L15.2046 18.587L15.5406 18.0323Z' fill='%230018FF'/%3e %3cpath d='M9.66508 16.0961L9.51977 16.7447L9.25366 15.722L9.40964 15.0739L9.66508 16.0961Z' fill='%2300ACFF'/%3e %3cpath d='M12.5123 20.8584L12.5817 21.4268L11.9765 21.0711L11.906 20.5024L12.5123 20.8584Z' fill='%23000089'/%3e %3cpath d='M15.8408 16.8866L15.822 17.3408L15.5403 18.0324L15.6122 17.5531L15.8408 16.8866Z' fill='%23005CFF'/%3e %3cpath d='M17.7441 14.2092L17.0628 14.3537L17.0295 15.129L17.7368 14.9422L17.7441 14.2092Z' fill='%2316FFE1'/%3e %3cpath d='M15.2144 19.1094L15.3238 19.6315L14.8301 20.0808L14.7705 19.5361L15.2144 19.1094Z' fill='%230000ED'/%3e %3cpath d='M21.0577 9.72862L19.3873 9.22273L19.3589 8.62573L20.9979 9.16784L21.0577 9.72862Z' fill='gold'/%3e %3cpath d='M18.5669 14.1423L17.7443 14.2095L17.7371 14.9426L18.5823 14.8315L18.5669 14.1423Z' fill='%231CFFDB'/%3e %3cpath d='M10.4702 10.7558L9.69946 11.269L9.80303 10.2794L10.5588 9.79102L10.4702 10.7558Z' fill='%23D7FF1F'/%3e %3cpath d='M10.7836 19.3498L10.8563 19.9209L10.3682 19.1535L10.2944 18.5802L10.7836 19.3498Z' fill='%230000FA'/%3e %3cpath d='M20.4474 14.8258L19.5093 14.7941L19.5636 15.3732L20.5242 15.3677L20.4474 14.8258Z' fill='%2302E8F4'/%3e %3cpath d='M14.4563 7.69659L13.0674 7.67545L13.2471 7.05273L14.5764 7.10215L14.4563 7.69659Z' fill='%23FF6F00'/%3e %3cpath d='M19.359 8.62564L17.6694 8.18591L17.6786 7.64905L19.3208 8.11761L19.359 8.62564Z' fill='%23FF9800'/%3e %3cpath d='M17.0634 14.354L16.5614 14.5744L16.4995 15.3895L17.0301 15.1293L17.0634 14.354Z' fill='%2313FCE4'/%3e %3cpath d='M22.4596 16.2967L21.688 16.2347L21.8629 16.5207L22.6545 16.5724L22.4596 16.2967Z' fill='%23009CFF'/%3e %3cpath d='M16.1633 15.7167L16.0188 16.1009L15.8408 16.8862L16.0294 16.472L16.1633 15.7167Z' fill='%2300A8FF'/%3e %3cpath d='M21.413 15.4238L20.5242 15.3678L20.6265 15.8385L21.537 15.8662L21.413 15.4238Z' fill='%2300CCFF'/%3e %3cpath d='M24.8045 14.8286L23.7947 14.4665L23.8964 13.8867L24.9169 14.3031L24.8045 14.8286Z' fill='%231FFFD7'/%3e %3cpath d='M13.1295 21.0545L13.1978 21.6233L12.5816 21.4268L12.5122 20.8584L13.1295 21.0545Z' fill='navy'/%3e %3cpath d='M24.0009 12.6726L22.6716 12.1795L22.6727 11.524L24.0006 12.0687L24.0009 12.6726Z' fill='%238DFF6A'/%3e %3cpath d='M22.6443 10.8962L21.0974 10.3556L21.0576 9.72876L22.5869 10.3119L22.6443 10.8962Z' fill='%23E1FF16'/%3e %3cpath d='M19.4748 14.1497L18.5669 14.1421L18.5823 14.8312L19.509 14.7941L19.4748 14.1497Z' fill='%2323FFD4'/%3e %3cpath d='M10.2946 18.5802L10.3683 19.1535L9.94431 18.281L9.86963 17.705L10.2946 18.5802Z' fill='%230024FF'/%3e %3cpath d='M24.19 16.9715L23.5881 16.8346L23.8305 16.6827L24.4458 16.8482L24.19 16.9715Z' fill='%230084FF'/%3e %3cpath d='M14.8301 20.0807L14.8996 20.6475L14.338 20.949L14.2908 20.3704L14.8301 20.0807Z' fill='%230000BB'/%3e %3cpath d='M23.9314 17.0153L23.3433 16.9001L23.5881 16.8345L24.1899 16.9714L23.9314 17.0153Z' fill='%230080FF'/%3e %3cpath d='M24.4459 16.848L23.8306 16.6825L24.0645 16.4482L24.6927 16.6483L24.4459 16.848Z' fill='%230090FF'/%3e %3cpath d='M23.6767 16.9788L23.1021 16.8778L23.3432 16.9002L23.9314 17.0154L23.6767 16.9788Z' fill='%230084FF'/%3e %3cpath d='M24.6924 16.6482L24.0642 16.4481L24.2838 16.1371L24.924 16.3771L24.6924 16.6482Z' fill='%2300A0FF'/%3e %3cpath d='M16.5612 14.5743L16.2555 14.8649L16.1636 15.7169L16.4994 15.3895L16.5612 14.5743Z' fill='%230CF4EB'/%3e %3cpath d='M9.40948 15.0739L9.25349 15.7221L9.07861 14.6616L9.2415 14.0159L9.40948 15.0739Z' fill='%2313FCE4'/%3e %3cpath d='M22.2911 15.9473L21.5369 15.8663L21.6883 16.2349L22.46 16.2969L22.2911 15.9473Z' fill='%2300B8FF'/%3e %3cpath d='M17.6784 7.64898L16.0732 7.30469L16.147 6.85779L17.6882 7.22345L17.6784 7.64898Z' fill='%23FF6000'/%3e %3cpath d='M24.9167 14.3031L23.8962 13.8867L23.9657 13.2836L24.993 13.754L24.9167 14.3031Z' fill='%2343FFB4'/%3e %3cpath d='M9.68183 12.3047L9.16577 12.9478L9.18577 11.8964L9.69929 11.2692L9.68183 12.3047Z' fill='%2397FF60'/%3e %3cpath d='M13.7431 21.0852L13.8104 21.6552L13.1979 21.6233L13.1296 21.0544L13.7431 21.0852Z' fill='%23000084'/%3e %3cpath d='M16.0733 7.3049L14.5767 7.10227L14.7195 6.6333L16.147 6.858L16.0733 7.3049Z' fill='%23FF4E00'/%3e %3cpath d='M20.9977 9.16757L19.3588 8.62545L19.3206 8.11743L20.9193 8.68813L20.9977 9.16757Z' fill='%23FFAB00'/%3e %3cpath d='M23.4323 16.8623L22.8706 16.7676L23.102 16.8776L23.6767 16.9786L23.4323 16.8623Z' fill='%23008CFF'/%3e %3cpath d='M20.3982 14.2265L19.4749 14.15L19.5091 14.7944L20.4472 14.8261L20.3982 14.2265Z' fill='%232CFFCA'/%3e %3cpath d='M24.9241 16.3772L24.2839 16.1371L24.4837 15.7571L25.1347 16.0413L24.9241 16.3772Z' fill='%2300B8FF'/%3e %3cpath d='M11.7028 8.57856L10.72 8.8988L10.9502 8.10331L11.8896 7.81165L11.7028 8.57856Z' fill='%23FF9400'/%3e %3cpath d='M13.0676 7.67522L11.8894 7.81162L12.1281 7.16134L13.2473 7.05249L13.0676 7.67522Z' fill='%23FF6400'/%3e %3cpath d='M21.3194 14.9185L20.447 14.8259L20.5238 15.3678L21.4126 15.4239L21.3194 14.9185Z' fill='%230CF4EB'/%3e %3cpath d='M18.5626 13.3975L17.7504 13.4147L17.7444 14.2093L18.567 14.1421L18.5626 13.3975Z' fill='%2350FFA7'/%3e %3cpath d='M17.7503 13.4147L17.0813 13.5114L17.063 14.3538L17.7443 14.2092L17.7503 13.4147Z' fill='%234DFFAA'/%3e %3cpath d='M24.0008 12.0689L22.6729 11.5242L22.6445 10.8961L23.965 11.4881L24.0008 12.0689Z' fill='%23B4FF43'/%3e %3cpath d='M15.822 17.3406L15.9338 17.817L15.6056 18.5321L15.5403 18.0322L15.822 17.3406Z' fill='%230058FF'/%3e %3cpath d='M19.3206 8.11749L17.6785 7.64892L17.6882 7.22339L19.2735 7.71267L19.3206 8.11749Z' fill='%23FF6F00'/%3e %3cpath d='M9.86958 17.7049L9.94427 18.2809L9.59508 17.3239L9.51953 16.7445L9.86958 17.7049Z' fill='%230068FF'/%3e %3cpath d='M22.5869 10.3115L21.0576 9.72838L20.9978 9.1676L22.5018 9.78666L22.5869 10.3115Z' fill='%23FFE200'/%3e %3cpath d='M15.6059 18.5322L15.7593 19.0323L15.324 19.6317L15.2146 19.1095L15.6059 18.5322Z' fill='%230014FF'/%3e %3cpath d='M16.019 16.1011L16.0417 16.528L15.8223 17.3406L15.8411 16.8864L16.019 16.1011Z' fill='%2300A0FF'/%3e %3cpath d='M23.2042 16.6691L22.6545 16.5725L22.8705 16.7676L23.4322 16.8624L23.2042 16.6691Z' fill='%23009CFF'/%3e %3cpath d='M19.4621 13.4565L18.5627 13.3977L18.5672 14.1423L19.4751 14.1499L19.4621 13.4565Z' fill='%2353FFA4'/%3e %3cpath d='M25.1346 16.0415L24.4836 15.7573L24.6586 15.3175L25.3187 15.6492L25.1346 16.0415Z' fill='%2300D4FF'/%3e %3cpath d='M14.5767 7.10215L13.2473 7.05273L13.4616 6.56104L14.7195 6.63316L14.5767 7.10215Z' fill='%23FF3F00'/%3e %3cpath d='M10.559 9.79097L9.80322 10.2794L9.99136 9.36175L10.72 8.8988L10.559 9.79097Z' fill='%23FFD300'/%3e %3cpath d='M17.0813 13.5115L16.5932 13.6872L16.561 14.5742L17.063 14.3538L17.0813 13.5115Z' fill='%2349FFAD'/%3e %3cpath d='M22.1525 15.5321L21.4126 15.4238L21.5366 15.8663L22.2908 15.9472L22.1525 15.5321Z' fill='%2300DCFE'/%3e %3cpath d='M24.9931 13.7544L23.9658 13.284L24.001 12.6727L25.031 13.1955L24.9931 13.7544Z' fill='%2366FF90'/%3e %3cpath d='M16.2553 14.8647L16.1408 15.2159L16.0188 16.101L16.1634 15.7168L16.2553 14.8647Z' fill='%2309F0EE'/%3e %3cpath d='M14.338 20.9491L14.4043 21.5209L13.8104 21.6555L13.7432 21.0855L14.338 20.9491Z' fill='%2300009B'/%3e %3cpath d='M15.3236 19.6316L15.4133 20.1869L14.8992 20.6476L14.8298 20.0808L15.3236 19.6316Z' fill='%230000E8'/%3e %3cpath d='M22.9988 16.4034L22.4602 16.2968L22.6551 16.5724L23.2047 16.669L22.9988 16.4034Z' fill='%2300B0FF'/%3e %3cpath d='M25.3189 15.649L24.6587 15.3173L24.8043 14.8286L25.4718 15.2099L25.3189 15.649Z' fill='%230CF4EB'/%3e %3cpath d='M21.2594 14.3627L20.3979 14.2263L20.4469 14.826L21.3193 14.9185L21.2594 14.3627Z' fill='%2333FFC4'/%3e %3cpath d='M20.3783 13.5842L19.4617 13.4565L19.4747 14.15L20.3981 14.2264L20.3783 13.5842Z' fill='%2356FFA0'/%3e %3cpath d='M17.6884 7.22365L16.1472 6.85799L16.2303 6.54309L17.6984 6.92188L17.6884 7.22365Z' fill='%23FF3B00'/%3e %3cpath d='M11.9765 21.0714L12.0853 21.5817L11.5116 21.0808L11.3967 20.5653L11.9765 21.0714Z' fill='%230000A8'/%3e %3cpath d='M23.9648 11.488L22.6443 10.896L22.5869 10.3118L23.8939 10.9454L23.9648 11.488Z' fill='%23D7FF1F'/%3e %3cpath d='M20.9195 8.68842L19.3208 8.11772L19.2737 7.71289L20.8242 8.30369L20.9195 8.68842Z' fill='%23FF8600'/%3e %3cpath d='M11.3969 20.5651L11.5118 21.0806L10.9771 20.4433L10.8564 19.9208L11.3969 20.5651Z' fill='%230000CD'/%3e %3cpath d='M9.24126 14.0156L9.07837 14.6613L9 13.5888L9.16581 12.9475L9.24126 14.0156Z' fill='%2353FFA4'/%3e %3cpath d='M16.5932 13.6875L16.3023 13.9376L16.2554 14.865L16.5611 14.5744L16.5932 13.6875Z' fill='%2346FFB1'/%3e %3cpath d='M16.1473 6.85773L14.7197 6.63304L14.8817 6.30347L16.2304 6.54283L16.1473 6.85773Z' fill='%23FF2900'/%3e %3cpath d='M9.51953 16.7446L9.59507 17.3239L9.32971 16.305L9.25342 15.7219L9.51953 16.7446Z' fill='%2300B0FF'/%3e %3cpath d='M18.5694 12.6169L17.7552 12.5793L17.7505 13.4149L18.5626 13.3977L18.5694 12.6169Z' fill='%2380FF77'/%3e %3cpath d='M12.5815 21.4269L12.6842 21.9339L12.0852 21.5815L11.9763 21.0712L12.5815 21.4269Z' fill='%23000092'/%3e %3cpath d='M22.5021 9.78697L20.9982 9.16791L20.9197 8.68848L22.3913 9.33564L22.5021 9.78697Z' fill='%23FFB900'/%3e %3cpath d='M17.7552 12.5791L17.0843 12.6237L17.0815 13.5114L17.7505 13.4147L17.7552 12.5791Z' fill='%2380FF77'/%3e %3cpath d='M22.0482 15.062L21.3193 14.9186L21.4126 15.424L22.1525 15.5323L22.0482 15.062Z' fill='%2316FFE1'/%3e %3cpath d='M19.2738 7.71268L17.6885 7.2234L17.6985 6.92163L19.219 7.42276L19.2738 7.71268Z' fill='%23FF4E00'/%3e %3cpath d='M25.0308 13.1953L24.0007 12.6725L24.0005 12.0687L25.0292 12.6409L25.0308 13.1953Z' fill='%238AFF6D'/%3e %3cpath d='M9.69956 11.269L9.18604 11.8962L9.30216 10.8882L9.80312 10.2794L9.69956 11.269Z' fill='%23D7FF1F'/%3e %3cpath d='M10.8563 19.9207L10.9769 20.4433L10.494 19.6845L10.3682 19.1533L10.8563 19.9207Z' fill='blue'/%3e %3cpath d='M22.8203 16.072L22.2913 15.9473L22.4601 16.2969L22.9987 16.4035L22.8203 16.072Z' fill='%2300C8FF'/%3e %3cpath d='M19.4705 12.7317L18.5692 12.6167L18.5625 13.3975L19.4618 13.4563L19.4705 12.7317Z' fill='%2380FF77'/%3e %3cpath d='M25.4717 15.2101L24.8042 14.8288L24.9166 14.3033L25.5895 14.7351L25.4717 15.2101Z' fill='%2329FFCE'/%3e %3cpath d='M13.2471 7.0526L12.1279 7.16145L12.4129 6.64654L13.4614 6.56091L13.2471 7.0526Z' fill='%23FF3000'/%3e %3cpath d='M11.8896 7.81189L10.9502 8.10356L11.2446 7.42686L12.1283 7.16162L11.8896 7.81189Z' fill='%23FF5900'/%3e %3cpath d='M24.2003 17.1639L23.9316 17.0151L24.1901 16.9712L24.4629 17.139L24.2003 17.1639Z' fill='%230098FF'/%3e %3cpath d='M24.4628 17.1393L24.1899 16.9715L24.4458 16.8481L24.7227 17.0413L24.4628 17.1393Z' fill='%23009CFF'/%3e %3cpath d='M13.198 21.6235L13.2944 22.1292L12.6844 21.934L12.5818 21.427L13.198 21.6235Z' fill='%23000084'/%3e %3cpath d='M23.9414 17.1151L23.677 16.9786L23.9316 17.0152L24.2002 17.164L23.9414 17.1151Z' fill='%230098FF'/%3e %3cpath d='M17.0842 12.6238L16.5945 12.7514L16.5933 13.6872L17.0814 13.5114L17.0842 12.6238Z' fill='%2380FF77'/%3e %3cpath d='M24.7227 17.0412L24.4458 16.8481L24.6926 16.6484L24.9734 16.8724L24.7227 17.0412Z' fill='%2300A4FF'/%3e %3cpath d='M16.0414 16.5281L16.1897 16.9808L15.9339 17.817L15.822 17.3406L16.0414 16.5281Z' fill='%23009CFF'/%3e %3cpath d='M14.8996 20.6477L14.965 21.2219L14.4044 21.521L14.3381 20.9492L14.8996 20.6477Z' fill='%230000BB'/%3e %3cpath d='M15.9342 17.8169L16.1246 18.2958L15.7594 19.032L15.606 18.5319L15.9342 17.8169Z' fill='%230054FF'/%3e %3cpath d='M14.7194 6.63293L13.4614 6.5608L13.7049 6.21484L14.8813 6.30336L14.7194 6.63293Z' fill='%23FF1600'/%3e %3cpath d='M21.2349 13.7707L20.3784 13.5842L20.3981 14.2265L21.2596 14.3629L21.2349 13.7707Z' fill='%235AFF9D'/%3e %3cpath d='M23.6927 16.9936L23.4324 16.8624L23.6768 16.9787L23.9412 17.1151L23.6927 16.9936Z' fill='%2300A0FF'/%3e %3cpath d='M10.3683 19.1532L10.4942 19.6844L10.0749 18.8221L9.94434 18.2808L10.3683 19.1532Z' fill='%230028FF'/%3e %3cpath d='M16.1408 15.2158L16.192 15.6142L16.0414 16.5279L16.0188 16.1009L16.1408 15.2158Z' fill='%2306ECF1'/%3e %3cpath d='M23.8938 10.9454L22.5868 10.3117L22.5017 9.78687L23.7896 10.4555L23.8938 10.9454Z' fill='%23FBF100'/%3e %3cpath d='M20.3887 12.9159L19.4704 12.7319L19.4617 13.4565L20.3783 13.5841L20.3887 12.9159Z' fill='%2380FF77'/%3e %3cpath d='M24.9734 16.8722L24.6926 16.6482L24.9242 16.3772L25.2084 16.6368L24.9734 16.8722Z' fill='%2300B4FF'/%3e %3cpath d='M22.674 15.6827L22.1528 15.5322L22.2912 15.9473L22.8203 16.072L22.674 15.6827Z' fill='%2302E8F4'/%3e %3cpath d='M20.8243 8.30368L19.2738 7.71288L19.219 7.42297L20.7148 8.02465L20.8243 8.30368Z' fill='%23FF6400'/%3e %3cpath d='M10.7199 8.89888L9.99121 9.36182L10.2601 8.54082L10.9501 8.10339L10.7199 8.89888Z' fill='%23FF9100'/%3e %3cpath d='M25.5896 14.735L24.9167 14.3033L24.993 13.7542L25.6691 14.2361L25.5896 14.735Z' fill='%2346FFB1'/%3e %3cpath d='M21.9814 14.5481L21.2598 14.3627L21.3196 14.9185L22.0485 15.0619L21.9814 14.5481Z' fill='%2339FFBE'/%3e %3cpath d='M17.6981 6.92174L16.23 6.54295L16.3203 6.36987L17.7082 6.75301L17.6981 6.92174Z' fill='%23FF2200'/%3e %3cpath d='M25.0292 12.6407L24.0005 12.0686L23.9646 11.4878L24.9878 12.1052L25.0292 12.6407Z' fill='%23ADFF49'/%3e %3cpath d='M16.3023 13.9373L16.203 14.253L16.1409 15.2158L16.2553 14.8646L16.3023 13.9373Z' fill='%2343FFB4'/%3e %3cpath d='M23.4611 16.8024L23.2046 16.6692L23.4326 16.8624L23.693 16.9936L23.4611 16.8024Z' fill='%2300B0FF'/%3e %3cpath d='M22.3913 9.33524L20.9197 8.68808L20.8245 8.30334L22.2575 8.96999L22.3913 9.33524Z' fill='%23FF9800'/%3e %3cpath d='M15.7593 19.0319L15.8669 19.5764L15.4137 20.1866L15.324 19.6313L15.7593 19.0319Z' fill='%230014FF'/%3e %3cpath d='M18.5872 11.8202L17.7583 11.7245L17.7551 12.579L18.5694 12.6166L18.5872 11.8202Z' fill='%23B4FF43'/%3e %3cpath d='M25.2085 16.6368L24.9243 16.3772L25.1349 16.0414L25.4221 16.3405L25.2085 16.6368Z' fill='%2300C8FF'/%3e %3cpath d='M13.8104 21.6555L13.9006 22.1619L13.2944 22.1293L13.198 21.6237L13.8104 21.6555Z' fill='%2300008D'/%3e %3cpath d='M19.2189 7.42292L17.6985 6.92179L17.7085 6.75305L19.1579 7.25669L19.2189 7.42292Z' fill='%23FF3800'/%3e %3cpath d='M9.25349 15.722L9.32978 16.3051L9.15551 15.2486L9.07861 14.6615L9.25349 15.722Z' fill='%2313FCE4'/%3e %3cpath d='M19.5009 11.9949L18.5872 11.8202L18.5693 12.6166L19.4706 12.7316L19.5009 11.9949Z' fill='%23ADFF49'/%3e %3cpath d='M17.7582 11.7247L17.071 11.7144L17.0841 12.6238L17.755 12.5792L17.7582 11.7247Z' fill='%23B7FF40'/%3e %3cpath d='M16.2301 6.54267L14.8813 6.30331L15.0583 6.12354L16.3204 6.3696L16.2301 6.54267Z' fill='%23F60B00'/%3e %3cpath d='M16.5944 12.7513L16.3025 12.9585L16.3022 13.9373L16.5932 13.6871L16.5944 12.7513Z' fill='%2380FF77'/%3e %3cpath d='M9.16581 12.9479L9 13.5892L9.02121 12.5317L9.18581 11.8965L9.16581 12.9479Z' fill='%2397FF60'/%3e %3cpath d='M23.2516 16.5461L22.9985 16.4034L23.2044 16.6691L23.461 16.8023L23.2516 16.5461Z' fill='%2300C0FF'/%3e %3cpath d='M9.9444 18.2808L10.0749 18.8221L9.72973 17.8764L9.59521 17.3237L9.9444 18.2808Z' fill='%230068FF'/%3e %3cpath d='M22.5636 15.2453L22.0486 15.062L22.1528 15.5323L22.6739 15.6828L22.5636 15.2453Z' fill='%231FFFD7'/%3e %3cpath d='M25.4217 16.3406L25.1345 16.0415L25.3187 15.6492L25.6082 15.9908L25.4217 16.3406Z' fill='%2300E0FB'/%3e %3cpath d='M21.2463 13.1575L20.3887 12.9159L20.3784 13.5842L21.2349 13.7707L21.2463 13.1575Z' fill='%2380FF77'/%3e %3cpath d='M25.669 14.2359L24.9929 13.754L25.0309 13.1951L25.7078 13.7257L25.669 14.2359Z' fill='%2366FF90'/%3e %3cpath d='M23.7896 10.4556L22.5017 9.78691L22.3909 9.33557L23.6545 10.0315L23.7896 10.4556Z' fill='%23FFCC00'/%3e %3cpath d='M20.4293 12.2391L19.501 11.9952L19.4707 12.7319L20.389 12.9158L20.4293 12.2391Z' fill='%23AAFF4D'/%3e %3cpath d='M17.071 11.7145L16.5642 11.7918L16.5943 12.7516L17.084 12.624L17.071 11.7145Z' fill='%23BAFF3C'/%3e %3cpath d='M21.9531 14.0038L21.2349 13.7705L21.2595 14.3626L21.9812 14.548L21.9531 14.0038Z' fill='%235AFF9D'/%3e %3cpath d='M20.7148 8.02439L19.219 7.42272L19.158 7.25647L20.5937 7.85933L20.7148 8.02439Z' fill='%23FF4E00'/%3e %3cpath d='M9.80273 10.2796L9.30176 10.8884L9.51225 9.9504L9.99086 9.36194L9.80273 10.2796Z' fill='%23FFD000'/%3e %3cpath d='M24.9881 12.1054L23.9649 11.488L23.894 10.9454L24.9079 11.6027L24.9881 12.1054Z' fill='%23D1FF26'/%3e %3cpath d='M13.4616 6.5608L12.4131 6.64642L12.7372 6.2823L13.7051 6.21484L13.4616 6.5608Z' fill='%23F10800'/%3e %3cpath d='M23.07 16.2311L22.8201 16.0719L22.9985 16.4034L23.2515 16.5461L23.07 16.2311Z' fill='%2300D8FF'/%3e %3cpath d='M15.4135 20.187L15.4781 20.7642L14.9648 21.2219L14.8994 20.6477L15.4135 20.187Z' fill='%230000ED'/%3e %3cpath d='M22.257 8.97021L20.8239 8.30357L20.7144 8.02454L22.1036 8.70135L22.257 8.97021Z' fill='%23FF7A00'/%3e %3cpath d='M14.8815 6.30363L13.7051 6.21511L13.9716 6.02588L15.0584 6.12386L14.8815 6.30363Z' fill='%23DF0000'/%3e %3cpath d='M18.616 11.0297L17.7601 10.8743L17.7585 11.7248L18.5874 11.8204L18.616 11.0297Z' fill='%23E4FF13'/%3e %3cpath d='M17.7084 6.75312L16.3206 6.36999L16.4157 6.34473L17.7183 6.72309L17.7084 6.75312Z' fill='%23FA0F00'/%3e %3cpath d='M12.1283 7.16165L11.2446 7.4269L11.5961 6.88848L12.4133 6.64673L12.1283 7.16165Z' fill='%23FF2500'/%3e %3cpath d='M25.6084 15.9906L25.3188 15.649L25.4718 15.2098L25.7631 15.5959L25.6084 15.9906Z' fill='%2316FFE1'/%3e %3cpath d='M14.4044 21.5208L14.4885 22.0299L13.9007 22.1617L13.8105 21.6554L14.4044 21.5208Z' fill='%2300009F'/%3e %3cpath d='M19.1576 7.25644L17.7083 6.7528L17.7181 6.72278L19.0919 7.21923L19.1576 7.25644Z' fill='%23FF2500'/%3e %3cpath d='M19.5523 11.2661L18.6157 11.0298L18.5872 11.8205L19.5009 11.9952L19.5523 11.2661Z' fill='%23DBFF1C'/%3e %3cpath d='M17.7598 10.8744L17.0425 10.8079L17.0711 11.7146L17.7582 11.7249L17.7598 10.8744Z' fill='%23EBFF0C'/%3e %3cpath d='M16.1918 15.6141L16.3653 16.0433L16.1895 16.9806L16.0413 16.5279L16.1918 15.6141Z' fill='%2302E8F4'/%3e %3cpath d='M22.4921 14.7704L21.9812 14.548L22.0483 15.0618L22.5634 15.2451L22.4921 14.7704Z' fill='%233CFFBA'/%3e %3cpath d='M16.1899 16.981L16.4093 17.4402L16.1245 18.2961L15.9341 17.8172L16.1899 16.981Z' fill='%230098FF'/%3e %3cpath d='M16.203 14.2531L16.2688 14.622L16.192 15.6141L16.1409 15.2158L16.203 14.2531Z' fill='%2343FFB4'/%3e %3cpath d='M16.3204 6.36966L15.0583 6.1236L15.2456 6.09998L16.4156 6.34441L16.3204 6.36966Z' fill='%23DF0000'/%3e %3cpath d='M12.0854 21.5816L12.192 22.0092L11.6293 21.5178L11.5117 21.0807L12.0854 21.5816Z' fill='%230000B2'/%3e %3cpath d='M25.7081 13.7256L25.0311 13.195L25.0295 12.6406L25.7052 13.2172L25.7081 13.7256Z' fill='%238AFF6D'/%3e %3cpath d='M11.5118 21.0808L11.6294 21.5179L11.1049 20.893L10.9771 20.4435L11.5118 21.0808Z' fill='%230000DA'/%3e %3cpath d='M21.294 12.5389L20.4292 12.2388L20.3889 12.9155L21.2465 13.1571L21.294 12.5389Z' fill='%23A7FF50'/%3e %3cpath d='M16.3023 12.9585L16.2026 13.2375L16.2028 14.253L16.3021 13.9372L16.3023 12.9585Z' fill='%2380FF77'/%3e %3cpath d='M22.9213 15.8651L22.6741 15.6825L22.8204 16.0718L23.0703 16.231L22.9213 15.8651Z' fill='%230CF4EB'/%3e %3cpath d='M24.126 17.3402L24.2001 17.1638L24.4627 17.1389L24.3857 17.3318L24.126 17.3402Z' fill='%2300A8FF'/%3e %3cpath d='M23.6545 10.0313L22.3909 9.33535L22.2571 8.97009L23.492 9.68489L23.6545 10.0313Z' fill='%23FFAB00'/%3e %3cpath d='M9.59496 17.3238L9.72947 17.8764L9.4673 16.8698L9.32959 16.3048L9.59496 17.3238Z' fill='%2300B0FF'/%3e %3cpath d='M20.4988 11.5716L19.5526 11.266L19.5012 11.9951L20.4294 12.2389L20.4988 11.5716Z' fill='%23D4FF23'/%3e %3cpath d='M23.8701 17.2808L23.9414 17.115L24.2002 17.1639L24.1261 17.3403L23.8701 17.2808Z' fill='%2300ACFF'/%3e %3cpath d='M10.9502 8.10345L10.2603 8.54088L10.604 7.83941L11.2446 7.42676L10.9502 8.10345Z' fill='%23FF5500'/%3e %3cpath d='M9.07837 14.6613L9.15527 15.2484L9.07734 14.1804L9 13.5889L9.07837 14.6613Z' fill='%2353FFA4'/%3e %3cpath d='M12.6844 21.934L12.7796 22.3552L12.1921 22.0091L12.0854 21.5815L12.6844 21.934Z' fill='%2300009B'/%3e %3cpath d='M20.5933 7.8594L19.1575 7.25654L19.0918 7.21936L20.4638 7.81348L20.5933 7.8594Z' fill='%23FF3F00'/%3e %3cpath d='M24.3855 17.332L24.4626 17.1392L24.7225 17.0411L24.6424 17.2557L24.3855 17.332Z' fill='%2300ACFF'/%3e %3cpath d='M16.5645 11.7915L16.2556 11.9543L16.3027 12.9585L16.5946 12.7513L16.5645 11.7915Z' fill='%23BEFF39'/%3e %3cpath d='M16.1242 18.2959L16.2469 18.8305L15.8666 19.5766L15.759 19.0321L16.1242 18.2959Z' fill='%230050FF'/%3e %3cpath d='M21.9651 13.4429L21.2463 13.1571L21.2349 13.7703L21.9531 14.0036L21.9651 13.4429Z' fill='%2380FF77'/%3e %3cpath d='M25.763 15.5961L25.4717 15.21L25.5895 14.735L25.8817 15.1663L25.763 15.5961Z' fill='%2330FFC7'/%3e %3cpath d='M24.9078 11.6025L23.894 10.9452L23.7898 10.4553L24.7905 11.1461L24.9078 11.6025Z' fill='%23F1FC06'/%3e %3cpath d='M23.6243 17.1548L23.6929 16.9934L23.9413 17.1149L23.8701 17.2808L23.6243 17.1548Z' fill='%2300B4FF'/%3e %3cpath d='M10.9768 20.4434L11.1047 20.893L10.6312 20.1493L10.4939 19.6847L10.9768 20.4434Z' fill='blue'/%3e %3cpath d='M22.1036 8.70114L20.7144 8.02432L20.5933 7.85925L21.9347 8.53648L22.1036 8.70114Z' fill='%23FF6400'/%3e %3cpath d='M24.6428 17.2557L24.7229 17.0411L24.9736 16.8723L24.8904 17.1135L24.6428 17.2557Z' fill='%2300B8FF'/%3e %3cpath d='M18.6545 10.2661L17.76 10.051L17.7601 10.8742L18.6159 11.0297L18.6545 10.2661Z' fill='gold'/%3e %3cpath d='M17.0424 10.8079L16.5034 10.834L16.5642 11.7919L17.071 11.7146L17.0424 10.8079Z' fill='%23F1FC06'/%3e %3cpath d='M17.7183 6.72273L16.4158 6.34436L16.5131 6.46876L17.7276 6.83321L17.7183 6.72273Z' fill='%23ED0400'/%3e %3cpath d='M19.0921 7.2196L17.7183 6.72314L17.7276 6.83363L19.0234 7.3133L19.0921 7.2196Z' fill='%23FF1E00'/%3e %3cpath d='M19.6234 10.5642L18.6543 10.2662L18.6157 11.0298L19.5523 11.2661L19.6234 10.5642Z' fill='%23FFE200'/%3e %3cpath d='M23.395 16.9656L23.4612 16.8025L23.6931 16.9937L23.6245 17.155L23.395 16.9656Z' fill='%2300C0FF'/%3e %3cpath d='M9.18584 11.8961L9.02124 12.5314L9.14272 11.5159L9.30196 10.8882L9.18584 11.8961Z' fill='%23D7FF1F'/%3e %3cpath d='M13.2945 22.1293L13.3782 22.5473L12.7798 22.3552L12.6846 21.9341L13.2945 22.1293Z' fill='%23000092'/%3e %3cpath d='M17.7598 10.0511L16.999 9.92871L17.0426 10.8078L17.7599 10.8744L17.7598 10.0511Z' fill='%23FFCC00'/%3e %3cpath d='M24.8901 17.1134L24.9733 16.8722L25.2083 16.6368L25.1222 16.9087L24.8901 17.1134Z' fill='%2300C4FF'/%3e %3cpath d='M22.4621 14.2707L21.9534 14.0038L21.9814 14.548L22.4923 14.7705L22.4621 14.2707Z' fill='%235DFF9A'/%3e %3cpath d='M22.8088 15.4576L22.5637 15.2454L22.674 15.6828L22.9213 15.8654L22.8088 15.4576Z' fill='%2326FFD1'/%3e %3cpath d='M25.705 13.2173L25.0294 12.6408L24.988 12.1052L25.6601 12.7239L25.705 13.2173Z' fill='%23AAFF4D'/%3e %3cpath d='M15.0585 6.12399L13.9717 6.02601L14.2541 6.00024L15.2457 6.10036L15.0585 6.12399Z' fill='%23C80000'/%3e %3cpath d='M14.9647 21.2219L15.0432 21.7358L14.4882 22.0302L14.4041 21.521L14.9647 21.2219Z' fill='%230000C4'/%3e %3cpath d='M23.1875 16.7176L23.2516 16.5464L23.461 16.8026L23.3948 16.9658L23.1875 16.7176Z' fill='%2300D0FF'/%3e %3cpath d='M13.705 6.215L12.7371 6.28245L13.092 6.08072L13.9715 6.02576L13.705 6.215Z' fill='%23CD0000'/%3e %3cpath d='M21.3765 11.9322L20.4986 11.5718L20.4292 12.2391L21.294 12.5392L21.3765 11.9322Z' fill='%23CEFF29'/%3e %3cpath d='M20.4642 7.81348L19.0921 7.21936L19.0234 7.31306L20.3299 7.88856L20.4642 7.81348Z' fill='%23FF3800'/%3e %3cpath d='M20.5953 10.9318L19.6233 10.5642L19.5522 11.2661L20.4985 11.5717L20.5953 10.9318Z' fill='%23FBF100'/%3e %3cpath d='M25.8819 15.1662L25.5896 14.7348L25.669 14.2358L25.9615 14.7123L25.8819 15.1662Z' fill='%234DFFAA'/%3e %3cpath d='M10.494 19.6845L10.6313 20.1491L10.2203 19.3041L10.0747 18.8221L10.494 19.6845Z' fill='%230030FF'/%3e %3cpath d='M16.4156 6.34453L15.2456 6.1001L15.4381 6.23457L16.5129 6.46893L16.4156 6.34453Z' fill='%23D10000'/%3e %3cpath d='M23.4923 9.6852L22.2574 8.9704L22.104 8.70154L23.3064 9.42602L23.4923 9.6852Z' fill='%23FF9100'/%3e %3cpath d='M15.8668 19.5765L15.9307 20.1572L15.4782 20.7639L15.4136 20.1868L15.8668 19.5765Z' fill='%230014FF'/%3e %3cpath d='M18.702 9.55075L17.7583 9.27783L17.76 10.051L18.6545 10.2661L18.702 9.55075Z' fill='%23FFA700'/%3e %3cpath d='M25.1223 16.9087L25.2084 16.6368L25.422 16.3406L25.3329 16.6465L25.1223 16.9087Z' fill='%2300D8FF'/%3e %3cpath d='M22.017 12.8807L21.2938 12.5392L21.2463 13.1575L21.9651 13.4433L22.017 12.8807Z' fill='%23A4FF53'/%3e %3cpath d='M21.9352 8.53663L20.5938 7.8594L20.4644 7.81348L21.7551 8.48119L21.9352 8.53663Z' fill='%23FF5500'/%3e %3cpath d='M24.7903 11.1464L23.7896 10.4556L23.6545 10.0316L24.6388 10.7485L24.7903 11.1464Z' fill='%23FFDB00'/%3e %3cpath d='M19.0236 7.31305L17.7278 6.83337L17.7363 7.08213L18.9539 7.53573L19.0236 7.31305Z' fill='%23FF1E00'/%3e %3cpath d='M9.99106 9.36198L9.51245 9.95044L9.81307 9.10774L10.26 8.54102L9.99106 9.36198Z' fill='%23FF8D00'/%3e %3cpath d='M19.7124 9.90874L18.7019 9.55078L18.6543 10.2662L19.6234 10.5642L19.7124 9.90874Z' fill='%23FFB600'/%3e %3cpath d='M17.7274 6.83356L16.5129 6.46912L16.6099 6.7407L17.7359 7.08233L17.7274 6.83356Z' fill='%23F10800'/%3e %3cpath d='M12.4133 6.64659L11.5962 6.88834L11.9961 6.50436L12.7375 6.28247L12.4133 6.64659Z' fill='%23E40000'/%3e %3cpath d='M23.0078 16.4166L23.0702 16.2311L23.2517 16.5461L23.1876 16.7173L23.0078 16.4166Z' fill='%2302E8F4'/%3e %3cpath d='M16.9989 9.9284L16.4133 9.90417L16.5034 10.8337L17.0424 10.8075L16.9989 9.9284Z' fill='%23FFC100'/%3e %3cpath d='M17.7581 9.27788L16.9417 9.10156L16.999 9.92864L17.7598 10.0511L17.7581 9.27788Z' fill='%23FF9800'/%3e %3cpath d='M13.9007 22.1616L13.9729 22.5798L13.3781 22.5471L13.2944 22.129L13.9007 22.1616Z' fill='%23000096'/%3e %3cpath d='M16.5037 10.8337L16.1621 10.9521L16.2556 11.9544L16.5645 11.7916L16.5037 10.8337Z' fill='%23F8F500'/%3e %3cpath d='M22.7359 15.0182L22.4924 14.7708L22.5637 15.2454L22.8088 15.4576L22.7359 15.0182Z' fill='%2343FFB4'/%3e %3cpath d='M9.33004 16.3049L9.46774 16.8699L9.29578 15.8266L9.15576 15.2485L9.33004 16.3049Z' fill='%2313FCE4'/%3e %3cpath d='M20.3295 7.88861L19.0231 7.31311L18.9534 7.53578L20.194 8.08319L20.3295 7.88861Z' fill='%23FF3800'/%3e %3cpath d='M16.2556 11.9545L16.1399 12.1964L16.203 13.2377L16.3027 12.9586L16.2556 11.9545Z' fill='%23C1FF36'/%3e %3cpath d='M22.474 13.7589L21.9653 13.4434L21.9534 14.0041L22.4621 14.271L22.474 13.7589Z' fill='%2380FF77'/%3e %3cpath d='M18.757 8.90348L17.7546 8.57629L17.758 9.27797L18.7017 9.55088L18.757 8.90348Z' fill='%23FF7E00'/%3e %3cpath d='M25.3328 16.6466L25.4218 16.3407L25.6083 15.9908L25.5165 16.3334L25.3328 16.6466Z' fill='%2309F0EE'/%3e %3cpath d='M16.2026 13.2379L16.2687 13.5773L16.2687 14.6223L16.2028 14.2534L16.2026 13.2379Z' fill='%2383FF73'/%3e %3cpath d='M20.7167 10.3366L19.7121 9.90881L19.623 10.5643L20.595 10.9318L20.7167 10.3366Z' fill='%23FFC400'/%3e %3cpath d='M18.9537 7.53587L17.7361 7.08228L17.7436 7.46304L18.8848 7.88188L18.9537 7.53587Z' fill='%23FF2900'/%3e %3cpath d='M16.2687 14.6222L16.4554 15.0286L16.3654 16.0435L16.1919 15.6144L16.2687 14.6222Z' fill='%2340FFB7'/%3e %3cpath d='M19.817 9.31762L18.7572 8.9032L18.7019 9.5506L19.7124 9.90856L19.817 9.31762Z' fill='%23FF9100'/%3e %3cpath d='M25.66 12.724L24.988 12.1053L24.9077 11.6027L25.574 12.2585L25.66 12.724Z' fill='%23CAFF2C'/%3e %3cpath d='M25.9614 14.7124L25.6689 14.2359L25.7078 13.7257L25.9997 14.2459L25.9614 14.7124Z' fill='%236AFF8D'/%3e %3cpath d='M21.4916 11.3525L20.5951 10.9316L20.4983 11.5716L21.3762 11.932L21.4916 11.3525Z' fill='%23F1FC06'/%3e %3cpath d='M16.3655 16.0436L16.6051 16.4851L16.4091 17.44L16.1897 16.9808L16.3655 16.0436Z' fill='%2300E4F8'/%3e %3cpath d='M23.3064 9.42601L22.104 8.70153L21.9351 8.53687L23.1021 9.26143L23.3064 9.42601Z' fill='%23FF7A00'/%3e %3cpath d='M21.7549 8.48131L20.4641 7.8136L20.3298 7.8887L21.5685 8.53701L21.7549 8.48131Z' fill='%23FF4E00'/%3e %3cpath d='M17.7359 7.08211L16.6099 6.74048L16.7037 7.15244L17.7434 7.46288L17.7359 7.08211Z' fill='%23FF1300'/%3e %3cpath d='M16.5131 6.46886L15.4382 6.2345L15.6307 6.52443L16.6101 6.74044L16.5131 6.46886Z' fill='%23D60000'/%3e %3cpath d='M18.8186 8.34187L17.7498 7.96558L17.7546 8.57619L18.757 8.90337L18.8186 8.34187Z' fill='%23FF5900'/%3e %3cpath d='M9 13.5891L9.07734 14.1806L9.09883 13.1276L9.02121 12.5316L9 13.5891Z' fill='%2397FF60'/%3e %3cpath d='M18.8849 7.88149L17.7437 7.46265L17.7499 7.96522L18.8188 8.34151L18.8849 7.88149Z' fill='%23FF3B00'/%3e %3cpath d='M10.0749 18.8223L10.2205 19.3043L9.8823 18.3779L9.72974 17.8766L10.0749 18.8223Z' fill='%230070FF'/%3e %3cpath d='M22.8601 16.0707L22.9212 15.8651L23.0702 16.2311L23.0078 16.4165L22.8601 16.0707Z' fill='%2316FFE1'/%3e %3cpath d='M20.1942 8.08292L18.9536 7.53552L18.8848 7.88151L20.0612 8.39204L20.1942 8.08292Z' fill='%23FF4300'/%3e %3cpath d='M17.755 8.57607L16.8723 8.34949L16.9419 9.10145L17.7583 9.27776L17.755 8.57607Z' fill='%23FF6C00'/%3e %3cpath d='M19.9342 8.80745L18.8186 8.34167L18.7571 8.90319L19.8169 9.31761L19.9342 8.80745Z' fill='%23FF6F00'/%3e %3cpath d='M22.1077 12.3309L21.3762 11.9321L21.2937 12.5391L22.017 12.8806L22.1077 12.3309Z' fill='%23C7FF30'/%3e %3cpath d='M11.2441 7.42672L10.6035 7.83938L11.0139 7.27762L11.5956 6.88831L11.2441 7.42672Z' fill='%23FF1E00'/%3e %3cpath d='M15.2458 6.10012L14.2542 6L14.5449 6.13984L15.4383 6.23458L15.2458 6.10012Z' fill='%23BB0000'/%3e %3cpath d='M24.6392 10.7484L23.655 10.0315L23.4924 9.68506L24.4573 10.4199L24.6392 10.7484Z' fill='%23FFBD00'/%3e %3cpath d='M20.0614 8.39236L18.885 7.88184L18.8188 8.34187L19.9344 8.80764L20.0614 8.39236Z' fill='%23FF5500'/%3e %3cpath d='M16.4089 17.4399L16.5433 17.9659L16.2466 18.8305L16.124 18.2958L16.4089 17.4399Z' fill='%230098FF'/%3e %3cpath d='M17.7435 7.46267L16.7039 7.15222L16.792 7.69351L17.7498 7.96524L17.7435 7.46267Z' fill='%23FF2900'/%3e %3cpath d='M17.75 7.9657L16.7922 7.69397L16.8722 8.34974L17.7549 8.57633L17.75 7.9657Z' fill='%23FF4700'/%3e %3cpath d='M20.8603 9.8026L19.8167 9.31787L19.7122 9.90884L20.7168 10.3367L20.8603 9.8026Z' fill='%23FFA300'/%3e %3cpath d='M16.9417 9.10147L16.2964 9.02905L16.4135 9.90432L16.9991 9.92854L16.9417 9.10147Z' fill='%23FF8900'/%3e %3cpath d='M25.5166 16.3332L25.6084 15.9907L25.7631 15.5959L25.6687 15.9768L25.5166 16.3332Z' fill='%231CFFDB'/%3e %3cpath d='M21.5685 8.5371L20.3299 7.88879L20.1943 8.08338L21.3809 8.70285L21.5685 8.5371Z' fill='%23FF5200'/%3e %3cpath d='M22.7042 14.5579L22.4619 14.2706L22.4921 14.7704L22.7356 15.0178L22.7042 14.5579Z' fill='%2360FF97'/%3e %3cpath d='M23.4626 17.4728L23.87 17.281L24.126 17.3405L23.7111 17.5415L23.4626 17.4728Z' fill='%2300BCFF'/%3e %3cpath d='M13.9717 6.02588L13.0923 6.08085L13.4687 6.04871L14.2542 6.00012L13.9717 6.02588Z' fill='%23B20000'/%3e %3cpath d='M23.7112 17.5413L24.1261 17.3403L24.3858 17.3318L23.9631 17.5467L23.7112 17.5413Z' fill='%2300B8FF'/%3e %3cpath d='M15.4783 20.764L15.5517 21.2846L15.0436 21.7357L14.9651 21.2218L15.4783 20.764Z' fill='%230000F1'/%3e %3cpath d='M23.2239 17.3423L23.6241 17.1548L23.8699 17.2808L23.4625 17.4725L23.2239 17.3423Z' fill='%2300C4FF'/%3e %3cpath d='M21.6373 10.8162L20.717 10.3364L20.5952 10.9316L21.4918 11.3525L21.6373 10.8162Z' fill='gold'/%3e %3cpath d='M22.5277 13.2474L22.017 12.8804L21.9651 13.443L22.4738 13.7585L22.5277 13.2474Z' fill='%23A0FF56'/%3e %3cpath d='M23.102 9.26099L21.935 8.53642L21.7549 8.48096L22.8845 9.19592L23.102 9.26099Z' fill='%23FF6F00'/%3e %3cpath d='M16.61 6.74042L15.6306 6.52441L15.8177 6.96254L16.7038 7.15235L16.61 6.74042Z' fill='%23E40000'/%3e %3cpath d='M21.0219 9.34431L19.9343 8.80774L19.8169 9.3179L20.8605 9.80262L21.0219 9.34431Z' fill='%23FF8200'/%3e %3cpath d='M9.30182 10.8883L9.14258 11.516L9.36249 10.5691L9.5123 9.95032L9.30182 10.8883Z' fill='%23FFD000'/%3e %3cpath d='M14.4885 22.0299L14.5496 22.4518L13.9728 22.58L13.9006 22.1618L14.4885 22.0299Z' fill='%230000A8'/%3e %3cpath d='M16.4134 9.9043L16.0242 9.97929L16.1619 10.9521L16.5035 10.8338L16.4134 9.9043Z' fill='%23FFB900'/%3e %3cpath d='M22.748 15.6884L22.8084 15.4574L22.9209 15.8652L22.8598 16.0708L22.748 15.6884Z' fill='%2330FFC7'/%3e %3cpath d='M23.9631 17.5469L24.3858 17.332L24.6427 17.2557L24.2122 17.489L23.9631 17.5469Z' fill='%2300BCFF'/%3e %3cpath d='M25.9997 14.2461L25.7078 13.726L25.7048 13.2175L25.9954 13.779L25.9997 14.2461Z' fill='%2387FF70'/%3e %3cpath d='M21.3811 8.70285L20.1946 8.08337L20.0615 8.39246L21.1973 8.97436L21.3811 8.70285Z' fill='%23FF5900'/%3e %3cpath d='M25.5739 12.2584L24.9076 11.6025L24.7903 11.1461L25.4488 11.8331L25.5739 12.2584Z' fill='%23E7FF0F'/%3e %3cpath d='M23.0012 17.154L23.3949 16.9657L23.6243 17.1551L23.2241 17.3426L23.0012 17.154Z' fill='%2300D0FF'/%3e %3cpath d='M21.1968 8.97436L20.061 8.39246L19.9341 8.80778L21.0217 9.34435L21.1968 8.97436Z' fill='%23FF6C00'/%3e %3cpath d='M16.8722 8.34961L16.1555 8.23267L16.2965 9.02914L16.9418 9.10155L16.8722 8.34961Z' fill='%23FF5D00'/%3e %3cpath d='M12.1924 22.009L12.2662 22.3335L11.7192 21.8558L11.6296 21.5176L12.1924 22.009Z' fill='%230000C4'/%3e %3cpath d='M22.2354 11.8088L21.4919 11.3525L21.3765 11.932L22.108 12.3308L22.2354 11.8088Z' fill='%23E7FF0F'/%3e %3cpath d='M24.2122 17.4887L24.6426 17.2555L24.8902 17.1133L24.4521 17.3686L24.2122 17.4887Z' fill='%2300C4FF'/%3e %3cpath d='M24.4569 10.4198L23.492 9.68497L23.3062 9.42578L24.2494 10.1699L24.4569 10.4198Z' fill='%23FFA700'/%3e %3cpath d='M16.7039 7.15257L15.8179 6.96277L15.9944 7.53741L16.7921 7.69387L16.7039 7.15257Z' fill='%23FF1300'/%3e %3cpath d='M11.6294 21.5175L11.719 21.8557L11.2093 21.2485L11.105 20.8926L11.6294 21.5175Z' fill='%230000E8'/%3e %3cpath d='M25.6687 15.9767L25.7631 15.5959L25.8818 15.1661L25.7851 15.5859L25.6687 15.9767Z' fill='%2336FFC1'/%3e %3cpath d='M22.7998 16.9116L23.1876 16.7173L23.3949 16.9654L23.0013 17.1537L22.7998 16.9116Z' fill='%2300E0FB'/%3e %3cpath d='M16.7921 7.69382L15.9944 7.53735L16.1554 8.23263L16.8721 8.34957L16.7921 7.69382Z' fill='%23FF3400'/%3e %3cpath d='M16.1622 10.9523L16.0149 11.1577L16.1399 12.1965L16.2557 11.9546L16.1622 10.9523Z' fill='%23FBF100'/%3e %3cpath d='M16.247 18.8304L16.3105 19.415L15.9307 20.1571L15.8667 19.5765L16.247 18.8304Z' fill='%230054FF'/%3e %3cpath d='M12.7372 6.28266L11.9958 6.50456L12.4339 6.28722L13.0922 6.08093L12.7372 6.28266Z' fill='%23BB0000'/%3e %3cpath d='M15.438 6.23463L14.5447 6.13989L14.8358 6.44265L15.6305 6.52457L15.438 6.23463Z' fill='%23BF0000'/%3e %3cpath d='M21.8092 10.3378L20.8605 9.80249L20.717 10.3366L21.6374 10.8163L21.8092 10.3378Z' fill='%23FFB600'/%3e %3cpath d='M22.8844 9.19629L21.7547 8.48132L21.5684 8.53703L22.6597 9.2328L22.8844 9.19629Z' fill='%23FF6800'/%3e %3cpath d='M12.7797 22.3552L12.8371 22.6703L12.266 22.3337L12.1921 22.0092L12.7797 22.3552Z' fill='%230000AD'/%3e %3cpath d='M9.72946 17.8769L9.88202 18.3782L9.62534 17.3925L9.46729 16.8702L9.72946 17.8769Z' fill='%2300B4FF'/%3e %3cpath d='M9.15556 15.2487L9.29558 15.8268L9.21901 14.7723L9.07764 14.1807L9.15556 15.2487Z' fill='%2353FFA4'/%3e %3cpath d='M22.7156 14.0896L22.4738 13.7588L22.4619 14.2709L22.7042 14.5582L22.7156 14.0896Z' fill='%237DFF7A'/%3e %3cpath d='M10.2602 8.54074L9.81323 9.10747L10.1972 8.38348L10.6039 7.83923L10.2602 8.54074Z' fill='%23FF4E00'/%3e %3cpath d='M24.4521 17.369L24.8903 17.1136L25.1223 16.9089L24.6769 17.1897L24.4521 17.369Z' fill='%2300D4FF'/%3e %3cpath d='M11.1048 20.8928L11.2091 21.2488L10.749 20.5263L10.6313 20.1492L11.1048 20.8928Z' fill='%230004FF'/%3e %3cpath d='M22.6755 15.279L22.7357 15.0178L22.8086 15.4573L22.7483 15.6882L22.6755 15.279Z' fill='%2349FFAD'/%3e %3cpath d='M16.1399 12.1964L16.1916 12.507L16.2691 13.5771L16.203 13.2377L16.1399 12.1964Z' fill='%23C1FF36'/%3e %3cpath d='M22.6245 16.6219L23.0074 16.4166L23.1872 16.7174L22.7994 16.9117L22.6245 16.6219Z' fill='%230CF4EB'/%3e %3cpath d='M22.6226 12.7506L22.1078 12.3307L22.0171 12.8803L22.5278 13.2473L22.6226 12.7506Z' fill='%23C1FF36'/%3e %3cpath d='M22.0028 9.93016L21.022 9.34412L20.8606 9.80242L21.8093 10.3378L22.0028 9.93016Z' fill='%23FF9800'/%3e %3cpath d='M16.2963 9.02881L15.8457 9.06293L16.0241 9.9791L16.4134 9.9041L16.2963 9.02881Z' fill='%23FF7E00'/%3e %3cpath d='M22.6598 9.23276L21.5685 8.53699L21.3809 8.70273L22.4339 9.37008L22.6598 9.23276Z' fill='%23FF6C00'/%3e %3cpath d='M25.9957 13.7789L25.7051 13.2175L25.6602 12.724L25.9487 13.3233L25.9957 13.7789Z' fill='%23A7FF50'/%3e %3cpath d='M25.4487 11.8334L24.7902 11.1464L24.6387 10.7485L25.2878 11.4599L25.4487 11.8334Z' fill='%23FFEA00'/%3e %3cpath d='M22.3963 11.3284L21.6375 10.8163L21.4919 11.3526L22.2354 11.8088L22.3963 11.3284Z' fill='%23FFE600'/%3e %3cpath d='M24.2494 10.17L23.3062 9.42591L23.1018 9.26135L24.0215 10.0056L24.2494 10.17Z' fill='%23FF9400'/%3e %3cpath d='M16.2691 13.5771L16.4566 13.9622L16.4557 15.0286L16.269 14.6221L16.2691 13.5771Z' fill='%2383FF73'/%3e %3cpath d='M22.2129 9.60483L21.197 8.97437L21.022 9.34433L22.0028 9.93037L22.2129 9.60483Z' fill='%23FF8200'/%3e %3cpath d='M22.434 9.37022L21.3809 8.70288L21.197 8.97438L22.2129 9.60485L22.434 9.37022Z' fill='%23FF7300'/%3e %3cpath d='M13.3781 22.5472L13.4189 22.8573L12.8372 22.6702L12.7798 22.3551L13.3781 22.5472Z' fill='%230000A4'/%3e %3cpath d='M14.2542 6L13.4688 6.04859L13.8565 6.18843L14.545 6.13984L14.2542 6Z' fill='%23A40000'/%3e %3cpath d='M25.7852 15.5862L25.8818 15.1664L25.9615 14.7125L25.8628 15.1711L25.7852 15.5862Z' fill='%2350FFA7'/%3e %3cpath d='M24.6768 17.1897L25.1222 16.9089L25.3328 16.6467L24.8805 16.9556L24.6768 17.1897Z' fill='%2300E4F8'/%3e %3cpath d='M15.6309 6.52467L14.8362 6.44275L15.1195 6.90085L15.818 6.96281L15.6309 6.52467Z' fill='%23CD0000'/%3e %3cpath d='M16.4558 15.0283L16.7063 15.4545L16.6054 16.4847L16.3657 16.0432L16.4558 15.0283Z' fill='%2340FFB7'/%3e %3cpath d='M22.4812 16.2918L22.8603 16.0707L23.008 16.4166L22.625 16.6219L22.4812 16.2918Z' fill='%231FFFD7'/%3e %3cpath d='M9.02148 12.5316L9.0991 13.1276L9.22068 12.1167L9.14297 11.5161L9.02148 12.5316Z' fill='%23D7FF1F'/%3e %3cpath d='M11.5957 6.88849L11.0139 7.2778L11.4807 6.87257L11.9955 6.50452L11.5957 6.88849Z' fill='%23DA0000'/%3e %3cpath d='M15.0435 21.7354L15.094 22.1642L14.5496 22.4515L14.4885 22.0297L15.0435 21.7354Z' fill='%230000CD'/%3e %3cpath d='M10.6312 20.1493L10.7489 20.5264L10.3496 19.7058L10.2202 19.3043L10.6312 20.1493Z' fill='%23003CFF'/%3e %3cpath d='M16.1555 8.23267L15.6316 8.22961L15.846 9.06329L16.2965 9.02917L16.1555 8.23267Z' fill='%23FF4E00'/%3e %3cpath d='M22.7693 13.6243L22.5276 13.2476L22.4736 13.7587L22.7154 14.0895L22.7693 13.6243Z' fill='%239DFF5A'/%3e %3cpath d='M22.6438 14.8533L22.7043 14.558L22.7357 15.0179L22.6755 15.2791L22.6438 14.8533Z' fill='%2363FF94'/%3e %3cpath d='M15.8179 6.96284L15.1194 6.90088L15.387 7.50206L15.9944 7.53747L15.8179 6.96284Z' fill='%23E80000'/%3e %3cpath d='M22.5861 10.9027L21.809 10.3379L21.6372 10.8164L22.396 11.3285L22.5861 10.9027Z' fill='%23FFC400'/%3e %3cpath d='M16.0242 9.97937L15.8306 10.15L16.0146 11.1577L16.1619 10.9522L16.0242 9.97937Z' fill='%23FFAE00'/%3e %3cpath d='M24.0216 10.0055L23.102 9.26125L22.8845 9.19617L23.7795 9.93127L24.0216 10.0055Z' fill='%23FF8600'/%3e %3cpath d='M22.7558 12.2817L22.2351 11.809L22.1077 12.331L22.6224 12.7509L22.7558 12.2817Z' fill='%23DEFF19'/%3e %3cpath d='M16.6052 16.485L16.748 17.0037L16.5436 17.9659L16.4092 17.44L16.6052 16.485Z' fill='%2300E4F8'/%3e %3cpath d='M15.9943 7.53749L15.387 7.50208L15.6314 8.22972L16.1553 8.23277L15.9943 7.53749Z' fill='%23FF2200'/%3e %3cpath d='M15.9306 20.1571L15.9994 20.6861L15.5514 21.2844L15.478 20.7638L15.9306 20.1571Z' fill='%230018FF'/%3e %3cpath d='M25.288 11.4596L24.6389 10.7482L24.457 10.4198L25.0952 11.148L25.288 11.4596Z' fill='%23FFD000'/%3e %3cpath d='M24.8809 16.9555L25.3331 16.6466L25.5169 16.3334L25.0584 16.6723L24.8809 16.9555Z' fill='%230FF8E7'/%3e %3cpath d='M25.9485 13.3232L25.66 12.724L25.574 12.2584L25.8598 12.8911L25.9485 13.3232Z' fill='%23C1FF36'/%3e %3cpath d='M22.3718 15.9296L22.7482 15.6884L22.8599 16.0707L22.4809 16.2918L22.3718 15.9296Z' fill='%2333FFC4'/%3e %3cpath d='M13.9727 22.58L13.9968 22.8899L13.4187 22.8574L13.3779 22.5472L13.9727 22.58Z' fill='%230000A8'/%3e %3cpath d='M25.8628 15.1712L25.9615 14.7126L25.9998 14.2461L25.8994 14.7422L25.8628 15.1712Z' fill='%236AFF8D'/%3e %3cpath d='M13.0922 6.08084L12.4338 6.28713L12.8983 6.24412L13.4686 6.04871L13.0922 6.08084Z' fill='%239F0000'/%3e %3cpath d='M22.7444 17.6893L23.4626 17.4725L23.7111 17.5413L22.9826 17.7665L22.7444 17.6893Z' fill='%2300C8FF'/%3e %3cpath d='M22.8007 10.5429L22.0029 9.93005L21.8093 10.3377L22.5864 10.9025L22.8007 10.5429Z' fill='%23FFAB00'/%3e %3cpath d='M22.5156 17.5544L23.2242 17.3424L23.4629 17.4727L22.7446 17.6894L22.5156 17.5544Z' fill='%2300D0FF'/%3e %3cpath d='M23.7794 9.93127L22.8844 9.19617L22.6597 9.23267L23.5295 9.94956L23.7794 9.93127Z' fill='%23FF8200'/%3e %3cpath d='M9.46738 16.8702L9.62544 17.3924L9.45733 16.3711L9.29541 15.8269L9.46738 16.8702Z' fill='%2316FFE1'/%3e %3cpath d='M9.51236 9.9502L9.36255 10.569L9.67644 9.71643L9.81298 9.10754L9.51236 9.9502Z' fill='%23FF8D00'/%3e %3cpath d='M22.9827 17.7669L23.7111 17.5416L23.963 17.5471L23.2241 17.7843L22.9827 17.7669Z' fill='%2300C8FF'/%3e %3cpath d='M22.3013 17.3649L23.0009 17.1538L23.2238 17.3424L22.5153 17.5543L22.3013 17.3649Z' fill='%2300D8FF'/%3e %3cpath d='M14.545 6.13989L13.8564 6.18848L14.2447 6.49765L14.8361 6.44265L14.545 6.13989Z' fill='%23A80000'/%3e %3cpath d='M16.0149 11.1578L16.0378 11.4411L16.1917 12.5073L16.1399 12.1967L16.0149 11.1578Z' fill='%23FEED00'/%3e %3cpath d='M23.0336 10.2594L22.2131 9.60449L22.0029 9.93005L22.8008 10.5429L23.0336 10.2594Z' fill='%23FF9800'/%3e %3cpath d='M23.5296 9.94932L22.6597 9.23242L22.4338 9.36977L23.2787 10.0597L23.5296 9.94932Z' fill='%23FF8200'/%3e %3cpath d='M22.6541 14.4221L22.7157 14.0896L22.7043 14.5582L22.6438 14.8535L22.6541 14.4221Z' fill='%237DFF7A'/%3e %3cpath d='M22.8651 13.1747L22.6229 12.7507L22.5281 13.2475L22.7698 13.6242L22.8651 13.1747Z' fill='%23BAFF3C'/%3e %3cpath d='M22.9246 11.8527L22.3962 11.3285L22.2354 11.8089L22.756 12.2817L22.9246 11.8527Z' fill='%23FBF100'/%3e %3cpath d='M23.2244 17.784L23.9632 17.5469L24.2123 17.4889L23.463 17.7411L23.2244 17.784Z' fill='%2300C8FF'/%3e %3cpath d='M25.0583 16.6724L25.5169 16.3335L25.669 15.9771L25.205 16.3473L25.0583 16.6724Z' fill='%2326FFD1'/%3e %3cpath d='M22.1077 17.1258L22.7994 16.9117L23.0009 17.1539L22.3012 17.365L22.1077 17.1258Z' fill='%2302E8F4'/%3e %3cpath d='M10.2205 19.3043L10.3499 19.7058L10.0215 18.8065L9.88232 18.3779L10.2205 19.3043Z' fill='%230078FF'/%3e %3cpath d='M23.2785 10.0602L22.4337 9.37024L22.2126 9.60485L23.0332 10.2598L23.2785 10.0602Z' fill='%23FF8900'/%3e %3cpath d='M25.0953 11.148L24.4571 10.4199L24.2495 10.1699L24.8756 10.9068L25.0953 11.148Z' fill='%23FFB900'/%3e %3cpath d='M16.5435 17.9657L16.6067 18.5544L16.3103 19.4148L16.2468 18.8303L16.5435 17.9657Z' fill='%230098FF'/%3e %3cpath d='M9.07764 14.1805L9.21901 14.7721L9.24085 13.7328L9.09912 13.1276L9.07764 14.1805Z' fill='%2397FF60'/%3e %3cpath d='M15.8458 9.06335L15.5923 9.20185L15.8306 10.1501L16.0242 9.97953L15.8458 9.06335Z' fill='%23FF7300'/%3e %3cpath d='M22.3005 15.5444L22.6755 15.2791L22.7482 15.6883L22.3719 15.9296L22.3005 15.5444Z' fill='%234DFFAA'/%3e %3cpath d='M25.8599 12.8913L25.574 12.2586L25.449 11.8334L25.7316 12.4941L25.8599 12.8913Z' fill='%23DEFF19'/%3e %3cpath d='M10.604 7.83935L10.1973 8.38359L10.6555 7.79919L11.0143 7.27759L10.604 7.83935Z' fill='%23FF1A00'/%3e %3cpath d='M23.4626 17.741L24.212 17.4887L24.452 17.3687L23.6924 17.6387L23.4626 17.741Z' fill='%2300D0FF'/%3e %3cpath d='M21.9395 16.8427L22.6245 16.6218L22.7994 16.9116L22.1077 17.1256L21.9395 16.8427Z' fill='%2313FCE4'/%3e %3cpath d='M25.8996 14.7421L26 14.2459L25.9957 13.7788L25.894 14.3104L25.8996 14.7421Z' fill='%2387FF70'/%3e %3cpath d='M16.1917 12.5068L16.3672 12.8723L16.4566 13.962L16.2692 13.5769L16.1917 12.5068Z' fill='%23C4FF33'/%3e %3cpath d='M14.836 6.44263L14.2446 6.49763L14.6227 6.9684L15.1193 6.90073L14.836 6.44263Z' fill='%23B60000'/%3e %3cpath d='M23.1239 11.4753L22.5861 10.9026L22.396 11.3284L22.9244 11.8526L23.1239 11.4753Z' fill='gold'/%3e %3cpath d='M24.8752 10.9068L24.2491 10.1699L24.0212 10.0055L24.6344 10.7427L24.8752 10.9068Z' fill='%23FFA700'/%3e %3cpath d='M15.5513 21.2847L15.5922 21.7237L15.0937 22.1646L15.0432 21.7358L15.5513 21.2847Z' fill='%230000FA'/%3e %3cpath d='M14.5496 22.4517L14.5576 22.7659L13.997 22.8897L13.9729 22.5799L14.5496 22.4517Z' fill='%230000BB'/%3e %3cpath d='M25.2048 16.3472L25.6688 15.9769L25.7852 15.5862L25.3168 15.9882L25.2048 16.3472Z' fill='%233CFFBA'/%3e %3cpath d='M23.6924 17.6389L24.452 17.3689L24.6767 17.1896L23.9073 17.4798L23.6924 17.6389Z' fill='%2300DCFE'/%3e %3cpath d='M22.9992 12.7526L22.7559 12.2815L22.6226 12.7507L22.8648 13.1746L22.9992 12.7526Z' fill='%23D4FF23'/%3e %3cpath d='M15.6312 8.22937L15.3059 8.33945L15.5921 9.20155L15.8456 9.06305L15.6312 8.22937Z' fill='%23FF3F00'/%3e %3cpath d='M22.7066 13.9959L22.7697 13.624L22.7158 14.0892L22.6543 14.4217L22.7066 13.9959Z' fill='%239AFF5D'/%3e %3cpath d='M11.9958 6.50408L11.481 6.87212L11.9921 6.63622L12.4338 6.28674L11.9958 6.50408Z' fill='%23B20000'/%3e %3cpath d='M12.2655 22.3339L12.2903 22.541L11.7635 22.0809L11.7185 21.8562L12.2655 22.3339Z' fill='%230000D6'/%3e %3cpath d='M21.801 16.5231L22.4808 16.2917L22.6246 16.6219L21.9396 16.8427L21.801 16.5231Z' fill='%2326FFD1'/%3e %3cpath d='M11.7189 21.856L11.7639 22.0807L11.273 21.496L11.2092 21.2488L11.7189 21.856Z' fill='%230000FA'/%3e %3cpath d='M22.269 15.1462L22.6439 14.8534L22.6756 15.2792L22.3007 15.5445L22.269 15.1462Z' fill='%2363FF94'/%3e %3cpath d='M16.4566 13.9622L16.7082 14.3757L16.7063 15.4547L16.4558 15.0285L16.4566 13.9622Z' fill='%2383FF73'/%3e %3cpath d='M15.1195 6.90088L14.6228 6.96855L14.98 7.58827L15.3871 7.50205L15.1195 6.90088Z' fill='%23D60000'/%3e %3cpath d='M13.4687 6.04846L12.8984 6.24387L13.3768 6.37789L13.8564 6.1883L13.4687 6.04846Z' fill='%23960000'/%3e %3cpath d='M25.7317 12.4938L25.4491 11.8331L25.2881 11.4596L25.5671 12.1422L25.7317 12.4938Z' fill='%23F4F802'/%3e %3cpath d='M15.3869 7.50183L14.9797 7.58805L15.306 8.33956L15.6313 8.22949L15.3869 7.50183Z' fill='%23FF1300'/%3e %3cpath d='M12.837 22.6702L12.8408 22.865L12.2907 22.5407L12.2659 22.3336L12.837 22.6702Z' fill='%230000BF'/%3e %3cpath d='M23.349 11.1598L22.8005 10.543L22.5862 10.9025L23.1239 11.4752L23.349 11.1598Z' fill='%23FFC100'/%3e %3cpath d='M9.14282 11.5159L9.22053 12.1164L9.44035 11.174L9.36274 10.569L9.14282 11.5159Z' fill='%23FFD000'/%3e %3cpath d='M24.6351 10.7427L24.0219 10.0055L23.7798 9.93127L24.3797 10.6602L24.6351 10.7427Z' fill='%23FF9C00'/%3e %3cpath d='M25.894 14.3106L25.9956 13.779L25.9486 13.3234L25.8462 13.8874L25.894 14.3106Z' fill='%23A0FF56'/%3e %3cpath d='M15.8306 10.15L15.811 10.4082L16.0376 11.441L16.0147 11.1577L15.8306 10.15Z' fill='%23FFAB00'/%3e %3cpath d='M11.2091 21.249L11.2729 21.4962L10.8299 20.8008L10.749 20.5266L11.2091 21.249Z' fill='%230014FF'/%3e %3cpath d='M23.9072 17.4796L24.6766 17.1894L24.8804 16.9553L24.1019 17.2674L23.9072 17.4796Z' fill='%2306ECF1'/%3e %3cpath d='M9.88192 18.3781L10.0211 18.8066L9.77209 17.8499L9.62524 17.3923L9.88192 18.3781Z' fill='%2300BCFF'/%3e %3cpath d='M16.3105 19.415L16.3755 19.9542L15.9995 20.6862L15.9307 20.1572L16.3105 19.415Z' fill='%230054FF'/%3e %3cpath d='M21.696 16.1749L22.3721 15.9296L22.4811 16.2918L21.8013 16.5231L21.696 16.1749Z' fill='%2339FFBE'/%3e %3cpath d='M23.5941 10.9149L23.0337 10.2594L22.8008 10.5428L23.3493 11.1597L23.5941 10.9149Z' fill='%23FFAE00'/%3e %3cpath d='M16.7059 15.4545L16.8532 15.9675L16.7478 17.0034L16.605 16.4847L16.7059 15.4545Z' fill='%2340FFB7'/%3e %3cpath d='M24.3795 10.6602L23.7797 9.93127L23.5298 9.94954L24.1162 10.6618L24.3795 10.6602Z' fill='%23FF9800'/%3e %3cpath d='M9.29532 15.8266L9.45724 16.3708L9.38276 15.3388L9.21875 14.7721L9.29532 15.8266Z' fill='%2356FFA0'/%3e %3cpath d='M25.3167 15.9882L25.7851 15.5862L25.8627 15.171L25.3908 15.6045L25.3167 15.9882Z' fill='%2353FFA4'/%3e %3cpath d='M23.1692 12.3696L22.9244 11.8528L22.7559 12.2818L22.9991 12.7529L23.1692 12.3696Z' fill='%23EEFF09'/%3e %3cpath d='M23.852 10.7477L23.2789 10.0601L23.0337 10.2597L23.5941 10.9152L23.852 10.7477Z' fill='%23FF9F00'/%3e %3cpath d='M24.1161 10.6619L23.5297 9.94958L23.2788 10.06L23.8519 10.7476L24.1161 10.6619Z' fill='%23FF9800'/%3e %3cpath d='M22.7997 13.587L22.8649 13.1747L22.7696 13.6242L22.7065 13.9961L22.7997 13.587Z' fill='%23B4FF43'/%3e %3cpath d='M13.4188 22.8574L13.401 23.0456L12.8409 22.8651L12.8372 22.6703L13.4188 22.8574Z' fill='%230000B6'/%3e %3cpath d='M21.5459 17.7914L22.5153 17.5543L22.7443 17.6894L21.7641 17.9325L21.5459 17.7914Z' fill='%2300D8FF'/%3e %3cpath d='M25.5671 12.1423L25.288 11.4597L25.0952 11.1481L25.3704 11.8458L25.5671 12.1423Z' fill='%23FFDE00'/%3e %3cpath d='M22.2779 14.7445L22.654 14.4218L22.6437 14.8531L22.2688 15.1459L22.2779 14.7445Z' fill='%237DFF7A'/%3e %3cpath d='M21.7639 17.9325L22.7442 17.6893L22.9824 17.7666L21.9908 18.0181L21.7639 17.9325Z' fill='%2300D0FF'/%3e %3cpath d='M21.342 17.5983L22.3016 17.3647L22.5156 17.5542L21.5461 17.7913L21.342 17.5983Z' fill='%2300E0FB'/%3e %3cpath d='M21.9915 18.0183L22.983 17.7667L23.2245 17.7841L22.2213 18.0462L21.9915 18.0183Z' fill='%2300D0FF'/%3e %3cpath d='M9.81306 9.10766L9.67651 9.71655L10.0773 8.98197L10.1971 8.38367L9.81306 9.10766Z' fill='%23FF4E00'/%3e %3cpath d='M21.157 17.3582L22.1078 17.1256L22.3013 17.3648L21.3418 17.5983L21.157 17.3582Z' fill='%2309F0EE'/%3e %3cpath d='M24.1021 17.2676L24.8805 16.9555L25.0581 16.6724L24.2715 17.0076L24.1021 17.2676Z' fill='%2319FFDE'/%3e %3cpath d='M10.7491 20.5261L10.83 20.8003L10.4456 20.0106L10.3499 19.7056L10.7491 20.5261Z' fill='%230048FF'/%3e %3cpath d='M21.6267 15.8069L22.3007 15.5446L22.372 15.9297L21.696 16.1751L21.6267 15.8069Z' fill='%2350FFA7'/%3e %3cpath d='M25.8463 13.8871L25.9487 13.3231L25.86 12.891L25.7573 13.4836L25.8463 13.8871Z' fill='%23BEFF39'/%3e %3cpath d='M13.8563 6.18835L13.3767 6.37794L13.8557 6.6865L14.2446 6.49753L13.8563 6.18835Z' fill='%23960000'/%3e %3cpath d='M23.3708 12.0353L23.124 11.4753L22.9246 11.8527L23.1693 12.3695L23.3708 12.0353Z' fill='%23FFE600'/%3e %3cpath d='M15.0938 22.1644L15.0864 22.4877L14.5573 22.766L14.5493 22.4518L15.0938 22.1644Z' fill='%230000DA'/%3e %3cpath d='M22.2209 18.0461L23.2242 17.784L23.4628 17.7411L22.4479 18.0155L22.2209 18.0461Z' fill='%2300D0FF'/%3e %3cpath d='M16.0378 11.4408L16.1889 11.789L16.3672 12.8724L16.1917 12.507L16.0378 11.4408Z' fill='%23FFEA00'/%3e %3cpath d='M20.9961 17.0772L21.9395 16.8429L22.1077 17.1258L21.1569 17.3584L20.9961 17.0772Z' fill='%2316FFE1'/%3e %3cpath d='M15.5925 9.20154L15.5176 9.43755L15.8112 10.408L15.8308 10.1498L15.5925 9.20154Z' fill='%23FF6C00'/%3e %3cpath d='M9.09888 13.1275L9.2406 13.7328L9.36147 12.7352L9.22045 12.1166L9.09888 13.1275Z' fill='%23D7FF1F'/%3e %3cpath d='M25.3911 15.6047L25.863 15.1712L25.8996 14.7423L25.4254 15.2062L25.3911 15.6047Z' fill='%236DFF8A'/%3e %3cpath d='M11.0142 7.27779L10.6553 7.79939L11.1761 7.37197L11.481 6.87256L11.0142 7.27779Z' fill='%23D10000'/%3e %3cpath d='M25.3706 11.8457L25.0954 11.148L24.8757 10.9067L25.1468 11.6124L25.3706 11.8457Z' fill='%23FFCC00'/%3e %3cpath d='M16.7478 17.0038L16.8109 17.597L16.6066 18.5548L16.5435 17.966L16.7478 17.0038Z' fill='%2300E4F8'/%3e %3cpath d='M22.9315 13.2049L22.9994 12.7523L22.8651 13.1744L22.7998 13.5867L22.9315 13.2049Z' fill='%23CEFF29'/%3e %3cpath d='M12.4337 6.28716L11.9919 6.63664L12.5338 6.57823L12.8982 6.24414L12.4337 6.28716Z' fill='%23960000'/%3e %3cpath d='M22.3275 14.3506L22.7063 13.9961L22.654 14.4219L22.2778 14.7447L22.3275 14.3506Z' fill='%2397FF60'/%3e %3cpath d='M13.9968 22.8897L13.9576 23.077L13.4009 23.0454L13.4187 22.8572L13.9968 22.8897Z' fill='%230000BB'/%3e %3cpath d='M22.448 18.0153L23.4629 17.7409L23.6926 17.6387L22.6664 17.9269L22.448 18.0153Z' fill='%2300D8FF'/%3e %3cpath d='M15.9996 20.6862L16.0319 21.1386L15.5924 21.7235L15.5515 21.2844L15.9996 20.6862Z' fill='%230020FF'/%3e %3cpath d='M24.2715 17.0075L25.0581 16.6723L25.2048 16.3472L24.4112 16.7062L24.2715 17.0075Z' fill='%2329FFCE'/%3e %3cpath d='M20.8638 16.7618L21.8013 16.5231L21.9398 16.8427L20.9965 17.077L20.8638 16.7618Z' fill='%2329FFCE'/%3e %3cpath d='M23.5984 11.7591L23.3491 11.1599L23.124 11.4753L23.3708 12.0352L23.5984 11.7591Z' fill='%23FFD000'/%3e %3cpath d='M21.5955 15.4282L22.2691 15.1461L22.3007 15.5445L21.6267 15.8069L21.5955 15.4282Z' fill='%2366FF90'/%3e %3cpath d='M25.7573 13.4836L25.86 12.8909L25.7318 12.4938L25.6294 13.1103L25.7573 13.4836Z' fill='%23D4FF23'/%3e %3cpath d='M25.1466 11.6124L24.8755 10.9067L24.6348 10.7426L24.9018 11.4486L25.1466 11.6124Z' fill='%23FFB900'/%3e %3cpath d='M14.2449 6.49768L13.856 6.68666L14.3223 7.16203L14.6229 6.96846L14.2449 6.49768Z' fill='%23A80000'/%3e %3cpath d='M9.62562 17.3922L9.77247 17.8498L9.6096 16.8588L9.45752 16.3708L9.62562 17.3922Z' fill='%2319FFDE'/%3e %3cpath d='M16.3672 12.8724L16.6098 13.2763L16.7082 14.3756L16.4566 13.9621L16.3672 12.8724Z' fill='%23C4FF33'/%3e %3cpath d='M15.306 8.33984L15.1646 8.55733L15.5173 9.43793L15.5922 9.20193L15.306 8.33984Z' fill='%23FF3400'/%3e %3cpath d='M10.3496 19.7059L10.4454 20.0109L10.1294 19.1456L10.0212 18.8065L10.3496 19.7059Z' fill='%230080FF'/%3e %3cpath d='M23.8463 11.5486L23.5941 10.915L23.3494 11.1598L23.5986 11.759L23.8463 11.5486Z' fill='%23FFC100'/%3e %3cpath d='M22.6665 17.9271L23.6927 17.6389L23.9077 17.4797L22.8706 17.7829L22.6665 17.9271Z' fill='%2300E4F8'/%3e %3cpath d='M25.4249 15.206L25.8992 14.7421L25.8936 14.3104L25.4182 14.8029L25.4249 15.206Z' fill='%2387FF70'/%3e %3cpath d='M20.7622 16.4206L21.6955 16.175L21.8008 16.5233L20.8633 16.762L20.7622 16.4206Z' fill='%233CFFBA'/%3e %3cpath d='M23.0984 12.8613L23.1694 12.3695L22.9993 12.7528L22.9314 13.2054L23.0984 12.8613Z' fill='%23E4FF13'/%3e %3cpath d='M24.9016 11.4486L24.6346 10.7426L24.3792 10.6602L24.6421 11.3589L24.9016 11.4486Z' fill='%23FFB200'/%3e %3cpath d='M14.6227 6.96851L14.322 7.16207L14.7624 7.79143L14.9798 7.58825L14.6227 6.96851Z' fill='%23C80000'/%3e %3cpath d='M14.9798 7.58826L14.7625 7.79144L15.1646 8.55723L15.3061 8.33974L14.9798 7.58826Z' fill='%23F10800'/%3e %3cpath d='M22.4171 13.9742L22.7998 13.5869L22.7066 13.9961L22.3279 14.3506L22.4171 13.9742Z' fill='%23B1FF46'/%3e %3cpath d='M24.1069 11.4097L23.8514 10.7476L23.5935 10.9151L23.8457 11.5487L24.1069 11.4097Z' fill='%23FFB200'/%3e %3cpath d='M9.36279 10.5691L9.44041 11.1742L9.754 10.3259L9.67668 9.71655L9.36279 10.5691Z' fill='%23FF8D00'/%3e %3cpath d='M24.4114 16.7062L25.205 16.3471L25.3169 15.9882L24.5176 16.3711L24.4114 16.7062Z' fill='%2340FFB7'/%3e %3cpath d='M24.6423 11.3588L24.3793 10.66L24.116 10.6616L24.3751 11.3456L24.6423 11.3588Z' fill='%23FFAB00'/%3e %3cpath d='M24.3748 11.3456L24.1158 10.6616L23.8516 10.7473L24.107 11.4094L24.3748 11.3456Z' fill='%23FFAE00'/%3e %3cpath d='M21.6028 15.0489L22.2779 14.7449L22.2689 15.1463L21.5952 15.4284L21.6028 15.0489Z' fill='%237DFF7A'/%3e %3cpath d='M20.3831 18.0561L21.5462 17.7916L21.7644 17.9327L20.5902 18.2053L20.3831 18.0561Z' fill='%2300DCFE'/%3e %3cpath d='M20.1887 17.8558L21.3416 17.5983L21.5457 17.7913L20.3826 18.0558L20.1887 17.8558Z' fill='%2300E4F8'/%3e %3cpath d='M9.21875 14.7719L9.38276 15.3386L9.40482 14.3217L9.24058 13.7325L9.21875 14.7719Z' fill='%2397FF60'/%3e %3cpath d='M25.6293 13.1103L25.7317 12.4938L25.5671 12.1422L25.4656 12.7774L25.6293 13.1103Z' fill='%23EBFF0C'/%3e %3cpath d='M12.2908 22.5406L12.267 22.623L11.7642 22.184L11.7639 22.0806L12.2908 22.5406Z' fill='%230000ED'/%3e %3cpath d='M16.6067 18.5548L16.6689 19.1055L16.3754 19.9543L16.3103 19.4151L16.6067 18.5548Z' fill='%23009CFF'/%3e %3cpath d='M16.7079 14.3759L16.8559 14.8847L16.8534 15.9679L16.7061 15.4549L16.7079 14.3759Z' fill='%2383FF73'/%3e %3cpath d='M20.5901 18.2053L21.7643 17.9327L21.9912 18.0184L20.8052 18.2999L20.5901 18.2053Z' fill='%2300D4FF'/%3e %3cpath d='M11.7641 22.0808L11.7644 22.1842L11.296 21.6263L11.2732 21.4961L11.7641 22.0808Z' fill='blue'/%3e %3cpath d='M15.8108 10.4081L15.9254 10.7418L16.1884 11.789L16.0374 11.4408L15.8108 10.4081Z' fill='%23FFA300'/%3e %3cpath d='M20.0134 17.6101L21.1572 17.3582L21.342 17.5983L20.1891 17.8558L20.0134 17.6101Z' fill='%230CF4EB'/%3e %3cpath d='M22.8704 17.7827L23.9074 17.4795L24.1021 17.2673L23.0551 17.5863L22.8704 17.7827Z' fill='%230CF4EB'/%3e %3cpath d='M14.5573 22.7659L14.4972 22.9583L13.9575 23.0771L13.9967 22.8897L14.5573 22.7659Z' fill='%230000CD'/%3e %3cpath d='M20.6956 16.0617L21.6266 15.8069L21.6958 16.175L20.7625 16.4206L20.6956 16.0617Z' fill='%2350FFA7'/%3e %3cpath d='M12.8407 22.8651L12.7917 22.9326L12.2668 22.6231L12.2906 22.5408L12.8407 22.8651Z' fill='%230000D6'/%3e %3cpath d='M23.2961 12.5639L23.3706 12.0352L23.1692 12.3694L23.0981 12.8612L23.2961 12.5639Z' fill='%23F8F500'/%3e %3cpath d='M20.8052 18.2996L21.9912 18.0181L22.221 18.046L21.023 18.3373L20.8052 18.2996Z' fill='%2300D4FF'/%3e %3cpath d='M12.8986 6.24402L12.5342 6.57811L13.092 6.70032L13.377 6.37804L12.8986 6.24402Z' fill='%23890000'/%3e %3cpath d='M19.8604 17.325L20.9965 17.0771L21.1572 17.3583L20.0135 17.6103L19.8604 17.325Z' fill='%2319FFDE'/%3e %3cpath d='M15.5923 21.7235L15.5707 22.0604L15.0864 22.4876L15.0938 22.1644L15.5923 21.7235Z' fill='blue'/%3e %3cpath d='M25.4185 14.8028L25.8939 14.3104L25.8461 13.8872L25.3708 14.4056L25.4185 14.8028Z' fill='%23A0FF56'/%3e %3cpath d='M11.2729 21.4959L11.2957 21.6261L10.873 20.9626L10.8298 20.8004L11.2729 21.4959Z' fill='%230024FF'/%3e %3cpath d='M10.1969 8.3836L10.0771 8.9819L10.5552 8.38643L10.6551 7.79919L10.1969 8.3836Z' fill='%23FF1600'/%3e %3cpath d='M22.5433 13.6251L22.9311 13.2051L22.7994 13.5868L22.4167 13.974L22.5433 13.6251Z' fill='%23C7FF30'/%3e %3cpath d='M25.4655 12.7777L25.5671 12.1426L25.3704 11.8461L25.2703 12.494L25.4655 12.7777Z' fill='%23FEED00'/%3e %3cpath d='M24.5176 16.3714L25.3169 15.9884L25.391 15.6047L24.5875 16.0111L24.5176 16.3714Z' fill='%2356FFA0'/%3e %3cpath d='M11.4811 6.87252L11.1763 7.37193L11.7463 7.11488L11.9922 6.6366L11.4811 6.87252Z' fill='%23A80000'/%3e %3cpath d='M21.0229 18.3374L22.221 18.0461L22.448 18.0155L21.2379 18.3169L21.0229 18.3374Z' fill='%2300D4FF'/%3e %3cpath d='M21.6498 14.6781L22.3281 14.3506L22.2784 14.7446L21.6033 15.0486L21.6498 14.6781Z' fill='%2397FF60'/%3e %3cpath d='M19.7336 17.0072L20.8637 16.7618L20.9964 17.0771L19.8602 17.3249L19.7336 17.0072Z' fill='%2329FFCE'/%3e %3cpath d='M10.0215 18.8063L10.1297 19.1454L9.89017 18.2252L9.77246 17.8496L10.0215 18.8063Z' fill='%2300C4FF'/%3e %3cpath d='M23.0552 17.5863L24.1022 17.2673L24.2717 17.0073L23.2157 17.3424L23.0552 17.5863Z' fill='%231CFFDB'/%3e %3cpath d='M13.4012 23.0457L13.3264 23.105L12.792 22.9328L12.841 22.8652L13.4012 23.0457Z' fill='%230000CD'/%3e %3cpath d='M20.6648 15.6945L21.5954 15.4283L21.6267 15.807L20.6957 16.0618L20.6648 15.6945Z' fill='%2366FF90'/%3e %3cpath d='M23.52 12.3215L23.5982 11.759L23.3706 12.0351L23.2961 12.5638L23.52 12.3215Z' fill='%23FFDE00'/%3e %3cpath d='M9.22046 12.1164L9.36148 12.735L9.57955 11.8054L9.44027 11.1741L9.22046 12.1164Z' fill='%23FFD300'/%3e %3cpath d='M16.8537 15.9677L16.9168 16.5655L16.8113 17.5969L16.7483 17.0036L16.8537 15.9677Z' fill='%2340FFB7'/%3e %3cpath d='M21.2378 18.317L22.4479 18.0155L22.6662 17.9271L21.4443 18.2388L21.2378 18.317Z' fill='%2300DCFE'/%3e %3cpath d='M25.2706 12.4937L25.3707 11.8458L25.1469 11.6124L25.0488 12.267L25.2706 12.4937Z' fill='%23FFDB00'/%3e %3cpath d='M25.371 14.4057L25.8463 13.8873L25.7574 13.4838L25.2834 14.0248L25.371 14.4057Z' fill='%23B7FF40'/%3e %3cpath d='M16.1887 11.7891L16.4125 12.1863L16.6096 13.2763L16.367 12.8725L16.1887 11.7891Z' fill='%23FFE600'/%3e %3cpath d='M10.8299 20.8006L10.873 20.9629L10.5064 20.2096L10.4456 20.0109L10.8299 20.8006Z' fill='%230054FF'/%3e %3cpath d='M9.45753 16.3709L9.60962 16.8588L9.53781 15.8579L9.38306 15.3389L9.45753 16.3709Z' fill='%2356FFA0'/%3e %3cpath d='M19.6367 16.6651L20.7625 16.4207L20.8636 16.762L19.7335 17.0073L19.6367 16.6651Z' fill='%233CFFBA'/%3e %3cpath d='M16.3753 19.954L16.4004 20.4225L16.0316 21.1384L15.9993 20.686L16.3753 19.954Z' fill='%23005CFF'/%3e %3cpath d='M15.5173 9.43787L15.5843 9.76023L15.9255 10.742L15.8109 10.4083L15.5173 9.43787Z' fill='%23FF6400'/%3e %3cpath d='M23.7642 12.1407L23.8461 11.5487L23.5984 11.7591L23.5203 12.3216L23.7642 12.1407Z' fill='%23FFD000'/%3e %3cpath d='M22.7043 13.3133L23.0982 12.8613L22.9312 13.2054L22.5435 13.6255L22.7043 13.3133Z' fill='%23DEFF19'/%3e %3cpath d='M13.3768 6.37781L13.0918 6.70009L13.6501 7.0007L13.8558 6.68637L13.3768 6.37781Z' fill='%23890000'/%3e %3cpath d='M24.5874 16.0109L25.3909 15.6045L25.4252 15.2059L24.6189 15.6346L24.5874 16.0109Z' fill='%236DFF8A'/%3e %3cpath d='M25.0485 12.2669L25.1466 11.6124L24.9018 11.4486L24.8062 12.1032L25.0485 12.2669Z' fill='%23FFCC00'/%3e %3cpath d='M21.7338 14.3262L22.4169 13.9742L22.3277 14.3507L21.6494 14.6782L21.7338 14.3262Z' fill='%23ADFF49'/%3e %3cpath d='M23.2158 17.3427L24.2718 17.0076L24.4115 16.7063L23.3478 17.0574L23.2158 17.3427Z' fill='%232CFFCA'/%3e %3cpath d='M20.6709 15.3282L21.603 15.0488L21.5954 15.4283L20.6648 15.6945L20.6709 15.3282Z' fill='%237DFF7A'/%3e %3cpath d='M19.1769 18.4522L20.4852 18.137L20.2841 17.9619L18.9727 18.2743L19.1769 18.4522Z' fill='%2300DCFE'/%3e %3cpath d='M18.9727 18.2742L20.2842 17.9618L20.0988 17.7383L18.7842 18.0471L18.9727 18.2742Z' fill='%2302E8F4'/%3e %3cpath d='M24.0219 12.0261L24.1076 11.4097L23.8463 11.5487L23.7644 12.1406L24.0219 12.0261Z' fill='%23FFC400'/%3e %3cpath d='M15.0865 22.4878L15.0065 22.6911L14.4973 22.9585L14.5574 22.7661L15.0865 22.4878Z' fill='%230000ED'/%3e %3cpath d='M21.4446 18.2389L22.6665 17.9273L22.8707 17.7831L21.6375 18.1049L21.4446 18.2389Z' fill='%2302E8F4'/%3e %3cpath d='M19.3916 18.5765L20.6968 18.2593L20.485 18.137L19.1768 18.4522L19.3916 18.5765Z' fill='%2300D4FF'/%3e %3cpath d='M13.9576 23.0772L13.8572 23.1352L13.3262 23.1049L13.4009 23.0455L13.9576 23.0772Z' fill='%230000D1'/%3e %3cpath d='M24.8061 12.1032L24.9017 11.4486L24.6422 11.3589L24.5496 12.0071L24.8061 12.1032Z' fill='%23FFC400'/%3e %3cpath d='M19.5725 16.3069L20.6959 16.0616L20.7628 16.4205L19.6371 16.665L19.5725 16.3069Z' fill='%2353FFA4'/%3e %3cpath d='M18.7841 18.0474L20.0987 17.7385L19.9338 17.4722L18.616 17.7769L18.7841 18.0474Z' fill='%230FF8E7'/%3e %3cpath d='M24.2859 11.9815L24.3752 11.3461L24.1074 11.4099L24.0217 12.0264L24.2859 11.9815Z' fill='%23FFC100'/%3e %3cpath d='M25.2832 14.0246L25.7572 13.4836L25.6292 13.1104L25.158 13.6703L25.2832 14.0246Z' fill='%23CEFF29'/%3e %3cpath d='M24.5498 12.0073L24.6424 11.3591L24.3752 11.3459L24.2859 11.9814L24.5498 12.0073Z' fill='%23FFBD00'/%3e %3cpath d='M19.6118 18.6442L20.9142 18.3257L20.6971 18.2594L19.3918 18.5766L19.6118 18.6442Z' fill='%2300D4FF'/%3e %3cpath d='M22.8953 13.0463L23.2963 12.5641L23.0983 12.8613L22.7043 13.3133L22.8953 13.0463Z' fill='%23F1FC06'/%3e %3cpath d='M15.1648 8.55713L15.1743 8.87166L15.5845 9.7601L15.5175 9.43774L15.1648 8.55713Z' fill='%23FF2D00'/%3e %3cpath d='M18.6158 17.777L19.9337 17.4723L19.7934 17.1698L18.4724 17.4699L18.6158 17.777Z' fill='%231CFFDB'/%3e %3cpath d='M9.67651 9.7163L9.75384 10.3257L10.1541 9.59509L10.0773 8.98169L9.67651 9.7163Z' fill='%23FF4E00'/%3e %3cpath d='M16.6096 13.2764L16.7542 13.7829L16.856 14.8846L16.708 14.3757L16.6096 13.2764Z' fill='%23C4FF33'/%3e %3cpath d='M13.8561 6.68665L13.6504 7.00098L14.1936 7.47242L14.3224 7.16203L13.8561 6.68665Z' fill='%239B0000'/%3e %3cpath d='M9.24072 13.7326L9.40496 14.3218L9.52415 13.3462L9.3616 12.735L9.24072 13.7326Z' fill='%23D4FF23'/%3e %3cpath d='M10.4457 20.0111L10.5065 20.2098L10.2051 19.3847L10.1296 19.1458L10.4457 20.0111Z' fill='%23008CFF'/%3e %3cpath d='M24.6191 15.6346L25.4253 15.2059L25.4186 14.8027L24.6113 15.2521L24.6191 15.6346Z' fill='%2387FF70'/%3e %3cpath d='M19.8311 18.6533L21.131 18.3344L20.914 18.3258L19.6116 18.6443L19.8311 18.6533Z' fill='%2300D4FF'/%3e %3cpath d='M11.992 6.63665L11.7461 7.11493L12.35 7.03692L12.5338 6.57825L11.992 6.63665Z' fill='%238D0000'/%3e %3cpath d='M21.8538 14.0021L22.5434 13.6255L22.4168 13.9744L21.7336 14.3263L21.8538 14.0021Z' fill='%23C4FF33'/%3e %3cpath d='M23.3479 17.0571L24.4116 16.706L24.5178 16.371L23.4479 16.7377L23.3479 17.0571Z' fill='%2343FFB4'/%3e %3cpath d='M21.6372 18.1047L22.8703 17.7829L23.055 17.5864L21.8116 17.918L21.6372 18.1047Z' fill='%230FF8E7'/%3e %3cpath d='M16.0316 21.1387L15.9975 21.4934L15.5706 22.0605L15.5921 21.7236L16.0316 21.1387Z' fill='%230028FF'/%3e %3cpath d='M16.8111 17.597L16.8714 18.1604L16.6691 19.1054L16.6069 18.5548L16.8111 17.597Z' fill='%2302E8F4'/%3e %3cpath d='M20.714 14.9721L21.6495 14.6781L21.603 15.0487L20.6709 15.328L20.714 14.9721Z' fill='%2394FF63'/%3e %3cpath d='M9.77249 17.8496L9.8902 18.2252L9.73378 17.2723L9.60962 16.8586L9.77249 17.8496Z' fill='%231CFFDB'/%3e %3cpath d='M12.2668 22.6231L12.2119 22.581L11.7366 22.1659L11.7641 22.1841L12.2668 22.6231Z' fill='blue'/%3e %3cpath d='M19.5417 15.9423L20.6647 15.6946L20.6956 16.0619L19.5722 16.3071L19.5417 15.9423Z' fill='%2366FF90'/%3e %3cpath d='M11.7641 22.1842L11.7366 22.1661L11.2937 21.6386L11.2957 21.6263L11.7641 22.1842Z' fill='%230010FF'/%3e %3cpath d='M18.4722 17.4699L19.7932 17.1698L19.6811 16.8387L18.3572 17.1338L18.4722 17.4699Z' fill='%2330FFC7'/%3e %3cpath d='M25.1581 13.6702L25.6294 13.1103L25.4657 12.7773L24.9983 13.3517L25.1581 13.6702Z' fill='%23E4FF13'/%3e %3cpath d='M14.7624 7.79126L14.7061 8.10174L15.1741 8.87159L15.1646 8.55706L14.7624 7.79126Z' fill='%23E80000'/%3e %3cpath d='M14.3219 7.16211L14.1931 7.4725L14.706 8.10194L14.7623 7.79146L14.3219 7.16211Z' fill='%23BB0000'/%3e %3cpath d='M10.6551 7.79913L10.5552 8.38636L11.0984 7.94774L11.1759 7.3717L10.6551 7.79913Z' fill='%23D10000'/%3e %3cpath d='M23.1117 12.8314L23.5203 12.3214L23.2965 12.5638L22.8955 13.046L23.1117 12.8314Z' fill='%23FEED00'/%3e %3cpath d='M12.7918 22.9328L12.7082 22.8738L12.2119 22.5812L12.2668 22.6233L12.7918 22.9328Z' fill='%230000F1'/%3e %3cpath d='M15.9258 10.7418L16.1212 11.1358L16.4126 12.1864L16.1888 11.7891L15.9258 10.7418Z' fill='%23FF9F00'/%3e %3cpath d='M20.0446 18.6031L21.3424 18.2848L21.131 18.3342L19.8311 18.6531L20.0446 18.6031Z' fill='%2300D8FF'/%3e %3cpath d='M11.2955 21.6263L11.2935 21.6386L10.8938 21.0113L10.8728 20.9629L11.2955 21.6263Z' fill='%230038FF'/%3e %3cpath d='M14.4971 22.9581L14.3715 23.0218L13.8569 23.1349L13.9574 23.0769L14.4971 22.9581Z' fill='%230000E3'/%3e %3cpath d='M24.6113 15.2522L25.4185 14.8029L25.3709 14.4056L24.5642 14.8735L24.6113 15.2522Z' fill='%239DFF5A'/%3e %3cpath d='M18.3573 17.134L19.6812 16.8389L19.6002 16.4877L18.2737 16.7774L18.3573 17.134Z' fill='%2343FFB4'/%3e %3cpath d='M24.9981 13.3518L25.4655 12.7775L25.2702 12.4938L24.8079 13.0778L24.9981 13.3518Z' fill='%23F4F802'/%3e %3cpath d='M21.8115 17.9181L23.055 17.5865L23.2154 17.3427L21.9628 17.6834L21.8115 17.9181Z' fill='%231FFFD7'/%3e %3cpath d='M22.0068 13.7142L22.7042 13.3132L22.5434 13.6254L21.8538 14.002L22.0068 13.7142Z' fill='%23D7FF1F'/%3e %3cpath d='M17.8295 18.8008L19.1769 18.4524L18.9726 18.2744L17.6169 18.6156L17.8295 18.8008Z' fill='%2300D8FF'/%3e %3cpath d='M23.4475 16.738L24.5174 16.3712L24.5873 16.011L23.5128 16.3925L23.4475 16.738Z' fill='%2356FFA0'/%3e %3cpath d='M17.6169 18.6156L18.9726 18.2744L18.7841 18.0474L17.4204 18.3794L17.6169 18.6156Z' fill='%2300E4F8'/%3e %3cpath d='M23.3473 12.6751L23.7642 12.1407L23.5203 12.3217L23.1116 12.8316L23.3473 12.6751Z' fill='%23FFDE00'/%3e %3cpath d='M19.5462 15.5796L20.6708 15.3279L20.6647 15.6942L19.5417 15.9419L19.5462 15.5796Z' fill='%237DFF7A'/%3e %3cpath d='M20.7929 14.6357L21.7338 14.326L21.6494 14.6781L20.7139 14.972L20.7929 14.6357Z' fill='%23AAFF4D'/%3e %3cpath d='M13.326 23.105L13.2132 23.0366L12.708 22.8738L12.7916 22.9328L13.326 23.105Z' fill='%230000E8'/%3e %3cpath d='M18.0527 18.9301L19.3918 18.5765L19.177 18.4521L17.8296 18.8006L18.0527 18.9301Z' fill='%2300D0FF'/%3e %3cpath d='M9.38281 15.3388L9.53756 15.8578L9.5596 14.872L9.40487 14.322L9.38281 15.3388Z' fill='%2394FF63'/%3e %3cpath d='M17.4207 18.3792L18.7843 18.0472L18.6162 17.7767L17.2451 18.0979L17.4207 18.3792Z' fill='%230CF4EB'/%3e %3cpath d='M20.2468 18.4958L21.5428 18.1788L21.3424 18.2852L20.0447 18.6036L20.2468 18.4958Z' fill='%2300E4F8'/%3e %3cpath d='M16.856 14.8848L16.9194 15.4872L16.9166 16.5657L16.8535 15.9679L16.856 14.8848Z' fill='%2383FF73'/%3e %3cpath d='M9.44019 11.1742L9.57946 11.8056L9.89026 10.9692L9.75378 10.3259L9.44019 11.1742Z' fill='%23FF9100'/%3e %3cpath d='M15.5706 22.0603L15.4723 22.2802L15.0063 22.6909L15.0863 22.4876L15.5706 22.0603Z' fill='%230008FF'/%3e %3cpath d='M24.808 13.0778L25.2704 12.4939L25.0486 12.2671L24.5923 12.8557L24.808 13.0778Z' fill='%23FFE600'/%3e %3cpath d='M18.2807 19.0008L19.6116 18.6442L19.3916 18.5767L18.0525 18.9303L18.2807 19.0008Z' fill='%2300CCFF'/%3e %3cpath d='M16.669 19.1052L16.6884 19.5924L16.4006 20.4226L16.3755 19.954L16.669 19.1052Z' fill='%2300A0FF'/%3e %3cpath d='M10.1294 19.1456L10.2049 19.3845L9.97664 18.5074L9.88989 18.2253L10.1294 19.1456Z' fill='%2300CCFF'/%3e %3cpath d='M23.5962 12.5811L24.0215 12.0262L23.764 12.1407L23.3472 12.6751L23.5962 12.5811Z' fill='%23FFD300'/%3e %3cpath d='M10.873 20.9626L10.894 21.011L10.5474 20.299L10.5063 20.2094L10.873 20.9626Z' fill='%230064FF'/%3e %3cpath d='M17.2449 18.0983L18.616 17.7771L18.4726 17.47L17.0947 17.7789L17.2449 18.0983Z' fill='%231CFFDB'/%3e %3cpath d='M18.2737 16.777L19.6002 16.4872L19.5526 16.1246L18.2236 16.4089L18.2737 16.777Z' fill='%235AFF9D'/%3e %3cpath d='M12.5339 6.57788L12.3501 7.03656L12.9714 7.14115L13.0917 6.70011L12.5339 6.57788Z' fill='maroon'/%3e %3cpath d='M24.5642 14.8733L25.3708 14.4054L25.2833 14.0245L24.479 14.5082L24.5642 14.8733Z' fill='%23B4FF43'/%3e %3cpath d='M24.5924 12.8557L25.0487 12.2671L24.8063 12.1034L24.3569 12.6913L24.5924 12.8557Z' fill='%23FFDB00'/%3e %3cpath d='M22.1891 13.4705L22.8955 13.0463L22.7045 13.3133L22.0071 13.7142L22.1891 13.4705Z' fill='%23E7FF0F'/%3e %3cpath d='M23.852 12.5521L24.2857 11.9812L24.0215 12.0261L23.5962 12.581L23.852 12.5521Z' fill='%23FFD000'/%3e %3cpath d='M18.5085 19.0106L19.8314 18.6534L19.6119 18.6444L18.281 19.001L18.5085 19.0106Z' fill='%2300D0FF'/%3e %3cpath d='M21.9631 17.6831L23.2158 17.3424L23.3478 17.0571L22.0873 17.4061L21.9631 17.6831Z' fill='%2330FFC7'/%3e %3cpath d='M24.3568 12.6911L24.8062 12.1032L24.5497 12.0071L24.1079 12.589L24.3568 12.6911Z' fill='%23FFD000'/%3e %3cpath d='M24.1078 12.5893L24.5496 12.0074L24.2857 11.9814L23.8521 12.5523L24.1078 12.5893Z' fill='%23FFCC00'/%3e %3cpath d='M23.5132 16.3927L24.5876 16.0111L24.6192 15.6349L23.542 16.0301L23.5132 16.3927Z' fill='%236DFF8A'/%3e %3cpath d='M19.5859 15.2294L20.714 14.9722L20.6709 15.3281L19.5464 15.5799L19.5859 15.2294Z' fill='%2394FF63'/%3e %3cpath d='M20.9059 14.3277L21.8538 14.0017L21.7336 14.3259L20.7927 14.6356L20.9059 14.3277Z' fill='%23C1FF36'/%3e %3cpath d='M20.4326 18.3325L21.7273 18.0177L21.543 18.1785L20.2471 18.4955L20.4326 18.3325Z' fill='%230CF4EB'/%3e %3cpath d='M17.0944 17.7787L18.4722 17.4699L18.3572 17.1338L16.9734 17.4293L17.0944 17.7787Z' fill='%232CFFCA'/%3e %3cpath d='M15.5845 9.76025L15.7427 10.1541L16.1211 11.1359L15.9256 10.742L15.5845 9.76025Z' fill='%23FF6000'/%3e %3cpath d='M16.4124 12.1865L16.5495 12.6924L16.754 13.783L16.6095 13.2765L16.4124 12.1865Z' fill='%23FFE600'/%3e %3cpath d='M13.8572 23.1355L13.7151 23.0653L13.2134 23.0367L13.3262 23.1052L13.8572 23.1355Z' fill='%230000ED'/%3e %3cpath d='M9.60917 16.8586L9.73332 17.2723L9.66463 16.3103L9.53735 15.8577L9.60917 16.8586Z' fill='%2356FFA0'/%3e %3cpath d='M18.2238 16.409L19.5527 16.1248L19.5397 15.76L18.2087 16.0388L18.2238 16.409Z' fill='%236DFF8A'/%3e %3cpath d='M18.7291 18.9589L20.0446 18.6034L19.831 18.6533L18.5081 19.0105L18.7291 18.9589Z' fill='%2300D4FF'/%3e %3cpath d='M10.0771 8.9822L10.154 9.5956L10.6314 9.00369L10.5552 8.38672L10.0771 8.9822Z' fill='%23FF1A00'/%3e %3cpath d='M24.4792 14.5083L25.2834 14.0246L25.1582 13.6702L24.3579 14.1667L24.4792 14.5083Z' fill='%23CAFF2C'/%3e %3cpath d='M12.2119 22.5812L12.1583 22.4225L11.7129 22.0334L11.7366 22.1661L12.2119 22.5812Z' fill='%23000CFF'/%3e %3cpath d='M15.0066 22.6912L14.8572 22.7673L14.3718 23.0222L14.4974 22.9586L15.0066 22.6912Z' fill='blue'/%3e %3cpath d='M16.5238 19.184L17.8295 18.8008L17.617 18.6156L16.2981 18.9872L16.5238 19.184Z' fill='%2300D0FF'/%3e %3cpath d='M16.2979 18.9871L17.6168 18.6155L17.4203 18.3793L16.0889 18.7363L16.2979 18.9871Z' fill='%2300DCFE'/%3e %3cpath d='M11.7366 22.1661L11.7128 22.0335L11.2978 21.5391L11.2937 21.6386L11.7366 22.1661Z' fill='%230028FF'/%3e %3cpath d='M22.3949 13.2773L23.1113 12.8314L22.8952 13.0461L22.1887 13.4703L22.3949 13.2773Z' fill='%23F8F500'/%3e %3cpath d='M11.1761 7.37181L11.0986 7.94784L11.6929 7.6797L11.7461 7.11475L11.1761 7.37181Z' fill='%23A40000'/%3e %3cpath d='M16.7606 19.3218L18.0528 18.9304L17.8297 18.8009L16.5239 19.1841L16.7606 19.3218Z' fill='%2300C8FF'/%3e %3cpath d='M16.4007 20.4229L16.3559 20.7995L15.9978 21.4935L16.0319 21.1388L16.4007 20.4229Z' fill='%230064FF'/%3e %3cpath d='M9.36157 12.735L9.52412 13.3462L9.73858 12.4375L9.57963 11.8054L9.36157 12.735Z' fill='gold'/%3e %3cpath d='M10.5064 20.2095L10.5475 20.2992L10.2628 19.5194L10.2051 19.3844L10.5064 20.2095Z' fill='%230098FF'/%3e %3cpath d='M16.9738 17.4293L18.3576 17.1338L18.274 16.7772L16.8853 17.0585L16.9738 17.4293Z' fill='%2343FFB4'/%3e %3cpath d='M16.089 18.7365L17.4204 18.3795L17.2449 18.0981L15.9019 18.4378L16.089 18.7365Z' fill='%2306ECF1'/%3e %3cpath d='M12.7083 22.8736L12.6234 22.6964L12.1584 22.4222L12.2121 22.581L12.7083 22.8736Z' fill='blue'/%3e %3cpath d='M22.0869 17.4063L23.3475 17.0573L23.4475 16.7379L22.1806 17.0941L22.0869 17.4063Z' fill='%2343FFB4'/%3e %3cpath d='M23.5419 16.0297L24.6191 15.6346L24.6114 15.2521L23.5332 15.6593L23.5419 16.0297Z' fill='%2383FF73'/%3e %3cpath d='M13.0917 6.70032L12.9714 7.14136L13.593 7.42673L13.65 7.00091L13.0917 6.70032Z' fill='%23840000'/%3e %3cpath d='M20.5966 18.1183L21.8904 17.8065L21.727 18.0179L20.4324 18.3327L20.5966 18.1183Z' fill='%2319FFDE'/%3e %3cpath d='M16.9165 16.5658L16.9759 17.1426L16.8713 18.1605L16.811 17.5972L16.9165 16.5658Z' fill='%2340FFB7'/%3e %3cpath d='M17.0022 19.3969L18.2809 19.0009L18.0527 18.9304L16.7605 19.3218L17.0022 19.3969Z' fill='%2300C4FF'/%3e %3cpath d='M21.0507 14.0566L22.0071 13.714L21.8541 14.0018L20.9062 14.3278L21.0507 14.0566Z' fill='%23D4FF23'/%3e %3cpath d='M19.6593 14.9L20.7929 14.636L20.7138 14.9723L19.5857 15.2295L19.6593 14.9Z' fill='%23AAFF4D'/%3e %3cpath d='M11.2935 21.6386L11.2976 21.539L10.9231 20.9512L10.8938 21.0114L11.2935 21.6386Z' fill='%23004CFF'/%3e %3cpath d='M18.9381 18.8472L20.2469 18.4957L20.0447 18.6035L18.7292 18.959L18.9381 18.8472Z' fill='%2300E0FB'/%3e %3cpath d='M15.9022 18.4379L17.2452 18.0982L17.095 17.7788L15.7417 18.0988L15.9022 18.4379Z' fill='%2316FFE1'/%3e %3cpath d='M24.3576 14.1669L25.1579 13.6704L24.998 13.3519L24.2034 13.8578L24.3576 14.1669Z' fill='%23DEFF19'/%3e %3cpath d='M15.1743 8.8717L15.2875 9.26886L15.7428 10.1541L15.5846 9.76017L15.1743 8.8717Z' fill='%23FF2900'/%3e %3cpath d='M22.6201 13.1401L23.3471 12.6749L23.1114 12.8314L22.395 13.2772L22.6201 13.1401Z' fill='%23FFEA00'/%3e %3cpath d='M18.209 16.0387L19.5399 15.7599L19.5619 15.4023L18.2295 15.6758L18.209 16.0387Z' fill='%2383FF73'/%3e %3cpath d='M9.89031 18.2254L9.97705 18.5075L9.82812 17.5996L9.73389 17.2726L9.89031 18.2254Z' fill='%231FFFD7'/%3e %3cpath d='M13.2133 23.0366L13.0965 22.8489L12.6233 22.6965L12.7081 22.8738L13.2133 23.0366Z' fill='blue'/%3e %3cpath d='M17.2425 19.4073L18.5082 19.0104L18.2807 19.0007L17.002 19.3967L17.2425 19.4073Z' fill='%2300C4FF'/%3e %3cpath d='M16.8851 17.0584L18.2738 16.7771L18.2238 16.4091L16.8313 16.6756L16.8851 17.0584Z' fill='%2356FFA0'/%3e %3cpath d='M14.3715 23.0222L14.2009 22.958L13.7148 23.0652L13.8569 23.1354L14.3715 23.0222Z' fill='blue'/%3e %3cpath d='M15.7411 18.0987L17.0944 17.7787L16.9735 17.4292L15.6113 17.7277L15.7411 18.0987Z' fill='%2329FFCE'/%3e %3cpath d='M24.2035 13.8578L24.9981 13.3519L24.8079 13.0779L24.0203 13.5894L24.2035 13.8578Z' fill='%23EEFF09'/%3e %3cpath d='M13.6501 7.00085L13.593 7.42668L14.1973 7.88556L14.1933 7.47229L13.6501 7.00085Z' fill='%23920000'/%3e %3cpath d='M15.9977 21.4934L15.883 21.7354L15.4724 22.2804L15.5708 22.0605L15.9977 21.4934Z' fill='%230038FF'/%3e %3cpath d='M22.8585 13.0626L23.5964 12.5808L23.3473 12.6748L22.6204 13.14L22.8585 13.0626Z' fill='%23FFDE00'/%3e %3cpath d='M23.5331 15.6591L24.6113 15.2519L24.5643 14.8732L23.4871 15.2907L23.5331 15.6591Z' fill='%239AFF5D'/%3e %3cpath d='M10.8939 21.0111L10.9232 20.9509L10.5985 20.2837L10.5474 20.2991L10.8939 21.0111Z' fill='%230074FF'/%3e %3cpath d='M22.1809 17.0941L23.4478 16.7379L23.5132 16.3925L22.2416 16.7545L22.1809 17.0941Z' fill='%235AFF9D'/%3e %3cpath d='M15.3302 19.5999L16.5237 19.1838L16.2981 18.9871L15.0867 19.3876L15.3302 19.5999Z' fill='%2300C4FF'/%3e %3cpath d='M15.0865 19.3879L16.2978 18.9873L16.0888 18.7365L14.8606 19.1173L15.0865 19.3879Z' fill='%2300D0FF'/%3e %3cpath d='M9.40479 14.3222L9.55951 14.8721L9.67591 13.9267L9.52397 13.3466L9.40479 14.3222Z' fill='%23D1FF26'/%3e %3cpath d='M21.2227 13.8293L22.1889 13.4705L22.0069 13.7142L21.0505 14.0567L21.2227 13.8293Z' fill='%23E4FF13'/%3e %3cpath d='M14.7063 8.10181L14.7676 8.50546L15.2875 9.26883L15.1744 8.87167L14.7063 8.10181Z' fill='%23DF0000'/%3e %3cpath d='M20.7354 17.8578L22.0289 17.5497L21.8907 17.8064L20.5969 18.1182L20.7354 17.8578Z' fill='%2329FFCE'/%3e %3cpath d='M16.7539 13.783L16.8177 14.3899L16.9191 15.4871L16.8557 14.8847L16.7539 13.783Z' fill='%23C4FF33'/%3e %3cpath d='M15.585 19.749L16.7603 19.3218L16.5237 19.1841L15.3301 19.6002L15.585 19.749Z' fill='%2300BCFF'/%3e %3cpath d='M19.1294 18.6778L20.4323 18.3325L20.2467 18.4955L18.938 18.8471L19.1294 18.6778Z' fill='%2309F0EE'/%3e %3cpath d='M19.7651 14.5996L20.9059 14.3278L20.7927 14.6356L19.6592 14.8996L19.7651 14.5996Z' fill='%23BEFF39'/%3e %3cpath d='M14.1931 7.47229L14.1971 7.88556L14.7672 8.5054L14.706 8.10175L14.1931 7.47229Z' fill='%23B20000'/%3e %3cpath d='M17.4762 19.3531L18.7293 18.959L18.5083 19.0106L17.2427 19.4075L17.4762 19.3531Z' fill='%2300CCFF'/%3e %3cpath d='M14.8608 19.1173L16.089 18.7364L15.9018 18.4377L14.6582 18.7951L14.8608 19.1173Z' fill='%2300E0FB'/%3e %3cpath d='M24.0201 13.5895L24.8078 13.078L24.5921 12.8558L23.8127 13.3691L24.0201 13.5895Z' fill='%23FBF100'/%3e %3cpath d='M9.75391 10.3259L9.89039 10.9692L10.2869 10.2491L10.1542 9.59534L9.75391 10.3259Z' fill='%23FF5200'/%3e %3cpath d='M23.1032 13.0471L23.8522 12.5519L23.5963 12.5808L22.8584 13.0626L23.1032 13.0471Z' fill='%23FFDB00'/%3e %3cpath d='M16.1211 11.1356L16.247 11.6425L16.5497 12.6921L16.4125 12.1862L16.1211 11.1356Z' fill='%23FF9F00'/%3e %3cpath d='M10.2048 19.3847L10.2625 19.5197L10.0469 18.6911L9.97656 18.5076L10.2048 19.3847Z' fill='%2300D4FF'/%3e %3cpath d='M12.1581 22.4222L12.1492 22.1609L11.7352 21.7994L11.7126 22.0332L12.1581 22.4222Z' fill='%230028FF'/%3e %3cpath d='M15.8451 19.8301L17.0019 19.3967L16.7602 19.3215L15.585 19.7487L15.8451 19.8301Z' fill='%2300B8FF'/%3e %3cpath d='M18.229 15.676L19.5615 15.4026L19.6182 15.0615L18.2847 15.3298L18.229 15.676Z' fill='%239AFF5D'/%3e %3cpath d='M16.8712 18.1602L16.8868 18.668L16.6884 19.5924L16.6689 19.1052L16.8712 18.1602Z' fill='%2302E8F4'/%3e %3cpath d='M11.7127 22.0333L11.7352 21.7995L11.3495 21.34L11.2976 21.5389L11.7127 22.0333Z' fill='%230040FF'/%3e %3cpath d='M16.8311 16.6757L18.2235 16.4092L18.2085 16.0389L16.8135 16.2907L16.8311 16.6757Z' fill='%236DFF8A'/%3e %3cpath d='M15.6115 17.7275L16.9737 17.429L16.8851 17.0582L15.5159 17.3339L15.6115 17.7275Z' fill='%2340FFB7'/%3e %3cpath d='M23.8129 13.3688L24.5923 12.8555L24.3568 12.6912L23.5869 13.2023L23.8129 13.3688Z' fill='%23FFE600'/%3e %3cpath d='M23.3483 13.0944L24.108 12.5893L23.8522 12.5522L23.1033 13.0474L23.3483 13.0944Z' fill='gold'/%3e %3cpath d='M13.7149 23.0649L13.5664 22.875L13.0964 22.8486L13.2132 23.0364L13.7149 23.0649Z' fill='blue'/%3e %3cpath d='M23.5871 13.2023L24.357 12.6912L24.1081 12.5891L23.3484 13.0942L23.5871 13.2023Z' fill='%23FFDB00'/%3e %3cpath d='M14.6584 18.7952L15.902 18.4378L15.7415 18.0988L14.4841 18.4296L14.6584 18.7952Z' fill='%230FF8E7'/%3e %3cpath d='M12.6233 22.6965L12.5815 22.4157L12.1494 22.1611L12.1583 22.4224L12.6233 22.6965Z' fill='%230018FF'/%3e %3cpath d='M11.7463 7.11499L11.6931 7.67995L12.3226 7.59124L12.3502 7.03699L11.7463 7.11499Z' fill='%23890000'/%3e %3cpath d='M15.4725 22.2805L15.3011 22.3759L14.8572 22.7673L15.0066 22.6912L15.4725 22.2805Z' fill='%230018FF'/%3e %3cpath d='M23.4869 15.2909L24.5642 14.8735L24.479 14.5084L23.4045 14.934L23.4869 15.2909Z' fill='%23B1FF46'/%3e %3cpath d='M21.4178 13.6518L22.3948 13.2773L22.1886 13.4704L21.2224 13.8293L21.4178 13.6518Z' fill='%23F1FC06'/%3e %3cpath d='M11.2981 21.539L11.35 21.3401L11.0021 20.7937L10.9236 20.9512L11.2981 21.539Z' fill='%230060FF'/%3e %3cpath d='M22.2415 16.7545L23.513 16.3924L23.5417 16.0298L22.2674 16.3963L22.2415 16.7545Z' fill='%236DFF8A'/%3e %3cpath d='M16.1039 19.842L17.2427 19.4074L17.0021 19.3969L15.8452 19.8303L16.1039 19.842Z' fill='%2300B8FF'/%3e %3cpath d='M9.53735 15.8578L9.66463 16.3104L9.68631 15.3633L9.55939 14.8719L9.53735 15.8578Z' fill='%2394FF63'/%3e %3cpath d='M17.6965 19.2345L18.9381 18.8469L18.7292 18.9587L17.4761 19.3528L17.6965 19.2345Z' fill='%2300D8FF'/%3e %3cpath d='M14.303 20.0434L15.3301 19.6001L15.0867 19.3878L14.0376 19.8119L14.303 20.0434Z' fill='%2300B4FF'/%3e %3cpath d='M20.8444 17.558L22.1381 17.2542L22.0288 17.5497L20.7354 17.8579L20.8444 17.558Z' fill='%233CFFBA'/%3e %3cpath d='M19.2987 18.4552L20.5967 18.1182L20.4325 18.3325L19.1296 18.6778L19.2987 18.4552Z' fill='%2316FFE1'/%3e %3cpath d='M14.0378 19.8121L15.0869 19.388L14.861 19.1174L13.7913 19.5171L14.0378 19.8121Z' fill='%2300C0FF'/%3e %3cpath d='M10.5472 20.2993L10.5984 20.2839L10.3317 19.5533L10.2625 19.5195L10.5472 20.2993Z' fill='%2300A8FF'/%3e %3cpath d='M19.9009 14.3372L21.0504 14.0565L20.9059 14.3278L19.7651 14.5997L19.9009 14.3372Z' fill='%23D1FF26'/%3e %3cpath d='M10.5557 8.38649L10.6318 9.00347L11.1743 8.56788L11.0989 7.94788L10.5557 8.38649Z' fill='%23D10000'/%3e %3cpath d='M14.5806 20.2059L15.5851 19.7489L15.3301 19.6002L14.303 20.0435L14.5806 20.2059Z' fill='%2300A8FF'/%3e %3cpath d='M14.4839 18.4292L15.7412 18.0984L15.6114 17.7274L14.3425 18.0292L14.4839 18.4292Z' fill='%2323FFD4'/%3e %3cpath d='M13.0968 22.8487L13.0215 22.5568L12.5818 22.4155L12.6236 22.6963L13.0968 22.8487Z' fill='%230010FF'/%3e %3cpath d='M13.7911 19.5171L14.8609 19.1174L14.6583 18.7953L13.5696 19.1661L13.7911 19.5171Z' fill='%2300D4FF'/%3e %3cpath d='M15.5161 17.3341L16.8853 17.0584L16.8315 16.6757L15.457 16.9277L15.5161 17.3341Z' fill='%2356FFA0'/%3e %3cpath d='M14.8571 22.7671L14.6594 22.7168L14.2012 22.9578L14.3718 23.022L14.8571 22.7671Z' fill='%230008FF'/%3e %3cpath d='M16.8137 16.2905L18.2087 16.0387L18.2292 15.6758L16.833 15.9131L16.8137 16.2905Z' fill='%2383FF73'/%3e %3cpath d='M18.2849 15.3298L19.6184 15.0615L19.7085 14.7457L18.3744 15.0094L18.2849 15.3298Z' fill='%23B1FF46'/%3e %3cpath d='M23.4045 14.934L24.4789 14.5084L24.3576 14.1667L23.2878 14.5982L23.4045 14.934Z' fill='%23C4FF33'/%3e %3cpath d='M14.8638 20.2948L15.8453 19.8302L15.5852 19.7489L14.5808 20.2058L14.8638 20.2948Z' fill='%2300A8FF'/%3e %3cpath d='M21.6315 13.5291L22.6202 13.14L22.395 13.2771L21.418 13.6516L21.6315 13.5291Z' fill='%23FEED00'/%3e %3cpath d='M16.6883 19.5927L16.6351 19.9946L16.3557 20.7995L16.4005 20.4229L16.6883 19.5927Z' fill='%2300A8FF'/%3e %3cpath d='M16.3545 19.7837L17.4761 19.3529L17.2426 19.4073L16.1038 19.8419L16.3545 19.7837Z' fill='%2300C0FF'/%3e %3cpath d='M12.1496 22.1613L12.2341 21.8166L11.8522 21.4832L11.7356 21.7998L12.1496 22.1613Z' fill='%230040FF'/%3e %3cpath d='M10.9236 20.9511L11.002 20.7936L10.7005 20.1735L10.5989 20.2839L10.9236 20.9511Z' fill='%230088FF'/%3e %3cpath d='M9.73349 17.2726L9.82773 17.5995L9.76254 16.6833L9.66479 16.3105L9.73349 17.2726Z' fill='%235AFF9D'/%3e %3cpath d='M11.7353 21.7994L11.8519 21.4828L11.4962 21.0588L11.3496 21.3399L11.7353 21.7994Z' fill='%230058FF'/%3e %3cpath d='M9.57959 11.8054L9.73854 12.4375L10.0439 11.6202L9.8904 10.969L9.57959 11.8054Z' fill='%23FF9400'/%3e %3cpath d='M13.5696 19.1659L14.6583 18.7951L14.484 18.4294L13.3787 18.7674L13.5696 19.1659Z' fill='%2306ECF1'/%3e %3cpath d='M13.477 20.5037L14.3031 20.0437L14.0377 19.8121L13.186 20.2498L13.477 20.5037Z' fill='%2300A0FF'/%3e %3cpath d='M17.8982 19.0553L19.1296 18.6777L18.9381 18.847L17.6965 19.2345L17.8982 19.0553Z' fill='%2302E8F4'/%3e %3cpath d='M13.1861 20.2497L14.0378 19.8121L13.7912 19.5171L12.9155 19.9264L13.1861 20.2497Z' fill='%2300B0FF'/%3e %3cpath d='M16.9195 15.4869L16.979 16.0778L16.9761 17.1423L16.9167 16.5654L16.9195 15.4869Z' fill='%2383FF73'/%3e %3cpath d='M12.5815 22.4156L12.6325 22.0509L12.2339 21.8163L12.1494 22.161L12.5815 22.4156Z' fill='%230034FF'/%3e %3cpath d='M22.2674 16.3964L23.5417 16.0298L23.533 15.6594L22.2578 16.0289L22.2674 16.3964Z' fill='%2383FF73'/%3e %3cpath d='M14.2008 22.9577L14.0212 22.7743L13.5662 22.8751L13.7147 23.0649L14.2008 22.9577Z' fill='%230008FF'/%3e %3cpath d='M14.3424 18.0292L15.6113 17.7275L15.5156 17.3339L14.2375 17.6047L14.3424 18.0292Z' fill='%2339FFBE'/%3e %3cpath d='M15.7429 10.1542L15.854 10.6638L16.2472 11.6429L16.1213 11.136L15.7429 10.1542Z' fill='%23FF6000'/%3e %3cpath d='M13.7809 20.6816L14.5805 20.2057L14.3029 20.0433L13.4768 20.5034L13.7809 20.6816Z' fill='%230094FF'/%3e %3cpath d='M20.063 14.1195L21.2225 13.8293L21.0504 14.0568L19.9009 14.3375L20.063 14.1195Z' fill='%23E1FF16'/%3e %3cpath d='M19.4408 18.1849L20.7351 17.858L20.5966 18.1184L19.2986 18.4554L19.4408 18.1849Z' fill='%2329FFCE'/%3e %3cpath d='M20.9211 17.2261L22.2153 16.9271L22.1379 17.2541L20.8442 17.5579L20.9211 17.2261Z' fill='%2353FFA4'/%3e %3cpath d='M11.3497 21.3399L11.4963 21.0589L11.1755 20.5547L11.0017 20.7935L11.3497 21.3399Z' fill='%230074FF'/%3e %3cpath d='M15.1447 20.3079L16.1037 19.8418L15.8451 19.8301L14.8635 20.2947L15.1447 20.3079Z' fill='%2300A8FF'/%3e %3cpath d='M23.288 14.5981L24.3578 14.1667L24.2036 13.8575L23.1401 14.2923L23.288 14.5981Z' fill='%23D7FF1F'/%3e %3cpath d='M12.9153 19.926L13.791 19.5167L13.5695 19.1656L12.6719 19.5413L12.9153 19.926Z' fill='%2300C4FF'/%3e %3cpath d='M21.8575 13.4651L22.8581 13.063L22.62 13.1404L21.6313 13.5294L21.8575 13.4651Z' fill='%23FFE600'/%3e %3cpath d='M9.97681 18.5073L10.0472 18.6908L9.90663 17.8334L9.82788 17.5994L9.97681 18.5073Z' fill='%2326FFD1'/%3e %3cpath d='M13.5663 22.8753L13.4575 22.5811L13.021 22.557L13.0963 22.8489L13.5663 22.8753Z' fill='%230014FF'/%3e %3cpath d='M15.457 16.9276L16.8315 16.6755L16.8139 16.2905L15.4363 16.5188L15.457 16.9276Z' fill='%236DFF8A'/%3e %3cpath d='M12.3502 7.03662L12.3225 7.59087L12.9699 7.68538L12.9715 7.14122L12.3502 7.03662Z' fill='maroon'/%3e %3cpath d='M12.2341 21.8162L12.4594 21.4101L12.1094 21.1045L11.8523 21.4828L12.2341 21.8162Z' fill='%23005CFF'/%3e %3cpath d='M12.8649 20.9655L13.4769 20.5037L13.1859 20.2498L12.5454 20.6867L12.8649 20.9655Z' fill='%23008CFF'/%3e %3cpath d='M11.8523 21.4828L12.1094 21.1044L11.7834 20.7157L11.4966 21.0588L11.8523 21.4828Z' fill='%230070FF'/%3e %3cpath d='M13.3786 18.7672L14.484 18.4292L14.3426 18.0292L13.2231 18.3313L13.3786 18.7672Z' fill='%231CFFDB'/%3e %3cpath d='M12.5453 20.6865L13.1858 20.2496L12.9152 19.9263L12.248 20.3317L12.5453 20.6865Z' fill='%23009CFF'/%3e %3cpath d='M14.0905 20.7797L14.8633 20.2948L14.5804 20.2058L13.7808 20.6817L14.0905 20.7797Z' fill='%230094FF'/%3e %3cpath d='M13.0212 22.5571L13.0381 22.1811L12.6325 22.0511L12.5815 22.4158L13.0212 22.5571Z' fill='%23002CFF'/%3e %3cpath d='M16.5496 12.6923L16.614 13.3034L16.8179 14.3898L16.7541 13.7829L16.5496 12.6923Z' fill='%23FFE600'/%3e %3cpath d='M16.5912 19.6566L17.6967 19.2346L17.4763 19.3529L16.3547 19.7836L16.5912 19.6566Z' fill='%2300CCFF'/%3e %3cpath d='M16.3556 20.7993L16.227 21.0683L15.8828 21.7354L15.9975 21.4934L16.3556 20.7993Z' fill='%230070FF'/%3e %3cpath d='M16.8333 15.9132L18.2295 15.6759L18.2852 15.3297L16.889 15.5532L16.8333 15.9132Z' fill='%239AFF5D'/%3e %3cpath d='M18.3743 15.009L19.7083 14.7454L19.8296 14.4633L18.4955 14.7227L18.3743 15.009Z' fill='%23C4FF33'/%3e %3cpath d='M12.4592 21.4102L12.8649 20.9653L12.5454 20.6865L12.1091 21.1046L12.4592 21.4102Z' fill='%230074FF'/%3e %3cpath d='M13.1984 21.1611L13.7809 20.6816L13.4768 20.5034L12.8647 20.9653L13.1984 21.1611Z' fill='%230080FF'/%3e %3cpath d='M12.6325 22.0508L12.8246 21.6249L12.4592 21.41L12.2339 21.8162L12.6325 22.0508Z' fill='%23004CFF'/%3e %3cpath d='M10.2627 19.5196L10.3319 19.5534L10.1302 18.7773L10.0471 18.6909L10.2627 19.5196Z' fill='%2300E0FB'/%3e %3cpath d='M23.1401 14.2925L24.2036 13.8577L24.0204 13.5894L22.9648 14.0249L23.1401 14.2925Z' fill='%23E7FF0F'/%3e %3cpath d='M12.1094 21.1046L12.5457 20.6865L12.2484 20.3317L11.7834 20.7159L12.1094 21.1046Z' fill='%230084FF'/%3e %3cpath d='M22.0906 13.4606L23.1033 13.0472L22.8585 13.0627L21.8579 13.4649L22.0906 13.4606Z' fill='%23FFE200'/%3e %3cpath d='M12.6716 19.5417L13.5692 19.166L13.3783 18.7676L12.4614 19.1051L12.6716 19.5417Z' fill='%2300E0FB'/%3e %3cpath d='M12.248 20.3319L12.9152 19.9265L12.6717 19.5417L11.9802 19.9097L12.248 20.3319Z' fill='%2300B4FF'/%3e %3cpath d='M11.4966 21.059L11.7834 20.7159L11.4896 20.2535L11.1758 20.5548L11.4966 21.059Z' fill='%23008CFF'/%3e %3cpath d='M10.5987 20.2838L10.7003 20.1734L10.4527 19.4945L10.332 19.5533L10.5987 20.2838Z' fill='%2300B4FF'/%3e %3cpath d='M12.8247 21.625L13.1986 21.1612L12.8649 20.9653L12.4592 21.4101L12.8247 21.625Z' fill='%230068FF'/%3e %3cpath d='M22.2579 16.0289L23.5331 15.6594L23.487 15.2909L22.2129 15.6618L22.2579 16.0289Z' fill='%239AFF5D'/%3e %3cpath d='M11.0018 20.7937L11.1756 20.5548L10.8977 19.9827L10.7002 20.1735L11.0018 20.7937Z' fill='%23009CFF'/%3e %3cpath d='M18.076 18.8193L19.2986 18.4552L19.1295 18.6778L17.8982 19.0553L18.076 18.8193Z' fill='%2313FCE4'/%3e %3cpath d='M15.4171 20.2452L16.3546 19.7838L16.1038 19.8421L15.1448 20.3082L15.4171 20.2452Z' fill='%2300B0FF'/%3e %3cpath d='M9.52441 13.3462L9.67635 13.9263L9.88527 13.0461L9.73888 12.4375L9.52441 13.3462Z' fill='%23FFDB00'/%3e %3cpath d='M14.2379 17.6048L15.516 17.334L15.457 16.9276L14.1724 17.1666L14.2379 17.6048Z' fill='%2353FFA4'/%3e %3cpath d='M20.2475 13.952L21.4181 13.652L21.2228 13.8294L20.0632 14.1196L20.2475 13.952Z' fill='%23EEFF09'/%3e %3cpath d='M22.9647 14.025L24.0202 13.5894L23.8128 13.369L22.7666 13.8028L22.9647 14.025Z' fill='%23F4F802'/%3e %3cpath d='M11.7833 20.7157L12.2482 20.3315L11.9804 19.9093L11.4895 20.2533L11.7833 20.7157Z' fill='%2300A0FF'/%3e %3cpath d='M22.3235 13.5168L23.3481 13.0943L23.1031 13.0474L22.0903 13.4608L22.3235 13.5168Z' fill='%23FFE200'/%3e %3cpath d='M13.5381 21.2691L14.0907 20.7796L13.781 20.6816L13.1985 21.1612L13.5381 21.2691Z' fill='%23007CFF'/%3e %3cpath d='M14.3981 20.7948L15.1446 20.3082L14.8635 20.2949L14.0906 20.7798L14.3981 20.7948Z' fill='%230094FF'/%3e %3cpath d='M15.8831 21.7354L15.6919 21.8564L15.301 22.3758L15.4725 22.2804L15.8831 21.7354Z' fill='%230044FF'/%3e %3cpath d='M10.1545 9.59528L10.2873 10.2491L10.76 9.66613L10.6319 9.00342L10.1545 9.59528Z' fill='%23FF1E00'/%3e %3cpath d='M20.9634 16.8709L22.2589 16.5771L22.2154 16.9271L20.9211 17.2262L20.9634 16.8709Z' fill='%2366FF90'/%3e %3cpath d='M13.0379 22.181L13.1963 21.7438L12.8245 21.6251L12.6323 22.0511L13.0379 22.181Z' fill='%230048FF'/%3e %3cpath d='M22.7666 13.8028L23.8129 13.369L23.5868 13.2025L22.551 13.6319L22.7666 13.8028Z' fill='%23FEED00'/%3e %3cpath d='M19.5523 17.873L20.8441 17.558L20.735 17.8578L19.4407 18.1847L19.5523 17.873Z' fill='%233CFFBA'/%3e %3cpath d='M22.5512 13.6316L23.587 13.2021L23.3483 13.094L22.3237 13.5165L22.5512 13.6316Z' fill='%23FFE200'/%3e %3cpath d='M13.2231 18.3316L14.3425 18.0295L14.2377 17.605L13.1072 17.8689L13.2231 18.3316Z' fill='%2336FFC1'/%3e %3cpath d='M13.1963 21.7435L13.538 21.2689L13.1984 21.161L12.8245 21.6248L13.1963 21.7435Z' fill='%230064FF'/%3e %3cpath d='M11.9801 19.9097L12.6716 19.5417L12.4614 19.1051L11.7485 19.4306L11.9801 19.9097Z' fill='%2300D0FF'/%3e %3cpath d='M15.2876 9.2688L15.3806 9.78269L15.8541 10.6636L15.7429 10.154L15.2876 9.2688Z' fill='%23FF2900'/%3e %3cpath d='M15.436 16.519L16.8136 16.2907L16.8329 15.9133L15.4543 16.1183L15.436 16.519Z' fill='%2387FF70'/%3e %3cpath d='M13.4577 22.5808L13.4406 22.2024L13.0381 22.1807L13.0212 22.5567L13.4577 22.5808Z' fill='%230030FF'/%3e %3cpath d='M12.4616 19.1048L13.3785 18.7673L13.2231 18.3313L12.29 18.6271L12.4616 19.1048Z' fill='%2313FCE4'/%3e %3cpath d='M16.9757 17.1426L16.9892 17.6727L16.8866 18.6683L16.8711 18.1605L16.9757 17.1426Z' fill='%2343FFB4'/%3e %3cpath d='M11.1754 20.555L11.4892 20.2537L11.2349 19.729L10.8975 19.9828L11.1754 20.555Z' fill='%2300ACFF'/%3e %3cpath d='M15.301 22.3757L15.0783 22.3468L14.6594 22.7168L14.8571 22.7671L15.301 22.3757Z' fill='%23002CFF'/%3e %3cpath d='M11.0986 7.94806L11.174 8.56807L11.7673 8.30236L11.6929 7.67993L11.0986 7.94806Z' fill='%23A80000'/%3e %3cpath d='M16.8072 19.4637L17.8983 19.0554L17.6966 19.2347L16.5911 19.6567L16.8072 19.4637Z' fill='%2300DCFE'/%3e %3cpath d='M12.9714 7.14111L12.9697 7.68527L13.6171 7.96139L13.5929 7.4265L12.9714 7.14111Z' fill='maroon'/%3e %3cpath d='M14.0215 22.7744L13.8803 22.4868L13.4578 22.581L13.5665 22.8752L14.0215 22.7744Z' fill='%230020FF'/%3e %3cpath d='M18.4956 14.7228L19.8297 14.4633L19.979 14.2223L18.6455 14.4782L18.4956 14.7228Z' fill='%23D7FF1F'/%3e %3cpath d='M11.4897 20.2534L11.9806 19.9094L11.7491 19.4303L11.2354 19.7287L11.4897 20.2534Z' fill='%2300C0FF'/%3e %3cpath d='M14.6594 22.7166L14.4503 22.548L14.0215 22.7742L14.2011 22.9576L14.6594 22.7166Z' fill='%230020FF'/%3e %3cpath d='M16.8889 15.553L18.285 15.3295L18.3746 15.009L16.9799 15.2197L16.8889 15.553Z' fill='%23B1FF46'/%3e %3cpath d='M22.2127 15.6617L23.4868 15.2908L23.4044 14.934L22.1333 15.3046L22.2127 15.6617Z' fill='%23B1FF46'/%3e %3cpath d='M9.55957 14.8721L9.6865 15.3634L9.799 14.4555L9.67597 13.9266L9.55957 14.8721Z' fill='%23CEFF29'/%3e %3cpath d='M13.8752 21.2863L14.3982 20.7947L14.0907 20.7797L13.5381 21.2692L13.8752 21.2863Z' fill='%23007CFF'/%3e %3cpath d='M20.449 13.8393L21.6315 13.5292L21.418 13.6518L20.2473 13.9518L20.449 13.8393Z' fill='%23FBF100'/%3e %3cpath d='M15.6735 20.107L16.5909 19.6565L16.3544 19.7836L15.417 20.2449L15.6735 20.107Z' fill='%2300BCFF'/%3e %3cpath d='M10.7002 20.1734L10.8977 19.9826L10.6697 19.3563L10.4526 19.4946L10.7002 20.1734Z' fill='%2300C4FF'/%3e %3cpath d='M14.6959 20.7263L15.417 20.2451L15.1447 20.3081L14.3982 20.7947L14.6959 20.7263Z' fill='%23009CFF'/%3e %3cpath d='M14.1723 17.1666L15.4569 16.9277L15.4362 16.5189L14.1479 16.7257L14.1723 17.1666Z' fill='%236DFF8A'/%3e %3cpath d='M13.4404 22.2026L13.5654 21.7631L13.1963 21.7438L13.0378 22.1809L13.4404 22.2026Z' fill='%23004CFF'/%3e %3cpath d='M18.2254 18.5326L19.441 18.1848L19.2988 18.4553L18.0762 18.8195L18.2254 18.5326Z' fill='%2323FFD4'/%3e %3cpath d='M13.5654 21.763L13.875 21.2862L13.5379 21.269L13.1963 21.7436L13.5654 21.763Z' fill='%230064FF'/%3e %3cpath d='M11.7488 19.4305L12.4616 19.1051L12.29 18.6273L11.5593 18.9063L11.7488 19.4305Z' fill='%2309F0EE'/%3e %3cpath d='M14.7673 8.50549L14.8395 9.02508L15.3803 9.78271L15.2873 9.26882L14.7673 8.50549Z' fill='%23DF0000'/%3e %3cpath d='M20.97 16.5014L22.2671 16.2131L22.2589 16.5771L20.9634 16.8709L20.97 16.5014Z' fill='%237DFF7A'/%3e %3cpath d='M10.3319 19.5532L10.4526 19.4944L10.2654 18.7733L10.1301 18.777L10.3319 19.5532Z' fill='%2302E8F4'/%3e %3cpath d='M9.66504 16.3102L9.76278 16.683L9.7838 15.7813L9.68672 15.3632L9.66504 16.3102Z' fill='%2394FF63'/%3e %3cpath d='M13.593 7.42664L13.6171 7.96153L14.2463 8.41216L14.1974 7.88552L13.593 7.42664Z' fill='%23920000'/%3e %3cpath d='M19.6302 17.5281L20.9209 17.2262L20.8441 17.558L19.5522 17.873L19.6302 17.5281Z' fill='%2350FFA7'/%3e %3cpath d='M13.1072 17.869L14.2377 17.605L14.1722 17.1667L13.0339 17.3913L13.1072 17.869Z' fill='%2350FFA7'/%3e %3cpath d='M12.2902 18.6274L13.2232 18.3316L13.1073 17.869L12.1616 18.1204L12.2902 18.6274Z' fill='%2330FFC7'/%3e %3cpath d='M22.1337 15.3049L23.4048 14.9342L23.2882 14.5984L22.022 14.9672L22.1337 15.3049Z' fill='%23C4FF33'/%3e %3cpath d='M10.0468 18.6909L10.1298 18.7773L9.99842 17.9745L9.90625 17.8335L10.0468 18.6909Z' fill='%232CFFCA'/%3e %3cpath d='M10.8976 19.9827L11.2351 19.7289L11.0267 19.1547L10.6697 19.3564L10.8976 19.9827Z' fill='%2300D4FF'/%3e %3cpath d='M9.82789 17.5995L9.90664 17.8335L9.84529 16.9685L9.7627 16.6832L9.82789 17.5995Z' fill='%235AFF9D'/%3e %3cpath d='M14.1973 7.88574L14.2462 8.41239L14.8395 9.02518L14.7674 8.50558L14.1973 7.88574Z' fill='%23B20000'/%3e %3cpath d='M11.2353 19.7287L11.749 19.4304L11.5596 18.9061L11.0269 19.1545L11.2353 19.7287Z' fill='%2300E4F8'/%3e %3cpath d='M20.6626 13.785L21.8574 13.4648L21.6313 13.5292L20.4487 13.8393L20.6626 13.785Z' fill='%23FFEA00'/%3e %3cpath d='M15.4543 16.1182L16.8329 15.9133L16.8887 15.5532L15.5114 15.7359L15.4543 16.1182Z' fill='%239DFF5A'/%3e %3cpath d='M18.6453 14.4784L19.9788 14.2224L20.1526 14.0291L18.82 14.2822L18.6453 14.4784Z' fill='%23E7FF0F'/%3e %3cpath d='M16.9973 19.2095L18.0761 18.8193L17.8983 19.0553L16.8071 19.4637L16.9973 19.2095Z' fill='%2309F0EE'/%3e %3cpath d='M16.8869 18.668L16.8277 19.0982L16.6353 19.9943L16.6885 19.5924L16.8869 18.668Z' fill='%2306ECF1'/%3e %3cpath d='M13.8801 22.4869L13.83 22.1152L13.4404 22.2027L13.4576 22.5811L13.8801 22.4869Z' fill='%23003CFF'/%3e %3cpath d='M14.2012 21.2116L14.6957 20.7261L14.398 20.7945L13.875 21.2861L14.2012 21.2116Z' fill='%230088FF'/%3e %3cpath d='M16.8179 14.3896L16.8788 14.9946L16.9788 16.0778L16.9192 15.4869L16.8179 14.3896Z' fill='%23C4FF33'/%3e %3cpath d='M16.2471 11.6427L16.3123 12.2577L16.6141 13.3034L16.5497 12.6923L16.2471 11.6427Z' fill='%23FF9F00'/%3e %3cpath d='M16.9795 15.22L18.3741 15.0093L18.4954 14.723L17.1035 14.9222L16.9795 15.22Z' fill='%23C7FF30'/%3e %3cpath d='M9.89062 10.9691L10.0441 11.6203L10.4334 10.9171L10.2872 10.249L9.89062 10.9691Z' fill='%23FF5900'/%3e %3cpath d='M15.9081 19.8973L16.8073 19.4636L16.5912 19.6565L15.6738 20.1071L15.9081 19.8973Z' fill='%2300D0FF'/%3e %3cpath d='M22.0216 14.9673L23.2878 14.5985L23.1399 14.2927L21.8804 14.6582L22.0216 14.9673Z' fill='%23D7FF1F'/%3e %3cpath d='M14.9761 20.5759L15.6735 20.1073L15.417 20.2452L14.6958 20.7264L14.9761 20.5759Z' fill='%2300ACFF'/%3e %3cpath d='M20.8834 13.7905L22.0906 13.4607L21.8579 13.4649L20.6631 13.7851L20.8834 13.7905Z' fill='%23FFE600'/%3e %3cpath d='M13.9228 21.6821L14.2016 21.2117L13.8753 21.2861L13.5657 21.7629L13.9228 21.6821Z' fill='%230070FF'/%3e %3cpath d='M13.8302 22.1152L13.9228 21.6824L13.5657 21.7632L13.4407 22.2028L13.8302 22.1152Z' fill='%230054FF'/%3e %3cpath d='M14.1477 16.7258L15.436 16.519L15.4543 16.1183L14.1653 16.2935L14.1477 16.7258Z' fill='%2387FF70'/%3e %3cpath d='M20.9404 16.1273L22.2397 15.8446L22.2671 16.2131L20.9699 16.5014L20.9404 16.1273Z' fill='%2394FF63'/%3e %3cpath d='M11.5594 18.9063L12.2901 18.6274L12.1615 18.1204L11.417 18.3499L11.5594 18.9063Z' fill='%2326FFD1'/%3e %3cpath d='M18.3419 18.2016L19.5525 17.8729L19.4409 18.1846L18.2253 18.5323L18.3419 18.2016Z' fill='%2339FFBE'/%3e %3cpath d='M14.4502 22.548L14.2781 22.2759L13.8801 22.4866L14.0214 22.7742L14.4502 22.548Z' fill='%230038FF'/%3e %3cpath d='M10.4525 19.4946L10.6696 19.3563L10.4975 18.6913L10.2654 18.7735L10.4525 19.4946Z' fill='%230CF4EB'/%3e %3cpath d='M19.6727 17.159L20.9636 16.8712L20.9213 17.2264L19.6306 17.5283L19.6727 17.159Z' fill='%2366FF90'/%3e %3cpath d='M16.635 19.9946L16.4954 20.2951L16.2271 21.0685L16.3557 20.7995L16.635 19.9946Z' fill='%2300B0FF'/%3e %3cpath d='M21.8805 14.658L23.1401 14.2925L22.9648 14.0249L21.7134 14.3856L21.8805 14.658Z' fill='%23E4FF13'/%3e %3cpath d='M13.034 17.391L14.1722 17.1665L14.1478 16.7256L13.0054 16.9103L13.034 17.391Z' fill='%236AFF8D'/%3e %3cpath d='M21.1041 13.8557L22.3235 13.5168L22.0903 13.4607L20.8831 13.7905L21.1041 13.8557Z' fill='%23FFE600'/%3e %3cpath d='M12.1614 18.1199L13.1071 17.8686L13.0338 17.3909L12.0793 17.5963L12.1614 18.1199Z' fill='%2349FFAD'/%3e %3cpath d='M18.8201 14.2823L20.1526 14.0292L20.3462 13.8887L19.0152 14.1398L18.8201 14.2823Z' fill='%23F4F802'/%3e %3cpath d='M11.6929 7.67969L11.7672 8.30211L12.3956 8.21513L12.3223 7.59094L11.6929 7.67969Z' fill='%238D0000'/%3e %3cpath d='M15.0784 22.347L14.8421 22.2014L14.4504 22.5483L14.6595 22.717L15.0784 22.347Z' fill='%230040FF'/%3e %3cpath d='M11.0269 19.1545L11.5596 18.9061L11.4172 18.3496L10.8699 18.5448L11.0269 19.1545Z' fill='%231FFFD7'/%3e %3cpath d='M10.6697 19.3563L11.0267 19.1546L10.8696 18.5449L10.4976 18.6913L10.6697 19.3563Z' fill='%2316FFE1'/%3e %3cpath d='M21.7132 14.3856L22.9645 14.0249L22.7664 13.8027L21.5247 14.1573L21.7132 14.3856Z' fill='%23F1FC06'/%3e %3cpath d='M15.5115 15.7358L16.8888 15.5532L16.9798 15.2198L15.6059 15.3819L15.5115 15.7358Z' fill='%23B4FF43'/%3e %3cpath d='M21.3198 13.9791L22.5509 13.6318L22.3234 13.5168L21.104 13.8558L21.3198 13.9791Z' fill='%23FFE600'/%3e %3cpath d='M16.2273 21.0685L16.0194 21.2211L15.6919 21.8566L15.883 21.7355L16.2273 21.0685Z' fill='%23007CFF'/%3e %3cpath d='M21.5249 14.1571L22.7667 13.8026L22.5511 13.6317L21.3201 13.9789L21.5249 14.1571Z' fill='%23FEED00'/%3e %3cpath d='M17.1563 18.9006L18.225 18.5326L18.0758 18.8195L16.9971 19.2097L17.1563 18.9006Z' fill='%231CFFDB'/%3e %3cpath d='M15.692 21.8564L15.4469 21.8561L15.0784 22.3468L15.3011 22.3758L15.692 21.8564Z' fill='%230054FF'/%3e %3cpath d='M10.6313 9.00358L10.7594 9.66628L11.2963 9.23776L11.1738 8.56799L10.6313 9.00358Z' fill='%23D60000'/%3e %3cpath d='M14.5085 21.0471L14.9762 20.5756L14.6959 20.7261L14.2014 21.2117L14.5085 21.0471Z' fill='%230098FF'/%3e %3cpath d='M17.104 14.9221L18.4958 14.7229L18.6457 14.4784L17.258 14.6678L17.104 14.9221Z' fill='%23D7FF1F'/%3e %3cpath d='M9.73853 12.4377L9.88492 13.0463L10.182 12.2551L10.0439 11.6204L9.73853 12.4377Z' fill='%23FF9C00'/%3e %3cpath d='M10.1302 18.777L10.2655 18.7733L10.1438 18.0278L9.99878 17.9742L10.1302 18.777Z' fill='%2330FFC7'/%3e %3cpath d='M20.8757 15.7584L22.1775 15.4813L22.2399 15.8446L20.9406 16.1273L20.8757 15.7584Z' fill='%23AAFF4D'/%3e %3cpath d='M14.2779 22.276L14.1966 21.92L13.8298 22.1151L13.8799 22.4868L14.2779 22.276Z' fill='%230050FF'/%3e %3cpath d='M16.1136 19.6209L16.9971 19.2096L16.8069 19.4637L15.9077 19.8974L16.1136 19.6209Z' fill='%2300E4F8'/%3e %3cpath d='M15.2321 20.3465L15.908 19.8975L15.6737 20.1072L14.9763 20.5758L15.2321 20.3465Z' fill='%2300C0FF'/%3e %3cpath d='M19.0154 14.1394L20.3464 13.8883L20.5548 13.8046L19.2258 14.0546L19.0154 14.1394Z' fill='%23FEED00'/%3e %3cpath d='M14.165 16.2934L15.4541 16.1182L15.5111 15.7358L14.2243 15.8808L14.165 16.2934Z' fill='%23A0FF56'/%3e %3cpath d='M18.4226 17.8357L19.6303 17.5282L19.5524 17.8731L18.3418 18.2019L18.4226 17.8357Z' fill='%2350FFA7'/%3e %3cpath d='M14.2588 21.5028L14.5085 21.0474L14.2014 21.2119L13.9226 21.6823L14.2588 21.5028Z' fill='%230080FF'/%3e %3cpath d='M11.4169 18.3497L12.1615 18.1202L12.0795 17.5966L11.3254 17.7748L11.4169 18.3497Z' fill='%2346FFB1'/%3e %3cpath d='M16.9785 16.0781L16.992 16.6314L16.9891 17.6727L16.9756 17.1426L16.9785 16.0781Z' fill='%2383FF73'/%3e %3cpath d='M19.6773 16.7745L20.9699 16.5016L20.9633 16.8711L19.6724 17.1588L19.6773 16.7745Z' fill='%237DFF7A'/%3e %3cpath d='M14.1968 21.9201L14.2588 21.5027L13.9227 21.6822L13.8301 22.1151L14.1968 21.9201Z' fill='%230068FF'/%3e %3cpath d='M9.90656 17.8332L9.99874 17.9742L9.94157 17.1647L9.84521 16.9683L9.90656 17.8332Z' fill='%235DFF9A'/%3e %3cpath d='M15.854 10.6635L15.9202 11.2819L16.3124 12.2576L16.2472 11.6425L15.854 10.6635Z' fill='%23FF6000'/%3e %3cpath d='M9.67603 13.9266L9.79905 14.4555L10.0005 13.6107L9.88494 13.0464L9.67603 13.9266Z' fill='%23FFE200'/%3e %3cpath d='M13.0051 16.9103L14.1476 16.7256L14.1651 16.2932L13.0222 16.4388L13.0051 16.9103Z' fill='%2387FF70'/%3e %3cpath d='M12.0793 17.5965L13.0338 17.3911L13.0052 16.9104L12.0461 17.0695L12.0793 17.5965Z' fill='%236AFF8D'/%3e %3cpath d='M20.7769 15.4045L22.0815 15.1328L22.1774 15.4813L20.8756 15.7585L20.7769 15.4045Z' fill='%23BEFF39'/%3e %3cpath d='M10.2655 18.7735L10.4976 18.6913L10.386 18.0039L10.1438 18.0279L10.2655 18.7735Z' fill='%2336FFC1'/%3e %3cpath d='M15.606 15.382L16.9799 15.22L17.1039 14.9222L15.7356 15.0657L15.606 15.382Z' fill='%23CAFF2C'/%3e %3cpath d='M17.2576 14.6679L18.6453 14.4785L18.82 14.2823L17.4376 14.4639L17.2576 14.6679Z' fill='%23E7FF0F'/%3e %3cpath d='M9.7627 16.6831L9.84529 16.9685L9.86542 16.1177L9.78372 15.7815L9.7627 16.6831Z' fill='%2390FF66'/%3e %3cpath d='M9.68677 15.3632L9.78384 15.7814L9.89145 14.9175L9.79928 14.4553L9.68677 15.3632Z' fill='%23CAFF2C'/%3e %3cpath d='M10.8698 18.5449L11.4172 18.3497L11.3257 17.7749L10.7683 17.915L10.8698 18.5449Z' fill='%2340FFB7'/%3e %3cpath d='M19.2258 14.055L20.5548 13.8049L20.7726 13.7804L19.446 14.0303L19.2258 14.055Z' fill='%23FFE600'/%3e %3cpath d='M14.8421 22.2015L14.6416 21.9534L14.2783 22.2762L14.4504 22.5484L14.8421 22.2015Z' fill='%230054FF'/%3e %3cpath d='M17.2807 18.5441L18.3421 18.2019L18.2255 18.5326L17.1567 18.9006L17.2807 18.5441Z' fill='%2333FFC4'/%3e %3cpath d='M10.4976 18.6915L10.8697 18.5451L10.7682 17.9152L10.386 18.0041L10.4976 18.6915Z' fill='%233CFFBA'/%3e %3cpath d='M14.7886 20.7961L15.232 20.3462L14.9762 20.5755L14.5085 21.047L14.7886 20.7961Z' fill='%2300ACFF'/%3e %3cpath d='M12.3223 7.59119L12.3956 8.21538L13.0417 8.31086L12.9696 7.68573L12.3223 7.59119Z' fill='maroon'/%3e %3cpath d='M16.614 13.3036L16.6773 13.9224L16.8788 14.995L16.8179 14.39L16.614 13.3036Z' fill='%23FFEA00'/%3e %3cpath d='M20.6467 15.0751L21.9544 14.8085L22.0813 15.1329L20.7767 15.4047L20.6467 15.0751Z' fill='%23D1FF26'/%3e %3cpath d='M19.645 16.3852L20.9405 16.1273L20.97 16.5014L19.6774 16.7743L19.645 16.3852Z' fill='%2394FF63'/%3e %3cpath d='M16.2858 19.2842L17.1564 18.9004L16.9972 19.2095L16.1138 19.6208L16.2858 19.2842Z' fill='%2316FFE1'/%3e %3cpath d='M15.4566 20.0437L16.1137 19.6207L15.9078 19.8973L15.2319 20.3463L15.4566 20.0437Z' fill='%2300D8FF'/%3e %3cpath d='M18.4654 17.4435L19.6724 17.1588L19.6303 17.5282L18.4226 17.8357L18.4654 17.4435Z' fill='%2366FF90'/%3e %3cpath d='M19.446 14.03L20.7726 13.7802L20.994 13.8156L19.6702 14.0662L19.446 14.03Z' fill='%23FFE200'/%3e %3cpath d='M14.2246 15.8807L15.5114 15.7357L15.6058 15.3817L14.3243 15.4986L14.2246 15.8807Z' fill='%23B7FF40'/%3e %3cpath d='M16.9894 17.6725L16.927 18.1332L16.8276 19.0983L16.8868 18.6681L16.9894 17.6725Z' fill='%2343FFB4'/%3e %3cpath d='M10.2869 10.2492L10.4331 10.9173L10.8969 10.3485L10.7596 9.66626L10.2869 10.2492Z' fill='%23FF2500'/%3e %3cpath d='M11.3254 17.7749L12.0795 17.5966L12.0463 17.0696L11.2874 17.1961L11.3254 17.7749Z' fill='%2366FF90'/%3e %3cpath d='M14.5657 21.2284L14.7888 20.7963L14.5087 21.0472L14.259 21.5027L14.5657 21.2284Z' fill='%230098FF'/%3e %3cpath d='M15.4466 21.8561L15.1862 21.7413L14.8418 22.2012L15.0781 22.3468L15.4466 21.8561Z' fill='%230068FF'/%3e %3cpath d='M20.4888 14.7785L21.7997 14.5165L21.9543 14.8082L20.6467 15.0749L20.4888 14.7785Z' fill='%23E1FF16'/%3e %3cpath d='M17.4377 14.4636L18.8201 14.282L19.0153 14.1395L17.6392 14.3154L17.4377 14.4636Z' fill='%23F8F500'/%3e %3cpath d='M14.6416 21.9533L14.5316 21.6217L14.197 21.9201L14.2783 22.2761L14.6416 21.9533Z' fill='%23006CFF'/%3e %3cpath d='M15.3804 9.78271L15.4476 10.4039L15.92 11.282L15.8538 10.6636L15.3804 9.78271Z' fill='%23FF2900'/%3e %3cpath d='M9.99882 17.9744L10.1438 18.028L10.0911 17.2764L9.94165 17.1649L9.99882 17.9744Z' fill='%2360FF97'/%3e %3cpath d='M19.6699 14.0665L20.9937 13.8159L21.2129 13.9105L19.8921 14.1627L19.6699 14.0665Z' fill='%23FFE600'/%3e %3cpath d='M15.7356 15.0657L17.1039 14.9222L17.2579 14.6678L15.8972 14.7955L15.7356 15.0657Z' fill='%23DEFF19'/%3e %3cpath d='M13.0225 16.4391L14.1654 16.2934L14.2247 15.8809L13.0849 15.989L13.0225 16.4391Z' fill='%23A4FF53'/%3e %3cpath d='M14.5316 21.6218L14.5656 21.2286L14.259 21.5029L14.197 21.9202L14.5316 21.6218Z' fill='%230080FF'/%3e %3cpath d='M12.0461 17.0695L13.0052 16.9104L13.0222 16.439L12.0628 16.5524L12.0461 17.0695Z' fill='%2387FF70'/%3e %3cpath d='M20.3074 14.5234L21.6216 14.2654L21.8 14.5166L20.4891 14.7786L20.3074 14.5234Z' fill='%23EEFF09'/%3e %3cpath d='M19.8923 14.1625L21.2131 13.9103L21.4242 14.0615L20.1066 14.3163L19.8923 14.1625Z' fill='%23FFEA00'/%3e %3cpath d='M11.1741 8.56783L11.2966 9.23759L11.8838 8.97681L11.7674 8.30212L11.1741 8.56783Z' fill='%23AD0000'/%3e %3cpath d='M20.1064 14.3163L21.424 14.0615L21.6213 14.2655L20.3071 14.5235L20.1064 14.3163Z' fill='%23FBF100'/%3e %3cpath d='M16.8277 19.0983L16.6802 19.4339L16.4956 20.2949L16.6353 19.9944L16.8277 19.0983Z' fill='%230CF4EB'/%3e %3cpath d='M19.5757 16.0014L20.8754 15.7585L20.9403 16.1274L19.6448 16.3853L19.5757 16.0014Z' fill='%23AAFF4D'/%3e %3cpath d='M17.3661 18.1492L18.4229 17.8357L18.3421 18.2018L17.2808 18.544L17.3661 18.1492Z' fill='%234DFFAA'/%3e %3cpath d='M16.0193 21.2211L15.7553 21.256L15.4468 21.8562L15.6918 21.8566L16.0193 21.2211Z' fill='%230088FF'/%3e %3cpath d='M12.97 7.68555L13.0421 8.31068L13.6882 8.58698L13.6173 7.96164L12.97 7.68555Z' fill='maroon'/%3e %3cpath d='M10.7681 17.9149L11.3255 17.7748L11.2874 17.196L10.7251 17.2805L10.7681 17.9149Z' fill='%2366FF90'/%3e %3cpath d='M16.4955 20.2949L16.2743 20.4843L16.0193 21.2209L16.2272 21.0683L16.4955 20.2949Z' fill='%2300B8FF'/%3e %3cpath d='M15.0344 20.4647L15.4565 20.0438L15.232 20.3464L14.7886 20.7962L15.0344 20.4647Z' fill='%2300C8FF'/%3e %3cpath d='M18.469 17.0354L19.6776 16.7745L19.6726 17.1588L18.4656 17.4435L18.469 17.0354Z' fill='%237DFF7A'/%3e %3cpath d='M10.1438 18.0277L10.3859 18.0037L10.338 17.3111L10.0911 17.2762L10.1438 18.0277Z' fill='%2360FF97'/%3e %3cpath d='M17.6392 14.3155L19.0152 14.1396L19.2257 14.0548L17.8568 14.2274L17.6392 14.3155Z' fill='%23FFEA00'/%3e %3cpath d='M14.8396 9.02527L14.908 9.6486L15.4477 10.4041L15.3805 9.78289L14.8396 9.02527Z' fill='%23DF0000'/%3e %3cpath d='M10.3858 18.0039L10.7681 17.915L10.725 17.2805L10.3379 17.3113L10.3858 18.0039Z' fill='%2363FF94'/%3e %3cpath d='M9.84497 16.9685L9.94132 17.165L9.96047 16.3692L9.8651 16.1178L9.84497 16.9685Z' fill='%2390FF66'/%3e %3cpath d='M16.4198 18.896L17.2807 18.5441L17.1567 18.9005L16.2861 19.2844L16.4198 18.896Z' fill='%232CFFCA'/%3e %3cpath d='M14.3245 15.4988L15.606 15.382L15.7356 15.0657L14.4622 15.1574L14.3245 15.4988Z' fill='%23D1FF26'/%3e %3cpath d='M10.0442 11.6205L10.1824 12.2552L10.5609 11.5749L10.4335 10.9174L10.0442 11.6205Z' fill='%23FF6000'/%3e %3cpath d='M15.644 19.6755L16.2858 19.2844L16.1137 19.621L15.4565 20.044L15.644 19.6755Z' fill='%230CF4EB'/%3e %3cpath d='M13.6172 7.96155L13.6881 8.58689L14.3159 9.03691L14.2463 8.41219L13.6172 7.96155Z' fill='%23920000'/%3e %3cpath d='M15.8972 14.7953L17.2579 14.6676L17.438 14.4636L16.0866 14.5786L15.8972 14.7953Z' fill='%23EEFF09'/%3e %3cpath d='M19.4719 15.6329L20.7771 15.4044L20.8758 15.7583L19.576 16.0012L19.4719 15.6329Z' fill='%23C1FF36'/%3e %3cpath d='M15.1862 21.7411L14.9605 21.5253L14.6414 21.953L14.8418 22.2011L15.1862 21.7411Z' fill='%23007CFF'/%3e %3cpath d='M14.2461 8.41235L14.3157 9.03708L14.9078 9.64847L14.8394 9.02514L14.2461 8.41235Z' fill='%23B20000'/%3e %3cpath d='M16.8787 14.9948L16.8942 15.5716L16.9922 16.6312L16.9787 16.0779L16.8787 14.9948Z' fill='%23C1FF36'/%3e %3cpath d='M11.2874 17.1962L12.0463 17.0697L12.063 16.5526L11.304 16.6282L11.2874 17.1962Z' fill='%238AFF6D'/%3e %3cpath d='M17.8569 14.2273L19.2258 14.0548L19.446 14.03L18.0851 14.2017L17.8569 14.2273Z' fill='%23FFE200'/%3e %3cpath d='M13.0847 15.989L14.2245 15.8808L14.3242 15.4988L13.1913 15.5722L13.0847 15.989Z' fill='%23BEFF39'/%3e %3cpath d='M14.8348 20.8658L15.0347 20.4647L14.7888 20.7962L14.5657 21.2284L14.8348 20.8658Z' fill='%2300B4FF'/%3e %3cpath d='M16.3123 12.2574L16.3791 12.8895L16.6774 13.922L16.6141 13.3031L16.3123 12.2574Z' fill='%23FFA300'/%3e %3cpath d='M9.78345 15.7815L9.86515 16.1177L9.96707 15.303L9.89105 14.9176L9.78345 15.7815Z' fill='%23C7FF30'/%3e %3cpath d='M12.063 16.5522L13.0223 16.4388L13.0848 15.9888L12.1296 16.0585L12.063 16.5522Z' fill='%23A7FF50'/%3e %3cpath d='M9.88477 13.0462L10.0004 13.6105L10.2866 12.8516L10.1819 12.255L9.88477 13.0462Z' fill='%23FFA300'/%3e %3cpath d='M17.4103 17.7262L18.4655 17.4436L18.4227 17.8358L17.366 18.1493L17.4103 17.7262Z' fill='%2363FF94'/%3e %3cpath d='M18.4324 16.6219L19.6447 16.3853L19.6772 16.7744L18.4686 17.0353L18.4324 16.6219Z' fill='%2397FF60'/%3e %3cpath d='M9.79907 14.4553L9.89125 14.9174L10.0836 14.114L10.0006 13.6105L9.79907 14.4553Z' fill='%23FFEA00'/%3e %3cpath d='M19.3352 15.2901L20.6468 15.0751L20.7768 15.4046L19.4716 15.6331L19.3352 15.2901Z' fill='%23D4FF23'/%3e %3cpath d='M14.9606 21.5255L14.8253 21.2267L14.5315 21.6216L14.6415 21.9532L14.9606 21.5255Z' fill='%230090FF'/%3e %3cpath d='M14.8253 21.2268L14.8346 20.866L14.5655 21.2286L14.5315 21.6217L14.8253 21.2268Z' fill='%2300A0FF'/%3e %3cpath d='M18.0852 14.2018L19.4461 14.0302L19.6703 14.0663L18.3177 14.2396L18.0852 14.2018Z' fill='%23FFDE00'/%3e %3cpath d='M9.94141 17.1646L10.0909 17.2761L10.1091 16.5377L9.96055 16.3688L9.94141 17.1646Z' fill='%238DFF6A'/%3e %3cpath d='M14.4622 15.1572L15.7356 15.0655L15.8971 14.7953L14.6345 14.8655L14.4622 15.1572Z' fill='%23E4FF13'/%3e %3cpath d='M16.0867 14.5787L17.4381 14.4638L17.6395 14.3157L16.2991 14.4214L16.0867 14.5787Z' fill='%23FEED00'/%3e %3cpath d='M10.7249 17.2803L11.2872 17.1959L11.3039 16.6279L10.7418 16.6575L10.7249 17.2803Z' fill='%238AFF6D'/%3e %3cpath d='M15.2395 20.0606L15.644 19.6753L15.4566 20.0438L15.0344 20.4647L15.2395 20.0606Z' fill='%2302E8F4'/%3e %3cpath d='M15.755 21.256L15.474 21.1792L15.186 21.7415L15.4465 21.8562L15.755 21.256Z' fill='%230098FF'/%3e %3cpath d='M16.511 18.4657L17.3658 18.1493L17.2804 18.5441L16.4194 18.8961L16.511 18.4657Z' fill='%2346FFB1'/%3e %3cpath d='M19.1699 14.9816L20.4888 14.7787L20.6467 15.075L19.3352 15.2901L19.1699 14.9816Z' fill='%23E4FF13'/%3e %3cpath d='M11.7673 8.30208L11.8838 8.97677L12.5055 8.8924L12.3957 8.21509L11.7673 8.30208Z' fill='%23920000'/%3e %3cpath d='M10.7598 9.66628L10.8971 10.3486L11.4238 9.93094L11.2967 9.23779L10.7598 9.66628Z' fill='%23DF0000'/%3e %3cpath d='M18.3176 14.2396L19.6702 14.0663L19.8924 14.1625L18.5485 14.3399L18.3176 14.2396Z' fill='%23FFDE00'/%3e %3cpath d='M15.7896 19.2497L16.4197 18.8958L16.286 19.2841L15.6443 19.6751L15.7896 19.2497Z' fill='%2326FFD1'/%3e %3cpath d='M16.9923 16.6315L16.9296 17.1242L16.927 18.1334L16.9894 17.6727L16.9923 16.6315Z' fill='%2383FF73'/%3e %3cpath d='M18.9805 14.7158L20.3073 14.5234L20.489 14.7787L19.1702 14.9815L18.9805 14.7158Z' fill='%23F1FC06'/%3e %3cpath d='M18.5486 14.3401L19.8925 14.1627L20.1068 14.3165L18.7715 14.5003L18.5486 14.3401Z' fill='%23FFE600'/%3e %3cpath d='M10.0911 17.2763L10.338 17.3111L10.3554 16.6309L10.1093 16.5378L10.0911 17.2763Z' fill='%238DFF6A'/%3e %3cpath d='M10.3381 17.3111L10.7253 17.2803L10.7422 16.6574L10.3556 16.6309L10.3381 17.3111Z' fill='%238DFF6A'/%3e %3cpath d='M18.3574 16.2139L19.5757 16.0013L19.6448 16.3852L18.4324 16.6218L18.3574 16.2139Z' fill='%23ADFF49'/%3e %3cpath d='M18.7712 14.5001L20.1065 14.3163L20.3071 14.5235L18.9803 14.7159L18.7712 14.5001Z' fill='%23FEED00'/%3e %3cpath d='M13.1914 15.5723L14.3243 15.4989L14.462 15.1575L13.3396 15.1997L13.1914 15.5723Z' fill='%23D7FF1F'/%3e %3cpath d='M17.4124 17.2858L18.469 17.0355L18.4656 17.4437L17.4104 17.7262L17.4124 17.2858Z' fill='%237DFF7A'/%3e %3cpath d='M11.3042 16.6282L12.0631 16.5526L12.1297 16.0588L11.3756 16.0856L11.3042 16.6282Z' fill='%23AAFF4D'/%3e %3cpath d='M16.2744 20.4844L15.9952 20.5604L15.7554 21.2559L16.0194 21.221L16.2744 20.4844Z' fill='%2300C4FF'/%3e %3cpath d='M16.2991 14.4214L17.6395 14.3157L17.8571 14.2275L16.529 14.3278L16.2991 14.4214Z' fill='%23FFE200'/%3e %3cpath d='M12.1294 16.0588L13.0847 15.9891L13.1912 15.5723L12.2444 15.6013L12.1294 16.0588Z' fill='%23C4FF33'/%3e %3cpath d='M15.059 20.4237L15.2395 20.0608L15.0344 20.4649L14.8345 20.866L15.059 20.4237Z' fill='%2300D8FF'/%3e %3cpath d='M16.9271 18.1332L16.7752 18.5068L16.6802 19.4339L16.8277 19.0983L16.9271 18.1332Z' fill='%2346FFB1'/%3e %3cpath d='M9.86523 16.1179L9.9606 16.3692L10.0563 15.6076L9.96715 15.3032L9.86523 16.1179Z' fill='%23C1FF36'/%3e %3cpath d='M15.9202 11.2821L15.9914 11.9263L16.3792 12.8899L16.3124 12.2578L15.9202 11.2821Z' fill='%23FF6400'/%3e %3cpath d='M14.6345 14.8655L15.8971 14.7954L16.0866 14.5786L14.8372 14.6315L14.6345 14.8655Z' fill='%23F8F500'/%3e %3cpath d='M15.4743 21.1792L15.2273 21.0031L14.9607 21.5256L15.1864 21.7415L15.4743 21.1792Z' fill='%2300A8FF'/%3e %3cpath d='M16.68 19.4338L16.4493 19.6644L16.2742 20.4842L16.4954 20.2948L16.68 19.4338Z' fill='%230FF8E7'/%3e %3cpath d='M18.2454 15.8225L19.4716 15.6331L19.5757 16.0014L18.3574 16.214L18.2454 15.8225Z' fill='%23C4FF33'/%3e %3cpath d='M16.558 18.0043L17.4104 17.7261L17.366 18.1492L16.5112 18.4656L16.558 18.0043Z' fill='%2363FF94'/%3e %3cpath d='M16.6772 13.9221L16.6969 14.5224L16.8943 15.5716L16.8787 14.9947L16.6772 13.9221Z' fill='%23FFEA00'/%3e %3cpath d='M10.4333 10.9174L10.5608 11.575L11.0116 11.0252L10.8972 10.3486L10.4333 10.9174Z' fill='%23FF3000'/%3e %3cpath d='M15.0707 20.7444L15.0593 20.4235L14.8347 20.8658L14.8254 21.2266L15.0707 20.7444Z' fill='%2300C8FF'/%3e %3cpath d='M16.5288 14.3277L17.8569 14.2275L18.0851 14.2019L16.7701 14.3006L16.5288 14.3277Z' fill='%23FFDB00'/%3e %3cpath d='M15.2273 21.0029L15.0707 20.7444L14.8254 21.2266L14.9608 21.5254L15.2273 21.0029Z' fill='%2300B8FF'/%3e %3cpath d='M15.3983 19.5938L15.7893 19.2499L15.644 19.6753L15.2395 20.0606L15.3983 19.5938Z' fill='%231CFFDB'/%3e %3cpath d='M10.7422 16.6576L11.3043 16.6281L11.3757 16.0856L10.8191 16.0624L10.7422 16.6576Z' fill='%23ADFF49'/%3e %3cpath d='M12.3958 8.21509L12.5056 8.8924L13.1449 8.98808L13.0419 8.31057L12.3958 8.21509Z' fill='%23840000'/%3e %3cpath d='M17.3713 16.8393L18.4325 16.6219L18.4687 17.0354L17.4121 17.2856L17.3713 16.8393Z' fill='%2397FF60'/%3e %3cpath d='M15.8885 18.7779L16.5109 18.4653L16.4194 18.8957L15.7893 19.2496L15.8885 18.7779Z' fill='%2343FFB4'/%3e %3cpath d='M9.89136 14.9177L9.96737 15.3031L10.1493 14.5459L10.0837 14.1143L9.89136 14.9177Z' fill='%23FBF100'/%3e %3cpath d='M18.0994 15.4579L19.3352 15.29L19.4717 15.633L18.2455 15.8225L18.0994 15.4579Z' fill='%23D7FF1F'/%3e %3cpath d='M13.3394 15.1995L14.4618 15.1573L14.6341 14.8656L13.5255 14.881L13.3394 15.1995Z' fill='%23EEFF09'/%3e %3cpath d='M9.96069 16.3689L10.1092 16.5378L10.1985 15.8314L10.0564 15.6072L9.96069 16.3689Z' fill='%23BEFF39'/%3e %3cpath d='M14.8372 14.6312L16.0865 14.5784L16.299 14.421L15.0649 14.4613L14.8372 14.6312Z' fill='%23FFE600'/%3e %3cpath d='M16.7703 14.3007L18.0852 14.202L18.3177 14.2398L17.0167 14.341L16.7703 14.3007Z' fill='gold'/%3e %3cpath d='M10.1821 12.2551L10.2869 12.8517L10.6514 12.1996L10.5607 11.5748L10.1821 12.2551Z' fill='%23FF6C00'/%3e %3cpath d='M11.3755 16.0854L12.1296 16.0586L12.2446 15.6011L11.5001 15.5824L11.3755 16.0854Z' fill='%23CAFF2C'/%3e %3cpath d='M10.3555 16.631L10.7421 16.6575L10.819 16.0622L10.4384 15.9806L10.3555 16.631Z' fill='%23B4FF43'/%3e %3cpath d='M10.0005 13.6109L10.0836 14.1144L10.3567 13.3931L10.2868 12.8519L10.0005 13.6109Z' fill='%23FFAE00'/%3e %3cpath d='M12.2446 15.601L13.1915 15.572L13.3397 15.1993L12.4053 15.1919L12.2446 15.601Z' fill='%23DEFF19'/%3e %3cpath d='M15.4475 10.4039L15.5241 11.0588L15.9911 11.9262L15.9199 11.282L15.4475 10.4039Z' fill='%23FF2D00'/%3e %3cpath d='M17.9231 15.1301L19.1702 14.9818L19.3355 15.2903L18.0996 15.4581L17.9231 15.1301Z' fill='%23EBFF0C'/%3e %3cpath d='M15.9952 20.5602L15.6979 20.5278L15.4744 21.179L15.7554 21.2557L15.9952 20.5602Z' fill='%2300CCFF'/%3e %3cpath d='M11.2969 9.2377L11.424 9.93085L11.9998 9.67733L11.8841 8.97693L11.2969 9.2377Z' fill='%23BB0000'/%3e %3cpath d='M10.1094 16.5379L10.3555 16.631L10.4384 15.9806L10.1986 15.8315L10.1094 16.5379Z' fill='%23B7FF40'/%3e %3cpath d='M17.0166 14.3408L18.3177 14.2396L18.5485 14.3399L17.2615 14.4475L17.0166 14.3408Z' fill='gold'/%3e %3cpath d='M16.5584 17.5236L17.4121 17.2854L17.4102 17.7259L16.5579 18.0041L16.5584 17.5236Z' fill='%237DFF7A'/%3e %3cpath d='M17.2888 16.3988L18.3575 16.214L18.4326 16.6219L17.3714 16.8392L17.2888 16.3988Z' fill='%23B1FF46'/%3e %3cpath d='M15.2329 19.9121L15.3984 19.5938L15.2395 20.0606L15.0591 20.4235L15.2329 19.9121Z' fill='%2316FFE1'/%3e %3cpath d='M17.7207 14.8476L18.9803 14.7161L19.17 14.9818L17.9228 15.1301L17.7207 14.8476Z' fill='%23F8F500'/%3e %3cpath d='M17.2612 14.4476L18.5482 14.34L18.7711 14.5001L17.4981 14.6179L17.2612 14.4476Z' fill='%23FFDB00'/%3e %3cpath d='M13.0417 8.31067L13.1447 8.98818L13.7838 9.26225L13.6878 8.58699L13.0417 8.31067Z' fill='%23890000'/%3e %3cpath d='M17.4985 14.6178L18.7716 14.5L18.9806 14.7158L17.721 14.8473L17.4985 14.6178Z' fill='%23FFE600'/%3e %3cpath d='M16.8943 15.5719L16.8342 16.0972L16.9296 17.1241L16.9923 16.6314L16.8943 15.5719Z' fill='%23C1FF36'/%3e %3cpath d='M15.0647 14.4615L16.2988 14.4212L16.5287 14.3276L15.3116 14.3604L15.0647 14.4615Z' fill='gold'/%3e %3cpath d='M13.5259 14.8811L14.6345 14.8656L14.8372 14.6316L13.7453 14.6255L13.5259 14.8811Z' fill='%23FFEA00'/%3e %3cpath d='M15.9385 18.2722L16.5577 18.0043L16.5109 18.4657L15.8884 18.7782L15.9385 18.2722Z' fill='%2360FF97'/%3e %3cpath d='M15.5065 19.0757L15.8886 18.778L15.7895 19.2497L15.3984 19.5936L15.5065 19.0757Z' fill='%233CFFBA'/%3e %3cpath d='M14.9082 9.64832L14.9908 10.3121L15.5244 11.0587L15.4479 10.4038L14.9082 9.64832Z' fill='%23E40000'/%3e %3cpath d='M15.6976 20.5279L15.4337 20.3981L15.2271 21.0029L15.4741 21.179L15.6976 20.5279Z' fill='%2300D8FF'/%3e %3cpath d='M16.4497 19.6643L16.1597 19.7864L15.9954 20.5602L16.2746 20.4841L16.4497 19.6643Z' fill='%2316FFE1'/%3e %3cpath d='M15.2604 20.1865L15.2329 19.912L15.0591 20.4233L15.0705 20.7443L15.2604 20.1865Z' fill='%230CF4EB'/%3e %3cpath d='M10.8188 16.0623L11.3754 16.0855L11.5001 15.5825L10.9542 15.5103L10.8188 16.0623Z' fill='%23D1FF26'/%3e %3cpath d='M13.6877 8.58716L13.7837 9.26242L14.4047 9.70781L14.3156 9.03718L13.6877 8.58716Z' fill='%239B0000'/%3e %3cpath d='M9.96729 15.3027L10.0564 15.6071L10.227 14.8996L10.1492 14.5455L9.96729 15.3027Z' fill='%23F4F802'/%3e %3cpath d='M17.1665 15.9759L18.2455 15.8225L18.3575 16.214L17.2888 16.3987L17.1665 15.9759Z' fill='%23C7FF30'/%3e %3cpath d='M16.3792 12.8896L16.4048 13.5122L16.6971 14.5224L16.6775 13.9221L16.3792 12.8896Z' fill='%23FFA700'/%3e %3cpath d='M14.3159 9.03711L14.405 9.70773L14.9906 10.3122L14.908 9.64846L14.3159 9.03711Z' fill='%23BB0000'/%3e %3cpath d='M15.4339 20.3982L15.2605 20.1868L15.0706 20.7445L15.2272 21.003L15.4339 20.3982Z' fill='%2302E8F4'/%3e %3cpath d='M16.9296 17.124L16.7771 17.5376L16.7751 18.5069L16.927 18.1333L16.9296 17.124Z' fill='%2380FF77'/%3e %3cpath d='M12.4053 15.1921L13.3397 15.1995L13.5258 14.881L12.6078 14.8423L12.4053 15.1921Z' fill='%23F8F500'/%3e %3cpath d='M16.5122 17.0367L17.3711 16.8392L17.4118 17.2856L16.5581 17.5237L16.5122 17.0367Z' fill='%239AFF5D'/%3e %3cpath d='M16.7755 18.5068L16.5394 18.782L16.4497 19.6645L16.6804 19.4339L16.7755 18.5068Z' fill='%2349FFAD'/%3e %3cpath d='M15.3118 14.3606L16.5288 14.3278L16.7702 14.3007L15.5714 14.3313L15.3118 14.3606Z' fill='%23FFD000'/%3e %3cpath d='M11.5002 15.5826L12.2447 15.6013L12.4054 15.1921L11.6753 15.1326L11.5002 15.5826Z' fill='%23E7FF0F'/%3e %3cpath d='M10.8967 10.3485L11.0111 11.0251L11.5229 10.6218L11.4234 9.93091L10.8967 10.3485Z' fill='%23F10800'/%3e %3cpath d='M10.4382 15.9803L10.8188 16.062L10.9542 15.5099L10.585 15.3768L10.4382 15.9803Z' fill='%23DBFF1C'/%3e %3cpath d='M17.0076 15.5821L18.0993 15.458L18.2455 15.8226L17.1665 15.976L17.0076 15.5821Z' fill='%23DEFF19'/%3e %3cpath d='M13.7451 14.6256L14.837 14.6317L15.0648 14.4617L13.9922 14.4399L13.7451 14.6256Z' fill='gold'/%3e %3cpath d='M10.0562 15.6077L10.1983 15.8319L10.3569 15.1761L10.2267 14.9001L10.0562 15.6077Z' fill='%23EBFF0C'/%3e %3cpath d='M11.8838 8.9768L11.9995 9.67721L12.6091 9.59622L12.5055 8.89246L11.8838 8.9768Z' fill='%239F0000'/%3e %3cpath d='M15.3511 19.3444L15.5065 19.0758L15.3984 19.5937L15.2329 19.9121L15.3511 19.3444Z' fill='%2336FFC1'/%3e %3cpath d='M10.084 14.114L10.1495 14.5456L10.4076 13.8662L10.3571 13.3927L10.084 14.114Z' fill='%23FFB900'/%3e %3cpath d='M15.5715 14.331L16.7703 14.3004L17.0167 14.3407L15.8369 14.3745L15.5715 14.331Z' fill='%23FFCC00'/%3e %3cpath d='M15.938 17.7451L16.5584 17.5239L16.5578 18.0044L15.9386 18.2723L15.938 17.7451Z' fill='%2380FF77'/%3e %3cpath d='M10.1987 15.8316L10.4385 15.9806L10.5853 15.3771L10.3574 15.1758L10.1987 15.8316Z' fill='%23E1FF16'/%3e %3cpath d='M16.8164 15.2277L17.9232 15.13L18.0997 15.458L17.0079 15.5821L16.8164 15.2277Z' fill='%23F1FC06'/%3e %3cpath d='M15.5608 18.5199L15.9387 18.272L15.8887 18.778L15.5066 19.0757L15.5608 18.5199Z' fill='%235DFF9A'/%3e %3cpath d='M10.5605 11.575L10.6513 12.1998L11.0851 11.6732L11.0114 11.0251L10.5605 11.575Z' fill='%23FF3B00'/%3e %3cpath d='M16.1596 19.7866L15.8508 19.8039L15.698 20.528L15.9953 20.5604L16.1596 19.7866Z' fill='%231CFFDB'/%3e %3cpath d='M16.4209 16.5559L17.2887 16.3988L17.3712 16.8392L16.5123 17.0366L16.4209 16.5559Z' fill='%23B7FF40'/%3e %3cpath d='M15.8367 14.3744L17.0165 14.3406L17.2614 14.4473L16.1008 14.4898L15.8367 14.3744Z' fill='%23FFCC00'/%3e %3cpath d='M10.2869 12.8515L10.3568 13.3927L10.7043 12.7734L10.6514 12.1995L10.2869 12.8515Z' fill='%23FF7A00'/%3e %3cpath d='M16.5972 14.9221L17.7207 14.8473L17.9229 15.1299L16.8161 15.2275L16.5972 14.9221Z' fill='%23FFEA00'/%3e %3cpath d='M12.6077 14.8421L13.5257 14.8809L13.7451 14.6253L12.8469 14.5613L12.6077 14.8421Z' fill='%23FFDB00'/%3e %3cpath d='M16.1008 14.4898L17.2614 14.4473L17.4982 14.6176L16.3566 14.6739L16.1008 14.4898Z' fill='%23FFD000'/%3e %3cpath d='M10.9543 15.5103L11.5002 15.5826L11.6752 15.1326L11.145 15.0161L10.9543 15.5103Z' fill='%23F4F802'/%3e %3cpath d='M16.3564 14.674L17.4981 14.6177L17.7206 14.8472L16.597 14.9221L16.3564 14.674Z' fill='%23FFDB00'/%3e %3cpath d='M13.9922 14.4397L15.0648 14.4615L15.3117 14.3604L14.2604 14.3292L13.9922 14.4397Z' fill='%23FFC800'/%3e %3cpath d='M15.9915 11.9261L16.025 12.5695L16.4049 13.5124L16.3792 12.8898L15.9915 11.9261Z' fill='%23FF6C00'/%3e %3cpath d='M16.6968 14.5226L16.6423 15.0802L16.8341 16.0971L16.8942 15.5718L16.6968 14.5226Z' fill='%23FBF100'/%3e %3cpath d='M15.3897 19.5671L15.3511 19.3445L15.2329 19.9121L15.2604 20.1867L15.3897 19.5671Z' fill='%2330FFC7'/%3e %3cpath d='M11.6748 15.1326L12.4049 15.1922L12.6075 14.8424L11.8959 14.7477L11.6748 15.1326Z' fill='%23FFE600'/%3e %3cpath d='M15.8507 19.8037L15.575 19.7258L15.4341 20.398L15.698 20.5278L15.8507 19.8037Z' fill='%2323FFD4'/%3e %3cpath d='M15.5746 19.7259L15.3895 19.5671L15.2603 20.1867L15.4337 20.3981L15.5746 19.7259Z' fill='%2329FFCE'/%3e %3cpath d='M16.2864 16.094L17.1666 15.9758L17.2889 16.3987L16.4211 16.5557L16.2864 16.094Z' fill='%23D1FF26'/%3e %3cpath d='M15.8862 17.2102L16.5123 17.0366L16.5582 17.5237L15.9378 17.7449L15.8862 17.2102Z' fill='%239DFF5A'/%3e %3cpath d='M10.1489 14.5455L10.2267 14.8996L10.4683 14.2651L10.407 13.8661L10.1489 14.5455Z' fill='%23FFC400'/%3e %3cpath d='M16.5391 18.7821L16.2431 18.9541L16.1594 19.7867L16.4494 19.6646L16.5391 18.7821Z' fill='%234DFFAA'/%3e %3cpath d='M12.5056 8.89233L12.6091 9.5961L13.2357 9.69114L13.1449 8.98799L12.5056 8.89233Z' fill='%23920000'/%3e %3cpath d='M14.2605 14.3294L15.3117 14.3606L15.5713 14.3313L14.543 14.2974L14.2605 14.3294Z' fill='%23FFC100'/%3e %3cpath d='M10.585 15.3771L10.9541 15.5101L11.1448 15.0159L10.7923 14.8365L10.585 15.3771Z' fill='%23FEED00'/%3e %3cpath d='M15.4102 18.7349L15.5606 18.52L15.5064 19.0759L15.3511 19.3445L15.4102 18.7349Z' fill='%235AFF9D'/%3e %3cpath d='M11.4236 9.93101L11.523 10.6219L12.0823 10.3778L11.9994 9.67749L11.4236 9.93101Z' fill='%23C80000'/%3e %3cpath d='M16.8344 16.0969L16.6851 16.5513L16.7773 17.5374L16.9298 17.1238L16.8344 16.0969Z' fill='%23BEFF39'/%3e %3cpath d='M15.5591 17.9408L15.9379 17.7451L15.9385 18.2723L15.5606 18.5203L15.5591 17.9408Z' fill='%2380FF77'/%3e %3cpath d='M12.8469 14.5616L13.7451 14.6256L13.9921 14.4399L13.1168 14.3575L12.8469 14.5616Z' fill='%23FFC800'/%3e %3cpath d='M16.7773 17.5376L16.5403 17.8596L16.5393 18.7821L16.7754 18.5069L16.7773 17.5376Z' fill='%2380FF77'/%3e %3cpath d='M16.1118 15.6639L17.0076 15.582L17.1666 15.976L16.2864 16.0941L16.1118 15.6639Z' fill='%23E7FF0F'/%3e %3cpath d='M10.2271 14.8999L10.3573 15.1759L10.5819 14.5882L10.4687 14.2655L10.2271 14.8999Z' fill='%23FFD300'/%3e %3cpath d='M15.5242 11.0585L15.5672 11.7203L16.0248 12.5692L15.9912 11.9259L15.5242 11.0585Z' fill='%23FF3400'/%3e %3cpath d='M10.3572 15.1756L10.5851 15.377L10.7925 14.8365L10.5817 14.5879L10.3572 15.1756Z' fill='%23FFDE00'/%3e %3cpath d='M14.543 14.2974L15.5714 14.3313L15.8368 14.3748L14.8321 14.3449L14.543 14.2974Z' fill='%23FFB900'/%3e %3cpath d='M11.145 15.016L11.6752 15.1325L11.8963 14.7476L11.3865 14.5931L11.145 15.016Z' fill='gold'/%3e %3cpath d='M11.896 14.7473L12.6076 14.842L12.8468 14.5611L12.1577 14.4381L11.896 14.7473Z' fill='%23FFCC00'/%3e %3cpath d='M10.3564 13.393L10.4069 13.8665L10.7351 13.2836L10.704 12.7737L10.3564 13.393Z' fill='%23FF8600'/%3e %3cpath d='M15.7852 16.6822L16.4212 16.5558L16.5127 17.0366L15.8866 17.2102L15.7852 16.6822Z' fill='%23BAFF3C'/%3e %3cpath d='M13.1448 8.98828L13.2356 9.69143L13.8619 9.96079L13.7839 9.26236L13.1448 8.98828Z' fill='%23960000'/%3e %3cpath d='M15.9021 15.2765L16.8163 15.2274L17.0078 15.5818L16.1119 15.6637L15.9021 15.2765Z' fill='%23FBF100'/%3e %3cpath d='M15.4546 18.9014L15.4104 18.7349L15.3513 19.3444L15.3899 19.5671L15.4546 18.9014Z' fill='%2356FFA0'/%3e %3cpath d='M16.2434 18.9539L15.9281 19.0249L15.8508 19.8037L16.1597 19.7865L16.2434 18.9539Z' fill='%234DFFAA'/%3e %3cpath d='M11.0112 11.0249L11.085 11.673L11.5773 11.2873L11.5229 10.6217L11.0112 11.0249Z' fill='%23FF1300'/%3e %3cpath d='M14.8323 14.3446L15.8369 14.3745L16.101 14.4898L15.1203 14.4706L14.8323 14.3446Z' fill='%23FFBD00'/%3e %3cpath d='M16.4047 13.5123L16.3586 14.101L16.6425 15.08L16.697 14.5225L16.4047 13.5123Z' fill='%23FFAE00'/%3e %3cpath d='M14.9905 10.3119L15.0443 10.9894L15.5671 11.7203L15.5241 11.0585L14.9905 10.3119Z' fill='%23F10800'/%3e %3cpath d='M13.1167 14.3572L13.992 14.4396L14.2603 14.3292L13.4102 14.2357L13.1167 14.3572Z' fill='%23FFB900'/%3e %3cpath d='M15.6626 14.9432L16.5975 14.9224L16.8164 15.2277L15.9022 15.2768L15.6626 14.9432Z' fill='%23FFDB00'/%3e %3cpath d='M10.6516 12.1997L10.7045 12.7736L11.118 12.2739L11.0855 11.6731L10.6516 12.1997Z' fill='%23FF4A00'/%3e %3cpath d='M15.1201 14.4709L16.1008 14.4902L16.3566 14.6743L15.3994 14.6722L15.1201 14.4709Z' fill='%23FFC100'/%3e %3cpath d='M15.3994 14.6719L16.3567 14.6741L16.5973 14.9221L15.6624 14.9429L15.3994 14.6719Z' fill='%23FFCC00'/%3e %3cpath d='M13.7837 9.26233L13.8618 9.96076L14.4703 10.3975L14.4047 9.70776L13.7837 9.26233Z' fill='%23A40000'/%3e %3cpath d='M15.5017 17.3524L15.8865 17.21L15.9381 17.7446L15.5592 17.9404L15.5017 17.3524Z' fill='%23A0FF56'/%3e %3cpath d='M14.4048 9.70776L14.4704 10.3975L15.0441 10.9897L14.9903 10.3122L14.4048 9.70776Z' fill='%23C40000'/%3e %3cpath d='M15.6456 19.0031L15.4544 18.9012L15.3896 19.5669L15.5747 19.7257L15.6456 19.0031Z' fill='%2353FFA4'/%3e %3cpath d='M15.4082 18.099L15.5592 17.9404L15.5607 18.5199L15.4102 18.7348L15.4082 18.099Z' fill='%2380FF77'/%3e %3cpath d='M15.9277 19.0249L15.6456 19.0032L15.5747 19.7258L15.8504 19.8037L15.9277 19.0249Z' fill='%2350FFA7'/%3e %3cpath d='M15.6362 16.1749L16.2865 16.094L16.4212 16.5557L15.7851 16.6821L15.6362 16.1749Z' fill='%23D7FF1F'/%3e %3cpath d='M10.7927 14.8367L11.1452 15.0161L11.3867 14.5932L11.0558 14.3739L10.7927 14.8367Z' fill='%23FFC800'/%3e %3cpath d='M11.9995 9.67742L12.0824 10.3777L12.6742 10.3008L12.6091 9.59644L11.9995 9.67742Z' fill='%23AD0000'/%3e %3cpath d='M10.407 13.8664L10.4684 14.2654L10.7755 13.7215L10.7351 13.2834L10.407 13.8664Z' fill='%23FF9800'/%3e %3cpath d='M12.1582 14.4386L12.8473 14.5616L13.1172 14.3575L12.4539 14.2137L12.1582 14.4386Z' fill='%23FFB600'/%3e %3cpath d='M16.5402 17.8595L16.2432 18.084L16.2432 18.954L16.5392 18.782L16.5402 17.8595Z' fill='%2380FF77'/%3e %3cpath d='M13.4104 14.2359L14.2605 14.3293L14.543 14.2973L13.7198 14.2006L13.4104 14.2359Z' fill='%23FFAE00'/%3e %3cpath d='M11.3865 14.5932L11.8963 14.7477L12.158 14.4385L11.6728 14.2533L11.3865 14.5932Z' fill='%23FFB900'/%3e %3cpath d='M16.6422 15.0801L16.4998 15.5749L16.6846 16.5514L16.834 16.097L16.6422 15.0801Z' fill='%23F8F500'/%3e %3cpath d='M10.5818 14.5881L10.7925 14.8367L11.0556 14.3739L10.867 14.0846L10.5818 14.5881Z' fill='%23FFB600'/%3e %3cpath d='M10.4685 14.2654L10.5817 14.5881L10.8668 14.0845L10.7756 13.7214L10.4685 14.2654Z' fill='%23FFA700'/%3e %3cpath d='M16.685 16.5514L16.4517 16.9212L16.5403 17.8595L16.7773 17.5375L16.685 16.5514Z' fill='%23BAFF3C'/%3e %3cpath d='M15.4434 15.7023L16.1116 15.6638L16.2862 16.0941L15.6359 16.175L15.4434 15.7023Z' fill='%23F1FC06'/%3e %3cpath d='M15.3892 16.7721L15.7848 16.6824L15.8863 17.2104L15.5015 17.3529L15.3892 16.7721Z' fill='%23C1FF36'/%3e %3cpath d='M15.4523 18.2069L15.4082 18.0992L15.4102 18.735L15.4544 18.9015L15.4523 18.2069Z' fill='%2380FF77'/%3e %3cpath d='M16.0245 12.5697L15.9895 13.1873L16.3584 14.1012L16.4045 13.5125L16.0245 12.5697Z' fill='%23FF7300'/%3e %3cpath d='M13.7197 14.2007L14.5429 14.2974L14.8321 14.3449L14.0367 14.2528L13.7197 14.2007Z' fill='%23FFA700'/%3e %3cpath d='M10.7043 12.7735L10.7355 13.2835L11.1257 12.8135L11.1178 12.2738L10.7043 12.7735Z' fill='%23FF5D00'/%3e %3cpath d='M15.3445 17.4538L15.5014 17.3527L15.559 17.9405L15.408 18.0991L15.3445 17.4538Z' fill='%23A4FF53'/%3e %3cpath d='M11.5232 10.6218L11.5775 11.2874L12.1154 11.0545L12.0824 10.3777L11.5232 10.6218Z' fill='%23DA0000'/%3e %3cpath d='M15.2124 15.277L15.902 15.2769L16.1119 15.664L15.4436 15.7025L15.2124 15.277Z' fill='%23FFE200'/%3e %3cpath d='M12.4536 14.2138L13.1169 14.3576L13.4104 14.236L12.7755 14.0798L12.4536 14.2138Z' fill='%23FFA300'/%3e %3cpath d='M16.2433 18.0839L15.927 18.2115L15.928 19.025L16.2433 18.9539L16.2433 18.0839Z' fill='%2380FF77'/%3e %3cpath d='M12.6089 9.59619L12.6741 10.3005L13.2824 10.394L13.2355 9.69123L12.6089 9.59619Z' fill='%23A40000'/%3e %3cpath d='M14.0369 14.2527L14.8322 14.3448L15.1202 14.4708L14.353 14.3911L14.0369 14.2527Z' fill='%23FFAB00'/%3e %3cpath d='M11.0554 14.3738L11.3863 14.5931L11.6726 14.2532L11.3676 14.0016L11.0554 14.3738Z' fill='%23FFA700'/%3e %3cpath d='M15.644 18.2487L15.4524 18.2067L15.4545 18.9013L15.6457 19.0032L15.644 18.2487Z' fill='%2380FF77'/%3e %3cpath d='M11.0852 11.6729L11.1177 12.2737L11.5867 11.9082L11.5775 11.2872L11.0852 11.6729Z' fill='%23FF2500'/%3e %3cpath d='M14.9487 14.9103L15.6624 14.9432L15.902 15.2768L15.2124 15.277L14.9487 14.9103Z' fill='%23FFCC00'/%3e %3cpath d='M14.353 14.391L15.1203 14.4707L15.3995 14.6719L14.6598 14.6121L14.353 14.391Z' fill='%23FFAE00'/%3e %3cpath d='M15.9269 18.2114L15.644 18.2487L15.6458 19.0032L15.9279 19.0249L15.9269 18.2114Z' fill='%2380FF77'/%3e %3cpath d='M11.6729 14.2531L12.1581 14.4383L12.4538 14.2134L11.9966 14.0057L11.6729 14.2531Z' fill='%23FF9F00'/%3e %3cpath d='M14.6594 14.6121L15.3992 14.6718L15.6622 14.9429L14.9485 14.91L14.6594 14.6121Z' fill='%23FFBD00'/%3e %3cpath d='M15.2249 16.2139L15.6361 16.175L15.785 16.6823L15.3893 16.772L15.2249 16.2139Z' fill='%23E1FF16'/%3e %3cpath d='M15.5673 11.7206L15.5457 12.364L15.9899 13.1871L16.0249 12.5695L15.5673 11.7206Z' fill='%23FF3F00'/%3e %3cpath d='M10.7351 13.2834L10.7754 13.7214L11.1405 13.2832L11.1254 12.8135L10.7351 13.2834Z' fill='%23FF6F00'/%3e %3cpath d='M16.3585 14.101L16.2266 14.6348L16.4999 15.5749L16.6423 15.08L16.3585 14.101Z' fill='%23FFB600'/%3e %3cpath d='M12.7754 14.0796L13.4102 14.2358L13.7196 14.2005L13.1151 14.0405L12.7754 14.0796Z' fill='%23FF9800'/%3e %3cpath d='M10.8669 14.0845L11.0556 14.3738L11.3678 14.0015L11.2057 13.6792L10.8669 14.0845Z' fill='%23FF9400'/%3e %3cpath d='M16.4516 16.9214L16.1587 17.1995L16.2432 18.0841L16.5403 17.8597L16.4516 16.9214Z' fill='%23B7FF40'/%3e %3cpath d='M13.2358 9.69141L13.2827 10.3942L13.8907 10.6564L13.8622 9.96077L13.2358 9.69141Z' fill='%23A40000'/%3e %3cpath d='M15.383 17.5015L15.3447 17.454L15.4083 18.0993L15.4523 18.2069L15.383 17.5015Z' fill='%23A7FF50'/%3e %3cpath d='M15.2212 16.816L15.3895 16.7719L15.5019 17.3526L15.3449 17.4538L15.2212 16.816Z' fill='%23C7FF30'/%3e %3cpath d='M10.7756 13.7215L10.8668 14.0846L11.2056 13.6793L11.1407 13.2833L10.7756 13.7215Z' fill='%23FF8200'/%3e %3cpath d='M16.5001 15.5747L16.2749 15.9921L16.4516 16.921L16.685 16.5511L16.5001 15.5747Z' fill='%23F1FC06'/%3e %3cpath d='M15.0122 15.6936L15.4434 15.7024L15.6359 16.1751L15.2246 16.2139L15.0122 15.6936Z' fill='%23FBF100'/%3e %3cpath d='M15.0443 10.9896L15.0381 11.6552L15.5456 12.364L15.5672 11.7205L15.0443 10.9896Z' fill='%23FF1300'/%3e %3cpath d='M12.0823 10.3776L12.1152 11.0545L12.6843 10.982L12.6741 10.3007L12.0823 10.3776Z' fill='%23C40000'/%3e %3cpath d='M13.8623 9.96082L13.8908 10.6565L14.4815 11.0807L14.4708 10.3975L13.8623 9.96082Z' fill='%23B60000'/%3e %3cpath d='M13.1152 14.0405L13.7198 14.2005L14.0368 14.2526L13.4636 14.0977L13.1152 14.0405Z' fill='%23FF9400'/%3e %3cpath d='M11.9966 14.0058L12.4537 14.2135L12.7757 14.0796L12.3494 13.8583L11.9966 14.0058Z' fill='%23FF8D00'/%3e %3cpath d='M11.3677 14.0017L11.6726 14.2533L11.9964 14.006L11.7211 13.7306L11.3677 14.0017Z' fill='%23FF8D00'/%3e %3cpath d='M14.4702 10.3973L14.4808 11.0805L15.0377 11.6551L15.0439 10.9895L14.4702 10.3973Z' fill='%23D10000'/%3e %3cpath d='M11.1179 12.2739L11.1259 12.8136L11.5683 12.4703L11.5869 11.9084L11.1179 12.2739Z' fill='%23FF3800'/%3e %3cpath d='M15.5689 17.4825L15.3828 17.5016L15.4522 18.207L15.6438 18.2491L15.5689 17.4825Z' fill='%23ADFF49'/%3e %3cpath d='M16.1588 17.1991L15.8472 17.3845L15.9271 18.2114L16.2434 18.0837L16.1588 17.1991Z' fill='%23B4FF43'/%3e %3cpath d='M14.7576 15.2253L15.2124 15.277L15.4436 15.7025L15.0124 15.6937L14.7576 15.2253Z' fill='%23FFD300'/%3e %3cpath d='M11.5774 11.2873L11.5866 11.9083L12.0988 11.6882L12.1153 11.0544L11.5774 11.2873Z' fill='%23F10800'/%3e %3cpath d='M13.4634 14.0977L14.0366 14.2525L14.3527 14.3909L13.811 14.2499L13.4634 14.0977Z' fill='%23FF9400'/%3e %3cpath d='M15.8469 17.3849L15.5691 17.4825L15.644 18.249L15.9269 18.2117L15.8469 17.3849Z' fill='%23B1FF46'/%3e %3cpath d='M15.0403 16.2031L15.2251 16.214L15.3896 16.772L15.2213 16.8162L15.0403 16.2031Z' fill='%23EBFF0C'/%3e %3cpath d='M15.9897 13.187L15.8718 13.7573L16.2267 14.6348L16.3586 14.101L15.9897 13.187Z' fill='%23FF7E00'/%3e %3cpath d='M14.4673 14.8213L14.9489 14.91L15.2126 15.2767L14.7577 15.225L14.4673 14.8213Z' fill='%23FFB900'/%3e %3cpath d='M13.8113 14.2499L14.353 14.3909L14.6597 14.612L14.1488 14.4933L13.8113 14.2499Z' fill='%23FF9C00'/%3e %3cpath d='M15.2477 16.8041L15.2209 16.8162L15.3447 17.454L15.383 17.5015L15.2477 16.8041Z' fill='%23CEFF29'/%3e %3cpath d='M14.1489 14.4934L14.6598 14.6122L14.9489 14.9101L14.4673 14.8214L14.1489 14.4934Z' fill='%23FFA700'/%3e %3cpath d='M11.2058 13.6792L11.3679 14.0016L11.7213 13.7305L11.5895 13.3838L11.2058 13.6792Z' fill='%23FF7700'/%3e %3cpath d='M12.3494 13.8586L12.7756 14.0799L13.1153 14.0408L12.722 13.8153L12.3494 13.8586Z' fill='%23FF8200'/%3e %3cpath d='M11.1257 12.8134L11.1409 13.2832L11.5546 12.9634L11.5682 12.4701L11.1257 12.8134Z' fill='%23FF4A00'/%3e %3cpath d='M12.6743 10.3005L12.6845 10.9819L13.2693 11.0729L13.2826 10.394L12.6743 10.3005Z' fill='%23B60000'/%3e %3cpath d='M16.275 15.9924L15.9912 16.3238L16.1587 17.1994L16.4517 16.9213L16.275 15.9924Z' fill='%23EBFF0C'/%3e %3cpath d='M11.1409 13.2833L11.2058 13.6793L11.5895 13.3839L11.5546 12.9636L11.1409 13.2833Z' fill='%23FF6000'/%3e %3cpath d='M11.7212 13.7305L11.9965 14.0059L12.3494 13.8584L12.1066 13.5686L11.7212 13.7305Z' fill='%23FF7700'/%3e %3cpath d='M16.2269 14.635L16.0142 15.0983L16.275 15.9925L16.5002 15.575L16.2269 14.635Z' fill='%23FFC100'/%3e %3cpath d='M14.8064 15.6313L15.0125 15.6936L15.2249 16.2139L15.0401 16.2031L14.8064 15.6313Z' fill='%23FFE200'/%3e %3cpath d='M15.4226 16.7241L15.2478 16.8038L15.3831 17.5013L15.5692 17.4823L15.4226 16.7241Z' fill='%23D7FF1F'/%3e %3cpath d='M15.5457 12.3641L15.4448 12.9671L15.872 13.7575L15.9899 13.1872L15.5457 12.3641Z' fill='%23FF4A00'/%3e %3cpath d='M12.7219 13.8149L13.1153 14.0404L13.4636 14.0976L13.1043 13.8776L12.7219 13.8149Z' fill='%23FF7A00'/%3e %3cpath d='M11.5869 11.9085L11.5684 12.4704L12.0515 12.2641L12.0991 11.6884L11.5869 11.9085Z' fill='%23FF1A00'/%3e %3cpath d='M12.1156 11.0545L12.0991 11.6883L12.6409 11.6206L12.6846 10.9821L12.1156 11.0545Z' fill='%23DA0000'/%3e %3cpath d='M15.0496 16.1335L15.0398 16.2033L15.2208 16.8164L15.2475 16.8042L15.0496 16.1335Z' fill='%23F4F802'/%3e %3cpath d='M15.991 16.3237L15.6895 16.5666L15.8469 17.3847L16.1585 17.1993L15.991 16.3237Z' fill='%23E4FF13'/%3e %3cpath d='M13.2824 10.394L13.269 11.0729L13.8534 11.3257L13.8903 10.6563L13.2824 10.394Z' fill='%23BB0000'/%3e %3cpath d='M14.5261 15.1166L14.7576 15.2252L15.0124 15.6936L14.8064 15.6314L14.5261 15.1166Z' fill='%23FFC100'/%3e %3cpath d='M15.6896 16.5665L15.4226 16.7241L15.5692 17.4823L15.847 17.3846L15.6896 16.5665Z' fill='%23DEFF19'/%3e %3cpath d='M11.5891 13.3839L11.7209 13.7306L12.1063 13.5687L12.0078 13.2072L11.5891 13.3839Z' fill='%23FF6000'/%3e %3cpath d='M13.104 13.8778L13.4633 14.0979L13.811 14.2502L13.4858 14.045L13.104 13.8778Z' fill='%23FF7E00'/%3e %3cpath d='M12.1064 13.5684L12.3492 13.8582L12.7218 13.8149L12.5137 13.5206L12.1064 13.5684Z' fill='%23FF6C00'/%3e %3cpath d='M15.0381 11.6553L14.9568 12.2862L15.4448 12.9671L15.5456 12.3641L15.0381 11.6553Z' fill='%23FF1E00'/%3e %3cpath d='M14.2065 14.6727L14.4669 14.8214L14.7574 15.2251L14.5259 15.1164L14.2065 14.6727Z' fill='%23FFA700'/%3e %3cpath d='M13.8904 10.6561L13.8535 11.3256L14.4213 11.7337L14.481 11.0803L13.8904 10.6561Z' fill='%23C80000'/%3e %3cpath d='M13.4858 14.0447L13.811 14.2498L14.1486 14.4932L13.8567 14.3121L13.4858 14.0447Z' fill='%23FF8600'/%3e %3cpath d='M11.5683 12.47L11.5547 12.9633L12.0063 12.7716L12.0514 12.2637L11.5683 12.47Z' fill='%23FF3000'/%3e %3cpath d='M15.872 13.7572L15.6758 14.2634L16.0141 15.098L16.2269 14.6347L15.872 13.7572Z' fill='%23FF8900'/%3e %3cpath d='M13.8567 14.3123L14.1486 14.4934L14.4669 14.8214L14.2065 14.6727L13.8567 14.3123Z' fill='%23FF9400'/%3e %3cpath d='M14.4809 11.0807L14.4211 11.734L14.9564 12.2862L15.0378 11.6553L14.4809 11.0807Z' fill='%23E40000'/%3e %3cpath d='M16.014 15.098L15.7444 15.4809L15.9911 16.3235L16.2748 15.9921L16.014 15.098Z' fill='%23FFC800'/%3e %3cpath d='M11.5544 12.9634L11.5893 13.3837L12.008 13.2069L12.0061 12.7717L11.5544 12.9634Z' fill='%23FF4A00'/%3e %3cpath d='M14.7939 15.5076L14.8061 15.6312L15.0398 16.2029L15.0496 16.1332L14.7939 15.5076Z' fill='%23FFD300'/%3e %3cpath d='M15.2077 15.9948L15.0498 16.1331L15.2478 16.8037L15.4225 16.724L15.2077 15.9948Z' fill='%23FEED00'/%3e %3cpath d='M12.6843 10.9818L12.6406 11.6204L13.1974 11.708L13.2691 11.0728L12.6843 10.9818Z' fill='%23CD0000'/%3e %3cpath d='M12.5139 13.5209L12.722 13.8152L13.1044 13.8778L12.932 13.589L12.5139 13.5209Z' fill='%23FF6400'/%3e %3cpath d='M12.0991 11.6883L12.0515 12.264L12.5625 12.2014L12.641 11.6206L12.0991 11.6883Z' fill='%23F10800'/%3e %3cpath d='M15.7444 15.4812L15.4583 15.7796L15.6895 16.5668L15.991 16.3239L15.7444 15.4812Z' fill='%23FFD300'/%3e %3cpath d='M12.0081 13.2072L12.1066 13.5687L12.5138 13.5209L12.4506 13.1545L12.0081 13.2072Z' fill='%23FF5200'/%3e %3cpath d='M15.4581 15.7794L15.2075 15.9949L15.4224 16.7242L15.6894 16.5666L15.4581 15.7794Z' fill='%23FFE200'/%3e %3cpath d='M14.4878 14.9443L14.5264 15.1165L14.8066 15.6313L14.7944 15.5077L14.4878 14.9443Z' fill='%23FFB200'/%3e %3cpath d='M15.4445 12.9672L15.2686 13.5119L15.6756 14.2637L15.8717 13.7575L15.4445 12.9672Z' fill='%23FF5900'/%3e %3cpath d='M12.9319 13.589L13.1043 13.8777L13.486 14.0449L13.3495 13.7717L12.9319 13.589Z' fill='%23FF6400'/%3e %3cpath d='M12.051 12.2642L12.0059 12.7721L12.4834 12.7145L12.562 12.2015L12.051 12.2642Z' fill='%23FF2200'/%3e %3cpath d='M14.9298 15.3147L14.7939 15.5078L15.0496 16.1335L15.2075 15.9951L14.9298 15.3147Z' fill='%23FFC400'/%3e %3cpath d='M12.0059 12.7719L12.0078 13.2071L12.4503 13.1545L12.4834 12.7144L12.0059 12.7719Z' fill='%23FF3800'/%3e %3cpath d='M15.6757 14.2638L15.4248 14.6947L15.7444 15.4812L16.0141 15.0984L15.6757 14.2638Z' fill='%23FF9400'/%3e %3cpath d='M13.2693 11.0729L13.1975 11.7081L13.7539 11.9494L13.8537 11.3257L13.2693 11.0729Z' fill='%23D10000'/%3e %3cpath d='M14.1382 14.4586L14.2069 14.6727L14.5262 15.1164L14.4876 14.9442L14.1382 14.4586Z' fill='%23FF9400'/%3e %3cpath d='M13.3494 13.7716L13.4859 14.0448L13.8568 14.3123L13.7551 14.0641L13.3494 13.7716Z' fill='%23FF6C00'/%3e %3cpath d='M13.7551 14.064L13.8568 14.3121L14.2066 14.6726L14.1379 14.4584L13.7551 14.064Z' fill='%23FF7E00'/%3e %3cpath d='M14.9565 12.2863L14.8037 12.8641L15.2684 13.512L15.4444 12.9672L14.9565 12.2863Z' fill='%23FF3000'/%3e %3cpath d='M12.4507 13.1545L12.5138 13.5209L12.9319 13.589L12.9052 13.2282L12.4507 13.1545Z' fill='%23FF4A00'/%3e %3cpath d='M12.6405 11.6205L12.562 12.2012L13.087 12.2848L13.1972 11.7082L12.6405 11.6205Z' fill='%23E80000'/%3e %3cpath d='M13.8535 11.3259L13.7537 11.9497L14.2942 12.3385L14.4213 11.734L13.8535 11.3259Z' fill='%23DF0000'/%3e %3cpath d='M15.1593 15.0447L14.9302 15.3143L15.2079 15.9948L15.4585 15.7793L15.1593 15.0447Z' fill='%23FFB200'/%3e %3cpath d='M14.421 11.7336L14.2939 12.3381L14.8036 12.8637L14.9564 12.2858L14.421 11.7336Z' fill='%23FA0F00'/%3e %3cpath d='M15.4249 14.6946L15.1592 15.0449L15.4584 15.7795L15.7445 15.4811L15.4249 14.6946Z' fill='%23FFA300'/%3e %3cpath d='M14.5967 14.7019L14.4875 14.9445L14.7942 15.5079L14.93 15.3147L14.5967 14.7019Z' fill='%23FF9F00'/%3e %3cpath d='M15.2686 13.5118L15.0405 13.9861L15.4247 14.6946L15.6756 14.2637L15.2686 13.5118Z' fill='%23FF6800'/%3e %3cpath d='M12.4837 12.7141L12.4507 13.1543L12.9052 13.2279L12.9742 12.793L12.4837 12.7141Z' fill='%23FF3000'/%3e %3cpath d='M12.905 13.228L12.9317 13.5889L13.3494 13.7716L13.3591 13.4264L12.905 13.228Z' fill='%23FF4A00'/%3e %3cpath d='M12.5622 12.2013L12.4836 12.7143L12.9742 12.7931L13.0872 12.2849L12.5622 12.2013Z' fill='%23FF1A00'/%3e %3cpath d='M14.2169 14.1736L14.1382 14.4588L14.4876 14.9444L14.5968 14.7018L14.2169 14.1736Z' fill='%23FF7E00'/%3e %3cpath d='M13.1976 11.7083L13.0874 12.2849L13.612 12.5131L13.754 11.9496L13.1976 11.7083Z' fill='%23ED0400'/%3e %3cpath d='M13.3591 13.4266L13.3494 13.7718L13.7551 14.0644L13.8004 13.7446L13.3591 13.4266Z' fill='%23FF5500'/%3e %3cpath d='M14.7997 14.3832L14.5967 14.7017L14.93 15.3145L15.159 15.0449L14.7997 14.3832Z' fill='%23FF8D00'/%3e %3cpath d='M13.8006 13.7444L13.7554 14.0641L14.1382 14.4586L14.2169 14.1734L13.8006 13.7444Z' fill='%23FF6800'/%3e %3cpath d='M15.0405 13.9861L14.7996 14.3832L15.1589 15.0449L15.4247 14.6946L15.0405 13.9861Z' fill='%23FF7A00'/%3e %3cpath d='M14.8039 12.8638L14.6021 13.3753L15.0405 13.9859L15.2685 13.5115L14.8039 12.8638Z' fill='%23FF4300'/%3e %3cpath d='M12.9738 12.7932L12.9048 13.2282L13.3589 13.4266L13.4639 13.0069L12.9738 12.7932Z' fill='%23FF3400'/%3e %3cpath d='M13.7538 11.9495L13.6118 12.5129L14.1215 12.8798L14.2943 12.3382L13.7538 11.9495Z' fill='%23FA0F00'/%3e %3cpath d='M13.0872 12.285L12.9741 12.7933L13.4642 13.007L13.6117 12.5132L13.0872 12.285Z' fill='%23FF1A00'/%3e %3cpath d='M14.2944 12.3384L14.1216 12.8799L14.6022 13.3755L14.8041 12.864L14.2944 12.3384Z' fill='%23FF2200'/%3e %3cpath d='M14.3896 13.813L14.2166 14.1736L14.5965 14.7018L14.7995 14.3833L14.3896 13.813Z' fill='%23FF6800'/%3e %3cpath d='M14.602 13.3752L14.3896 13.8126L14.7995 14.383L15.0404 13.9858L14.602 13.3752Z' fill='%23FF5500'/%3e %3cpath d='M13.4642 13.007L13.3591 13.4266L13.8004 13.7446L13.9405 13.35L13.4642 13.007Z' fill='%23FF3B00'/%3e %3cpath d='M13.9406 13.3499L13.8005 13.7445L14.2168 14.1735L14.3898 13.8129L13.9406 13.3499Z' fill='%23FF4E00'/%3e %3cpath d='M13.6118 12.5131L13.4644 13.0069L13.9406 13.3499L14.1215 12.88L13.6118 12.5131Z' fill='%23FF2500'/%3e %3cpath d='M14.1214 12.8798L13.9404 13.3497L14.3897 13.8127L14.602 13.3754L14.1214 12.8798Z' fill='%23FF3800'/%3e %3c/svg%3e", + "iconPng": "data:image/png;base64,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" + }, + "oneInch": { + "color": "#323232", + "title": "1inch", + "icon": "data:image/svg+xml,%3csvg width='1070' height='420' viewBox='0 0 1070 420' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3cpath d='M470 116H510V276H550V76H510C488 76 470 94 470 116Z' fill='white'/%3e %3cpath d='M590 276H630V196C630 174 612 156 590 156V276Z' fill='white'/%3e %3cpath d='M670 156V276H710V196H750V236C750 258 768 276 790 276V196C790 174 772 156 750 156H670Z' fill='white'/%3e %3cpath d='M1030 156H990V116C990 94 972 76 950 76V236H870V196H910V156H870C848 156 830 174 830 196V236C830 258 848 276 870 276H990V196H1030V236C1030 258 1048 276 1070 276V196C1070 174 1052 156 1030 156Z' fill='white'/%3e %3cpath d='M590 116H630C630 94 612 76 590 76V116Z' fill='white'/%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M532.363 316V342.177H528.698L514.301 324.04V342.177H510V316H513.665L528.062 334.212V316H532.363ZM613.729 342.177H598.21V316H613.356V320.301H602.81V326.807H612.234V331.108H602.81V337.877H613.729V342.177ZM679.577 320.301H688.066V342.177H692.665V320.301H701.154V316H679.577V320.301ZM799.05 316H803.463L795.983 342.177H791.683L785.363 323.255L779.155 342.177H774.817L767.001 316H772.162L777.435 334.661L783.269 316H787.831L793.814 334.698L799.05 316ZM873.124 319.889C870.581 322.482 869.31 325.686 869.31 329.5C869.31 333.514 870.594 336.767 873.162 339.26C875.729 341.753 878.983 343 882.922 343C886.836 343 890.09 341.729 892.682 339.186C895.275 336.643 896.572 333.414 896.572 329.5C896.572 325.511 895.275 322.258 892.682 319.74C890.115 317.247 886.861 316 882.922 316C878.983 316 875.717 317.296 873.124 319.889ZM876.677 336.082C875.007 334.337 874.171 332.143 874.171 329.5C874.171 326.807 874.994 324.601 876.639 322.881C878.31 321.161 880.404 320.301 882.922 320.301C885.39 320.301 887.472 321.161 889.167 322.881C890.862 324.626 891.71 326.832 891.71 329.5C891.71 332.143 890.912 334.337 889.317 336.082C887.746 337.827 885.615 338.699 882.922 338.699C880.429 338.699 878.347 337.827 876.677 336.082ZM967.018 332.454V342.252H962.419V316.075C963.715 316.075 965.124 316.062 966.644 316.037C968.165 316.012 969.412 316 970.384 316C976.716 316 979.883 318.693 979.883 324.078C979.883 326.072 979.372 327.717 978.349 329.014C977.327 330.26 976.156 331.108 974.834 331.557L983.024 342.252H977.452L970.234 332.454H967.018ZM970.16 320.301C970.035 320.301 969.836 320.313 969.561 320.338C969.287 320.338 968.901 320.35 968.402 320.375H967.018V328.154H970.01C971.481 328.154 972.678 327.792 973.6 327.069C974.548 326.346 975.021 325.361 975.021 324.115C975.021 321.572 973.401 320.301 970.16 320.301ZM1048.87 342.177H1053.47V328.677L1064.17 342.177H1070L1058.56 328.191L1069.33 316H1063.79L1053.47 328.416V316H1048.87V342.177Z' fill='%232F7AEA'/%3e %3cpath d='M104.449 229.147L114.949 150.069L23.73 86.7412L107.074 114.96L126.761 84.7725L198.621 40.1475L357.105 127.429L365.308 260.647L294.761 358.757L238.98 367.288L267.855 314.46V263.601L246.855 223.897L225.527 209.788L192.714 243.585V279.351L167.121 303.304L134.636 307.241L120.199 315.444L96.5737 307.897L86.73 272.46L104.449 247.522V229.147Z' fill='white'/%3e %3cpath d='M250.136 86.0848C232.746 82.4754 213.715 83.4598 213.715 83.4598C213.715 83.4598 207.48 112.335 168.761 119.882C169.09 119.882 219.949 137.272 250.136 86.0848Z' fill='%2394A6C3'/%3e %3cpath d='M265.886 347.929C286.886 331.523 302.636 308.882 309.855 283.288C310.183 282.304 313.136 280.663 315.105 279.351C318.386 277.382 321.667 275.741 322.324 273.116C323.636 265.569 324.292 257.694 324.292 249.819C324.292 246.866 321.339 243.913 318.386 240.96C316.089 238.991 313.792 236.694 313.792 235.054C310.511 205.194 296.73 177.304 274.746 156.96L272.449 159.257C293.777 179.273 307.558 206.507 310.511 235.382C310.839 238.007 313.464 240.632 316.089 243.257C318.386 245.226 321.011 248.179 321.011 249.491C321.011 257.038 320.355 264.585 319.042 272.132C318.714 273.444 315.761 274.757 313.464 276.069C310.183 277.71 307.23 279.351 306.574 281.976C298.699 309.866 280.652 334.148 256.699 349.898C260.964 340.71 274.417 310.851 281.636 295.757L280.324 247.194L238.652 206.835L215.027 210.116L189.105 252.116C189.105 252.116 201.246 267.538 184.183 285.585C167.449 303.304 154.324 307.241 154.324 307.241L142.183 300.679C145.792 296.085 153.011 289.194 158.589 284.601C168.105 276.726 177.621 276.069 177.621 267.538C177.949 249.819 158.917 254.741 158.917 254.741L152.027 261.304L149.074 285.585L134.636 303.632L132.996 303.304L109.371 298.054C109.371 298.054 123.808 290.507 126.105 281.976C128.402 273.773 121.511 246.538 121.183 244.898C121.511 245.226 128.074 250.804 131.027 259.991C136.277 245.554 143.167 231.773 145.136 230.46C147.105 229.148 173.683 215.038 173.683 215.038L164.824 238.335L171.386 234.726L187.136 196.007C187.136 196.007 202.558 188.46 214.042 188.46C234.714 188.132 265.23 162.866 251.449 117.585C255.386 119.226 323.636 153.351 335.449 220.288C344.308 271.804 315.105 320.038 265.886 347.929Z' fill='%2394A6C3'/%3e %3cpath d='M187.793 93.3039C195.34 84.4445 192.386 71.3195 192.386 71.3195L170.402 103.804C170.074 103.804 178.277 104.132 187.793 93.3039Z' fill='%231B314F'/%3e %3cpath d='M113.964 270.82L116.589 257.695C116.589 257.695 105.761 276.726 104.777 279.351C103.793 282.305 105.433 287.555 109.699 287.226C113.964 286.898 119.214 280.664 119.214 276.07C119.214 270.164 113.964 270.82 113.964 270.82Z' fill='%231B314F'/%3e %3cpath d='M308.871 62.1324C308.871 62.1324 325.277 62.7886 342.339 64.7574C303.949 34.5699 267.527 25.7105 237.996 25.7105C197.308 25.7105 169.746 42.4449 168.105 43.4292L180.902 23.0855C180.902 23.0855 129.714 18.1636 111.667 72.3042C107.074 60.8199 102.808 44.0855 102.808 44.0855C102.808 44.0855 76.23 67.3824 88.6987 106.101C58.1831 94.9449 14.5425 79.523 12.9019 79.1949C10.605 78.8667 9.94875 79.8511 9.94875 79.8511C9.94875 79.8511 9.2925 80.8355 11.2613 82.4761C14.8706 85.4292 83.7769 136.289 98.8706 146.132C95.5894 157.945 95.5894 163.523 98.8706 169.101C103.464 176.648 103.792 180.585 103.136 186.164C102.48 191.742 96.5737 239.976 95.2612 245.882C93.9487 251.789 80.1675 272.789 80.8238 279.023C81.48 285.257 90.0113 311.835 97.5581 314.789C103.136 316.757 116.918 321.023 126.105 321.023C129.386 321.023 132.339 320.367 133.652 319.054C139.23 314.132 140.871 313.148 144.808 313.148C145.136 313.148 145.464 313.148 145.793 313.148C147.433 313.148 149.402 313.476 151.699 313.476C156.949 313.476 163.839 312.492 168.761 307.898C175.98 300.679 188.449 290.835 192.386 286.242C197.308 280.007 199.933 271.476 198.621 262.945C197.636 255.07 201.902 248.179 206.824 241.289C213.058 233.085 224.542 218.32 224.542 218.32C247.183 235.382 261.292 261.304 261.292 290.179C261.292 341.367 216.668 382.71 161.543 382.71C153.011 382.71 144.808 381.726 136.605 379.757C161.871 388.617 183.199 391.57 200.589 391.57C237.667 391.57 257.355 378.117 257.355 378.117C257.355 378.117 250.464 386.976 239.308 397.148C239.636 397.148 239.636 397.148 239.636 397.148C300.996 388.617 330.855 338.085 330.855 338.085C330.855 338.085 328.558 354.492 325.605 365.648C407.308 304.289 393.527 227.507 393.199 224.882C393.855 225.867 402.058 235.71 406.324 240.96C419.449 105.773 308.871 62.1324 308.871 62.1324ZM183.199 278.039C181.886 279.679 176.308 284.601 172.371 288.21C168.433 291.82 164.168 295.429 160.886 298.71C159.574 300.023 156.949 300.679 153.011 300.679C151.699 300.679 150.386 300.679 149.402 300.679C148.746 300.679 148.089 300.679 147.433 300.679C146.777 300.679 146.449 300.679 146.121 300.679C145.136 300.679 144.152 300.679 143.167 300.679C148.089 294.117 162.527 279.023 167.449 275.742C173.355 271.804 176.308 267.867 172.699 260.976C169.089 254.085 159.574 255.726 159.574 255.726C159.574 255.726 165.152 253.429 170.074 253.429C163.839 251.789 155.964 253.429 152.355 257.039C148.418 260.648 149.074 273.445 147.433 281.648C145.793 290.179 140.214 294.445 131.683 302.32C127.089 306.585 123.808 307.898 121.183 307.898C115.605 306.914 109.042 305.273 104.449 303.632C101.167 299.367 96.2456 285.257 94.9331 279.351C95.9175 276.07 99.855 269.179 101.824 265.242C105.761 257.695 108.058 253.429 108.714 249.492C110.027 243.914 114.293 209.46 115.933 195.023C120.199 200.601 126.105 209.789 124.793 215.695C134.308 202.242 127.418 189.117 124.136 183.867C121.183 178.617 117.246 168.117 120.527 156.96C123.808 145.804 135.621 114.96 135.621 114.96C135.621 114.96 139.558 121.851 145.136 120.539C150.714 119.226 195.667 51.6324 195.667 51.6324C195.667 51.6324 207.808 78.2105 195.011 97.5699C181.886 116.929 169.089 120.539 169.089 120.539C169.089 120.539 187.136 123.82 203.871 111.679C210.761 127.757 217.324 144.492 217.652 146.789C216.667 149.085 203.542 180.585 202.23 182.554C201.574 183.21 196.98 184.523 193.699 185.179C188.121 186.82 184.839 187.804 183.527 188.789C181.23 190.757 170.73 219.632 165.808 233.742C159.902 235.382 153.996 238.664 149.73 245.226C152.027 243.585 159.246 242.601 164.496 241.945C169.089 241.617 183.199 249.164 186.808 263.273C186.808 263.601 186.808 263.601 186.808 263.929C187.464 269.179 185.824 274.101 183.199 278.039ZM152.355 281.976C155.308 277.71 154.98 270.492 155.308 268.195C155.636 265.898 156.293 261.632 158.918 260.976C161.543 260.32 167.777 261.304 167.777 265.898C167.777 270.164 163.183 271.148 159.902 274.101C157.605 276.398 153.011 281.32 152.355 281.976ZM283.277 219.304C286.558 202.57 286.886 188.132 285.902 176.32C298.699 193.382 306.574 214.054 308.871 235.382C309.199 238.007 311.824 240.632 314.449 243.257C316.746 245.226 319.371 247.851 319.371 249.492C319.371 257.039 318.714 264.585 317.402 272.132C317.074 273.117 314.121 274.757 311.824 276.07C308.542 277.71 305.589 279.351 304.933 281.976C297.714 307.242 282.292 329.554 261.621 345.304C292.136 313.476 306.902 260.976 283.277 219.304ZM262.605 348.257C283.933 331.851 300.339 308.882 307.558 282.96C307.886 281.976 310.839 280.335 312.808 279.023C316.089 277.382 319.371 275.414 320.027 272.789C321.339 265.242 321.996 257.367 321.996 249.492C321.996 246.539 319.043 243.585 316.089 240.632C314.449 238.664 311.824 236.367 311.824 234.726C309.199 210.773 299.683 188.132 284.918 169.429C278.355 130.054 252.105 117.914 251.449 117.585C252.105 118.57 269.168 143.179 257.355 172.054C245.214 201.257 214.043 196.664 211.418 196.992C208.793 196.992 198.621 210.117 185.824 234.398C184.183 233.742 177.292 232.101 169.417 233.414C175.324 217.007 184.183 193.71 185.824 191.742C186.48 191.085 191.402 189.773 194.683 188.789C200.917 187.148 203.871 186.164 204.855 184.851C205.511 183.867 208.792 176.32 212.074 168.445C215.027 168.445 222.574 167.789 223.23 167.46C223.886 166.804 230.121 150.726 230.121 148.757C230.121 147.117 217.324 115.289 212.402 103.148C214.699 100.523 216.996 97.2417 219.292 93.6324C286.558 100.851 339.058 157.945 339.058 227.179C339.058 280.335 307.886 326.601 262.605 348.257Z' fill='%231B314F'/%3e %3cpath d='M175.324 171.07C181.558 163.851 178.277 150.398 166.793 148.101C169.746 141.21 174.011 127.429 174.011 127.429C174.011 127.429 140.543 179.929 137.589 180.913C134.636 181.898 131.683 170.413 131.683 170.413C125.449 194.367 142.183 197.648 144.152 190.101C153.339 187.804 169.089 177.96 175.324 171.07Z' fill='%231B314F'/%3e %3cpath d='M146.777 183.867L163.839 154.664C163.839 154.664 173.683 159.586 168.761 167.461C162.527 176.648 146.777 183.867 146.777 183.867Z' fill='%23FFD923'/%3e %3cpath d='M357.761 319.054C352.839 325.617 347.261 332.507 340.699 339.07C383.027 257.695 342.668 183.211 341.027 180.257C343.98 183.211 346.933 186.492 349.558 189.445C382.043 225.539 385.98 279.679 357.761 319.054Z' fill='%23D82122'/%3e %3cpath d='M397.136 214.382C382.371 174.679 361.371 140.882 315.105 110.367C270.48 80.8355 222.574 83.1323 219.949 83.4605C219.621 83.4605 219.293 83.4605 219.293 83.4605C220.933 82.8042 222.574 82.4761 224.214 82.148C234.386 78.8667 247.511 76.2417 260.636 74.6011C295.418 69.6792 330.527 81.4917 354.48 106.757C354.808 107.085 354.808 107.085 355.136 107.414C382.371 136.289 396.48 172.382 397.136 214.382Z' fill='%23D82122'/%3e %3cpath d='M304.605 51.9613C255.714 42.7738 224.214 47.3675 201.574 55.8988C200.918 53.2738 198.621 48.0238 196.652 43.7582C189.761 51.9613 182.543 61.805 177.949 68.0394C165.48 76.5707 160.23 84.7738 160.23 84.7738C167.449 60.1644 188.449 41.7894 214.043 37.1957C221.261 35.8832 229.136 35.2269 237.668 35.2269C260.308 35.555 282.949 41.1332 304.605 51.9613Z' fill='%23D82122'/%3e %3cpath d='M123.808 114.961C85.4177 113.649 98.2145 69.0238 98.8708 66.3988C98.8708 66.7269 101.496 101.508 123.808 114.961Z' fill='%23D82122'/%3e %3cpath d='M161.543 34.5702C132.011 52.2889 137.918 94.6171 137.918 94.6171C109.699 51.6327 159.246 35.5546 161.543 34.5702Z' fill='%23D82122'/%3e %3cpath d='M112.98 126.773C114.949 128.414 116.918 131.367 114.621 135.632C113.308 137.929 111.34 137.601 108.386 136.289C104.449 134.32 80.824 120.539 59.4958 106.429C83.7771 114.96 108.386 124.148 112.324 126.117C112.324 126.117 112.652 126.445 112.98 126.773Z' fill='white'/%3e %3c/svg%3e", + "iconPng": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAItUAAA2sCAYAAABTSr5cAAAACXBIWXMAAFxGAABcRgEUlENBAAAgAElEQVR42uzBAQEAAACAkP6v7ggKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA2bvjGMmrg4DjVzgKSKmhQI55b3bRc/HMXXfnvZ2TYnPN2PRIT/fmvdnVSWtLwNB4pIZINMJZSwupNgG8kKBN0yOKqRit2BZ00T+kbbShaWtJG9Fao72IUqSNhZIWPBvgxjfnYQzRNlAOdm8/n+Sb95vfzN3uzrz3+739awEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID15+xt5czZ+aWzZneubI1p6YLO4qgf8ujHQiq7Qy4lpjJu4+VxcbSvk+s1Mdf9zxRSfVd73Q3P6jdbB59dTPW3/o/XHq0996vT/6+Th1dOv05Iw8umXzfm4cr0++gs1teFhZKn3+N5aXxu96Lx6T45AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBfIudvHr4jzy93uwvKrO/3RrrA42hvz8JJOHl4Zcrk25nKg9dshlQ/HVD7Wuq8dH2rPPRJy/c+Y62TdlspT7Wf7Wkz1S+3xve3xn3Z7owvNCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBmdn7prJnecEenP9oVUxm3roq5Xh9SOdiOV9vxve34UMjl2+14ov8upPq5TePxyWYQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcEKb7S93Yr+8JqYyDrn8Ukj15pDK7THXv2jj/e3xwzGXp9vjiZ5jqT7Z6e9dNMsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAdW379vHLZ3eubO30R7tiKuOY6/6QysF2vNq6L+byrXZuouNVOWAWAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGve+YPBaTO94Y5OGtaYylUh1ZtDKh8Ouf51O3445jrRS1QqD2xZuPgMsxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYEzr9vd8X83ChtdLJ9ZqQ662tT8RU/yXmeqQ10RqsV5bMXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBFNzu/dFZncdSPqVwaUrmhjattPBRzeTrmOtE6KpU/MqMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA4yrOL3e7ebgn9MrVMdXbQqqfDrl8I+Y60fpv+lnO9pc7ZjoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwgtjaH39/Z3HUj6lcGnK9JeZ6T8zla22c6ITuCrMfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeF5md65sjan8dEz110Muf9Z6MOY60UarfGrTputOsiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA72ww2DzTG+6IqYxjrte3cTWm+u/teKINXqpPxrTcs0gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAZ7nupPNS2R7S8LKY6vtCLp8NqR6OuU6kZ9fmx3utGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDTTC4h5DqMuV4fU1kNuTzSjifSdyuk+k/di8anW0UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwwWxZuPiM2Ks/HnK5NqayGnP9amsiPY+OhFzfYFUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADABjCTSwi5DkMqN8Rc7w25fLuNE+l7rc2rD1phAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCIaj0+eyWVnTOWq1odCLg/GXCfSC14qX+/0955j0QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCJYDw+ubM46sdUroq53hFyfbSNE+l4F9LwMgsQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1qvBYHNncdSPue6PqayGVB5rxxPpxSzk8pdtNr7MggQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YjDYHFJ9bUjl3W38eEz1iZjrRHqpavPwcFgY/ckRkJoAACAASURBVLDFCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGvc7M6VrXFxtC/mekfI9dE2TqS1UsjlWqsUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1qDz0vjcmMo4pHKwjQ/EXCfSGu0f5ub2nGrVAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwBowN7fn1JDK7pjLgZDq38Rcj7Qm0hrvSKc/2mUFAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwEuo0987G3O9onVXzOVbbZxI66mQykErGYANZzDYPDu/dFbby50zu3Nl60x/9EOdxVF/Wsj1De3+uDvm4UpMZdztlbfGxdG+Zwq9cnW7h+6fFlJ9V3vtDc/U9oPvn95bp8VUb2uvueM71f79R9p4z3Or3Pn//n+5fvCZr//s2vfzvv/9vR77ft8z/Tk6uV7zzM/XTfUt05+7k4Z1+j5M+5/3Zr5sm75fcX65O33/pplMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA89fv7Tom98vqY600h179r40Rar4VUH56dXzrLygZgLdqycPEZs/3lTpgv2zqLo/7RPViqPxlTGXdSfVsnD69s97P9IZf3tnvazSGVg+35P2zn7mrd085/tp27v3WoPf9Q27s92s4/bg9w3Hr82Hv81el73j6LL7XP6r7Wx9rxn0w/m6OfUS4HWu+ZfnZxcbQv5uElrZX23O7YL6/pLiy/enbnytbpHmVubs+pVgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ5TZ/nIn9srPhVQ/GlP9Zsx1Ip0IhVzfZIUDcDycPxicNt1DzfSGOzr90a6QS4mpXNrJwytjGr4jpHJD6wMxlz9o96O723OfbMdfaOcOtcePtsdPuVfraKk+eWxOPND6+9Z97fw9x/bmv9PmzYE2v97ZHv98G9/cXaxv7PZGF8a0dEGnv/ecTZuuO8mKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAldV4q22MqvxJS/UzM5emY60Q6kQq5/LmVDsB3Mze359RubynGtNzrpOHFIdc3hTR6e7uPvLPtkQ7EVG9r451tz/RXIZX72/NfaeeecK/Vmtr3pPJYm6f/3I4/3+bqx9s8/ePWrW2/f+N0z9/OX9HGcXvd7s7iqD+7c2Xr2dvKma4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxP153U6Y92xVxvCrn+Yxsn0gnc41t69Qese4CNZ8vCxWd083AuLg4vCoujvaFXfzb0ytUxl99o/W5MZTWk+umQypdjqt90z9RGrq2Fw21N/GsbP9d+R7j72Bq5sY2/GPPwku5ifWMbF2b7y51Ng8FmVxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACADez8weC0kMrukOstbfy3mOtE2giFVH/ZFQDgxLF9+/jlM7mEmd5wx3RvE1O5tF3v9x/b4/xeO76n9cWQyzfcB6Xjusc63NbcoXZ8b1uHq+34YDu+vh1fNV2X0/U5XafT9dqW7stcvQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWuXO3j18RcnlzSPUjMdUnYq4TaWNVvrBpMNjsagCw9vX7+04JO+tM27e8tl3Dfyqm8gutG0Mqt4dcP9HOfbHtax5xb5PWX20d/0fry21Nf7Kt599v5246usbzcCUuDi/q9paiPRsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAGnT2tnJmJ41+JqT60ekfr3++f/heWvel8lQ37f1RVwWAl96rLtzzypnecEdMo58IuVze9ijvbn2gXatX2zX7823f8nAbj7h/SRt779auBQ+1PnP0d5lcb+nkek3Mw0u6aTSIaemC7kXj011RAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI6zs7eVM7upviXmcmdI9fCL9ofvpTVcyPUWVweA46/f33fKeXnl/M5ifV3Mw0tiGr6j7UneH1NZDbn8bUjlMfclSS9YqXy9XVfub3u9u1u3tuPrOqm+rZuHe8J82TY3t+dUV2YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA5+hVF+55ZbdX3hpzvSukenhN/+F76UUu5PLg2dvKma4UAN+78weD0zr9vT/SzcM9IY3e3q6zN8VUPhRz+VTI9SttfNq9R9Ia6kj7/eihNt4bUrk9pvprbW94eeyV129ZGP7gpsFgsys7AAAAAAAAAAAAAAAAAAAAAAAA/Bd79x6t11kXeDxN71CK9ELy7n2SNOec5Jzznsv77POe9JImnKRN2qQ577NPgq84FYuMEh0YjFoGdBQTF8uxCAUDKHYJo2aojlFAWkccq3SKVWCoimBsvIAVBS9cy6X0ljzznMioYFvSNJdz+XzW+q6dsmDR7nfv336e/vMAAAAAAAAAAAAAAABA1t+/5eyy6uwoQv323Ffm0cH30nGtETq1iQFwdNrtnWcun9jRW453rmqE+jvLUL+qqOq35Xl6d15vfMJ3RdK8KtSPlFX86zzn3pP//NY8516Z91jPb7Q6Vy6rYpHH4mm+DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA8tntx2ao3lFV8S1HFzy3Ig++lJ1ER6neYGwBf6+Jm97yiVYc8J5+be0VeU/xcUdXvKUO8rwz1I74fkvTVtWRVP5ivB/Oa8t15Pr65UdUvL8anv6UnTK1ptKcu8kUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5qRlrc5wWdV7ch9zuL10lIX6/nJ0e48JAixEy0e3PasxPt0uQ+zmmfiKIsRb8vWOfP1ovh72nZCkp15Rxc/lOXtP/vP+PF9vyn++YWb2XjgQn+FLBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwqS6sdK8rQ+aGiih9xYL305GtUnf9skgDzWc/l3XPLsL1VhtjN64UfLkLcl68fyH3Gd0CSTnEhfjz3O2Wo31xW8fvz9bqeqtO/aHLyDF8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4KS4uNk9r6jiC4tQ31VW9WGH0UvHVn6H3r9o0e7Fpgow9+1evKRVX9JoTV/TU9UvLUP9pjznfrsM8T5rBUmai+vU+HC+Hszz/F1lFV9TtuKLyla9YXl7e8M3DwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgeTmuM1+vLKv587osOmpeeYqF+pAzbW0YLMJf09285u6w6Y0VVPy/Psh/L7S9C/HD+6wfNdklaMOvYL5Qh3pOvvzzzLegJ9fWN9tR4z+Xdc30pAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgCe0rIpFWdWvKKr6LxwgLx2/ihBvMmGA2arZ7J61rNUZLkPs5pm1J7c/dyD/9aNmuCTpCda4n8zfittn1rr5ekNjfLrdc3n3XF9WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWMBWTE6eU1TxW4sQf6us4iGHw0vHt/xufbTRnnqaaQOcav39W87O82i8CJ0X5G/+a498+0O8L8+qw+a1JOk4rX0fztcDuf35zz+ar88tRuPAosnJM3yJAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYB5rjE+3y1C/qajqzzr8XTpx9YzX15o4wMm2tNqxohifnipD54fKEP9nnkcH8nf/EXNZknQqyvvOB8sq/nFRxVtnvk35Gpe1p/sWLdq92FcbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5qgVk5PnlCF2y6q+w8Hu0omvqOKtJg9wIjWb3bOWtTrD+ft+Q1HVe//5Gx//yQyWJM2R9fJD+Xogtz+3Z2a/OvNdW7Ro92JfeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJilZg4lL0P9xiLEzzu4XTo5FVX8zLNHOktMIOD42L24DNtW5fny3NyPFaF+R/6u/1X+82EzV5I079bSee+av3V3FVX9U0Wr/o4ybG+12zvPtB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAU6TZ7J5Vhtgtq/qO3GEHs0snt0aov9MkAo5Fb7v7zEZ7el05Pr2zqOq9eabcXVbxi2arJGkhV4T4cL4eyNd9ea+7a+ZbuWRs89OtHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAEKsO2VWUVX1OG+lMOXpdOTUWo78qv42kmEvCNrFhz3dKyFbcVIe4uQ7ytqOLfmqOSJB1lIT6a97735j3wLxWt+F/y93RTsWb6QisMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeCq63dPLqrOjrOo7cocdri6duoqqfnBpNT1kMAFf79kjnSVlqK8rQvzRfH1Xnhd/Z25KknQCCvXf5Ouv5/Y0QqdutKeWW4kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAN3DBpVvOL0PcVVbxrx2cLs2a9phOwIpW/U2N9vS6me90EeK+PBsOmI+SJJ268vf48/l6d1HVe/P3+YZlrc7wom73dKsWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFryl1fRQGeo3l1X9JYejS7Oqg/39W842pWCBfZdD9+KeqrOlqOKPlFV8Zxnix81DSZLmRF8qQn1X/n6/Jv/5ucVEvczKBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgIXitCLETWWIt5dVfdjh59Ks63A53rnKqIL5rbfdfWajPb0uf4935e/yvvzuH/BdliRp/pS/75/86r57T1HVnZ5m9wIrIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOaNCwfiM3qq+qVFVf+FA86lWVyo32piwfyyYnLynEarc2UR6huLEH+tDPE+806SpIVWPJSvB/L154sqfk8xFqtFk5NnWCkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwpyyf2NFbhPj6MtT3O8Rcmu3FfyzWTF9ocsHc1mhPLS+q+nm5nypC/f78HX7YfJMkSV9fXiM8kK935/36zTNrhyWt+hIrKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGalMmxvFSHuK0P9iMPKpblRTyt+m+kFc8zk5BmN8el2GeKuI9/dqv6YeSZJko61vJ74fL7ekdtTVHWn0Z66yIILAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAU6bRmr6mDPF3HEYuzbl+2wSD2a+YqJcV49PfUoT4+iLU7yuq+JD5JUmSTmCHy1DfW1T1Lxbj8SVFqw6Lut3TrcoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4gXYvLqq6U1TxAw4cl+ZeRYgPLGtP95llMMtMTp7RGJ9ulyHuyu/pvvy+fszMkiRJp774xXy9I7cnr1E29VzePdfCDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKdsydjmp/dU9UvLKv61Q8WlOVyIP2iiwanX09pW5vexW4T6dbn3FVV8yIySJEmzvX9es8Tfz+uYVxdV3elpdi+wsgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOCoNdpTF5VVvacM9accIC7N7YoqfqTd3nmmyQYn37IqFmWI3SLEW/L7eMBMkiRJ82afEeJHc/vK8emdy1qdYSs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/p1ydHtPEeIbylB/2SHh0nwoHirHO5ebbnByLK2mh/K7991FVb+tqOLfmkGSJGmhNLP2yd1ahPrFPe16dNGi3YutDgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABaoRntqeVHVe4tQf8Vh4NJ8Kv60CQcnzvKJHb3l+PTOIsR9ZYgfN3MkSZK+Wqi/kK935PbktdKmFZOT51g9AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzHPL2tN9ZRXfUoT4sEO/pflVEepP9La7zzTp4DiZnDyjJ0ytye/WjWWItxVV/VmzRpIk6Sj3J1X9YF5D/V6+/reyFbfZqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwjS8Y6K4sQbylD/YjDvaV523NNO3gKJifPaIxPt8sQd+X3aX9Rxc+ZK5IkScepEB/N3VNU9d587V5w6ZbzLUABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmmKUhNosq3nrk8GqHeEvz+YD620w8eHL6+7ecXbbixvwO7cnfyjuLEB8wTyRJkk5Oef31UBHqu/IabHdjvF7fbHbPskIFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYpXrGto8UIe4rQ3zUYd3SPC/UX14y1llp8sE3tnxiR285Pr0zvzv787tzvxkiSZI0e/Y1+XpHbk8R4qZ2e+eZVq8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACn2LJWZ7gI9TvKqj7sUG5pgTRef5/pB4/zXWxP95Xj0zvzu7K/DPWnzAxJkqS5UVHFz+Xrr5chfm/P2PaRvLQ7zeoWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgJFla7VhRhHhLGeKjDt+WFtBB86H+4KJu93RTEP5Zoz11Uf4Wdo98E6v6Y+aEJEnSfCn+U77uz2u9XY3x6baVLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAnQ09pWFlW9N/egA7alBVaIjzbaU+MmIQtZfgeeVoS4KXdTfifuKat4yHyQJEma/xWh/vt83V+OT+9cWu1YYWUMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwFDTaUxeVob65CPEBh2lLC7Q8A0xDFpzJyTOKavqKItSvLKr4f3IPmQeSJEnKHcx7pDeXIXaLNdMXWjgDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAchd5295llVf9YGeovODBbWsCFeN+Ssc1PNxVZCJZW00P5mf/e/O17V+5+M0CSJEnfYL/0aFHFD+S146sa4/X6RZOTZ1hVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/BuN9tTTyhB3lVX8RwdkSyqqumMyMp+/eUWIm/Jzvjd/++7zzkuSJOkp9qXcHblXLA2xacUNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsWO32zjOLUL+4CPGTDsGW9NX2m47MN8taneH8vXtZ7neLKj7kPZckSdKJqgjxr8oq/nQjdOoLB+IzrMYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAFodGqp8uqPujAa0n/cvh7FT+3vL29YUIy1104EJ/RMx63FyHeUob4ce+3JEmSTskeK8SHi1DflfdaP9xoT43npeppVusAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMC8sqyKE0UV73S4taTH6LtNSeaq5RM7essQd+Xn+I6iqh/0PkuSJGn2Ff8pX/fndesNy0e3PcsqHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmLPK0e09RYi3lFU85BBrSV9fEer3L1q0e7FpyVyxZGzz0/N3bVNR1XvLUP+N91iSJElzqhAfzd2T/7ynMT7dzkvc06zyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAWe/iZve8mQOai1B/xaHVkh77MPf6kTJsb5mYzHbLJ3b0liHuys/tHUUVH/L+SpIkaf4U/zFf9+f17g0rWvU3Wf0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACzSru988yeqn5pGepPOZha0hNVVPHHTU1moxWTk+fk79h1RYg/W1T133lfJUmStCD2aCE+nPdpdxahflkxGgfsDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFOqCHFTUdV/6iBqSd/4sPb6L3su755rcjJrvmFrpi8sQ+zmb9m+MtT3e08lSZKk+mN5fXxLUdWdZrN7ll0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUhRjsSpDfK/DpiUdZYeLqr7a9ORUa7SnBhtV/fL8TN6dv2OPejclSZKkx64I8fN5zfwr+c/fntfRF9lNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx93y0W3PKqp6bxniow6YlnTUh7FX9S+aoJwS3e7pjfHpdn4O9+QOeB8lSZKkYykeKkO8Z2ZdPbO+zivt02w2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAY9ftnl6E6f9UVPEzDpKW9KQK8dON9tRFBikny4UD8Rn5ufvmoqp/ceb58x5KkiRJx72P5fX23tzViyYnz7ALAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjlpPmFpTVPEDDoyWdCwVofMCk5QTbcnY9meXId6Qu72o6ge9e5IkSdJJ2vNV9Wfzdf/MevyCS7ecb3cCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pmVVLIqqfltZ1YcdEi3pGA9Xf08eJ6eZqJwIZdjeKkLcXYb6D32rJEmSpFmwBwz1V/I+8DfKVnzRijXXLbVrAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFrXbO88sQ9xVhvp+B0JLOubD1Kv6wUZ7atBU5Xha1uoM5+drT/5G3es9kyRJkmZz8VAZ4j0z6/elITbtZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAEqw/TWsop/7uBnSU+1ooo/Yqry1O1e3GhPrytCfH0Z6r/xbkmSJElztFDfm9f1N5XteFle6J9mrwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPYklZ9SRnqdznkWdJx6kCz2T3LdOWYdLunF1V9dVnFnylC/KT3SZIkSZpfFVX827zWf0PZqjfMrP9tggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYL6YnDyjDHFXWcUvOtRZ0nHqcKM9vc6A5Unpdk+feW6Kqt5bhPrvvUeSJEnSAinETxch7st7gU6z2T3L5ggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOaoRntqvAj1Bx3gLOl4VoR4iwnL0VgxOXlOUdWd/MzsK6r4Oe+PJEmStOD7Uhni7bkbLm52z7NrAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOaC33X1mUdV7yxAfdVizpOPcPywf3fYsk5bH03N599z8DeoUIe4rQ32/d0aSJEnSY5X3DA+UId6eu2Hm32XZTQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwCxUhtgtQv0JhzNLOiGHnlf180xavt6Ssc1PL6r4rWUV35m/QV/xrkiSJEl6knvNB8sQbyurzvMvuHTL+XZZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwivW0tpVFqN/uIGZJJ+yQ81C/27Tl/+vv33J2UdWdIsR9Zai/4B2RJEmSdFz2nlX9YBni7bkbLrh0y/l2XwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcDJNTp5RhrirrOIXHbws6YQV6i8vn9jRa+gucN3u6Y329LqiqvfmZ+JT3g1JkiRJJ7K893iwDPH23A0XXLrlfJsyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4gRrtqfEi1B90yLKkE36QeahfZuouVLsXN9rT64qq3pufhX/wPkiSJEk6RfvSr5Qh3p674YJLt5xvrwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMdJoz31tCLE15dVPORQZUknvvjHiyYnzzB9F5ae1vSlRahfV1T133kHJEmSJM2mihAfyPuVt+f9yvNm/j2ZHRwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAByjItRry6o+6ABlSSeneKiopq8wfReGZa3OcP7d9xRV/ReefUmSJElzoSLEB8oQb891+/u3nG1nBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR6Hn8u65RYg3lVU85MBkSSftcPKq3msCz29LWvUlZYi7ylD/oWdekiRJ0tzew8bPFSHuy3vZTru980w7PgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAyNVufKsop/7nBkSSf1MPJQf6K33X2mKTz/9DS7F5Tj0zvz73x37rDnXZIkSdK8K8RPFyHuy23K26DT7AQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFjwGu2ppxUh3lRW8ZDDkCWd7BqhU5vE88eKyclziqru5N92f/62POwZlyRJkrRgCvHjeT+0t9GeXmd3CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAglS24sayqj/m4GNJp6Ii1O8wieeD3YvLVr2hDPV/z93v2ZYkSZK04Av1vUWIP7qsPd1nzwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwLzXaE89rQjxprKKhxx0rPncsiqmraNXpyvHtqQe92O2HTB+fzm6vcdEnruWerHjwwAAIABJREFUVtND+bfck78nH/VMS5IkSdLj7X/jPbldzx7pLLGTBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABg3mmM1+uLUP+lQ401nwvhunTj0Nr0hoHxtLa1xT2ZhRXj8SUm8tzT0+xeUI5P78y/4d2eY0mSJEl6EoX4aL7eka83XNzsnmeHCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAnNZzeffcMtRvLKv6sIOMNR9bGWK6fmRDunXVWPpg7+r00ua6tKyK7s0srAj1+xct2r3YZJ4bGu2pp/WE+vqiir+ZvyOPeIYlSZIk6SkW6i/k6y8UIW5a1O2ebucJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCcUozFqqzqAw4t1nxs49g16TWDE+kPe1ele1f2pjcOtNNw2ObezN6Dwx8pw/aWyTzb7V5cVPXVM4e8f/Wwd8+uJEmSJJ2AilB/Iu+7bp7593f2ogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzHK7Fzeq+uVFFR9ySLHmU6vDVNrZXJ9uX9VMB1f2Huk9fYOpHr3K/Znthfhqs3n2WtKqL8m/0578O93neZUkSZKkk96B3Ct6WttKO1QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGaVRntqeVHFOx1GrPnUxrFr0s2DE+lDvf3p4MreIx1Y2Zf2DF2WVoboHs32Qrxvydjmp5vQs0t//5az82/Tzd2ee9SzKkl6si2rYhoIU0dqt7amibGtad3YtUfWbv+2a8Y2pzh69WO2Y/SqdP3IhsfshpHJtLO5/jF7SXNdunFo7df8Z88f/tf/7fTIv/5/bB7d/C9/L2tbW478fc4UwnX/8ve/3JpSkjQriofy9e5yfHrnxc3ueXauAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcUmWI3aKKn3EAseZDA2Eq7WyuT7/V10wHV/Z+TftXjaYrx7a4T3OlVtxmQs8ejfHpdlHVe/M349OeT0maX11SxTQYtqWJsa1p/di16ZqxzSmOXp2uH9mQvmv4OenFw+vSjUNrj7Rn6LIjvXpgTbp5cCK9caCdblldpbesDunWVWPpl3K39Q8f6Xf7BtOd/YPpfX2r0z29q9KHevv/3fpsvjTzz/eB3Mw/72/3Dx355//VvPacuScz92bmHr1uYCK9Nt+zmfv3yqHLj9zPXc0rj6xdv214Mu0YvSptHd2UNo5dc+S3GMm/SV/oeEYlSU+qIsQH8nV/vm7KW7nT7GYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhpLrh0y/lFiPscOKy53vIQ0/aRq9JbVod0YGVfOriy92v6o5X9aefw+tTjXs2dQ8CreKspfeotH932rHJ8emdZxT/2XErS7Ko3dFLVui5d2bo2bRrdnOLo1ek/jGxI/3H4OeklzXXpxqG1ac/QZemmwTVp70A73bK6SreuGkvvXDWS3t3fTHf2DaZ7elc95tpJs6t7czO/1Xv7BtL/zr/dbf3DR37LtwyE9KaB8fSawYkjv/XLmmvT9zTXp+cPb0j16FXp6rHN6dLW1tQMU0fWy94bSVqAhfjxIsSbeqpOvx0uAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnVFFNX1GE+FEHDGsu12ptSzcOrU139g2mgyt7H7NfXTWa1rS2ul9zqKKKn3n2SGeJSX2KdLun5+/Dpvxb7M/Xhz2TknRiu6SKabR1XbqydW3aOropPW9kY3rR8Pr0A80r056hy9LrBibSW1aHtH/VWHp3fzP9ft9A+nBv3+OufaTH649W9qf35ufnf/UPH3meZp6rnxpop1cNXpp+cOiK9JLmunTDyGSqR65KG8auTVV+LntDx3sqSfOlEO/J7SrWTF9o4wsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHHTbHbPKkN8dVnFQw4U1lxsWRXTN49sTP9j9Vj6s5V96eDK3sfsQ7396SXNdanHPZtz9YT6u0zrk29pNT2U7/9PFqH+e8+hJB1by3NjrevShtFr03NHr0ovHJ5M39e8Mr1y6PL0kwNr0s8OjKdfXjWafqN/OL23b+DIeuXx1jLSbGnmOZ15Xm/Lz+2+1a30pvwc//jQpenlQ1eknc316XnDG9PW0U1p7di1aSRsO7JeNw8kafZWhPhAUcVbG6GzedGi3YvthgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGaN9tRgWdV/5ABhzcUGwlR6aXNdurNvMB1c2fuEvWPVSLqstcV9m5OHe9d35XF1mol9clzc7J7XCPV3liH+gedPkp54HbJ27Nq0dfTq9O0jk+l7h65Me4YuS28YGE9vW91K7+5vpvf1rk73foM1irQQmnkPZt6Hmfdi5v2YeU9m3peZ92bm/Zl5j2bep5n3ynyRpFNciPfl654lrfoSO2QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ6Usuo8v6ziFx0YrLnWxrFr0s2DE+lPevvTwZW9T9iHe/vSjUNr0/IQ3bs5WFHFh5aG2DSxT7yZ+1yEeFO+55/x7ElaqF1SxVS1rkubRjen7sjG9N3N9em/Dl2RfnJgTXrr6lZ6x6qRdFff4JH1xTdag0g6tmber5n3bOZ9m3nvZt6/mfdw5n2ceS9n9gKj+T3tMbMk6QQXD+Xr3eX49M4lY5ufbtcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDjWjE5eU5R1XsdDqy51CVVTNePbEhv7x9JB1f2HlW/nv+7V4xtcf/mdntM7RP7PShD7Ob7fIdnTdJCqDd00sTY1hRHr047m+vTnqHL0hsH2unWVWPpzv7BdKC376jXGZJObQdW9qU/6BtIt/UPp19YHdLNgxPpxqG16YXDk0fe8Zl3fXneQ5h9kvTUK0L8fO6WRnt6nZ00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfoxiNA0Wo/8SBwJorTbS2plcNXpbu6V2VDq7sPao+srIvvay5Ni13/+Z48c9XTE6eY3Iff0tDbBYh3lRU8TOeM0nzpeVVTON53bB1dFP6juHnpJcPXZFeOziR9q1upd/qH0of6u0/6rWEpPnRgd6+9Pt9A+mdq0bSWwZC+onBNekHmlembx+ZTNeMbU5jretSj/kpSU+uEP8sX1+xZGz7s+2uAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWuCJ0XlBW9ZccAKy50JbRTennVlfpQG9fOriy96j7zf5mWjd2rXs49ztctuoNJvfxc3Gze17Zii8qqvr/er4kzcVWhpjWtrak545sTC8eXpf2DF2Wfmb1ePq1/pH0e70DT3rNIEkzfWRlX/qdvqF066qxdPPARHr50BXpBcPPSdeObU6t1ra0rIpmsCQ9RkUVH8r7y18tw/TWRd3u6XbdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALSM/l3XOLqt7rwF/N9pZXMV0/siG9Y9XIEx58/3i9caCdekPHvZwPhfqtpvfxsTTEZhHiTfk78FnPlqTZ3soQ05Wta9PzRjam72+uTa8dnEi/vGo0vbdvIN17DGsDSXqq/enKvvSevsH0S6vG0uvzfuMHh65I3zH8nLR1dFMK4brUY3ZLUipC/YmZfeeSsc5Ku3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgHmu0Z4aLEL8sAN+NZtbHabSS5vr0nv7Bo7poPsP9K5K3ZGN7uV8KdSfyrPrIhP82K2YnDynDLGb7+cdnilJs60VVUwTY1tTHL067WyuTz8xuCbdumos3dk/mA709h3TWkCSTlV/urLvyPyamWM3D06kG4fWputHNqSNY9ek3tAx9yUtsOKhI/vQvB9tt3eeaXcOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDPFFV8YRnqLzvQV7O1S1tb008Mrkkf6u0/5kPsf2XVaGq1trmf86rO803wY7M0xGZZxZ/Os/8LniNJp7IVVUwTY1tTHL067WyuP/K9v3XVWLqzfzAd6O075u++JM217uldlX6tfyTdPDiRbhxam64f2ZA2jl2TVoeO74WkeV0R4ieLKv748okdvXbrAAAAAAAAAAAAAAAAAAAAwP9j786j9Drvwo5LdhaSAk0IiT33HY0y7zbv+8673KsZRbIWj8baRhq990q2BwdI0jrtUUupSagoRmGxmpLaLVWK8YEekwXjYJbUrYtDix2TxDhOnDh26gVZaekS6JoFKDgJhGA/vTM0bRYvWmZ5l8/nnO+Zk5NjaeY+o+e5975//AAAAAAAAAAAAAAAAADoc6NbF14SJdnPG+CrXi1t7Q7vqbbD6fMYTn8q79r6tjAWp67pIA3dTrIP5tvYejv52bjugvy6dfPrd0/e036PJK1m5aQbLmvvC39z8tLw1tqW8EvVTrivNHFeZ7wkDUsPFKvh9nIz/LOJqXAsf7a5qjkbLmnPhY2JZxxJg1T6VP71/sKmw0cX31l6hgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6DMXx2mjEGenDexVr7UhScOVzdlwR6V53sPn7ytNhAOtPa7rgBXF6Zc2TB0u2cnPzMbNBy+O4uzHoyT7b35/JK10G/NzfFtnLnxPc1c4Xt8abq4m4a5yPTwxXjrvc12S9PWdyvtQuRZuq7TDydp0uKaxI6St3WG6fSCMOpMk9XXpZ/N+KmqlE57qAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6QCFOrywk6ZMG9KqX2pik4erJmXBPqb4sA+bfORGHWjzv2g5icfojdvLnN7Ip21mIs1+JkvTLfm8kLXevzs/tmfa+8PrmTLiutiW8q9oJHyzVwhPjpWU5xyVJ59dDxUq4o9IMPzOxKfxQY1t4bXNX2N7Zv7R/O8ck9VFP58+0947Eh7+7XJ57sSd9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBes7BwYSHJTiwOpDWUV71SJe6Gaxo7wv2l6rIMj3+sWFr681zbwSxK0senpo6+0Ib+zDbOzHxLIU7fkF+nR/y+SFqOxpI0bO/sD6+b3BV+tL41vKOahN8q1cOpZTizJUmr3+L+vbiPv7Mahx+rbwmvz/f3ne39YWO+3zv3JPX4+4A/ipLsxrHpy4ue/gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAekC0+fArCkl6tyG86pXanYPhrbUt4ZPj5WUbEL84HH5bZ871HdjSp6I422ZH/2ajSbccxekNUZL+gd8TSedaNe6GudaecLSxM1xf2xxuLzfDo8XlO6clSb3bqbwPlWvhlmocTtS3hKsnZ8Jse18o5meDM1JSr70byL/eU4jThXUzMy/wRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA2MTB3aVEjS/2LornqhzZ0D4fra5vBYsbSsQ+AXh79PxIdc48EenP2zdvSvdd0FUZKm+bV5f97Tfj8knU1J52D4ruZl4Xj9kvDOiTh8qFRb1nNZkjQYncp7f7ke3lFNwo/Wt4bvnZwJ2zv7w1iSOk8lrX1x+vtRnP342NSREe8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWyWgn/d5CnH3RoF2tdbPtfeGd1Tg8MV5a3iHvxVL4+41LwqhrPNBFcfY/N3ayl9nV1617xUT6bYVNh4/me/tpvxuSzqSJ+FCYa+0Jx+rbwi35WfxAqbqsZ7Ekafg6lXdXuR5uribheH1ruLI5G5qdeeeupLUpTv8i/3pPlGTd/LF5vTcHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArYWbmBVGc3mCwrta6S9v7lgatn16BQe4Plioha17mOg9HVwz7tj42fXlxcV+PkuwP/T5IeraqcTccau0Jx+rbwjvy8/e3S7VlP38lSXq2PlKaCO+ptsOJ+pbw+uZM2NaZC2POZ0mrWBRnv5t/vXZk6tB3ekEMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBMNm4+eHEhTj9skK7Wspn2vnBzNQmnV2hY+/vKjTDdOeBaD0Nxeucw7+lRku1evAaFJH3K74Okb6zdORi+p7krXF/bHO4sT4Ynxksrcu5KknSuncrPprvK9XDTxFQ4Vt8WrmzOhmY87xyXtKJFcfanhTh798imw1PeFgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnIcNSTpdiLPfMzxXa9We1t5wSzUOp1dwKPviMPZi3HW9h6E4++JF7e74sO3l5fLciwtx+oYozh71eyDpq5WTbphv7Qk/XL8k3FLphAdLlRU7ayVJWuk+XJwI786fHd+Sn2tXNmdDu3PQeS9phd4tpA8VNh0+Orp14SXeHgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnIUoSf923pcNy9VatLe1N9xSjVd06Prj46VwTWOH6z1MbcrePEz7+GhnvpDv428rxNnnrL+keudQuKo5G95Wf024szwZTq3gGStJUi/0QKkafrHSCT9W3xKumpwNSeegewJJy1j6mfx5+ycLrSOj3iQDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADyXmZkXFJL05wzG1Vq0r7033FKNV3y4+oeLE2FPa69rPkRFcfaJdQsLFw7DNl6YSrcU4uxXojj9c2svDW/NeD5c2ZwNJ+pbwp3lyfDEeGnFz1dJknq9h4uVcHu5Ga6vbQ5XT86EbZ25sCFJ3TtIOvfi7Cv58/fthU4668UyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA3eMVE+m1Rkv2Ggbha7Q609oRfqbRWZYj6v6o0QzOed92HasB1+hcjU4c2DfYOft0F+f7dzX/ee6y5NJy1OgfDX5u8NLx9Yjp8oFRblTNVkqRB6KFiZel59K21LeF1k7vCVOeAewtJ51j67/Ov127sZC/zphkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGHobpg6XCnH6hOG3Ws32tfeGX620Vm1Y+s9VN4XxOHXth2+o9T8d1L27XJ57cb53v8H+LQ1f5aQb0tbucKK+JdxZngynV+kslSRpGHq4WAm3VdrheH1ruLI5Gybjefcfks68OPuTKE5v3tDpTnrrDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMpZFOd3shST9r6K1Wq+3tuXBzNQmnV2kg+uLfc6K+JYy69sM4yPr3XtlY+NZB27cvjhdemf9810Zx+j+sszQcFeNuSFu7l86z28vNcGq8tCpnqCRJ+ss+WpoIt1TjcKy+Lcy19iydze5RJJ1B9xfidGHdwsKF3kIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEMhStI35n3ZgFutRknnYDhZmw6niqVVG3z++HgpvKE54/oPaVGSdQdpz94wdbiU/0w3FuLsi9ZXGvym2wfC0cbOcEs1XjrPVuvslCRJz9+pvLvK9XDTxFS4prEjzLb3hQ1J6h5G0jO/n4iz382/Xruxk73MG2kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFCtLyTZCUNttRo14kPhRH1LeKxYWtUh5x8tTYTd7b3WYFiL018blA17ZNPhqShOb81/pr+wttLgVovnw+smd4WfnpgKH8nPsNU8MyVJ0vn3cLEcfrnSDj9a3xqONC8LE/mzsHscSV//riL74/z5/uaolU54PQ0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADIxXNha+tZCkdxhkq5WunHTDsfq2pcHiqz3M/N+WG2FT54B1GOIh1aOd+UJ/79bXXRAlWTffrz9iTaXBbEOShj2tveF4fWu4o9IMp4qlVT8vJUnSyvXEeCncXaqHt09MhzdOXhq2dubcA0n6v6VPFeL0fVGc7lm3bt16b6wBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgL412pkvFOL0IYNrtZJtTNJwtLEzPFCsrsng8lurnVCNu9ZiuPtb/bpPNxoLL8r36TfkP8OnrKM0eBXz8+nK5mw4WZsOHylNrMk5KUmS1q6Hi+VwW6Udjte3hrS1e+newD2SNNxFSfpIYdPhoyNTh17q7TUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0FcKU+mWKM7+p2G1WqnG8q6enAn3lmprNqD8+trmsCFJrccwD6OOs4+tW3fdBf22R79iIv22Qpy+KUqy/2YdpcFqqnMgHG3sDLdU4/D4eGnNzkhJktR7ncq7q1wPJ2vTS8/T0+0D7p+koS39bBSnN0TT2QZvsgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAnhcl6WujOPtTw2m1Eo3mvW5yV/hAqbZ2g8iLpXC0sdN6DHn5Xvfl0faRZj/tz69qdi+KkuwfRXH6v62hNBhtSNKwr703nKhvCXeV62t2NkqSpP7svtJE+LnqpvB9kzvCts7c0jO3eyxpuN5tRHH6nqidJt5qAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9qRCnbyok6VOG0molmmvtCXeWJ9d04PijxXK4qjlrPRQKcfaT/bI3X9TJXh0l2Y359/xFayf1f2NxunQmXl/bHO4vVdf0XJQkSYPVw/kz722VdjhW37Z0v7ExSd1/ScPT/YU4XVi3sHCht9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQC9YX0iyf2L4rFaipHMw3DQxFU6v8XDxh4qVcKC1x5ooRHH2u6NbF17S6xvz6FTWiuL01kKcfcW6Sf1dMe6GK5uzS+fh4nn0qTU+EyVJ0nD0SLEcbqu0w/H61pC2dofxOHVvJg38O4/0Pxbi9E0jU4de6pU3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAmNs7MfEuUZP/C0Fktd6W4uzS4+7Fiac0HiX+0NBEube+zLlrs6XzP293L+/LIpmxnlKT/ZvF7tV5S/zYRHwpXT86Ed1U74dFiec3PQkmSpMV7kl+rtMJb8mf1bmv30nO7+zZpQIuzz+X9w42bD17sDTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsGo2drKXRUl6r0GzWs42JGm4enImPFCq9sTQ8PeX6yHpHLQ2WipKsl/s1T15ZOrwjvx7vMc6Sf1bNT60dAbeUo3D4+OlnjgHJUmSnq1T+f3Kv6o0w4n6lnC4uTuUk657Omng3oOkX47i9NbRqazlbTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsKI2JGkUJekjhstqOZtv7Qm/UZ7smQHh/7rcDJPxvLXRXxann7+ofeRVvbYfR3G6J4qzB6yR1J8V4264sjkbbpqYCo8Wyz1zBkqSJJ1tp4qlcGf+TH+iviWkrd1L9znu96SB6v4oybrr1q1b7+04AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALCsRttHmlGS/leDZLVcbe4cCDdXk54aBn5bpR0qBoDra4o62V/vnZ34ugsKSffy/Pv6pLWR+q/F8+UNzZnw7mocHh8v9dT5J0mStFw9ViyFX620wo/ULwn723vDWJK6F5QG4f1Ikv1OlKRvbDQWXuRNOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABw3gqdbFeUpH9kgKyWo3LSDcfrW8Pj46WeGvx908SUYd/6hoHR6b35Frh+7Xfh6y6IkqxbiLOHrYvUX43FaUhbu5fOmH83Xu6pc0+SJGk1erRYDrdV2kvvARbvizx3S33f/8o7Mdaaf7m35gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAOSkk3cujOPtTA2N1vo3lfd/kjvCxYrXnhnyfqG8Jo9ZIX1OUZH82MnWotrY78HUXFOJ0oRBnp62J1D8tnidzrT3hp2rT4cFSpefOPEmSpLXs4WIl/EI1Dj9Q3x4ube/zLC71a3H2J1GS3RhNZxu8QQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzlhhU/bmQpI+ZVCszre0tTvcXar35EDv4/VLrJG+qShJf2yt9t6pqaMvHImzv5F/H//ZWkj90/b2XH6mbA0fLNV68ryTJEnqxT5erISbq0k42tgZks5B95VS/70/+XIhSX9hQ6c76W06AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPBc1heS7ITBsDrf2p2D4aaJqZ4d3n1tfZt10jP1qXJ57sWrv/Ved0EhTheiJPsP1kDqj5rxfPiB+vbwb8qTPXvWSZIk9VN3l+rhbfXXhMtbl4VS3HXPKfVX90dJ1vVqHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4ejMzL4ji9FZDYHU+jSVpuKaxI3xyvNyTQ7pP5/1Afbu10jP19MjU4R2ru/Fed8FIfPi787/7U66/1AdnXJyGtLU73FxNwqnxUk+ec5IkSYPQqbw7y5PhRH1LmGvtCRuS1P2o1AdFcfax/OsVi+87vGwHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgCHXaCy8KIrT2w1/1fk039oT7i7Ve3Yo9+m872/ssFZ6lsHP6c2ruO2uj5KsW0jSf+faS73fts5cOFHfEh4oVnv2jJMkSRrkHixVws3VJBxt7AybOgfco0q9/47lPxXi9E0jU4de6s07AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyhxeGmUZzeZeCrzrUJ4EfRAAAgAElEQVR252C4aWKqpwdwnyqWwhsnL7Veerb+11hr/uWrsefm++2eQpw+5JpLvd1kPB/e3NgefrPc6OnzTZIkaRh7f7kebqhtDlc0Z0Mp7rp/lXq29LP51xOr9c4FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOgBr2wsfGsUZx8w4FXn0ljeDza2hUeK5Z4etn1qvBReN7nLmulZi5LsqpXeb6M43ZP/PQ+63lLvtiFJw1xrTzhZmw6P9vjZJkmSpK8+8xfD7eVmOFbfFmbb+9zXSr1YnP1JlGQ35s9ckTfyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDAxlrzL4/i7GMGu+pc2tXaH+4sT/b8cO3fGS+Fq5qz1kzPWr4P/uZK7rUjU4d3REl6r2st9W6tzsFwrL4tfLBU6/lzTZIkSc/dh/J7upO16fA9zV2hEnfd70q99A4myf4sitNbC/F8xdt5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgwGzcfvDiK08cMc9XZVo0Phetrm8OpYqnnB2k/Pl4KC81Z66ZnL86+ODZ9eXEl9tmRTnd7FGcfcJ2l3mxDkoa0tTvcXE3CqfHeP9MkSZJ09j1WLIXbKu1wrL4tzLb3uQ+Weqb0qfzrezd0upPe1AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAALg4uXxjlGT/wfBWnW2vbe4KHylN9MXg7MfHSyFrXWbd9JxFcfZDy73HFjZ1txbi9H2ur9SbtTsHw1vql4T7S9W+OM8kSZK0fH2wVAs31DaHI83LQjHuuj+W1r6nF9+hRMnhS7y1BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA+FbXSiUKc/r6BrTqbOp358I5q0jdDsk+Nl8JCc9ba6TmL4uzRqamjL1yu/bWQdNv5n/te11bqvUbzDrX2hJ/Pz7LFM6JfzjNJkiStXI8Wy+E91Xb4/saOMN0+4L5ZWvvuj5Ksu27duvXe4gMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAnyjERzqFJP2MAa060zYkafi7jR3hkWK5b4Zin8r77uYu66fnLk7/YjQ+tHk59taL47SR/5n/2nWVeq9q3A1HGzvDXaVG35xjkiRJWps+VK6F62ubQ9raHcbcS0tr+c7mofzrFevWXXeBN/oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0MM2JOl0IU4/bzCrzrTNnQPh1yqtvhqA/cR4Kfy1yUutn563KMluPN99dbQzX4ji9OZCnH3FNZV6q12t/eFkbTo8Uiz31TkmSZKk3ujBUiXcXE3C1ZMzoRp33WNLa/HuJk7/Y2HT4aPrZmZe4O0+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSY0fjwTCHO/sQwVp1JY3nH6tvC4+Olvhp4fTrvbzV2WkOdwVDm7L8Xpxb+6rnuqa9sLHxr/udca1+VeqsNSRqubM6G2yrtvjq/JEmS1Ns9Viwt3WNe09gRks5B997S6vefC3H6pnJ57sXe9AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABADxjpHN4XxemXDF/VmXRpe1+4szzZl0Ou39zYZg11Ro3E3exc9tPF4c2FJP3BQpx+3nWUeqdqfChc09gR7itN9OX5JUmSpP7qrnI9nKhvCXOtPWHU/bi0esXpp6P48Pctvp/x1h8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1shI3N0bxemXDF3V8zUep+F4fWs4NV7qy4HWP9TYZh11RkVx9i/PYTtdX4jThXw//U+uodQ7be/sDycnpsOjxXJfnl2SJEnq/z5Smggna9PhiuZsKMZd9+nSqpR+Jv967cjUoZf6BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVtFI3N0bxemXDFnV87W3tTfcU6r37QDr4/VLrKPOrDj740LryOjZ7KX5Pron/+8edv2k3mhDkoaF5mz45Uq7b88tSZIkDWaPFMvhHdUkvKE5EybiQ+7fpZV/z/O5/OuJjZ3sZT4NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAVNhJ390Zx+iXDVfVcjSVpOF7fGk4VS307sPona6+xljrjok3p95/pPjraPtKMkuw3XDepN3p1fmZdPTkT7i43+vbMkiRJ0vC0+K7l9nIzXNPYETqdeff00koWZ38cxekNo42F7/DJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsgCjJdkdx+iUDVfVc7WjvD+8rN/p6QPXJ2rS11BkXxdnH1q277oLn20PHpi8vFpL0l/P/5mnXTVr7JuP5cKy+LXy0NNHXZ5YkSZKGtyfGS+HO8mQ4Xt8aLmnPuc+XVqo4++MoSd82MnXoO31KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADLpLCpe1khzr5oiKqerbG8Y/Vt4XfGS309kPrd1XjpZ7GmOsOhyl8pxEc6z7V/buxkL4vi7O1Rkn7ZNZPWvs2dA+H62ubwaLHc1+eVJEmS9I3dVa6HE/UtYa61J4y695dWoPTJKMmuH5k69J0+MQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA8zCyKdu5ODDU0FQ9W9va+8Ovlyf7fvj0eyutMB6n1lRnXBSnNzz77nndBYU4fUO+f37GtZLWvtn2vnDTxFQ4VSz1/XklSZIkPV+/XaqF62ubQ9raHcY8D0jL3ReiJLtx4+aDF/v0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADO0simbGchSZ80KFXP1IYkDW9ubA+PFUt9P2z635YbYSI+ZF115sXppy9q7/0rz7R3Rkm2O4qzR10naW0bzbuidVm4vdzs+3NKkiRJOtceKFbDydp0SFu7w5jnBGk5+0KUZDdu3HzwYp8kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAZGNmU7Swk6ZOGo+qZasbz4dZqZyCGS3+4OBGSzkHrqrOrk85/474ZtQ9X8//vva6PtLZtSNJwZXM23FmeHIhzSpIkSVquHipWwk0TU0v3y2P5fbPnB2lZ+kKUZDdu3HzwYp8qAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCzGJk6vKOQpE8aiKpn6qrmbHiwVBmIYdIfL1bCJe0566qzKkrS2752zxxrzb88itMboiT7M9dHWrs2Jmm4enIm3FOqD8QZJUmSJK1kDxUr4aaJqXBlc3bpXtozhXTefSFKshs3bj54sU8YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBrFDrZrsUBoIag6hurxN1wsjY9MMOjHy2Ww772XmursypK0j94VbN70dKGOTPzgtEku6YQp593baS1q5SfT9c0doT7ShMDc0ZJkiRJq9lDxUq4aWIqXNmcDRuT1HOGdF6lT0ZxesPI1KHv9GkDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENvZFO2s5BkXzD4VN/Y7vbe8IFSbWCGRZ8aL4Ujzcusrc660Tj7m4v7ZaGT7YqS9HHXRFq7qnE3/HD9kvDxYmVgzidJkiRprXuwVAlvn5gOWfOyMJaknj2kcy59MorTGy6OF17pkwcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhlIhPtKJkvSPDDvV1zaWd6y+LZwaLw3McOjTeW+cvNT66uyL0/tGO/OFKE5vzf/3066JtDZV4u7S2fSJYnVgziZJkiSpF3uoWAk3TUyFK5uzYWOSeh6Rzq0vRHF6w1hr/uU+hQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgaFycHK4XkvSzBpzqa0s6B8Pt5ebADYS+tr7N+uocSp8qxNm7869PuhbS2jQRHwrH61vDQ8XKwJ1NkiRJUq/3iWI1vH1iOhxq7QljceoZRTrLojj933k/8R2vmft2n0gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMNCi6WxDIU4/bbCpvraF5uzSsORBGwD9zyeSMGp9JamvqsbdcKy+LTxUrAzcuSRJkiT1Yw+WKuFkbTrMtfZ4zyKdZVGS/kH+9cR3vGbu2306AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAuah95FWFJPuUYab6amNJGk7Ut4TTAzjw+fZyM7w6//mssyT1R7V4PvxEbWv45Hh54M4kSZIkaVD6ULkWfry+NWzv7PccI51Ncfa5/Ou1o1sXXuKTCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQnFq4a8WkuyTBpjqq23qHAh3VJoDOeD53lItNON56yxJfVA17oa31C8JDxcr57X3f/w8/3tJkiRJZ9dvlhvh7zcuCdOdA55tpDMu/Uz+9dqNMzPf4lMLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPrWyNShlxbi9MMGluqrXdWcDQ8VKwM50PnhYjls7+y3zpLU4xXjbrimsSM8UKye997/ifzP2NKZC3eXGwN5tkmSJEm93l3lejhW3xZanYOed6QzKU5/P+9N5fLci32CAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBfaTQWXhTF6V0GlWqxYtwNJ2vTAzvA+VRe1rrMWktSD7cxScPRxs7w0dLEsu393dbupT978c8d1DNOkiRJ6oeeGC+F28vNcE1jR5iM5z0DSc9XnH66sOnw0XUzMy/waQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACskijJdrsKcI5mZl5QSNI7DCfVYknnYPj18uRAD27+O5M7rLUk9WhjSRqONnaG+0oTK7b3j8dpeKBYHeizTpIkSeqXHh8vhXdVO+G1zV3h1fnzgOci6TmK0yfyrly3bt16H2wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADACiok2bVRnP75d7xm7ttdDThr6wtx9i4DSbXYFc3Z8FCxMtCDmt9Wf421lqQebDTv9ZO7wgdLtWXf+//JxOZv+vt+pH7JQJ93kiRJUj+2+F7qn9amw/723qVnBM9K0jMXxeljhThd8PEGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALL/1UZz+zP8bJNhJ510SODuFOLvJEFKNxWk4Xt8anhgvDfRg5vdU22HMektSz5W2doc7y5Mrsve/t9IKG5P0m/7OWjwfHimWB/rckyRJkvq5+0oT4UR9S9jSmfPcJD1LUZJ+KEoOX+KTDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFge6wtJ+rNfNzwwzt7ussCZK8TZPzR4VM14PvxypT3wg5jvLjdCJe5ac0nqobZ39odbqvGK7f33lmphMj/nnu3v/8cTmwf+/JMkSZIGoTvLk+Gaxo6l91iepaRn7J6onSY+9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBztbBwYSFJf+EbhwZGcfqYiwNnJv839IMGjWq2vS/cW6oN/ODlT46Xw/b2nDWXpB5pU+dAOFmbDk+Ml1Z27+/sf87vY7p9IJwqlgb+HJQkSZIGpcX799sq7XD15Ewoxl3PV9LXlT4Vxel7xqYvL/oEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM7GwsKFUZL94rMMDXx64+aDF7tI8NyiTYe/a3HApiGjw93Rxs7wO+OlgR+2fDrvtc1d1lySeqBmPB9uqG0Op1b4/Hki//OvaF12Rt/TO6vxwJ+FkiRJ0iD2iWI1/FRtOuxv7w2jnrek/1cUp3+ed/OGJI18GgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADPZ2HhwihO3/NcwwJH4sPf7ULBsxtN0kujOPtTw0WHt1cnafjpiamhGbD8lvpW6y5Ja9x4nIYfamwLDxfLq7L3/73G9jP+3va19w7NmShJkiQNah8s1cLx+tYw3TngGUz6anH2xSjJbryofeRVPhkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAZzA1dfSFUZzefgZDAt/lasEzuzhOG1GS/aGBosNbu3Mw3FFpDs1A5V+qdMJYnFp7SVqjRvO+p7krfKhUW7W9/6aJqbP+Pv9leXjORkmSJGnQu7M8GY42doZy0vVcJuVFSfpHhTh7y0XtvX/FpyQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwfzUaCy8qJOkdZzQgMM5+zxWDbzY2dWSkEKefNkR0eNvV2h/uK00MzQDle0u1UO8csvaStEbtbu8Nt5ebq7r331meDMW4e9bf61XN2aE5HyVJkqRh6eFiOdw0MRXS1u4w6hlNWvz87HP512sXP3PziQkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDbXG4XyFO33d2gwHnK64c/H+vmEi/Lf+38UmDQ4e31zdnwqPF8tAMTX4k/1m3d/Zbe0lag5LOwaXB9adXee//SGkidDrz5/Q9b0jS8IFSbWjOSUmSJGnY+q1SPRyvbw1TnQOe26Qk/ff51yvWrVu33qcnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADJ+FhQsLcfqrZzsQMErSv+3iwV+amjr6wihO7zIodDgbi9Nwor5l6AYlv25yl/WXpFWuGh8Kb61tCY+Pl1Z933+0WA67WvvP6/v/O5M7hu68lCRJkoatU8VSuLXaCd87ORNenaSe5TTURUn2YKGTzvoUBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgOGxsHBhlGS/dI6DAP+FCwhL1hfi7N0GhA5n1bgbfqEaD91w5LfWtlh/SVrFRvOunpwJDxSra7Lvn857/eSu8/45ivm5+fFiZejOTUmSJGlYeyi//z9Zmw5zrT2e7TTs3RN1stjHKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAy69VGS/fw5DwCM08+vW3fdBS4jwy7/9/APDAQdzrZ05sIHSrWhG4b8q5VWGLP+krRqXdbeF+6oNNd07z9e37psP89b8j9r2M5OSZIkScVwd7kRjtW3hWY871lPQ1r6VP71vRe1u+M+WQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAQrS8k6c+e7wDAkalDm1xKhtlInP0Ng0CHs/3tveFjxerQDT9+IP+Z252DfgckaRXqdObDz1Y3hdNrvPe/o5qE0WX8uZrxfHisWBq6M1SSJEnSX3ZqvLT0nJE1LwsbktTzn4auKEm/HMXpzRe1j7zKpywAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjEKcnVyOwX8jSfbDribDajTpzuX/lr5iCOjw9brJXeGxYmnoBh4/MV4KWesyvwOStMJtTNJwTWNH+OR4ec33/t8oT4ZS3F32n/FkbXrozlFJkiRJ39z9pWo4Ud8SNnUOeB7U0BUl2R8ufs42unXhJT5xAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoK8V4uwtyzj07/2uKMNoZOrQpkKSPmnw53A1mne8vjWcHtIhxz9R+z/s3XuYZWdd4PsG5AF1BmdwNPTelerUvt/32lXVt0p1qu9d1V21dhPTCQRFo6YVQzsywaPhKGkICAdPIhDITDRIjIaBiEQ6gIkIragJkAuGpLtzjuc5owcVx8vMqOAV8ju7ysATY25935fP53m+D/9p117vet+1sv74bbAOJOk0d3FjaxwuVPpi378nV4pOe/dp+Ts3tubj6ER+JM9TSZIkSf+6I7l8vLeUxEWNLTGepN4PNVJlOukXen3vqlVXP9fXFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZOttP9gVM66C/p/t2aubkX+mUZJee0u+f11v4XDfscrc7rpPHu0uTIDja+vdiI8Y6BxpJ0uppuLcTNpaR/BtpP5GOhue20/s3v7aO/V5IkSVL/dHe+HAer61fek7wvaqRK0qOZyb2LvsIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDKTey/OJulXTvmQv3a6xa/LqHjxuvkXZTrdhw34HK2q7cW4rdgc2UHG9+WKMdk2xFiSTkfjnTQO1Gbj93KFvtr799c3nfa/faG5bWTPVkmSJEnP3NGJfNxabMWljc2xpvfu5B1So1ImSe/MdpZavsgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ1zKd7rZef39aBvwl3Tf5hRkNVz83m6SHDPUcrTa25uNwoTKyw4uP9fqOxhZrQZJOQ4vN7XFXodZ3e/81lfVn7De4vdgY2TNWkiRJ0rPvvlwxrq1Mx/ntXd4nNSKlX+39720v6Vy4xrcZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+s5Ye++6bCf9m9M12C+TdO/xKzMKevfRTxvkOVpta+2Iz+SKIz2w+JrKemtBkk5xnfbu+LlSpy/3/VtK7RhP0jP2W7yiPjfS56wkSZKk4+tYr/cXm/Fdjbk4r5N6x9Twl3S/nEnSt7543fyLfKUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgL7wkSWuZTvqXp3egX/qVNe3uv/NrM8wyydJ3G+A5Wn1HY0s8mCuM9JDiDxfqscZwYkk6ZY33+k+18+P3+vR8uatQi1KyeMZ/k8P5ykift5IkSZJOrM/kinGwuj7Wthe8c2royyTdL2Yn9+5ftW/f83yxAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4KwZn3rp6myS/sGZGOa3Olnq+sUZVpmkO5PpdP/e4M7R6bL6XByZyI/0UOL7csWYNpBYkk5Zm5u74lCh3tf7/rqztO8fqM2O9JkrSZIk6eQ6OpGPW4utuLSxOca9f2rYS7rHskm6z5cbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzrhvLaf/NtvpPnCmhvhlkvSdfnWG0eqpxfHeGv9TwzpHpx+tbYxjhhHHd9Y3Ww+SdArKJ0txsLo+juTyfbvnH+m11Nx2Vn+jz+aLI3/2SpIkSTr57s6XV97BOu3d3kk11GWS7icyrbTjKw4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnxNTU/udnO91fP6MD/JLuMb88w+ac1o5vznbSzxnQORqN9bqmst7w4V7vKk9aE5J0CrqkviV+J1/q+33/itrsWf+trnYGS5IkSTqFHZnIx42lTuxpbl/5737eUTWcpV/t/e/N2eZLx3zRAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4HR6zsoAvbMwvG/11OK4n5+hupeS9AOGco5Gazpp3FDuGDjc67dz5Sgni9aFJJ1EnfbueE+pPRD7/nXl6b74zZq93+yhibyzWJJ0VjvSO4vuyxXj7nw5Dhcq8WuFWhwq1OP9xWbcWmzFjaXOyrvjtZXpla6prIuD1fUr/WR1Q1xZnfl6r6rPxv7appW+t35BXNrY/PW6za2RNretNN/cHltaO7/edGvh6y2fj8vvZ8fbqTyjx3vvy0/8v7/8rPP4f+fa9sK/+BuWW/67vvY3fq2XP+43WO6Vjbmv/0bL/UCvr/1+V1f++Xd9W3ntym99Q2ly5fe/udheuRa/3Lsmy9dm+RotX6tP9a7Z8rW7v5e1LOmJ/XqhGgdqs/6bl4a3pPvlTJK+9VvL6b/1aQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBTLtPp/tTZGtq3Oul+nyvAsMgm3WsM4xyNislS/Ndi04DhXkcn8rGnud26kKQTbDxJVwa1PzBRGIh9//ZiI87rpH3z+72jPOU8liQ9bUdy+bgvV4zD+Up8tFCPX+69y91Sasd/KU/GtZXpeFNlXRysro8frW2MK6szsb+2KS6vb4pLG5vj4sbWSJvbYldrR2xp7YwN7fmYbi1Etb0YpWTRs8wQVu5d1+Wm2gsr13qud92Xr/1Cbx0sr4V9jS0ra+N76hesrJXlNfO66oZ4Y2X9ynq6odyJny8lcWuxFYd66+2uQi1+q7f2ltfgEfejNJA9mCvEdeXplb3APqlhLJN0/zg7uXf/qlVXP9dXHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE6JbDu9/KwO7EvS97sKDMW9lKQX9db0o4ZwjsaA7Q8VG4YKP9by4HDrQpJOrPNb83H7AJ0p9+RL0W7v6avfcK6103ksSUPa53P5uCdXik/mK3GoUI/3F5vx86Uk3lWejLeV18bB6vp4bW0mrqjNxvfUL4hLGltiqbkttvTOhnXthWgkeyKXLHnmUF91Xidd+e8K062FOL+9K7a1dkTaW7eX1LfEKxtzsb+2Ka6szsTrqhtW3revrUzHDaXJeE+pHbcWWyv3wl2FWtydL8eDuYK9QjrDfbh3D35/78xxvmgoS9L7Vk92N/naAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwEnJdLpL2ST9ytkc0pfppH+5at++57kaDLKxZHFtJkn/1uDN4W95KPtHC3VDhB/rzkI1JpLU2pCk42y8k8b/Vt0YD03kB2bPf7j3b51vbu/L3/MDxaZzWZL6uM9NFOJT+XJ8pPcu9b5iK/5LeTLeVl4bP1ndED9SOz8uq8/FRY0tsau1I2Zau1beu5bPSs8M0jO3/E7eaO+Jja352N7cEXsb2+K7GnPxqvpsvLY2Ewer6+Pa8nTcWOrErb3771DvPvxkvhKfzRfjSC5vj5JOsHtzpXhDZV1MtRfsRRq2Hs0m6ftf0rlwjS8/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHLdz20v1bChxaxIAACAASURBVNL9q34Y0jfW3rvOFWFQjU+9dHWmk37BsM3hr9neHXflqwYHP9ZDE/m4oLXT2pCk42xza1d8pFAfuH3/VfXZvv1NL25sdTZL0hl6B/idfCk+VqjFB4rNuKmUxLXl6bi6sj5eU5uJ769fEJc0tsRCc3vMtOdX3qHO66TOf6mPKyZL0endq5t6z6jL9+6+3j18WX0uDtRm43XVjfHm6rp4R3kq3lNqx23FVny09xz727lyfD6Xty9KvY707oXl83Cxd//YUzRMZTrpP2Q63Xe8eN38i3wFAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4FlZs3b3S7JJ9w/7aDjfT7gqDOS9NDf3wt76/Ywhm8PfVHshPpmvGBb8uF5Tm7E2JOk4Gu+kcWV1Jh6eyA/cnv/O8mRf/7bn9n5b57QknVgP9c6lu/PluLNQjVuLrbi+PBVvqaxdObMuq8/FRY0tsaW1M1rt3Sv7rTNd0tfKJUsre8NMez7mm9vj0sbmOFCbjauqG1b2keX9ZHlfWd5flveZI/ZcDXm/ka+u3AP53r1hj9DQlHT/PJuk/3HVvn3P80UIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACApzS2Yd83ZjrpZ/prKF/6KVeGQZRJ0l80WHP429iaj9/OlQ0Hfly3FZsxnqTWhyQ9y7Y3d8SdhepA7vm3FxtxXqf/9/zl4fXOaEn65x6ayMfd+fLK2XNrsRXXl6fiLZW1cWV1Ji6rz0Xa3BYz7flotXfHuR3P9ZLOXLlkaWXv2dLaGRc1tqzsScvPcVdVN8S1lem4uZTEBwuNlf1reR87Zk/XAHZ/rrCynpf/m6L7XkPUA9l2d7OvQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADyZ52Q66a19N4wv6f5Tbmrft7g8DJLVnaVXG6Q5/M21dsY9uZKBwP9iMHAxJtsL1ockPYsmkjSuqayPI7n8QO759+RL0W7vGYjfupQsrQyvd1ZLGuaOTuTj7nw5Plyox02lJN5aWRtXVmfiu+sXxEJze2xsza/sh85gScP0PL38PHpBa2ekzW3xXY25OFCbjat7z9jvLE/GLaV2fLS3Jy4/ty7vkc4K9du5/d7eeb28dsfczxqWkvSOc6f25n0hAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4OuynfSN/TqIb3Wy1HWFGJh7aSpdn+mk/2CI5nC3vbkj7ssVDQF+Qvvrm6wPSXoWbWvtiLsKtYHd749M5GOhuX2gfvM3VdY5qyUNdMvvH4cK9bi5lMS1lem4sjoTl9XnIm1ui+nWQox3UmesJD1N5WQxZtrzMd97jr20sTkO1GbjYHV9XF+eiluLrbizUI2782Vnjs54n8hXVs715TXqXtWgl0nSf8x0uu948br5F/laBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMOKySbov2+k+2r+D+NJ3u0oMgnNaL/32TCf9guGZw93m5q6VgfaG/v7L3l9sxpj1IUlP25pOGq+vbIgjA77nv6o+O3C//XRrIY7k8s5sSX3XwxP5OFyoxG295+l3lybjDZV18erabFxS3xLbmzui1d4d5/bOD+eoJJ2ZcslSrG0vxK7WjnhZY3Nc0duTf6K6Pn6mPBU3F9txqFCP382XB/6ZXv3X/blivLm6bmX9uRc16GWS9E+yk3v3r1p19XN9OQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABhB53bS6WzS/XJ/D9/r/r4rRd/bt+952U56l4GZw93m1q64N1cy6PcJPZgrGPgrSc/QXGtnfKxQG/g9/7ry9MBeg5tKiXNb0hnvSC4fn8qX47ZiM95ZnozXVTfGZfW5WGhuj057d5zbSZ2TkjSAjfVqJHtitrUruo2tK3v7ldWZ+KnK2pXnztuLjfjd3v6/fA44D3U8HZ3Ix83Fdiw1t7nXNPBlku69vWZ8QAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABghL+lcuCbbSf/7IAzeO3dqb94Vo59lkvSthmQOd3OtnXFvrmS475N0oDZrjUjSUzTe68rqTDw8kR/4/f72YiPO66QDey0Wmtuc25JOS/flinGoUI8bS504WF0f+2ub4qLGltjSe4fIJUvOQ0ka8crJ4sqZsHw2LJ8Ry2fF9eWpuLXYisOFShwZgncFnZ4+VqitrBnPExrs0q/2eu+atbtf4ksSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAkBvbsO8bs0l636AM3cske1/lqtGvMp007a3TRw3HHN4uaO2Mz+aLhvk+SbcXGzGepNaJJD1J57fm41ChPhT7/T35UrTbewb+mtxRqDm/JR139+WKK/vHTaUkrqmsjytqs/Edza0r+3wuWXLmSZJOqnM7abTau2N7c0dc0tgSr+6dM2/snTc3lCbjl4vN+M18JR6eyDuTR7jl97Efr26MerLHPaNB7ku9DhYK8y/wVQkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBIZTvp+wZp2F4m6X7IVaMv76VkTzGTpP/LQMzhbVNrV3wmVzTA90l6aCIf57fmrRNJekJjvfbXNsWDucJQ7PdHevv9QnP7UFyby+pzznBJT/lse2ehGjeWOnGwun5lH0+b26LZ3u1skyT1ReVkMWba8yvn0/I5dVV1Q1xbmY5bi62VM+yBiYIzfQSeV64vT8X57V3uCQ1smaT7+9kk3efrEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwJDJtNMfHbhBe0n3r6am9j/f1aOfnNPa8c2ZTvqQQZjD28bWfNyTKxna+xS9tjZjnUjSE2q2d8cvldpDtd//YG3T0Fyf8zpp3JN3tkuj2kMT+bizUI2bSkkcrK6Py+ubYqG5bWXvdoZJkoaherIn5lo74+LG1jhQm42fqqxdOfc+UqjHfbmi54Eh6Viv5ffObu86j1n3Gtw+fm57qe5LEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwBDIJOn2bNL9p0EcsLd6au+sK0hf3U+d7i8YfDm8bWzNxz35kkG9T9FHC/UY76TWiiQ9rksaW+Kz+eEaVH9deXrortPrqhud5dIQd6TXJ/OV+MVSK95SWRtX1Gaj29wa0+2FONfzqyRpxCsli3FBa2fs6727HOidkW+uroubSkncUajFfbmiZ4kB7K58NS6vb4qJxHOOBq9Mkv5jptN9R25q37f44gQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCgxqcvzGU66V8O7oC99I2uIv1irNM9YOjl8La2vRB358sG8z5FR3ptae20ViTpsYrJUvxMeWro9vvbi404rzN8g9mb7d3x8ETemS4NePfnCiv71HXl6XhNbSYuamyJDe35WDOE+5YkSWeqUrIYm1q7Yl/vXH11bTbeVFkXN5WTuKNQi3tzJc8gfdyne9fnddUN0WjvsZY1iP1pppNetmrVquf4+gQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBAzmnt+OZMkn5+kIfqZZLup11J+kF2cmlDppP+g0GXw1m7vSd+M18xjPdpen1lg7UiSY+1o7kjDheG79y4O1+OVnv30F63G0qTznRpQLo/V4jbi424rjwdP1KbiW5ja3SGeH+SJKmfKyVLsam1Ky5qbIlX12bjTZV1cVMpiTuKtbg3V/Ls0gc9NJGPd5SnVq6TNasB/A54b3YqXe8rFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwGB4TjZJ3z/wA/WS9CtjtX0vdjk5m769sXROptP9IwMuh7Nashh3FqoG8D5Nv5WvRD5Zsl4kjXzjSRpXVTfEkSHc6x+eyMeu1o6hvn47e3+fc13qr+7PFeP2YiOuK0/Hj9TOj25ja3Tau505kiQNUMVkKWZbu+KixpZ4dW023lRZFz9fSlb+e9vnc3nPPGewY71+sdSKxeZ2a1MDVvrVTJLe8pJk37f5IgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDHskn648MyTC8zufdiV5SzZm7uGzKd9LChlsM79PdQoW7o7jP0HY0t1oukka/T3h23FZtDu9f/QG3TSFxH5750dro/V1i5/64vT8WV1Zm4qPd8Od1aiDHniyRJQ185WYwtrZ1xaWNzXFXdEDeWOivPBffnip6TTmMf6f3Gl9XnYtwa1CCVdP88204vX7Xq6uf6OAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBnVidLO7JJ+pVhGaKX6aQ/56pytmQ76RsNsxzO1nTS+KVi25DdZ+jnSh3rRdLId0l9S9ybKw3tXn9deXpkruX31S9wvkunsSO97ixU44bSZFxZnYluY2t02rudJZIk6UlrJHtiR3NHfE/vOf111Q3x7t4zxO3FRnwmV/RsdYo6nK/EFbXZyCVL1pwGp6R7f6azd6MvVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH1i9dTieDZJ/2KYhudlOukXXFnOhrFOekHvfvqKIZbD13iSxs+VOgbrPkMP5gox2V6wZiSNbBO98+ItlbVDvdcvD6w/r5OOzDVd/lvvyZWc89Ip6IGJQhwq1OP68lQcqM3GfHN75JIl54ckSTpl72Mz7fm4tLE5rqzOxLWV6bi12IrDhUocnch7HjvO7s8VV95vW+3d1pcGpUczSXrLOa2XfruvVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGfR1NT+52eT9O5hHJ63emqx4gpzJo039/z7bNL9Q4Mrh6+xXj9TnjJM91n0I7XzrRlJI9tMa1d8rFAb6n3+nnwp2u09I3dtr66sd85Lx9nd+XLcXEriYHV9XFafi5n2fJzbSZ0XkiTprLSm9xwy3VqItLkt9tc2rTyjLD+rHC5U4ohnt6ftoYl8XF+eio2teWtJA1Gm0/0f2ST9j6v27XueL1cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnQTbpXj+0g/OWB+bBmfOc3rr7VQMrh7O3VtYaoPss+lihFuPWi6QR7Qdrm+LBXGGo9/mHJ/Kxs7VjJK/vZHshjuTyznvpKfaGO4q1eHt5Kg7UZmN3c3uUk0VngyRJGpjWdNJY356Plza2xhW955n/o7w2bi224lP5sue9x7X8TvSzpU5sbe20bjQgpZ9b3V463+crAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAMygzuffiYR6Wl+l0P+Iqc6Zkk/SHDagczv5T7XxDc59Fx3rtbO2wZiSNXKVkKW4sdUZir/+B2qaRvtY3lRJnvka+B3OF+GChEW+urovvqV8Qm1q7YryTOg8kSdLQlu+9821u7orvqm+Oq6ob4j+XO3FHoRa/13suGuXnwg8Um3Fhc2uMWSPq/x7NJOkt395YOseXLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgNMs09pbyibdvx7yQXlfKhTmX+Bqc9rvp3Y3yXS6f2845fB1aWNzHJ3Ij/SA3GfbdeVpa0bSyLW5tSs+ma+MxD5/rX0+lprbnPkaqR7uPQcfKtTjbeW18f31C2JTb88bt/dLkiStNNar094dae894YrabLy1sjZuLbbiU/lyHBuhZ8Y787W4rD7Xe05MrQv1dZlO+j8zk+kVq/bte56vWgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKfBmrm5F2Y73QdGYkhekm53xTmdzmnt+OZs0j1mKOXwNd/cHp/P5UdmAO7J9Nl8MWrJonUjaaT6gdqmkTknPlRsxHkGpMdYrzsLVWe/hrIjvf3sznwt3l6eih+qz8bW1s5Y476XJEk6oXLJUmxu7YrvrG+O11U3xg2lybijWIvPTRSG9nnyt/KVuKI2u/K3WwPq8x7ITi5t8HULAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgFMsm3Z8fmeF4SfdaV5zTej910vcaQjl8bWjPx2fzxaEdcnuqu7y+ybqRNDIVOksrA9FHZY+/J1eKdnuPa/9YP1SfdfZrKLo7X46bS0lcVd0QFzW2RDlZdI9LkiSdgZafu+ab22N/bVMcrK5feSY7XKjE0Yn8UDxnfrr3Drn8jOn5Uv1d+tVMkt6SWbv3W33lAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAXG2ukrRmowXpIeddU5XTKTey82fHL4qiWL8Yl8ZSiG2J6J7ijU4txOau1IGolmW7vi4/nqyOzxR3rtbm537R9XobMU9+eKngE0UH0qX46bSkm8tjYTaXNblHvPu+5nSZKk/iqXLMVca2e8oj4XP17dGDeUJuNQoR4PTBQG8hl0+b3p9ZUN0Uj2uL7q2zKd9C+zk3v3r1q16jm+eAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJygsdZLG9mk++VRG4o3Pn1hztXnVFteV7376a8Mnhy+4bUfKjYGclDt2Wqhud3akTQSfX/9gngwVxipPf41tRnX/kl6a2WtZwD1bQ9P5FeeZ6+prIuXNTZHq73bfStJkjTgTbYXYm9j28o72tvLU/HhQj0+NzEY76fL79HL71Adz6Xq4zJJ97fObS/VffkCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4Tt9W2/dvskl6dDSH4e19lRXAqTQ1tf/5maR7j2GTw9W5nTRuKicDMYy2X7qh3LF2JA195/XOh2vL0yO3x99USmLM9X/SZlq74pjnAPVJ9+RLcXPvfr2quiHS5rbIJUvuU0mSpBGp1d698gx4oDYb11am44OFRnxuotCXz61HJvJxfXlq5X3KtVN/fktM/zHT6b5j+Xuqr2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADPUqaT3jqyw/CS9JAVwKnUW1dvM2Ry+HpLZW1fDpzt1x7MFWKyvWDtSBrqOu3d8auFxsjt8b+Rr0YpWbIGnqbbik3PAzrjHcnl485CNa6tTMdl9bmYac/HmPtRkiRJT6jVe5dNm9viQG125dnxg7332s9NFPrimfboRD5uLiWxrbXDtVK/flP8g0wnTX0JAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAbZJH3liA/B+1KhMP8CK4FTYWyyuyvbSb9quORw9b31C/piqOwg9brqBmtH0lC3p7k97smVRm5/Xx60PtOetwaeoVc25jwP6LR3f64QtxZbcVXvueuixpYoJ4vuP0mSJJ1wrfbuSJvb4kBtNq6tTMcHC434vd4z59l63l3+/7/8nOvaqC9L0jvOaS1N+CoGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwJManL8xlk+5fjfrwu0ySbrcaOFnntF767Zmk+0UDJYerna0d8dBE/qwNjx3EfidfinyyZP1IGsrO7aRxVXVjHB3Bs+FYr0sbm62DZ9F5vXXymVzRc4FOaXcVanFdeTq+r35BbGzNx5h7TZIkSWfgHXhteyH2NbbEa2sz8e7SZNzRey79fO7MvRN/sNCI72hudT3Uj98W/7b3vwcLhfkX+EIGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwmKmp/c/PJN1PG3y3PPiue50VwUl6TqaTftT9NFx12rvjnlzpjA2IHZZe2ZizfiQNZaVkKW4qJyO7v7+xst46OI6Wfy/PBTqZDhcqcW1lOi6rz608l7qvJEmS1E+1es+oaXNbHKjNrjy3frDQiAdzhdP2fPyxQi0ubWyOMb+9+q0kPTrWSS/wmQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAn00nfbNjd1wbedY9ZEZyM7OTe/e6l4SqXLMWHC/XTNgR2WLu92DDYVtJQNtfaGYcLlZHd328rtmLcOjiu1rUX4phnAz3LjuTycUexFm+urouLG1uj2l50H0mSJGngGk/SlXehlzc2x/9e3RDvKbXjcP7Uvkt/tFCPl/X+75/bSf3m6qcezSTpLaunFv+DL2YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDIWj3Z3ZRN0q8Ycve4YY/TF+asDE7EOa2liWzS/Wv30fA01uuG0uQpHfY6Ch3rtb25wxqSNHR9Z31zPJgrjOz+fk++FK32bmvhBHpfseUZQU/akVw+DhXq8ZbK2ri0sTkqyR73jCRJkoa2UrIUW1o747L63Moz8AcLjfjcxMm9Z9+Vr6783xtPUr+x+qZMJ/3L7OTe/atWrXqOr2cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBIWdPu/rts0v1Dw+2eMOgu2fsqq4Pjd/VzM530N91Dw9WP1jae1EDXUe1d5UnrR9JQtTyY+2B1fRwb4b39yEQ+FprbrYcT7NLGZs8IeuxeysWhQn1lT7mosSXKyaJ7RJIkSSNfq7175fn4yupMXF+eijsL1Tjaew89nmftw4VK7K9tinG/p/rpm2Mn/c3VU4sV39AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICRkU3S9xto9yQl6SGrg+OVSbqvdf8MV3sb2+JI7vgGtyoXD0/kY7q1YA1JGprKyWL8Yqk18vv7FbVZ6+EkGu+kcU++5FlhBPt873nyA8VmXFXdEHua2yOXLLknJEmSpGdRsffsvLO1I36wtil+ujIdv1JoxAMThWd8Bv+NfDUuq8/13sP8huqPMkn373r/e7BQmH+Br2kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBQy7bTyw2ye8q+ZLAdx+Pc9lL9saGI7p8haWNrPu7PPfOAVv3rrqmss4YkDU3r2/NxV6E28nv7DaXJgbt2r/zha/ru3/T6ygbPCiPS4UIlrq1Mx6WNzVFMluynkiRJ0ims1d4dFzW2xJXVmbi+PBV3FqpxdCL/r57LfzNfiQO12Tivk/rd1C8dWT3Z3eSrGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMJTGOkuFbCf9G8PrnrrVydIOK4VnZW7uGzKd7mfdN8NTLlmKjxbq/2oIq565+3LFqLYXrSNJQ9GFza1xf29fG/W9/dcKtcj3zsZBunYX7//J+Kd/+kqsW/j+vvp3ddq740gu75lhCDtcqMS1lem4tLHZs5AkSZJ0FlrTSWOmPR+X1efiLZW1cWuxFZ957J3+U/lyHKjNxkSS+q3UDz2aSdJbVk8t/gcf2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKFRKMy/INvpPmBo3dOXSbrXWS08G7318gb3zHD1zvLkyrBVHX+vrc1YQ5IGvrFeP17dGEcn8iO/r9+XK8ba9sJAXb/K7MvjC3/yZ7Hs3e/9lb779/1Cse2ZYQj6dK4U/7ncicvrm2J6wO4RSZIkaZRafl6/uLF15T3/TZV10W1ujfFO6rdRH5T+97F2+gpf2QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKGQ7aQ/bVDdsyjpHrNaeCZjyeLa3lr5J/fM8HR5fVM8MpHTCfS7+XLkkiXrSNJAt7yP3Vjq2Nd7Heu1r7Fl4K7hL/3KXfE1/+N//XXk1u/rq3/f8m9qfQ1eD+YK8YulVrymNhNzrZ0xZr+UJEmSJJ2afv3cqb15X9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICBtXpq72y2k37VgLpn1zmtpQmrhqcytmHfN2aT9Kh7ZXiabe2KB3OFeGQipxPo8vom60jSQNds744PF+r29Mf6ier6gbuGL3/V1fHoo4/G4/3I69/RV//G8V5358vWWJ93JJePQ7394GDvPkib22IiSe2TkiRJkqTTUiZJ/zabLF01NbX/+b6+AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2X11OI3ZTrd/9twuuMZYrf3VVYOT6V3P73dfTI8FTpL8euFajwykdMJ9PF8NcatI0kD3JbWzvidfMme/li3FlsxnqQDdQ0rsy+PP/rin8UTPfDQ/9V3/9Y3VNZZZ33Yb+fKcW15Oi6pb4lSsmhvlCRJkiSd4e+S6eezU+l6X+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICBkU267zKQ7jhL0kNWDk9m9dTe2Wwn/ar7ZHj62VInHpnI6QS7uLHVOpI0sL2ssTkezBXs54/1qXw5asniwF3H993+8XgqC6+4sq/+rRva89ZaH3Qkl49DhXpcVd0QW1o7Y8x+KEmSJEk666VfzSTpjd9W2/dvfI0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6WnZyaWu2033UILrj7ktr5uZeaAXxeC9eN/+ibJL+gftjeDpQm41HJnI6wW4vNmLMOpI0gC3vXVdWZ+LoRN5+/lgP9X6Lra2dA3ctX/aDr49HH300nsr7bv943/2bl89Pa+7Md0+uFNeXp+LSxuYoJ4v2QkmSJElSn5b+t7HJ7i5f5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgL50TmvHN2eS9P8xfO7EWp0s7bCKeLxs0v1598bwtL25Ix6eyMcjEzmdYLtaO6wlSQPXeZ003lmetI8/ocvrmwbuWlZmXx5/9MU/i6fzd3//D1Hf/Iq++nfvr22y5s5AR3L5OFSox1XVDbGltTPG7H+SJEmSpMHqtpck+77N1zkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCvZDrdnzVw7sTLJN3rrCIedz8tuS+Gp3yyFJ/IV+KRiZxOsFtKbWtJ0sBVT/bEh4oN+/gTuq48PZDX8323fzyejYP/53v66t9dShbjwVzB2jsN/U6+tLKeX9bY3Pudl+x7kiRJkqQBL/2zsXb6Cl/pAAAAAAAAAAAAAAAAAAAAAAAAAAAALuZpSQAAIABJREFUAAAAAACAvjA22d2V7XQfNWzuJEq6x6wkluWm9n1LJun+sftieHp7eSoemcjpJNre3GEtSRqoNrTn45P5ij38CR0q1GMiSQfuer7iijfEo48+Gs/G7/+3L/Tdv/9d5Unr7xR0pNdtxVZcWZ2JC1o77XWSJEmSpKEs00k/9pLOhWt8sQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM6a3NS+b8km6f9nyNzJNz59Yc6KIpOkN7ofhqdL6lvikYmcTqKbS4m1JGmg2tHcEZ/OlezhT+je3m8y3V4YuOtZ2fTy+OM//fM4Ht3v+bG++hsWm9utwRPswVxh5Vlkf21TNJI99jhJkiRJ0miUdL/c+98fW7Vv3/N8uQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM64TKf7C4bLnZoySfeHrKjRNtZJL+ithUfdD8NRq707PpsvxiMTOZ1EW1s7rSdJA9PLG5vjwVzB/v2Ejk7k46WNrQN5Td//4d+I4/Vff/XjffU3jPX6ZL5iLT7LPpUvx7WV6biosSXO66T2NkmSJEnSKPfA6qnFSV/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAMybT6S4ZJncKS9I7rKrRtWZu7oW9dfCIe2E4Gut1S6kdj0zkdBK9p/cbWk+SBqUDtdk4OpG3fz9JP1adGchr+p2vfkOciC99+e+idP4lffW3vK660Vp8mu4sVONgdX3MN7evPMfZ0yRJkiRJ+ucySfqP2aR7TaEw/wJf8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgNMqs3bvt2aS7hcNkzulfWnN3NwLra7RlE26b3IPDE8/XD0/HpnI6SQ61mtLa6f1JKnvG0/SeFt5rb37Kbq5lMS5nXTgrmtl08vjj//0z+NEXXnw+r76eybbC3F0Im9NPtaRXh8sNOJAbTY67d32MkmSJEmSnqFM0v39sWTvnC96AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAaZPtpO8zQO7Ut7q9d6fVNYr301Irk6T/6B4Yjs5vzceDuUI8MpHTSXRTKbGeJPV9xWQpfqnUtm8/RYfzlSgniwN5bT/w4U/Eybj394713d90a7E10uvx3lwp3lWejEsbm1fuXXuYJEmSJEnHWZJ+JZN0r1s9tfhNvu4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACnVDbZu2Bw3OlpeRCdFTZqrn5uNknvtv6Ho/M6aXy0UI9HJnI6iY71uqC105qS1Nc1kj1xR7Fm336KPp/Lx+bmroG8tq/84WviVNh84RV99Xd9X/2CkVuHh/OVeFNlXexubo9x+5YkSZIkSaeq/zfT6W7zjQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADglVk8tftPyoDTD4k5TSfeYVTZasp30Ndb+8PTGyvp4ZCKnk+zGUsd6ktTXTbcW4hP5ij37adpf2zSQ17ay6eXxJ3/6F3EqvPvmD/XV31ZKluLzufzQr73DvXvzLZW1Md/cHmP2K0mSJEmSTlePZpL0xhevm3+Rr30AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBJySTpzxgSd3o7d2pv3kobDS/pXLgm20n/xrofjra1dsSRXD4emcjpJDo6kY+Z9rw1Jalv29raGffkSvbsp+mG0uTAXt9fvuOTcar82V/8z1iz9sK++vveU2oP5Zq7s1CNg9X1Md/cbp+SJEmSJOkMlknSP1mdLHV99QMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE7IWLK4NpukXzEg7vS2urP0aqttNGSS7q9Z88PReK+PFOrxyEROJ9nPljrWlKS+LW1uiwcmCvbrp+nOfC3yydJAXt/v/uFr4lT73tf8VF/9jd9V3zw8a61QjauqG2Kmtcv+JEmSJEnS2e/m8eaef+/rHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8OzNzX1DNunebyDc6S+TpHdacMMv21n6Tut9eLqquuH/Z+9OoCSr60OPt5gY15y4IPStnhnrVvW+1L3dDDMDM9MzwOzd9zbEDiJCUHCUuKBiQsDEIZoQnsYFTUw0KBGNCtEYBIOoGZUQcQFxxIFSYzQ+RVDEJSDLDPN/BXnPPBOFWaq6q25/Pud8Tw24cLru7/6Gc/5zzj/Uy7Ga0Nqx9WZKUlv27OHJsLNcsasfohvK1XDE2IaOfL4Dq04It9x6e2i2qz752bb6OeNk+sHn1Kkz9pHq4IP/3rW8ttFekiRJkiSp/bq10W86BQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPZKVMt+10Vwc1OU5vccPDT7eFNXXN0TU08pJfn3zXsxWjG2MdxYroR6OdYB9u6+mpmS1Ja9aGhluNmefth+e3h1xz7jv7t8e2iFXbt3h3TdKW31s76lP+2Ymbqp8e9YH6oOh7MHl4eltU32kSRJkiRJnVCSXXLI2LFPdSIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8Uoemxy0ppfmdLoGby6aPM3nFFSXZu8x4MVqUZuED1ZFQL8dqQptGjzZXktpuz58/sNSO3ose+J469Tn/9otfHVrp3D97e1v9vL81clRbz9LOuBLe2zsafmd4ZRitbbaLJEmSJEnqwKI0v6M0PrPVqSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPALldLsKpe/zXFJ/g6TV0w94/kGM16cXjJ0ZKiXYzWhD/aOmClJbdXiJAtv6J+wo/eif6iOhCVp1pHPeXjNieG2798RWmnHzq+11c/8wLP6fNzXdnP0oepweNHQyjBa22wHSZIkSZJUmDPP7EOLJ47tdkIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8TE8tO9GFb/NRdltX17aDTGCxHDK27nGNZ/sN812MJmqbwg3laqiXYzWh3xxZa64ktU1PS7NwYV9iP+9Fn4/7Hvw9sVOf9Qc+/IkwF1bNnN5WP/cb+yfaYn4+Uh0MZw8uD0s7eIYkSZIkSdJDF6XZD0rp9LOcFAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3R0pknl9Lsey57m6fGp5ebwmIpJfnrzHYx6mn0t71joV6O1YT+sTr04HdqtiS1Q9V02o7fy24qV8LMyNEd+6yf89Lzwlx53V+9t61+9nzkqHmbm09WBsK5g8vCEWMb7BxJkiRJkhZW/7Bk6eZDnRgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMACVkqzi1zuNo8l+R+bwuI4NMmGoiS7z2wXo+cMrw71cqwmddLIpLmS1BaNJFvC5b1DdvNe9orB5Z37rNc8K3zv9jvCXPnGt25pq59/caPPxH1zNitXV/rDqwaWhbVj6+0aSZIkSZIWcFGa/bA0PrPVySEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACxAPcnMZCnN97jcbR4vlUvyHSaxOKI0326ui1FfMh0+XekP9XKsJvSJ6kBYbK4ktUFpbXP4WGXQbt7L3ts7GhYnWcc+7w999Jow1zadeGZbfQdv7J9o6Yx8Pu4Lb278M7LRo8OiNLNnJEmSJEnSf52DpvkVi9IscoIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALRLW68ddKSX6zC93mv0Nq+dNMZOfrSfJnmufi9KcDS0O9HKtJbR1eZa4kzXsrxjaGqyv99vJedk2lL4wkWzr2eZ/6svPCfHjbuy9rq+/ht0aOavpsXB/3hgv6J0Le+P9ebLdIkiRJkqSHKEqzH5bGZ7Y6SQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAWglObnusitTS6TS/LfMZGd7cn92RMaz/E75rkYrRzbEHaW41BXU7q20heelmZmS9K8tnpsfbg27rOX97Kd5UrYMLauY5937eiTw+13/DjMh1u/94OweOLYtvku4mQ67IirBzwTX27MxNv7auH4kbWhnPh9XZIkSZIk7eN5aJr/3SFjxz7VqSIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU98TU4lKS3+UCtza5RC7JrzSVna3xPr3OLBenS3pHQ70cq0mdNXiEuZI0r60dWx8+V+m1k/ehM4aO7Ohn/uGPfzrMp+Of94dt9X1c1Jfs9yx8pDoYzmz8Xj6SbLFPJEmSJEnSgZ2Jpvkdjc+TnCwCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEABRUn+9y5ua6sL5O55cn/2BJPZmQ5NsqEoye4zy8XopJHJUC/HalI74moYSqbMlqR5a+PoMeH6xi6yk/e+C/uS0NPBz/yFr3h9mG/v+eDH2uo72Tq8ap9m4OpKf3jlwPKwYmyjPSJJkiRJklrRpYcmswc7ZQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgIKI0vxoF7W1Xz3j2bGms2Pfqe1muBhV0+lwTaUv1MuxmtSfDRxmtiTNW5tGjw5fKFft431oe2Ug9CVTHfvM03WnhB/+6D/CfPvJnXeFyvLZtvlexmubHvbZ74ir4a19aXj6yNqwOMnsEEmSJEmS1OKy20pJ9nQnjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0OEmJrb+ainNd7qkrQ1L8reb0M7TncycYH6L07mDy0K9HKtJ3dzoiLENZkvSvHTc6FFhR1y1j/ehL8WVsKbD9/ZHP/W50C5OO/P8tvpuPl4Z/B/P/KZyJby/OhK2Dq0K1XTa7pAkSZIkSfNQ9p6eodknOXUEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAOFaXZy1zM1rYXxt3W1bXtIFPaOZ7cnz0hSvNvm91idHhtU7ixXAn1cqwm9c7emtmSNC89fWStnb4fnTq8uqOf+0u3XRDayRUf+5e2+n7OH1j6s2d9VXUonD24PEw0/v3HzpAkSZIkSW3QrVGaTzt9BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACADnPI2LFPjdLshy5la+MmsmUmtXOU0uzPzG1xelffWKiXYzWxbPRosyVpzjt5ZDLstIP3uTf0T3T0cx9f/+zwox//R2gn99x7bxhc/cy2+Y6mRo8JfzJ4eFgzusGukCRJkiRJbVmUZBc/uT97glNIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoEKU0u8hlbG1ekr/apHaGQ5NsKEqy+8xtMdo8ekyol2M1sY9UhkKP2ZI0x500vCbstIP3uSurQyFOpjv62W+/5vrQjl627U3eTUmSJEmSpH0q+0aplq9xGgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG2uNJEtK6XZ/S5ha/tL4m4wrZ0hSvPt5rUY9TT6UHU41Muxmtipw6vNl6Q57aThNWGn/bvPfaFcDSvGNnb0s3/5q/48tKtPfvoG76ckSZIkSdK+n5k+cK79miWTk492KgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1p20FRkn/G5Wud0aHpcUvMbHvrTmZOMKvF6aThNaFejtXEro37QjnJzJekudvlI5NhZ1yxg/exmxs9Y2RNRz/7ZZtPCz+5867Qrnbt3h1G157kPZUkSZIkSdq/dnaPz0w4nQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDbTneSnunCtc4qSmdNNbft6cn/2hCjNv21Wi9HiNAvbKwOhXo7VxM4ZXGG+JM1Zpw6vDjeVK/bvfvTqgWUd/ex7xmfCJz/9hdDuzjz3zd5VSZIkSZKk/S3Jd0VJdv7ExNZfdVIJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABt4EmHb/z1KMm/68K1zilKs380ue2rlGavNafF6QVDK0O9HKuJ7SxXwlhts/mSNCedNrw63NTYO/bvvvfB3pGwJM06+vm/4k/fGjrBP/3zdd5XSZIkSZKkAz9D/Wz3xNSA00oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJhnUZK9wSVrHXYhXJLffcjYuseZ3vbzwEV9jXfqPnNajKrpdLi20hfq5VhN7C/7U/MlaU46bXh1uKlcsXv3o2vjvlCrbeno579iamu48667Qye4775dYWDVCd5bSZIkSZKkAz5HzX5aSrIXd3V1PcLJJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzINDk2woSrL7XLDWeXUn07kJbj9Rml9hPovTOYMrQr0cq8ltGj3GfElqec8dXhVuKlfs3f3oge8tGz26o5//oomZcO11Xw6d5EWveL13V5IkSZIkqXlds2hipuL0EgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5lgpzT/mQrVOLbvQBLfZ+zQ+fZS5LE5DyVS4Pq6GejlWE/tIdTD0mC9JLe7E4cmwM67Yu/vZOYPLO34G/vA1fx06zZXbP+P9lSRJkiRJamZJ/uOolp/iFBMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZIqZZtcZlaJ5fd1tW17SCT3C62HVRKsuvMZXE6b2BpqJdjNbnTh1eaL0kt7Rkja8JO+3a/u6R3NCxOso6egRVTW8Odd90dOs09994b+o98hvdYkiRJkiSpyUVJ/oHuiamnOM8EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBWmp19ZJRmN7pErbPrSaaWGub2ENXyU8xkcRqtbQ474mqol2M1sS+Uq6EvmTZjklrW8cNrw85yxc7dz66N+8JY4/fATp6BRRMz4TNf2Bk61elnvda7LEmSJEmS1JpujcZnppxqAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAi5TGZ7a6OK0IZa8yzfOve2LqsVGaf9s8Fqc/GTw81Muxmtz5A0vNl6SWNTNydLixXLFv97ObGt9dNnp0x8/Bq99wUehkH/roNd5nSZIkSZKk1rWnlORv7lk++xgnnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EQHD80+Pkry77o0rRB9wUTPvyjJXmkWi9NQMhVuKFdDvRyryR1Z22DGJLWkbPTo8KW4YtceQGcNHtHxczB57AvC3ffcGzrZnXfdHeJls95rSZIkSZKkVpbkN3ePz0w45QQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgCYpJfkfuyytMO0pjR7bY6rnz1NHpg9pvFM/MYvF6dzBZaFejtXk3tc7ar4ktaSNo8eEL8ZVu/YAem9jRy9Oso6egyWHHRduuPGroQhOfMEfebclSZIkSZJaXZLvanye2zU7+0gnngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAB6altKpSS/y0VpxSlKs+eb7PlTSrMLzWFxGki2hC+Uq6FejtXkThhZY8YkNb0NY+vCF2N7+0C6ptIXRhq//3X6LJz/5+8KRfHOS6/0fkuSJEmSJM3VWWuSX9uTTledegIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwH4qpdlFLkcr2EVvaX6FyZ4fPRP5aCnJdpvD4nT24PJQL8dqctfGfWFxmpkxSU1t1diGcF3ca88eQDsbbRo9puNn4ajZF4V7770vFMV3b7s99IzPeM8lSZIkSZLmqiT/cVTLT3H6CQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+6hnIh8tpdn9LkYrVlGS/fSQsXWPM+Fzr/E+XWUGi1NfMh2ui3tDvRyryZ07uMyMSWpqh9c2hWsrfXbsAfbyoSM6fhaWHHZc2LHza6FoNp14pnddkiRJkiRpzs9d8w90T0w9xSkoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADspVKSXe4ytIJe8JZmmQmf6/dpZpPZK1a/O7Qi1MuxWtARYxvMmKSmldY2h09VBuzXA+zivlpYlGYdPw+v+6v3hiJ6419f4n2XJEmSJEman26NxmemnIYCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDD6K5NH+kCtOIWpfnbTPkcmp19ZJRmN5q94lRJpsO1cV+ol2M1uUt7R82YpKY1kmwJH60O2q8H2D/H/WEomer4eVj/jJeEXbt2hyK6+Wvf9M5LkiRJkiTNX3uiJHtTz/LZxzgYBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAXyJKs0+4/Ky4RUl2S+MxP8Kkz43Gd/48c1eszhg6MtTLsVrQs4cnzZikptSXTIXLq0N26wG2s9GGsXUdPw9Llh4XvnTzv4YiWzG11bsvSZIkSZI0nyXZTdFYljodBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA/yZK82mXnhW/RWl2mGlvvYOHZh8fJfl3zVxxWpxk4ROVgVAvx2py18fVUEmmzZmkAy5u7JK/6x21W5vQS4aOKMRMXHDhpaHoXvnaC73/kiRJkiRJ81yU5vc0Ps/q6tp2kJNSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB40LaDoiTf4cKzhVD2KvPeeqUk/2OzVqyOH14b6uVYLejPBg4zY5IOuKelWXhP75i92oTe0ZeEngLMxKYTzwy7du8ORXfN53bYAZIkSZIkSW1SlORXLlm6+VCnpQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALHilND/JJWcL5iK3HSa+tXpqW0qlJL/LvBWrS3pHQ70cqwUdNbbejEk6oBalWXhrX2qnNqGrK/1hsDbV8TNRXvb0UP/av4eFYNeu3WFg1Ql2gSRJkiRJUtuUfS9K82mnpgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALFhDQ7OPKqX5v7ncbOG0+LDjYpPfOqUkf4c5K1ZH1jaEm8txqKvpXVkdMmOSDrjzBpbaqU1oZ7kS1o+tK8RM/MVFHwgLyWlnnm8XSJIkSZIktVd7Skn+5iWTk492egoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwIITpdnzXWq2sGo885eZ/Ba9T2MzfaUk32XOitXr+w8L9XKsFvTCoZVmTNIBdc7gCvvUTv65pk/+vbD7/vvDQvKev/+ofSBJkiRJktSOJdlNUS1PnKICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBgVKsbf62UZN9yodnCKkryT5n+1mi8T5eYsWI1WJsKO+JqqJdjNbkby5UwkGwxZ5L2u61Dq+zTJnVRXxJ6CjAT8bLZ8JWvfyssNLd+7wehZ3zGXpAkSZIkSWrPs9m7G59ndXVtO8hpKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhVdKshe7yGwhlt3/1JHpQ7wBzdUzkY8+8N2ar2L18qEjQr0cqwVd2JeYMUn73ezI2rDTLm1Kn6oMhIFkSyHm4m3vviwsVOuOP8NukCRJkiRJau8+unji2G6nqgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFNaSyclHR2n+bZeXLcyiNHuOt6C5Skl2udkqVosbXV3pD/VyrBZ0/MhacyZpv9o0enT4UlyxS5vQjeVKWDu2vhBzkZ9yVth9//1hoTrvTRfbD5IkSZIkSW1f9r1ofGbKySoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIUUJfmZLi1bwCX5Zd6C5ulJppY2vtc9ZqtYPXNkTaiXY7Wgz8d94WlpZs4k7XOrxjaE6+Neu7RJ/c7wykLMRXXFb4V/+/fvhIXsM9d/2Y6QJEmSJEnqjPZESfbW7ompxzplBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgMA4emn18Kc1uc2HZwi1Ksp8eMrbucd6G5oiS/J/MVfG6tHc01MuxWtBr+peaMUn73Fhtc7i60m+PNqm39qWFmY13vO+KsNDt2r07DK5+pl0hSZIkSZLUOee1X1pUmx520goAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQCGUkumzXVSmUjp9nLfhwPWk2WqzVLwOr20KN5fjUFdLWje6zpxJ2qf6kunw4eqwHdqktlcGGt/pVCFmY3brH4Q9e/YEQnje773GvpAkSZIkSeqgoiS/u5RkZzhxBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgoz25P3tCKclud0mZoiS72Btx4Brv06fNU/F65cDyUC/HakHbKwOhx4xJ2ocWp1n4294xO7RJfSmuhDVjGwoxG/1HPiN86zu3Bf7TJZf9k50hSZIkSZLUmV26pJb/hpNXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6UinJft+lZHqgKM1+0DU5+Sveiv0Xpfm0WSpei9IsXF3pD/VyrBZ0zuAKcyZpr+tpdEH/hP3ZxLYOryrMfLzr/R8J/Jfbvn9H6BmfsTskSZIkSZI6suwbUTqzwgksAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdpXti6rGlNLvNhWT6WePTR3kz9tsjGu/TDeaoeOUjR4V6OVaLWlbbaM4k7XXnDC63O5vYW/rGCzMbxz/vD8OePXsCP++o2RfZHZIkSZIkSZ1aku9qfJ7bNTv7SEexAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0hCjNXuYyMv3/RWl+gTdjf9+n/HgzVMze0p+GejlWC3p/dcSMSdrrThtebXc2se2VgdCXTBdiNgZWnhC+/d3vBf6nba+90P6QJEmSJEnq/DPc7YvSLHIiCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAW1syOfnoKMm/4xIy/fyFbNn/bozHI7wh+2h29pGlJLvJDBWv/mQqfCmuhHo5Vgt6/tAqcyZpr8pHjwo7y/Zxs3rg97bJsfWFmY/3XfbxwC/28as/b4dIkiRJkiQVoST/fjQ+M+VgFgAAAADD6hgGAAAgAElEQVQAAAAAAAAAAAAAAAAAAAAAAAAAAACAttWdTr/Q5WP6RXVPTI17Q/ZNlGbPNjvF7PThlaFejtWCdjYaTraYM0kP25FjG8N1ca/d2cSeP7SqMPNxwunbwp49ewK/2F0/vTuUlz3dLpEkSZIkSSpGe6I0v6Ba3fhrTmgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGgrExNbf7WUZN906Zh+SX/kLdm39ylKsq+bm2J2WXU41MuxWtC7+sbMmKSHbSiZCtsrA/ZmE3tbX1qY+Rhc/cxwy623Bx7acaeeY59IkiRJkiQVqSS/vpRs6XVSCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA2yjVsue6bEy/rCjJd3hL9l53Ov1Cc1PMjqhtDPVyrBZ16vBqcybpISsnWfj73hE7s4ltrwyEvmSqMDPygQ9/IvDw3vC2S+wUSZIkSZKkopXkP2l8nuS0FgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA+Tc5+StRkn3dRWN6qBYfdlzsZXl43RNTj228T7eYmWL2qoFloV6O1YK+XK6E/mTKnEn6pfU0ekvfuJ3ZxHY2du8xo+sKMyPPeel5gb1z3Y66vSJJkiRJklTQojR/58FDs493cgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwLzpqWUnulxMD3/5WvYyb8vDi5L85ealmPU0urrSH+rlWC3ob/oScybpIfuDwWX2ZZN7wdDKwszHyJpnhe/dfkdg7+zavTsMrDrBbpEkSZIkSSps2VeisSx1egsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwLwopdkNLhXTXnSNt+WhLZmcfHSUZLeYlWJ2zOi6UC/HalGnDK82Z5J+ac8aXhNutiub2t/0JaGnQDNy2VX/HNg3z3npefaLJEmSJElSgYvS/J5Skp3hFBcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDlVqmVbXCimvSu7f1GaRd6ah3ifkuzF5qS4/dHA4aFejtWCbixXQl8yZc4k/cI2jh7z4J6wL5vX1ZX+MJBsKcyMnPqy8wL77h3vu8KOkSRJkiRJWgBFSf73i0e3PNFpLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyJKs0+6SEz7cOHa73hrfrGhodlHlZLsW+akuG2vDIR6OVYLurAvMWOSfmGH1TaFz8a9dmUT21muhGNG1xVmRmpHnxxuv+PHgX33r9/4tj0jSZIkSZK0YM55s3/tHp+ZcKoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBLlSayZS4Q0z6VZB/35vyS96mWPdeMFLfJsfWhXo7Vok4aXmPOJP2Pqul0uLI6ZE82uZcMHVmoObniY/8S2H/j659t30iSJEmSJC2QoiS7r/F5VldX1yOc7gIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0BKlJL/M5WHap5Js96HJ7MHenv9mdvaRUZp/1YwUtz8YXBbq5VgtaEdcDdV02pxJ+rl6Gv1V/7g92eTe2Vt78Lstypy84JzXBQ7M6We91s6RJEmSJElaeP3D4tEtT3TICwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAU3VPTA2U0ux+F4ZpX4vS7DneoJ9XSqefZTaK3VXVoVAvx2pBF/YlZkzS/+gVg8vtyCb3z3F/GEqmCjMj6bpTwg9/9B+BA/POS6+0cyRJkiRJkhZiSf7vUTqzwkkvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABNU0qzi1wWpv0pSvMrvEE/5xFRmt1oNorbkWMbQ70cq0WdPDJpziT9XMcPrw03249NbWejDWPrCjUnV26/NnDgvvL1b9k7kiRJkiRJC7Uk39X4POuB805HvgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHJBFaRZFaXavi8K0P0Vpfs+TDt/4696k/1RKp48zF8Xu9wdXhHo5VgvaWa6E/mTKnEn6WavH1ocvxlU7ssmdOXhEoebkjD98Y6A59uzZE8aOOsn+kSRJkiRJWtj9w+LRLU908gsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwH6L0vxPXQymA6knyZ/pTfq/71OSf95MFLsPV4dDvRyrBb27t2bGJP2swdpU+ER1wH5scu/qGwuL0qwwczK+/tnhRz/+j0DznHbm+XaQJEmSJEnSQi/JvtVdmz7S6S8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPuse2LqsaUku93FYDqQoiR7v7epq6uU5JvNQ7E7rLYp1MuxWtTpwyvNmaQHW5xm4dLeMbuxyV1T6QvDyZZCzcr2a64PNNfb33O5PSRJkiRJkqRQSvJdjc9zu7q2HeQkGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvRYlM6e7EExN6M7uianHLvT3qfE9XGMWit3zh1aFejlWC7qpXAljtc3mTNKDnT+w1G5swZ6dGj2mUHPy8j96c6D5dn7lG/aQJEmSJEmS/qsku7xnaPZJ/nQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7YdtBpTSvuwhMzahnPDt2Ib9NpVq+xhwUvwv7klAvx2pBH6iOmDFJD3byyKS92IJ+b3BFoebk8E2nhZ/ceVeg+e6/f08YmjzRPpIkSZIk7Wv1B0uyb0Vpfkcpze73nUgFKsm+2VObOdyfsQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4CGVatkWF4CpWUVp/u4F/T6l+cfMQbFbnGThurg31MuxWtBLh44wZ5LC6rH1YUdctReb3Pt6Rx/8fawoc9IzPhOu/swXA63z7Jf8iZ0kSZIkSdq3c6Ik+1GU5m+Mxmb6/t/ZyZLJyUf3DM0+afFhx8U9E/loaSJb1vjvHVNKp49r9KzS+MzW7jT/vcb//txGr2n8Z2+N0uxvS2n2wQfOXRr/f59r9OXGX3+j8XlH4/N+37U0n+fB2b3d6fQL/UkLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+qSjJ/8nlX2paSf6TBy5HXIjv0gOXQJqB4rd+bF2ol2O1qGW1jeZMWuD1J1PhE9UBO7HJXRv3hdHa5kLNyh+c/7ZAa/3lOz9oL0mSJEmS9rc9jT5WSrLZrsnJX2n2mUzP8tnHLB7d8sRFaRYtqk0Pd0/MrIzSfPqBf16jkxud0fjnn9v4exdESXZx49eXNv7e5Y3PaxrtbPy9Wxr/2R2ek3QgZR9cUst/w5+4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg55TS6TGXfanpJTObFuT79J+XMXr+Be/sweWhXo7Vgq6sDpkxaYG3KM3CxX01O7HJ3VSuhGz06ELNyhHTzwt3/fTuQGt98ctftZskSZIkSQdclGRfj5L85T1Ds09qt7OdoaHZR3VPTD1l8WHHxY3P8Z5kZjIan5nqSfJnRsnM6aVk+uxSkv2vxs/w1sbnJaU0uypKs882Pr/S+NlujdL8Hs9YC7x6z0Q+6k9eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwM6U0u8hFX2p+2YUL7l1Kjq01fvY9nn3x+0B1JNTLsVrQKwaXmzFpgffKgeX2YQs6u2D7ddHETPjsDTcFWm/X7t2h94jj7SdJkiRJUlOKkuynD5whRbU8KdIZUc/y2ccsWbr50O6JqYHS+PTynnR6Y5Tmxzd+5uc1Oqvxc59fSvK/bPTeKMmvLCXZpxvd1Pj7t/znd2I21OEl+V2N9/oUf/oCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICuQ5PZg6Mkv9tFX2rBxWnf75qc/JWF9D41fu5LPfvi15dMh53lSqiXY7Wgo8bWmzNpAfdbI0eFm+3Cpndp71hYnGSFmpVXv+GiwNx5+nNfYUdJkiRJkppelOSf6k6m866ubQct9DPboaHZRx0yduxTo7GZvp5kamnje1lXSrLZ0vjM1qiW/W6UZn9SSrO/KCX5exufVzW+u89HSfb1xt//oVlSm50Rv71n+exj/EkMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAFrJRMn+1yL7WsWrZ2obxL0WjWX0qz+z334nf8yNpQL8dqQdfGfWFRmpkzaYG2vLYxXB9X7cMW7NbR2uZCzcra33xhuOfeewNz57w3XWxPSZIkSZJaVpTmX43S7PndE1OPdXq7P7Yd1PjunhKNzfSVxqeXl5J8cymdflYpyV4cJdm2xvd7QePzXY3v+MNRkl9bSrOvNP4732/857vNn1rzTmdfLCVber2bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL0ezsI0tp9g0Xe6llJfmfL5TXKUqyt3rmC6PXDhwW6uVYLeiN/RNmTFqglZMsXFEdtgub3M2Nnj6ytlCzsuSw48IXv/zVwNy66pOftaskSZIkSS0vSrIfRWl+QU9tS8lB7tzoWT77mEVpFi2qTQ93T8ysbHz/06UkO7nRGY1ncu4Dz6PxXC5u/PXlja5r/PqWxt+7x7xqL86Jf9KYleO9ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0x3LZ9xoZdae/lh/p2urm0HFf1dOjSZPThKsp965gujT1QHQr0cqwU9Y2SNGZMWaBf0T9iDLejcwWWFm5XXvuVvA3Pv+z/4kV0lSZIkSZq786U0v6eUZhcuqk0PO9FtT4eMrXtcdFi+qJQcWyvVsrWN5/abjc/nNj7Pajy71za6qJRkl0dJfm2jr5WS/Cdme8G+z28cGpp9lLcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCBKCXZx13kpVbXPZ6vKvq7FCXZNs96YZTWNod6OVYL2lmuhL5k2pxJC7DThlfbgy3osupwWJJmhZqV9c94Sbjvvl2B+XHE9PPsLEmSJEnSfHRNlObTXV1dj3C62/kWj2554qLa9HD3xMzKB55rKclObjzjsxq/viBKsosbf315o+sav76l0X3mvxhFSf75Q8amy94AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICC656YGiil+R6XeKn1l6Rlbyryu7RkcvLRjZ/zVs96YXTS8JpQL8dqQe/pHTNj0gJs5diGsCOu2oNN7rq4NxxW21SoWSkve3q4+WvfDMyfF73i9faWJEmSJGn+zpvS7IuNz5MmJrb+qpPehaNnaPZJ0WjW312bPrI7mc67k/zUUpKfEyX566Mku7gxFx+O0vxzpST7ZmM+7vSutHFJdnspmdlkqgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqyU5G92eZfm5JLDJP9u1+zsI4v6LvUk+Wme88LpvIGloV6O1YLOGDrSjEkLrGo6HT5aHbQDW9BJw2sKNy9//o73B+bX31zyj3aXJEmSJGn+S7JvNjqje2LqsU58+e+WTE4+elGaRYtq08PdEzMrozSfLo3PbG3MzrmNX18QJdnFjV9/rNHOxq9vKSX5Lu/VnLan8b2fX+SzYwAAAAAAAAAAAAAAAAAAgP/D3r1A2V3Vhx6fUHu1176uXg35n0niOWfer/P/zyQEQsJAQshz/v8JMkVrAVHEKio+qkgrN6hV0SottYIUil4qVlGqhWpBKiCiqIWigZBja0uhYq1PRHxAHvueUOoNkMc8zpk5j89nre9K7FpFsv97/5quPWttAAAAAAAAAAAAAICW9czu9NdycfYjj3ZptmpP0qOa9DjNi5LsLt+4dfpkx0Ao5wuqQctK6+wxqcV6X9ew+VeD3tm9tOn2ytjJbwg7d+0KzK2t279hdkmSJEmS6qj0P3Px2NmFkYnfcPvL9G05ZP7Q5mcfGqd9e+4zc8nY8dFwekZlj51b2WMXVvpE5fe3REn2T5Xf/9i5q05RnP1dtHT8mfYfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEATieLs5R7r0qwWZ+9txrPUnoyt831bp+ckabgzXwzlfEFV7oZijz0mtVhn9K0w/2rQtcW+UIjHmmqvFA+fCN+455uBubdj587QufxEM0ySJEmSVFdFcfpAlGRvnz+0+dlugan53eDhE78yv5Q9Jzc8dnhl3421x9lpUZK+qfL7C3Jx+pHK72+q/Hp3pe85nwcrvWfB8PiIXQUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0CSiOPuaR7o0yw8afqutbcshzXaWKn+2z/i+rdPaoTWhnC+oBr2t9zB7TGqhVg0dF+7KF82/KndHviMcMbSu6fbLpVdcHagfJ7zkD8wxSZIkSVK93kX9NBdn7z00OX6x22DqwcjI6b/cXtqYi4bSJBePr4/isVOiUvr6KM7Oj5LsQ1GS3ljZu9sqv/6wdc9t9rP2ODvNbgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaHC5kXSZh/U0F7XH46PNdJbaR7LByp9rt2/bOr2678hQzhdUg7KBVfaY1CJ1JGPh74u9Zl8NOrV/tOn2y+ZT3xh27dodqB9v/9PLzTJJkiRJUp2X7qr8euWhcdrnZphG0dGx7qkLkzRaMDw+EiXZWC5OT67s47Mqv79gz36udEsUp/9S6ZFmPLeVP9flC0Y2/U87AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgQeWS9FKP6WlOirM/a66zlH3Qd22tLulKQjlfUJXbWiiGQjxmj0kt0vu6hs2+GnRhd9J0e6X7yOeFe7/57UB9ue6mL5tlkiRJkqQGKd0Vxdlft8eblrohppnMH9r87PaRbLB9OFubi9OTFyTZG6I4/ePKnv9wZc9/Lhdn2ys92IB3ybfPHxrL+8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3mWX0Tv9qQD2ipKYri7D/aJiZ+qRnO0sIkjaIkfdh3ba1uKXaFcr6gKvehzpL9JbVIL+lfae7VoBuKPaEzHmu6/XLFVdcF6s93vvcD80ySJEmS1IjdEiXZmNtiWsni0dGn7bnTXDA8PpKL04lKZ0Zxel6lyytn4vpK23Jx9qO6OquVf58FpWzc1wMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaCC5JHupR/M0l7XH46PNcJaiJH2b79laJaUNoZwvqAa9pm+5PSa1QEcOrQtfK3SYe1XuznwxHD20tun2ywvOeHPYvXt3oD4la15orkmSJEmSGrIozr4UJWna1tY2z80x/Jf2volntA9tHmgfztZGpeyFlTPyplyc/Vmlv6n8/suVc3N/5fc7Zu+sprsqv57b1rblEF8HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAB5OL0Ng/maW5L39fo52jByKb/WTlL3/MtW6sX9I+Gcr6gGrRyaK09JjV5+TgNn+roN/Nq0Mv7VzTdfukbfUH4j//8XqB+nfyqt5ptkiRJkqTGLs5uj5I0bWtrm+cGGSZjyyGLRjYvWJikS6IkG4vi8ZdVztKbK2fpsijO/q7yP7sritMHqnlOK2f00+19E8+w9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdSwXby55JE910LfbJiZ+qZHPUjScnuE7tl5v7jkslPMFVblbi12h3f6Smr4/6lli5tWgD3bFTTlDr/rUjYH69u6LPmy2SZIkSZKaoihOt+bidKKtrW2e22SYucWjo09btOT4woKR8RV7zlblnJ0VJdkFlV+vrPzn2ypn7ltTOqdxel97afwwKwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUKdycXaRx/FUF5Wyoxv3JG05pPJnKPuOrdflXaVQzhdU5f60e9j+kpq85w0cbd7VoJuL3aEn3th0++VFr3l7oP5de+OXzDdJkiRJUlMVxenWXJxOtLW1zXOrDLW1eHT0aYuWHF9YMDK+Ys+5q5zBs6Iku6Dy65WV/3xb5Tx+63HnM8l+nhseP93KAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADUmflDa56ei7MfeRRP9VF6YaOepQXxWOb7tWY3F7tDOV9QlTul/yj7S2riktKGcFuh07yrctvyxbBmcE3T7ZehVSeF737/gUD9u//b3zXjJEmSJEnNWZzdHiVp2tbWNs8NM8ydZ3anv3ZonPa1D2drK2fyRVGcbonibLmVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoI1Epe6GH8FQ/pd9pGx19SiOepVycft73a7264rGwPV8IZVW1PWs6WNpgj0lN2sIkDR/pHDTvatDrepc35Z752+u/EGgc8bGnmHWSJEmSpKYtitOtuTidaGtrm+emGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYB+iJL3RA3iqq0rpMY12jhYm6RLfrjVbM7gmlPMFVbm/7ei3v6Qm7nW9y826GvShrlKo/J2k6fbLK/7g/EBjecEZbzbrJEmSJElNXxSnW3NxOtHW1jbPjTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBj5pey5+SSdJeH71RXxdlFjXaWoiS9wrdrzV7SvzKU8wVVubf0LLO/pCbt6KG14a580ayrcrcWusJAaWPT7Zfh404NP3zgx4HGct6f/aV5J0mSJElqpXut26MkTdva2ua5fQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFpeFKdbPHan+iv9Ttvo6FMa5RwtXrrh0ChJH/bdWrO39R4WyvmCqtzmgVX2l9SE5eM0XFvsM+eq3N35YkgHVzflnvns528LNJ5Pf/aLZp4kSZIkqeWK4nRrLk4n2tra5rmFBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWtW8KE6/4ZE71WXDY6sa5SBVztEW36x1u6JzKJTzBVWxbZW64jH7S2rC3tW91JyrQW/qXdaU++X1b31foDHdd/9/mnmSJEmSpJYtitOtuTid2HMX6zoaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoKe1JepSH7VTHDw5e3AjnaGTk9F+O4ux+36x1+2KxO5TzBVWxT3QO2FtSEzY+sDpsN+Oq3pWdg2FRE+6XZRtOCw8+9JNA4xo4+nfMPkmSJElSaxdnty+Ix7K2trZ5bqYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICWkIuzv/Cgneq1KMl+0Nc38T/q/RxV/j1P9L1at+54UyjnC6pyW3qW2V9Sk9Ufbwy3FrvMuCp3W6EzDJfWN91+aR8eDzd98Y5AY3v+y7aYf5IkSZIk7bnzitOtuTidcDsNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0tflDa56ei7MHPWSnun5kcHh8U72fpSjOPudbtW7rB48N5XxBVS4bXGV/SU3WZV2x+Vbltlc6YeCYptwvb3rnnwca3x/+yQfNP0mSJEmS9r73irPPLRgZX+GmGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaEq5OD3Z43Wq+8cFk/SKej5H7UObB3yn1u53+1aGcr6gKrYtXwzFeMz+kpqo0/qPMt9q0Nt6D2vK/XLEptPDQz/5WaDxfeyaG8xASZIkSZL23fULk3SJG2sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCp7HmszYN1qv/SH88fWvP0ej1HUZL9uW/U2p3buyyU8wVVsY93DNhbUhMVxxvCbYVO863KXd3RH56TpE23XxaNbA7/8NXtgeawdfs3zEFJkiRJkvbf7ihOP35onPa5uQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABreopHNC3JxutNjdWqEoiR9Xj2eo8Wl7Dcr/34P+Uat3YXdSSjnC6pi5/Qebm9JTVJ7pQ91lcy2KndHviMcXlrXlHvm7X96eaB5/Pzhh0Pl//c0DyVJkiRJOmDprsqvV7YnYx1usQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgIaVi9MzPVCnhinO/qYez1GUpK/1ffTXnQOhnC+oio0Nrra3pCbpFX0rzLUadPLAaFPul1UTrwwPP/xIoLmsHH+ZeShJkiRJ0iSK4vSRXJJe2F7amHObDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANJwoSb/scTo1zCOCSfpwtHT8mXV2jOblkvTrvo9uKXaFcr6gKnVXvhgK8Zi9JTVBS0vrwx35DrOtyp3fvaQp98viJceHr971T4Hmc9rrzjMTJUmSJEma6r1YnF58aDzxLLfaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQ1g4Ml7MJdluj9JVr754k3Woce1xdlo9naMoyVb7LlqcpOHufDGU8wVVqY93DNhbUhO0sDIfP9Y5aK5VuWs7ekMhHmvKPfOe9/9VoDm9+6IPm4uSJEmSJE2nOHuw8uu57YdP/IobbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoK5FcXaOh+iq24v7jwqLktRa1LDKvv1sPZ2jyr/Tlb6LlgytD+V8QVXs3N5l9pbUBP1e33IzrcptLRTDUUPHNeV+Wfv814QdO3YGmtPVn7nFXJQkSZIkaSZ3ZEn2zdzw+Olto6NPcdMNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADUpSjJ7vIAXXV7X9dwGIg3Woualu5qL23M1cMZevbA2PwoTh/xTbRh8NhQzhdUxU4YOMbekhq85aV14c580Uyrcqf3r2zK/ZJfdkLY/s//FmheX/+X+8xGSZIkSZKqUzkXpxNtbW3z3HgDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IyplsQfnqt8txa6wfGittah56Wvq4Rzl4uz3fQvt6dT+0VDOF1SltlfqLW2yt6QGbmGShqs6Bsy0KndxV9K0e+bCD5Rf7+oAACAASURBVP51oLnt2Lkz5JedYEZKkiRJklSloiT7Sm54bJWbbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoC7k4vSdHpurbkcOrQvlfCFsGDzWeszCI4Fzf4q2HFL5d/lX30N7emPvEY+ef1Wn64q99pXU4L2270jzrMrdUOwJXfGmptwv6SlvCDt37Qo0v2N/60wzUpIkSZKk6nf9gpFNw27AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAuTQvF2f3emCuup3RtyKU84Vw0sCo9ZiF2pOxjrk8RJX//nW+g/6787uXPHr+VZ3e3bPEvpIauGWldeFrhQ7zrIptyxfDsYNrmnK/dBzxW+Ff770/0BrO+P33mJOSJEmSJNWkdFeUpFfMHxrLuwoHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmXRRnyz0sV/0u7YpDOV8Ir+070nrMQpV9fM5cnqPKv8MnfQf9d1d0Dj16/lWdXth/lH0lNWgLkzRc2TlollW5V/U2798vL/vI3wZax59e+jGzUpIkSZKkmt6fpY9UuvjQeOJZbsUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBZk4uz93hUrrotitNwW6EzlPOF8Lbew6zJbBRn2+fqDC0a2bxgz6OEvoP+u2s7eh89/6pOS0rr7SupQTujb4U5VuX+b2cptDfpfvmt088Ju3fvDrSO6276slkpSZIkSdIsFCXZDyq/nrV4dPRpbscBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBam5dL0ns8Jlfdjhk6LpTzhUd7f/ewNZmtBwFLWTwXhyiK0/9j/bV3txa6fjEDNLO+UOy2p6QGbbi0PvxjvsMsq2K3FLtCX7ypKfdLz4rnh3//1ncCreWe+75lXkqSJEmSNKul97TH2W/vuSN2TQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANREe7xpqcfjqt+r+44M5Xzh0T7eMWBNZqs4fefsn6Ith1T+e//N+mvv7soXfzEDNLMu6k7sKakBa6/0oa6SOVbF7q7835ZNg8c27Z75yN/8faD17Ni5Myxeery5KUmSJEnS7N+p3ZYrpce4LQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKouitPzPBxX/S7tikM5X3i0G4s91mT2HgC8r61tyyGzeYbah7O11l57V4zHfnH+NfNe0bfCvpIasBf3H2WGVbk39h7RtPvlhWf+YaB1rcheZm5KkiRJkjR3XZ9LxobcmgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFUTJdk/eSyuurVX+lKhK5TzhUe7M1989H9mbWanBcPZytk8Q7k4/ah1194lpQ2/OP+aeauH1thXUoPVF28KXy50mmFV7MrOobAoTptyvwwec1L4zvd+EGhdJ73yLWanJEmSJElzWZztiOL0/YuXbjjU7TkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAjUSmLPRRX/Y4srQ3lfOFx9cWbrM3sPfx30aydoaXjz4yS7OfWXXs3OnTck2aApted+WJ4TpLaV1KDdWHXsBlWxb5U6ApDpQ1Nu1+u/swtgdZ2zrsuMTslSZIkSaqPHori9LxnHLbu192kAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA05JL0rd4HK76vax/RSjnC49r5dBaazNLRUn2g46OdU+dpTP0GmuuJ7Zx8NgnzQBNr090DthTUoOVDawyv6rY9konDBzTtPvljLPfHeADH/2U+SlJkiRJUj3dtcXZ/VGSntrWtuUQN+oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCU5OL0bg/DVb8Lu5NQzhce13MHjrE2s1mcnjAbZyiKs69Zbz2x5w0c/aQZoOn1jp6l9pTUQBXisXBjR4/5VaVuLXSFE5r475DDx50afvjAjwPc9MV/NEMlSZIkSarL+7bs9vZ4fNStOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCmHxmmfx+Bq0xeK3aGcLzyuM/pWWJvZfeTvb2p9hnLDY4dba+2r0/tXPmkGaHqdNDBqT0kN1Ft6lpldVeqSriT0xZuadq+0D4+HG265PcAe937z22aoJEmSJEl1XBRnVy0cGS+6YQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4oF2e/7xG46re0tD6U84Un9daew6zPbBZnO549MDa/lmcoStJLrLX21et6l+9zDmjqLRlab09JDdLKobVhW75ods2w2wsd4fS+lU2/X876wwsD/Ledu3aF5xz2XLNUkiRJkqQ6LorTR6Iku2BxKftNN+0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA+RXF2qwfgqt9p/UeFcr7wpC7tjq3PLNeeZK+s1fmZP7Tm6bk4e9A6a19t6Vm2zzmgqfWVYueec2xPSQ3QojgNV3f0m10z7KqOgbC0tL7p98sRm04PP37opwH2dtTml5unkiRJkiQ1QFGSfj8Xp2e2jY4+xY07AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwC/OHNj87l6S7PPxW/S7oHgnlfOFJXdPRZ31m+1G/OPuHWp2hKElfZI21v97Ts2Sfc0BT64OdJftJapBe1XukuTWDthaK4dV9y8PCJG36vbJwZDx86fa7AjzRKa96q3kqSZIkSVIj3cMl6Z0LSuPHuXkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAetSDOXuyxt9p0Y0dPKOcLT+r2Qqf1mYPahzYP1OIM5eL0Zuur/XVRd7LPOaCpdXbvEfaT1AANlDY++vccc2t6XVvsC6NDx7XMfnnL+ZcF2Jctf3SpmSpJkiRJUmN2fa3u4wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAaSS7JPeuCt+pVKG0M5X9hv3fEm6zTLRUn29mqfn/lDY/nKP3u39dX++ouu0gFngSbX+MBq+0lqgC7qTsysaXR3vhjO7V0WFidpy+yVo48/I/zs5w8H2JcPfvTTZqokSZIkSY1anO2I4vTi+UObn+0mHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWtDi0dGn5ZLsIQ+8Vb+TBkZDOV/Yb0cPrbVOs/6IX3pfW9uWQ6p5hir/3HOtrQ7UhzpLB5wFmlz98Ub7Sarz0sHV5tU0urXQFcYHVrfUXlm85PjwtW3/HGB/PnfrHeaqJEmSJEkNXpRkP2hPsle2jY4+xa08AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0kFycbfCoW236o54loZwv7LcT+4+xTnPR8NiqKh6heZV/5r9aVx2oKzsHDzgLdPBuLnbbS1KdtzhJw2c6es2sKXZpVxx6S5tabr+85/1/FeBA7v3mt81WSZIkSZKapChJ76zy/RwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFDPojh9v8fcatN1xd5Qzhf226v7jrROc1L6gWqdn/Z4fNR66mB9smPggLNAB+/S7thekuq8s3qXm1dTaGuhGF7ZtyK0t+BeWfv814QdO3YGOJA9e2TRyGbzVZIkSZKkZipOr5k/NJZ3Qw8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM1tXpSk/+4Rt+rXHW8Kd+eLoZwv7LfzepZaq7npoWf1TfxqNQ5QLs4us546WJ/u6DvgLNDBO6t3ub0k1XFJaUP4aqHDvJpk1xV7w8qhtS25V/LLTgjlf743wGSMrH2RGStJkiRJUpMVJenDUZJd8Mzu9Ndc1QMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBNaMDw+4vG22jQ+sDqU84UD9sGu2FrNWWO/M9PzM39ozdNzcfagtdTBur7Ye9B5oAN3/OAqe0mq4z5Q+TuNWXXwtld6T8+SUIjHWnavXPR/PxFgstJT3mDGSpIkSZLUrMXpfVGSnejGHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmkwUZ+d4tK02nd17eCjnCwfsumKvtZqjoji9dqbnp/LPOclaajJ9tthz0HmgAzdQ2mgvSXXaxMAx5tQk+lKhKzy3slatvFfGT31j2LlrV4DJ+t03vMuclSRJkiSp6e/sss/l4s0lN/cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAkckl2i8faatOHOkuhnC8csK8WOqzVnJXuyg1ubp/R+YnTv7eOmkw3FHsOOg+0/z5f6LaPpDotH6fhxg4z7mBd0TkUBuKNLb1XOpefGO6571sBpuKtf/wBs1aSJEmSpBa5t4vi9PL5Q5uf7QYfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa2OJS9pu5ONvhkbbq117ptkJnKOcLB60/3mjN5qiolL5+uucnWpIt3PPAn3XUZLqx2DOpeaB9d1lXbB9JddpZvcvNqQO0rVAMZ/ceHhYmacvvlb/8+LUBpuovPnyNWStJkiRJUivd3SXp96Ph9Iy20dGnuM0HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAGlEuy53qcrTYtH1obyvnCpFozuMaazd3DfHfO4PycZQ012W4q9kx6JujJnd17hH0k1WFxvCF8tdBhTu2nzxe6w/rBY+2VSi84481h9+7dAabq72641RmSJEmSJKkV7/DidGuulB7jRh8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABpMlKSXeJStNr2kf2Uo5wuT6tT+UWs2l4/yDaXJtM7Pnsf8rJ8m2c3F7knPBD25EwaOsY+kOuzC7sSM2k9XdA6FgXijfVKp96jfDvd/+7sBpuNrd3/DOZIkSZIkqZWL02sWjGxa5GYfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaRC5O7/MYW206v3tJKOcLk+pNvcus2RwWJdmfTPnsJGND1k5T6eZi96Rngp5cUtpgH0l11tqhNWG7+fSktlU6u/fwsDBJ7ZPH+sSnPxdgur77/QecI0mSJEmSWr04ezCKs9eNjJz+y274AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgji0sjfV7hK12XVfsDeV8YVK9v3vYms3pQ3zp9zo61j11Kuen8r/zTmunqXRTsWfSM0GP77ZCZ2i3h6S6amGShqs7+s2oJ3RzsTscN7TGHtmrF7/27QFmYvfu3aF4+ITzJEmSJEmSKqVfXxCPrXHTDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdSqKs9d5eK02dcVj4e58MZTzhUn1qY5+6zbHRUl24uRPz5ZDcnF6n3XTVPpssWfSM0GP78rOIXtIqrNe2rfSfHpCl3QloTveZH/s1dCqk8J3v/9AgJlakb3MmZIkSZIkSf+/OL0mWpItdOMPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1Jpdkn/HoWm3aOHhsKOcLk+6rhY7Qbt3mus9M+uyUsqOtl6badR19U5oL+v+d17PUHpLqqO54U/hyodN8eqxtlV7Xu9zf5fbRpz/7xQDVcOJLz3GmJEmSJEnSE3uo0rl9fRP/w80/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADUgfbDJ34litOfemytNr2278hQzhemVKm00drNbbsXLTm+MJnzEyXpJdZLU+3THX1Tngv6r17Sv9Iekuqot/csNZse6/OF7nDc0Br7Yh+97tz3BqiW12y5wLmSJEmSJEn7qxzF6bF+AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZY+3C21gNrteui7iSU84UptXHwWGs39735YGeno2PdU6Mk/aG10lS7prNvynNB/9XqoTX2kFQnLS2tD3fli2ZTpY90DoaB0kb7Yh8dtv608OCPfxKgWt590YedLUmSJEmSdKB2R3F6+eKlGw71kwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBHojg9z+NqteuGYk8o5wtT6qV9K63dXBdn97a1bTnkQGcnl4wdb600nT7ROTDluaBCuDtfDMV4zB6S6qS/6Cq1/FzaXunc3mVhUZzaE/uofXg83PKVrwWopiuuus75kiRJkiRJBy2K0wdycfqqttHRp/iJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmGVRkn3Fw2q1qTveFLbnC6E8xd7ac5j1q4Pah7O1Bzw7cXaVddJ0+mjn4JTnggrh74u99o9UJ60fXN3yM+krxc4wPrDafjhA57zrkgDVdu2NX3K+JEmSJEnSpIuS9KsLRsZX+KkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYJYWRid/IxelOD6rVpnRwdSjnC1Pu8q6S9auPrtzf2XnGYet+PYqzn1kjTacPdpamNRtavYu7EvtHqoMWJmm4uqO/pefRnj//ktJ6++EArRx/Wfjpz34eoNr+4avbnTFJkiRJkjTVdufi7LIFI5v+t58QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAGouSbMwjarXr9/qWh3K+MOVuKvZYvzooStKHD40nnrWvs5OL05Otkabb+7uHpzUbWr2ze4+wf6Q66IX9R7X0LDqvZ2lYnKT2wgFavOT48I93fj1ALdxz37ecM0mSJEmSNM27v+wHuTg9s61tyyF+UgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGokirPzPaBWuy7tikM5X5hy2yt1JGPWsC5KX7PPs5Okn7I2mm4XdI9Maza0eicOHGP/SHNcIR4LNxe7W3IGbS0Uw2n9R9kHk+idf/ahQHX85Kc/C9+455sWYi8P/vgnzpkkSZIkSZpZcfr5haWxfj8tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANZBL0js8nFa7bi52h3K+MK2OHlxrDeugKMnueuK5WTS48X9FSfqw9dF0O69n6bRnQyt3xNA6+0ea497Ye0RLzp89f6dbNXScPTCJ1px4ZnjkkR2B6viDd1wcLrniagvxBIVlE86bJEmSJEma2R1gnD4SJdkFz+qb+FU/NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFXS3jfxjFyS7vJoWm3qjzeGcr4w7U7pP8o61ksj6bLHnZ04O826aCad27tsRvOhFbsrXwyL7B1pThuo/N3m9kJHy82fj3YOPvpntwcOXn7ZCeHuf7onUB23fOVroX14PJx5zp9YjCdYsu5FzpwkSZIkSapKUZz+Sy4eX++nBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoApyydjxHkqrXeMDq0M5X5h2W3qWWcd6eUwvyf788Wcnu966aCa9ofeIGc2HVuzaYp+9I81x7+5Z0lJzZ3ulc3uXhUVx6vtPsvd94KpAdTz40E/Csg2nPbquqydeZUGeYN3zX+vMSZIkSZKk6han10RLsoV+igAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGYgF2fv9UBa7Xp93xGhnC9Mu0u7Y+tYN6U/fmZ3+mt7zs2h8cSzKmdnhzXRTHp5/4oZzYdW7KLuxN6R5rBlpXVhW77YMjPnjnxHeP7A0b79FEpPeUPYuWtXoDp+783v/cXaLl5yfPjZzx+2KHv57Zef69xJkiRJkqSqF8XpA7k4PbNtYuKX/DQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMQ5Rkd3kcrXa9v3s4lPOFaXd9sdc61tMjekl66n+dm/R3rYdm2kkDozOaD63Y2b1H2DvSHHZxV9Iy8+YzHb1h+dBa330KdRzxW+Ff770/UB033HJ7aB8ef9wab93+DQuzl1e96Y+dPUmSJEmSVMN7wewrC0Y2DfuJAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmIL2voln5JJst0fRatf1xd5Qzhem3bZKz0lSa1k/3bLn7ERJepO10EwbH1g9o/nQij1v4Gh7R5qjVg0dF7a3yKz5y66h0B1v8t2n2Ac++qlAdfzowYfCknUvetIa//WnbrI4e3nL+Zc5e5IkSZIkqcalu6I4vfgZh637dT9dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkxAl2ZiH0GpXIR4L2wrFUM4XZtTy0jrrWU8Nj63KxelOa6GZduzgmhnPh1Zr+dBae0eaoz7cOdQSc+YdPUvDojj1zafYiS89J+zevTtQHa/4g/P3uc7vet8VFmcv7/vAVc6fJEmSJEmalaI4/VYuTk/2EwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAQUZK9wyNotWv10JpQzhdm3O/0H2096+nRvCT7pnVQNVpWWleVGdEqbcsXw6IktXekOWh8YHXTz5ithWI4tX/U955GPSufH+7/9ncD1XHdTV/e71q/5PfOs0B7+atPXu8MSpIkSZKk2S1Or46WZAv9pAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOxHLk4/7/Gz2nV6/8pQzhdm3Dm9h1tPqQnrizdVZUa0StcVe+0baQ5amKThms6+pp4vtxS7wqqh43zvafaxa24IVMf3f/ijEB97yn7X+pjnvsIi7eX6m//BGZQkSZIkSbNfnP2k8utZbRMTv+QnDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYC8dHeueGsXZzzx8VrvO61kayvnCjLusK7aeUhPWXmlbvliVOdEKXWoWSnPSyQOjTT1bruoYCAOljb71NDv11W8LVM/pr3/nAdd78dLjw44dOy3UY/7xzq87h5IkSZIkae6K0y8uLI31+8kDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4TJSMH+Gxs9r2sc7BUM4XZtyNxR7rKTVpXyh2V2VOtEJbepbZM9IstzhJw40dPU07V97TveTRP6NvPb2GVp0UvvO9Hwaq4xN/d/Ok1v3f/v0/LNZj7v3mt51FSZIkSZI0p0VJ+nDl1zd3dKx7qp9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACg5UWl9PUeOqtd7ZVuL3SGcr4w47ZX6orHrKvUhF3T2VeVOdEKvbj/KHtGmuV+t29lU86TbYViOKNvhW88w/72+i8EquM/v/uDMHD070xq3T936x0W7DHf/+GPnEVJkiRJklQXRXH2z7lSeoyfQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoKXlkuyTHjirXUtK60M5X6haawbXWFepCbu8q1TVWdHMrR0yB6XZLB+n4eZid9PNkjvyHeGEgWN84xn2qjf9caB6Xvzad0x67f/y49dasMc88sgO51GSJEmSJNVT/4+9ew+Ts64P/g/a1tanvz4++vRXmQ2JO6fdmd2duSfZkDPJJkvIaWfDYUU5WPEQRVRQFAzYEn8q4AEqoLSpWCM2HvCAQq2gLXgOKIgcQqhni1VLLSKoiEA+z7175bHWH+AmmdmdnXm9rut95br8A+H+3vc99z18mc/uTFK/bFZ57Kl2IwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0IkO7KrV7zbYrHkd0zcUd3ZnG9am8jLHVWrD3tYzr6H3inaunGxwzkhT2MvKS9vuPvKFXDFWDBxuffezuatPjJ/ce3/QGB/4+D/t1fF/44XvcdB+wzMOOcp1KUmSJEmSWqpMUv9B+udRtiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBRMgP1HgPNmtvm0sK4szvbsM7rne+4Sm3Y2b0LGnqvaNduzBacL9IUlk1G4ou5nra6j/xDvi+SZJ313c9mzd0Yn/nSzUFj/PDffxzl5cft1Rq86PQ3O3C/YWDoBNemJEmSJElqyTK10Q/Nmb/u6XYnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQETLV0ecaZNbcLi0mcWd3tmFdXqg4rlIbdnJ5aUPvFe3aFYV+54s0hZ1WWtxW95Dx57JsMmJtG9CZ5/5N0Bi7d++O405+3V6vwdpjX+ng/YZFGza5NiVJkiRJUsuWqY3eMysZfcEBBxxwoF0KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0ta5k9K8NMWtun8qX4s7ubMO6MVtwXKU27Jn9Kxt6r2jXLuqZ63yRpqh8bSR2ZIttc/84t3d+HFyrW9sGtHjkRfGznz8QNMZ7Lv/kPq1D34rjHLzfMPzMU1yfkiRJkiSp9Uvqnzto3oZeOxUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhbmdrolw0va16za/XY2Z2LO7uzDa1aXe/4Sm3WisrhDb9XtGOnlxY5X6Qp6jXp9dYO942daSf1LbWmDWrO4JFx0613Bo3xve//KIpLjtnn9fjpfT9zEPc44sTXuEYlSZIaXE+yYaIkWReDlbWxuHJ4DFVWT1QfWPXfOqZvKI7tX/HrTuxbHpvKy37dyeWlcVpp8T71ivLi//bXGm/8r/+b/3/jHTWw8r/9Pa2qHDbx97qksmbi779WXffrf6ZZ1leSNI1lktEHupKRzfPmbfp9OxYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGgr+fyaJ2Vqo780uKx5jQ/rvLM72/COHFjp+EptVjnZ0JT7Rbt1XN9y54s0RYPTb8wWZvw9Y/yfYcPAsDVtYG+5ZHvQGI88sjuOesGZ+7Ue//Ktf3Ug9zju5Ne5RiVJUseVTUZioLouFlXWxMrK6qgPrIpn9q+ME/pWxKbysjilvCReXV4UW0oL4rze+fFXPfNia7EWlxWr8cHCQFyZ74tP5UtxXb43vpArTrxD3ZTNd9R3TV9L/3nH/7l3ZIsTx+Hq9HiMH5f3FSrxnkJ14nhd0DMYb+qZP3EczygtjleUF08c3z/vOzSe3b9iOY1kMQAAIABJREFU4riPH/+F1TXRX10/sS7OT0nSZMok9VsPrtUH7VwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKBtzKpuPMSwsuY2PlCzGYM+Ty8tcnylNuyWDhtavC+NDyh2rkjN76zSwhl/v7g21zsxWN56Nq7Dn/2K+NWvHgoa453br9zvNfn8Dbc4kHu86PQ3u04lSdKM6+BaPfqS9RPvLodXDoux/qF4ft+hcWp5SZyZvped0zs/LuyZF5f2JPH+wkBcme+beNe5IVuInd053xW1cOPr8+VcIa7L906s2wfS9bu0mMRFPXPjvHRdX1taEKek63xi3/I4Kl331en6L6yumTgfZid114ckdVLJ6EOZpH5ePr/mSXYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw42WS0ZcYVNbcNpcWNWUg5zuLNcdXasM+nSsZOvw7KicbnCtSkyum19mN2cKMvld8tNAf/cl669nAuhccHbu+8d2gMb75ne9HbuHYfq/LRz5xnYO5x6ted7FrVZIkTXuFZCQWVNfE4ZXD4pi+oTipb2mcUVocbywdEhf1zI1thWpckb6v/HOuN76SLfquR4/Z+Hv5tel58rF8f7y3WIl3FOfGeb3zJ/6dw4vLy+KY/qGJ82z8fBs/71x/kjTzy9RGb59V3XiIXQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMxoXbX6uw0oa26X9NSaMlDzunyv4yu1YdsLFUODH6ebu/POE2kKOrO0aEbfK/6mZ25kDRRveFvf+7GgMR55ZHccceJrGrIu79j2UQd0j7PfcqlrVZIkNaVi+n6xpLIm1g6sihP6VsRLy0vjtaUF8Vc98+LdxSSuKPTH53I9cUs27/sbTVu3ZnMT5+HH8v2xLT0v35aen2f3LoiXl5bEc/qXT5y/C6trIud9WZJau2T0oUxt9MKD5m14st0MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMSJna6O2GkzW3T+T7mjIgc1daT7LBMZbarLf2DhoC/Dh9Ml92nkhTMCz+K9nijLxHjD8fbSktiFnWseEdceJr4uFHHgka4+1/9+GGrc3Zb7nUAd3jLZdsd71KkqS9ak6tHpXquhiqrI6j+4diU3lZbC4tjPN7B2NbMYkr831xY7bgOxm1Xbdmc3Fdvjc+nO+PrcVanNs7P04rLY4T+5ZHfWBVLK6uiUIy4j4hSdNYJql/c1aycbkdDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzCh/Wh77466k/rChZM3r4Fo9bsnmmzb4ct3AsOMstVmvLC8x2PdxencxcZ5ITe7V5UUz8v5wW3cuTuhfbg2bUHHJMfHdu34YNMbXv31XZBeMNWx9TjrjLQ7qHpds+6hrVpIk/bpZaQPVdTE8cFgc17c8XlFeHOf1zp/4buGqfDl25Iqxy3ct0uO2I1uMK/N9cWl63ZyTXj+nlpfEsf0rJq6r8etrlnuNJDW73ZmkvnX83+vb3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwIwwq1Y/1CCy5ja/urapAy3HB1g6zlJ7dUzfkIG9j9O5vfOdJ1ITyyUjcX22OOPuDTd352N0YKU1bFIf+Pg/BY3x0MMPx7rjX9XQ9Tny+Wc6sHtc9qFPumYlSeqg5tTqcUh1bdQHVsUL+g6NzaWFcVHP3Hh/YSCuzfXGbd0536VITe729Dq7Lt8bH0yvu/Hr77WlBfHCvmWxYWA4BtPrc7Z7lSQ1qm93zR1ZaYcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtL5OMnmYAWXM7un+oqQMr394z13GW2qyllcMN5H2cTikvcZ5ITey00uIZd1/YkSvGivTeaf2a04mnvjFonPP/5v2Nf3YYPcmB3eOKf/ys61aSpDarJ9kQQ5XVcWz/ion3lfN7B2N7oRLX5Xtjp+9JpJZv/Dr9Uq4nrsz3xdZiLbaUFsSm8rKoD6yKwcramOU+J0l70+5MUt/6tJ76/2OnAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALaurVn+f4WPNbXzQazMHUl6TKznOUpuVTUZil4G7j9kx/UPOE6mJ958d2eKMuidcm+uN+dW11q9JVVaeEHf/+CdBY9y261sxZ/6RDV+n4pJjHNw9PnntDteuJEkzrNm1egxW1sbIwKrY1Lcszu5dEFuLtbgy3xc3Zgu+C5HavJuy+fhEer1fWkxiS2lBvDC9D6wdGI7+ZL17pCQ9ZvXvZJL6sN0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0pK6kfoehY83twp55TR04uTObi2wy4lhLbdYXcz2G6j5Gh1ZWO0ekJnVqefGMuh98PN8XfYZsN7V/+PQXg8Z48MFfxaqxlzdtrX754IMOcupTn/2ya1eSpBasJ9kQQ+n7/LH9K+K00uI4v3cwthcqcV2+N3b6rkPSY3Rbdy6uzpdia7EWW0oLYlN5WdQHVkV/1XcBkpS2O5PUL5tVHnuqXQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALSMWQvH/qgrGX3IwLHm9rF8f9MHSw4PHOZYS23WBwoDBuc+RsVkg3NEakLPqNXjS7meGXMveE+hGrlkxNo1sVecfWHQOOdcdFlT1+vuH9/jIKeu/cJNrl9JkqahnvRdfUXl8DimfyhOLS+O83rnTzyzX5Mvx63ZnO8zJDW8G7KF+HC+Py7oGZy47xzRvzIGq2tjlnuypA4rk9R/cFAyMmr3AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALeHgWn3QoLHmd1O20PThkSf1LXWspTZrfPi04bj//25M76nOD6k5vai8bMbcCy7umReza3Xr1sQOWfuCuO/+nweNcdOtd8bseUc0dc2+8Z27HOjU567/mmtYkqQmdHD6/F2rrov1A8OxqW9ZbCktiL8t1uKqQnniXd13FpJapVuy+Yl70zuKc+PV5UVxTP9QLKqs8T2CpA6o/u7svLH/aRcEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADT6qBk9PmGizW3vmT9lAyJPL9n0PGW2qyTy0sNwX2UxgfiOj+kxjc7qcc/53pnxH3g3N75McuaNbWD522ML3751qAxfvnggzF01Eubvm433Xqng50aP3ddx5Ik7eN7Qa0e86trY2P/qonvJd5YOiTeXUzimnw5buvO+V5C0oxuZ3ofuzpfir8t1mJzaWE8q39FHJLe88a/E/EZIKldyiT1H3RV6+vthAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYNpkkvpFhos1t8MGDpuSYZD/kO9zvKU2a/3AsGG3j9I7izXnh9SEju9b0fLX/660V5QXW68paMtb3xU0ztlvuXRK1u26L97kYKeu/+pO17EkSY/TnFo9Bitroz6wKjaVl8WW0oLYmr5rX50vxU7fO0jqwG7vzk3cAy/umRenlRbH0f1DE/dJnxmSZnC7M0l965+Wx/7YjggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKZcJhn9rKFize25fYdOydDH8YG3uWTEMZfaqP7qekNtH6XX9y5wfkhN6Mp8X8sPuD6hb4W1moJWHHlyPPDLB4PG+PLNd8TseUdMydp97OrPOeCpm26907UsSer4ZtfqsbC6Jo7uH4pTy4vj/N7B+EBhID6f7YldvluQpEm1I1uM7YVKvKH3kHhB36ExVFkdc9L7q88ZSTOob89KNi63KwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKl0YKY2eo9hYs1tc2nhlA14PLxymGMutVlfzhUMsP2tTi4vdW5IDW60f2VLX/c3d+djdGCltZqC5gweGV+7/etBY/z8Fw/EkvqLp2z9LvvQJx301C07v+F6liR1TD3JhlgzMBybystiS2lBbC3W4sp8X9yazfkOQZKa0M60q/OluLhnXpxWWhxH9w9FqbrBZ5KkVm53JqlvPWjehifbHgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQNM9vXbkHEPEmt87inOnbJjjKeUljrnUZl1eGDCs9rc6amClc0NqcB9o4XvNjlwxVlQOt05T1AVbPxA0zmve+NdTun5v/7sPO+ip2+/8tutZktRW9SQbYqiyOo7tXxGnlRbHxT3z4sp8X9zcnfc9gSS1SF/K9cS2YhKbSwvj6P6hGKiu8xkmqdXaeXCtPmiXBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATZWp1euGhzW/Kwr9Uza08ZLiXMdcarPO651vKO1vtaSyxrkhNbBVlcNa9nr/51xvDFbXWqcpau2xr4yHHno4aIzP33BLzJq7cUrX8I0XvseBT935je+5piVJM67ZST3mp8++R/cPxWmlxfFXPfMmvlf8cq7guwBJmqF9MdcT7y4msbm0KI7oXxnlZIPPPEnTWzL6UCapn1cuj/2B3RIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADRFJhn9C8PDmt8N2akbfHttrtcxl9qsTX3LDKD9rXLJiHNDamCX9iQtea1fnS9FpbrOGk1R2QVj8S/f/F7QGPfd//M4ZO0Lpnwdz3jDJQ5+6hvfuct1LUlq2ebU6rG4uiaO7V8Rp5UWx8U98+LKfF/cks1755ekDuhLuZ7YVkxic2lhHN0/FL3Jep+Pkqa8TFK/NVMdTeyYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACg4bpqo5cbGtbcepINUzqMcVdaqbrBsZfaqKHKasNmf6Md2aLzQmpgC6pr4o7uXMtd6x/P9xkqPcW9631XBY1z2paLp2UdTzrjLQ5+6rt3/dB1LUma9srJhlg7MBybysviDb2HxHuLlfhMrnfi+zvv95Kk/9v49zJX50txUc/cOLm8NIYHDotn1Oo+SyU1vUxt9JcH1UZPP2Bs7Il2TgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0DCZ2ujtBoY1t6HK6ikfwLixf5VjL7VR4wNUd3bnDJjd01WFsvNCamBv7R1suev88sJAFJMR6zOFHfOiv4jdu3cHjfHpz31l2tbyxFPfaAFSd/3gbte2JGnKqlbXR31gVZxSXhLn9wzGh9Ln2S/nCt7hJUn73O3dubii0B9vLB0Sx/Utj1p1nc9cSU0rk4zuyAzUe+yeAAAAAABgOkTE76X977RC2vy04bT1aWNpz03blHZ62plp56W9NW3ro/T+tMslSXvdQp9GAJN+dl34G/fP9zzKM+lf73lmHf+Pe85IO3XP8+yxe55vD0tbkZakPSPtfzqqAAAAAAAAAAAAAADsLfvbAQAAAAAAmBmWL/+9TG30lwaFNbcT+lZM+bDF15QWOfZSm3V1rmyY7J62FRPnhNSgepP18bVsvqWu8Q8UBiJfG7E+U3keLHt2fP+HdweN8dP7fhaDa543bet5/EtfZxFSP/z3H7u+JUkNryfZEGsGhmNTeVmc2zs/thcqsSNb9K4uSZqSvpTrmfhudHNpYdQHVkU28f2JpMaVSeq/SP8844ADzn6CjRQAAAAAAOyPiHhaWjltedqz0l6e9vq0d6Vdmfa5tNvS7kq7345HgGk35tMLYNLPumNNuA/vTrsn7VtpN6X9U9qH0i5O+8s9P1peT1uU1p32ZCsBAAAAAAAAAAAAANDZ7G8HAAAAAABgRshUNhYNCGt+p5cWTflgxXcXE8dearPe3jPX4Ng9nd8z6JyQGtTmaXhOebzGB0N3J3VrM8V95BPX+RnwBjp581undT2PedFfWITU3T/+ietbkrTP9SfrY8PAcJxcXhpv7R2MywsD8ZVs0Tu5JKmlur07Fx8t9Mcbeg+J4/qWR7W63ue4pP0vqX/+4Hkbc3ZTAAAAAADwaCLif6fV0kbSXpr2prTtaZ9P+17ar+xgBJhxxnzCAUz6eXisRe7d96ftTLsm7dK0s9Oemzac1pP2R1YLAAAAAAAAAAAAAKB92d8OAAAAAADAjJCp1esGgzW/t/XMm/JBijuyRcdearNOLS8xKHZPZ5UWOiekBvSMWj125Iotc21f0lOL2enfk7WZ2l74qvP8BHgDXX3d9dO+pkc+b7OFSP3k3vtd45Kk31mpuiHWDwzHS/qWxpt75sflhUp8OVfw7i1JmrFdl+uNi3rmxqa+ZbG4crjPe0n7VCap35tJRv7cjgoAAAAAgM4UEf8rbd6eH1TcknZ52o1p99mdCNCWxnz6AUz6WXlsBt3f79nzHD/+PD/+H5BtSlua9hQrCQAAAAAAAAAAAAAws9nfDgAAAAAAwIzQVRs9w1Cw5nd5YWBaBifOra51/KU2au3AsKGwe3pReZlzQmpAL+xb1jLX9cU982K2NZnyqqueE//xn/f6CfAG+c+f/DSS4T+f9nXdcMKrLcb4zsh773OdS5J+3exaPRZX18Sx/Stic2lhbCsmcV2+N3Z5x5YktXk3ZfOxvVCJ00qLY83AcMxJPxM9G0iabJlk9COZ+RufZmcFAAAAAED7iYjfTyvv+dHEs/f8EOGtaQ/YgQjQccZ8MgJM+jl6rE3u/f+R9sW0v007Ne2wtC4rDAAAAAAAAAAAAAAwM9jfDgAAAAAAwIzQVau/2zCw5velXM+0DEocHxLs+EvtUzYZiZ2GwE401j/knJD2s1lp1+RKLXFNv6lnfhxsoPO09OnPfcXPfzfQple/qSXWdc2zX2kxxnc//ue9rnNJ6tBq1XVx5MDKeFV5cVxSnBtX58rp+3TO+7QkSWk3d+dje6ESZ5YWxYaB4YnvnT0/SPod/airWl9vdwUAAAAAwMwVEXPSNqadnXZ52u1pv7LTEIA9xnxaAkz62XqszT8TfvIbP0Z+StrytD+x8gAAAAAAAAAAAAAArcX+dgAAAAAAAGaETDK6wxCw5tad1GPXNA1GfH3vAmsgtVn/mC8b/Jo2VFntfJD2syP6V7bE9byl5Hllunr169/hp78b6KOf+EzLrO3KsZdZkNS//8c9rnVJavPm1OqxuLomTuxbPvFcua2YxI5s0XuzJEl70c60K/N9E5+l9YFVkU1GPGdIerR2Z5L61oPmbXiyXRYAAAAAAK0tIjJpI2lb0q4a305nRyEAv8OYT1CAST9vj3XoZ8UP9rxfbNnzvvF0ZwMAAAAAAAAAAAAAwPSxv93+dgAAAAAAgBkhUxu9xwCw5nZIde20DUK8otBvDaQ264KeQYNe0yrVdc4HaT97X6Ey7dfymaVF1mKaWrRhU9z/s1/46e8G+dHd/xl9K45rmfVdtvEkizK+m/FHP3a9S1IbNbe6Np7Zv3LiGfLSniSuzfXGLu/HkiQ1vFuzubi8UJn4zF07MBzPqNU9i0j6r5L6HZlKvWanBQAAAABAaxj/ob+0jWnnpX0m7T67BwHYB2M+VQEm/Qw+5mPj1+5K+0jaq9KWpj3ZGQIAAAAAAAAAAAAAMDXsb7e/HQAAAAAAoOXNnnfEQQZ/Nb8NA8PTNvhwZ3cussmIdZDaqE3lZR0/1PWO9N4227kg7VdLK4dP63W8K+3k8lJrMU0dPG9j7LjxdtvaGuiEl/1/LbXGC9e/0KKM71z8wd2ueUmagY2/7y2urolj+1fE5tLC2FZMYke22PHvwpIkTVe3ZPPx4Xx/bCktiPrAqnhGre6ZRerwMkn9V+mfWw4YG3uiXRcAAAAAAFMnIp6Utijt1LT3p33XTkEAGmTMJy3ApJ/L/ej4Y3so7ca0t4//51ZpBWcMAAAAAAAAAAAAAEBz2N9ufzsAAAAAAEDL66rWhwz9an4n9i2f1mGHawaGrYPURh1aWd3xQ1x35IrOBWk/O793cNqu4Tu6c/HCvmXWYRp749u22cLWQO+74tMtt8bzDn+ehUl97/s/cs1LUotXSEYmvrs6ubw0LugZjCvzfXFb+rzY6e+9kiS1cl/L5uO9xUqcWl4cyyqHxyzPNFIHV//i7MEjs3ZeAAAAAAA0R0T8ftq8tDPSPp32CzsDAWiSMZ+8AJN+Tvej43vnR2lX7XmvGX+/eYKzCAAAAAAAAAAAAABg/9nfbn87AAAAAABAy8skG08y6Kv5nVFaPK3DDU9L//+tg9Q+zU4bH1rayUNbr8qXnQvSftSTbJi2+8iutJP6llqHaWzV2MvjwQd/Zbtag/zw338cpUOPbbl1rqw8weKkvvOvP3DdS1KLPYeuGRiOl5WXxsU98+LqfCnu6M519PutJEnt0PXZYmwt1mJTeVnUqus890gdVqZW/8msZPRYuy8AAAAAAPZfRDw57bC016d9Pu2XdgICMEXGfBIDTPq53Y+O75+70z6c9vK0StqBzioAAAAAAAAAAAAAgL1nf7v97QAAAAAAAC2vKxk936Cv5nd+7+C0DjP8u2JiHaQ2632FSkcPad3mvibtV68oL56Wa3dX2kv6llqDaewZhxwVt9/5bVvTGmT37t1x7Eu2tORa9y57tgVKffM733ftS9I0Vauui2P6h+K1pQVxWbEaO7LFjn6PlSSpk7omX45ze+fHUemzQL424tlI6pjq75tTHX2KXRgAAAAAAHsnIvrSzkj7dNoDdv4BME3GfCoDTPoZ3o+ON/5HyC9P25Q22xkGAAAAAAAAAAAAADA59rfb3w4AAAAAANDyumqjHzPcq/mNDw6ezuGFN2QLMcs6SG3V5tLCjh7Ken7PoPNA2scOrtXjunzvlF+3u9Je0rfUGkxzF7/rQ7ahNdC7P/iJll3r3qXPtkCpO77+Hde+JE1Bteq6OKZ/KF5bWjDxPdiObLGj31klSdJ/tbM7F5cXBmJzaVEMDxw28d2U5yepjUvq/9pVrQ/ZiQEAAAAA8Ngi4s/2/Ejh1rR/s9MPgBYx5lMaYNLP9H50vLm+ted9afw4/4kzDgAAAAAAAAAAAADg0dnfbn87AAAAAABAy8sk9VsN92p+V+fK0z60cGF1jbWQ2qj6wKqOHsS6ubTQeSDtY2P9Q1N+ze5Ke0nfUsd/uj87/vz0ePiRR2w7a5Dvff9HUVxyTMuud+nQYy1S6ubbvu76l6QGV6mui6PTZ8rx97JtxSR25Iod/X4qSZL2ri/nCrG1WItN5WUTzxWer6S2bHemNnphPr/mSXZkAAAAAABM/CDhE9LmpW1JuzFtt919ALSgMZ/aAJN+xvej41PnobQvpJ2RVnT2AQAAAAAAAAAAAAD8F/vb7W8HAAAAAABoeV21+v2GejW/m7KFaR9S+IK+Q62F1EblkpHY2Z3r2MGrLyovcx5I+9j2QmVKr9ddaSeXlzr201xh8THx7e/9m21mDfLII7vjqBec2dJr3r/ieAuVuv6rO90DJGk/qlTXxdH9Q7G5tDC2FZPYkSt27HuoJElqTlfnS7GltCDqA6tidq3uGUxqozK10du7kiOqdmUAAAAAAJ0oIp6cNpK2Ne0HdvMBMAOM+QQHmPTzvh8dnz7fSrswbTjt95yNAAAAAAAAAAAAAEAns7/d/nYAAAAAAICW9v/2j/yZYV7Nr5CMtMRQwgt6Bq2H1GZ9PN/XsYNWx/qHnAPSPrSguiZ2TeG1Ov7/dXJ5qWPfAl32oU/aUtZAf3PZx1p+zSsrT7BQqc/uuNk9QJImWTEZiTUDw/Gy9Plta7EWO3LFjn3nlCRJ09NXssWJ55BN5WVRra73jCa1QZlk9IH0zzMOOODsJ9ihAQAAAAC0u4h4etqL065J+6UdfADMMGM+zQEm/ezvR8dbw7+nvSttfdqTnJkAAAAAAAAAAAAAQKexv93+dgAAAAAAgJaWqW1cZJBX81tSWdMSgwg/lS9ZD6nNekPvIR07XHWosto5IO1Db+qZP2XX6a60k8tLHfcW6LiTXxe7d++2jaxBvvGduyK3cKzl1z0Zfq7FSn36c19xH5CkR6k7qcdhA4fFS9PntXcU58Y/5UoTz293SpIktUjjzyZXFcpxVmlhrKysjlme4aQZXv2aOfPXPd0uDQAAAACg3UTErLRNaVelPWTXHgAz2JhPdoBJvwf40fHW8/M972XPSftjZykAAAAAAAAAAAAA0Ansb7e/HQAAAAAAoKV11UaON7yr+Y32r2yZ4YPlZIM1kdqoY/qHOnagarW63jkg7WWFZCS+2p2fsueOl/QtddxboNKhx8YPfvRj28Ya5KGHH44NJ7x6Rqz9vMOfZ8HGdwt+6gvuBZKUNlhZGyf2LY9ze+fHh/P9cWs217Hvk5IkaWZ2fbYYF/fMi2P7V0x8z+UZT5qJ1e/OzN24wU4NAAAAAGCmi4jutFel7UjbbaceAG1izKc8wKTfCfzoeGv7Wdrlacf4AXIAAAAAAAAAAAAAoJ3Z325/OwAAAAAAQEvLJPW/NLir+b2wb1nLDBw8qn/ImkhtVE+yIXZ24CD0XWmza3XngLSXvbi8bMqu0ZPLSx3zFunj13zeNrEGuvhdH5oxa3/I2hdYsNRHPnGde4GkjqtSXRdH9w/F5tLC2FZM4ivZYse9N0qSpPbu1mwuthcq8bLy0qilzz6eAaUZ1e5MbfTCfH7Nk+zYAAAAAABmkoh4atqmtC+k7bY7D4A2NOYTH2DS7wd+dHzmeCDtqj1r9gfOXgAAAAAAAAAAAACgndjfbn87AAAAAABAS+uq1d9taFfzO7O0sGWGDJ7du8CaSG3Wlfm+jhuYemO2YO2lfeiqQrnp1+eutJPLSx3vFuklr3mrbWEN9C/f+tfILhibMeu/bONJFi31vis+7X4gqa3rTupxeOWwOLW8OC4tJvGlXE/HvSNKkqTObvz7qPHvvTaXFsZQZXXM8owozYyS0ZsylY1FuzYAAAAAgFYWEX+054fpxn+g7ld25AHQ5sZ8+gNM+l3Bj47PTPekXZY2nHagMxkAAAAAAAAAAAAAmOnsb7e/HQAAAAAAoKV1JfXPGdjV/N7WM69lBgsqw0toAAAgAElEQVR+qDBgTaQ2a0tpQccNSb0212vtpb1seOCwKbk+TykvcbxbpLmrT4yf3Hu/rWAN8tDDD8faY185s677Z55i4VKXbr/SPUFSW1Wrrovj+1bEOb3z44pCf9zeneu4d0JJkqTH64u5nnhzz/yoD6yK2bW6Z0iphcsk9V90JfVT7NwAAAAAAFpJRDwxbV3a+9J+bhceAB1kzJMAwKTfG/zo+Mz33bRz0krOaAAAAAAAAAAAAABgprK/3f52AAAAAACAlpapjX7fsK7mt71QaZlBguODlrPJiHWR2qiN/as6bijqx/L91l7ayy7smdf0a/PM0iLHukWaNXdjXPuFm2z9aqC3XLJ9xp0HG054tYVLve2dH3RfkDRjm502VFkdLysvjYvT57nrcr0d9/4nSZK0P92YLcTWYi1O7FseBf9+TGrZMkn9w7MH1v8vOzgAAAAAgOkUEcW0LXt+eA4AOtGYJwKASb8/+NHx9nJj2ilpT3V2AwAAAAAAAAAAAAAzif3t9rcDAAAAAAC0rHx+zZO6avVHDOlqfp/Ml1tqgODIwCrrIrVR2WQkbuvOddQg1MuKVWsv7UU9yYa4JZtv6nV5bu98x7qF2nzOX9vq1UC37fpWzJl/5Iw7D45+4VkWL/XGt21zX5A0Yxqorouj+4dic2lhbC9U4tZsZ73rSZIkNbPxZ6ttxSQ2lZdFf7Le86fUen27a+7IQjs5AAAAAICpFBF/tOfHAj+dttuOOwA63JinA4BJv0v40fH29EDa5WnDaQc60wEAAAAAAAAAAACAVmd/u/3tAAAAAAAALevgeRtzBnNNTTuyxZYaGnhWaaF1kdqsywsDHTX89O09c627tBe9vLSkqdfkRek1OctxbpkWbdgUP/v5A7Z4NciDD/4qVo29fEaeC8ed/DoLmNp8zl+7N0hqyWYn9Ti0sjpOLi+NS3pq8blcT0e910mSJE1nO9PeV6hMPIslyTrPp1KrlIw+lP655YCxsSfa0QEAAAAANFNELEh7V9r9dtkBwK+NeUoAmPQ7hR8db3/fTDsr7enOeAAAAAAAAAAAAACgVdnfbn87AAAAAABAy5qVbFxuMFfzO7hWnxjM10qDAi8vDFgbqc06s7Soowaents737pLe9E1uVLTrsdLi0nMTuqOc6s8e87bGNd/dactXQ30hrdtm7Hnw/Nfea4FTL3srAvcHyS1RNlkJNYODMfp6fvbZcVq3JTNd9R7nCRJUqu2K+2KQn+cWl4cc6trPbtKLVCmNnrtrOr6Lrs6AAAAAIBGiog/THtO2lftrAOARzXmiQFg0u8XfnS8czycdlXacNqBzn4AAAAAAAAAAAAAoJXY325/OwAAAAAAQMuaVa0fZyBX8+tL1rfccMDbu3MTg5ytj9Q+DQ8c1lFDTl9TWmTdpUm2bmC4adfi3xeq8Yxa3XFuod709r+3jauBbrzlzpg974gZez689KwLLGLqea84x/1B0rRUSEaiPrAqNpcWxvZCJW7N5jrqvU2SJGmmdnW+NPEMN7+61nOtNJ0lo/+RqY2O2NkBAAAAAOyviCimnZf2n3bUAcDjGvPkADDp9ww/Ot6Z/iXtjLSnuQoAAAAAAAAAAAAAgFZgf7v97a4CAAAAOtac5cv/sKs2Ukk78qDayEu7aqOv60pGz88k9a17uihTGz0n/d/POCgZff5B1Y2rn17bWDpo3oYnO3oAAFMjU62/2jCu5re4uqYlBwJuGBi2PlIbdXCtHtdnix0z1PQlfUutuzTJLinObcp1+IHCQGSTEce4hVr9rFPjV796yNatBvnFA7+MZRtPmtHnxFnnbrWQqWdu+gv3CElTUqW6Lo7tXxHn9s6PK/N9cUd3rmPe0SRJktq1q/Ol2FxaGPOraz3zStPT7vG9puP7Ue3wAAAAAAD2RkT83p4fAbzOLjoAmLQxTxEAk37n8KPjne3nae9MS1wNAAAAAAAAAAAAAMB0sr/d/nb72wEAAOgkB2aS0cVpF3Qlozd1JfWH92kIQjL6UKZWvy7967zqoHkbeh1WAIDmydRGLzSEq/mtHxhuySGAZ5YWWh+pzbqkOLdjBpke37fCmkuTqJhsiFuy+YZfgx/L90chGXGMW6jsgrG48xvfs12rgf7ize+c8efFm97+9xYyte74V7lPSGp4s9IWV9fEyeWlE+9in8/2dMz7mCRJUie2K+2KQn+cWl4cc6trPRNLU1ymVv/a02sbS3Z5AAAAAAC/S0T8Sdopad+1ew4A9tqYpwmASb97+NFx/q8v7DkfnujKAAAAAAAAAAAAAACmmv3t2N8OAABA25szf93Tu2qjr8sk9W82ZRhC+tfN1Ebflv45XC6P/YEjDgDQOJlk9CMGcDW/4/tWtOTwv8sLFesjtVkn9i3vmAGm9YFV1lyaRCeXlzb8+vtkvhy9yXrHt8Xa+t6P2Z7VQDfcfEccPG/jjD8vLtn2UYuZWjp6kvuEpP1uVtqS6uETz1d/W6zF9dlix7x/SZIk6b+3K+2KQn+cUl4Sleo6z8vSVJWM/nxWMvoCOz0AAAAAgEcTEbm0C9N+ZtccAOyzMU8VAJN+B/Gj4/y2b6WdkfYUVwgAAAAAAAAAAAAAMFXsb8f+dgAAANrWn5bH/jiT1M/uqtXvn6qhCJna6D3pn9u6qvX1+fyaJ1kFAID9k0lGrzd8q/mND1tuxYF/t3XnIpuMWCOpjepL1scd6bXdCUNLV1QOt+bSJLqqUG7otXdtrjcGDApuucY2vTYeeWS3bVkN8vNfPBCLR17UFufG33/kGgua6l9xvHuFpH1qsLI2NpWXxdZiLW7IFjriXUuSJEl71/h38h/O98fLykujP1nvOVqami6fUx31H2cCAAAAABMiYjjtH9IesVsOAPbbmKcLgEm/i/jRcR7LvWnnpz3DlQIAAAAAAAAAAAAANJv97djfDgAAQFvKVEeTTDL6jekcjJCp1X8yPhyhK6k/588qh/0PqwIAsA/Pdcnovxm41fzOKi1s2UF/6waGrZHUZl1VKHfEoNJadZ31ln5Hh1ZWN/S6+3y2x7XXgvUue3Z8/4d324rVQKe//h1tc35c+akvdPx6PvLI7jh43kb3C0mTarCyNjaVl8XWYi1uyBY64t1KkiRJjWtnNhfbC5U4sW95FJIRz9hSM0tGv5epbVxk1wcAAAAAdKaIeELaSNoNdj0CQEONedIAmPR7iR8d53f+Z01pV6UNumIAAAAAAAAAAAAAgGaxvx372wEAAGg7s2ojazJJ/RctNiDhp+nf03sPSkZG5yxf/odWCQBgEpYv/72upP6wgVvN7629gy073G9zaaE1ktqs15YWdMRwUgNJpd/dub3zG3bN3ZQtxKGV1Y5rC/aRT1xn+1UDfe76r8WsuRvb5vz4zJe+2vFreu9P73evkPSYDVbWxqbystharMUN6fNOJ7xLSZIkaWq6NZuLbcUkju1fEXNqdc/fUhPK1OoPdiX1Uw444IADbQABAAAAgM4QEX+Q9py0O+14BICmGPPEATDp9xM/Os7e+ELaiCsHAAAAAAAAAAAAAGg0+9uxvx0AAIC20pWsL2SS+i9aelhCMnpfplbfPmtu/YhZC8f+yKoBADy6zODowQZtTU2X9iQtO9Dvg4UBayS1Wasqh7X9MNLbunPWWvodjQ/qvSFbaNgA4LUDw45rC/ai099su1UD/fS+n8Xgmue11Tly821f7/h1/e5dP3S/kPTrFlbXxEv6lsalxSS+ki22/buTJEmSWqPxZ88LegZj3cBwHFyrezaXGlwmGf3onOroU+wCAQAAAID2FRF/nHZK2vftdgSAphrz5AEw6fcUPzrOvrhxz7lzoKsIAAAAAAAAAAAAAGgE+9uxvx0AAIC20lWrv2VmDUyo39+VjL6/qzZy5Jzly//QCgIA/Maz3dyRhQZsTU0fzve37BC/27pz0Z0Y3ie1U7PSvpBr7+HwX8z1WGvpd3R834qGXG93pM8Kz+pf4Zi2YHNXnxj33HufbVYNdMpfvK3tzpO7fnB3x6/r127/unuG1MH1J+vj2PRZ5vzewfhsrret35MkSZI0Mxr//v7c3vlxaGW1Z3apsX17VrJhvp0gAAAAANBeIuKpaa9Pu9cuRwCYEmOeQAAm/b7iR8fZH7elPSvtCa4mAAAAAAAAAAAAAGB/2N+O/e0AAAC0lUwyumPGDk1IRn+aSeqXpX+umzdv0+9bTQCg06XPSEcZrDU1/VOu1NLD+9YNDFsnqc0aHxjfzkNHP5kvW2fpd/T3xWpDrreTy0sdzxZs1tyN8ZkvfdXWqgb61Ge/3JbnygO/fLDj1/a6L97kviF1UPnaSNQHVsWW0oK4Mt8Xu9r4vUiSJEkzv6vzpTittDj6k/We56UGlKnVH+xK6i8/4IADDrQjBAAAAABmtoh4atqWtJ/Y4QgAU2rMkwjApN9b/Og4jbAz7TlpT3RVAQAAAAAAAAAAAAD7wv527G8HAACgrXQlo//RFgMUkvqPM7XRv+2aO7LygLExL9wAQEfKJBtPMlhraropW2jpgX2vLS2wTlKbddTAyrYeNPrBwoB1lh6nWnVd3NGd2+9r7azSQsezRTvr3K22UzXQPffeF8nwc9vuPOlZ8iyLm7riHz/rviG1cbPThiqr47TS4theqMTOBjwDSZIkSVPdzmxu4nn2xL7lkU1GPOtL+1kmGf3onOroU+wKAQAAAICZJyKelrYl7Sd2vwHAtBjzRAIw6fcXPzpOI93hx8cBAAAAAAAAAAAAgH1hfzv2twMAANBWumr1+9twgMIPM0n9ooOqI0vSf8QDrTIA0CnSZ6C/NFCr+T2jVo9dLT6o74pCv7WS2qzupB5fy+bbdsDou4pV6yw9Tq8qL97v6+yCnkHHskU79IiXxC8e+KVtVA304tPf3JbnypL6iy1u6tLtV7p3SG3UwbV6DFVWTzzvbC9U4pY2fu+RJElSZ3ZjthBv7R2MwyuHxSzvANL+9O30HXLQzhAAAAAAmBki4mlp56TdZ9cbAEyrMU8mAJN+j/Gj4zTrx8ePTXuCqwwAAAAAAAAAAAAAmAz727G/HQAAgLbSVat/p50HKWRq9bsytdELD5q3cWn6j3ugFQcA2vzZ7h0GaTW/JFnX8sP5dmZz0Zust15Sm3VpT9K2Q0Xf3jPXGkuP09W58n5dY9uKScx2HFuyOYNHxs23fd3WqQb65LXXt+35MvrcMyzw+JSViy5z/5BmeP3V9XFi3/K4pDg3bsgW2vY9R5IkSfrtrs31xmtKi6JWXefdQNqXktGH0j/PsBcUAAAAAFpXRPyPtPHNbvfa7QYALWHMEwrApN9n/Og4zf7x8fFzzL4XAAAAAAAAAAAAAOBx2d+O/e0AAAC0lUyt/o+dMlAhUxv9elcy+vqDqyN9Vh4AaEddSf2DBmk1v2WVw2fEUL5n9a+wXlKbNT50vl0Hib65Z741lh6jocrq/bq+rij0Ry4ZcSxbtAu2fsB2qQb68T0/jeqq57Tt+fL8V55jkVOvPPsi9w9phjV7zzPN5tLCuDLfF7va9L1GkiRJmmx3dOdie6Ey8b1/1nd30t7vBU1GPzKnOvoUu0QAAAAAoHVExB+kbUr7oV1uANBSxjypAEz6vcaPjjMVrk9b6YoDAAAAAAAAAAAAAB6L/e3Y3w4AAEBb6Urqr+nIoQq1+m1pZ82qjeSdBQBAu0ifb64zQKv5rR0YnhHD+N7SO2i9pDarJ9kQt3fn2nKA6JbSAmssPUbn9M7f52vrmnw5epP1jmOLtuGEV8dDDz9sm1QDPf+V57T1OXP6699hkVPHv/R17iHSDGiwsjY2lZfF1mItbsoW2vI9RpIkSWpE48/L5/cOxpr/w969x8lV14f/T7zVttraWoXMJoHdmb3M7OzsOdmEhM1lE8g9u2cSYIqiIKjEC1IUsDRefsSqgN8KFahU1FpE8QJ4A6qgFRRRFEHkEqK23uqlioooyj35/E7S2Ib7JpmdnTnzfD4er0f+a3XO55z9nOm78xlY6l1C2pUZ0Cj57ow4mW1SBAAAAAAmVwjhSTt+mO+7ptsAoCnV7FgAxv1+40fHaaTPpQ258wAAAAAAAAAAAACAhzPfjvl2AAAAMmV6PFboiKtb2/yAhU1pG2cMrc1bEQBAK+uIktscnjXxHTxwQEscwHdVvs/1kjLYB3oqmTw09KTisOsrPUoz067N9+zWffW1ru4wZ3CVz7FJ6x4+NHz3Bz8xGlVHF116ZebXzZnvvdCFTq14/ms8R6QmrCsaC8nAgWFjcW64vFDM5HuLJEmSNNFt20ufUBwO/dEa7xnSOMpFyf3pvydNmTJlqokRAAAAAGi8EMLatE2m2gCgqdXsWgDG/Y7jR8dptK1pH03rdgcCAAAAAAAAAAAAAH9gvh3z7QAAAGROR5Rc7YCF7W1NP4svTYvHXvXc8theVgYA0HL7uji53Z5u4ju8PNIyB+/NrqxyzaSMdXT/wkweFHpsaYHrKz1KBw8csFv31M1d+bC8ssxn2MSdf9FnjETV0c9u/1Uojbwg8+vm4suucrFTs5Yf5TkiNUmLKsvDiaXhcGF3JWzqzGfyXUWSJEmajG5J99fn9sRhXfmAMDNKvH9IT1AuSi7uGqr9uakRAAAAAGiMEMJQ2hdMswFAS6jZvQCM+13Hj44zWe5POzftOe5EAAAAAAAAAAAAAMB8O+bbAQAAyJyOqLrawQoPL9mS/ntNR5Qct1dl3XOtEgCg6dVqT96xh7GXm+BeVlrYMgfubfvP6ppJ2ao4OBo2ZfCA0Jf2L3J9pUfpn3vjXb6fNqcdUR7x+TVxh71yY9i6datRqDp64ave1BZr59rrb237a71ly9awz+yDPEukSaorGgvJwIHh1L454ep8b+beSyRJkqRm7Mvp3ntjcW4YGlzlvUR6vKLqDztmjc0zPAIAAAAAEyeEMH3Hj6BtMbkIAC2jZhcDMO53Hj86zmS7I+2ktD9yRwIAAAAAAAAAAABA+zLfjvl2AAAAsmhqR5Rc7WCFRy8XJ/fl4uplHfHYC5/dmzzTcgEAmtFzy2N72bs1puNL81vmkL339MSumZTBLuiuZO5Q0MPKi11b6WH1RGPhpq7CLt9PJ5aGfX5N3MCSw8Ptv7zD+FMdffBjV7TN+vnhj3/W9tf7F7+607NEanDlaE04qn8knNsThxs7C5l7F5EkSZJapds689v/7wPbvk+f6V1FeoxZz+q90+PqsSZIAAAAAKC+Qgh/mrYx7W5TiwDQcmp2MwDjfvfxo+M0ix+mHZE21Z0JAAAAAAAAAAAAAO3HfDvm2wEAAMik6UPVgY6o+oCDFZ7g0IUouTvt4o4oOWT6vNofWzkAQNPs5yrryvZrjen1xXktc7je9V3dYWaUuG5SxnpZaWHmDgNdWz7QtZUe1kv7F+3yvfSO3iGfXZP36c9/xchTHf3XT34eeuc/ry3WzoyhteH++x9o+2t+67e+51kiTXDbvkdYUlkeNhTnhUsK/WFzxt49JEmSpCz05Xxv2FicG4YGV3mPkR69C5/dmzzTJAkAAAAA7JkQwpPS1qf9zMQiALSsml0NwLjfgfzoOM3m6rQhdycAAAAAAAAAAAAAtBfz7ZhvBwAAILM64uqbHKawC0XV3+bi6gfTxkql2tOsIABgUvdys8YOsEdrTKf0zWmpQ/UOrCxz3aSMVY7WhE1d+UwdALrCs0p6RB/qruzSfXRh90DYN058dk3ca04+05hTHW3dujUc9sqT22b9zFp+lIue+uwXr/M8kSagvvQd47Dy4nB63+xwbb4nU+8akiRJUpa7rTMfLuiubN/Pz/RuIz18vnPz3lFSMk0CAAAAALsnhDA77VpTawDQ8mp2NgDjfg/yo+M05f8bXdr5ac91lwIAAAAAAAAAAABAezDfjvl2AAAAsqtWe3JHlFztQIVdLxdX7+iIqv8yLRpbtu1ztJgAgEbLzVr71/ZljekdvUMtdZje3xb3d92kDLbtkMwsHfy5sLLCdZV2qjy4Jmzqyo/7HvpsoRh6o1GfXRM3b83R4be/+70Rpzp630cua6s1tObwE1301Hkf/bRnilSn5g6uDCcUh8OF3QO7tO+QJEmS1Jxdne8NryvuH6JotXce6X9L7srFyfNMlAAAAADA+IUQnp12ZtoWE2sAkAk1OxyAcb8P+dFxmtkdacel+W0zAAAAAAAAAAAAAMg48+2YbwcAACDTpg+u6cjF1R87TGGPDmL4edo7p82qLpwy5eQnWVUAQCN0zFq73j6sMb2nJ26pA/Qu7K64blIGe3H/okwd9jl7cJXrKu3UMaUF475/rst3hznuoaZuxtDa8NUbbjXWVEc//PHPQs/8Q9tqHb3q9We48KlTzjrfc0Xag4YHV4YNxXnhkkJ/pt4nJEmSJP1ft3XmwwXdlXBIeUmY7j1I2l4urp45NLT+qSZLAAAAAOCxhRCesuPHy+40qQYAmVKz0wEY93uRHx2nFdyYtsAdCwAAAAAAAAAAAADZZb4d8+0AAABk3vTKunIuSu50mEJdDmP48bYDGaYNrd32oj7V6gIAJkpuMHmt/Vdj2nYIXSsdnHdrZz4U4jHXTspYPdFYuKmrkJlDPkvRqOsq7dRF3QPj/ju/cmCpz6zJe+uZ7zfKVEdbtmwNB714Q9uto9Pf9WEXP3XMhrd7rki70Mwo2b5XOLVvTvhSV29m3h8kSZIkja/P5/vCCcXh0Bet8Y4ks5xR9et7xwftY7oEAAAAAB4phDCSdosJNQDIpJrdDsC434386DitYmva+Wl7u3MBAAAAAAAAAAAAIHvMt2O+HQAAgLYwPR5bmYur9zpMoZ6HMiTfzcXJWzvisYoVBgDUW0dUfbM9V2P6RHe55Q7MO3jgANdOymDv7okzc7DnvnHimko7igdXh83jvHfWlxb6zJq8pX99XLjvvvuNMdXROed9vD3fQz79RRc/ddCLN3i2SE9QVzQWDikvCaf3zQ7XdvVk5p1BkiRJ0u53c1c+nN07FEYqy703qd37WcdgssSECQAAAAD8jxDCX6Sdu+PHygCAbKrZ9QCM+x3Jj47Tau5MOy7tye5gAAAAAAAAAAAAAMgO8+2YbwcAAKBt5OLqWC5O7nOQwoS0Kf1s3zBjaG3eSgMA6rJ3i5Kz7LEa0xWFUssdlHda3xzXTspgh5aXZOIwz02deddT2qnjS/P9fc9InXMPCZv/4wdGl+roP77/o5CfV2vL9fTNW79jAaTmrTna80V6lIqDo+Go/pFwbk8cvtlVyMR7giRJkqSJ6ZJCf1hfWhi6ojHvU2rPouoD0+Lq306ZMmWqSRMAAAAA2tmOH9O73VQaAGRezc4HYJfek6AVXZ825C4GAAAAAAAAAAAAgGww3475dgAAANpKLk6SXFy912EKE1cuqn61I0qOmzm0bpoVBwDs/r6t+n57q8Z0Tb6n5Q7Huyrf59pJGWyfOAlf7+pp+QM8t/13cD2l/2vbobZPdN9c2D2w/Rng82ru3nX+J40r1dEDDz4Y1hx+Ytuupzt/c1fbr4EtW7aGfeYc5PkipRXisbBqYGk4vjR/+75gU1e+5d8LJEmSJDW2a7t6whuL80I8uNp7ltp1bvPjf7nfyj8zbQIAAABAuwkhFNI+ayoRANpGzQ4IYNzvS350nJb+f79LOzPtGe5mAAAAAAAAAAAAAGht5tsx3w4AAEDb6RhMluTi5NcOUpjgouTBtH9PP+sX7zNYfZaVBwDs0p4trn7SnqoxfaOz0JIH4w1XVrh+UgY7o3d2yx/c+cV8n2sp7WjO4KonvGe+kN4z/dEan1eTd8jRrw9btmw1qlRH//juj7bteqoccLgFkPrJz37h+aK2rCsaC0sHloVjSgvCWb2zwhX5YtjUlW/59wBJkiRJzdGmtHf3xGHVwFLvYGrDkm9PH6oOmDgBAAAAoB2EEJ6adlLaPabRAKCt1OyEAMb93uRHx8mC76WtdEcDAAAAAAAAAAAAQOsy3475dgAAANrSjMGx/o6o+kOHKDSmXFy9tyNKLk074jml2jOsQADgieSi6hftoya+GXESNrfogXivKQ27hlIGWz2wtOUP7Ly8UHQtpR2dVBx+3Pvlxs5CWFBZ4bNq8voWPj/86Ke3G0+qo03f/n7Yd7+D23ZNVY88ySJIffm6mz1jlPlmRklYmP6tf3lpYTijd3b4t0L/9gPuvyVJkiRJDejS7lI4qn8k7Bsn3tHUPrOaUfWeXJy82NQJAAAAAFkWQpiXdpspNABoSzW7IYBxvzv50XGy5MK0v3JnAwAAAAAAAAAAAEDrMd+O+XYAAADa1vTBNR25qPpVByk0uKj621yUfCD9d/XQ0PqnWokAwKPpiJMb7Z0mvp5otGUPwfto94BrKGWw6WlX5vta+5DOQsm1lHb0mfR+eKx7ZXPaoeUlPqcW6KJLrzSSVEf33/9AWHbocW29pk5809kWQupDH/+sZ4wyVz4aCysHloYTisPhvJ4ofL2rp6X39pIkSZKy0bXpu8nG4twQRau9u6md5jT/qVSqPc30CQAAAABZEkJ4etppaQ+aQAOAtlWzKwIY9zuUHx0na36WdrC7GwAAAAAAAAAAAABai/l2zLcDAADQ3kZGnpKLktMcojA55eLqHennf37a0ilTTn6SBQkA/EFHnHzffmniqwyubtnD7zZ15kNvNOo6ShlsQ3FeSx/O+Ynususope03uOpx75XXpfe6z6n5e8nxpxpFqrO3/dMH235d/cuHLrUQUqecdb7njDLxvcIh5SXbD6e/uFAOt6bv6q28l5ckSZKU7ba9s5zbE4dlA8u806k9ipLr9xqs7msCBQAAAIAsCCHsn7bZ5BkAtL2anRHAuN+j/Og4WXVh2nPc5QAAAAAAAAAAAADQGsy3Y74dAAAAUtOj6mEdcfV3DlKYvHJx8qNcXD1z2tDaBVYkAJDuC+6wR5r4ZldWtfTBd4eVF+WKdyQAACAASURBVLuOUgYbGlwVbuvMt+yz6aPdA66jlHZiafgx75MLuithZpT4nJq8eNmR4Y47f2sEqY5u3vyfYZ85B7X92vrK12+xGFLrX/s2zxq1XP3Rmu3v4qf3zQ5X5fta+jsFSZIkSe3dJYX+cFT/SJjpXU9ZL6r+Ytrg2uWmUAAAAABoVSGEP047Le1BU2cAwLYf0LVDAhj3+5QfHSfLfp52hDsdAAAAAAAAAAAAAJqf+XbMtwMAAMAO04ZG+zri6iYHKTTDQQ7Jbem/G3OVtT1WJgC0pakdUfUB+6KJb35lZUsfdndW7yzXUcpoH+0eaNln0wd7Bl1DKW3bobSPdo98Md8XStGoz6jJmz5rbfj8l643elRH9913f1hyyLHWV9odd/7Wgkgtf96rrQc1fTPjJIwOLA1v7psbLs+XwuYW/g5BkiRJkh6tq/O94TWl4dDjO0tlex7zwW3zmFOmnPwk4ygAAAAAtJIQwoK0/zBtBgDspGaXBDDudyo/Ok47uCjtr9zxAAAAAAAAAAAAANC8zLdjvh0AAAB28pf7rfyzXJRc7CCF5ikXJ1/rmFV99Yw4yVmhANAe9qos+1P7oMa0eGBFSx9y99WunpDuE11LKYMd1T/Sss+m9/VErqHavnhwddj8KPfHzV35sKSy3GfUAr3u1HcZN6qzvz/jfdZW2uyVL7YYduid/zxrQk1Zf7Rm+3783J443NDV3dLfG0iSJEnSeLuhqxDe3Dd3+3eb3g2V2aLqp/YZrD7LVAoAAAAAzS6E8NS0jWkPmjQDAB6mZrcEMO53Kz86Trv4eVrirgcAAAAAAAAAAACA5mS+HfPtAAAA8EhTc1H1hI6o+oCDFJqpZEsurl45Paq+dObAmr+wTAEgu/aOas+x92lMyyvLWv6AuwPT/w6upZS98tFY+EZnoSWfS+f2xK6h2r7jSvMf9f44un+hz6cFWrj2FeHue+41alRHX//m5jBzaJ31lXbE37zZgkj94ld3Wg9qqvqiNeGo/pFwXk8UNnXmW/67AkmSJEna3W5L34m2vRstHfB/g1Q2y0XV/5heWVc2mQIAAABAswohlNJuMGUGADyGmh0TwLjfr/zoOO3m/LRnuPsBAAAAAAAAAAAAoLmYb8d8OwAAADyG6XGyKBclP3WQQhMe7BAn93VE1U+l/z5v2tDon1itAJAt6d/3mfY8jWl0YGnLH2z3uuI811LKaP/YO9SSz6V/6p3l+qntu6h74BH3xum9s302LdA+sw8KN97yHeNFdXT3PfeGBdVXWF87OvXsD1gUqetuvM160KTXG42G9aWF4cPp3+1NXfmW/35AkiRJkurdtvelgwYOCNO9QypzJXd1RMkhplMAAAAAaCYhhKlp69N+b8IMAHgcNTsngHG/Z/nRcdrR99IWegIAAAAAAAAAAAAAQPMw3475dgAAAHgce0e153REyb87RKF5y0XJ3ek1ujStVirVnmbVAkDryw0kvfY5jWld+YCWP8zukkK/aylltGUDy1ryuXRG72zXT21deXBNuK0z/4i/151R4vNpgU5/14eNFdXZG057t7W1U5/4zNUWReqCj11hPWhSmhEnoTpwQDinZ1a4uSv/hHvbr3V1h6sKfeGy9G/5tr/nF3RXwgd7BsO5PXF4Z/o/4/S+2eHUvjlhY3Fu+Lvi/uGE4nB4Rf+CsL60MBxWXhwOLS8JycCB21s1sDQsqSx/SHMGV4XZlf9rMN1H9Eaju1UUrX7I/6xtLa6seMT/zj/85/lDtfQ/47b/rIeXR7b/597Wtv8e23p9cd72/25v6dtv+3/X09O9/rb/7tv6QE9l++dxUffA9s/mynxf+FJXb7g+/cw2tfh3LZIkSZIe2uWFYji6f2HYN/YdpzLV1lyUnDalVnuyKRUAAAAAJlsIYWbalSbLAIBxqNk9AYz7XcuPjtOuHkw7Lc1vkQEAAAAAAAAAAABAEzDfjvl28+0AAAA8kZGRp3TE1Y3bDhFwkEJzl4urd+Si5Pz03zGHPQBA68oNViN7m8Z0aP+Slj/EbnNaZXC16ylltMsK/S33XHpb7xzXTm3dK/oXPOSeuLGzEOYNrvTZtECrDjs+PPDAg0aK6uia624K02ettb526gc/+m8LI7Xx7f9iPajhFQdHwzGlBWFjce7/dnLf3PCa0nB4Sf+iUCsvCSsqy8L+lZWhP1oTZjgsfo+amdYbjYZ4cHXYb3BVWFJZHlYNLA3JwIHhsPLicFT/SFhfWhhOKA6H1xX333493t43O5zTG4fzewbDxwrlcHm+FK7O94Ybugot//2NJEmSlIWuzfeEv033733pO5P3HmVm5jKqfmbmwJq/MKkCAAAAwGQJIRyUdoepMgBgnGp2UADjft/yo+O0u+vTCp4GAAAAAAAAAAAAADC5zLeD+XYAAADGafqsZF0uSu50kEKLHPYQJz/qiJO3TxsanWX1AkBr6Zg1Ns9+pjEd3r84EwfYHd2/0PWUMtoxpQUt90x6c99+rp3augu6Kw+5J44oj/hcWqDC/n8dvvuDnxgjqqPf/f6eMDz2Mutrp8qLXxi2bt1qcaRecMybrAlJu9T0tN5oNAwNrgqLKsvDqoGl4ZDyku17rVf2LwgnlobDxuLccHrf7HBObxzO7xkMn+guh8/n+8L1Xd2Z+P5HkiRJapZu7CyEt/TtF6JotfcVZaTk23tHScm0CgAAAACNFEJ4etqZpskAgF1Us5MCGPd7lx8dhxB+m/ZCTwQAAAAAAAAAAAAAmDzm28F8OwAAALtg7/igfXJR9VqHKLTcoQ/fz0XJabmBpNcqBoDm1zFr7AD7l8Z0ZP+iTBxc996eyPWUMlpPNBpu6iq01DPp5L65rp3a+p7d1Jn/3/vhzN4hn0uL9P4LP2N8qM5OfNPZ1tbDOvzYv7cwdthv1UutCUkNrysaC5XB1WFJZXk4pLwkHNU/Eo4tLQgbivPCqX1zwtnp3u28nihcXCiHqwp94Zad9nWSJEmSHtm270K37aOHKyu8cygLM5Z3pf8ebGIFAAAAgEYIIZTSbjZJBgDshprdFMC437386Dj8n/PTnuHJAAAAAAAAAAAAAACNZ74dzLcDAACwiwqFlX+Ui6tnOkShZduUtnGvylin1QwAzakjqq62Z2lML+5flIkD677RWQj7xolrKmW0s3pntdQz6XXF/V03tW2Hl0f+9164Mt8XuqMxn0sLdNgrTw5bt241NlRHX7z2xjB91lrr62Gdce5HLI7U735/j/UhqWXatp8bGlwVllSWh2r5gHBk/6Lw6tL88Oa+ueHs3qHwwZ7B8OlCKVyb7wm3deYz8T2TJEmStKtt2wu/pyfevm/2HqEWb2suSk6bMuXkJ5lcAQAAAGCihBCOSPu9STIAYDfV7KgAxv3+5UfH4aG+lRZ7OgAAAAAAAAAAAABAY5lvB/PtAAAA7KZpg9W1uTj5tYMUWrVkS/rvNR1RctxelXXPtaIBoHmkf6MPtldpTEf3L8zMYXUHDRzgmkoZbeXA0pZ6Hp1YGnbd1Lad0zNr+31wS2c+LK6s8Jm0QANLDg8//8UdxoXq6Ld3/T7MWfkS6+tR+sJXvmGBpL5563esB0mZrTcaDcODK7e/xx1WXhyOLS0IG4rzwul9s8N5PVG4uFAOVxX6wqaMfB8lSZIkPbxte95Dyku8H6ily8XJv+0zWH2W6RUAAAAA6imE8BdpHzdBBgDsoZqdFcC438P86Dg80r1px3pCAAAAAAAAAAAAAEDjmG8H8+0AAADsgb0Gq/vm4uRrDlJo8aLkwfTfz6X/HvHs3uSZVjYATK6OeOyF9iiNaX1pYWYOqDujd7ZrKmW4K/LFlnkeHVea75qpLZuZdn1X9/b74FWlBT6TFumSz15jTKjOjn39GdbWozR91tpwx52/tUBSF116pTUhqe2bESehPLgmLKisCNWBA8KR/YvCiaXhcFrfnPC+nihcUugPX8n3hs0Z+d5KkiRJ7den0j3toeUl2/e+3gHUiuXi6nf2jpKSCRYAAAAA6iGEEKf9p+kxAKAOanZXAON+F/Oj4/DYPpn2LE8KAAAAAAAAAAAAAJh45tvBfDsAAAB7aJ+RkafnouRdDlLITL/riJMP5eLqWKlUe5oVDgCNNz2qvtSepDG9on9BZg6m+1pXd5gZOZROymrHlFrnefXK9NnqmqkdWzOwdPs98P7uwTDd59ESHffGdxgNqrMrvvA1a+sxWrTulRbIDm898/3WhCSNs5lxEuLB1WFFZVk4rLw4/E1xfnhz337hnN44XNQ9EL6Q7wu3duYz8/2WJEmSstdnC8Xw4v5F2/e29vhqtXJRcmdu1tpRUywAAAAA7IkQwhFpd5scAwDqpGaHBTDu9zE/Og6P7ztpFU8LAAAAAAAAAAAAAJhY5tvBfDsAAAB10hGPHbTtEAGHKWToUIg4+XV6Tc/PxdWxKSMjT7HKAaBB+6oo+Rt7kcZ0TGlBpg6lWzWw1HWVMlpPNBa+0VloiWfR+v6Frpnasrf07ReuyfeEUjTq82iBZq98cbjzN3cZC6qjX/36NyFa+iLr6zF69f93pkWywwuOeZM1IUl1rjy4JiyurAiHlJeEV/QvCG8ozg1n9c4KF3RXwhWFUvhmVyFT34FJkiSp9boq3xfWlxaGfeLEHl6t1tZclJw2ZcrJTzLNAgAAAMCuCCE8Pe29JsYAgDqr2WkBjPu9zI+OwxO7J+2lnhgAAAAAAAAAAAAAMHHMt4P5dgAAAOooV1nbk4uTbzpIIXvl4uqP086cNrR2QXqpp1rtADBx0r+9J9l/NKa/Kc7P1GF0by3u57pKGe60vjkt8Sw6un+h66W27N/zxbBmYKnPogWaMbQ2fPm6m40D1dnL/vb/WV+P04WXfN4i2SFaeqQ1IUmTUG80GoYHV4Zk4MCwvrQwbCzODef2xOGSQn+4oas7U9+RSZIkqXm7tqsnnFAcDl3RmH26WqsoubRrqPbnJloAAAAAGI8QQk/aTabFAIAJULPbAhj3u5kfHYfxOz/tjz05AAAAAAAAAAAAAKD+zLeD+XYAAADqbJ+Rkafn4uqZDlLI9AERP8hFyWnThkb7rHgAqL9cnLzBnqMxvbo0nKlD6L6Y7wvTXVcpsw1XVoTNLfAsekn/ItdLbdf8yspwSt8cn0WL9JZ3nGcEqM4+efnV1tYT9KOf3m6hpH7+izusB0lq0nqj0bCksjwcUl4S1pcWho3FueHcnjhcUugPN3QVMvUdmiRJkia/a7t6wobivNATjdmPq5X61t7x2qKpFgAAAAAeTwjhkLTfmhYDACZIzY4LYNzvZ350HHbN9Wn7enoAAAAAAAAAAAAAQH2Zbwfz7QAAAEyQjnjshR1xcpeDFDLfprSNM2cf1GXVA0B95KLkZHuMxnR8aX7mDqBbPLDCtZUy3AXdlaZ/Dh3VP+Jaqe06rLw4FGKHv7ZCSw5+Vbj3vvuM/9TRL351Zxg88Ajr63Haf3S9hbLDldfcYE1IUovWG42GJZXl4ZDykrC+tDBsLM4N5/bE4ZJCf7ihq5C579gkSZLUmL7W1R02FOdt32/ad6sliqq/mRaNVU22AAAAAPBwIYSpaSelbTUpBgBMoJqdF8C439P86Djsul+mLfUEAQAAAAAAAAAAAID6Md8O5tsBAACYQLmBpDcXVW9ymEI7lGxJ/72mI0qO26uy7rlWPwDsvvRv6kZ7i8Z0fGl+5g6ee0NxrmsrZbhDy0ua/jl0ZP8i10ptV1c05nNogTrnHhI2ffv7xn7q7CXHn2p9PUEnbDzbQtnh7H+5yJqQpIxWjtaE5ZVl4aj+kfDG4rzwz71xuKTQH27oKmTu+zdJkiTVv6939YQNxf1DbzRqf61WaGsuSk6bMmXKVBMuAAAAAGwTQnhm2idNiAEADVCz+wIY97uaHx2H3fNg2kmeIgAAAAAAAAAAAABQH+bbwXw7AAAAE2za0OifdMTJvzpIoX3KRcn9ubh62fTB5AV7VZb9qbsAAHZNunf6e3uKxvTq0nDmDpy7Il90baUMNzNKwlX5vqZ+Dh1RHnGtJDVl55z3ceM+dfbRT33e2hpHH/u3qyyWHV5x0j9YE5LUhpWjNWFFZVl4cf+i8MbivPCu3lnh0u5S+EZnIXPfzUmSJGnPuqGrEN5QnBt6o1F7abVCF5qPBAAAACCE0JN2m+kwAKBBanZgAON+X/Oj47BnPpT2J54mAAAAAAAAAAAAALBnzLeD+XYAAAAapCNKjuiIq79zkEJ7lYuq96TX/tK0WqlUe5o7AQDGs2+qvsU+ojG9ujQ/k4fNzRtc6fpKGe6E4nBTP4MOL4+4TpKarnVH/V14cMsWYz519N8//2UojbzA+hpHP/7v2y2YHRate6U1IUl6SL3RaFhSWR4OKy/e/r57du9QuKTQH27oKmTyeztJkiSNrxs7C2Fjce72/aJ9s5p7PjK5ea/B6r4mXQAAAADaUwhhddqvTYYBAA1UswsDGPc7mx8dhz33jbR9PFEAAAAAAAAAAAAAYPeZbwfz7QAAADTQjMGx/o4ouc1hCm1alPyyI07OmTa0dkG6HKa6IwDg0eXi6in2Do3pb4rzM3nI3LYDiF1fKdsHjm87TLJZn0GH9y92nSQ1VX0Lnh/+6yc/N95TR1u3bg0vfNWbrK9xND95uQWzw+/vvifMHFpnXUiSxl15cE1YNbA0vLR/UTi5b254d08cLiv0h5u6Cpn8Tk+SJEmP7Pqu7nBScTh0R2P2yGrmfpaLqsOmXQAAAADaRwhhatob07aYDAMAGqxmNwYw7nc3PzoO9fGztPmeKgAAAAAAAAAAAACwe8y3g/l2AAAAGmz6vNof5+LkPQ5SaO/SNfCjXFw9c9rQ2gXuCgB4qFyUnGa/0JiOLS3I5OFyn+guu75Sxjutb07TPoNe0D/iGklqqi669EpjPXV2/kWfsbbG2etPPdeC2eHa62+1JiRJdasyuDokAwdu/37v9L7Z4YLuSvhqV08mv+uTJElSV/h6utfbUJwXeqIx+2E16Txk9d5cNPYiEy8AAAAA2RdC+KO0D5gIAwAmSc2ODGDc729+dBzq5960IzxZAAAAAAAAAAAAAGDXmW8H8+0AAABMko4oOaIjqv7egQpK25S2ccbQ2rw7AwDSfVKc/IP9QWM6prQgk4fKbU6LB1e7xlKG229wVbitM9+Uz6Dnlxe7RpKappccf4pxnjr7r5/8PPTOf571Nc6uvOYGi2aHd573cWtCkjTh9UajYeXA0rC+tDCc2jcnXNBdCV/J92byO0BJkqR27Gtd3WFDcV7oicbsf9WU5eLqmVOmnPwkky8AAAAA2RRC+Ku0q02DAQCTqGZXBjDudzg/Og71d2aa2RgAAAAAAAAAAAAA2AXm28F8OwAAAJNo73htMRdXb3WYgv63KLk+7bjnlsf2cocA0K46ourp9gWN6ZjSgsweKLftv5trLGW79/VETfn8ObS8xPWR1BQNHnhE+MWv7jTGU0dbtmwNhxz9eutrnOXn1cLd99xr4exw9ImnWReSpEmrNxoNSyrLw1H9I2FjcW44L32nvqrQFzZn9LtBSZKkrPe1ru5wQnE4dEVj9rtqunJx8um/3G/ln5l+AQAAAMiWEEI57fsmwQCASVazMwMY93ucHx2HiXFR2p94ygAAAAAAAAAAAADA+JhvB/PtAAAATLJn9ybP7IiTDzlMQQ85WCJK7s/F1cumR9XD9qos+1N3CgDtJP07+I/2A43plf0LMnuQ3Ie6K66xlPFWDyxtyufPoeUlro+kSW/6rLXhymtuML5TZ++54BLraxc68ri3WDQ72W/VS60LSVLT1RONhqUDy8LR/QvD3/fNDe/vHgxX5fvC5ox+ZyhJkpS1vpzvDceUFoR94sT+Vk02/1i9ae/4oH1MwAAAAABkQwhhedqdpsAAgCZQszsDGPe7nB8dh4nz1bS9PWkAAAAAAAAAAAAA4ImZbwfz7QAAADSJjig5oiOq/t6BCnrkARPJ3en6uDStVirVnuZuASDrcnH1THuAxvSy0sLMHiC3Ka04OOo6SxnvU4X+pnv+1MpLXBtJk94bTnu3sZ06+8GP/jt0Dx9qfe1CH7j4cgtnh5//4g5rQpLUUnVFY2HxwIpwZP+i8Pd9c8MF3ZVwbVdPZr9LlCRJavWuyveFo/pHwow4sZ9V8xRVfzE9WjtiCgYAAACgtYUQjk170BQYANAkanZoAON+n/Oj4zCxfpg24GkDAAAAAAAAAAAAAI/PfDuYbwcAAKCJ7B2vLebi5BYHKuixysXVO3JRcn7a0nTJTHXXAJBFHVH1bH/3G9NL+hdl+vC49f0LXWcp472oCZ9jh5SXuDaSJrXFBx0T7r7nXiM7dbRly9aw7qi/s752sR/99HaLZ4fPXHmtNSFJykS90WhYObA0HFtaEE7vmx0uLpTDzV35TH/HKEmS1EpdUSiFw8qLw3R7VzXPvOO9ucHqkSZhAAAAAFpPCGFq2kbTXwBAk6nZqQGM+73Oj47DxLsrbaUnDgAAAAAAAAAAAAA8NvPtYL4dAACAJrNXZdmf5uLq+x2ooCcsSn6QrpVTplfWld05AGRJR5y809/6xnR4eSTTh8Z9qLviOksZb584CVfne5vq2XPwwAGujaRJa9/9Dg43b/5Pozp19s5//Zj1tYstO/Q4C2cnp579AetCkpTZZqYND64Mh5UXhw3FeeG8nih8pcne1SVJktqtTxbK4ZDyEvtVNdOs49umTDn5SSZiAAAAAFpDCOFpaR8y+QUANKGa3RrAuN/t/Og4NMZ9aS/w1AEAAAAAAAAAAACAR2e+Hcy3AwAA0KRy0diLOuLq7xyooPGUi5Kb039PmjY0OtPdA0Dr74OSs/x9b0zPLy/O9GFxt3XmQ2VwtWstZbzjSvOb6tlz8MABroukSeud//oxIzp19u3//GHonHuI9bWLnfZPH7B4dvLX699oXUiS2q7eaDSsHFgaji0tCGf3DoVLCv3h5q58pr+PlCRJarYuLpTDqnRPZn+qpiiqfurZvckzTcUAAAAANLcQwrPSvmDqCwBoUjU7NoBxv9/50XFonK1pGz15AAAAAAAAAAAAAOCRzLeD+XYAAACaWG4g6c1F1ZscqKBdO3wiuT7tuL0q657rLgKgJfdAUfUMf9Mb0yHlJZk/KO6Y0gLXWsp4+WgsfK2ru2meO9uera6LpMlo3VF/Fx7cssV4Th098OCDYfULT7S+dqNbNn/XAtppHfXOf551IUlS2sw4CcODK8Nh5cVhQ3FeOK8nCtfmezL/HaUkSdJkd0F3JYxUltuTatLLRcnNe1XGOk3GAAAAADSnEEIu7UZTXwBAE6vZtQGM+x3Pj45D470n7SmeQAAAAAAAAAAAAADwf8y3g/l2AAAAmtw+IyNPz8XVMx2ooF0uSh5M//1c+u8RzynVnuFuAqBVpH+73uZveWOqDhyQ+QPiPlYou9ZSG/S64rymee4c2r/ENZHU8PoWPj/86Ke3G8mps9Pf9WHrazcaHnuZxbOTb9zybetCkqQnaGBwdaiWDwgnFIfDP/fG4fP5vrA5499bSpIkNbrbOvPh7N6hMDS4yh5Ukz3X+Mvp0doR0zEAAAAAzSWE0J/2QxNfAECTq9m5AYz7Pc+PjsPk+GTaH3sKAQAAAAAAAAAAAMD/MN8O5tsBAABoER1x9eBcnPzaoQranXJRcnf674W5uDo2NLT+qe4oAJpZuud5q7/fjWnVwIGZPxxu2+G7DoaTsl9xcDTc2FloiufO88uLXRNJDe8Tn/6iUZw6u/Vb3wv77new9bUb/cM5F1hAOznnvI9bF5Ik7Ubd0VhYObA0HFtaEM7uHQqXF4phU1c+899nSpIkTXSbOvPh9L7ZoRytse/U5M0zxsl9aUeZkAEAAABoDiGEBWm/Nu0FALSAmt0bwLjf9fzoOEyeL6X9uScRAAAAAAAAAAAAAJhvB/PtAAAAtJSOaE13R1z9hkMVtGcHUlTvyEXJ+WlL02U11Z0FQNPteeLqm/zNbkxLB5a1xcFwJxSHXW+pDTq1b05TPHNe2L/Y9ZDU0Na/9m1GcOrsvvvuD0v/+jjrazf79n/+0CLayZHHvcW6kCSpThXisbByYGlYX1q4/XuAiwvlcGtnvi2+45QkSap3N3YWwobivNAVjdlrajJnGc+cUqs92aQMAAAAwOQJIRyYdpdJLwCgRdTs4ADG/b7nR8dhct2SlvM0AgAAAAAAAAAAAKDdmW8H8+0AAAC0mEJh5R9tO0jAgQqqS1HyX9vW07Sh0VnuLgCaRS6qvtHf6ca0eGBFWxwId2l3yfWW2qB4cHVTHKR9eHnE9ZDUsGavfHH49Z3Osqi3U8463/razUbWHWMB7WTLlq2hf/ELrA1JkiawrmgsLBtYFo4pLQhn9c4KVxRK4bYm+H5AkiSpVbo63xuO6h8JM+LE/lKTUi6qfqZrqPbnpmUAAAAAGi+EsDbtXpNeAEALqdnFAYz7nc+PjsPk+25a3hMJAAAAAAAAAAAAgHZmvh3MtwMAANCipg1W1+bi6h0OVVAd25S2ccbQWl9UADCpOqKxDf4uN6b5lZVtcxjc3MGVrrnUBp3dOzTpz5ttB0+6FpIa0YyhteHL191s7KbOvnHLt8PMoXXW2G72j+/+qEW0k03f/r51IUnSJFSIx8LKgaXh2NKC7d8VXF4ohs1t8j2oJEnS7rZtz3RYebH9pCalXJzcsldlrNPEDAAAAEDjhBBelPaAKS8AoMXU7OQAxv3e50fHoTn8NK3sqQQAAAAAAAAAAABAuzLfDubbAQAAaGEzZx/UlYur1zlUQfUt2dIRJVfn4uTluTlrn+1OA6DRclH1RH+PG9OswVVtcwjchuL+rrnUBg1XVoTbOvOT+rx5Sf8i10JSQ3rrO84zblNn9913f1hyyLHW1x70ne/9yELayfs+cpl1IUlSk9QbjYZk4MCwoTgvdWv/1AAAIABJREFUnNcThWu7etrmu1FJkqRd6UPdlbB4YIU9pCZjbvH2aYNj803NAAAAAEy8EMJJaVtNeAEALahmNwcw7nc/PzoOzeNXaXM9mQAAAAAAAAAAAABoR+bbwXw7AAAArW5k5CkdcXVjR5xscaiC6l6UPJj++7n03yOeU6o9ww0HQCOk+5rX+DvcmIqDo21z+NtnC0XXXGqTzu2JJ/V5c3T/QtdB0oS34vmvCfff/4BRmzp70+nvs772cF3yUC//2/9nbUiS1MQNDa4KL+gfCW/u2y9cXCiHm7oKbfN9qSRJ0uN1W2c+nNMza/t+yb5RjSwXV++dPpi8wOQMAAAAwMQJIbzNZBcA0MJqdnQA437/86Pj0Fx+k7bI0wkAAAAAAAAAAACAdmO+Hcy3AwAAkBG5uDqWi5NfOVhBE3ZgRZTcnf574ba1NjS0/qnuOgAmyrR47FX+9jamfeOkrQ5/W1hZ4bpLbdDw4Mrthz1O1rPmZaWFroOkCa1rbi1s/o8fGLGps+tuvC3MHFpnje1B7/vIZRbSTrZu3RqipUdaG5IktVAzd3yvsD59tz+7dyhcXiiGzW30/akkSdLDu7UzH07tmxN6olH7RTWyrWkbTc8AAAAA1FcIYWraP5rsAgBaXM3ODmDc74F+dByaz+/TlnlCAQAAAAAAAAAAANBOzLeD+XYAAAAyJDe7OqMjrl7jUAVNdLk4+VUuSs5PW5ouvanuPgDquqeJk5f7e9u4NnXm2+bQt5P75rrmUpv03p5o0p41x5QWuAaSJrT3feQyozX1ntS5+54wP3m59bUHdc2thTt/c5fFtJNbv/U9a0OSpAzUE42GZODAsKE4L5zXE4Wvd/W0zfepkiRJf+i6fHc4trQgzLQ/VENL/nVoaP1TTdEAAAAA7LkQwtS0s0x1AQAZULO7Axj3u6AfHYfmdG/amKcUAAAAAAAAAAAAAO3CfDuYbwcAACBrRkae0hFXN3bEyRaHKqghRcl/5eLqmdOGRme5AQGoh+lR9aX+xjau67u62+awt6vyfWG6ay61RYsrK8LmSXrWvKq0wDWQNGEd9sqTw9atW43V1NmGU/7Z+trDXvX6MyykhznnvI9bG5IkZbAZcRLmD64IR/cvDGf0zg6XF4qT9h2EJElSo7siXwzV8gH2hWrkbOK/7zNYfZZJGgAAAIDdF0KYmvZOE10AQEbU7PAAxv0+6EfHoXndl7bWkwoAAAAAAAAAAACAdmC+Hcy3AwAAkFEd0dpVHXFyu4MV1MhycfLN3GDy2tzs6gx3IQC7v49JjvB3tXFdne9tq4Pelg4sc92lNum87sFJec4cV5rv85c0IQ0sOTzc/ss7jNPU2Ze+dlOYPmutNbaHffm6my2mhznslSdbG5IktUnd0VhIBg4MG4rzwgXdlXBTV6GtvnOVJEnt17Y9z4LKCntBNWgmsXrr3vFB+5imAQAAANh1IYQnp/2raS4AIENqdnkA434n9KPj0Pw/PH6QpxUAAAAAAAAAAAAAWWe+Hcy3AwAAkGHPLY/t1RFXP+tgBTW+ZEv67zUdUXLcXpV1z3U3ArAr0r8fh/hb2riuKJTa6oC3t/Tt57pLbdLSgWWT8px5TWnY5y9pQrrsc182RlNnv/3d78N+q15qfe1h+4+uD1u2bLWgdnLvffeF/Lya9SFJUps2M214cGVYX1oYzu4dCl/M97XVd7CSJKk92pR2et/sUI7W2ANqwstF1f+eHo3OMVEDAAAAMH4hhCenvd80FwCQMTU7PYBxvxf60XFofg+mvdATCwAAAAAAAAAAAIAsM98O5tsBAADIulrtyR1xdWNHlDzocAVNSv+z9j6X/nvEc0q1Z7gpAXgiHdHaVf6GNq5PFfrb6nC3r+R7tx9q69pL7dEHewYb/px5bWl/n72kuvfaN7/T+MwEOP7ks6yvOnTmey+0mB7m6q9+09qQJEkPqTK4OhxWXhxO7ZsTLin0h9s68231vawkScpuN3YWwobivNAZJfZ9mtByUfWeXFw91FQNAAAAwBMLITw57cMmuQCADKrZ7QGM+93Qj45D6/zwuJkYAAAAAAAAAAAAADLLfDuYbwcAAKBNdAwmS3JR8lOHK2hyD7ZI7k7/vTAXV8eGhtY/1Z0JwKOZHieL/N1sXB/uHmi7g90OGjjAtZfapAMqy8PmBj9jXlec57OXVNeGx14W7vrd3UZn6uzfr/669VWHZg6tCz/52S8sqId56zvOsz4kSdLj1hONbv+e8uS+ueHiQjnc2plvu+9pJUlStroy3xcO7V9ir6eJbmvaRpM1AAAAAI8thPCktPNNcQEAGVWz4wMY9/uhHx2H1vrh8ed5cgEAAAAAAAAAAACQRebbwXw7AAAAbWTvqPacXJRc7mAFNUO5OPlVuh7PT1uaLs+p7lAA/mDarLVD/lY2rvf0xG13oNu7eme59lIbdV73YEOfMRuLc33ukurWPrMPCjfc/C0jM3X26zvvCrOWH2WN1aGXHH+KBfUoVjz/NdaHJEnapWbGSVhSWR5OKA6H83qicH1Xd9t9bytJkrLRR7oHwoLKCns8TfDsYfXdU0ZGnmLCBgAAAOChQghT095lggsAyLCaXR/AuN8R/eg4tJb70xJPLwAAAAAAAAAAAACyxnw7mG8HAACg7Zz8pFxUfWNHlDzocAU1zSEXUfLdjqj6lr2jpOQeBWDa0Gifv4+N6/Te2W13kNutnflQHBx1/aU2afHAirC5gc+YU/rm+Nwl1a0zzv2IUZkJcMyGt1tfdeqrN9xqQT3M7b+8I8wYWmt9SJKkPWpmlIQlleXh2NKCcG5PHK7Ld7fd97iSJKl125R2et/sUIr832Q1gUXJpc8p1Z5hygYAAADgf4QQpqadY4ILAMi4mp0fwLjfE/3oOLSe+9JGPcEAAAAAAAAAAAAAyBLz7WC+HQAAgDY1PU4W5eLqjx2uoCZsU9rGmbMP6nKnArSnaUOjM/09bFwbi3Pb8iC3V/QvcP2lNuq9vVHDni9v75vtM5dUl1a/8MTwwAMPGpOps8uv+qr1VadWPv94C+pRfOgTn7M+JElS3ZsRJ2FBZUU4prQg/HNvHL6S723L73UlSVJr9dWunrC+f+H2vYw9nSaiXFS9KTe7OsOkDQAAANDuQghT0842vQUAtIGa3R/AuN8V/eg4tO4Pj6/2FAMAAAAAAAAAAAAgK8y3g/l2AAAA2ti0odG/ysXJvzlcQc1ZsiX995qOKDlu76j2HHcsQPvIzVn7bH8HG9cJxeG2PMDtE91l119qo4YHV4bbOvMNeb6c1TvLZy5pj+sePjR874c/MR5TZ7/69W9CtPRF1lid+vi/fcGiehQvOf4U6+P/Z+/Oo+Qsy4T/B7d5dcaZ9x0XSFUSSO/d6eWpdBZIAklIgIR0P9UsJYsmAkpQAQFBEZAhisqiIEsGQVEjQtwYUVF03BDCuDAggkZ0XBBEQQYF2SEh1+9JxvGHmJDqTlX1Up/POd+T+W/OKe66667qy+eWJEk1aVr34jh0ytw4p21aXN/YWpe/80qSpNHR1U0dsahroTOcqlIuKf42150WTNsAAAAA9SwizjK5BQDUiZLTH0DZ3xU9dBxGr8ey5tvJAAAAAAAAAAAAABgLzLeD+XYAAADYLp+kx+SS9CkXLGjElqTrs3+/nv277BUdpX/wtgUY23acO/f/+PyrXcun7Fq3l7fN6t7LGpDqqItaCzXZWz6Y/f/xekva1j71hW8Yi6mC5W89y/qqUFP3PDSeemqdRfUsTz75VLTOPtAakSRJw9K07sWxvGPXuLC1N25obKnb330lSdLIbVVLEoWevZ3dVIXSh/M96RITNwAAAEA9ioh3m9wCAOpIyQkQoOzvix46DqPbo1mz7WYAAAAAAAAAAAAAjHbm28F8OwAAAGySS4qz8knxTpcraMSXFB/KFYofnzC1uNe4Uun53r0AY1M+Sdf73KtNB3XOq9tL205rm2kNSHXUjJ7FsbYGe8ulLYnXW9I2dfgJZxqHqYLPffnb1lcFW/nRKy2qzbj2P262PiRJ0ohpWvfiWN6xa1zSUogbG5vr9ndgSZI0srq1oSlOat85JiepM5sqPVe4Lj91YLmJGwAAAKCeRMTRprYAgDpTcgoEKPs7o4eOw+j3QFZiRwMAAAAAAAAAAABgNDPfDubbAQAA4C8aekv/lCsUP+uCBY2WcoX0D7kkvWR878CcbAlv510MMHbkk+JDPutqU1/Xwrq9sO0/GltjksvapLrqgtapVd9bLm/p8VpLGnJT9zw0/vjgQ0ZhKuz3//3HmDLv1dZYhWra5VXW6RacfMbF1ogkSRqRTSykMa97rzimY3Z8rCWJmxua6/Z3YUmSNDL6VmNb7NO5u7OaqjBTWDx/3LjTnmfyBgAAABjrImJZ1gZTWwBAnSk5CQKU/b3RQ8dhjPzPI7Na7GoAAAAAAAAAAAAAjFbm28F8OwAAADzbdvkkPSZXSJ90wYJGVUn661ySnpnrHvAjCcAYkEuK9/h8q01zu/es68vaBjoXWAdSHTW1Z3H8aHJjVfeVTzd3ea0lDakJUwfiWzfcbASmCpa9+XRrrIKd9N4PWlRbsPOSw60RSZI0KpqUpDG/e884vn1WXNHcHbc1NNb178SSJGn4WtWSRG/PYmc0VbRcUvy38b19LzF9AwAAAIxVEVHMWmdiCwCoQyWnQYCyvzt66DiMHb/MGm9nAwAAAAAAAAAAAGA0Mt8O5tsBAABgsyYkfdPzheKvXLCgUXopxvfySfrmV3b2b+/dDDA6ZXv5z32m1aZCz951fUnbRa0F60Cqs97TPqOq+8pVzZ1eZ0lD6rT3XWr0pQpWX/V166uC7Th937jz7nstrM34yX/dYY1IkqRRW0PSH2nXgljRPjO+2DQlfjK5sa5/N5YkSbXt1oamOKl959ipkDqbqXIl6Xd2SEqvMIEDAAAAjDURsXvW4ya2AIA6VXIiBCj7+6OHjsPY8qOsf7a7AQAAAAAAAAAAADDamG8H8+0AAACwRTv2FP9vLkmvdMGCRvHFGOtzSfEr2f+99BUdpX/wrgYYPXKF9Ic+y2rTxovJbq/jC9pua2iM1qTPWpDqqI7sPX9zQ1PV9pUvNU3xOksadLuXjo4nnnzS2EuF3fP7+6N9t4OtsQp2wrtWWlhbcN6HP22NSJKkMfX7ycGd8+KMtunxxaYpdfv7sSRJqm3fbGyLYufuzmOqWLmk+POJvQONpnAAAACAsSIiZmY9bFoLAKhjJadCgLK/Q3roOIw93836ezscAAAAAAAAAAAAAKOJ+XYw3w4AAABblU/SZbkkfcwlCxrlF2Q8nq3lq7NKHR2lF3lnA4xsuUJ6rc+v2nVTQ3NdX852RMeu1oFUZ53UvkvV9pSvNbV7jSUNqskz94+1P7vDuEuFbdiwIQ5+0wprrILtOH3fuPPuey2uLVj4qmOsE0mSNGbr6tk7Du6cF+e0TYsbGlvq+vdkSZJU/Va1JFHIzh/OYapISXp/rjCwi0kcAAAAYLSLiKas35vUAgDqXMnJEKDs75EeOg5j0zVZL7DLAQAAAAAAAAAAADBamG8H8+0AAABQllx3WsgViv/lkgWNhbK1/Mdckl6WtTBb3tt5hwOMwLNHUvycz6za9e9NHXV9KdvnmjutA6nOair0x3erdAH09Y2tXmNJg+riyz5vzKUKVn36Guurwp3wzgstrC345a9/a41IkqS6aULWvO694oSOWfGp5q748eTGuv59WZIkVacfTG6KYzpmxyTnL1WmR/LJwGLTOAAAAMBoFRGvyPq5SS0AgCg5HQKU/V3SQ8dh7PpElmdmAQAAAAAAAAAAADAqmG8H8+0AAABQtpe1pi/NFdIrXLCgMVWS3pUrFM/PdacF73KAkSNfSC/1OVW7Pt3cVfeXsu3SvchakOqsIzvmVGU/uamh2esrqez2fd3J8fTTG4y4VNidd98brbMPtMYq2I7T9930urJ551/6GetEkiTVbQ1Jf6RdC2JF+8z4YtOUuv+tWZIkVbavN7ZvOms4d2nb5wSL6yYkxdebyAEAAABGm4h4adbNprQAADYpOSEClP190kPHYWxbYacDAAAAAAAAAAAAYDQw3w7m2wEAAGDQ8km6LJ8UH3XRgsZga7NWbN/dP9k7HWCYzxuF9H0+l2rXRa2Fur+M7V/adrYWpDprUiGNbzW2VXw/WZvl9ZVUTu27HRx333Of0ZYKe/rpDbHf60+2xircCe+80OJ6DnsddJx1IkmS9Oem9SyON3TsGpe2JnFzQ1Pd//YsSZK2vduzzmvtjfaePuctbWsbNs4HmsoBAAAARouIeGHWV01oAQD8RckpEaDs75QeOg5j35vsdgAAAAAAAAAAAACMdObbwXw7AAAADMkOhYH2XCH9kUsWNDZLn87+vSGfpMeM7+17uXc8QO3lk+LJPo9q13vaZ9T9RWxrGlpjUpJaD1KdtbRzblX2lMn2E0ll9PmvXm+kpQou+cTnra8Kt+P0fePOu++1uLZg42tjnUiSJG2+jb+5zu/eM45vnxVXNHfH2jr/HVqSJG1bNzU0x/KOXWOCc5a2taR44bhxpz3PdA4AAAAwkkXEdlkfNaEFAPBXSk6KAGV/r/TQcRj71mcN2PEAAAAAAAAAAAAAGMnMt4P5dgAAABiyCTuXXpxL0ktcsqCxXK5QfCKfpFdnLRvf2/cS73yA2sgV0jf4HKpdJ3TMcglb1n6d860Hqc7aeOni55o7K76fdCR9Xl9Jz9kxp55nnKUKfn7Hb6Jx55I1VuHeevq/WlzPYeVHr7ROJEmSymzjbyZLp8yLC1qnxncbWvwuLUmShtQnm7tiRs9i5ytt21xgUvzcxhlYEzoAAADASBURp5vOAgD4GyUnRYCyv1d66DjUh0eyptv1AAAAAAAAAAAAABipzLeD+XYAAADYZvkkXZYvpA+7aEFj/yKN9MGsy3KFYv+4uXNf4N0PUD3ZXnuAz57addiU3Vy+lrWqJbEepDpsj6494vYK7ye9LnKU9Bzt0rc8HnrkUaMsFbZu/froW/pWa6zCtcw+IH7/33+0wJ7D4oPfYq1IkiQNsVk9i+L49llxRXN3rPUbtSRJGkRrJzfGivaZsVMhda7S0EvS7+SmD7zMlA4AAAAw0kTEa01mAQBsVslpEaDs75YeOg71456sSXY+AAAAAAAAAAAAAEYi8+1gvh0AAAAqYofCQHsuSW9z0YLqpVwh/U3279n5ZJ8eOwBA5Y1P+vfweVO7BjoXuHht48VrDY0xtWexNSHVYZe2JhXdT+Z07+V1lbTZJvXuE9+/5SdGWKrggks/a41VoY2vK1t25933xoSpA9aKJElSBWrv6YuDO+fFOW3T4ruNLX6zliRJZfXNxrbo71rgPKWhzwEm6W0TepbkTeoAAAAAI0VEzMl6wnQWAMBmlZwYAcr+fumh41Bf1mb9k90PAAAAAAAAAAAAgJHGfDuYbwcAAICK2XHu3P+TKxTPd9GC6rC1WSsmFPqb7AQAlTGxkE7z+VK7Zvfs5cK1P/eO9pnWhFSHTeteHD+e3FixvWSPrj28rpI221krLze6UgU/++Vd0TCzZI1V+vNx0WHx2OPuZnku517yKWtFkiSpCk0spDG/e884vn1WXNnUGbf77VqSJD1HG88KF7b2RkfS5yylIZVLir/NF/q7TesAAAAAwy0iJmfdZzILAGCLSk6NAGV/x/TQcag/X8l6vh0QAAAAAAAAAAAAgJHEfDuYbwcAAICKyxeK++UK6QMuW1BdlqQ3ZR2zffc+r7QbAAzdpGn7NvhcqV3NSb/L1v7cdxtbYlIhtS6kOuyMtukV20vSrgVeU0l/06KD3hJPPbXO2EqFrVu/Pha/+nhrrApd9ZXrLbCt2G2fN1krkiRJNWhKsiQO7pwXF7b2xk0NzX7LliRJm+0/G1pieceuMcH5SUMoVyj+cfzU4q4mdgAAAIDhEhH/mPVjU1kAAM+p5OQIUPb3TA8dh/r0ATsgAAAAAAAAAAAAACOJ+XYw3w4AAABVsX1PcadcUvyeyxZUtyXp+uzfr2f/LntFR+kf7AoAgzOpa8n/83lS21xE+v93UOc8a0Kqw1qTvk2XLVZiHzmgc77XVNJf1bTLq+IXd9xtXKUK3v/B1dZYFepb+tbYsGGDBfYcbr7tp9aKJEnSMDSpkMaSroXx7rYZ8a3GNr9pS5Kkv+mK5u6Y1rPY2UmDLlcoPpGbOvAqUzsAAABArUXEC7O+bioLAGCrSk6PAGV/1/TQcahfb7ILAgAAAAAAAAAAADBSmG8H8+0AAABQNU1Ni/4uVyie77IF1f1lG0n6WPbvZ7L3Q39v7/IX2h0AynHa8/JJut7nSO26pqnDBWvPuGTNmpDqs2M7ZlVkHzl0ylyvp6S/6rLPfsWYShX86PZfxo7T97XGKtyEqQPx/Vt+YoFtxclnXGy9SJIkjYCmdS+OozvmbPpdd+3kRr9xS5KkTd3a0BTHt8+KSUnqzKTBlaTrc0nR//ASAAAAqKmI+JCJLACAspScHgHK/q7poeNQv9Zl7WEnBAAAAAAAAAAAAGAkMN8O5tvthAAAAFRdvlDcL1dIH3DhglSMXFK8J1conjch6ZtudwB4btn54Q8+O2rXx1oSl6v9uduzZvYssi6kOmynQhrXNrVt8z5yZMccr6ekv/TaN58eGzZsMKZSYU8++VTsXjraGqtCb3r7+y2wrXjqqXXROe811oskSdIIq72nLw7unBcXtvbGzQ3Nfu+WJElxVXNnzPK3Xw2lpHj6uHHjtjO9AwAAAFRbRLzZRBYAQNlKTpAAZX/f9NBxqG9/ymq3GwIAAAAAAAAAAAAw3My3g/l28+0AAADUxPjevkn5JP2OyxakZ168kf46l6Rn5roHWuwSAH8rnxRv93lRu85sm+5StWf0rraZ1oVUpx0wZf427yFvb9/FaylpU927L4377v+j8ZQqeM95q6yxKtQ256D43b33W2Bb8dVrv2e9SJIkjfAmZS3qWhgr2mfGNxrb/e4tSVIdt3Zy46YzwU6F1DlJgypXKH68t3f5C03wAAAAANUSEXOynjSRBQBQtpJTJEDZ3zk9dBy4Peuf7IgAAAAAAAAAAAAADCfz7YD5dgAAAGpn7twX5AvFFflC+rQLF6S/aW3WiTtO33sHmwXA/8gV0mt9PtSu49tnuVDtGd3Y2ByTE5eqSfXa5c0927SHnN42w+soaVNfu+5GYylVcNOtP41JvftYY1Vo1aevscDKcPgJZ1ovkiRJo6xZPYs2/Q5+ZVNn/GRyo9/BJUmqw77a2BELu/ZwNtJg+9rLWtOXmuIBAAAAKi0idsy6zzQWAMCglJwkAcr+3umh48BGn896nl0RAAAAAAAAAAAAgOFivh0w3w4AAEDN5QppmvUHly1Imykprsslxa9k//fSV3SU/sGOAdSzbE/8pM+G2rW0c66L1J7Va6fsZm1Iddrs7kWxdhsuVz6vtdfrKClOeu8HjaNUwWOPPxG7DrzRGqtCfUvfGk8/vcEi24oHHnw4Js/c35qRJEkaxXX17B1HdOwan2jpjh9vw29AkiRp9LW2oTHe3TYjGpJ+5yKVXS4pfm+HpPQKkzwAAABApUTEi7NuMo0FADBoJadJgLK/e3roOPC/TrMrAgAAAAAAAAAAADBczLcD5tsBAAAYFrlpxYn5JF3jwgXpOS/jeDx7n1ydVeroKL3IzgHU3XkhST/g86B27dm9h0vUntWVTZ3WhlTHndk2fcj7x6WtiddQqvNmp2+IRx593ChKFZx69oetsSq004z94me/uNMCK8OHr/iiNSNJkjSGakj6Y//O+XFha2/c3NDkt3FJkuqkaxvbIu1a4DykQczypb/MJ0uaTfMAAAAA2yoitstabRILAGBISk6UAGV///TQceB/bcja384IAAAAAAAAAAAAwHAw3w6YbwcAAGD4zJ37gnyhuCJfSJ926YK0lUs5CsU/5pL0sqyF2btnOxsIUA+y/e9EnwG1qzNZ4vK0zTSney/rQ6rTWpO++H5D85D2jk81d3kNpTpux2n7xi0/+i9jKFVw4y0/iYm9A9ZZFXr/B93RUq75+x9tzUiSJI3RdiqksV/X7nFu67T4bkOL38glSRrj3Z618XO/JelzFlJ5M3xJ8Z58sk+PiR4AAABgW0TEiaawAACGrORECVD2908PHQee6aGsKXZHAAAAAAAAAAAAAGrNfDtgvh0AAIBhlysUF2y6bMClC1J5Jeld2fvm/Fx3WrCDAGP6jJD0v9a+X9tubmhyedqzOrNturUh1XFHdswZ0t7xpaYpXj+pjrvwI581flIFjz72eMxO32CNVaFdB94YTzz5pEVWhhtv+Yk1I0mSVCdNLKQxv3vPOKl95/h6Y7vfyyVJGsN9p7E1Sp3znYFUVrlC+sD4nv7ZpnoAAACAoYiIhVnrTWIBAAxZyakSoOzvoB46DjzbT7NeaocEAAAAAAAAAAAAoJbMtwPm2wEAABgRXtnZv32+UPyaSxekQbc2a8X23f2T7STAWDNhanEv+3xtu7qpw6Vpz+oHk5uiOem3PqQ6bVKSxjVD2Bu/3djm9ZPqtIFD3x7rn37a6EkVvO30f7XGqtCEqQNxw423WmBlOvZfzrduJEmS6rRZPYvi+PZZcWVTZ9zut3NJksZkl7QUoi1Z4uyjrZcUH51Q6F9ksgcAAAAYjIjYIeseU1gAANuk5GQJUPb3UA8dBzbn81nb2SUBAAAAAAAAAAAAqBXz7YD5dgAAAEaOUun5+UJxRT5J17t4QRps6dPZvzdk759jxvf2vdyGAowF+UJ/t/29tl3cOtVlaZvp8Cm7Wh9SHdfftWDQ+8ZNDc1eO6kOa9v1oLjrt783clIF3/7OLTFh6oB1VoVOPuNiC6xMDz38aDTt8irrRpIkSTGtZ3Ec2zErPtfcGbf7DV2SpDHV9Y2tUeza3Zm3QUcoAAAgAElEQVRHWy1XSJ/MTR14lekeAAAAoBwR8YKsNaawAAC2WcnpEqDs76IeOg5syTF2SQAAAAAAAAAAAABqxXw7YL4dAACAESffk87PJenvXLwgDfXCjuIT+SS9OmvZ+N6+l9hVgNFq++59Xmlfr22ntu/sorTNdHVzh/Uh1XkXt04d1L7xk8mNMSlJvXZSnXXll641alIFDz38aMxY/HprrArN2/fIeOzxJyyyMn3s01+2biRJkvQ3Jcnesbxj11jVksRav6dLkjRmuqSlEK1Jn/OOnrskXZ/vSQ834QMAAABsTUR8wAQWAEBFlJwuAcr+Luqh48CWPJU1x04JAAAAAAAAAAAAQC2YbwfMtwMAADAi7ZCUXpFLil9x8YK0beUK6QO5JL0sVyj2jyuVnm93AUaX056X7WFP2c9r12FTdnNB2hZa3LXQGpHq/HLkWyY3DWrf6HDRolRXHX7CmcZMquTYfznfGqtCk2fuHz/+6a8ssEHY66DjrB1JkiQ9Zxt/Dzp0ytxY1ZLEWr+rS5I06vtOY2vs1znfOUdba8P4QvFtZnwAAACALYmIYtYGE1gAABVRcsIEKPv7qIeOA8/lnqwd7JYAAAAAAAAAAAAAVJv5dsB8OwAAACPYac/LJcVT80m63sULUgVK0ruyf8/OF/q77S/AaJGdBX5rD69de3Xv4XK0LXRpa2KNSHXe8e2zBrVv7NK9yOsm1UnTF70uHvzTw0ZMquBr191ojVWpD13+BQtsEH7wo59ZN5IkSRpU7T19ceiUubGqJYm1kxv9zi5J0ijuwtbeaE76nXH0nOUKxTPGjRu3nUkfAAAA4JkiojnrQRNYAAAVU3LKBCj7O6mHjgNb862s59sxAQAAAAAAAAAAAKgm8+2A+XYAAABGvAmFdLdcoXi3ixekirY2a8XE3oFGuwwwkuWT4s327NrVmSxxKdoW+snkxpjes9g6keq4SVlfaeooe99Y3LXQ6ybVQdn36rjhxluNllTBHx98KJKFh1hnVeigN54WGzZssMgG4ciT3m/tSJIkach1JH1x+JRd4/KWnlg7udFv7pIkjcKua2yLtGuBs4221qpxc+e+wLQPAAAAsFFEvDjLgCEAQGWVnDQByv5e6qHjQDneaccEAAAAAAAAAAAAoJrMtwPm2wEAABgVxvf2vTxXSL/s0gWpCiXpTVnHbN+9zyvtNsBIkysUv2Svrm03NzS5FG0LvbdtujUi1XmLuxbG7WXuGQdMme81k+qgM1d+wkhJlbzxxPdZY1Woa/7S+P1//9ECG4SNr9dOM/azfiRJklSR2pIl8bopu8XHm3ti7eRGv71LkjSK2vg3ojPbpkdD0u9co+covaqpadHfmfgBAAAAIuKDpq8AACqu5KQJUPb3Ug8dB8rxdNYCuyYAAAAAAAAAAAAA1WK+HTDfDgAAwGiyXa4nfWsuSZ9y8YJU+XKF9Ml8UvxCrlA8YMLOpRfbcoCRINubPmyPrm1XNXe6EG0L/WByU7QkfdaJVOdd1Fooa89Y3rGr10sa4y1ZekKsW7feSEkVfOVb37PGqtS/f/v7Ftggve+iK6wdSZIkVaXWpC8OnTI3VrUksXZyo9/hJUkaJV3b1BZ7de/hPKMtz+Elxa+M7+17iakfAAAAqF8Rsa/JKwCAqig5bQKU/d3UQ8eBct2d9XI7JwAAAAAAAAAAAADVYL4dMN8OAADAqDOxkE7LJekvXL4gVfNij/Sx7N/P5ArF/t7e5S+08wDDJZcUT7Uv17ZzW6e5CO05OrZjtnUi1XmdPUvi5obmre4Xb+3YxesljeGaZx0Qv/z1b42SVMF99z8Q3bsvtc6q0DvO+pAFNkhPPvlUJAtfa/1IkiSp6rUlS+LQKXNjVUsSaxsa/R4vSdIIb23WivaZsWMhdZbR5ufvCun3c9MHXmbyBwAAAOpPREzM+oPpKwCAqig5cQKU/f3UQ8eBwbgmazu7JwAAAAAAAAAAAACVZr4dMN8OAADAqPTPMxb9Yz4pftLlC1INStL7c0l6yfjegTnZ28+PQ0BNZXvQMntxbTumY7ZL0J6j6xrbYpJ1ItV9x5axV767bYbXShrDffoL3zRCUiWHn3CmNVaFioecGE89tc4CG6RPfeEb1o8kSZJqXk/Pkji6Y05c2dQZt/tdXpKkEd0XmqbELt2LnGG02XKF4o8nFtKc6R8AAACoHxHxgqwbTF4BAFRNyakToOzvqB46DgzWm+2eAAAAAAAAAAAAAFSa+XbAfDsAAACjWj5Jl+WT4qMuYJBqVJL+OpekZ+a6B1rsQEAtTEgG5tp/a1vatcDlZ1vpoM551opU503Kurqp4zn3igtbe71W0hjt8BPONDpSJVd+6VprrAoV9jgk7r3vDxbYECx+9fHWkCRJkob3PN+zdxzdMSeubOr0+7wkSSO02xoa4/j2WTGxkDq/aHP9amLvQKMJIAAAAKgPEfFuU1cAAFVVcuoEKPs7qoeOA4P1RFbBDgoAAAAAAAAAAABAJZlvB8y3AwAAMOrlk3168oXiT12+INW2XFL87vhC/1E7JKVX2ImAatm+p7iTPbe2dffs7eKzrfRvTZ3WiqTYvXvPWNvQuMW94vLmHq+TNAabsfj18eCfHjY6UgX33veHmDLv1dZZhWuYWYpbfvRfFtgQfO8Ha60hSZIkjaim9SyO49tnxb83dfitXpKkEdjq5u4o9Ozt3KK/nbMrFO/eIUk7TAEBAADA2BYRc7PWm7wCAKiqkpMnQNnfUz10HBiKn2e91C4KAAAAAAAAAAAAQKWYbwfMtwMAADAmvKKj9A+5QvHjLmCQhqGkuC57/31pQlI8eHxv30vsSEAl9fYuf2E+Sdfbb2vbjY3NLj3bSgu79rBWJMXZrdO3uE98tbHDaySNsSb17hPfu/nHRkaqZOnR77LOqtDqq75ucQ3R695yhjUkSZKkEdtu3XvGaW0z4/rGVr/ZS5I0grqpoTmWdc51XtFmZuzS+yf0DMwwCQQAAABjU0T836y7TF0BAFRdyekToOzvqh46DgzVh+2iAAAAAAAAAAAAAFSK+XbAfDsAAABjSj5Jl+UL6cMuYZCGp1ySPpb9+5lcodjf27v8hXYloBJyhfQ39tja9pnmLheebaWLWgvWiqRoSfrjhsaWze4TNzY2e42kMdbZ/3qFUZEqueLf/t0aq0Knnv1hi2uIfnHH3TGxd8A6kiRJ0ohvYiGNxV0L45y2aXFTQ7Pf7yVJGiFd0lKI1qTPeUXP7pHxPQN7mgQCAACAsSciPmnqCgCgJkpOnwBlf1f10HFgW+xnJwUAAAAAAAAAAACgEsy3A+bbAQAAGHNy3QMt+UJ6iwsYpGEuSe/PJekl43sH5mRvze3sTsBQZXvKDfbV2nZW63QXnW2ltVmFnr2tF0nxminzNrtP3J41OUm9RtIYafGrj49169YbE6mC3/zuvmibc5B1VuH2OfTt8dRT6yywIXrLaRdYR5IkSRp17VRIY//O+XFha2/8sKHJb/mSJA1z321siWLn7s4p+qtyhfTJfJLubxoIAAAAxo6IONjEFQBAzZScQAHK/r7qoePAtrgvawe7KQAAAAAAAAAAAADbynw7YL4dAACAMampadHf5QrF8/OF4gYXMUgjoKR4e/bvinyypNkOBQxWrpBeYS+tbW+cMsclZ2W0on2m9SJpU6taks3uE709i70+0hioZfYB8ctf/9aISBVs2LAhXrX8VOuswu3Stzz++w8PWmBDdM/v74+dZuxnLUmSJGl0f5dN+uLQKXM3/W611u/5kiQNW7dnndE2PXYspM4oesYsXbp+fFJ8nYkgAAAAGP0iIp/1B1NXAAA1U3IKBSj7O6uHjgPb6gt2UwAAAAAAAAAAAAC2lfl2wHw7AAAAY1q+0L9vrpA+4CIGacS0IeuGXFJ8U276wMvsUkA5coXie+2ftW2Prj1ccFZGNzU0R1Oh35qRFFN7FscPG5r+Zp/YuJ96faTR32e++E2jIVXy0U9+yRqrcF3zl8Yv7rjb4toG7zr3o9aSJEmSxlQ9PUvi6I45cWVTp9/2JUkapr7YNCVm9ixyNtGz5ujS40wFAQAAwOgVEdtlXWPiCgCgpkpOogBlf2/10HGgEl5vRwUAAAAAAAAAAABgW5hvB8y3AwAAMOaN7+2blC8Ub3AJgzTCStL12b9fz/5dtn33Hn9vtwK2JFdI32DfrG2TkzTWTm50uVkZHdkxx5qRtKkTOmb9zR5xYOc8r400ylv+1rOMhFTJnXffGy2zD7DOKljTLq+Km279qcW1DR548OFonX2g9SRJkqQx2+zuRXFS+87xrcY2v/FLklTjbm1oiqP9fVnPKpekZ5oMAgAAgNEpIt5s4goAoOZKTqIAZX9v9dBxoBIeyWq2qwIAAAAAAAAAAAAwVObbAfPtAAAA1IXe3uUvzCfpWflCcYOLGKQRWFL8U76QfiyXpAvHlUrPt2sBz5RPBhbbK2vfNU0dLjYro40Xj04spNaMpJiU7QXP3juPdDGiNKqbuffr408PPWIkpAqefnpD7Pu6k62zCrbj9H3j2v+42eLaRh/40KetJ43ZDjn+vDj8pIviwKPOisVLT4k5+xwTPQsPjZ1m7O/1kSSpDtv4u/biroVxbuu0uLmh2e/9kiTVsA+3FKItWeJMor+UK6TvMR0EAAAAo0tEtGU9ZuIKAKDmSk6jAGV/d/XQcaBSbsh6np0VAAAAAAAAAAAAgKEw3w6YbwcAAKCuTCj0L8oX0t+7iEEawZeEJMXfZu/T9+e604JdC9hohyTtsD/WvvNae11oVmav6tzdmpG0qbnde8baZ+wP/9K2s9dFGqVN6t0nvveDtUZBquSDH7/KOqtgE6YOxGe++E0Laxs99vgT0b37UmtKY7I9X/32WLl6zRZ7/0e/HqddcFUce/rH43VvuzBKbzwjFr3m5NileFRMmbcsJmafi15HSZLGbjsV0ti/c35c0lL4q9+2JElS9fpuY0sMdC5wFtEzZ+bOHTdu3HamhAAAAGDk2/iApaw1Jq4AAIZFyYkUoOzvrx46DlTScXZWAAAAAAAAAAAAAIbCfDtgvh0AAIC6M6l3n/G5pPhNFzFIo6K1+aR48g6FfXe0e0H92r57j7+3H9a+N02Z4zKzMruqudOakfSX3tU28y/7w/mtvV4TaZT2vouuMAJSJT+/4zfRuHPJOqtgl3zi8xZWBXz4ii9aTxqTNc8+MM7+yNdi5eo1Q+6CK66P91785Tjx7E/GEadcHAcceVYsXnpyzCoeHVPmLYuJvft4rSVJGiN19ewdR3fMiaubOvz+L0lSlbs964y26bFjIXUO0Z9LLxo3btx2JoUAAABgZIuI401bAQAMm5ITKUDZ3189dByopEezmu2uAAAAAAAAAAAAAAyW+XbAfDsAAAB16rTn5ZLiqfkkXe8iBmlUtCF7v16fnzqwfFLXkv9nD4P6k+0D99oLa9vCrj1cZDaIFnctsG4kbaoh6Y9vNbZt2hsub+nxmkijsP5lb4t169cbAamCja/rkqUnWGcV7D3nf9zCqoDHHn8ikoWHWFMak73pHR+KlavXVLULLr8u3nPxl+NtZ30yjjj5g3HAm86MPV799pi+9xuiedaB/jtIkjRKm9+9Z5zZNj2+39Ds7wCSJFWxLzZNiek9i50/9D8lxY+MK5Web1IIAAAARqaIaNk4bmTiCgBg2JScSgHK/g7roeNApf1H1vPssAAAAAAAAAAAAAAMhvl2wHw7AAAAdS3fm87MF4q/chmDNHrKFdIn80l6dday7bv3+Hs7GdTJZ3aSrrEH1rbJSRprJze6xKzMLmvpsW4k/aW+roVxe7Y3fLWxw+shjbJaZh8Qv7rzt0Y/quS8D3/aOqtgR51ybmzYsMHCqoCLVn3OmtKYbLf9jouVq9cMe+d94tp49we/FMecvipec+w5seS1p8bsgTfHlHnLYuLUAf+tJEka4U1K0ki7FsQlLYX4sb8bSJJUlX4wuSmWdc519tD/lKSf6u1d/kLTQgAAADCybHygUtZ1pq0AAIZVyckUoOzvsR46DlTDUXZYAAAAAAAAAAAAAAbDfDtgvh0AAIC6N7637+X5JL3aZQzS6CtXSB/IF9JL8z3FeePGnfY8OxqMXfmk+BH7Xu37UtMUF5gNonlde1k3kv7Sua3TNl2A6LWQRldXfulaIx9VsvZnd8ROM/azzirU0qPfFevWrbewKuCRRx+P7t2XWlcaczXMKMV7L7kmVq5eM6I7/7JvxztXfj6OedfHYumx58aSQ06NXdIjo3XOwf47SpI0AmtN+mJ5x65xZVOnvwtIklSFLmztjcak37lDkUvSKzs6Si8yMQQAAAAjR0QcY9oKAGDYlZxMAcr+Huuh40A1PJrVaJcFAAAAAAAAAAAAoFzm2wHz7QAAAPA/tssn6TG5QvqkCxmkUXqRSKF4d9b543sH5tjSYOzJPqffbq+rfee2TnNx2SC6qLVg3Uj6Sy1JX6xpaI22ZInXQxolHfG2s417VMm6detj8cFvsc4q1MChb49HH3vcwqqQCz/yWetKY7LD3rYyVq5eM6o7/7Jvx4oLroqjTrs0XnPsObHktafGzL43RcPMV/lvLEnSCGhWz6J4Z9uM+E5jq78RSJJUwb7a1B6ze/Zy3lDkCuk1E3YuvdjUEAAAAAy/iJic9bBpKwCAYVdyOgUo+7ush44D1fKtrO3stAAAAAAAAAAAAACUw3w7YL4dAAAAnmFiIZ2WS9JfuJBBGuUXiiTpbeMLxbflphUn2tlgbMgX+ve1v9W+w6fs6tKyQbS2oTFm9Cy2diT9pf0658e8bpceSqOhnZccHg89/KhRjyo5a+Xl1lmF6lv61nj4kccsqgp56JFHo3Pea6wtjb3Ptb43xYVXXB8rV68Zs5354a/GW8+8Ig5964WRHrYiZg8cHa1zDvbfX5KkYWhiIY20a0Fc0lKItZMb/b1AkqQKdFtDYxzdMcdZQxv72vjevpeYHAIAAIDhs/EBSn9+kBIAAMOv5IQKUPb3WQ8dB6rpcDstAAAAAAAAAAAAAOUw3w6YbwcAAIBneVlr+tJcIb3CZQzSWCh9Ovv3hnySHjO+t+/ldjgYvSb0FrvsabVvl+5FLiwbZO9rm2btSPqrWpI+r4M00i//7h2I7970YyMeVXLb7b+IHafva61VoD0OOCYeePBhi6qCzr3kU9aWxlyTsj13xYWfj5Wr19Rl53zsm3HKB66Mo067NA486qxYcODbomfhYTFx6oD1IUlSDersWRJHd8yJrzR1+JuBJEkV6NLWJFr9rUlJev0/z1j0j6aHAAAAYHhExCEmrQAARoySEypA2d9nPXQcqKYHs8bbbQEAAAAAAAAAAADYGvPtgPl2AAAA2IJ8T3p4LkkfcymDNDbKJcXHs/f0leN7igNNTYv+zi4Ho8uEnUsvzhfSp+1ntW1C1vcaWlxWNohua2iMrp69rR9JkkZR51z8SeMdVfLkk0/F7qWjrbMKtOvAG+O++x+wqCroTw89Eu27HWx9acx18JvfFytXr9GzOu+ya+PUD/xbvOGUS2K/I94du+53bLTPXWrNSJJUxeZ37xnntE2LWyY3+fuBJEnb0PWNrbFn9x7OF/Vekn6nobf0TyaIAAAAoLYi4mVZ95m2AgAYMUpOqQBlf6f10HGg2i632wIAAAAAAAAAAACwNebbAfPtAAAA8Bx2KAy055LirS5lkMZWuUL6QC5JL8taOG7cac+z28HokE+Kd9rDat9HWnpcVDbITm+bae1IkjRK2vs1J8S6deuNdlTJ6R/4mHVWgWb1HxH33vcHC6rCzrjwE9aXxlyFPV8fF1x+XaxcvUZlds6qb8QpH7gyjjjl4tjviPfE3P2Oi5Y5B1tPkiRVsOakPw6dMjeuaO6O2/0NQZKkIbU266T2nWNiIXW+qO9+ML637+UmiAAAAKB2IuJjJq0AAEaUklMqQNnfaT10HKiFve24AAAAAAAAAAAAADwX8+2A+XYAAADYivG9fS/JF9JLXcggjdGS4p25QvG9E3v6p9jxYGTL3rNft2/Vvrd0zHZJ2SD7YUNTdCZLrB9JkkZ4bXMOijvvvtdIR5XcdOtPY1LvPtbaNjZt0WHWaRX87t77o3HnkjWmMdXEbM99x7mfjZWr16gCnfnhr8bx7/1ELD3uA7HoNSdHYa/Xb3qNrTVJkrat2d2L4vS2GfG9hhZ/T5AkaQitau6J9p4+54o6LpcUb92+e59XmiICAACA6ouI3bI2mLYCABhRSk6qAGV/r/XQcaAW7sj6e7suAAAAAAAAAAAAAFtivh0w3w4AAABlyheK++UK6QMuZpDGdGuzVmzf3T/Zrgcj8bM4vcg+Vfv26NrD5WRD6LS2mdaPJEkjvM99+dvGOarkscefiDnFN1pn21jPgmXx8zt+Y0FVwXGnnW+Nacy1/xvPiJWr16iKXXD5dbHigqviiFMujv2OeE/M3e+4aJl9kPUnSdIQmpSkkXYtiEtaCrHW3xQkSRpU1ze2bvo7vjNFXffTCT1L8iaJAAAAoHoi4kVZPzFpBQAw4pScVgHK/m7roeNArbzbrgsAAAAAAAAAAADAlphvB8y3AwAAwCBMKPQ35ZP0JpcySGO99Onsvf6NXCE99J9nLPpHux+MDPmpxWPtT8NwsWUhjVsbmlxONsh+mL1mHUmfNSRJ0gjtqFPONcZRRe8460PW2TbWs2BZ/OwXd1pMVXD7z38dk3r3sc40tvaMhYfGeZ+4NlauXqNh6L0XfzmOOX1VHHT02bHgwLfGlPmvtS4lSRpESbJ3vL19l7i+sdXfFyRJKrMfT26MozrmOEvUcbmk+PPxvX2TTBMBAABAdUTECpNWAAAjUslpFaDs77YeOg7UyrqsHjsvAAAAAAAAAAAAAJtjvh0w3w4AAACD1Nu7/IX5QnFFvpA+7XIGqS4uIHk8n6RXZ5U6OkovsgvC8Mn3pEvsS8PTZ5q7XUw2hE5p39n6kSRpBLZL3/J46JFHjXFUyQ033hoTpg5Ya9tQz4Jl8dOf32kxVcmrj3yndaYx1cY99+3v+1SsXL1GI6hzVn0jTsz+uxxy/Hmx12tOip6Fh/l8lCRpK00spJF2LYhLWgqx1t8YJEkqq0tbkmhN+pwl6rWkeOeEQn+TiSIAAACorIhoynrCpBUAwIhUcmIFKPv7rYeOA7V0XdZ2dl8AAAAAAAAAAAAAns18O2C+HQAAAIYoVyj255P0fpczSPVTrpA+kEvSy7IWZtuAH7qg1p+93QMt9qLh6dT2nV1INoRubmh2gZkkSSOsHaftG//5w9uNb1TJo489HrP6j7DWtqFk4WvjZ7+402Kqkv+48TbrTGOufY94d6xcvUajoHNWfTNOfN+n4pDjz4u9XnNS9Cw8LCZMHbCOJUnaTF09e8fx7bPi241t/t4gSdJW+mb2eblb957OEPU6z5YU75nY0z/FVBEAAABUTkR8yaQVAMCIVXJiBSj7+62HjgO1drDdFwAAAAAAAAAAAIBnM98OmG8HAACAbZCbVpyYT9I1LmeQ6rJf5ZPi6TsUBtrthlAbvb3LX5hL0qfsP7Uv7VrgMrIhdlL7LtaQJEkjqHMu/qSxjSo64V0rrbNtKFl4SPzsl3dZSFXy9NMbYtFBb7HWNKbqWnBInHfZtbFy9RqN0s5d9a048exPxrK3nBd7HnxidM4/xNqWJOkZTSykm/5GcUlLIdb6m4MkSVvstobGOLpjjvNDnZZLivdM6N6n02QRAAAAbLuI6DdpBQAwopWcWgHK/o7roeNArd2T9Y92YAAAAAAAAAAAAACeyXw7YL4dAAAAttXcuS/IJ8V35wvp0y5okOq0JL0p2wOOm9S7z3ibIlRX9p5ba9+pfZOTNG5taHIZ2RC6qaE5WpM+60iSpBHQwKFvj/VPP21so0qu++4tMWHqgLU2xKYtOizuuOt3FlIV/duXr7XWNKbauOee+L5PxcrVazTGet9HvxZvec9lceDRZ8fc/Y6LljkHW/OSJGV19+wdx7fPiusa2/z9QZKkLXRha280Jv3ODnU5v1b871x3WjBZBAAAAEMXEX+X9TOTVgAAI1rJyRWg7O+5HjoODIez7MAAAAAAAAAAAAAAPJP5dsB8OwAAAFRILkkX5pLiPS5okOr5cpJ0fb6Q/nv277KXtaYvtTNC5WXvr0/bb4anK5q7XUI2xE5sn2UNSZI0zLXtelDc9dvfG9eokocefjSmL3qdtTbENr52d9z1Owupih559PHo3esw601jquLr3xkrV69RnfSei78cR532kdjviHfHLumR0TCj5H0gSarbJhbSSLsWxCUthVjrbxCSJP1NX2tqj1k9i5wb6rBcofjHCT0DM0wXAQAAwNBExKkmrQAARrySkytA2d9zPXQcGA5PZrXZhQEAAAAAAAAAAAD4X+bbAfPtAAAAUEE7JKVX5ArpNS5okJRLio/nk/TqrFJHR+lFdkiojOy9dao9Zng6oWOWC8iG2E0NzdGa9FlHkiQNY1ddc51RjSo6+pRzrbMhNmPx6+PXv7nHIqqy95z/cetNY6op85bFuau+FStXr1GddsEV18eKC66KI065OJa89tToWXhYTJg64P0hSaq7pvYsjne0z4zvNLb6e4QkSc/oB5Ob4uDOec4LdTmzlj44oWdghgkjAAAAGJyImJj1iEkrAIARr+T0ClD2d10PHQeGy9ftwgAAAAAAAAAAAAD8L/PtgPl2AAAAqLzt8kl6TC5Jn3JJg6RNl5UUin/M9oTLshZu3CNskzB0E6am+9hXhqf53Xu6fGwbOrl9Z+tIkqRh6s3v+IARjSr66rXfs86G2C59y+Ou3/7eIqqyO+76XUyeub81pzHThKkDccIZl8fK1Wukv+qcVd/YtDYOPOqsmLvfcdE46wDvGUlS3TQp64DO+bG6uTtu9zcJSZI2tfEz8V1tMzd9TpStI/sAACAASURBVDov1NmsWpI+OKFnYIYpIwAAAChfRFxp0goAYFQoOb0ClP1d10PHgeG0j50YAAAAAAAAAAAAgI3MtwPm2wEAAKBKcklxVj4p3umSBknPurTkF9m/78x1D7TYKWHwJhT6m+wlw9PEQhrfb2h2+dgQu2VyU0xJllhLkiTVuF36lsdDjzxqPKNK/vDAnyJZeIi1NoTm7Xtk3PP7+y2iGnjNUe+05jSmSg87LVauXiNttQuuuD7+5fzPxetOXBmLlp4S3QsO9R6SJNVFM3oWx4r2mfGfDS3+PiH9f+zdeXicZb34f9Dj8fj16+8sHg90krY2SZM2bZNnkpYdSqFAS5uZtDDs+1JAoYgogoDgwQXQgtiAgCCINIiVg4JLWWRpKjuyliIiCrLveyk0+XwHfp5NQdI2k8w883pd1/vqn+dczJ37fuZ6Ps4tScV+NHpCjG/1rrrqZtSy+eeHtXW2mzQCAACA9xcRU0xZAQBUjIInWIB+f9/1o+PAUHqo2IftxgAAAAAAAAAAAACYbwfMtwMAAEAJjZgw459rsrlLXdIg6d0vL8ndXJPk5v7b+I517JjQX8d9oCbJv2YPGZrOasy6dGwNevsST+tIkqTBa+TE2XHbXfcbzSihA4842Vpbjabveng898JLFtAguOK6m605papxm+8R887/VXR190ir1UnfXRQHH3du5Pf7crRts3/UtnX625IkpbaGbEfMad40ft4wzjsKSVLVt6S+MbaasJVnhKqbTcs/P6x9ZptZIwAAAHhvEfGBYreZtAIAqBgFT7EA/f7O60fHgaF2hN0YAAAAAAAAAAAAAPPtgPl2AAAAGAQ1SW6PTJJ73UUNkt61JLey+O+SmrbOOR9vyn3Mrgl/WybJ32rvGJrevnzShWOr3511DTE+mWEtSZI0SJ169sVGMkroJ4sWW2er0fb7Hx2vvPq6BTQIVqx4MzbJH2TdKTXVtnXGESd2R1d3jzRgnXL+NfG5r18YOx18UmzcOTdGTJrt702SlMqmtGwd85vaY+moeu8rJElV29Jih4/dyLNBlZXJ5l6oTWZOMm0EAAAA7y4i9jJpBQBQUQqeYgH6/Z3Xj44DQ+3lYuvYkQEAAAAAAAAAAACqm/l2wHw7AAAADJLhrR3jMtn8vS5qkPQ3LzJJ8suL//6ouF90tLfP+ZDdE/5aTTZ3nv1iaJrYOt1lY2vYV8euZy1JkjQIzdr7yFjZ22sko0Seff6laN1yD2ttFdvr0K/EGytWWECD5JSzfmjdKV1n2/4nRFd3j1TSTv3+NfGFb/wwdvvMvJi83WFRt0HB358kKVWNb50Rh4/dKBbXN3lnIUmq2rqa2qIu6fBsUE3zaNncC8OzuYkmjgAAAOB/i4iPFHvEpBUAQEUpeJIF6Pf3Xj86DpSDLjsyAAAAAAAAAAAAQHUz3w6YbwcAAIBB9PGm3McySe4HLmqQ1M+ezGTzp9W2dq5nB4X/lknyh9sfhq4rGppdNLYG3V1XH0myrbUkSVIJG7vZLvGnx582ilFC+x1+orW2ih1y9Cnx1sqVFs8geeSxp6Jhwx2sPaWmli33iW9dcG10dfdIg9q3L7w+jpp3cez+mVNi8+0/G/Ub7uhvUpKUioZnc7H9+CmxYHRLLPPuQpJUhf2sYVxMbJnuuaCaSnLPZlrziakjAAAA+G8RcZxJKwCAilPwJAvQ7++9fnQcKAdv/48qx9mVAQAAAAAAAAAAAKqX+XbAfDsAAAAMgZokt0dNNveKyxokrcLFJn/MJLkTa5IZo+2iVLvatvw29oWh6/ix67tkbA07qWmStSRJUgm79JeLjWGU0MU//ZV1tood/fWzore3z+IZRHvOPcHaU2oa3j4rjp63MLq6e6Sy6Cvf+Vnsd+Tpsc1uR0Xz5N39nUqSKr71W6e98+7jtrrR3mFIkqqqW+saIz9+C88DVVQmm39+WFtnu8kjAAAAeOeH19Yp9rJJKwCAilPwNAvQ7+++fnQcKBc/sysDAAAAAAAAAAAAVC/z7YD5dgAAABgi62Y7x2aS3N0ua5C0yiW5GzJtuU+vmxQ+YTelGg3P5jL2gqFrm5atXDC2hi0dVR+TWqdbT5IklaBDj/2W8YsSevzJZ2PsZrtYa/2stq0zvn3OQgtnkP3Hz6+z/pSqdvjUidHV3SOVbSecflnM+eJ3YvruX4xxm+/h71aSVLGNTjri082bxFX1Y73LkCRVz7vruvr4fPOGUetZoIrmzvLP1GQ7WkwfAQAAUO0i4lyTVgAAFangaRag3999/eg4UE62tjMDAAAAAAAAAAAAVCfz7YD5dgAAABhCIydP/odMNn+ayxokrd4lJ7mVxX+vKv67xyeaC//Xrko1Ka77Z+0DQ9PwbC5urGt0wdgadkZjm/UkSdIAt+HMOfHyq68ZvSiRvr6+2O3gL1tr/eyT620Xl/z8WgtnkD3/4svRuuUe1qBSU9s2+8e3f3BddHX3SBXTid9dFAcfd07M2PPYGDt5d3/LkqSKq7ZYbsKWcX5jEsu8z5AkVUnnFc+9xqTDs0DVlHu6tj0/wfQRAAAA1SoixhVbadoKAKAiFTzRAvT7+68fHQfKyR3FPmB3BgAAAAAAAAAAAKg+5tsB8+0AAABQBmrbcrMy2fzzLmuQtLplktzrxX9/VNxLOtaaPPnv7KykXSbJX+9vf+j6VlO7i8XWsLcv4tx8wjbWkyRJA9TIibPjtrvuN3ZRQj/48SJrrZ81bbxTXPvr2y2aIXDosd+yBpWaRkyaHV867T+iq7tHqui+8p2fxX5Hnh5b7nRENGy4k79vSVJFNal1enx9zKS4Y1SDdxuSpNT3y4bmmNgy3TNA1ZR7urY9P8EEEgAAANUoIn5q0goAoGIVPNEC9Pv7rx8dB8rNTnZnAAAAAAAAAAAAgOpjvh0w3w4AAABlYp2WjlGZbO5mlzVIWtMySe7xTJI/ZVj7zDa7K2lVk+S7/L0PXTuOm+JSsQHowsZW60mSpAHqtHN+ZNyihB557Klo2ngna60ftW29d9x7/0MWzRC4/sY7orat0zpUatr10G9GV3ePlKrmL1gcx556Sex+2Kmx2XaHxaj1t/f3LkmqiBqTjjikeZO4rn6M9xuSpFR3a11j5CZs6fyvmnJPDW/tGGcKCQAAgGoSEesV6zNtBQBQsQqeagH6/R3Yj44D5eaBYh+yQwMAAAAAAAAAAABUF/PtgPl2AAAAKCPt7XM+VJPNfbMmm+9zYYOkAWppTdJx1LD2mSPssqRJbZLfz9/30FWXdMRddQ0uFRuAOlxIJknSGjd73y/Gyt5e4xYl0tvbF9vvf7S11o+2KBwSjz35jEUzBF5f/kZs1HGAdajUtN6Mg+LbCxZHV3ePlOq+feH1ceQ3fhg7fvrEd9b98LZOe4Akqawbns3F9uOnxILRLbHMOw5JUkpbWlcfh4/dyNlfPT25bpJrNokEAABAtYiIa0xbAQBUtIKnWoB+fwf2o+NAOTrADg0AAAAAAAAAAABQXcy3A+bbAQAAoAzVJPlta7K5p13YIGngyvVmsrnrapP8fiNb8/9kp6XSZVpyWX/XQ9v5o1tdKDYA/bRhXNRaT5IkrXZjN9slHn3iaWMWJXTOgsustX604wHHxsuvvGbBDJGvfOt861Cp6ZPrbR8nnH5ZdHX3SFXXvPOujkO+fG7M3Pu4GDdlT3uCJKms26xl65g3ZmLcVdfgfYckKZWd0dgWdUmHc786enLdJNdsGgkAAIC0i4hpJq0AACpewZMtQL+/B/vRcaAcPV7s/9ilAQAAAAAAAAAAAKqH+XbAfDsAAACUqdrWGTWZbO46FzZIGugySX55JptfOCzpyDc3F/7ejkslenvtFtfxG/6mh645zZu6SGyA2nn85taUJEmr2WVXLjFiUUK//+Nj0bDhDtba+/S5L8+Pt95aacEMkd/c89sYOXG2tajUtM8RXdHV3SOp2FfOuDz2PWJ+bLHD56NuA88kkqTybFwyIw4fu1Esrm/yzkOSlLoub2iObOu2zvzqmCd7Yt1s51gTSQAAAKRVRKxd7HbTVgAAFa/g6Rag39+F/eg4UK6OsEsDAAAAAAAAAAAAVA/z7YD5dgAAAChnhcIHa7L542uS3EoXN0gqyYUo2dxzNdncGcNaOzYu7jpr23ipJJls/hZ/x0NXczIzlo6qd5HYAHR1/dgYYU1JkrTKHXbcaUYrSqi3ty9m73OUtfY3GtE+K04/7xKLZQi99vry2CR/kPWo1DR5u8Ni/oLF0dXdI+kv+nbxb+Oob14cO376pJi47QFR29Zp35AklVUjs7nYffzk+EnDeO8+JEmp6ob6pthqwlbO+2qYI0vyTwxrnznGRBIAAABpFBE7mrYCAEiFgqdbgH5/F/aj40C5eqHYP9upAQAAAAAAAAAAAKqD+XbAfDsAAABUgNqkc3Imm3/UxQ2SSlqSeyST5E7MTMg12XmpBDVJ/jv+doe2HzS2uERsgDqweVNrSpKkVWijjgPilVdfN1pRQqefd4m19jdq2ninuPL6WyyUIXbkV79jPSo1jS7uKyd9d1F0dfdI6kcnn3tlHHzcObHNbkdF/YY72kckSWXVlJatY35Teyytq/cORJKUiu4ZVR/7j/NOu0p6ct0k12wqCQAAgDSJiA8Wu9+0FQBAKhQ84QL0+/uwHx0Hytm/26kBAAAAAAAAAAAAqoP5dsB8OwAAAFSIYe0z/zWTzf/MpQ2SBqmlxb7wb+M71rEDU65qk/x+/laHtn3GbeYCsQHqprrGaExmWleSJPWjkRNnx+13u9+ilB546E9Rt37BenuPNuo4IH774MMWyhC77oY7orat05pUajr0hPOjq7tH0mr07QWL4+hTfxw7HXxSrLftAc4HSVLZNLFlenx9zKS4s67BuxBJUiqaN2ZijHDGV0NPrpvkmk0mAQAAkBYRsZtpKwCA1Ch4wgXo9/dhPzoOlLOXiv2L3RoAAAAAAAAAAAAg/cy3A+bbAQAAoLKsXZPkDs1kcytc3CBpUEpyK4v/XlX8d49PNBf+r22YcpJpyWX9nQ5tjUlH3F1X7/KwAeq4MetbV5Ik9aP55y40TlFCb61cGdvu9jlr7T2atfeR8ezzL1koQ+y5F16K7FZ7WZNKTR17fym6unskrWFnXvzreOq5V+LpZ1+IhZdfEwcccXKM2WRn+4wkqQzep8yMQ5o3iSX1jd6HSJIqvgtHt0ZT8Wxzxqe+J9fNdo41nQQAAECli4gPFltm4goAIDUKnnIB+v2d2I+OA+Xuy3ZrAAAAAAAAAAAAgPQz3w6YbwcAAIAKNDybm5hJcg+6uEHSYFbcd14v/vujTDbfsdbkyX9nN2aotbfP+VAmyS/39zm0ndOYuDhsgLq7rj7aWqdbV5Ik/Y1m7/vFWNnba5SihOadeZG19h59/oTT4623VlokZeCAI062JpWaxk/ZK045/5ro6u6RtIY98Men/+rMeGvlyrj5jvviq6d9P6Zsd7B9R5I0pI3M5mLvcZNjUX2z9yKSpIruV/VjYoPWac731M+K5Z9YN9s51oQSAAAAlSwidjVtBQCQKgVPuQD9/k7sR8eBcvdSsX+2YwMAAAAAAAAAAACkm/l2wHw7AAAAVKi69sI/ZrL5hS5vkDQkl6Zk84/WZHPfqMl2tNiRGUqZbO5mf5ND2+7jNndp2AB2RmObdSVJ0ns0Ycru8cRTzxqjKKF7738oRk6abb39RaPW3z5+8ONFFkiZ+NFlv7IulZqGt8+KY05ZGF3dPZLWsFvvfaRf58jv//hYfHfBZbHzQce9c8bbiyRJQ9W0CVPj/MYklnk3Ikmq0G6ta4wZxfPMuZ72GbHcn9Zp6RhlQgkAAIBKFBEfLLbMxBUAQKoUPOkC9Pt7sR8dByrB8XZsAAAAAAAAAAAAgHQz3w6YbwcAAIAKV5Pk9qhJ8q+5wEHSELa02PEuUGFIzsFs7gx/g0NbXdIRd4xqcGnYAPX25Zlbt2xlbUmS9BfVtnXGomtvMj5RQm+++VZM3eFQ6+0vmjhtn7j97vstkDLxyGNPxZhNdrY2lZp2mfuN6OrukbSGLVqyenegvb78jVh8051x7MnfjUnT9rUvSZKGpM1ato75Te2xdFS99ySSpIprabFPjdvEmZ72kvzD67TmP2lKCQAAgEoTEbuYuAIASJ2CJ12Afn8v9qPjQCV4sdg/27UBAAAAAAAAAAAA0st8O2C+HQAAAFKgJtvRUpPkl7nAQdLQluvNJPlfZbK5vf9lvWn/n92ZwTAsye/rb2/oO6Mp68KwAew/Ro+PWutKkqT/1TEnnm10osS+Pv8H1tpftP3+R8fTz75gcZSJ3t6+mL3vF61NpaYNZn4qvr1gcXR190hag3585V2xsrd3QM6ae+9/KOafuzDye30hhrd32qskSYPa+NYZcdTYDeK2utHelUiSKq55YybGCOd5qstk8w+MaJ81zKQSAAAAlSIiPlDsHlNXAACpU/C0C9Dv78Z+dByoFMfbtQEAAAAAAAAAAADSy3w7YL4dAAAAUqJ2g8JHMtn8aS5wkFQWF6kk+eU1Se7yYoXm5sLf26UplUxrPvE3N/RtP36Ki8IGuJ3Gb25tSZL057YoHBLL31hhbKKE7rrvwRg5abb19udq2zrjq6d9P1b29locZeT08y6xPpWaRq2/fZxwxmXR1d0jaQ36/k9vjdeXv1mSc+e5F16KhZdfE3vOPeGdv1l7lyRpsGpMOuIzzRvH4vom70skSRXV+aNb3znHnOep7v6Rk7Zd17QSAAAAlSAidjJxBQCQSgVPuwD9/m7sR8eBSvFisX+0cwMAAAAAAAAAAACkk/l2wHw7AAAApExNkts+k+RedIGDpHIpk80/X9yXzhrW3rlJcZta207NQGpvn/Oh4vp63d/a0Dai2A0udxzQrqkfE5/M5qwvSVLVV7d+IZb97o9GJkpoxYo3Y8r2h1hvf27MJjvHz6++wcIoM7998OF39gNrVGnpoGPOiq7uHklr0Hd/fGM89+Jrg3IOvb78jbjy+lti7jGnvvOsYB+TJA3Ou5dc7D1uclxRP9Z7E0lSxbSovjkmtk53lqd5DizJ35WZ1PlxE0sAAACUu4i43dQVAEAqFTztAvT7u7EfHQcqyZF2bgAAAAAAAAAAAIB0Mt8OmG8HAACAFMq0dDbWZPO/cYmDpLIryT+cSXIn1iQzRtutGbBzL5u72d/X0Hf82PVdEjbAfa55I2tLklT1LbjkCqMSJfbled+z1v7cNjsfFn945HGLosysWPFmTN3hUGtUqWn67kdHV3ePpDXojB8uiUeeeGFIzqU3VqyIxTfdGcee/N1Ipu5lX5MklbzaYoXxU+KShvHenUiSKqKb6hpj2oSpzvF095sRE2b8s4klAAAAylVETDd1BQCQWgVPvAD9/n7sR8eBSvJksY/YvQEAAAAAAAAAAADSx3w7YL4dAAAAUqqhYdqHa5L8fBc4SCrT+mqS3A2ZJP+pzKTOj9u1WRPF867L39TQt37rtFjmgrAB7a66hsi2bmt9SZKqtjmfP8mYRIndeueyGNE+ywXlbZ1x7MnfjRUr3rQoytAJp55nT1Rqatlynzj1+9dEV3ePpDXo/oeeKoszamVvb9x4271x3DfOiQ1m7G+fkySVvGkTpsb5jYn3MZKksu+eUfWx57jNnN/pbsk6LVt91NQSAAAA5Sgirjd1BQCQWgVPvAD9/n7sR8eBSnOQ3RsAAAAAAAAAAAAgfcy3A+bbAQAAIOWGJR35TDb3nEscJJVtSW5l8d+riv/u4bIVVkdtkt/F31J5tHD0BBeEDXCnN7ZZW5KkqmzitH3ihRdfMSJRQq+9vjw2yR9U9Wtt/Oa7xZXX32JBlKmbfrM0RrTPsi8qFY2YNDuOPfWS6OrukbQG3XrPI2V7bv32wYdj3pkXxfRdPmvfkySVtE1aton5Te2x1HsUSVIZt6zYUWM3cHane+arx6wXAAAA5SYi1jd1BQCQagVPvQD9/o7sR8eBSvNQsb+zgwMAAAAAAAAAAACki/l2wHw7AAAAVIF1s7NH1mRzv3aRg6RyL5PkXqxJ8ufWtOY3X2ut4z5gB6c/1mnNf9LfT3m0z7jNXA5WgovGpk+Yan1JkqqqkRNnx8133Gc8osSO+tp3qn6tbbffF+PxJ5+1GMrUy6+8Futvu599Ualp789/O7q6eyStQb+66YGKOcf+8Mjjccb5/xH5vb4Qw9s77YOSpJLU1jo9vj5mUtxV1+CdiiSpbDutqT1GZnPO7tTOeuV/2dAw7cOmlwAAACgXEfFTk1cAAKlW8NQL0O/vyH50HKhEO9vBAQAAAAAAAAAAANLFfDtgvh0AAACqxeTJf1eTzR9fk831usxBUkVcupLNP1rstGHtM9ts4ryft9eLv5uhrz7piNtd3DjgXd7QHCMSl4xJkqqnU876obGIEltyy11R29ZZtWtseHtnHHvyd+Ott1ZaDGXs01+cZ09Uapq8/WExf8Hi6OrukbSaXXr13bGyt68iz7TnXngpFl5+Tew594QYtf729kVJ0oDXnMyMo8ZuELfWNXqvIkkqyy4aPSGaiueVczu1/aS9fc6HTC8BAAAw1CJibLFek1cAAKlW8OQL0O/vyX50HKhEdxVb2y4OAAAAAAAAAAAAkB7m2wHz7QAAAFBlhrV2bl2TzT/pIgdJlVXujkw299nh2VzGTs67ySS5H/s7KY/mNU10KVgJmtO8qfUlSaqKZu/7xVjZ606LUnr51ddiven7Ve0a23DmnLjp9nsthDJ30U+usicqNY3dbLf45rlXRVd3j6TVrPvnt8cbK95Kx7PYK6/Fpb+4Pvb97Ndi1Prb2yclSQNaQ7YjDmneJBbXN3m3Ikkqu35VPybWa53uzE5rSe7itQqFD5pgAgAAYChFxPkmrwAAUq/gyReg39+T/eg4UKmm28UBAAAAAAAAAAAA0sN8O2C+HQAAAKrQOi2z/i2T5H/pMgdJlVeut/jvkpq2zjkfb8p9zI7Of8pkc5/191EeTZ2wlQvBStBNdY3RlMy0xiRJqa558q7xp8efNg5RYocfP79q19jcY06NV1593SIocw89/Fg0bbyTfVGpaHhbZ3z+xAXR1d0jaTU779Kb45XX3kjlmff68jfi8iuXxJ5zT4hPrredfVOSNGCNzOZiv3GbxZUNY71jkSSVVTfWNcaWLVs5r1NaJpv//lprHfcBU0wAAAAMhYjIFFth+goAIPUKnn4B+v1d2Y+OA5XqKrs4AAAAAAAAAAAAQHqYbwfMtwMAAED1WrsmyR2aSXJvutBBUkVexJLklxf3scuLFdrb53zItl7dMtnODf1dlE+Xj252IVgJOnHMJOtLkpTqfnnNTUYhSuy6G+6I2rbOqltbrVvuEYuutb4qwYoVb8Y2Ox9mT1Rq2vmQk6Oru0fSanb2whvimRderYoz8MWXXomFl18Te849IUZOmm0PlSQNSMOzudh+/JS4rGGc9yySpLLp7rr62H3c5s7qtJbk55tiAgAAYChExFdMXwEAVIWCp1+Afn9X9qPjQCVrtZMDAAAAAAAAAAAApIP5dsB8OwAAAFS5Ye2dm9QkuUdc6CCpwnsyk81/qzaZOcnOXp0aGqZ9OJPkl/tbKI/2HjfZZWAlaGldfWzeso01JklKZUd97TtGIErspZdfjYnT9qm6tTXn8yfFcy+8ZAFUiGNOOtueqNS0Uf6QmL9gcXR190hajb7zwyXxyBMvVOV5+PSzL8R5F/88Zu9zVAxv77SnSpIGpNyELePS0eO9b5EklUXLih01dgNndGrL/btJJgAAAAZTRHyk2DOmrwAAqkLBEzBAv78v+9FxoJKdaycHAAAAAAAAAAAASAfz7YD5dgAAAGCtuvbCP9Zk8z9ymYOkVJTklxX/Pb4229Fgh68uxc99ib+B8uiT2VzcWN/oMrAS9NOGcTG8+N/XOpMkpakp2x8Sy99YYQSixA4++pSqWlfjNt81Lv3F9T74CvKrntuitq3TvqhU1LjJLnHi2b+Mru4eSavR6Rf1xO8edt/Z25546tk4Z8Fl0bn3kc5JSdKA1Dl+y1g4eoJ3LpKksuikpkkxIvH+O40Ny+aPMMkEAADAYImIOd4uAwBUjYInYIB+f1/2o+NAJXuj2Dp2cwAAAAAAAAAAAIDKZ74dMN8OAAAA/Jeats45mWz+DZc6SEpNSe62YoeumxQ+YZevgnMsmz/Zui+fvjh2A5eAlag5zZtaY5Kk1FS3fiHue+APxh9KbNG1N1XVutpz7gnxxFPP+uAryNuf14Qpu9sXlYqGt3XG575+YXR190haze68/zGH47t49Imn45wFl0Xn3kfabyVJa9y0CVPj/MbEexdJ0pB3bmNr1CUdzuf01ZfJ5g40zQQAAMBgiIi7vFEGAKgaBU/AAP3+vuxHx4FK9yW7OQAAAAAAAAAAAEDlM98OmG8HAAAA/pdh7TPbMtn8Ay51kJSmivvaGzVJ7vJiexT3uf9jt0+n2rbcLOu9fJrQum3cO6reJWAl6La60TE+mWGdSZJS0QULf2nsocSee+GlSKbuWRXrKZm6V/z86ht86BWmt7cvdphzrD1RqWnXQ78ZXd09klazG+/8g8OxHx557Kk4Z8FlMW3nz9p7JUlr1OYt28RZjdlY5v2LJGkIu3T0+BjnHXgKy/XWJvldTDQBAABQShGxtTfIAABVpeApGKDf35n96DhQ6Z4q9g92dAAAAAAAAAAAAIDKZr4dMN8OAAAA/JWPN+U+lsnmL3Spg6Q0lklyLxa7oNjU4pa3tl0/PdZpmfVv1nh5dXpjmwvAStRpTe3WmCSp4tv3s1838jAI5nz+pNSvpdq2zph7zKnxwouv+MAr0Cln/dCeqNQ0efvDYv6CxdHV3SNpNbrqxt86GFfDbx98OOadeVFsNutT9mJJ0mq3acs2Mb+pPZbW1XsPI0kakq6pHxOTa+s13AAAIABJREFUWqc7l9NWkltZbHtTTQAAAJRKRPzCW2MAgKpS8BQM0O/vzH50HEiDPe3oAAAAAAAAAAAAAJXNfDtgvh0AAAB4T7VJfr+aJP+ayx0kpbfcH4r73FfWzXaOteunQybJPWhdl09TWrZ2+VeJWlZsxoSp1pkkqWKbNG3feOHFV4w7lNilv1yc/ku/Ow+Km26/14ddoW6+474YOXG2fVGpaNzmu8c3z70qurp7JK1Gl117b/T29jkc19Bd9z0YX/nW+TFx2j72ZknSarVR67SY39QeS72LkSQNQTfWN74zZ+BMTleZJL88k+SmmmoCAABgoEXE6GJeNAMAVJeCJ2GAfn9v9qPjQBrcbkcHAAAAAAAAAAAAqGzm2wHz7QAAAMDfNKx95phMkr/L5Q6SqqClxb4wctK269r9K1cmyV1gLZdXl44e7/KvEnVF/dgYkc1ZZ5Kkimt4e2f8+pa7jTqU2FPPPB/jNt81teuofoNCzDvzonhjxQofdoV66eVXY4MZ+9sXlYpGTJodx5yyMLq6eyStRguvuDPefGulw3EA9fb2xc133BdHnHB6NG28k71akrTKTWydHl8fMynuGVXvnYwkaVC7Y1RDzBq/hfM4bSX514a15Tc12QQAAMBAiohTvB0GAKg6BU/CAP3+3uxHx4G0WM+uDgAAAAAAAAAAAFC5zLcD5tsBAACA91W7QeEjmWzuuy53kFQdl7jkVhb3vF/UtuZ2Xadlq486BSpL8bM70Dour3Ybt7mLv0rY4WM3ss4kSRXXvDMvMuIwCPb97NdSu4b2nHtCPPLYUz7kCrff4SfaE5Wa9v78/Ojq7pG0GnX//PZYvuItB2MJvfb68lh4+TWx04FfiuHtnfZtSdIqNbF1epzSNDGWjqr3XkaSNGi9fe7sNW4zZ3HKymRzL2Ra84npJgAAAAZCRHyk2HPeCAMAVJ2Cp2GAfn939qPjQFqcZ1cHAAAAAAAAAAAAqFzm2wHz7QAAAEC/ZbK5nWqS/EsueJBUPeVeySS5C4a1dm69VqHwQSdB+Vs32znWui2vRiS5uKp+rIu/StRddQ0xqXW6tSZJqphm7X1krOztNeJQYhf95KpUrp+NOg6Iqxff6gNOge//6Jf2RKWmrXf5QnR190hajc7/yS3xymtvOBgH0eNPPhtd3/txTNnuYHu4JGmVyrZuG18fMynuGVXv/YwkaVBaVuyosRs4h9M3i/VUZkKuyYQTAAAAayoi9vYGGACgKhU8DQP0+7uzHx0H0uL1Yv9iZwcAAAAAAAAAAACoTObbAfPtAAAAwCoZ3t5Zn0nyt7rcQVK1lUlyjxf3v1MyLbms06Csrf32Z2XNllf7jtvMpV8l7OLRE6LWOpMkVUDNk3eNR5942nhDiT325DMxZtOdU7V2Rm+0Y5x69sXxxooVPuAUuP93D0f9BgX7olJR69S945Tzr4mu7h5Jq9i5l9wUL7z0uoNxCN219HdxzElnR8sWu9vTJUn9rq11eswbMzGWej8jSRqkTmmaGCOcwekqyT+cmZgfbsQJAACANRERt3jrCwBQlQqehgH6/d3Zj44DaXKYnR0AAAAAAAAAAACgMplvB8y3AwAAAKusubnw95kkd2pNNt/nkgdJVdrSmqTjqGHtM0c4FcpPTTbXbY2WVyOyubiufowLv0rYvuM2s9YkSWXfz6++wVhDifX19cWun/5yatZMbVtnHHDEyfGnx5/24abEK6++HpNnfdqeqFRUt14hjp//0+jq7pG0ip298MZ45vlXHYxl4q23VsYV190c+3/uxBi1/vb2eElSv5rUOj2+3dQWS72jkSQNQuc0JTEqyTmD01SSu29Y+8x/NeUEAADA6oiIxJteAICqVfBEDNDv789+dBxIk98VW9vuDgAAAAAAAAAAAFB5zLcD5tsBAACA1TYs6diqJpt/0iUPkqq3XG/x3yU1Se5QF72Uj5q2zjnWZvn1qXGbuOyrhN1eNzpaWre11iRJZdtRX/uOkYZBcP7Fv0jNminMOSbuWfZ7H2rKHHL0KfZEpaLats44+Lhzo6u7R9IqdubFv47HnnrRoVimXnr51Vh4+TWx04Ffemevs+dLkt6v9tbpMW/MxFjqXY0kqcT9aHRLNCYznb8pKpPN3TmyNf9PJp0AAABYVRFxjre7AABVq+CJGKDf35/96DiQNlvY3QEAAAAAAAAAAAAqj/l2wHw7AAAAsEZqJsyqzST5613yIKnqL3pJ8ssz2fzCYUlHvrm58PdOiCE8m5IZo63J8uuT2Vz8ur7JZV8l7MymNmtNklSWbVmYG8vfWGGcocQefvTJaNx4x4pfL5t2HhSLrr3JB5pC37voZ/ZEpaadDj4purp7JK1iZ/xwSfzh0eccihXioYcfi2+csSA2mLG/vV+S9L5NbJ0e88ZMjKXe10iSStii+uZoad3W2ZuueatfNTRM+7BpJwAAAPorIv6p2Kve6AIAVK2Cp2KAfn+H9qPjQNostLsDAAAAAAAAAAAAVB7z7YD5dgAAAGDNFQofrMnmj69Jcitd9CBJ+chkcy9kktwFxaYWd8m1HRSDrybJP2wtll+fad7IRV8lbsfxU6w1SVJZ1bDhDvHb3z9ilKHEenv7Yrv9vljZl29P2yfOWXBZvPnmWz7QFLrjngfik+ttZ19UKtq8cHjMX7A4urp7JK1Cp1/UE7/949MOxQp1130PxrEnfzfGb76bs0CS9Le/37dMj3ljJsbSunrvbSRJJena+jExqXW6czdNJfmfrjV58t+ZdgIAAKA/IuIgb3ABAKpawVMxQL+/Q/vRcSBtVhT7hB0eAAAAAAAAAAAAoLKYbwfMtwMAAAADpqY1v3kmm3/URQ+S9N9lktzvi/9+OdPS2eikGDzF/+4XWH/lV33SETfVNbroq4TdUN8UTclM602SVDZ1X3qVMYZBcPaFP63YNTJhyu5x+nmXxPI3VvggU+r5F1+O9abvZ09UKmqdunfMO//q6OrukbSK3fu7JxyKKfD2M9ulv1wcOx90XAxv73Q2SJLes41aton5Te2xtK7e+xtJ0oB3Y31jbNaytTM3TSX5c9daa621TTwBAADwfiLiFm9uAQCqWsFTMUC/v0P70XEgjQ6zwwMAAAAAAAAAAABUFvPtgPl2AAAAYEANa5/5rzVJ7nIXPUjSX5dJ8jfVZvOHrJsUPuHEKK1MNre3NVeeHTF2Q5d8lbiTmyZZa5KksujTR33T+MIgePAPj0b9BoWKWx9jN9slvvXdi+PV15b7EFOst7cvdv30l+2JSkV1xb3237sui67uHkmr2G+WPepQTKGHH30yTuq6MNq23ts5IUl6zzZumRbzm9pjaV29dziSpAHttrrRMW3CVOdtqsp9w8QTAAAAf0tEjPemFgCg6hU8GQP0+3u0Hx0H0ugeOzwAAAAAAAAAAABAZTHfDphvBwAAAEph7Zokd2gmm3/DRQ+S9C4luZXFf68q/rvHOi1bfdSxMfCGtc8cYa2VZw3ZjrixvtElXyVsWbH8hC2sN0nSkLZRxwHx8quvGV8osd7evpi195EVtTbGb75bzDvzonjxpVd8gFXglLN+aE9UKqpt64zPfOX70dXdI2kVu/XeRxyIVfBMuvimO+OAI06OkRNnOzckSe/aJi3bxLmNrd7jSJIGtLvqGmI778bTNlN1pKknAAAA3svb40je0AIAVL2CJ2OAfn+P9qPjQFpNsssDAAAAAAAAAAAAVA7z7YD5dgAAAKBkhrXPbMtk8w+47EGS3rtMknux2AXFpq611nEfcHoMnJps7g/WWHn26eZNXPBV4q6rHxOjkw7rTZI0JI2cNDtuv/t+YwuDYP65CytmXbRssXvMO/OiePmV13xwVWLJLXfFiPZZ9kWlol3mfjO6unskrWI33PkHB2KVeeqZ5+P08y6JDWfOcX5Ikt61LVu2ivMbE+9yJEkD1tK6+thv3GbO2fTUV9PWOcfUEwAAAH8pIj5U7GlvZQEAql7B0zFAv79L+9FxIK3OsMsDAAAAAAAAAAAAVA7z7YD5dgAAAKCkPt6U+1gmyf3AZQ+S9P5lsrk/ZbL502qSWa1OkDVXk+S/Z12VZyOyubimfowLvkrcN8ZMtN4kSUPSWT/4iZGFQXD/7x6OUetvX/brYYMZ+8f3LvpZLH9jhQ+tijz97PORTN3LnqhUNGWHw2P+gsXR1d0jaRW67tYHHYhVrLe3LxbfdGcccMTJ8cn1tnOeSJL+qmkTpsaPRk/wPkeSNCAtK3ZY80bO2NSU681k8zuafAIAAOB/iojZ3sQCAFBU8HQM0O/v0n50HEirF4v9Hzs9AAAAAAAAAAAAQGUw3w6YbwcAAAAGRaY1v1dNNv+qCx8kqX9lsvlbapLc3HWTwiecIqun+N9xd2upfNt9/GSXew3CxWGd47e03iRJg3vGH/Lv0dfXZ2ShxN5auTKm73p4eV+OvfNnY+Hl17zz/ytVtj7fWhmdex9pT1Qqattm/zjl/Guiq7tH0ip09U0POBD5L88892Kccf5/xKadBzlbJEl/VWH8lPhlQ7P3OpKkAenYsRs4X1MzN5VbMSzp2Mr0EwAAAP8pIi739hUAgKKCp2OAfn+X9qPjQJrtYqcHAAAAAAAAAAAAqAzm2wHz7QAAAMCgyUzINdVkc3e49EGSVqEkt7L471XFf/dYp2WrjzpN+m94Npexhsq32mKXj3ZJYqlbUt8YTclMa06SNCglU/eMp599wajCIPjmd7rLcg0Mb++MPeeeEItvutOHVMWO/+a59kSloqZNdomvnfWL6OrukbQKXbFkWfT29TkQeVd33fdgHHHC6dGw4Q7OGknS/3pntMv4zePq+rHe7UiS1riTmybF8GzOGZuKman8a5ls54YmoAAAAIiIdYu95Y0rAABFBU/IAP3+Pu1Hx4E0u9JODwAAAAAAAAAAAFAZzLcD5tsBAACAQdXQMO3DmWz+tJpsvs/FD5K0amWS3IvFLig2tbilru1UeX+ZJP87a6d8y4/fwqVeg9ApTROtN0lSyRve3hk9N99lTGEQ3LPs9zFy0uyy+vzHbLpzHHHC6fHAQ3/yAVW5K667OWrbOu2LqvhGTtoujp63MLq6eyStQouWLIvevj4HIu/r5VdeiwsvuSK23ukzzh1J0n81otje4ybHtfVjvN+RJK1Rpze2vXOuOF9TUJJ/JjMh12QCCgAAoLpFxKHesgIA8GcFT8gA/f4+7UfHgTTrLVZjtwcAAAAAAAAAAAAof+bbAfPtAAAAwJAY1prvzGRzz7n4QZJW99KY3B9rkvxXhrXPHONUeW+ZJHem9VLedY9ucanXIDRr/BbWmySppH3jjAVGFAbBihVvxpaFuWXzuU/f5bNx4SVXxOvL3/DhEA89/FiM2XRne6Iqvtq2zpj75e9FV3ePpFVo0ZJl0dvX50Bkld1+9/3xuS/Pj8aNd3QOSZLeaWQ2F3OaN40b6xu945EkrXbfa0xiVJJztqagTJL7/chJ265rCgoAAKB6RcQt3qwCAPBnBU/IAP3+Pu1Hx4G0+4zdHgAAAAAAAAAAAKD8mW8HzLcDAAAAQ2ZY+8wRNUmux8UPkrSGl8dk87cU99O56yaFTzhd/uKsac13WiPl3RYtW8cyF3qVvJ66pmhKZlpzkqSSNHufo2Jlb6/xhEHw1dO+P+Sf97jNd41jTjw77l72oA+E//Lqa8tjy8Jce6JS0W6fOSW6unskrUJX3nB/9PX1ORBZI6+8+npceMkVMX3Xw51HkqR3qk864vCxG8VtdaO965EkrVYXNLZGXfE8ca6modwdde2FfzQJBQAAUH0ioqGYF9IAAPyngqdkgH5/p/aj40Da3WK3BwAAAAAAAAAAACh/5tsB8+0AAADA0CoUPliTzR9fk+RWuvhBktaw/38vvar47x7rtGz1UYfMWmt9vCn3sUySe9P6KO++3dTmQq9B6PTGNutNkjTgNU/eNf70+NNGEwbB7XffHyPaZw3J5zy8vTN2OvBLsfDya+L15W/4MPhf+vr64sAjTrYnKhVN3/2L0dXdI2kVWrRkWfT2ub+MgXXXfQ/GESecHg0b7uB8kiTFmGRGHDV2g/jNqAbveyRJq9yPRk+IxqTDmZqCMtnctSMnT/4H01AAAADVJSKO9wYVAID/oeApGaDf36n96DhQDRrt+AAAAAAAAAAAAADlzXw7YL4dAAAAKAs1rfnNM9n8oy5/kKQBukgmyb1Y7IJiU4vb7NrVfMZkkvz11kR5Nz6ZEbfVjXah1yC0+/jJ1pwkacCqbeuMRdfeZCRhELyxYkVM2e7gQf+M3/6/efp5l8RTzzzvQ+A9ffuchfZEpaINOj4dp11wXXR190jqZ4uWLIvevj6HISXz0suvxjkLLosNZuzvrJIkxYTWbeMbYybGUu97JEmr2E8bxsXY1pnO03T0k7UKhQ+auAUAAKgeEXG/N6cAAPwPBU/JAP3+Tu1Hx4FqcJwdHwAAAAAAAAAAAKC8mW8HzLcDAAAAZWNY+8x/zWTzP3PxgyQNbJls7k/F/fW0mmRWazWeLzVJ/ovWQfl3SPMmLvMahG6vGx1trdOtOUnSgPSlb5xjHGGwph6K/60H4zOtbeuMbXf7XMw/d2E8/OiT/sPzvq674Y4Y0T7LnqiKb9yUPePkc6+Mru4eSf1s0ZJl0dvX5zBkUPT29sXim+6MPeee8M4zq7NLkqq79VunxVmN2VjmvY8kaRW6oqE5WltnOEvTMAeV5M40bQsAAFAdImKSt6UAAPyFgidlgH5/r/aj40A1+J0dHwAAAAAAAAAAAKC8mW8HzLcDAAAA5WbtTJI/PJPNrXABhCSV4GKZbP6W2mz+kHWTwieq5WDJtOSyPvvyb0SSi583jHOZ1yD0o9ET3vnvbd1JktakbXY+LFaseNM4wiC45Y77Ynh7Z8k+y7r1C7HTgV+KcxZcFk889az/4PTbQw8/FmM328WeqFR07Lcuia7uHkn9bNGSZdHb1+cwZGgmgv/wpzjmxLNjzCY7O8MkqcrbsmWruHj0BO9+JEn97tr6MTGxZbpzNA3zT0n+WKO2AAAA6RcR3/KGFACAv1DwpAzQ7+/VfnQcqBYT7foAAAAAAAAAAAAA5ct8O2C+HQAAAChLw9o62zNJ/ncugJCkEpXkVhb/var47x7rtGz10ZQfK2tnktzjPvfyb9qEqbHMRV6D0mebN7bmJEmr3eiNdnznIntK77XXl8fGuQMH/DNs2WL3mHvMqXH5lUvilVdf9x+aVfbqa8tji8Ih9kSlpv2POiO6unsk9aNFS5ZFb1+fw5Ah9/Zz7IWXXBFbFuY6yySpyiuMnxKLGsZ6/yNJ6leL65ti/dZpztAUVJvNH2LSFgAAIL0i4gPFHvNmFACAv1DwtAzQ7+/WfnQcqBbftOsDAAAAAAAAAAAAlC/z7YD5dgAAAKBsfbwp97FMNn+hCyAkqbRlktyLxS4oNrW4/a6dxjOleJ5832ddGZ3R2OYir0HonlH1Mblla2tOkrRa/fhn1xpBGCRHfvU7A/KZtWyxe+x3+IlxzoLL4p5lv4++vj7/cVltb6+fA4442X6oVDVx+oHR1d0j6X1atGRZ9HqOoAzdfMd97zyfjJw427kmSVXa8Gwudhm/eVxXP8Z7IEnS+3ZjXWNs0rKNM7TSS3Iri/9uZ9IWAAAgnSJiY29CAQB4FwVPywD9/m7tR8eBavGHYmvb+QEAAAAAAAAAAADKk/l2wHw7AAAAUPYy2dw+Ndn8qy6CkKRBuXDmjzVJ/ivD2meOSdNZMizp3NnnWxmNb50Rt9eNdpHXIHRFQ3PUJR3WnSRplTr02G8ZPxgk1994R9S2da7W5zRp2r5x8NGnxA9+vCh++/tHoq+vz39QBsypZ19sP1QqO/rUH0dXd4+k9+iKX9/vmYKy99iTz8SJXT+I1i33cLZJUpX29nuPw8duFLd51yRJep9uqmuMTVu2cX5WeJkkv3xYW35TU7YAAADpExGneAMKAMC7KHhaBuj3d2s/Og5Uk4l2fgAAAAAAAAAAAIDyZL4dMN8OAAAAVIRh7TPH1GRzd7gIQpIGtaXFvvBv4zvWScE58q/Fc6TXZ1oZfaZ5Y5d4DVInjplkzUmS+t3GuQPjlVdfN3owCF5+5bVYb/p+7/uZjGifFRvOnBN7zj0h5p15UVx5/S3x9LMv+A9IyVx3w2/eWXf2RKWxGXseG13dPZLepUVLlkVvX5+DkIrx5ptvxeVXLomdDvySM06SqrQxyYw4fuz6cXddvfdBkqT37La60bFFy9bOzgovk+RerMl2tJiyBQAASI+IWLvYH735BADgXRQ8MQP0+/u1Hx0HqsnX7fwAAAAAAAAAAAAA5cl8O2C+HQAAAKgYIydP/odMNn9aTTbf5zIISRrEktzK4r9XFf/dY52WrT5aqedIJpu72edZGQ3P5uKShvEu8RqElhXbYfwW1p0k6X0btf72cc+y3xs7GCSHHXfaO//dGzfeMTbOHRj5vb4Q+xz2tTjuG+fE9y76WVy9+NZ44KE/xYoVb/qPxaD5/R8fizGb7mxPVKrPunnnXx1d3T36f+zdeZScdZ3of5jxd5253nHuz7kjUt1JSC9JuumlKguEsIRAAklIqjqBYhHZBEF0IDg6AbyAKDI4KEKkIzDAIAodFSJIUIEoSDpA2AMkRDZlB5ElECBk6f7cJo4zKCSpJN3V9VS9Xue8T878o051nefzPPX9nucrvacbFi6Lru5ug5DEenDZ4zHzjNlRt9P+5p0kVWCZ1slxzrCRsbSm1rqQJOkDu6emPsY3TzA3E14qk3s2NTI3wC5bAACA8hARo6x0AgCwHnl3zAAFP1976ThQSR515QcAAAAAAAAAAAAoTfa3A/a3AwAAAIlTlZk6PZXJveowCEnqh0No0tnlVZnsJdWZ7G49l+StkzU/cl/1N0xOO7VMjAcdcFi0Q8KGt07yvZMkbbD/mHO9LQdF9M6qVT4ESsobb74VY6d93vVQZd+RM8+P9o5OSf/ZTbf9Jrq6uw1CysIrr70esy+bGztOPsrMk6QKbEzrxLhoSMa6kCTpA7u3pj72aplgZiZ9T1Mmu/hjO0z8qB22AAAAyRcR37DCCQDAeuTdMQMU/HztpeNApWl19QcAAAAAAAAAAAAoPfa3A/a3AwAAAIn0icz0QVWZ7G0Og5CkfiydfbIqnfv6tiOmDEvC7Eilc2P83ZLVzIadHOBVpK6pb4qBmazvnSTpAzvyn/81uru7bTeACtXV1R1HnHCm66EqouF7fybaOzol9XTLXY+FW0DK0Zq1a+OnN3bG5E99yeyTpAos27xnzKtrtDYkSXpf9w2ui0nN483L5De/sTH/P+ywBQAASLaI+I2VTQAA1iPvjhmg4OdrLx0HKs3XXP0BAAAAAAAAAAAASo/97YD97QAAAEByjR37oVQme2ZVJtvlMAhJ6t9Smdxd1ZnccZ9I5/+xZOdGPv/XPf87X/X3Sk4De7qubnsHeBWpUxtG+95Jkt7XjpOPiuWvr7DVACrYty7ocD1URfXlc34c7R2dUkW34J4nDEAqwqL7lsaR//yvMWBEmxkoSRVUdU+fbNo9bq0dZn1IkvRnPVBTF9nmPc3LpO9hSmd/sNVWW21tgy0AAEAyRUSLlUwAADYg764ZoOBnbC8dByrNUld/AAAAAAAAAAAAgNJjfztgfzsAAACQeFWt2XGpdO45B0JIUgmUzq7t+Xd+z7+HbtMy4SMlNzMyuR/7OyWrXVv2jiWDax3gVYQe7vmcHRAmSXpvg0ZOj7sXL7PNACrYvJsWRvXwNtdEVVSTDz0l2js6pYrtniVPG4BUnKeefTFOPfviqB9zgFkoSRVUTXpqfLFhTNw3uM46kSTpv3pocG3s1zTOrEx4qUzuLDtrAQAAkikiTrOCCQDABuTdNQMU/IztpeNAJao3AQAAAAAAAAAAAABKi/3tgP3tAAAAQFnYpmXax1Pp3C8cCCFJJXRATTq7vCqTvaQ6k92t51K9dSnMi1R66mH+Nsnryw07ObyrSN1RMySaWyf73kmS1nXB5dfYXgAV7N4HfxM1O+ZdD1VxbbfDfnHOZb+M9o5OqeJa/JvnDEAq2mvLV8T5l14VmQmHm4mSVEG1tE6Oc4aNjKU1tdaKJEnrWjK4Ng5oGmdOJn7fUu5zdtYCAAAkT0TcZeUSAIANyLtrBij4GdtLx4FK9AUTAAAAAAAAAAAAAKC02N8O2N8OAAAAlJOtq9LZGalMdpVDISSpxA6qyWSfSWVys6rS01r7c1CkRrX9Q1U6t8bfJFkN7GlefaPDu4rUD+ubY2A667snSRXeIcd9Lbq7u20vgAr1zPMvRXr8Ya6HqtgO/5dZ0d7RKVVMs+csjIefeNEAhP+0evWamHfTwpj8qS+Zi5JUQe3evHf8uL7FWpEkaV1LBtdGvmmcGZnosl1VmanTbasFAABIjojYticbFwEA2JC8O2eAgp+zvXQcqES/MgEAAAAAAAAAAAAASov97YD97QAAAEDZGZDJjkylc485FEKSSralPZ348aap2/THnOiZEbf6GyTwIMOWveOhwbUO7ypSMxt28r2TpApu5MRPxyuvvW5rAVSoFW++HeP3n+F6qIqudfwR0d7RKVVEF/xwYTz+9B8MQFiPO+9/OA47/oyoHt5mRkpShZRt3jNurG2wXiRJiiWDa2P/pj3MxwSXSmff3rZ16s521QIAACRDRBxlhRIAgI3Iu3MGKPg520vHgUq0uqf/bQoAAAAAAAAAAAAAlA772wH72wEAAICy9LEdJn40lcle6WAISSrh0tm1Pf/O7/n30G1aJnykWDOiZz78s88/mc1o3NnBXUXq4cG1kXM4mCRVZINGTl93aDxQmbq6uuOIE850PZR6OumbP4r2jk6prLvwR7fFU8+/agBCAX771HNx6tkXR+3ovDkpSRXQwEw2jm7cNRbVDLH0Yo3QAAAgAElEQVRuJEkV3pLBtZFvGmc+Jnt/0svbjpgyzK5aAACA0hcRP7UyCQDARuTdOQMU/JztpeNApdrfFAAAAAAAAAAAAAAoHfa3A/a3AwAAAGWtOp07qiqde8vhEJJU2qXS2eVVmewl1Znsbj2X7637cjYMGNFW6zNPZtU9XTqk1cFdRerumiExonWS754kVVjt/3G17QRQwb7yzUtcC6X/bO9PnRztHZ1S2Xbx1XfE8y+9bvjBJnrp5dfiWxd0RMseh5iXklQBDU1PidMbdoyHBtdaO5KkCm5JzxzYr2mc2Zjsfjto1ORP2FELAABQuiLib3t604okAAAbkXf3DFDws7aXjgOV6vumAAAAAAAAAAAAAEDpsL8dsL8dAAAAKHvbjpgyLJXJLnYwhCQlo55r9jOpTG5WVXpaa1/Nhp7//CU+6+QeXrigdqiDu4rUtXVNsV0m67snSRXSwZ//anR1ddtOABWq45r5roXSexo0at/41qXzo72jUyq7Lv3JovjDq84igy2xatXquGrezTFu338yNyWpAtqhdVJcNCRj7UiSKrglg2tjv6Zx5mKSS2fv2aZlwkfsqAUAAChNEbGPVUgAAAqQd/cMUPCztpeOA5XqlZ4+ZBIAAAAAAAAAAAAAlAb72wH72wEAAICKMGjs2L9JZXKzHA4hSYlraU8nfrxp6ja9ORdSmeyZPtvkNql5fCytqXVwV5H6t6GjfO8kqQJKjz8sXnr5VVsJoELdcc+S2G6HfV0Ppb/osC+eF+0dnVJZ9b1r74pXX3/b8INe0t3dHQsWLY7Djj8jqoe3mZ+SVObt0zw+5tU1Wj+SpAptyeDa2LdpnJmY4FKZ3PVb5fN/bUctAABA6YmI71p9BACgAHl3zwAFP2t76ThQyXY2CQAAAAAAAAAAAABKg/3tgP3tAAAAQEWpSmf3S2WyrzkgQpISdqhNOru65xo+LzW8bf9BY8f+zZbOg+rWth18rsnuyw2jHdpVxD69/W6+d5JUxg0cMS3uuGeJLQRQoR773TPROPZg10PpA2odf0Scf+WCaO/olMqi7193dyxfsdLwgz7ywMOPx2e+9I0YMKLNHJWkMm5AJhtHbr9b3F471BqSJFVgD9bURq55DzMx2XuQvmMnLQAAQOmJiCesOAIAUIC8u2eAgp+1vXQcqGRfNQkAAAAAAAAAAAAASoP97YD97QAAAEDF2XbElIFVmdxCB0RIUmIPt1ne0/d7Gt9zWd96M8fB1qlM9hmfZ7IPLJxT3+zQriIeDLZ7y96+e5JUpp138Y9sH4AK9dryFbFL7ljXQmkDnXj2nGjv6JQSX8fP7o03315l+EERPPnMC3Hq2RfH4B33M0slqYyrTU+NkxtGx0ODa60lSVKF9e61f9/mPczDJDc8d4KdtAAAAKUjImqtMgIAUKC8O2iAgp+3vXQcqGR3mAQAAAAAAAAAAAAApcH+dsD+dgAAAKAyjR37oapM7vSqTLbLIRGSlNxSmewzqUxuVlV6WuumjoJUOnuhzzDZZVonx1219Q7tKlK/qh0WQ9JTfPckqczKH31KrO3qsn0AKtCaNWtj/6NPdS2UNtKEg0+K9o5OKdHNnf9ArFy1xvCDInv2hZfi1LMvjrqd9jdTJamMG9U6KS4akrGWJEkV1gM1dZFt3tMsTGzv7hudOt1GWgAAgNIQEcdaXQQAoEB5d9AABT9ve+k4UMnW9vQx0wAAAAAAAAAAAACg/9nfDtjfbn87AAAAVLRt01MnVGVyLzokQpKSXyqTvbM6kzvuE+n8PxYyA6rSbZN8bskv17xHLK2pdWhXkbpsSDoGZLK+e5JUJqXHHx4vvfyarQNQgbq7u+MLX5nlWigV0MBR0+PsS2+K9o5OKZH9fMHDsWZtl+EH/egPryyPs87/QQzb9SCzVZLKuGlNe8T82gbrSZJUQT1QUxdTm/c0B5NaOvdWdWvbDnbRAgAA9L+I+IlVRQAACpR3Bw1Q8PO2l44DlW4/0wAAAAAAAAAAAACg/9nfDmB/OwAAAFS8T6Tz/5jKZH/uoAhJKpdDb7Jre/6d3/Pvodu0TPjI+q7/dXUTP1yVzr3hM0t+JzSOcWBXETu1YbTvnSSVQQNGtMWtd9xvywBUqG9d0OFaKG1Ch5zw7Wjv6JQS14J7nojubnMPSsWKN9+OS668LjITDjdfJalMG5jJxnGNu8S9NfXWlCSpQnqgpi4mN483BxO7xyj3h+rM1Dq7aAEAAPpPRPx1T69aTQQAoEB5d9EABT9ze+k4UOkuMg0AAAAAAAAAAAAA+p/97QD2twMAAAB/tHVVOjsjlcmucliEJJVPqXR2eU/f72n8u9f6v7z4pzK5q3xO5dG5Q0c4sKtILevpkKaxvneSlPC+dUGH7QJQoTqume86KG1i2487LM6/ckG0d3RKiWj2nM64f9mzhh6UqFWrVsdV826OnbOfNWclqUxraJ0SZw0bFUtraq0tSVIFtLimLiY2jzcDk1o6t2xg8z7/vy20AAAA/SMixlhBBABgE+TdRQMU/MztpeNApXvSNAAAAAAAAAAAAADof/a3A9jfDgAAALxHdXrKqFQ6+7jDIiSp/Eplss+kMrlZVelprX+67ldlpn7KZ1MeDU5n49q6Jgd2FakHaupij5a9fPckKaHte9SXY21Xl+0CUIFuXnhvDBo53bVQ2oz+5RtXRntHp1TyXfDD2+LRJ18y9CAB1qxZG1fNuzl2n/55s1aSyrTdm/eOq61fSVJFdG9NfYyzhp7cPUXp3K11dRM/bActAABA8UXEV6wcAgCwCfLuogEKfub20nGAiHoTAQAAAAAAAAAAAKB/2d8OYH87AAAA8Bc+tsPEj1Zlsh0Oi5Cksm5pTyemmrNDU+nsap9HedTcOjkW1g5xYFeRWlA7NJrS+/juSVLCatnjkHjxpVdsE4AK9MDDj8eQnQ9wLZQ2s/EHzoz2jk6ppLv46jviud8vN/QgYbq6uuOmW++KfQ75kpkrSWVYdU+fbNp93bqK9SVJKu/urKmPMa0Tzb+kls7N2Wqrrba2gxYAAKC4IqLTiiEAAJsg7y4aoOBnbi8dB4j4vIkAAAAAAAAAAAAA0L/sbwewvx0AAABYj6pM7phUOvu2AyMkqXzruc6vfjefRfk0oXlCPDS41oFdRWpuXVNsl8n67klSQhowoi1+fft9tghABXrq2RcjPf4w10JpS+boyOnxbxffEO0dnVJJdtk1d8YfXnvT0IOEu+W2e2P6kV82eyWpDKtNT42TG0bHgzXWsSSpnLujZkiMadnb7Ets2a/ZOQsAAFA8EfE/e1pllRAAgE2QdycNUPBzt5eOA0T82EQAAAAAAAAAAAAA6F/2twPY3w4AAABsQHXLtKZUJrfEYRGSJCWnI7Yf67CuIjZr6AjfO0lKSGed/wPbA6ACvbr8jdht2udcB6Ve6OAZ34r2jk6p5Or42b2x4q13DD0oI3fd/3AcevwZUT28zQyWpDJrVOukuGhIxhqTJJVxnTVDY2TP9d7cS2ap1tzhds4CAAAUR0TsaWUQAIBNlHcnDVDwc7eXjgNE/L6nrU0FAAAAAAAAAAAAgP5jfzuA/e0AAADARgwaO/ZvUpncLAdG6L05xFCSSruvDdvRYV1F7PONu/jeSVKJN/XQmbFmzVrbA6DCrHxnVbQdcZLroNRLbb/7oXH+lQuivaNTKpmu/dVDsWr1GkMPytSyx56M4085NwaNnG4WS1KZ1da0Z8yvbbDOJEll2i11wyKdnmzmJbBUOru6avjUPeycBQAA6HsR8TUrggAAbKK8O2mAgp+7vXQc4I+GmQoAAAAAAAAAAAAA/cf+dgD72wEAAIACVWWmTk9lcq86OEJ/ao/8cXHKN/49dskd6/OQpBKruqdZQ0c4rKtILa2pjf2axvnuSVKJtv3uB8czz79kWwBUmK6u7jjqi99wHZR6uX8+8wfR3tEplUTzb38k1vZc74Hy99SzL8bMM2bHwBHTzGNJKqMGZrJxXOMucf/gOutNklSG/ap2WDS3TjbzElgqk30l1dI2xK5ZAACAvhURt1oJBABgE+XdSQMU/NztpeMAf3SMqQAAAAAAAAAAAADQf+xvB7C/HQAAANgE246YMrAqk1vo4Aj9qfT4w+Jnv7w9Hnni6Thz1uU9//fhPhdJKqGDCH8wpMVhXUXqvsF1sVvLXr57klRiVQ9vixt/factAVCBTj37YtdBqQ/aY/9/ifaOTqnfu+OBJw07qEBPPftizDxjdgwcMc1clqQyqrV1nzh/6AjrTZJUhv2irjEa01PMuwSWSmef2HbElP9j1ywAAEDfiIgP97TSCiAAAJso724aoOBnby8dB/ijDlMBAAAAAAAAAAAAoP/Y3w5gfzsAAACwqcaO/VBVJnd6VSbb5fAI/aljZp4dL7/6eqzt6oq77n943YGGQ3c+0GcjSf1cTXpq/KS+yWFdReq22qGRaZ3suydJJdSZsy63HQAq0Ozv/cQ1UOqjBoyYFmdd9PNo7+iU+qXZcxbGQ48+b9hBhXv0t8/E8aecGwN75pL5LEnl07SmPeLm2mHWnCSpzJpX3xhD01PMuiSWzi6oq5v4YZtmAQAAel9EjLXqBwDAZsi7mwYo+NnbS8cB/uh5UwEAAAAAAAAAAACg/9jfDmB/OwAAALCZqofn9q7KZH/v8Aj9qcaxB8cVc2/8r1+c3lm1KuYvuDuOmXl2bLfDvj4jSeqv63N6SsyvbXBYV7EOBKtrjLrMVN89SSqBpn/65Fizdq3tAFBhrvnFgqge3uY6KPVhBx13drR3dEpF76Krbo/fPfuKYQf8l9889tS6dagBI9z/SVK5NCiTjeMad4nFNXXWnSSpzNbRh6X3MeuSWDr3H3bLAgAA9L6IOM1qHwAAmyHvbhqg4GdvLx0H+G91JgMAAAAAAAAAAABA/7C/HcD+dgAAAGALbNMy7eOpdO4XDo/QezvkuK/F8y++/Ge/PC1/fUVcff0tceBnT3OwtST1QyNbJ8XttUMd1lWkvj+kNQb63klSv9a656Hxwu9ftg0AKsyCRYtj8I77uQ5KfVzDbp+K71y5INo7OqWi9b1r74qXXl1h2AEf6JHHn4rjTzk3BoywBiVJZbO21TIpvlffat1JksqoeXWNMSy9jzmXzE60WxYAAKB3RcR8q3wAAGyGvLtpgIKfvb10HOC/HWkyAAAAAAAAAAAAAPQP+9sB7G8HAAAAttzWVensjFQ6u9rhEfpTw3Y9KK6Ye2N0d3e/71eo5198OS7tmBfTjjjJZyVJRWyXlr3jnpp6h3UVqXOGjfS9k6R+6t1D1H99+/22AECFuffB30T9mANcB6Ui9YWvXx7tHZ1SUbr6pgfirZWrDTtgo37z2FNx/CnnrnsuNK8lqTzar2lc/Lp2mLUnSSqT5tU1xrD0PmZc8upOZbIH2ioLAADQOyLir3p63eoeAACbIe+OGqDg528vHQf4b5eYDAAAAAAAAAAAAAD9w/52APvbAQAAgF5SnZ4yKpXOPuEACb23T37u9Hj2hZfW+4vUI088HedcOCfGTD3G5yVJRWhS856xuKbOYV1F6rjGXXzvJKkfevcZA6gsyx57Mrbf/WDXQKmI7Z7/YrR3dEp93q8WPRpru7oNO2CT/Oaxp+KYmWdH9fA2c1uSyqCa9NQ4uWF0PDS41vqTJJVB8+obY1h6HzMuYaXS2berRmR3tFMWAABgy0VEixU9AAA2U94dNUDBz99eOg7w35aYDAAAAAAAAAAAAAD9w/52APvbAQAAgF70sR0mfrQqnZvjEAm9t7qd9o/Zl82Nro0cfPrAw4/Had+8JFr3PNTnJkl92KTmPWNxTZ3DuorQ0praOKBpnO+dJBWx/NGnxNquLsv/UEGefOaFyEw43DVQKnIDhrfFmRf+LNo7OqU+afachXH/smcNOmCLLHvsyThm5tlR3TO3zG9JSn6jWifFD4a0WIOSpDJoXn1jDEvvY74lrFQ6+3xqZG6AnbIAAABbJiKOtpIHAMBmyrujBij4+dtLxwH+27svffrfpgMAAAAAAAAAAABA8dnfDmB/OwAAANAHqtLZQ6vSubccJKH3Nu2Ik+KJJ5/b6K9Ua7u6YsGixTHj1PNiyM4H+OwkqQ+a2Dw+7htc57CuIrRkcG1km/f0vZOkIpQef3i89PKrlv6hgrz40iux05SjXQOlfurAf/q3aO/olHq9i666PX777CsGHdBrHn70d3HMzLOjenibGS5JZdDB24+NhbVDrENJUsL7SX1T1Kanmm0JK5XJLfnYDhM/apcsAADA5ouIS63gAQCwmfLuqAEKfv720nGAPzfBdAAAAAAAAAAAAAAoPvvbAexvBwAAAPrIJ9LZxlQ6+6CDJPTeakfnY/Zlc2NtV1dBv1atfGdVzLtpYRw+4+sxaNR0n6Ek9WITm8fHfYPrHNZVhO6tqYvdW/b2vZOkPmzQyOmx6L6llvyhgryx4q3Y68ATXAOlfmzoLp+M71xxa7R3dEq91vevuzteWf6WQQf0iaWP/C6OmXl2VA9vM8slKeHVpKfGyQ2jY8ngWmtRkpTg5tQ3x3aZrNmWsFKZ7M+3yuf/2i5ZAACAzfPuspWVOwAANlPeHTVAwc/fXjoO8OdOMx0AAAAAAAAAAAAAis/+dgD72wEAAIA+tO2IKf+zKpO9xEES+sumHjozHv3tM5v0y9Vry1fEFXNvjGlHnOSwQ0nqpfZumRD3Da5zWFcRWlQzJHZoneR7J0l91OzL5lruhwry1tsr1/224Pon9X/Hf+2yaO/olHqlufMfiLdXrjbogD5330OPxMGf/6pZLkll0JjWiXFVfbO1KElKcBcPycTAdNZcS1rp3Dl2yAIAAGy6iPj7nrqs2AEAsJny7qoBCn4G99JxgD/3M9MBAAAAAAAAAAAAoPjsbwewvx0AAAAoglQme2BVOve6wyT03gaNmh5nzro8Vq9es8m/Yj37wktxace82OvAE3yWkrSF7d0yIe4bXOewriJ0c+2waGrdx/dOknq5w44/I7q7uy33Q4V493eET37uK65/Uom0674nRHtHp7TF3XznY7G2yz0dUFz3PPCbyB99ipkuSQmvuqcjth8bd9bUW4+SpIT2naHD113PzbVklcpkj7A7FgAAYNNExF5W6QAA2AJ5d9UABT+De+k4wJ97paetTQgAAAAAAAAAAACA4rK/HcD+dgAAAKBIPpGZPqgqk73NYRL6y8bvPyMeXPb4Zv+i9cgTT8c5F86JnaYc7fOUpM1s75YJcd/gOod1FaGf1zXG0PQU3ztJ6qVGTTwyXnntdUv9UCG6urrj2BO/6fonldLh9cPb4usX/CzaOzqlzWr2nIVx79JnDDmgXy1YtDgmffKfzXZJSnhN6X3i/KEjrEdJUkL7xrBR5lnCSqWzq6tac7vbHQsAAFC4iDjF6hwAAFsg764aoOBncC8dB3i/ISYEAAAAAAAAAAAAQHHZ3w5gfzsAAABQTGPHfqgqkzu9KpPtcqiE3tugkdPjzFmXx6pVqzf7V613D9a+6/6H47RvXhLN4w7xuUrSJrZHy15xR80Qh3UVoR/WN8d2mazvnSRt6XPEqOlx9+JllvihQnR3d8fMM2a7/kklWP7Ys6K9o1Pa5C6++o54+oXXDDmgZO435920MHbJHWu+S1LCm9w8PubXNliTkqQENrNhJ7MsaaWzLw8Y0VZrcywAAEBhIuJaK3MAAGyBvLtqgIKfwb10HOD9DjIhAAAAAAAAAAAAAIrL/nYA+9sBAACAflCVbptUlcm+5FAJ/WV75I+L+x96dIt/4Vq1anXMX3B3zDj1vKgfc4DPVpIKbHTrxLildpjDuorQhUOHx8B01vdOkragSzvmWd6HCnLGuZe59kkl2tBdPhnfueLWaO/olAruinn3xKuvv23AASVnzZq18f2rfhGZCYeb85KU4GrSU+PkhtGxZHCtdSlJSlgzGnc2yxJWKp174B8b8//LzlgAAICNi4inrMgBALAF8u6qAQp+BvfScYD3O9uEAAAAAAAAAAAAACgu+9sB7G8HAAAA+sk2LdM+nkpnb3CohP6yQSOnx2nfvCTeentlr/za9caKt+Lq62+Jw2d8fd1/ts9YkjZcU+s+Ma++0WFdReg7Q4fHgEzW906SNqMjTjgzuru7Le9DpexkmX2la59U4h331UujvaNTKqjrb10a76xaY8ABJe3tle/E7MvmRuPYg816SUpwu7TsHT+pb7IuJUkJallPR26/mzmWsFKZ7M+3yuf/2s5YAACA9YuIf7AKBwDAFsq7swYo+DncS8cB3m++CQEAAAAAAAAAAABQXPa3A9jfDgAAAPSvravS2RmpdHa1gyX0l42ZekzcfvdDvfrL16vL34gr5t4Y0444KaqHt/mcJWk91WWmxhVDWh3YVYS+PXRkVPvOSdImtXP2s/HGircs7UOFOPfff+TaJyWgXafPiPaOTmmDzZ6zMO588Kno7jbfgORY/vqKOHPW5VE7Om/mS1JCe3cd5ojtx8ZdtfXWpiQpIS2tqY0DmsaZYwkrlcn9qy2xAAAA6xcRE6y+AQCwhfLurAEKfg730nGA93vZhAAAAAAAAAAAAAAoLvvbAexvBwAAAEpAdWvbDql09gkHS+h9h1sNb4uZZ8yON99a2eu/gj3z/Esx+7K5sWvbsT5rSfqABmWy8d0hwx3YVYT+ddgo3zlJKrCaHfPx4LLHLetDhbj4yutc+6QE/Y53xuzror2jU/rALpm7KJ5+4TXDDUisF37/8ro1q0Ejp5v9kpTQmlr3ifOHjrA2JUkJ6YGaupjcPN4MS1xTP2VHLAAAwAeLiBOtugEAsIXy7qwBCn4O99JxgA820JQAAAAAAAAAAAAAKB772wHsbwcAAABKRM2I/N9XpbM/dKiEPqidphwdCxYt7rNfwx554uk4c9blkZlwuM9bkt57KHpPpzfs6MCuInRyw2jfOUkqoCvn3mg5HyrEf8y53nVPSlj7HnNmtHd0Su/rRzfcH2+8udJwA8rCE08+F8fMPDuqh7eZ/5KU0KY37xG/rh1mfUqSEtC9NXUxrmUv8ytBpdK5lVXDp462IxYAAOD9IuKHVtsAANhCeXfWAAU/h3vpOMAHy5kSAAAAAAAAAAAAAMVjfzuA/e0AAABAialKZw+tSufecsCE/rJ3Dyeccep5sfz1FX32q1hXV3fcdf/DMfOM2TFsl4N87pL0n81o3DmW1tQ6tKuP+2LDGN83SdpAnzvpW5byoULMuXb+ut8BXPukZFU/5sCY9f1fR3tHp/Rf3Xr347G2q9twA8rOsseejGNmnu0eQJISWm16apwxbMdYan1Kkkq+RTVDYqeWieZXgkqlcy+kRuYG2A0LAADw5yLiEatsAABsobw7a4CCn8O9dBzgg51uSgAAAAAAAAAAAAAUj/3tAPa3AwAAACXoE+lsYyqTfcgBE/qgMhMOjxtuWdTnv5C9s2pVzF9wd8w49byo22l/n72kim9S857rDqtyaFffdkLjGN83SfqAdm07Nla8+balfKgAP77uVzFgRJtrn5TQPv+VS6K9o1OKC350Wzz8xIsGG1D27rz/4Zh2xEnuAyQpqb87tuwd19Q3WaOSpBKvs2ZoZFonm12JKnv/Ni0TPmI3LAAAwB9FxN/11GV1DQCALZR3dw1Q8LO4l44DfLCfmhIAAAAAAAAAAAAAxWN/O4D97QAAAECJqh6d/9tUJjfL4RJaXyecNiuWv76iKL+Wvfvfc+XcG2Pfo77sYG9JFd2o1knxi7pGh3b1Yct6+sz2u/q+SdJ7qh9zQDzy+FOW8aECXD//thg0crprn5TgxuSOi/aOTlV4P5h3d7z82psGG1BRFixaHHvmj3c/IEkJbGA6G//UuEvcP7jOWpUklXA31jbEsPQ+ZleCSqVzc7fa6it/ZTcsAADAuhedjbaiBgBAL8i7uwYo+FncS8cBPthvTQkAAAAAAAAAAACA4rG/HcD+dgAAAKDEVbdmD65K595wyIQ+qPT4w+Lq628p6i9nL/z+5bi0Y15MO+IkfwNJFVldZmpcNCTj0K4+bFlPn2/cxfdNkv6zYt/zA/3jZ7+8PQaNnO66JyW86uFt8bX266K9o1MV2vW3Lo13Vq0x2ICKtGbt2rhy7o0xcuKn3RdIUgIb0ToprqhvtVYlSSXcNfVNUZueam4lq9PtggUAAFj3orMjraYBANAL8u6uAQp+FvfScYAP1tXTR0wKAAAAAAAAAAAAgOKwvx3A/nYAAAAgAaozU+uq0tl7HDCh9XXY8WfE8y++XPRf0R797TNxzoVzYufsZ/0dJFXWIek9fbFhTCytqXVwVx+1rKfPN+7i+yap4jvx69+1fA8V4KZb74rtdtjXdU8qk6YffUa0d3Sqwpo9Z2Hc+eBT0d1trgGsfGdVtP/H1TFsl4PcG0hSAvtk0+5xV2299SpJKtG+V98aA82rJNVdPTw7zS5YAACg0kXEOVbRAADoBXl31wAFP4t76TjA+o00KQAAAAAAAAAAAACKw/52APvbAQAAgIRobMz/j1Q69+13D1lw0IQ+qGG7HhRXzL0xuvvp1NYHHn48TvvmJZEef5i/h6SKqa1pz7inxqGCfdWyno5r3MV3TVLFNvlTX4pVq1ZbuocyN3/B3TF4x/1c96Qyqm6nA+O8H9wS7R2dqpAumbsonn7hNUMN4C/84ZXlcdKZF8SgkdPdI0hSwmpK7xP/PiRjvUqSSrTZQ4ZHtXmVnNK5N6pbpjXZBQsAAFSyiLjB6hkAAL0g7+4aoOBncS8dB1i/Q00KAAAAAAAAAAAAgOKwvx3A/nYAAAAgYbZNT52QSudecNiE1tf0T58cTzz5XL/9qra2qysWLFocM049L4bufKC/iaSyb8fWiXFDbaODu/qoZT0d37Cz75qkimv73Q+Op5590bI9lLlfLrg7Bu+4n+ueVIZ97pR/j+OMoAgAACAASURBVPaOTlVAV9+0OFa89Y6hBrABj/3umThm5tnuESQpge3XNC4W1g6xZiVJJdhXh+1gViWq7O+2HTHl/9gBCwAAVKqIeNqqGQAAvSDv7hqg4GdxLx0HWL9/MykAAAAAAAAAAAAAisP+dgD72wEAAIAE+njT1G2qMtkbHTSh9VW30/5x0Q+ujbVdXf36C9tbb6+Ma35+axx6/BkxaOR0fxtJZdvgdDbOGjYqljm4q8/6l8adfNckVUwDRrTFzQvvtWQPZe76+bfFoFGelaVybfTUz0d7R6fKuNlzOuOOxb+Lru5uQw2gQAsWLY7x+89wryBJCWtoekqcM2ykdTBJKsG+0DjGrEpW87caO/ZDdsACAACVJiI+2pPFdQAAekPeHTZAwc/jXjoOsH7XmxQAAAAAAAAAAAAAxWF/O4D97QAAAEBybV2Vzs5IpbOrHTah9bXXgSfEg8seL4lf25a/viKumHtjTDvipKge3ubvI6ksyzXtEXfUDnF4Vx91YoMDwSRVRt++6IeW66HMXXfTwhg0crprnlTmnf6da6K9o1Nl2KU/WRRPPf+qgQawGbq6uuOqeTdHevzh7hckKYHrYLfWDrNmJUkl1LKejtp+N3MqUWW/ZesrAABQaSJitFUyAAB6Sd4dNkDBz+NeOg6wfr8zKQAAAAAAAAAAAACKw/52APvbAQAAgISrGpHdsSqT+63DJrS+Bo2aHmfOujxWrVpdMr+8PfP8SzH7srmxa9ux/kaSyq6W1snRUd/iAK8+6sSGMb5nksq6g479Sqzt6rJcD2Xs2hsWxKCR013zpEo4cP6or0V7R6fKrJ/e/FC8tXKVgQawhd56e2Wcc+GcqB2dd98gSQmqJj01Tm/YMR4eXGvdSpJKpKU1tXHA9uPMqQSVymQ/becrAABQSSLiSKtjAAD0krw7bICCn8e9dBxg/bp7+l+mBQAAAAAAAAAAAEDfs78dwP52AAAAoAzUjMj/fVU6+yMHTmhD7ZI7Nu64Z0nJ/Qr3yBNPx5mzLo/0+MP8nSSVTdU9Hde4SyxxoGCf9I1ho2JAJuu7Jqns2nHyUfHKa69bqocyds3Pb42BI6a55kmVctj86P3j3MtvjvaOTpVB352zMO588Kno7jbPAHrT8y++HDPPmB0DRrS5f5CkBLVXy4S4qa7BupUklUgP1NTFxObxZlRCSqVzK6tb23aw8xUAAKgUEXG2VTEAAHpJ3h02QMHP4146DrBhw00LAAAAAAAAAAAAgL5nfzuA/e0AAABAGalKZw9NpbNvO3hC66t6eNu6gwlXvPl2yf0St7arKxYsWhwzTj0vhux8gL+XpLJoXMte8ctaBwr2RecPHREDfccklVE1O+bjgYcft0QPZazjJzfFgBFtrnlShXXM/70w2js6lfAu/+nd8cIf3jDMAPrQA0sfi+mfPtn9gyQlqMHpbJzesGMstW4lSSXR3TVDYkzrRDMqIaXS2ecHZLIpu14BAIBKEBE/sRoGAEAvybvDBij4edxLxwE2bH/TAgAAAAAAAAAAAKDv2d8OYH87AAAAUGYGtE7dPpXJPuTgCW2o0ft8Jn59+/0l+6vcyndWxbybFsbhM74eg0ZO9zeTlOjqMlPjnKEjY5lDvHq9S4akY7tM1vdMUlnUcc18y/NQxq6Ye2MMGNHmeidVYDtOOTbaOzqV4G5YuCzeWbXGMAMokptuvSvGTD3GfYQkJahdW/aO6+q2t3YlSSXQwtohkWmdbD4lpXT29rq6iR+26xUAACh3EfGgVTAAAHpJ3h02QMHP4146DrBhXzYtAAAAAAAAAAAAAPqe/e0A9rcDAAAAZah6dP5vU5ncLAdPaGMdM/PseOW110v6F7oXX3olLu2YF9OOOMnfTFKim9g8Pm6qa3CQVy/3w/rmqE9P9R2TlOiO+7/ftjQPZez7V/0iqoe3ud5JFdyp582N9o5OJayLrro9fvO73xtkAP1gzZq1ccmV10XDbp90LyFJCWlgJhszG3aKhwbXWr+SpH7uF3WNMTQ9xXxKTNnL7HgFAADKWURs3dObVsAAAOgleXfZAAU/k3vpOMCGXWpaAAAAAAAAAAAAAPQ9+9sB7G8HAAAAylhVJndIVTr3hoMntKHS4w+Lq6+/JRG/1j3yxNNxzoVzYqcpR/vbSUpkg9PZOLlhdCxxoGCv9tO67aPRoWCSEtreB30hVr6zytI8lKnZ3/uJa52kyH769Gjv6FSC+tEv7o/X3njbIAPoZ6+89np8+awLY9DI6e4pJCkhjWmduG7dxvqVJPVvP65vXrc/wWxKRql027F2uwIAAOUqIqqsegEA0Ivy7rIBCn4m99JxgA271bQAAAAAAAAAAAAA6Hv2twPY3w4AAACUuVRL25CqdO5eh09oYx12/Bnx/IsvJ+JXu66u7rjr/ofjtG9eEs3jDvH3k5S4dm3ZO66ta3KYVy92Q11DtLbu4/slKVE1jj04nnr2RcvyUKbOOv8HrnWS1lUzOh/nXn5ztHd0KgEtuOeJWNvVZZABlJBHf/tMHHr8Ge4rJCkhDezpiw1j4qHBtdawJKkfu3Do8BiQyZpNCSiVzq7ednhuV7tdAQCAchQRY612AQDQi/LusgEKfib30nGADXvOtAAAAAAAAAAAAADoe/a3A9jfDgAAAFSAurqJH05lcudVZXLdDqHQhhq260Fxace86OrqTswveKtWrY75C+6OGaeeF3U77e/vKCk5Bwqms3FC487xQE2dA716qVtqh8VOLRN9vyQlogEj2tbdxwLl591n6pP/9QLXOkl/1mdO/m60d3SqhLv0J4viyedeNcgAStiCRYtjz/zx7i0kKSHt3DIxrq1rsoYlSf3Yvw0dZSYlpxerW/epstsVAAAoNxFxpFUuAAB6Ud5dNkDBz+ReOg6wYe++XOnvTAwAAAAAAAAAAACAvmV/O4D97QAAAEAF2ba1ba93D19wAIU21vRPnxyP/+7ZxP2a9/obb8bV198SB372tKge3uZvKSkRjWydFFfUtzrQq5e6p6Y+JjWP992SVPJ987tXWo6HMrS2qyu+8JVZrnOS3v/sN+mz0d7RqRJt3q+XxJtvrzLIABJgzdq1ccXcG6N53CHuMSQpAQ3s6YsNY+KhwbXWsSSpnzqhcYyZlJBS6dyiurqJH7bTFQAAKCcRcZYVLgAAelHeXTZAwc/kXjoOsHGtJgYAAAAAAAAAAABA37K/HcD+dgAAAKDCfLxp6jZVmdxNDqHQxqodnY/Zl81ddyB4Ej334h/i0o55sdeBJ/h7SkpE+zWNi5trhznUqxd692DGQ5rG+l5JKtkOOObUxN5nA+u3atXqOOqL33Cdk7TeTjn36mjv6FQJ9e9X3RFLHnvBEANIoNeWr4hTz744Bo6Y5j5DkhLQzi0T49q6JutYktQPLevp8O13M48SUiqdvdAuVwAAoJxExI+sbAEA0Ivy7rIBCn4m99JxgI2bZmIAAAAAAAAAAAAA9C372wHsbwcAAAAq0lf+qiqTO7EqnV3rIAptrL0OPCEeXPZ4on/he+SJp+PMWZdHZsLh/qaSSrqBmWwc17hL3FtT73CvXjgY7OSG0b5XkkquUROPjJdffd0yPJSZt95eGQcd+xXXOUkbbMrhp0V7R6dKpJ/e/FCseOsdQwwg4R54+PHIHjbTvYYkJWIdLBdfbBgTDw2utZYlSUVuac+1N9u8p3mUkKrTuaPscQUAAMpFRCyyogUAQC/Ku8sGKPiZ3EvHATbuBBMDAAAAAAAAAAAAoG/Z3w5gfzsAAABQwarTbWNTmewzDqLQxho0cnqcOevyWLVqdaJ/6evq6o677n84Zp4xO4bufKC/raSSraF1Spw1bFQsdbjXFvftoSPXHdLoeyWpJO6rR02PuxcvswQPZWb56ysie9hM1zlJG23wjvvFOd/7ZbR3dKofu/BHt8W9S5+J7m4zDKBcdPdc1K+ad3O07nmoew5JSkA7t0yMa+uarGNJUpG7t6YuxrbsZRYloFQm9051a9sOdrgCAADlICKes5oFAEAvyrvLBij4mdxLxwE27hwTAwAAAAAAAAAAAKBv2d8OYH87AAAAUOFSo9r+oSqdvc5hFCrocKvsZ+P2ux8qi1/93lm1KubdtDAOn/H1GDRqur+vpJJsp5aJcXl9qwO+trBLh7RGTXqq75Skfu/7V/3C8juUmZdefjXG7z/DNU5SwR15Ynu0d3Sqn7rqpsXx2htvG2AAZer1N96MU8++OAaNtO4jSaXewJ6+2DAmHhpcay1LkorYbbVDY3jrJLMoAaXS2ecHjpi2rR2uAABAkkXE/9fTWqtYAAD0orw7bYCCn8u9dBxg435sYgAAAAAAAAAAAAD0LfvbAexvBwAAAHjX1lXp7IxUJveOAym0saqHt8XMM2bHijfL5/DZ15aviCvm3hjTjjhp3f9//s6SSq19m8bF/NoGh3xtQdfUN0VTeh/fJ0n91vGnnGvpHcrMU8++GDtNOdo1TtImNXziZ6K9o1NF7rs/XBh3PvhUdHd3G2AAFeDhR38X04/8snsPSUpAO7dMjGvrmqxlSVIRu6GuIYZZO09EqUz2lq3Gjv2Q7a0AAEBSRcR2Vq4AAOhleXfaAAU/l3vpOMDGLTIxAAAAAAAAAAAAAPqW/e0A9rcDAAAA/JdtR0wZnsrkHnUghQpp9D6fiV/ffl/Z/Rr4zPMvxezL5sYuuWP9nSWVVAMz2Ti6cde4tXaYg742swW1Q2Nsy16+T5KK3vj9Z8TbK9+x9A5l5KFlT0R6/OGucZI2q/97zlXR3tGpIjXn5/fFS6+uMLwAKkx3d3dc8/NbY8Ten3b/IUklvwaWiy81jokHa2qtZ0lSkfpxfXNsl8maQwkolc59285WAAAgqSJiN6tWAAD0srw7bYCCn8u9dBxg454zMQAAAAAAAAAAAAD6lv3tAPa3AwAAAPyZfxia/btUOvsDB1Ko0Gacel68uvyNsvtV8N3DFu9evCy+fNaF0bT7p/ytJZXQwYLZOGL7sXFz7TCHfW1G7x7IeGjTWN8lSUVr+90PjiefecGyO5SRW++4P4bufKBrnBLV0F0PjurhbT6LEmnyoadEe0en+rjvzlkYix54Mrq6ug0vgAr25lsr48zzvhfb7bCv+5D/x96dR1lZ3om+T25On3N6ndXn9j19V+dYTNbEDLU3BTILKCgo7CqQLSgOqAk4RFFMiHNMcCbEgcImCYpGKWIiGURNRANKORsHVBQjapxxVgSVoep3KU6vrOTG6C6oXfXuqs9nre9/vbrb/b68z7Pf59n1SFLCG9p3bPymrLf1LElqoRZ16xed0hljUAG0V6r6MDtbAQCAQhQR06xWAQDQzLJm2gA5fy/3R8cBvlz9zv6rUQMAAAAAAAAAAAAgf+xvB7C/HQAAAOBzdUhlskWpzIcOpVAu9Ro5LW5cfkebfUO4o74+1jz4RMw694ooHzLFNZeUiDqnM3FMrxGxqrS7A7+a2LM7O7/HQAeEScp7nSqrY9W9j1pyhzZk+W2rY+99DvGMU0G136HfiXnXrozhk071eSSkvfeZHPOX3BU1tXXKUzfc8ki88fZHBi4A/uLFl1+PI0/+gbmIJCV9/SuVidN7DImnikutaUlSC/S97gONPwVQUSrzyV6V4/vZ1QoAABSaiDjDKhUAAM0sa6YNkPP3cn90HCA3xUYNAAAAAAAAAAAAgPyxvx3A/nYAAACAf+jrFVV7F6WqHnAwhXLtiG99P1594+02/aZw0+YtcfOtq2P6rAuiS/9Jrruk1j9cMJ2JY3qNiFWl3R361cR+0jUdpakJ7iNJeavm2psttUMbsnjpLdGpstrzTQXT3vtMjumnXxE1tXW7OnXu9T6XBHXMd676y7VR87Vw2b1x72MvxvYd9QYuAD7XynsejsHjZ5iPSFLCG9p3bNxS1st6liS1QCf2GmbsKYRSmT/vVTn+/7WrFQAAKCQRUWN1CgCAZpY10wbI+Xu5PzoOkJt9jRoAAAAAAAAAAAAA+WN/O4D97QAAAABfqLJyxj91SFed3yGdqXc4hXKpbPChsXDJ8thR3/YPrn3zrXfjmtoVMfGYM1x7Sa1e53QmZvQaHneXdnfwVxNaUdYz0hUHuYckNXvHzb4oGhoaLLVDG9D4b3nu5Us821RQ9R93fMxdeEvU1Nb9pQVL10Sf/af7fBJSasxxf3N9tOctu/2x2PjuJgMXAF9q27btsXjpLdF16BTzEklK9NpXVZzeY0g8XVxqTUuS8ti6ktKY3HuUsacwWvmVbPZrdrUCAACFIiJ+ZWUKAIBmljXTBsj5e7k/Og6QmylGDQAAAAAAAAAAAID8sb8dwP52AAAAgJwUpTKjd/aGgymUawcedlqsfWZDu3mD+NwLr8T8Rcti8PgZrr+kVq1TOrPrwKul5X0dAJZjD5WUx7g++7t/JDVbIyaeFJs2b7HMDm3A1q3b4oTvzvNsU+F8H+hXHYfMvDCuuvGeqKmt+7uOmn25zylBnfnDmz73OqlpLbrpvnjoyZdjR32DgQuAJnlj47txyjnmR5KU9Ib3PTBuLetlTUuS8thjxWUxou8Bxp3C6Pt2swIAAIUiIu6zIgUAQDPLmmkD5Py93B8dB8jNKUYNAAAAAAAAAAAAgPyxvx3A/nYAAACAnHWunLhXh1TmLgdTKNe69J8U581bHFs++bTdvEmsr2+Ihx9/Ztd/d++RR7gPJLVqI/scGAu6Vca64lIHgX1J63Z2eo8h7htJe1yPfQ+PF19+3RI7tAEfbdock447y7NNBVPvUdPjjHk3RU1t3T9s/pK7Yu99Jvu8EtLYI876wuulL+9Xd66N9z/6xKAFwB6554HHY3j1CeYnkpTgilOZOL/HwFhXYs1LkvLVfaXdIl1xkHEn8WXqO6SqDrKbFQAAKAQRscFKFAAAzSxrpg2Q8/dyf3QcIDcXGDUAAAAAAAAAAAAA8sf+dgD72wEAAACa6qsdUplZRenMVgdUKNeGTJgZdQ+tbXdvFbdu3RZ3rnkkZs65LPbe5xD3gqRWq3fFwXFmj0HxUEm5w8C+pKu79ovS1AT3jaTdqlNlddy1c/4HFL6Nb78XY6bM8mxTQdSxX3UcfPS58aPrVkVNbd2X1vg/63NLRl0GHBI/vObOnK6b/raf3vxAPPPCRgMWAM1m+/YdsXDJ8igeONk8RZIS3Jg+Y+Ku0h7WtCQpT92x8xnbLTXemJPwitJV73fuP6nEVlYAACDpIuJjq1AAADSzrJk2QM7fy/3RcYDc/NSoAQAAAAAAAAAAAJA/9rcD2N8OAAAAsFs6psYPKEplNjikQk054HnWuVfE+x9uapdvGD/atDluvnV1TD3+vF2fhXtCUmu0dzoTx/QaEb8r6+lAsC9oZVmPGNp3rHtGUpO7/Cc3WVqHNuCZP70U+4z7hueaCqJuww6PU+deHzW1dTl3/lW/9m4iQU0//YomXT/Vxa33rIvNn2w1YAGQFy+98kYcdsL3zFMkKcGVpCbE+T0GxjPFpda1JCkP/by8T3RJZ4w5Ca8onXmi46DsP9vJCgAAJFVE/LOVJwAA8iBrtg2Q83dzf3QcIDe3GDUAAAAAAAAAAAAA8sf+dgD72wEAAAB22//aZ+z/LEpnljqkQk0pNXp63Hzr6nb9tvH1je/EwiXLY9+JJ7onJLVKHXeW6bN/LOrWL55y4ODn9mhJWUztPdL9Iinnjjn1wqivb7C0DgVu9X2PRvdhh3muqSDaf+qc+OG1d0ZNbV2TG1z1LZ9hQuq7/7GxYOma3bqO7a1rf/1QbHjlHYMVAC1ixcp7o+9+R5qvSFKCa1zrWlPazbqWJOWhy7tVGmsKoKJU5sd2sQIAAEkVEcVWnAAAyIOs2TZAzt/N/dFxgNw8ZNQAAAAAAAAAAAAAyB/72wHsbwcAAADYY3ulqo7rkK7a7KAKNaWjT5kbr290CO5zL7wSF155faRGT3dfSGqVuqbGx4yew+Pmst4OB/uc5nfvH53TGfeKpC9sxMSTYtPmLZbVocD9dOkt0blyoueakj+HH3Z4zPrBkqiprdvtTj7/Wp9lgvruZcv26Hq2h1Y//Hxs3bbDYAVAi3r/w00x+3tXRcd+1eYskpTYda4Ju9ZyrGlJUvM3p8dgY00BVJSacLQdrAAAQBJFxECrTQAA5EHWbBsg5+/m/ug4QG7+bNQAAAAAAAAAAAAAyB/72wHsbwcAAABoFkV9Mt06pDOPO6hCTan7sMPiuptuj/r6hnb/BnL7jh2x6t5H46Sz5kfZ4EPdH5JapSF9D4zzewyMB0q7OiTsr/pleZ/oW3GQe0TS59Zt6NR47oVXLKlDAdtRXx/nXPITzzQVRPtPnROXXbMyamrr9qirbrwneux7hM80IR0w7cw9vqZttRtX/DFe2/ihwQqAVvXQ48/EqMknm7dIUoI7tPd+8UCJ9S1Jas6e3dlRvUcYZxJeUarq070qx/ezgxUAAEiaiMhYZQIAIA+yZtsAOX8390fHAXLziVEDAAAAAAAAAAAAIH/sbwewvx0AAACg2ZSVjf1vRemqKzukqxocWKGmVDX9u/HcC694DfmfPv1sa6xYeW9Mn3VBdOk/yT0iqcXrvLPJvUfF4m6peLq41IFhO2s8iLGq937uD0l/U8d+1XHbXfebwEIB27zl0zj6lLmeaUp83YZPi1N+sCRqauuarcNP+aHPNinfwQZMissWr2zW61voLbrpvnjkqVdiR329wQqARNi+fUcsXnpLlA+ZYv4iSUn97pwaHzXd+lnXkqRmbF1xaRzcZ7RxJuEVpaqe71JR9a92sAIAAEkSEcdaYQIAIA+yZtsAOX8390fHAXL3P4wcAAAAAAAAAAAAAPlhfzuA/e0AAAAAza4oncl0SGXedWCFmlKXAZPiwiuvj61bt3kV+VfefOvduKZ2RRww9VT3iaRWqWdqfJzUc1jcVN4n1pWUtusDw57d2dzu+0SXdMa9IWlX8xctM2GFAv++deBhp3meKdF17FcdBx99bsy/7g9RU1vXrF12zcro0v8Qn3NCOvK0y5v9Ghdqt695JjZt/tRABUAivfzaxjj8xPPNXyQpwR3ee2Q8XFrerte0JKk5a3ym7lMxzhiT9FKZW77yla981e5VAAAgKSLidCtLAADkQdZsGyDn7+b+6DhA7joaOQAAAAAAAAAAAADyw/52APvbAQAAAPLi33tP+HqHdOYOB1aoqQ2rOiHue/hJryM/x3MvvBIXXnl9pEZPd69IapV6VIyPY3qNiOu6puLp4tJ2e2jY70t7xtCKA90TUns/mPXE82NHfb1JKhSox5/6k+9WSny9Rh0d37lkadTU1uWtsUec5bNO0PVesHRNXq930rthxSPx59ffN0gBUBBW3vNwVB54rHmMJCW0vhUHxfXlFe12LUuSmruVZT2iW2q8MSb5fdfOVQAAICkiYq4VJQAA8iBrtg2Q83dzf3QcIHe9jRwAAAAAAAAAAAAA+WF/O4D97QAAAAD5k81+rShVdW6HVNV2B1aoKXXsVx1z5i6MTZu3eC35OXbU18eaB5+IWedeEeVDprhnJLVKjQdmHd57ZCzoVhmPF5e1u0PD1paUxck9h7kXpHba8OoT4qNNm01MoUCtWHlvlA0+1PNMia1T/0lx6ImXxBU3rI6a2rq8dvb8X/jME9R3Llma92uexBbddF889OTLu955AUAh+fCjj3etZzWua5nLSFIyO6bXiHa5jiVJ+egX5X2iSzpjfElyjfs0KzKjbFwFAACSICIWWE0CACAPsmbbADl/N/dHxwFyN8zIAQAAAAAAAAAAAJAf9rcD2N8OAAAAkHcdKjMDi1KZFxxcoaaWHjM9brvrfq8mv8CmzVvi5ltXx/RZF0TnyonuG0mtUklqQkzuPSoWdKuMR0vK29XBYT/tmo5uqfHuA6kd1XXolHhuw8smolCAGhoaYuGS5dGp0oH3Sm4Dx58Y51/166iprWuxBhx0vM8+IY0+7Lsteu2T0K33rItNmz8zSAFQ0B554tnYL3uy+YwkJbT+FePiF+V92tX6lSTlqyu6VRpbEl/mrY4VB3ewaxUAAGhtEXGjVSQAAPIga7YNkPN3c390HCB3E4wcAAAAAAAAAAAAAPlhfzuA/e0AAAAALaJzn4P/n6JU1XKHVmh3mj7rgnhj47teUX6Jxs/omtoVMWbKLPeNpFarcyoTo/oeEKf3GBJLy/vGuuLSNn9w2JrSbjGuz2jXX2oHdexXHbf/4X4TTyhAmzZv2fXd0rNMSa108JT45hlXx4Kla6Kmtq5FO+GcH7sGCalT/0lx6eI7WvweaI1uXPHHePmN9w1QALQZ27fviJprb46ywYea10hSEtevdta4dvV0O1i3kqR8N7vnUGNL0ktl6iorZ/yTXasAAEBriohbrSABAJAHWbNtgJy/m/uj4wC5O9LIAQAAAAAAAAAAAJAf9rcD2N8OAAAA0KKK0pnji1KZTxxeoabWffhhcU3tiqivb/CqMgfPvfBKXHjl9ZEafbT7R1KrVpaeEJk++8f5PQbG78t6tNmDw9aVlO76b9w7nXHdpTbcpTU3mmhCAXrx5ddj5KSTPMeU2A6YdmZcuviOqKmta5Wu/Nnd0XXY4a5FQjri1Pmtdi+0RD/+5f3x+LOveccHQJv18msb44hvfd+8RpIS2vC+B8btZT3b7HqVJLVEz+7siF4jjSvJ7zK7VQEAgNYUEfdaOQIAIA+yZtsAOX8390fHAXJ3ipEDAAAAAAAAAAAAID/sbwewvx0AAACgxXXsO7F3UbrqaQdXaHeaeMwZ8fxLr3pdmaMd9fWx5sEnYta5V0T5kCnuIUmtXv++42JGz+Hx467peKSka5s7QOyO0h4xqu8BrrXUBjtu9kVRX99gggkF5u77H4ueI6Z5jimRVYw5Lr598dKoqa1r9Q498RLXJCH1GnV0LFi6JhH3RXN36z3r4uMtYnUGdQAAIABJREFUnxmcAGgXbll5b6THTDe/kaQEVpzKxPk9BsYzxaVtbp1KklqqtSVlMbrPGONKsmsoSldNsFsVAABoLRGxzooRAAB5kDXbBsj5u7k/Og6Qu/OMHAAAAAAAAAAAAAD5YX87gP3tAAAAAK2iy4gR/70oXXWlwyu0O5UMzMb8Rcti27btXls2waaPt8TNt66OqcefFx37VbuXJLV6nVOZGNX3gPhWz2Fxddd+cXdp9zZxgNi64tI4q8eg6JzOuM5SG2nUId+KTZu3mFBCgblx+R3Rpf8kzzEl773GoEPjiFPnx1U33B01tXWJ6JKf/C46VU50fRLS6RfdkJh7ozn6+e2PxetvfWhgAqBdrsvMmbvQmowkJbRMn/2jrqRbm1ibkqTW6P7SbpGuOMiYkuCK0lXvf73vhGK7VQEAgNYQEa9aLQIAIA+yZtsAOX8390fHAXL3IyMHAAAAAAAAAAAAQH7Y3w5gfzsAAABAq9qroqq6KJ15zyEW2p32z54Sjz31nFeXu+GNje/GwiXLY9+JJ7qXJCWq3hUHx+Teo+LMHoNiaXnfWFtSVrCHiP2urGeM7HOg6yoV+nNp5BHx51ffNIGEAvLZ1q1x6nlXeoYpcXXsVx0HHnFmXLr4jqiprUtco6fOcZ0S0n5Tvp3Ie6SpLfn1Q/H0829GQ0ODwQmAdu3u+x+LgQd9wzxHkhJY19T4WNCtsmDXoiSptbujtMeuZ6kxJbkVpase7tkz+1/tVAUAAFpaRHxglQgAgDzImm0D5Pzd3B8dB8jdIiMHAAAAAAAAAAAAQH7Y3w5gfzsAAABAq9urcnznDumqex1iod2pU2V1zJm7MD7e/IlXmLvpuRdeiQuvvD4q9j/KPSUpcXVOZ2K/vgfEt3oOi6u79ovVpd0L6hCxp4tLY06PwTv/O1xLqRDbe59D4sHH1pkwQgF57c23Y9y00z3DlLgGjj8xzrn85qiprUts371smWuVmPddE+OSn/4+0ffLF7Xopvvi/ideim3bdhiYAOA/Na5jnXXxoujYr9p8R5IS2OG9R8bDpeUFtQYlSUnpZ10ronMqYzxJcEWpzOV2qQIAAC0tIrZaIQIAIA+yZtsAOX8390fHAXJ3vZEDAAAAAAAAAAAAID/sbwewvx0AAAAgGbLZr3VIV53fIZXZ4SAL7dbh1Ad9I+5a84jXmHtg+/YdccfdD8WM71waJQOz7itJia1ranwc0HdMzOw5PC7pPiB+Ud43HinpmuiDxH5b1iuGVhzo+kkF1g03/94kEQrIfQ8/GanRR3t+KVF1Gz4tZp69KBYsXRM1tXWJr3LsDNctKQe6nzKvIO6Zv27hsntj1UPPx5ZPnIsFAP/Iw48/E/tOPNF8R5ISWCp1UCwt75vo9SZJSmoX9tjHWJLsGjqkJ0yySRUAAGgpEfE1q0IAAORJ1owbIOfv5/7oOEDufmnkAAAAAAAAAAAAAMgP+9sB7G8HAAAASJSOqeoRRenMqw6y0O42fdYF8cbGd73O3EObPt4SN9+6OqYef1507Fft3pJUEHVLjY+xfUbHyT2Hxfzu/ePmst6xtqQsMQeJrdvZxd0HRFl6guslFUDnzVtsUggFoqGhIRYuWR6dKyd6fikxddp5P1Z94/sx/7q7oqa2rmD65hlXu34JqceII+OqpWsK5t757aqn4p0PNhuUACAHn362NS688nrfYSQpgXXc2Yyew+OJBK0vSVKhNHPn89NYktyK0pkPOvefVGKHKgAA0BIi4l+sCAEAkCdZM26AnL+f+6PjALm7zcgBAAAAAAAAAAAAkB/2twPY3w4AAACQOF0qqv61Q7rqFw6z0O7WffhhcU3tiqivb/Basxm8vvGdXQfUD68+wf0lqeDqvLOBFWNjUp/94qSew+KC7vvE4q6puL2sZzxe3DoHIq4q7R5VO///cX2k5HbYCd+L7Tt2mAhCAdi0eUscN/tizy4lqqHVp8T5C34bNbV1BdcVP1sdZYOnuo4JafYFP0v8PbP01kfjpdfeMyABwG54ev2LceBhp5n3SFICG9L3wLilrFerrCNJUqG2rrg0Du4z2jiS4IrSmSc6Dsr+sx2qAABAvkXE160EAQCQJ1kzboCcv5/7o+MAuVtt5AAAAAAAAAAAAADID/vbAexvBwAAAEiqr3ZMV51clKr61IEW2t2qjzkjntvwslebzWjtMxvivHmLo2L/o9xjktpEvVMHx+g+Y+LI3iNiTo/BcXm3yripvE/cU9o91uX5ULGru/bb9X/fdZCS1fDqE+LDjz428YMC8OSzG2Lw+BmeXUpMffc/NmZf+LOoqa0r6CbNvMD1TEgjs6cn9j5ZvPzBeGL969HQ0GBAAoA9sHXrtph39dLoMmCS+Y8kJazO6Uyc02NgrCspzet6kSS1pR4qKY/+FeOMI0kuVVVjayoAAJBvEVFsFQgAgDzJmnED5Pz93B8dB8jdg0YOAAAAAAAAAAAAgPywvx3A/nYAAACAROtUMaFXUSrzpAMttLs1HkJ44ZXXx2dbt3rF2Yx21NfHmgefiFnnXhFlgw91r0lqs5WkJkT/vuNibJ/RcXjvkXFyz2FxZo9BMb97/7iuaypuLusdq8u6x7ri3TtQ8Y8l5bv+d3ZKZ3zeUgLqPuyweG7DyyZ7UAB+uWKV7yJKTOVDp8b006+Iq268J2pq6wq+CxfdFp36Vbu2CajxOly083ok6f5YdNN9cf8TL8XWbTsMRgDQjJ59/s9x0BHfNgeSpAQ2us+YWFXafbfWgSSpPXZHWc/omhpvDElwHSsy0+xMBQAA8ikieln9AQAgT7Jm3AA5fz/3R8cBcvekkQMAAAAAAAAAAAAgP+xvB7C/HQAAACDxvt53zP/okM4sdqCF9qQhE2bGPQ887jVnHny0aXPcfOvqmHr8edHRoduS2uuhUzvrnTo4hlYcGAf3GR3Z3qPiqN4jYmbP4XF6jyFxXvdBcUn3AXFFt8r4Sdd0LC3vG78p6x2/L+sRa0q7xZKuqRjad6zPUmrFOldOjLvvf8zkDhLus61b4/TzF3huKRGVDDo0pp0yLy6/flXU1Na1qUZOnu0aJ6QpJ12aiHvi6mX3xqqHno/Nn2w1GAFAnmzfsSMWXPPLKBmYNQ+SpITVNTUh5nfvH+uLSyRJOXRD177ROZUxhiS1VNVHHVIHl9uZCgAA5EtEDLDyAwBAnmTNuAFy/n7uj44D5G6DkQMAAAAAAAAAAAAgP+xvB7C/HQAAAKBgdEhPmFSUrnrfwRbak2bOuSzeff8jrzvz5LU3346FS5bHsKoT3G+SpIKs+7DD4nvzFvss2mE/XXqLyRwkfdfGS6/FmCmzPLPU6nXqPykOPvrcuHTxHVFTW9cmm33hDa51Uuan+06Lq5auabV7YeGyulh5//r4YNMnBiIAaCF/fvXNmPzNs82FJCmBHdZ7ZDxS0jXWF5dIkr6k83sMNHYkuKJU5smOg7L/bFcqAACQDxEx1IoPAAB5kjXjBsj5+7k/Og6Qu1eNHAAAAAAAAAAAAAD5YX87gP3tAAAAAAXl630nFBelqh5wsIX2pF4jp8WNy++IhoYGrz3zaO0zG+K8eYuj735Huu8kSQXTt39QE59+tjUGj5/h82hP1/37C0zeIOFu+u0fonzIFM8stWqd+lXHuCPPjot+fHvU1Na16RYsXRN99z/WdU9Is36wpFXug9+ueireeX+zQQgAWkF9fUMsXnqL70GSlMDSFQfFTeV9Yn1xiSTpS/pmr+HGjgRXlMr82I5UAAAgHyJihNUeAADyJGvGDZDz93N/dBwgd28aOQAAAAAAAAAAAADyw/52APvbAQAAAApOZeWMfypKV13cIZ2pd7iF9qRDvnFWbHjpNa8+82zr1m1x55pHYuacy2LvfQ5x70mSEt0jTzy7a/xafd+j0bFftc+kHTTxmDNi27btJm2QUJu3fBonn/0jzyu1eqOyp8f5C34TNbV17abp37nStU9IIyaf1qLX/rernoq33v3YIAQACfDyaxvj0BnnmhNJUsLquLOTew6Lp4tLY31xiSTpH7Ru53NyXJ/9jR0Jrqhf9aF2pAIAAM0tIvazygMAQJ5kzbgBcv5+7o+OA+TubSMHAAAAAAAAAAAAQH7Y3w5gfzsAAABAwepQkRlVlKp63eEW2pNKB2Vj/qJlsW3bdq9AW8BHmzbHzbeujqnHnxcd+1W7ByVJiWp49QnR0NDwl3HrO3MX+lzaeAMP+ka8896HJmmQUM9teDlGTT7Z80qt2oCDTojvXrYsamrr2l3zr/tDlAw81H2QhMPa+1XHhYtuy/s1X37n2nhto7kRACRN4/uqX65YFb1GTjM3kqSENarvAXFnaY9YX1wiSfoHPVRSHv37jjNuJLSiVObDzv0nldiNCgAANKeIGGOFBwCAPMmacQPk/P3cHx0HyN17Rg4AAAAAAAAAAACA/LC/HcD+dgAAAICC9vW+E/+9KJ25zQEX2tP2z54Sjz653mvQFvTam2/HwiXLY2jmePegJCkRNY5Lf+3jzZ/E4PEzfDZttK5Dp8S6514yKYOEuvbnt0bxwMmeV2q1UmOOi1MvuD5qauvadVXHft/9kJCmnHRJ3q7zL+94Il567T2DDwAk3Bsb340jvmV+JklJqyQ1IS7uPiCeLS6J9ZKkz+22sl5Rlp5g3EhoRenMQ5WVM/7JblQAAKC5RMRYKzsAAORJ1owbIOfv5/7oOEDuPjJyAAAAAAAAAAAAAOSH/e0A9rcDAAAAtAVf7ZDOnFaUzmx1yIX2pI79qmPO3IWxafMWr0Nb2NpnNsR58xZHn1FHuhclSa1Sl/6T4q133v+7MerBR5+OTpXVPqM2VufKiXHH3Q+ZhEECffjRx3Hc7Is9q9Rq9Tvwm3Hy+dfGgqVroqa2rt33/Zrf7Hpf4t5o/brvOy2uuvGeZr2+P7/9sXjptfcMPgBQQBoaGuLG5XdE16FTzJEkKWFV994/HijtGuuLSyRJn9PirqnolM4YMxJbZp5tqAAAQHOJiIOt6gAAkCdZM26AnL+f+6PjALnbbOQAAAAAAAAAAAAAyA/72wHsbwcAAABoM/aqHN+vQzrznAMutKelx0yPm29d7ZVoK9i6dVvcueaRmDnnsth7n0Pcj5KkFuvoU+b+w/HpBz+61mfUxrqmdoWJFyTQvQ+vjf5jj/WcUuu8CzjwG/Gt7y2OBUvXRE1tnf6qYRNnuUcS0qy51zXLNV1666Px/MvvGHgAoIC98vpbccg3zjJHkqSE1afioLixa0WsLy6RJH1O5/QYaLxIbg1F6aoJdqECAADNISIyVnMAAMiTrBk3QM7fz/3RcYDcfWrkAAAAAAAAAAAAAMgP+9sB7G8HAAAAaFM6Dsr+c1G66kqHXKg5Om72RfHmW+96NdpK3vvgo7j257fG+CO/436UJOW92/9w/z8ck7Zu3Rb7Z0/xObWRzpu32EQLEmb79h0xf9Gy6FRZ7TmlFm/g+BNi1tzrYsHSNVFTW6fPadYPlrhXEtKIQ07bo2u57PbHYv2Lb0VDQ4PBBwDagMYxffHSW6J44GRzJUlKUB13NqPn8FhbUhbri0skSX/Vszs7otdI40Viy7zdKZ0psgsVAADYUxEx0UoOAAB5kjXjBsj5+7k/Og6Qu+1GDgAAAAAAAAAAAID8sL8dwP52AAAAgDapQ3rCER1SVZscdKE9rXzIlFi4ZHnsqK/3irQVbXjptZi/aFkMHj/DfSlJavb6jDoytm3b/oVj0dpnNkSXAZN8XgXesaddZF4HCfPchpdjzJRZnlFq8QZXfSu+c8nSqKmt05d01dI10WvkUe6bBNSpX3Vc9OPbm3wNb/rd4/H8y+8YdACgjXr2+T/HAVNPNV+SpIQ1tO/YuLWsV6wvLpEk/VVrS8piVN8DjBUJrShdteor2ezX7EAFAAD2REQM2tkvJEk5B0DusmbcAL6fS1IeusnIAQAAAAAAAAAAAJAfjb8J8rMogJw1GDkAAAAACsjXK6r27pDK3O+wCzVHBx52Wqxd97zXpK2svr4hHn78mZgzd2F0HTrFvSlJapbOm7c4p3Hoxzf8xudVwI07fHZs+eRTEypIyg6Mhoa4cfkdUTb4UM8otWgDx58Y3754adTU1qkJHXHqj9w/CWnqty7N+br9+g9PxqsbPzDoAEA7sH3Hjli4ZHl0GTDJnEmSElRxKhMXdR8QzxaXxHpJ0l9aXdo9elSMN1YktKJU1bl2nwIAAAC0HCveAE2SNXIAAAAAAAAAAAAAAABA4Wj8TZCfRQHkzsgBAAAAUGhGjPgvHdJV53dIZ+odeKE9rUv/SXHevMWxecun3pYmwKefbY0VK++N6bMuiM6VE92jkqTd7un1L+Y09jQ0NMQ3v32Jz6wA6z/22HjzrXdNoCAh3n73gzjqlLmeT2rRhlafEmfOvylqauu0G/3w2jtj730mu5cSUPd9p8VVS9d84fX67aqn4s13NhlwAKAdeuyp52LfiSeaN0lSwsr02T/uL+0W64tLJEn/2S/K+0TndMY4kcgy9R36TdjP5lMAAACAlmGlG6BJskYOAAAAAAAAAAAAAAAAKByNvwnysyiA3Bk5AAAAAApUx/SEsR3SmbcceKHmaPD4GXH3/Y95Y5ogb771bixcsjyGV5/gHpUkNamxh81u0pjz0abNMWTCTJ9dAdVj38PjuQ0vmzBBQvz2jrroPfIIzye1SJ0qJ8YB086Ic69YHjW1ddrDDjrqHPdVQpo197q/uz4Ll9XFrfesi7fe+9hgAwDt3JZPPo2zLl4UHftVmztJUoLqnTo4ri+viPXFJZKk/+yi7gOMEQmtKJ15tWhA9b/ZeQoAAACQf1a5AZoka+QAAAAAAAAAAAAAAACAwtH4myA/iwLInZEDAAAAoIB9ve/Efy9KZ2536IWaq5lzLot33vvQm9OEWfvMhjhv3uLoM+pI96kk6Uu79ue3NnmseeZPL0XpoKzPrwDqMmBS3PPA4yZIkACN351mfOdSzya1SCUDD42qb3w/Lvrx7VFTW6dm6rwrfuX+SkgjDjntL9fl6p/fG3fe/1y8/9EWgw0A8DfWPPhE9B97rPmTJCWojjs7ueeweLq4NNYXl0iSdvbNXsONEQmtKJ257Stf+cpX7TwFAAAAyC+r2wBNkjVyAAAAAAAAAAAAAAAAQOFo/E2Qn0UB5M7IAQAAAFD4vtohlZlVlM5sdfCFmqMe+x4e19SuiPr6Bm9QE2br1m1x55pHYuacy6LLgEnuV0nS37X3PofEex98tFvjzC9XrPIZFkA33Px7kyJIgBUr742++x3puaS812vkUTH99Cvi8utXRU1tnfLQoAknudeScAh7v+q49Ce/i7sf2RCbNn9qoAEA/qFNH2+JOXMXmkNJUsIa1feAuKu0R6wvLpGkdt9TxaUxus8Y40NSS2Vm2XIKAAAAkF9WtgGaJGvkAAAAAAAAAAAAAAAAgMLR+JsgP4sCyJ2RAwAAAKCN6FhRvU9RKvOCgy/UXE069sz404uveouaUB98+HHcuPyOmHjMGe5XSdJfmjnnsj0aX37wo2t9jglu3tVLTYKglb37/ke7nrWeScp3gyacFKd8f0ksWLomamrrlMdO+t5i91xCunShuQ4AkLsVK++N3iOPMI+SpARVkpoQF3cfEOuLSySp3fdAadeoqDjY+JDAitJVn+1VOb6fHacAAAAA+WNFG6BJskYOAAAAAAAAAAAAAAAAKByNvwnysyiA3Bk5AAAAANqQf+uW+ZeiVOYGh1+o2Q69GpiNH/3457F16zZvUxPsmT+9FN+ff22kRk9330pSO2/1fY/u0ZhSX98QR58y12eZwE747rxoaGgw8YFWdOeaR6LfAcd4JilvdexXHSMOOS3O/OFNUVNbpxbqqhvvie77TnMPJqD+Y4+NHfX1BhwAIGdvv/tBHHvaReZSkpSwpvYeGX8sKY/1xSWS1K77dXnv2DudMTYksKJU1fONey3tOAUAAADID6vZAE2SNXIAAAAAAAAAAAAAAABA4Wj8TZCfRQHkzsgBAAAA0AYVpTPHdEhXbXYAhpqroZnj454HHvdGNeHq6xtizYNPxKxzr4jyIVPcu5LUzqo88NjYUV+/x+PJpo+3xMhJJ/lME9Sk486KrVu3mexAqx3S/n7MnHOZ55HyVsmgQ+OQmRfExT/+XdTU1qkVmnqyf+NJaeU9Dxt4AIAmq/3Vyug2dKr5lCQlqH4V4+KX5X1ifXGJJLXrrurWz7iQ2DKL7TQFAAAAyA+r2ABNkjVyAAAAAAAAAAAAAAAAQOFo/E2Qn0UB5M7IAQAAANBGFfXJdOuQzjzu8As1Z40Hyb/7/kferBaATR9viZtvXR1Tjz8vOvardv9KUjvo4gU3NNs48tIrb0SfUUf6XBPQvhNPjA8+/NjkBlpBQ0ND1P76zug5YprnkfJS5biZ8c0zro7Lr18VNbV1asUu/envo1P/Se7LBHT0KXMNQADAbnn5tY0x6dgzzakkKUF13tmZPQbFupLSWF9cIknttpN6DjMuJLVUZrKdpgAAAADNzwo2QJNkjRwAAAAAAAAAAAAAAABQOBp/E+RnUQC5M3IAAAAAtGFlZWP/W1G66soO6aoGh2CouWo8UP6a2hVRX9/gDWuBeO3Nt2PhkuUxZMJM97AktdE69quOF/78erOOH48/9acoHzLF59uKVex/1K4DoYGW9+LLr0d2xjmeRWr2igdOjoOnnxtnX35z1NTWKUEdMO1M92gSDlyvnBivb3zHQAQA7JbGtav/uP7Xu+bd5laSlJwO6jM67i3tGuuLSySpXbZuZ+P67G9MSGBF6ar3i/pXdbLTFAAAAKB5Wb0GaJKskQMAAAAAAAAAAAAAAAAKR+NvgvwsCiB3Rg4AAACAdmCv1IQxRamqNx2EoeZs0rFnxnMvvOIta4FZ+8yGmDN3YXQfdpj7WJLaUBOPOSMv40bdQ2sdQtxKdRs6dde4DbSs7Tt2xOKlt0T5kCmeRWrWKkYfE0ecOj9+eM2dUVNbpwR25vyb3KsJaf6iZQYkAGCPPLfh5Rh96CxzK0lKUF1T4+M/uqVjfXGJJLXLHijpGqnUQcaEJJbKrPlKNvs1u0wBAAAAmo9Va4AmyRo5AAAAAAAAAAAAAAAAoHA0/ibIz6IAcmfkAAAAAGgnOqUzRUXpqlUOwlBz1mXApLjwyuvjs61bvW0tMI3XbMXKe2P6rAuiS/9J7mdJKvCW/ebOvI0Zv7rt7ujYr9rn3IIVD5wcdQ+tNWGBFvb4U3+KMVMcuq7ma+99Jse4I8+OM+ffFDW1dSqAKsfNdO8moAFjj4sd9fUGJgBgj3zy6Wfx3QuuNr+SpIR1TK8RsbakLNYXl0hSu+s3Zb1j73TGeJDAitKZs+0wBQAAAGg+VqwBmiRr5AAAAAAAAAAAAAAAAIDC0fibID+LAsidkQMAAACgXfne/9V4AESHVNV2h2GoORsyYWbcff/j3rgWqI1vvxfX1K6IA6ae6n6WpAKsfMiU+HjzJ3kdK35y42991i1Up8rqWLHyXhMUaEEffPhxnHHhf+z69+c5pOaoYsxxccy3r4r5S+6Kmto6FVAzz/oP93BCWnnPwwYooNls27HDhwDt2O9WPRC9Rk4zx5KkBDW04sD4fWnPWF9cIkntrvnd+hsLkljjfsp+EwbZXwoAAADQPKxUAzRJ1sgBAAAAAAAAAAAAAAAAhaPxN0F+FgWQOyMHAAAAQDtUlKoa0iGV+bMDMdTczZxzWbzz3ofevBaw5154JS688vqo2P8o97QkFUinnndli4wRl9bc6PNuga676XYTEmghDQ0N8fPf3hV99zvS80d7XMmgQ+Pgo8+NM+b9PGpq61SgXXHD6igfOtU9nYCmz7rAQAU0m9vvfjyOOu2yeOKZl3wY0E69sfHdmPzNs82zJClBFacycXH3AbG+uESS2l0zeg03FiSwolTmhf+1z9j/aXcpAAAAwJ6zSg3QJFkjBwAAAAAAAAAAAAAAABSOxt8E+VkUQO6MHAAAAADtVJeKqn8tSlf90oEYau567Ht4XFO7IurrG7yBLWA76utjzYNPxMw5l8Xe+xzi3pakBPfgo0+32Phw2cKlPvM8Nn/RMpMQaCHP/OmlqD7mDM8e7VGdKifGyMmz41vfWxxX3LA6amrr1AaafPxF7u8E1Hnnv6/XN75jwAKaxaYtn8WUEy+JTv0nxaEnzI2H127woUA71LhuddXiX0aXnc8C8y1JSk5Teo+KP5aUx/riEklqN60rLo0D+44xDiSwolTmZ3aWAgAAAOw5K9QATZI1cgAAAAAAAAAAAAAAAEDhaPxNkJ9FAeTOyAEAAADQznXoVz2jQ6pqi0Mx1Nw1HlD/3IaXvYVtAz786OO4cfkdMXHnNXVvS1KyGjJhZjQ0NLTouDB/0TKffR466+JFJh3QAjZt3hLfm7fYIerao/qPOz6O+fZVcdnilVFTW6c21gX/cVt06lftXk9AjfNOgOZywy0PR/qAb+x6vnTpf0gcfvLF8fDaF6O+hb9TA63vsaeei8HjZ5hvSVKC6lcxLn5V3jvWF5dIUrvp/tJu0afiIONAAutYkZlmVykAAADAnrEyDdAkWSMHAAAAAAAAAAAAAAAAFI7G3wT5WRRA7owcAAAAAHzlf6cyPYtSmScdiqHmrsuASXHevMWx5ZNPvY1tI55/6dVdh1oPOvib7nFJSkBX/PSmVhkPrlz8C59/M3bKOZdHfb2D3CGfGv+N1f76zkiNPtpzR7tVjxFHRvaEi+L7Nb+Jmto6tfFGTp7tvk9AA8YeFzvq6w1iQLO4//GX4pzLb45OlRP/8pwpGZSNY759efzx6T/7TgbtzKbNW+Lks39kziVJCarzzs7sMSieKS6N9cUlktQuurms987nX8Y4kLCKUpkPv953QrFdpQAAAAC7z6o0QJNkjRwAAAAAAAAAAAAAAABQOBol9IrKAAAgAElEQVR/E+RnUQC5M3IAAAAAsEuXESP+e4d0ZqGDMZSPBo+fEavve9Qb2Tak8ZDZhx9/JubMXRhdh05xn0tSK9Spsjpe3/hOq40FNdfe7Do0Q8fNvji279hhcgF51DhvHXf4bM8cNbmSQdkYd+TZMeeS2liwdE3U1NapnTT7wp/5N5CQ7lzziIEMaBavv/Xhrmf8ITMv+LtnTddhh8fx51wdj657def3s3ofFrQjy29bHd2HHWbeJUkJanLvUfFwaXmsLy6RpHbRBd338fxPYqnM/V8ZMeK/2FUKAAAAsHusRgM0SdbIAQAAAAAAAAAAAAAAAIWj8TdBfhYFkDsjBwAAAAB/o2O/zMSidOY9h2MoH02fdUG8sfFdb2bbmE8/2xorVt4bU48/Lzr2q3avS1ILdfiJ32v1MWDx0luiU6Vn/+5fw/Nj69ZtJhOQJ69vfCdOOvOH5qhqUqWDp8TYI8+OUy+4Pq782d1RU1undtiCpWui96jp/k0k5F0SQHOob2iIn978QFx+/aroNfKoz33m9Bp1dJw2d0k8/uxrsX1HvQ8N2omXX9sY44/8jrmXJCWoVOqg+EV5n1hfXCJJ7aJjeo3w/E9kmR/YTQoAAACwe6xEAzRJ1sgBAAAAAAAAAAAAAAAAhaPxN0F+FgWQOyMHAAAAAH+nqH9Vpw6pzBoHYygfdR9+WFxTuyJ21DuUtC16Y+O7sXDJ8hhWdYL7XZLy3G9+vyYRz/7frXowygYf6po0sUnHnhmffPqZyQPkweYtn8b8Rcs8m5Rz5UOmxkFHnxOzL/xZXHXjPVFTWyfFkadd7t9HAupcOXHXuwaA5vD7e5/d9YyffeENX/js6X/QzDj/quXx6LpXY/sO77GhPdi+Y0dcUnNDdKqsNgeTpKR8H0xl4sweg2JdSWmsLy6RpDbd2pKyGNnnQM//pJXK7NirYsJQu0kBAAAAms4qNECTZI0cAAAAAAAAAAAAAAAAUDgafxPkZ1EAuTNyAAAAAPD5stmvdUhXnd94OIRDMpSPxh0+O9Y+s8Fb2jas8fqeN29x9Bl1pHtekpq5niOmxWdbtybmmf/4U3+K1OijXZtc50HTTo9Nm7eYLEAz27Zte1y77Nao2P8ozxp9aV2HHR7jj/lefPvipXHV0jVRU1sn/U0/vObO6DLgEP9eEtD8RcsMckCzePbFt/7ynD9g2hlf+Ozp2K86xhz23bji+jvjifWvx44d9T5AaAfuf+Sp6D/2WHMwSUpQB/cZHfeVdov1xSWS1Ka7u7R79KgY79mfsIpSmRf+rVvmX2wmBQAAAGgaq88ATZI1cgAAAAAAAAAAAAAAAEDhaPxNkJ9FAeTOyAEAAADAF+qYzuzbIZV5xSEZykdd+k+K8+Ytjs1bPvW2tg3bunVb3LnmkZg557LoMmCSe1+SmqGzLl6UuOf9K6+/FaMO+Zbr8yWNO3x2fPjRxyYI0Izq6xviV7fdHYPHz/Cc0RfWfd8jInPc+THn0mVx1dI1UVNbJ31h444827+dBDRg7HGxo77egAfssU8+2xYLl/2fZ/xli1dG+ZCpX/4Oe8AhkT3h4vjJL+6NJ9a/7nkE7cAHH34cx82+2DxMkhJU79TBsbS8b6wvLpGkNt115RXRKZ3x7E9aqapr7CIFAAAAaBorzwBNkjVyAAAAAAAAAAAAAAAAQOFo/E2Qn0UB5M7IAQAAAMCXKqnM/t8dUpmfOyRD+Wrw+Bnxh7o/emPbDrz97vux6Ge/if2yJ7v3JWkPWrvu+UQ+5z/e/ElMO+n7rtE/6MDDTov3P9xkQgDNaM2DT+z6t+UZo39Uxehj45CZF8Z35/08FixdEzW1dVLOnXv5cv+OEtJdax4x6AHN4he/f/wvz/mZZ/1Hzs+hbsOnxcyzF8V1v3konn7+zahvaPBhQhv3yxWronzIFHMxSUpIHXd2cs9hsa64NNYXl0hSm21Oj8Ge+0kslXGgKQAAAEATWHEGaBLvoAEAAAAAAAAAAAAAAKCANP4myM+iAHJn5AAAAAAgZ0WpqhN39qmDMpSvps+6IF7f+I43t+3Ecy+8EhdeeX303e9I978kNaH9s6ck+vm+bdv2OOfSn7hW/7/GHT47PvzoYxMAaCaPPrk+DvnGWZ4v+rtKBh4a+0/9Tsw4a1Fc+tPfR01tnbRH9T9opn9bCXlnBNAcHn7q5b884xcsXRNDq09p0vNoSNXJcf6C38QNKx6J9S++FQ0NDT5UaMP+9OKrMWbKLPMxSUrSGknfMbG6tHusLy6RpDbZM8WlUdV7P8/8pJWqeqfLgIP+tx2kAAAAALmx2sz/x96dR3dV3ov+t/d3zx1+6977W/fcdU5PA4gJg6Ii3zCI4oB1xApJACM41qmgtYpDxalOBa0Tjokz4gBBFHAAK4oKEgSZFEQgCoqIzPNMQpLPj3BP762t1oQp+5u8Xmu9/2m7IPl+936eh7330w3USL6ZAwAAAAAAAAAAAAAAANJH1Z4g26IAqs/MAQAAAECNNMjuckSD7Nw5XpahfdUhx50dA4tGRXlFhSu49URpaVmMnTAteve9Lxq36+Y8kKSf6OnBb6TF+P7a2xOi+TE9fGc7O/2ca2P9hk0mfdgLPitZGGdffmc0bJ1nfNH/6YiTLopuvfrF9fcMiUcHfxgFRcXSXqv3zU84zxLQgW26xtLlq02EwB5bsXrT98b5/o+PisbtutdoTGq0c0zq1rt/DHj+/RgyenrMX7TKBwt1/B7Grfc949+hkpSgmqc6x1PNs6MkM0uS6mTTsppH61anG/MTVkZ2zp8POOCAn3mCFAAAAOCnudMMUCP5Zg4AAAAAAAAAAAAAAABIH1V7gmyLAqg+MwcAAAAANfaLNp3/34zs3Ke9LEP7stPOviZmfv6lq7j1zIpVa2Ng0ag4pUcf54Ek/UCN23WLVWvWp824/sVX38ZJ+VfV6++sywV9Y/2GTSZ52E1btpbGgm9XxfAxU6PrpXdEIy8x184y258Zx3e/Ji687pHo//ioKCgqlvZZD784Lpoe3dO5l4AGPDnUxAjsscrKiOdGfvy9sb7HFffu1rh08HHnxuW3PrPrz3j1nZmxePk6HzDUYX9+f1IcctzZ1mWSlKB6HXpcfJ7ZJEoysySpzvVas8OjcXaO8T5hZbTOucLTowAAAAA/zR1mgBrJN3MAAAAAAAAAAAAAAABA+qjaE2RbFED1mTkAAAAA2G0NW+d0zcjOWeOFGdpXNW7bLf744HOxecs2V3ProU9mfxE33vVEtDj+HOeDJP17l1z7p7Qbz0tLy+KuR16IRm3y6t33deZvbolNm7ea1KGaKisrY/W6zTH7y6UxdtIX8eKb06L/E6PjjF/funMM6WoeqMdVff9tO/WK7r3vit//aXA88uL4KCgqlvZb3Xv3dy4moLadLo7yigoTJrDH3pv8xffG+YdfHBeHnXDBbo9PR+f+Lu4seGPXnzVi7KxYunKDDxnqqMVLV0aXC/pam0lSgvrlEafGuCaHRElmliTVuf50SDtjfcLKSOVua3hE18M9OQoAAADwj7m7DFAj+WYOAAAAAAAAAAAAAAAASB9Ve4JsiwKoPjMHAAAAAHvk561yD2qQypnkpRnal7U+9aIYPnqcK7r1VGlpWYydMC16970vGrft5pyQVK97Z/yUtB3PP5z8abTrdEm9+a4uufZPu+Yw4MeV7SiPpSs3xIw5i2P0h3Pi2eGTo6CoeFe3PTIyTj77hmjYOs/4Xw9rtPN7b/ur3nHmZXfHdXe/FA+98MH/OTak2qj/46OMRwnpvQnTTKDAHpu/aNXfjfVX3Tloj8ang448M867ekA8OvjDXX/eGx/MjtXrNvuwoY7es7j5T09am0lSgmqe6hzPNM+OkswsSapzXXjY8cb6hJWRyp3Wpk2vf/LkKAAAAMCPc2cZoEbyzRwAAAAAAAAAAAAAAACQPqr2BNkWBVB9Zg4AAAAA9lzHjv8xIzvnrgbZORVenKF92a+v6hffLlnhym49tnzlmhhYNCpOPquPc0JSvSt18oWxo7w8rcfxTZu3xh/ueToatcmr09/VNbc/EuUVFSZu+BsbN2+PL75ZGR9OXxDD3v40CodOjIKi4u91y4BX44T866Jh6zxjfz2q6vtOnXJJ5F56Z1z1x0ExYNB7f3dsSLXdcd2vdr4moIuuvsuECuyx0rId8fjLf78WPa7bnl9zzD710rhpwLBdf17h0OIYM3FebNi0zYcOddAb7xTHIceebY0mSUm5vrSzKw89NuZkNomSzCxJqjN9mtk0jjmik7E+aaVy+3toFAAAAODHuaMMUCP5Zg4AAAAAAAAAAAAAAABIH1V7gmyLAqg+MwcAAAAAe02D1l1OzEjlLvHiDO3LmhyVHwOeHBplZTtc4a3nZs1dELfd/2wcfsJ5zg1J9aJ+Dw2qM2P4tJnz4qT8q+rk93T3oy9GZWWliZp6r3Tnen3pyg0xs2RJjJk4L54bOSUKiop/tL73Do1ju/Yx3teTMtufGcfkXRk9rrgnrr3rxRjw/Hv/8PiQktDV/V9w/iagxm27xdLlq020wB4b+d5nfzfW31nwejTaOc7s6VjVsHVe5Fx8RwwY9P6uP/eJlyfGuKnzY8u2Uh881DFfL1oSp/Twb1lJSlInHXFKjG9ySJRkZklSnWlskxbRPNXFOJ+kUjnlv2jV5RhPjAIAAAD8MHeTAWok38wBAAAAAAAAAAAAAAAA6aNqT5BtUQDVZ+YAAAAAYK/6t1T+vzRI5Yzy8gzt647LuzyKp8xylZfYXloao96dGBf26b/r5drOD0l1tS+++rZOjd/lFRXxwitvR8tfnl8nvp+Djuwew95438RMvVRWVh5LV26ImSVLYuykL6LorRlRUFT8kz06ZEL87vaB0b7zb43zdbwWHc+PU8+5IS68/pH4w0PD49HBH1brGJGS1GM7x6zDTrjAOZ2AHnzqZZMvsMdmzFn8g+N9997999p4dfBx58bV/V/4P3/2U69OiimfLYqyHeW+AKhDtm0vjev7FVqnSVKCOjTVOV5s3ipKMrMkqc70xMHZxviElZHK+ep/HZzz3z0xCgAAAPD33EkGqJF8MwcAAAAAAAAAAAAAAACkj6o9QbZFAVSfmQMAAACAfeFnDVI5fTKyc7d7gYb2ZQ1b50WfWx+O1Ws3uNrLLstWrI7CQSPi2NzLnSOS6lSdz7++zo7d6zdsijsHPBdNjspP2+/n8BPOi8nTPzcRUy/sKK+IZas2xqwvlsTYSV/EkNHTo3BocRQUVb8HBo6N865+MFp0PN8YXwfLan9WHNXliuj6mz/GFbc9E3966u0aHR9Skjvv6gHO8wR05OmXRnlFhUkZ2CMr12z6wbF+wPPvx8HHnrNXx61Tz71x1xr4L3/HsyM+jhlzFu8cyyp9EVCHjHxrfDQ/pof1miQl5VmCnV156LExJ7NJlGRmSVKd6Iqd45oxPmGlcgd6VBQAAADg77mDDFAj+WYOAAAAAAAAAAAAAAAASB9Ve4JsiwKoPjMHAAAAAPtMxhE52Q2yc0u8QEP7ukM7nhsDi0ZFhZeQ8ldmzV0QffsVxsHH9HSeSEr7Xho+ps6P28tXrok/3Pt0ZLXPT6vv5uSz+sTCb5eaeKk3tpXuiPmLVsW4qfNj0GtToqCouNrd8ehr0fnC2+KgI880tteRso7Kj6NzfxfdevWLy299Ju4seCMeGzKhRseFlE7d9+y7cWC7bs7/BPTehGkmZWCPVFZGPDvi4x8c7y//w1N7fdxqfuw5cdWdz33v7xk8avqutTVQd8xfuDhOzL/Sek2SEtTpLU+Oj5ocHCWZWZKU9s3JbBKnHXGK8T1h/aJVbp4nRQEAAAC+z91jgBrJN3MAAAAAAAAAAAAAAABA+qjaE2RbFED1mTkAAAAA2Kf+5dD8/9YgO2eQF2hof9T1ohujZP4iV375nu2lpTHq3YlxYZ/+cWCbrs4VSWlXk6PyY8PGzfVm3F62YnX0f/j5OLTjuYn/bm66+4ld8wzUV5WVEStWb4qpsxfF8HdnRuHQiVFQVPy9Hh38YVz1x0FxTN5V0bB1nnE9jWt2TM+d3+OV0b13/7jitmeiX+Gb8diQCX/3nUt1vdPOu8mYkIAuuvouEzGwx94unveDY33VGqd959/uk/HrlLNviPsGvvu9v+/VnWvppSs3+EKgjti6bXtcc/sj1mySlKAOT50RRc2OiJLMLElK+yY0OThatOpsfE9UOSv+LZX/L54UBQAAAPi/3DkGqJF8MwcAAAAAAAAAAAAAAACkj6o9QbZFAVSfmQMAAACA/aJhKvecBqncDV6ioX1d47bd4rb7n43NW7a5AszfWbp8dRQOGhHH5FzmfJGUNl1x0wP1cszesnVbPD/sz9Gx6xWJ+05aHH9OjB77kYkV/kbZjvJY+N2aGDd1fgwYOCbOvOzuOPjYc4zlaVbWUfnRvvPlccavb42Lfv9oXH/PkLj32XeioKhY0s5uGjDMWJGQ6z/LVqw2+QJ7ZPb8ZT863t/60Iho1Dpvn4xhzY85O353+7N/93eO/nBOrN/oujbUFcPeeD+aHn2WtZskJaSGO7uuRYeYk9UkSjKzJCmte7F5q2iUnWN8T1AZqdyRnhAFAAAA+L/cMQaokXwzBwAAAAAAAAAAAAAAAKSPqj1BtkUBVJ+ZAwAAAID9plGbvCYZ2TlTvEhD+6M2p10cb703yVVgftSsuQuib7/COPiYns4ZSYlu/KRP6/2Y/cnsL+IP9z4dR5x4fq1+FzvXs3HdHY/FqjXrTaTwA7Zu2x6vjvogul1yczRsnWcMT3hNOvSIdr+6LDqdf0ucd/WDce1dL8bdT74VBUXFkn6iNp16GUcS0INPvWzyBfbI+o3b/uF43+Wi2/bpOHZSz+vjvoHvfu/vfPzliTFu6vzYsq3MFwR1QMn8RXFCtyus3SQpQZ3R8uSY1OTgKMnMkqS07roWHYzriavLeZ4QBQAAAPjf3C0GqJF8MwcAAAAAAAAAAAAAAACkj6o9QbZFAVSfmQMAAACA/apNm17/1CCVc2+D7NxKL9LQ/ujCPv3ju2UrXQ3mR20vLY1R706MnpfdFg1b5zlvJCWqtp0ujvKKCoP1v9uxozw+nPxp3H7/s3Fs7uX77Xs4sE3XOO93d8ans7/0JcDf2La9NN56b1JcfsP90axDD2N3wso66qxoe/plceo5N0SPK+6Jy//wVNw84JV4YODYKCgqllSDXnxzWoybOj/mL1oVL7z6jjEmAR15+qXWysAee+GNaT869t//3LvR9Oie+3QsO/jYc+La/i/+3d/91CuTYspni2JHuXEO0t3mLdvid7c8aP0mSQnq8NQZMaTZEVGSmSVJaducnZ3e8mTjeoLKyM5Z16Bl14aeEAUAAADY9X8GCUD15Zs5AAAAAAAAAAAAAAAAIH1U7QmyLQqg+swcAAAAANSKX7TKO7VBdu5yL9TQ/qjp0WfFgCeHRlnZDleF+YeWLF8VhYNGRIcuvZ07khLRPQUvGZz/gYXfLo2hr4+Nvv0K45QefeLANl332md/dOde8Zvf3xOPPz8yli5f7cOGHzDz8y/jipseiI5dr4iDjuxu3K6FstqfFalTL4mO3a+JnItvj3P7PBC//cPTcdMDw+K+ge9GQVGxpN3shdenxvsffxklC1fE5q2l3xv/tm7bHod2PNc4lIDemzDNhAzskQ+mfPkP54OLrn90n49lDVvnRZeLbouHXvjg7/7+53fOR5/PXxaVlZW+LEhzQ0a8s/PfcPnWcJKUkA7c2R0t2se8zKwokaQ0bWKT5nFY6gzjeoLKSOWMOeCAA37m6VAAAACgvnOHGKBG8s0cAAAAAAAAAAAAAAAAkD6q9gTZFgVQfWYOAAAAAGrNvx7e5edVL5LwQg3tr04+q09Mn1XiyjA/qaKiMqZ+Ojf69iuM5sf0cP5IqpWqXqr91TdLDMo1sHXb9vi85Ot4671JUfj8yLih/+PR6/p7o+dlt8Wvzvt9HN/1t3FMzmVx+jnX7qrqP/v1Vf12/e8efOrlePmN92Ly9M9j46YtPkyoofKKilj03fIYP+nTGDTsrej/8PPxu1sejG4X3xRHd+4Vme3PNLbXoEY754CDjz0nsk+7NI7vfk10Ov+WOPPyP8VF1z8aV/d/IW5/9LUYMOj9KCgqlrSXGjjy4xgzcV58Pn9ZrN+47SfHvTseGGi8SkAXX3O3SRjYI19+s/Ifzg+PDv4wjjjp4v0yprU86cK4ZcCrP/hzFL01IxZ+t8YXBmluzhcL47i8y63jJClBdT/8lzE9q1mUZGZJUlpW1OyIODCVY0xPUBnZOZd5MhQAAACo79wdBqiRfDMHAAAAAAAAAAAAAAAApI+qPUG2RQFUn5kDAAAAgNr2s4xU7u8zsnNKvVRD+6OGrfOiz60Px5p1G1whplq2bS+NUe9OjJ6X3bbr+HEeSdpf5V10o0EYqFNWrVkfn5d8He9+ODWGvj42CgeNiH4PDYprbn8kLuzTP3IvvGHXy8UPP+G8OjemZ7Y/M1p0PD9an/ab6JB7ZZzU8/o449e3xpmX3R3nX/1g9L7lybju7pfi9kdfi3ufGROPDZkQBUXFkvZhg0dNj/c+/jLmfrU81m3YWuMx7atvlvg3YgJq3LZbLFux2iQL7Lat28p+cs7o0+/5/TauNWrTNXpccW88OvjDH/xZRo37PNZu2OKLgzS2cfOWuKzvfdZykpSgslv9Kt5oeliUZGZJUlp2/aFHG88TVc6mRm3ymngsFAAAAKjP3BkGqJF8MwcAAAAAAAAAAAAAAACkj6o9QbZFAVSfmQMAAACARGiY6twuI5U730s1tL867IRzY/CId6KystKVYqrtu2Uro3DQiDi6cy/nkaR93pCd8xRAfVVRURmr1qyPL79eHLPmLogJH8+M18d8FE8Nfiv++MjQ6HPnM3He1QOixxX3Rvfed0Xni26PX13whzipZ984vvs1cUzeVbs6qvNvo22nXt/riJMu3vnvgQui9Wm/+bv/7q87OueKXX/GsV377Ppzqzr9/JvjjF/fGjkX377r7z3nqgfi19c9HJfeWBi/u/3ZuLrfC3H9PUPiloeGR7/CN+PeZ8bEoy+Nj4KiYkm1WOHQiVH01owYN3V+lHy9IjZu2b5XxqqzL7/dujUBPfT0MBMnsEeG/vmTn5xLOuReuV/Htra/6h1/LHjzB3+Wx3fOa1Vz2tbtZb48SGNPvvh6NG7bzXpOkhJSZionBhzcNkoysyQp7Zqb2SS6tDzJeJ6kUjnFBxxw+3/wVCgAAABQX7kjDFAj+WYOAAAAAAAAAAAAAAAASB9Ve4JsiwKoPjMHAAAAAInxvw7O+e8Z2bmDvVhD+7Nul9wcX3z1ravF1EhFRWVM/XRu9O1XGM069HAuSdrrNT36rNi4eYsBF+AfKCsrj6UrN8SMOYtj9Idz4tkRH0dBUbEkxVOvTIoRY2fFpJkLY+F3a6K0bMc+GYfe/uBja9cEdOTpl0Z5RYWJEdhtEz/5+ifnlj88NDwats7br+PbQUeeGZfeWPijP9MzwyfvWgsbAyF9fTT1szjixPOt6SQpQV10WMeYldU0SjKzJCmtmpzVPA5vdYaxPEFlpHJ/74lQAAAAoL5yNxigRvLNHAAAAAAAAAAAAAAAAJA+qvYE2RYFUH1mDgAAAAASp0Eq54IG2TmbvFxD+6vG7brFbfc/G1u2bnPVmBrbuHlLDB89Lnpedtt+f7GupLrblbc8aIAF2A1rN2yNeV8tj/FT58crYz6NJ4Z9FAVFxZLqcI+/PDGG7Tzfq877uTvP/9XrNkdlZeV+GXPKKyriqDN+Y/2agN4vnm4SBHbbN0vWVmvO6XTezbUyxv3yrN/HA8+N/dGfa/Co6TF/0SpfJKSpZStWR5cL+lrTSVKC6njEqfFBk0OiJDNLktKql5u1jANTOcbyhJSRnbu9YZvclp4GBQAAAOojd4IBaiTfzAEAAAAAAAAAAAAAAADpo2pPkG1RANVn5gAAAAAgkX7eKvegjFTuZC/Y0P7smJzLYvykT105ZrctWPhd3P3oi9H61IucU5L2qOIpswyqAHtBRWVlrFm/JUq+XhETpn8VI8bOiqdemRQFRcWS0rQX35wWYyd9ETNLlsTSlRtiR3lFrY4zjzz7ivVrArrk2rtNesBuK9tRHk+8PPEn56A/PfXnOOjIM2tlnGvR8fy48f6X/+HP9/r7s2P1us2+UEhDpaVlcX2/Qus6SUpQzVNd4pnm2VGSmSVJadWNLY42jierT9q06fVPngYFAAAA6ht3gQFqJN/MAQAAAAAAAAAAAAAAAOmjak+QbVEA1WfmAAAAACCxmjbt9J8zUrkPNsjOrfSCDe3PLuzTP5YsX+UKMrutoqIyJnw8M3r3vS8at+vmvJJUo448/dJd4wgA+0ZlZWWsWb8lvli4MiZ+8nW89t5n8fSrk6OgqFhSwnrxzWkxZuK8+GTu4vhuxfooKytP3JiycvW6OOjI7taxtVzjtt1i2YrVJjlgt40cO6tac1P+5X+qtbGuUZuucd7VA+KxIRN+9Od7fOjEGDd1fmzdVuZLhTT00vAxkdn+TOs7SUpIDXd25aHHxpzMrCiRpDRpbmaTyGl5knE8QWWkcm73JCgAAABQ37j7C1Aj+WYOAAAAAAAAAAAAAAAASB9Ve4JsiwKoPjMHAAAAAImXkco5eWdLvWRD+7NmHXpE4aARUV5R4Uoye2T9hk0xeMQ7cfJZfZxbkqrV/Y8PMXgC1Ma6beO2mL9oVUz5bFG8XTwvBo+eHo8PnRgFRcWS9nFPDvsoXn1nZnwwZX589uXSWLpyQ5SW7Uib8eOKmx6wjk1ADz09zGQG7LapsxdVa8568PkPovkxZ9fqeNch98q45+m3/+HP+czwyTFjzmLXtyENfTZvQbT/1aXWd5KUoDq3PDkmZzWPkswsSbwHKuUAACAASURBVEqLJjU5OA5PnWEMT0qp3B0NU53beQoUAAAAqE/c+QWokXwzBwAAAAAAAAAAAAAAAKSPqj1BtkUBVJ+ZAwAAAIC0cGCbrr9okMp5z4s2tL87tefVMeOzEleT2StmzV0QffsVxsHH9HR+SfrBGrbOi4XfLjVgAiRERUVlrFm/JeYvWhVTPlsUYybOi6K3ZkTh0OIoKJK0Oz332pR444PZMWH6V1Hy9Ypd51hlZWVajxVTPp1rLZuA2v/q0iivqDB5Abtl6coN1Z7LLrj24Vof85ofe05cd/dLP/mzDh41fddaFkgvK1evi26X3GyNJ0kJqlWrM2J408OjJDNLktKiwc1bRaPsHGN4QsrIzv28adNO/9lToAAAAEB94a4vQI3kmzkAAAAAAAAAAAAAAAAgfVTtCbItCqD6zBwAAAAApJOfNUjl9MnIzin1sg3tzxq2zos+tz4ca9ZtcFWZvWJ7aWmMendi9Lzstl3Hl/NM0l+qelkuAMlXtqM8VqzeFHO/Wh4fffJ1vDnu83j+9alRUFQs6d+rOife+GB2fDhtQcz+cml8t3x9bCvdUWfHhdPOvsZ6NgF9MHGGSQrYLRUVlfHUq5OqNcc9+tL4OOyECxJx3Tr30jt3/Tw/9TNXzclr1m/xRUMa2VFeHnc98oI1niQlqAN3dkeL9jEvMytKJCkNuq5FB+N3gsrIzrnL458AAABAfeGOL0CN5Js5AAAAAAAAAAAAAAAAIH1U7QmyLQqg+swcAAAAAKSdBq27HNUgO/drL9vQ/u6wE86NwSPeicrKSleX2WsWLPxu14sxUyf/2nkmKYa+PtbACJDGyisqYsOmbbHwuzUxY87iGDd1frzxwex48c1pUVBULNW5Hh86cdfxXXWcT5j+VXw+f1ksXbkhSsvK6935/9LwMdazCejia+42GQG7rWo+q+4c2OvmJxMz9rXvfHn86am3f/JnLhxaHGMnfRFbt5X5siGNjHxrfDQ9+ixrPUlKUGcdfmLMyGoWJZlZkpTo5uzslJanGLuTUip3R6PsnLae/gQAAADqA3d6AWok38wBAAAAAAAAAAAAAAAA6aNqT5BtUQDVZ+YAAAAAIC3985Gd/kdGds4QL9xQbdTt4puiZP4iV5jZq8orKmLCxzOjd9/7onG7bs41qR7WrEOP2LR5qwERoI4qKyuPlWs3xfxFq2L6nMXx/sdfxsixs+K5kVOioKhYSmyFQyfGC29Mi9ffnx0fTJkfM3Yev199uzrWbtgSFRWVTu5/t3nLtjjkuLOta2u5xm27xbIVqx2QwG6Z9vm31Z4fHx0yIVqdckmCrin0jOvufqlaP/szwyfHZ18sjYpK8ziki7lfLowOXXpb70lSgjr6iE4xpmmLKMnMkqREN67JIdE81dnYnZRSOXMbd+z4Xzz9CQAAANR17vIC1Ei+mQMAAAAAAAAAAAAAAADSR9WeINuiAKrPzAEAAABAWmuQyrmgQXbuZi/dUG28pPm2+5+NTZu3utLMXrdi1doYWDQqTsy/0vkm1aOuvu0RAyBAPVW2ozxWrt0U8xetihlzFsf4aQti9Idz4uU/fxLPDp8cBUXF0j7tyWEfxdCdx9tbE+bGxE++jtlfLo1FS9fGuo1bo7yi0klaTX+492nr2gT08DPDHIzAblmyYn2N5s+r7hyUqPGvUeu86Pm7e+OxIROq9fMPGT09vl22zhcPaWLj5i1x8TV3W+9JUoJqmt0lnmqeHSWZWZKU6J7eOVYZtxNUKrefpz4BAACAus4dXoAayTdzAAAAAAAAAAAAAAAAQPqo2hNkWxRA9Zk5AAAAAEh7v2jT+ZAG2TmfeumGaqM2p10cw0ePc7WZfWbW3AXRt19hND+mh3NOquN9NPUzgx4AP2hHeUWs3bAlvl22LuZ+tTymzl4U73/8ZbzxwewYMnpGPDnsoygoKpZ+sMKhE2PQa1Ni+Lsz4+3ieVE846uYWbIkFny7Kpat2hhbtpY6yfaSL79eHA1b51nb1nLtOl0S5RUVDkigxsp3rrmeeLlm66r2nS9P3DjYsfs18cBzY6v9O4z+cE5s3LLdAQBpoLKyMgoHjYhGbaw5JSlJ9Tr0uJiT2SRKMrMkKbFVjVXG7ISUyt3RKDunrac+AQAAgLrM3V2AGsk3cwAAAAAAAAAAAAAAAED6qNoTZFsUQPWZOQAAAACoE5o27fSfM7JzH2mQnVvp5RuqjS64ql8s+m65q87sMxs3b4nho8dFz8tuc85JdbD2v7o0KioqDXYA7LZtpTti9brNsfC7NTH7y6UxeebCGDv5i3hz3Ocx9M+fxHMjp0Th0IlRUFSsOtTTr06OIaOnx8j3PosxE+fFhOlfxSfzvosvv1kZS1duiE1btkdFpTXG/nRWr1utbxPQBxNnOBiB3TL83Vk1motvuG9oIsfBQzueH7cMeKXav8eTwz6KKZ8tivKKCgcBpIGxE6ZFi+PPse6TpAR1esuTY3JW8yjJzJKkRPZZVpM4/ohTjdnJaU7V846e+gQAAADqKnd1AWok38wBAAAAAAAAAAAAAAAA6aNqT5BtUQDVZ+YAAAAAoE7JyM7JaZDKWe3FG6qNmhyVHwOeHBqlpWWuPrNPzV+4OO565IVoddIFzj2pjlQ1fwDAvlZZGbFlW1msXrc5vl22LkoWrohP530Xkz5dGO9//GW8NWFujBg7K4remhHPjfw4Hh86MQqKirUfe2LYRzHotSm7voOR730WYybOiwnTv4pps7+NOQuWxcLv1sTy1Rtj05btUV5e4aBOoLfem2R9m4AuufZuByOwWybNXFjj+fu4blcncixs3K579L75iRr9LoNHTY9vlqx1IEAaWLDwuzih2xXWfpKUoFKpX8VrzQ6PkswsSUpkY5q2iKxUF2N2Ysr5o6c9AQAAgLrKHV2AGsk3cwAAAAAAAAAAAAAAAED6qNoTZFsUQPWZOQAAAACoc/718C4/z0jljPHiDdVWx+RcFuMnfeIKNPtcWdmOGDthWvTue180btvN+SelaQ1b58U3i5cZ1ABIpO2lO2L9xm2xfPXG+Gbp2vjym5Xx+fxlMWPO4pg8c2GMn7Yg3p1UEqM/nBMjx86KoX/+JF54Y1o8M3xyPPHyR1FQVFyveuqVSfHcyCnx0pvTYtiYT+O19z6LUePnxDsT58W4qfN3fWafzPsu5ixYHl8tXh1LVqyP1es2x+atpbGjvMIBVwfsKC+Ptp0uts6t5ar+jbx85RoHJFBj3yxZU+P5/5aHhu/6t31Sx8TTzrspHn5xXI1+p6q13YZN2xwQkHCbt2zbdX/A+k+SktNB2Tkx4OC2UZKZJUmJbMAhbY3XSSmVu+MXrfPaeNoTAAAAqIvczQWokXwzBwAAAAAAAAAAAAAAAKSPqj1BtkUBVJ+ZAwAAAIA66vb/0CCVe3PVyye8hEO11YV9+seS5atciWa/qHpZeOGgEdGhS2/nn5Rmdb/0ZoMYAHXa9tIdsWVraWzYtC1Wrt0Uy1ZtjG+XrYuvvl0dX36zMj6fv2xXM0uWxIw5i3c1edY3MWnmwpj06cIYN3X+rt77+MsYM3HeP+zNcZ/HGx/M/l5vTZj7g//b93f+eX/5s6saP23B//47d/aXn+OzL5fu+tlKvl4R8xetiq8Wr971sy9evi5WrtkU6zZsjU1btu/6HeEvBjw51Do3AT3y7CsORqDGSst2ROHQiVFQVFyjOna/JtFjYpvTe8ddT75Vo9/pyWEf7VoXle0od2BAglVWVu5a9zRqk2cNKEkJ6qLDOsasrKZRkpklSYnr/MM7GqsTUkZ2zsxDD83/T571BAAAAOoad3IBaiTfzAEAAAAAAAAAAAAAAADpo2pPkG1RANVn5gAAAACgTmuY6twuI5U730s4VFs169AjCgeNiPKKClek2W9mzV0QffsV7jr+nIdS8nvlzfcNXAAAdciKVWujcbtu1rq13NGde0VFRaUDEqixoX/+JAqKimvUHx4aHg1b5yV6XGx6dM+4/p4hNf7dnn99apR8vcKBAQn3fvH0OOTYs60DJSlBndDytBjf5JAoycySpEQ1I6tZtG11urE6Od3hKU8AAACgrnEHF6BG8s0cAAAAAAAAAAAAAAAAkD6q9gTZFgVQfWYOAAAAAOq8fz6y0//ISOW85AUcqs1O6dEnps8qcVWa/Wrjpi0xeMQ70fWiG52HUkJr1qFHbN6yzYAFAFDH9O57n/VuAvpw8qcORqDGPpy2IAqKimvcL8+6LvHjYqM2XeOi3z+6W7/f6+/PjjXrtzhAIMHmzf8mjjrjN9aBkpSgDk+dEcOatYySzCxJSlSvNz08DszOMVYnoVTujl+0zmvjKU8AAACgLnH3FqBG8s0cAAAAAAAAAAAAAAAAkD6q9gTZFgVQfWYOAAAAAOqNBqmcCxpk52zyMg7VVg1b50WfWx+ONes2uDrNfvfFV9/GXY+8EC1/eb7zUUpQ197+qAEKAKAOmjRttvVuAurd9z4HI1BjXy5aFQVFxTXu9kde23UNOB3GxzN+fWs8OvjDGv+Oj788MSZM/ypKy8odKJBQa9dvjDN/c4u1oCQlqANTOXFHi/YxLzMrSiQpQd12yFHG6YSUkZ0zs02bXv/kCU8AAACgrnDnFqBG8s0cAAAAAAAAAAAAAAAAkD6q9gTZFgVQfWYOAAAAAOqVn7fKPahBKmeSl3GoNjvshHNjYNGoqKiodJWa/a60tCxGvTsxLuzTPw5s09U5KdVyH8/43MAEAFBHnZh/pTVvLXfQkd1j1Zr1DkagRrZsLY2CouLd6sQev0+bMfKozr+Ne599Z7d+z+demxIlX69wsEBClZXtiOvueMx6UJIS1lmHnxgzsppGSWaWJCWiuZlNonPLk43RCSkjlXObpzsBAACAusJdW4AayTdzAAAAAAAAAAAAAAAAQPqo2hNkWxRA9Zk5AAAAAKh3Dj00/z81yM55oEF2bqUXcqg263rRjTFv/jeuVFNrlq1YHYWDRsTRnXs5J6VaqOrcq6ysNBgBANRRg4a9Zd2bgAqfH+lgBGrsxTenRUFRcY27/ZHXomHrvLQZIw874YK4/dHXdut3rWrk2Fmxet1mBwwk1FMvvR4HtulqTShJCeqoVp3inaaHRklmliQlouKsg6NFq87G6ASUkZ1T2rBNbktPdwIAAAB1gbu1ADWSb+YAAAAAAAAAAAAAAACA9FG1J8i2KIDqM3MAAAAAUG9lZOeelJHKXeKlHKrNGrfrFv0eGhSbt2xzxZpaU1FRGeMnfRq9+94XBx3Z3bkp7acefOplAxAAQB22afPWOOTYs619a7kOXXpHZWWlAxKokfcmfxEFRcW71cln35BW42Rm+zPjyjsH7vbv+/jQiTFh+ldRVlbuwIEEGj/pk2hx/DnWhZKUoJqnOseg5qkoycySpET0dPNs43NCysjOnXpAfv7/48lOAAAAIN25UwtQI/lmDgAAAAAAAAAAAAAAAEgfVXuCbIsCqD4zBwAAAAD12r8e3uXnGanct72UQ7Vd61MviuGjx7lqTa1bv2FTDB7xTpyYf6VzU9qHNWqTF98uWWHQAQCo4266+wnr3wT00dTPHIxAjcxZsCwKiop3qzseeyMatc5Lq3Gy4c6ft+eV98VjQybs9u896LUpUfK1ax2QRF9+vTiOybnMulCSkrT+2tl1LTrE3MwmUZKZJUm13qWHHW98TkgZ2TnXeqoTAAAASHfu0gLUSL6ZAwAAAAAAAAAAAAAAANJH1Z4g26IAqs/MAQAAAAAHHPCzqpdRZGTnbvdiDtV2Z/W6NeYvXOzqNYkwa+6C6NuvMJoefZbzU9oH4z0AAHXfvPnfWP8moCtuesDBCNTIug1bo6CoeLc7+ewb0nK8PKln33johQ/26HcfNX5ObNi0zUEESRvX1m+KHr1vtTaUpITVveWJMSOrWZRkZklSrTYzq2kc1aqTsTkZbT6wbbcsj3QCAAAA6cwdWoAayTdzAAAAAAAAAAAAAAAAQPqo2hNkWxRA9Zk5AAAAAODf/aJN59YNsnNLvJhDtV2To/LjoaeHRWlpmavYJMLa9Rvj6cFvxAndrnCOSnup4aPHGVwAAOqJvItutAau5TLbn7nr37YANTFw5MdRUFS8W932yMho2DovLcfM1p1+E/c8/fZu/+5VPTnso5g+Z3GUV1Q6kCBBdpSXx81/etL6UJISVvtWneKdpodGSWaWJNVqbzY9LBpn5xibk1Aq570DDjjgZ57oBAAAANKVu7MANZJv5gAAAAAAAAAAAAAAAID0UbUnyLYogOozcwAAAADAX2l4VP5/zcjOfcTLOZSEOnTpHe8XT3clm0SZNXdB9O1XGM069HCeSrtZ82N6xOYt2wwoAAD1xPDR46yDE9DTg99wMAI18taEuVFQVLzbnXDmtWk7Zh583Llx60Mj9uj3r2rwqOnx7bJ1DiZImMEj3onG7bpZI0pSku4dpbrEwOatoiQzS5JqtTtatDcuJ6SM7JyLPc0JAAAApCt3ZQFqJN/MAQAAAAAAAAAAAAAAAOmjak+QbVEA1WfmAAAAAIAf0CA7t3tGdu5aL+hQErqwT/9YvHSlK9okysZNW3a9ePPUnlc7T6Ua9vs/FhhEAADqkdLSsjjixPOthWu5jl2viMrKSgckUG3TPv82CoqKd7tbBrya1uNmZvsz4+p+L+zRZ/CXxkycF1u3lTmoIEGmfDrXGlWSElbDnd3U4qiYl5kVJZJUS83NbBJdWp5kXE5AGamc9Q1bndHAk5wAAABAOnJHFqBG8s0cAAAAAAAAAAAAAAAAkD6q9gTZFgVQfWYOAAAAAPgRv2jT+cAGqZxiL+lQEmp69Fkx4Mmhu17EDUkza+6C6NuvMJof08P5KlWjqhfWAgBQv/zxweesha3FgTTz7bJ1UVBUvEcdk3dVWo+bjVrnxcV9C/b4c6jqmeGTY2bJkqisrHRwQUJ8s3hZ/PLMK60TJSlhnXtYx5iZ1TRKMrMkqVaa2KR5tGjV2ZichFI5b3qKEwAAAEhH7sYC1Ei+mQMAAAAAAAAAAAAAAADSR9WeINuiAKrPzAEAAAAA/0jHjv+xQXbuHQ1SOeVe1KEkdEK3K2Li1FmubpNIGzdviRdffTs6nX2t81X6kY7NvdzLowEA6qFvFi+Lhq3zrIlruT63PuxgBKqttGxHFA4tjoKi3a/vPUV1YvzMvfTOeGzIhD36LP7SsDGfxorVmxxgkBCbNm+Ni66+y1pRkhLWcUecFuOaHBIlmVmSVCs92zxlPE5O3T3ECQAAAKQbd2IBaiTfzAEAAAAAAAAAAAAAAADpo2pPkG1RANVn5gAAAACAamjQKveEjOycxV7SoaR0YZ/+sWT5Kle5SaxZcxdE336F0axDD+es9Fc98uwrBggAgHqqR+9brYlruSZH5cf6DZscjEC1DR49PQqKiveoozr/tk6MoSf1vD4efnHcHn8eVT0+dGJMmP5VlJaVO8ggAcorKuKuR16wXpSkhNWiVecoanZElGRmSVKt1OvQ44zHCSgjlbvswJZn/E9PcAIAAADpxF1YgBrJN3MAAAAAAAAAAAAAAABA+qjaE2RbFED1mTkAAAAAoJqy2uT/fw1SOS97WYeSUrMOPWLAk0OjrGyHq90k1sZNW2LwiHfipPyrnLeq9zVqkxffLVtpYAAAqKdGj/3IujgBPffyaAcjUG1jJ30RBUXFe9Q1/V+oM2PokWdcHvc9++4efyZ/adBrU6Lk6xUONEiI196eEE2OyrdmlKQEdWAqJ+5o0T5KMrMkab83M6tptG/VyXichFK5Az29CQAAAKQTd18BaiTfzAEAAAAAAAAAAAAAAADpo2pPkG1RANVn5gAAAACAGspI5V2ekcrZ6oUdSkrHd/1tTPh4piveJN6suQuib7/CyGrvpZyqn519+e0GAgCAemzHjvLIPuVCa+Na7uSz+jgYgepfz/piSRQUFe9Rjw2ZEG069aoz42jLky6M/o+P2uPP5a8bNX5ObNi0zQEHCTD107nR8pfnWzdKUsI6//COMSuraZRkZknSfu3NpofFgdk5xuLarzIjO/ckT24CAAAA6cKdV4AayTdzAAAAAAAAAAAAAAAAQPqo2hNkWxRA9Zk5AAAAAGA3/Ft2XouM7JyZXtihpNSwdV70ufXhWLl6nSvfJF7VcVo4aEQc3bmX81f1qtf+/KEBAACgnruvcIi1cQL6ZPYXDkagWpav3hgFRcV73O9uH1inxtEmHXrEDfcN3SufzV96cthHMeWzRVFeUeHAg1q26Lvl0bHrFdaNkpSwOh5xaoxvckiUZGZJ0n7t5hZHG4cTUc7Cfzk0/795chMAAABIB+66AtRIvpkDAAAAAAAAAAAAAAAA0kfVniDbogCqz8wBAAAAALup4VH5/7VBdk6hF3YoSbU4/pwYWDTKi0dJCxUVlTHh45nRu+990bhtN+ew6nSHHHd2bNte6sQHAKjnvlu2Mg5s09UauZa77o7HHIxAtVRdZ33i5Y+ioKh4j3psyIQ44qSL69RY2rhd97jyzoF7/Nn8bUNGz4glK9Y7+KCWrV2/MbpedKO1oyQlrENTnWNos5ZRkpklSfutOTs7ueUpxuEklMod4KlNAAAAIB244wpQI/lmDgAAAAAAAAAAAAAAAEgfVXuCbIsCqD4zBwAAAADsoV+0ys1rkMpZ7cUdSlKn9rw6ps8qcRWctLF85ZooHDQi2nW6xDmsOtn1/Qqd6AAA7PLrq/pZI9dyzTr0iI2btzgYgWp59Z2ZUVBUvMddekNhnRtPG7XOi0tvLNwrn8/fNnbSF7Ft+w4HINSi7aWlcfkN91s/SlLCOnBn9xzSLkoysyRpv/VBk0OiaXYX43Btl8opb5jq3M4TmwAAAEDSudsKUCP5Zg4AAAAAAAAAAAAAAABIH1V7gmyLAqg+MwcAAAAA7AX/eniXn2ekcsZ4eYcS9ULTNnlxfb/CWLt+o6vhpI0dO8rjjXeKI++iG53HqlNNn1XiBAcAYJexE6ZZIyegl4aPcTAC1fLh9AVRUFS8xz3y4vhofuw5dXJM7d77rr3yGf1tz438OEq+XuEghFpUWVkZA54cav0oSQms16HHxZzMJlGSmSVJ+6X7D2lr/E1AGancWW3a9PonT2wCAAAASeZOK0CN5Js5AAAAAAAAAAAAAAAAIH1U7QmyLQqg+swcAAAAALD3/KxBKqdPRiqnzAs8lKQO7XhuDCwaFeUVFa6Kk1Zmz/sq+vYrjKZHn+VcVlp3XN7lu14+CwAAVSoqKuOoM35jrVzLndKjj4MRqJaSr1dEQVHxXqnnlffV2XE19+I747EhE/baZ/XXjRo/JzZu2e5ghFr08hvvReN23awjJSlhnd7y5Pg4q3mUZGZJ0n6p++G/NP4moIxU7u89qgkAAAAkmTusADWSb+YAAAAAAAAAAAAAAACA9FG1J8i2KIDqM3MAAAAAwF6WkZ13dIPsnIVe4KHEvVDrnGvjk9lfuDJO2tmwcXMMLBoV7X91qXNZadljA191IgMA8D2PPPuKtXICmjV3gYMR+ElrN2yNgqLivdL9z70bBx15Zp0dV08776Z4dPCHe+3z+uueemVSzJizOCorHZNQW8ZP+jQOOfZs60hJSljtWp0e7zRpESWZWZK0z/s4q3kcnjrD+Fv7bf55q9yDPKkJAAAAJJW7qwA1km/mAAAAAAAAAAAAAAAAgPRRtSfItiiA6jNzAAAAAMA+8M9HdvofGdm5g73AQ0mrUZu86HPrw7F2/UZXyEk7FRWVMXbCtOh52W3RsHWec1ppM+4uWb7KCQwAwPesXL02GrfrZs1cy9141xMORqBanhk+OQqKivdKuRffWafH1o5nXhMPvfDBXvu8/rbh786KNeu3OCihlpTMXxRHnn6ptaQkJaym2V3i2eapKMnMkqR93sDmrYy9CSgjlfu2pzQBAACApHJnFaBG8s0cAAAAAAAAAAAAAAAAkD6q9gTZFgVQfWYOAAAAANiHGqRyLmiQnbPJizyUtA474dwYWDQqKioqXSknLc1fuDhuu//ZaNahh3Naie7sy293wgIA8IN6973PmrmWa35Mj9i0eauDEfhJb3wwOwqKivdK/Z8YHY1a59Xp8bXdry6L+597d699Zn/b4y9PjEkzF0Z5RYWDE2rBilVr4/RzrrWelKSE1XBnN7U4KuZlZkWJJO3jfnPYccbeBJTROu8sT2gCAAAASeSuKkCN5Js5AAAAAAAAAAAAAAAAIH1U7QmyLQqg+swcAAAAALCP/fyILpkZqdzJXuShJNbt4pti3vxvXC0nba1dvzEefmZYtDrpAue0EtnIt8Y7UQEA+EHFU2ZZMyegotfGOhiBnzR51jdRUFS81zqp5/V1fnxtdcol8aen/rxXP7e/bfCo6fHdivUOUKgFW7Zuiwv79LeelKQEdt5hJ8SsrKZRkpklSfusmTvHmSNbnW7creUyUrnLDmx5xv/0hCYAAACQNO6oAtRIvpkDAAD4/9m78yipykPR28l3c4ez7jrnfitZ6yTpBkkXQyNjdTcoigoOUVSoahrLWYMTiaLibOJsxGg0GIfGeTY0zkbUaJwwtAOCOKK2EqMIKiAyTw3d/V7LdW5WEhmqoKt2VdfzrPX7z792vcOm937dAAAAAAAAAAAAQPFInwlyLAogc3YOAAAAAMiHIUO+V16VvKi8KtHqgx4qtLoMqAsXXHlrWLFqtb+aU7Sam9eHBx+fGnYbeYJ5rYKpx+CDwqrVa01QAAA2qq2tLexae7x754gbfsSZBiOwRR/NWxzqGxrbrXMn3F8Sa2zvoUeESyZOaddr969NnNwY/vLaX8P69S0GKuRZS2trOO/ym91TSlIBNrTfPmFa18rQVBGTpJz1ULc+Ybt4wrobcWXxxI1ezgQAAAAKjaepAFlJ2TkAAAAAAAAAAAAAAACgeKTPBDkWBZA5OwcAAAAAwDrRsAAAIABJREFU5FFZPLHX133ugx4qxKr3Pio88qe/fPNRbyjmj3hOefrFsO+hp5nXirzTL7rOpAQAYLNuvPuP7p0LoNlNfzMYgc1asWpdqG9obNcGjRhbEmtsj10ODef//qF2v37/2h2PvBo++nSxwQoRuHXSlNC5ptZ9pSQVWP367xf+2K1PaKqISVLOOqPXztbcyEu0/rimdhdvZgIAAACFxFNUgKyk7BwAAAAAAAAAAAAAAABQPNJnghyLAsicnQMAAAAA8uw/+4z4YVk88ZQPeqhQqzvmnPDehx/7CzpFb8Yb74XR48aHTtU+5qlomj5rtokIAMBmLVm2InQdlHL/HHHnXX6zwQhs0S0PvhLqGxrbrZN/fUfJrLOxr/e6s6+Y3K7Xb1M9/pd3w6o1zQYs5NkTz77svlaSCrCfVCXCtZXVoakiJkk5aXZF17Brv32suRFXVpWc3atX6n94MxMAAAAoFJ6gAmQlZecAAAAAAAAAAAAAAACA4pE+E+RYFEDm7BwAAAAAEI3vlsWTp5dVJZp92EOFWJcBdeGCK28NK1au9pd0it4tk6aY18p7Ow0fE9ra2kxAAAC2aNz5V7uHjrjtdzs0rF3XbDACm/Xws2+H+obGduu6SdNC3z1Hl8xa+5MdDghnXDapXa/hprrlwVfC7DlfGLSQZ7Pebgr99jjC/aUkFWAn9dolvFfRNTRVxCSp3XuiW+/QpSphvY24sqrEuV7JBAAAAAqFp6cAWUnZOQAAAAAAAAAAAAAAAKB4pM8EORYFkDk7BwAAAABE6Mc1w6vLqxIf+LCHCrU+Qw8PtzU8Flpb2/xFnaJ2y6Qp5rTy2oQbJ5t4AABkZOab77uHLoAeeOx5gxHYrGmvfRTqGxrbtaPOuLak1trtBtaFcZfc2e7XcVM9/OzbYenyNQYv5NHc+QvC0Lqx7i8lqQAb2WePMCvWPTRVxCSp3Ttv+x2ttRFXVpVcV9Y3UemNTAAAAKAQeHIKkJWUnQMAAAAAAAAAAAAAAACKR/pMkGNRAJmzcwAAAABAxDoNSv1bWVXyGh/3UCG372Gnhzfe+dBf1Slqt0yaYj4rL3Wqrg2fzPvCpAMAIGP7HHKqe+moPy5+1C8NRGCz3v3rglDf0NiuTbjzuRAblCqp9bbzgLpw8sV3tPu13FQ33vdSePXtuaG1tc0ghjxZtnxlOOC4c91jSlIBtnP/YWFqt56hqSImSe3au1+3Z7+fWmsjrqwqMfU73/nOd72RCQAAAETNU1OArKTsHAAAAAAAAAAAAAAAAFA80meCHIsCyJydAwAAAAAKRFlV4uCyeGKZD3yoYD92WlMbxp1/dfhq6XJ/Xado3TJpivmsnFd3zDkmGwAAWbnr/ifdSxdAH3z0qcEIbNLCr1aG+obGdi9xzEWl97fmAXXh5Itvz8n13FT3/un1sHDxSgMZ8qS5eX0Ye84E95iSVIBt3394uK9739BUEZOkdu3pbtuHWHyEtTbq4okjvYkJAAAARM0TU4CspOwcAAAAAAAAAAAAAAAAUDzSZ4IciwLInJ0DAAAAAArID/uNqCiLJ1/xgQ8Vcr2HHhZua3gstLS2+is7RemWSVPMZeW0yX98xkQDACArK1atDj0GH+R+OuIuvPJWgxHYpA0treH6yS+G+obGdu3X9VNCp+rakltzO9eMDGMvvLXdr+fmSv9+L7/x8Te/JZB7bW1t4eIJt7vPlKQCrEtVIlxTWROaKmKS1K6N77mDdTbyEovKBtb+wJuYAAAAQJQ8LQXISsrOAQAAAAAAAAAAAAAAAMUjfSbIsSiAzNk5AAAAAKDQDBnyvfKq5EXl8USLj3yokNv/iDPCm7M/9Jd2itLtkx8PnWtqzWW1e10HpcKKlatNMgAAsnbWJRPdU0dcn6GHh3XNzQYjsEkNT8wK9Q2N7d6udaeU5Lrbubo2/PycG3JyTTfX3VNmhs8WLjOgIU9unTTF3+MlqUA7qdcu4b2KrqGpIiZJ7VJ6Tdmv717W2Igrq0rc4iVMAAAAIEqekgJkJWXnAAAAAAAAAAAAAAAAgOKRPhPkWBRA5uwcAAAAAFCgyvsnh5ZVJeb50IcKuU7VtWHc+VeHL7/yAVKKz5PPvxK6DkqZy2rfjw+ee5XJBQDAVnn3g4/dUxdAjzw5zWAENunPLzWF+obGdu/U8XeV9N+Yj/vV9Tm5rltq6ow5Yf2GFgMb8uChJ6aGLgPr3G9KUgFW13eP8HpFt9BUEZOkdumFrj1D9/gIa2y0tZXFkzt7AxMAAACIiiekAFlJ2TkAAAAAAAAAAAAAAACgeKTPBDkWBZA5OwcAAAAAFLAu/ZP/f3k8cZ8PfajQ6zXksHBbw2OhpbXVX94pKq+/80Hot8cR5rHarWnT3zSxAADYasOPONN9dcSlxpxnIAKbNOvdeaG+obHdu27StNB3z9Elu/Z2qq4No8+8JifXdkvdPWVmmL9wmcENeZD+22nl4IPdc0pSAbZrv33CtK6VoakiJknt0oSeA6yvEVdWlXinpmbMf/cGJgAAABAFT0cBspKycwAAAAAAAAAAAAAAAEDxSJ8JciwKIHN2DgAAAAAoAuXxxJHl8eRqH/xQoTfskNPCa281+es7RWXOx/NC9d5HmcPa5mr2OTq0tLaaVAAAbLV7H33WvXXEdaquDR998pnBCGzU3M+XhPqGxpz0s9OvLvn1d/TX1yBX13dLTZ0xJ6zf0GKQQ469OfvD0G+PI9x3SlIB1rf/fuHRbr1DU0VMktqlur57WF8jL3GqNy8BAACAKHgyCpCVlJ0DAAAAAAAAAAAAAAAAikf6TJBjUQCZs3MAAAAAQJH4UVXt9mXx5Fs+9qFi+PjpuPOvDosWL/VXeIrGp58tDDsNH2MOa5u67Lp7TCYAALbJ2nXNoffQw9xfR9ylV99pMAIbtXpNc6hvaMxJE+58LsR2PLDk1+BDT/5dzq7xlrp7yswwf+EyAx1y7JN5X4SdR/zcfackFWAV8US4vkd1aKqISdI291LXytAzvr/1NcriyRWd+u9f7s1LAAAAIN88FQXISsrOAQAAAAAAAAAAAAAAAMUjfSbIsSiAzNk5AAAAAKCIdBqU+rfyePIGH/1QMbT9boeG2xoeCxtaWvw1nqIw7/NFYafhY8xfbXVzPp5nIgEAsM0uuPJW99cR13/PI8P69RsMRmCjbnt4eqhvaMxJiaMvtA5/3eGnTMjZNc6kqTPmhPUb/F0bcumLhYvDHqmTrHmSVIB1+rrztt8xvF8RC02StI3VV1ZbW6Pvfm9dAgAAAPnmiShAVlJ2DgAAAAAAAAAAAAAAACge6TNBjkUBZM7OAQAAAABF6MfxEcnyeGKxj36oGNrrwHFh+uvv+os8RWHu/AWh6qejzV1l3YgjzzKBAArMex9+HNra2lwIoOjM+Xhe6FRd6z474h5/5iWDEdioR59/J9Q3NOakX9dPsQf8V4efMiFn1zmT7p4yM8xfuMyAhxxavmJVqDv6V9Y8SSrU+7HeQ8NbsW6hqSImSdvUQb13t65GXTy5nzcuAQAAgHzyNBQgKyk7BwAAAAAAAAAAAAAAABSP9Jkgx6IAMmfnAAAAAIAiVd53ZKeyqsRUH/5QsTR63Pjw2YIv/WWegvf+nE9CryGHmbfKqrvuf9LkASggq9esDTfc9YgLARStA4471312xB1y/IUGIrBRL77+t1Df0JizBteebB3+uk7VteGoM6/L6bXOpKkz5oT1G1oMfMiRteuaw9Gn/sa6J0kF2l59fxpeifUITRUxSdrqXu5aGXrG97euRlhZPDmny5Ah/8sblwAAAEC+eBIKkJWUnQMAAAAAAAAAAAAAAACKR/pMkGNRAJmzcwAAAABAcftueTwxrqwq0ewDICqGuu98UJhw4+Swfv0Gf6GnoL3y2uwQ2zFl3iqjfrLDqLBk2QoTB6CAnH/FLWHa9DddCKBo/fGpae61I65TdW34ZN4XBiPwLU0fLwz1DY0568QLb7UO/8NafOwvJ+b0emfS3VNmhvkLlxn8kCMtra3h7PHXW/ckqUCLx/cLj3XrFZoqYpK01V1bWW1Njb6LvGoJAAAA5IunoABZSdk5AAAAAAAAAAAAAAAAoHikzwQ5FgWQOTsHAAAAAHQAneLDB5bFk3N8/EPF0u6jTgwvznjLX+kpaI/+ufGbD/eas9pSPz/rChMGoIC88c6HoffQw8L69RtcDKBopdew+F4/c78dcb+t/4PBCHzLl0tWhfqGxpx17R/+Eip3OdQ6/F+l/z53/Hk35fSaZ9LEyY2hcdZHYUNLq0kAOTLxjoese5JUoHWPjwh3de8fmipikrTVjeq7hzU1wsqqkuvK+iYqvWkJAAAA5IOnnwBZSdk5AAAAAAAAAAAAAAAAoHikzwQ5FgWQOTsHAAAAAHQQP6hM/HtZPHGTj4ComBo9bnyY9/kif62nYF169Z3mqrbYs9NmmiwABWJDS0vY++BTwknnXuViAEXvN9fe7X474uJ7jQ4bNrQYjMC/3HO2homTG0N9Q+4a9fNLrcP/UOfq2jD2gltyes0z7e4pM8P8BctMBMiRO+57InSuqbX2SVIBtl08ES7rOTA0VcQkaat6uWtlqIwPt6ZG29PesgQAAADywZNPgKyk7BwAAAAAAAAAAAAAAABQPNJnghyLAsicnQMAAAAAOpjyeCJVVpVY6iMgKpa67XRgmHDj5NDcvN5f7Sk4ra1t4bCxF5ur2mT99zwybNjQYrIAFIjf33zfN+vzn5572cUAit7c+QtC55pa990R9+Tz0w1G4FvuenRmqG9ozFnjb3g8dKq2B/xjnWtGhlPG35XT655NU2fMCev9TQhyIn3/FdsxZe2TpAJtTK9dw7sVsdAkSVvR1ZU11tKoiyd8nBUAAADIOU89AbLi77YAAAAAAAAAAAAAAABQRNJnghyLAsicnQMAAAAAOqAfVdV1Ka9KvuhDICqmdht5Qnjh5Tf85Z6Cs2TZirDjfseap9pov77qdpMEoEB89Mln33x0u+ugVFi9Zq0LAnQIh4292H13xB1x0q8NROBbpkydHeobGnPazsmTrMP/UucBdeG08Xfn/Npn2t1TZob5C5aZEJADL898J/Tc9RBrnyQVaLV99gyzYt1CU0VMkrJuZJ89rKURVhZPfhGrSf0fb1gCAAAAueSJJ0BWUnYOAAAAAAAAAAAAAAAAKB7pM0GORQFkzs4BAAAAAB3VkCHfK69KXlQeT7T4IIiKqdHjxodPP1voL/gUlBlvvBe2qxlpjupbvffhxyYIQAFoa2sLdUf/6pu1+ehTf+OCAB3Gk89Pd98dcZ1rasO8zxcZjMA/aZz1UahvaMxpJ1xwi3V4I/1khwPCWb+dnPPrn01TZ8wJ6ze0mBjQzprmzA01+xxt7ZOkAm3XfvuEaV0rQ1NFTJKy6qWv147K+HBraYSVxZNXebkSAAAAyCVPOwGykrJzAAAAAAAAAAAAAAAAQPFInwlyLAogc3YOAAAAAOjgyvsnh5ZVJeb5IIiKqa6DUmHCjZPDuuZmf8mnYFw84XbzU//UPoecamIAFIi7H3jy7+vzfY8+54IAHcaGlpYwYNjR7r8jLv03CoB/NHvOF6G+oTGnXXvPC6H74IOtwxsptuOB4dwJD+T8N8imu6fMDPMXLDM5oJ3Nnb8gDE78wtonSQVav/77hce69wpNFTFJyqqrKgdYR6MsntxQXjWinzcrAQAAgFzxpBMgKyk7BwAAAAAAAAAAAAAAABSP9Jkgx6IAMmfnAAAAAIAS0KlX6vtl8eTDPgqiYmvnET8Pz0yb6a/5FITm5vVhj9RJ5qb+3i2TppgYAAVg4ZdLwva7HfrN2rxdzcjw1dLlLgrQoUy4cbL774gbOOyY0NLaajACf/fZwmWhvqEx59X9fLx1eBN13emgcP7VD+Xld8imqTPmhPUbWkwSaEdffrUsDDvkNGufJBVo3apGhDt7xENTRUySsqq2z57W0SiLJ6Z95zvf+a43KwEAAIBc8JQTICspOwcAAAAAAAAAAAAAAAAUj/SZIMeiADJn5wAAAACAElIeTxxZXpVc5cMgKrZGjxsf5s5f4K/6RO7N2R+GzjW15qVClwF1YdHipSYFQAE45rTL/r4+p8ac54IAHc7CL5eELgPr3IdH3LPTZhqMwN+tWbs+1Dc05rxf108Jnar9LWpTdR98cLjo2kfy8ltk0z2PzQxffLncRIF2tGLl6lB71C+tfZJUoG0XT4TLew4MTRUxScq4F7v2CJXx4dbRCOvUP3GYNyoBAACAXPCEEyArKTsHAAAAAAAAAAAAAAAAFI/0mSDHogAyZ+cAAAAAgBLzo6ra7cuqEm/6MIiKrZ/sMCpccOWtYdXqtf66T6TOuPg6c1LhqFMuNRkACsDjz7z0T+vzbQ2PuShAh3TMaZe5D/dvAKDA3PrQK6G+oTHn7ZQ80Tq8mSp3OTRcMnFKXn6LbJo4uTFMe+2j0NLaarJAO1m9Zm045PgLrX2SVMCd1GuX8F5F19BUEZOkjPpdzwHWzwgriyc/+0Fl4t+9UQkAAAC0N083AbKSsnMAAAAAAAAAAAAAAABA8UifCXIsCiBzdg4AAAAAKEHdug37n2XxxOXlVYlWHwhRsTVg2NHhwcen+gs/kfnyq2Wh566HmI8l3p+ee9lkAIjYipWrQ80+R//T+jx3/gIXBuiQXnj5dffhEddlQF34YuFigxH4uweffivUNzTmvBPOu9k6vIW23+3w8Jub/pSX3yPbGp6YFRYtWWnCQDtZv35DOPb0y619klTAHdR79/BWrFtoqohJ0hZ7/+uG993L+hltV3ibEgAAAGhvnmwCZCVl5wAAAAAAAAAAAAAAAIDikT4T5FgUQObsHAAAAABQwsriib2+7nMfB1ExduCY88MHH33qL/1E4vo7HzYPS7jeQw8Lzc3rTQSAiJ15ycR/Wp/3PfQ0FwXosNra2sIuyePdj0fcNbfebzACf/fc9A9DfUNjzrvm7hdC98EHW4e3UHzvY8Lvbn8mL79Jtl1/74vh1bfnfrOfA9uupbU1nHLBNdY+SSrghvTbOzTGKkNTRUySttgLXXuGrvER1s+IKosn1v+oqnZ7b1ICAAAA7clTTYCspOwcAAAAAAAAAAAAAAAAUDzSZ4IciwLInJ0DAAAAAErcf/YZ8cOyePJJHwlRMfaTHUaFy667J6xes9Zf/Mmr9es3hEH7H2celmjnXnaTSQAQsVdemx06Vdf+0/p8za33uzBAhzbxzofdj0dc+t+Bra1tBiPwjdffmxfqGxrzUu2xv7YOZ9BOyRPDNXe/kLffJdseePrNsHTFGpMH2kH6nuzs8ddb+ySpgOvff//weLfeoakiJklb7Nc9d7R2RtvT3qIEAAAA2pMnmgBZSdk5AAAAAAAAAAAAAAAAoHikzwQ5FgWQOTsHAAAAAJD23fKqxKllVcl1PhKiYqx676PCg49P9Vd/8ur2ex83/0q0N2d/aAIARKi5eX0YWjf2W+vzB3+d6+IAHdriJcvDT3YY5Z484l54+XWDEfjGx/O/CvUNjXnp/KsfsgZn2J4HnxmumzQtb79Ntt1430vhzabPTCBoB21tbeHXV91u7ZOkAq57fES4q3v/0FQRk6TN9l5F1/DTvj+1dkbbKK9QAgAAAO3F00yArKTsHAAAAAAAAAAAAAAAAFA80meCHIsCyJydAwAAAAD4u879R/Quiyfe9pEQFWsHHHduaJoz11//yYs1a9eFfnscYe6VWLuPOtHgB4jYZdfd8631eXDiFy4MUBJ+cdYV7ssjbsyZvzUQgW8sXbEm1Dc05q2qvY+1DmfY8NEX5PW32Zoeff6dsHL1OhMJ2sHEOx6y9klSAbddVSL8vrImNFXEJGmz/albr2/WDGtnRMUTn/6w30//tzcoAQAAgPbgKSZAVlJ2DgAAAAAAAAAAAAAAACge6TNBjkUBZM7OAQAAAAD8k06DUv9WVpW8xsdCVKx1GVAXLrjy1rBi1WpPAci53998n3lXYk2882EDHyBC78/5JHQZWPet9fnSq+90cYCSMG36m+7LC+DvDgu/XGIwAqGtrS3ccO9Lob6hMS8dccpV1uEsOvikK/L222xtNz/wSpg95wuTCdrBHfc9ETrX1Fr/JKmAO6nXLuH9ilhokqTNdPb2O1szo+1ib08CAAAA7cETTICspOwcAAAAAAAAAAAAAAAAUDzSZ4IciwLInJ0DAAAAANioTtWJkeXxxGIfC1GxVr33UeGRP/3lm4/bQq4sXbYydN/5IHOuREp/lPXzBYsNfICItLS2hv0OP2Oja/TMN993gYCSkP437i7J492fR9zEOx4yGIFvNDwxK9Q3NOal397yVOhcM9I6nEWjz7wmb7/PtvTUi++Htes2mFCwjR58fGroMqDO+idJBdxRvYeEdyu6hqaKmCRttHe+XiMG9xtmzYyosqrkuvL4/t29OQkAAABsK08vAbKSsnMAAAAAAAAAAAAAAABA8UifCXIsCiBzdg4AAAAAYJPK+47sVFaVeMFHQ1TM7Xf4GeH1dz7wRICcGXvOBHOtRDps7MUGPECEbrrnjxtdn+N7jQ6trW0uEFAy6m9/0P15xO00fExoa7P3ACE82fh+qG9ozFu7jjrFOpxFnatrw0kX35bX32hru+ORV8OnXyw1qWAbPfrnxtBlYJ01UJIKuBF99wyzYt1DU0VMkjbaI937hO3iCWtmVMWTj3prEgAAANhWnlwCZCVl5wAAAAAAAAAAAAAAAIDikT4T5FgUQObsHAAAAADA5qVS/62sKnFueTy5wYdDVLQfT62pDePOvzp8+dUyTwZod881vmaelUiPPDnNgAeIyLzPF4Uegw/a6Pp87mU3uUBASVm0eGnoMrDOPXrEvTjjLYMRCC+98XGob2jMWydccIs1OMu6DBwVzr7y3rz+TtvS1BlzwvoNLSYXbIOn/zIjxHZMWQMlqYAb3H+fMK1rZWiqiEnSRhvbaxfrZZT1T+zvpUkAAABgW3hqCZCVlJ0DAAAAAAAAAAAAAAAAikf6TJBjUQCZs3MAAAAAABnpFB8+sCyenOPDISrmtt/t0DDxjofC+vUbPCGg3WxoaQnxvX5mjnXweu5ySFizdp0BDxCRQ0+4cJNr9Isz3nKBgJJz3BmXu0+PuLHnTDAQgfDOh5+H+obGvHX1PVNDbNCB1uEsiw1KhQuufjivv9W2NOnxWWHRkpUmGGyDV16bHSoHH2wNlKQCrl///cLj3XqHpoqYJH2rN2PdwoD++1ovI6osnvhrlyFD/pc3JgEAAICt5YklQFZSdg4AAAAAAAAAAAAAAAAoHukzQY5FAWTOzgEAAAAAZOwHlYl/L4sn7vbxEBV7u408ITz/4ixPCWg3519xi7nVwTvzkokGOkBE7nv0uU2uz32GHh42tLS4SEDJeeHl192nR1zFjgeEr5YuNxihxM39fEmob2jMa/v97Dzr8FZUueth4dIbn8j777W1XT/5xfDq23NDW1ubiQZb6c3ZH37zdwNroCQVbt3jI8I9PfqFpoqYJH2ru3v0t1ZGWTx5jrclAQAAgK3laSVAVlJ2DgAAAAAAAAAAAAAAACge6TNBjkUBZM7OAQAAAABkrbwqeUR5PLnCB0RU7B17+uVh7vwFnhawzV55bbY51cGb8cZ7BjpABL5aujz02+OITa7Pp190nYsElKTW1raw0/Ax7tUj7raGxwxGKHFLV6wJ9Q2Nee3sKyZbg7ey/nsdFa68/em8/2bb0oNPvxmWrVxrssFWmt30t9B/zyOtgZJUwHWpSoT6yurQVBGTpG/1s967WSuja1V535GdvCkJAAAAbA1PKgGykrJzAAAAAAAAAAAAAAAAQPFInwlyLAogc3YOAAAAAGCrdK6p7VoWT073AREVez/ZYVS44Mpbw8pVazw1YKs1N68PXQelzKkO2uDEL0JbW5uBDhCB48++crNr9LPTZrpIQMm69tYH3K9H3J6pkw1EKHEtra1h4uTGUN+Qv66bNC30HnqkdXgr22H/48Pv73o+r7/ZtnbzAy+H2XO+MOFgK835eF4YMOxoa6AkFXCdvu6CnoNCU0VMkv6pV2PdQ+/4/tbKiCqrSkzyliQAAACwNTylBMhKys4BAAAAAAAAAAAAAAAAxSN9JsixKIDM2TkAAAAAgK03ZMj3yquSF5XHEy0+JKJir2afo8ODj08NbW1tnh6wdf/3yjHnmUsdtKtvuc8AB4jAc42vbXZ9rhx8cFjX3OxCASVr0eIlocvAOvfsEffGOx8ajFDi7njk1VDf0JjXDj7xt9bgbWjIqFPDtZOm5f1329aebHw/rF23waSDrTDv80VhcOIX1kBJKvCO6b1beLeia2iqiEnS36uvrLZGRlfbj6uTu3pJEgAAAMiWJ5QAWUnZOQAAAAAAAAAAAAAAAKB4pM8EORYFkDk7BwAAAACwzcr7J3Yvq0rM8yERdYT2P+IMH8Rmq1x1073mUAesc01t+PSzhQY4QJ6tWLU6DBx2zGbX6LHnTHChgJJ3zGmXuW+PuDMvmWggQol7+Jm3Qn1DY14bf/1joVN1rXV4G6obc0nef7f26PaHXw2ffL7ExIOtsGDRV2H3USdaAyWpwEv03TPMinULTRUxSfp76bXBGhlNZVXJGd/5zoX/nzckAQAAgGx4OgmQlZSdAwAAAAAAAAAAAAAAAIpH+kyQY1EAmbNzAAAAAADtIlaT+j/l8eRkHxNRR2i7mpHhl5feEJYsW+FJAhmbPmu2+dMBS405z+AGiMCvfnPDFtfox595yYUCSt7zL85y3x5xPQYfFFauWmMwQgl75pUPQn1DY97bcfgJ1uFt7Kgzr43kt2uPps6YEza0tJqAkKXFS5aHPVMnWwMlqcDbtd8+4cWuPUJTRUySvumFrj1D1/gIa2RElfVPjvZ2JAAAAJANTyYBspKycwAAAAAAAAAAAAAAAEBtInYpAAAgAElEQVTxSJ8JciwKIHN2DgAAAACgXZVXJX9eHk+u9kERdYR6DTks3NbwWNjQ0uKJAlu0YtVq86YDdv+U5wxugDx77a2m0LmmdrPrc9dBqbB6zVoXCyh5ra1tYcf9jnXvHnENjzxjMEIJe/XtuaG+oTHvHXPWddbgbaxzzchw2vi7I/n92qPJf3o9fLVstUkIWVq8ZHnY68Bx1kFJKvBq+u8bnu62fWiqiEnSN13Yc0frY0SVxROf/6Ay8e/ejAQAAAAy5akkQFZSdg4AAAAAAAAAAAAAAAAoHukzQY5FAWTOzgEAAAAAtLsf1wzvWV6VfN1HRdRRGjJybHjh5dc9VWCL+u95pDnTgeq+80Fh5ao1BjZAHjU3rw+7jzpxi2v0Madd5mIB/JerbrrX/XvEJX52loEIJez9vy0M9Q2Nee+K254OnWtGWoe3sdgOqXDB1Q9H8hu2Rzfc91J4s+kzExGytGz5yrDvYadbByWpwKuMDw8PdO8bmipikhTe/brd+u1tfYyosqrkZd6KBAAAADLliSRAVlJ2DgAAAAAAAAAAAAAAACge6TNBjkUBZM7OAQAAAADkRLduw/5nWTxxeXlVotWHRdRRGj1ufJg7f4GnC2xS7VG/NFc6UKdccI1BDZBnv63/Q0Zr9ENPTHWxAP7Lwi+XhC4D6tzDR9wHf51rMEKJ+mzhslDf0BhJg2tPtga3Q5W7HhYuu+nJyH7H9ujR598Jq9c0m5CQheUrVoX9Dj/DOihJBd5PqhLh5h5VoakiJknhke59Quev1wXrY/4rq0o0l8f37+6tSAAAACATnkYCZCVl5wAAAAAAAAAAAAAAAIDikT4T5FgUQObsHAAAAABATpXHk/uVVyUW+riIOkpdB6XCpdfcFVatXuspA99y6oXXmCcdqBdnvGVQA+TR+3M+CV0G1m1xfU7/N8uWr3TBAP7BUadc6h4+4i688lYDEUrUytXrQn1DYyQd98vrrcHtVM2wMeH3dz0f2W/ZHt328PTwyWdfmZSQhaXLVoZ9Dz3NOihJBd528US4sueA0FQRk6Twi167WhsjqiyefNjbkAAAAEAmPIkEyErKzgEAAAAAAAAAAAAAAADFI30myLEogMzZOQAAAACAnPthv5H/WVaVfNzHRdSR2mHfY8NjT7/oSQP/5LrbHjA/Okg77ndsaG1tM6gB8iS95iZ+dlZGa/RhYy92wQD+xTPTZrqPj7g+Qw8Pzc3rDUYoQW1tIdxw70uhvqEx7/3u9mdC5wF11uF2avcDzwjXTZoWyW/Znk177aPQ0tpqckKGlq9YFYYfcaZ1UJKKoNO33zk0VcQklXizYt1C//77Wxcj6sf9a/f2NiQAAACwJZ5CAmQlZecAAAAAAAAAAAAAAACA4pE+E+RYFEDm7BwAAAAAQL58tzyeGFdWlVznAyPqSI069pzw3ocfe+LANyY99GfzooN0xcRJBjRAHt10zx8zXqPT+y0A/6y1tS3ssO+x7uUj7tE/NxqMUKL+8Nhrob6hMZJ2rTvFGtyOpY6/LLLfsj1reGJWWLx0lckJGVqxcnUYfsSZ1kFJKoKO6b1beLciFpoklXQ39aiyJkbXu98ZMuR7XoUEAAAANscTSICspOwcAAAAAAAAAAAAAAAAUDzSZ4IciwLInJ0DAAAAAMirzv1H9C6LJ972gRF1pDrX1IZx518dFi9Z7slDiXvoianmRAfprx/PN6AB8mTe54tCj8EHZXzftWjxEhcNYCMm3DjZvXzEHXL8hQYilKhHn38n1Dc0RtKYc26wBrdjnaprw/Hn3RTZ79me3XDfS+HNps9MUMjQipWrw4gjz7IWSlIRlOqze3gr1i00VcQklXDptcCaGE1l8eQJ3oIEAAAANsfTR4CspOwcAAAAAAAAAAAAAAAAUDzSZ4IciwLInJ0DAAAAAMi7ToNS/1ZWlbzGR0bU0eo15LBwW8NjYUNLiycQJepPz71sLnSAkqPPNpgB8ujQEy7MeI0edew5LhjAJny+YHHYrmake/oI61RdGz6Z94XBCCXohRlzQn1DYyRNuOPZsN3AOutwO9ZlwKjwqwn3Rfabtnd/mvZeWLtuvYkKGVi9Zu03f3uwFkpS4bdX35+GV2PdQ1NFTFKJNq1rZehWNcKaGEFlVYmvygbW/sBbkAAAAMCmePIIkJWUnQMAAAAAAAAAAAAAAACKR/pMkGNRAJmzcwAAAAAAkSmvSo4qq0ou8bERdbSGjBwbXnj5DU8hStDUl2aZAx2gPzz0Z4MZIE/ue/S5rNbo2xoec9EANuPIky9xTx9xV0ycZCBCCZo5+9NQ39AYWUNGnWoNbucqdzk0XHbTk5H+ru3Z7Q9PD598vsRkhQysXLUm1B71S2uhJBVBO/fbJ0zrWhmaKmKSSrRLeu5gPYyosqrkNd5+BAAAADbFU0eArKTsHAAAAAAAAAAAAAAAAFA80meCHIsCyJydAwAAAACIVNmAZOeyqsQLPjaijtjocePDp58t9DSihEyfNdvYL/JiO6bCsuUrDWaAPPhq6fLQb48jMl6jO1XXhvlfLHLhADbjqanT3ddHXM0+R4eW1laDEUrMex8tCPUNjZH1i3NvsgbnoOphx4Xf3/V8pL9tezZxcmN46Y2PQ2trm0kLW7B6zdqQGnOetVCSiqB4fL/wVNdeoakiJqkEe/frhvbbx3oYRfHkhk79Rvbx9iMAAACwMZ44AmQlZecAAAAAAAAAAAAAAACA4pE+E+RYFEDm7BwAAAAAQPRSqf9WVpU4L/2xDR8dUUer204HhqtuujesXdfsqUQJmP76u8Z9kTfmzN8ayAB5cvzZV2a1Ru9/xBkuGsAWbGhpCTX7HO3ePuKemTbTYIQSM/fzJaG+oTGyJtzxXNhuYJ01OAftefCZ4bpJ0yL9fdu7+596IyxbsdbEhS1YtXptqDvmHGuhJBVBlfHh4f7ufUNTRUxSCfZot96hc1XCehhBZfHkk158BAAAADbG00aArKTsHAAAAAAAAAAAAAAAAFA80meCHIsCyJydAwAAAAAoGJ3iwweWxZNzfHREHbEBw44ODz4+1ZOJDu6pqdON9yLv6b/MMJAB8iC93ma7Rk+84yEXDiADV0yc5N4+4o457TcGIpSYxUtXhfqGxkjbPXW6NThHHXzSFZH/vu3dTQ+8HD74eJHJC1uwZu26cNDPz7cWSlIR9JOqRLixsjo0VcQklWA/77WrtTCiOlUn9/HWIwAAAPCvPGkEyErKzgEAAAAAAAAAAAAAAADFI30myLEogMzZOQAAAACAgvL9HYb9R1k8cbePjqijdsBx54b3PvzYE4oO6r5HnzPOi7h+exwRNmxoMZABcmzFqtVh4LBjsl6nP5n3hYsHkIH5XywK29WMdI8fYV0G1IUFi74yGKGErF23PtQ3NEbaCefdbA3O2QfCa8Mp4++K/DfORc+8/EFY7+9hsFlr1q4LB//iAuuhJBVB28UT4beVA0NTRUxSifVarHvoE9/fWhhF8cR73xky5HveegQAAAD+kaeMAFlJ2TkAAAAAAAAAAAAAAACgeKTPBDkWBZA5OwcAAAAAUJDKq5JHlMeTK3x8RB3149pnXTIxfLV0uScVHczNf3jUGC/izvvtzQYxQB786jc3ZL1GDzvkNBcOIAuHjb3YPX7E1d/+oIEIJeaG+14K9Q2NkTXhzudCl4GjrME5KjYoFS6ufzTS3zhX/eHx18KXS1aZxLAZa9auCwf/4gLroSQVSb/cfqfQVBGTVGJdW1ltDYyq/onjvO0IAAAA/CNPGAGykrJzAAAAAAAAAAAAAAAAQPFInwlyLAogc3YOAAAAAKBgbTegLlYWT77i4yPqqPUeeli4reGx0NLa6olFB3Hl9ZOM7SLurXfnGMQAOfbaW02hc01t1mv0tbc+4OIBZOHJ519xjx9xgxO/CG1tbQYjlJC7p8wM9Q2NkbbHgWdag3NYvz2PDhPufDby3zkX3XDfS+HNps9MZNiMteuaw6EnXGg9lKQi6ejeu4V3K2KhSVLJ9P7X7d93L2tgBJXFk1/8oDLx7952BAAAAP4fTxcBspKycwAAAAAAAAAAAAAAAEDxSJ8JciwKIHN2DgAAAACgsA0Z8r3yquRF5fFEi4+QqKO2zyGnhumvv+upRQdw3uU3G9NF2tC6sQYwQI41N68Pu486cavW6Tkfz3MBAbKwoaUlVO99lHv9iHt55jsGI5SQh555K9Q3NEbaz8+90fqb678hHXBauG7StMh/61z1xLT3wtrmDSY0bOZvG6PHjbceSlKRdFCf3cPbsa6hqSImqUR6qtv2YbuqhDUwiuLJS7zoCAAAAPw/niwCZCVl5wAAAAAAAAAAAAAAAIDikT4T5FgUQObsHAAAAABAUfhxdXLX8njiEx8hUUetU3VtOOGXvwvzv1jk6UURO/LkS4znIq3+9gcNYIAc+239H7Zqjd7rwHEuHsBWuLz+Hvf6EXfiuVcZiFBCnnrx/VDf0BhpV97+dOhcM9IanOMOGnt55L91LrvzjzPCZ4uWm9SwCeuam8NhYy+2HkpSkbR/373CrFi30FQRk1Qinb79zta/KIonV5cNSHb2liMAAACQ5qkiQFZSdg4AAAAAAAAAAAAAAAAoHukzQY5FAWTOzgEAAAAAFI3v7zDsP8riiXt8iEQdua6DUuHSa+4KK1at9hSjCO2SPN44LsI619SGzxZ8aQAD5ND7cz4JXQbWbdU6/fub73MBAbbC3PkLvrnXdc8fXbEdU2HpspUGI5SIxlkfhfqGxsjbKTHWGpzjOlXXhhMvvLUgfu9cNXHyi+HVt+eGtrY2kxs2Yu265nDgmPOtiZJUJO3eb+8wPdYjNFXEJJVAb8W6hQH997X+RVBZPHG3NxwBAACANE8UAbKSsnMAAAAAAAAAAAAAAABA8UifCXIsCiBzdg4AAAAAoOiUxxNHlseTK3yMRB256r2PCvc9+lxobfXR0mLR3Lw+dBlQZ/wWYemPnwKQO+n7mcTPztrqdfrDv81zEQG20iHHX+ieP+Jun/y4gQglYtZ780J9Q2PkHXna762/eSi2QypcXP/HgvjNc9kjz74dVq1pNsFhI1avWRtqj/qlNVGSiqSd+g0L07pWhqaKmKQS6LYe/a19kZRo/XF1bY23GwEAAABPEwGykrJzAAAAAAAAAAAAAAAAQPFInwlyLAogc3YOAAAAAKAo/aiqrkt5PNHoYyTq6A075LQwfdZsTzSKwFvvzjFmi7T7pzxnAAPk0E33/HGr1+jdDzjJBQTYBo89/aJ7/ojbM3WygQglounjhaG+oTHyxl//mPU3T/Xb86gw4c5nC+J3z2W3PjQ9fPLZVyY5bMSKVavD/kecYU2UpCKpb//9wpPdeoWmipikEuiAPrtb+yKorCrxgjcbAQAAAE8SAbKSsnMAAAAAAAAAAAAAAABA8UifCXIsCiBzdg4AAAAAoHgNGfK98qrkReXxRIuPkqijN3rc+DB3/gJPNgrYHx76s7FahHXb6cCwctUaAxggR+Z9vij0GHzQVq/TE26c7CICbIMNG1pC1U9Hu/ePuDdnf2gwQinc+y5YGuobGgui/nsdbf3NU3sdcnbB/O65btprH4WW1jaTHf7FipWrw76HnmZNlKQiqTI+PDzUrU9oqohJ6uBN61oZusZHWPsi6MfxEUkvNgIAAEBp8xQRICspOwcAAAAAAAAAAAAAAAAUj/SZIMeiADJn5wAAAAAAil559YhBZfHEX32URB292I6p8Jtr7w4rVq32hKMAnXnJROO0CDvp3KsMXoAcOvSEC7dpnW6aM9dFBNhGl15zl3v/iDt7/PUGIpSAJcvXhPqGxoLogOMvs/7msdGnX1Mwv32uu/+pN8LylWtNePgXXy1dHnY/4CRroiQVSV3jI8I9PfqFpoqYpA7ehT13tO5FUPo9vl69Uv/DW40AAABQujxBBMhKys4BAAAAAAAAAAAAAAAAxSN9JsixKIDM2TkAAAAAgA7h+zsM+4+yeOIeHyZRKdRn6OHhtobHQktrqycdBWTX2uONzyLshZffMHgBcuT+Kc9t0xqd3lsB2HZz5y8Inapr3f9HWI/BB4VVq9cajNDBrV/fEuobGguiX024z/qbxzrXjAxnXzG5YH7/XHfzA6+Ev376pUkP/+LLr5aFoXVjrYuSVCR1qUqEGyqrQlNFTFIHbnZF17BTv2HWvQjqVJU8yRuNAAAAULo8PQTISsrOAQAAAAAAAAAAAAAAAMUjfSbIsSiAzNk5AAAAAIAOpTyeSJVVJZb6OIlKofTHGZ9/cZanHQVg4ZdLjMkirHrvo0JLa6sBDJADXy1dHvrtccQ2rdNXTJzkQgK0kwPHnO/fABF376PPGohQAm66/+VQ39AYeddNmhYqdznU+pvHenx9vS+/5amC+P3z1Uuv/y20traZ+PAPPl+wOOw0fIx1UZKKpE5fN77nDqGpIiapAzepez9rXgSVVSWXdOqV+r63GQEAAKA0eXIIkJWUnQMAAAAAAAAAAAAAAACKR/pMkGNRAJmzcwAAAAAAHc6Pquq6lMcTjT5QolLp6FN/E/429zNPPSL04ONTjcUibPzVdxq8ADly/NlXbvM6Pbvpby4kQDv541PT/Bsg4pKjzzYQoQTc9eiMUN/QWBDtP/p862+e2zl5Urj2D38pmDGQj+5/6o2wfOVakx/+wfwvFoVB+x9nXZSkIur07XcOTRUxSR24g/sMtd5FUuJ33mQEAACA0uSpIUBWUnYOAAAAAAAAAAAAAAAAKB7pM0GORQFkzs4BAPB/2bvzKKnLO/H3mfnlnnvn/pH7uznnTibdKFY1IMrSVQ2Ca8Adla5qkHINxn2NURO3aBLcNRr3dg0qUSjc9y1mRLERXHBBRcsVcRcVFUFoaOq5tr+cucncLNUKVd+n+vU65/3XnDNnTvXj5/Hr833mCwAA1KdRo77bmMmf2pjJdflAiXpDfTcaH4499ZLwyaefO/2ogYOPPds6jLCXXn3T4gVYCx7smPutZ/QmYw/0QwKsQStXrgpDt5roOaDGvfz6WxYj1Lkb7nsmtBc7EtGRp/3B7K1BEw4+IzFroFpdedOc8NpbHxkA8BfeWPhuyG67t7koSRF12IabhxdTTaGUSkuqwx5pWj+kM63mXZVryOZXrDt8fNqLjAAAAND7ODEE6JGCnQMAAAAAAAAAAAAAAADi0X0nyLUogMrZOQAAAACAutbY0rpxQyb3mg+VqLc0aPSe4ariXWFVV5dTkCpZtaorbPCjPay/yNp+96MsXoC1YMnSZWGjMft96zl9xkXX+jEB1rBTz7/Gs0CNO/ncqy1EqHN3zHg+tBc7EtEF1z4U1hsxwfytcn1a2sLPTrkmMeugmj0y9/XQtbpsEMCfvbbgnZDZZm+zUZIiauLgUWF+qimUUmlJddivNhhp1tWiTH66NxgBAACg93FaCNAjBTsHAAAAAAAAAAAAAAAAxKP7TpBrUQCVs3MAAAAAAHXv+yPGfK8hk7vOh0rUm9pywuHh4dlPOwmpgplznrHmIuzKqXdYvABrwS/PuGyNzOl5L77mxwRYw15/893Qp6XN80ANGzz6x6Gzc6XFCHXsj4+WQnuxIzFtucsvzN8a1LTJruH0y+9J1FqoVjfe/0z4/IvlhgH82YuvLPj63wHNRkmKp50HbxnmpfuFUiotqc56IdUURjaPMeuqX/mHLW3DvMEIAAAAvYuTQoAeKdg5AAAAAAAAAAAAAAAAIB7dd4JciwKonJ0DAAAAAOg1GjO5QkM296mPlag3tdvBvwmlVxc6EVmLjpp0obUWWX2Hjw+LPl5s8QKsYU89VwrrDGv71nN6450OCOVy2Q8KsBbsvP8Jnglq3J0PzLIQoY7NfPK10F7sSEwHnnCZ2VujNtrxkHDR1JmJWg/V6sqb5oTX3vrIQIA/e6H0Rthw1J5moyRF1A5Dtg5PpfuFUiotqc6a2r/ZnKtBDdncQ95cBAAAgN7FKSFAjxTsHAAAAAAAAAAAAAAAABCP7jtBrkUBVM7OAQAAAAD0KusMa2tqyOQf88ES9ab6Dh8fjj31kvDx4s+djKxhKzo7w8AtdrfOImvi4adYvABrWGfnyrDlzj9dI3P6tAum+EEB1pLb7p3pmaDG7X7IJAsR6tjjzy0M7cWOxHT25AdCn5Y287dGTTj4jESth2r3yNzXQ9fqssEAX3ny2ZfCgM12NRslKaK2HLpdeDzdP5RSaUl11oTBW5pzNahPS357by4CAABA7+GEEKBHCnYOAAAAAAAAAAAAAAAAiEf3nSDXogAqZ+cAAAAAAHqfUaO+25jNn9SYyXX5aIl6U4NG7xkmT7szrFrV5YRkDbnjjx3WVoTdfv8jFi/AGvbb9qlrbE4/8/wrflCAtaSzc2UYsuVEzwU1/XhsW3jz7fctRqhT815+N7QXOxLVsB0OMn9rOPOPOOWaxK2Janbj/c+EJUuXGw7wlcefeTH033RX81GSImqzoWPCrKYBoZRKS6qjHuo3MKQyOXOuyjVk8vO+851J/+rFRQAAAOgdnA4C9EjBzgEAAAAAAAAAAAAAAADx6L4T5FoUQOXsHAAAAABAr9XY0rpxQyb3ug+XqLe1Rdsh4a4HZjklWRP/HysP/JU1FVkDN989fLl8hcULsAa99Oqboe9G49fInN5ozH6hXC77UQHWol+ddaVngxr3u8uKFiLUqZcXLArtxY5EVTjkTLO3hjVtums44/J7ErcuqtnkW+aEhe8tNiDgKzPnPBPSIwvmoyRF1PDmHcKMpoGhlEpLqqN+ucEmZlxtmuiNRQAAAOgdnAwC9EjBzgEAAAAAAAAAAAAAAADx6L4T5FoUQOXsHAAAAABAr/b9EWO+15DJXeejJeqN7XrQr8OLryxwWvINLXjrvdCnpc1aiqyjT77Y4gVYg1avLofcT45dY3P65HOv9qMCrGXdz4GeDWr8Qe4x+4au1astRqhDb763OLQXOxLVsb+dbvbWuI1bDwsXTZ2ZuLVR7WY/uyCUy2WDgl7voUefCqmRE8xHSYqoIc07hvv6bRhKqbSkOmleul8Y3ryDGVftMrk3+/Ub8797YxEAAADqn1NBgB4p2DkAAAAAAAAAAAAAAAAgHt13glyLAqicnQMAAAAA4CsNmdafNGbyS3zARL2tdYeNC8effln4ePHnTk166KTfXWUNRdicuS9YvABr0BXX3b5G5/STz77kRwWogh32+Lnngxr3n488aSFCHfrg4yWhvdiRqC667uGQHlEwe2tc4ZAzErc2atFtDz4Xli3vNCzo9e56YNbX5zPmoyTF08DMTuG2/oNDKZWWVCdNHpAx32pQQzb3c28qAgAAQP1zIgjQIwU7BwAAAAAAAAAAAAAAAMSj+06Qa1EAlbNzAAAAAAD82TrD2poaMvnHfMBEvbEBm+0azr18eljR6YOmlViydFkYuMXu1k5kbbzTAaFcLlvAAGvI2+8t+vrfIdbUnB62/b5h9WpzGqAaptxwr2eEGrffz8+0EKEOffbF8tBe7Ehcoyf83OytcX1a2sIxZ01L5Pqodtfc9nh4b9HnBga93s13PxTWGdZmRkpSRPXLtoZi/6GhlEpLqpPGD9nKfKtyDdncJ32b8//Tm4oAAABQ35wGAvRIwc4BAAAAAAAAAAAAAAAA8ei+E+RaFEDl7BwAAAAAAH9p1KjvNmbzJzVmcl0+ZKLe2KatB4U7H5gVyuWyU5R/4JIpt1ovEXbOpdMsXoA1aI9DJ63ROf3rs3/vRwWokiVfLAv9NtnFc0IN6zt8fPjwo8UWI9SZFZ2rQnuxI3Htc/RFZm8CGvijH4ezr3ogkWuk2l06fVZ4av7bhga93pQb7jUfJSmy1svmwuQBmVBKpSXVQTOaBn79z7X5Vt0aMrmzvKQIAAAA9c1JIECPFOwcAAAAAAAAAAAAAAAAEI/uO0GuRQFUzs4BAAAAAPA3NLa0btyQyb3uQybqrY2deEx47On5TlL+hs7OlaFlu32skwh7bcE7FjDAGnLjnQ+u8Tn92FMv+GEBquinJ57nOaHGXXLNLRYi1KFLp88K7cWORHVy+x3mbkL60c5HhYunPZK4NVKr7pk5P6zoXGVw0Kv97rKi+ShJkdU3mwuXr98SSqm0pDroyA03NduqXEMmv/yHw8au6w1FAAAAqF9OAQF6pGDnAAAAAAAAAAAAAAAAgHh03wlyLQqgcnYOAAAAAIC/4/sjxnyvIZuf6mMm6s3tdvBvwkuvvulE5S9MueFeayPCWvc61uIFWEM++fTzMHSriWt0Tme33TusXl324wJU0awn5nlWqHGbth4UymX7H9Sbq255LLQXOxLXoNF7mb0Jad9j2xO5RmrV1Lvmho8+XWp40Kud9LurzEdJiqx1M7lw7vrDQymVlhR5T6f6hSHNO5pt1S6Tv8rbiQAAAFC/nAAC9EjBzgEAAAAAAAAAAAAAAADx6L4T5FoUQOXsHAAAAAAA/0RjJldoyOY+9UET9db6Dh8fjj31krDo48W9/mBlRWdnGD5mX+siwqbccK+TQYA15JDjzlnjc3rSOZP9sABVVi6Xw6atB3leqHFz5r5gMUKdmXb33NBe7EhcO+39a3M3Mf+9defwmwtvTeQ6qVWX3fBoeOHV9w0QevW/mx816UIzUpIiq89XnTpwRCil0pIi77z1h5tr1S6T6+ozdNxgbyYCAABAfXICCNAjBTsHAAAAAAAAAAAAAAAAxKP7TpBrUQCVs3MAAAAAAFTgB8359Rqz+Vk+aqLeXP9Ndw2nX/iHsGTpsl57sDJ52p3WQoStN2Ln8MmnnzsZBFgDHuyYu1Zm9dx5JT8uQA1c8PsbPDPUuJ/96nwLEerMTQ88G9qLHYnrp5Mmm7sJqnnb/cIF1z6UyLVSyx587JWwqmu1QUKvtGpVV9jrZ6eakZIUYb/YYNNQSqUlRdyLqaaw1dDtzLRqlyDsljMAACAASURBVMnd5a1EAAAAqE9O/wB6pGDnAAAAAAAAAAAAAAAAgHh03wlyLQqgcnYOAAAAAIBKjRr13cZs/qTGTK7Lh03Um8tuu3eYdssfQ9fq3vVx088+/yJktvmJNRBh+/38TKeCAGvAkqXLwvAx+67xOT1ih/1DuVz2AwPUwPsffhzWHTbOc0MNa9q48PXzJlA/7pjxfGgvdiSu3139p7BOS5vZm6Dy+56cyLVS666/9+nw2ZLlhgm90vIVnWH8vr80IyUpwn6xwaahlEpLirhb+g0Ofcyz6tfSupWXEgEAAKD+OPkD6JGCnQMAAAAAAAAAAAAAAADi0X0nyLUogMrZOQAAAAAAeqhPNvejxkx+oQ+bqLe35c4/DX98+PFec6hy9MkX+7tH2n0z5jgVBFgDjj/9srUyp089/xo/LkANTTz8FM8NNe7q6++2EKGO3PvIi6G92JHINtrxYHM3QfVpaQtHnDolseulll1x0+zw+lsfGyj0Sp8vWRq22eUIc1KSIuyQQZuHF1NNoZRKS4q0iYNHmWdVriGTn+NtRAAAAKg/Tv0AeqRg5wAAAAAAAAAAAAAAAIB4dN8Jci0KoHJ2DgAAAACAb+D7I8Z8ryGbn+rjJlI+jJ14TOh4fF5dH6jMmfvC1x+59feOr0Gj9wydnSudCgIkeC989oVX/MAANXTPf8727FDjttnlCAsR6sifZr8c2osdiWzXQ88ydxNW/013C7/9/f2JXTO1bvazC0K5XDZY6HU++uSz8KNxh5qTkhRhBwzaIryYagqlVFpShHWk1w9NmVbzrMo1ZHM5byMCAABAfXHiB9AjBTsHAAAAAAAAAAAAAAAAxKP7TpBrUQCVs3MAAAAAAHwLjZlcoSGb+9QHTqR82P2QSeHZF16pu8OUZV8uD1u0HeJvHGknnnmFE0GAb6mzc2UYPf6wtTKnNxl7oA+kA9TYypWrQvPWe3l+qHHz5r9qMUKdePiJV0N7sSORHXf2dDM3gW0x/shw8bRHErtuat1tDz4Xvly+0nCh11n4zgchu+3e5qQkRdjEQaPD/FRTKKXSkiLshA02NsuqXEM29/x3vjPpX72JCAAAAPXDaR9AjxTsHAAAAAAAAAAAAAAAABCP7jtBrkUBVM7OAQAAAADwLf2gOb9eYzY/y0dOpP/Vbgf/Jsx/eUHdHKYcctw5/q4R9/TzLzsRBPiWTr9gylqb02dcdK0fGCABTj73as8PNe740y+zEKFOPPr0G6G92JHILpo6M6Q3Lpi7CeyA4y9N7LpJQlNufyJ88PESA4Zep/TqwjBo9J7mpCRF2ITBW4bn0k2hlEpLiqx56X5hWPMOZlmV69Oc29NbiAAAAFA/nPQB9EjBzgEAAAAAAAAAAAAAAADx6L4T5FoUQOXsHAAAAAAAa8KoUd9tzORPa8zkunzoRMqHdYa1hSN+fUF4Y+G7UR+kXH7t7f6eEbdF2yFOAwG+pRdKb4S+G41fa7O6+38/ALX38utveYaocQM33z0s+3K5xQh14PHnFob2YkdiG134hbmbwFIjJ4TTLr0r0Wun1l12/aNh/mvvGzL0Ok8++1Lot8kuZqUkRdi4wVuFeel+oZRKS4qsy9dvMceqXEMm99qwYQf+b15CBAAAgPrglA+gRwp2DgAAAAAAAAAAAAAAAIhH950g16IAKmfnAAAAAABYgxpbWjduyORe97ET6X/Vp6Ut7HHoSeGPDz8eulavjuoQ5cGOuaHv8PH+jhF3we9vcBoI8C2s6uoKY3b/+Vqb05u2HuRHBkiQ1r2O9RxR426440ELEerA0y+9E9qLHYlt4pHnmbkJbeTYQ8JF0x5J9PpJQn+a/fJXz6urDRt6lUceezakRk4wKyUpwnYYsnV4OtUvlFJpSZG145BtzLEq15DNHeztQwAAAKgPTvgAeqRg5wAAAAAAAAAAAAAAAIB4dN8Jci0KoHJ2DgAAAACANez7I8Z8ryGbn+pjJ9Jf17LdPuHcy6eHjz75LPEHKA89+lRIjyz4u0Vcn5a2sPCdD5wGAnwLF06+ca3O6rMvmeZHBkiQabf80bNEjRu3z/EWItSB5195L7QXOxLbiefeZOYmuD1+9rtEr5+kdMN9z4QlS5cbOPQq9z44O6w7bJxZKUkRttXQ7cKT6QGhlEpLiqh7+g0K62Zy5lgVa8jk3vvhsLH/p7cPAQAAIH5O9wB6pGDnAAAAAAAAAAAAAAAAgHh03wlyLQqgcnYOAAAAAIC1pDGTKzRkc5/66In016VGTgg/PfG8MHdeKZGHJw/MfOLr/xv9reJu5/1PcBII8C28tuCdkB5ZWKuzuvTqQj80QIIsXbY8DNhsV88TNe7l19+yGCFypQUfhvZiR2K7aOrMkB5RMHMT2jrDxoUTz70x0WsoKU2+5bHw1vufGjr0Kn+48T6zUpIibfSQ7cPj6f6hlEpLiqgDB21hhlW5hubcMd46BAAAgPg52QPokYKdAwAAAAAAAAAAAAAAAOLRfSfItSiAytk5AAAAAADWoh8059drzOZn+eiJ9LfbfvejwpQb7g2LP1tS80OT1avL4fwrbwjrDhvnb1MHFW/7k5NAgG+xJ47b5/i1OqdHjTvMDw2QQEdNutDzRI079fxrLESI3Otvfxzaix2JbrO2n5m5Ca55m33CBdc+lPh1lIQumT4rPP7cwlAumz30Ht3nGGalJMXZpkO3D482rR9KqbSkSJqTHhAGZFrNsCrWkM0vXnfITv+3tw4BAAAgbk71AHqkYOcAAAAAAAAAAAAAAACAeHTfCXItCqBydg4AAAAAgLVt1KjvNmbypzVmcl0+fiL97dYbsXPY96gzwj3/OTus6Oys+oHJhx8tDnscepK/RZ3UtHEhLFm6zEkgwDd09fS71/qsPvfy6X5ogAR6/JkXPVPUuOat9worV66yGCFib73/aWgvdiS63Q4/28xNeOMPPDXx6yhJ3T1zfljRaf+k9/j12b83KyUp0jZuHhM60uuHUiotKZJ+vcHG5lfVy53ihUMAAACImxM9gB4p2DkAAAAAAAAAAAAAAAAgHt13glyLAqicnQMAAAAAoEoaW1o3bsjkX/XhE+kf12+TXcLeR5wWbr77obDki2Vr9aDky+UrwiXX3BIGbr67376OOuyXv3MKCPANvfP+orD+Zrut9Vn98utv+bEBEmr0+MM8V9S4+2bMsRAhYu9/tCS0FzsS3bFnFc3bhNenpS0cd/b0xK+lJDXt7rlh8efLDCF6hXK5HH5x0sXmpSRF2vChO4SZTQNDKZWWFEHz0v1CtnlH86uq5b7498GtP/C2IQAAAMTLiR5AjxTsHAAAAAAAAAAAAAAAABCP7jtBrkUBVM7OAQAAAABQRd8fMeZ7DZnctT5+IlVWauSEsPshk0L71TeHZ55/JXStXr1GDkgWvvNB+N1lxZDddm+/cx32YMdcp4AA39DeR5y21uf0Nrsc4YcGSLBLptzquaLG/eRnp1qIELGPP10a2osdie6Cax8K62403sxNeEO23juc/4cZiV9PSeqKG2eH1976yCCiV1i1quvrf280LyUpzrLNO4YZTQNDKZWWFEGXDmgxu6pcQyZ/njcNAQAAIF5O8wB6pGDnAAAAAAAAAAAAAAAAgHh03wlyLQqgcnYOAAAAAIAaaMzkJjRkc5/4CIrUswZusXvY7eDfhNMumBJuu++RUHp1Yfhy+Yp/eiCyZOmy8PDsZ8K5l08P4/c7IfRpafN71mnNW+8VVnV1OQUE+AZuumtGVWb1RZNv8mMDJNiijz8NfTca7/mihvUdPj58sOgTixEi9fkXy0N7sSPxjRx7qJkbQW37nxLFekpas59dEMpl84j6t3xFZ8jvfZx5KUmRlm3eMcxoGhhKqbSkhPfSV20/dFuzq4o1ZPLLG4bn1/GWIQAAAMTJSR5AjxTsHAAAAAAAAAAAAAAAABCP7jtBrkUBVM7OAQAAAABQI90f/mjI5mf4EIr07dvgR3uELSccHiYccGLY7eDffF3hwF+FLXf+6df/M79R7+nkc692AgjwDXzy6edh6FYTqzKr31j4rh8cIOH2PeoMzxc17pJrbrEQIVJfLl8Z2osdiW/CwWZ9DPVpaQvHnT09ijWVtO6eOT90ruwylKh7iz9bEn407lAzU5IibXDzTuH+fhuEUiotKeHd1n9w6GNuVbWGbO733jAEAACAODnFA+iRgp0DAAAAAAAAAAAAAAAA4tF9J8i1KIDK2TkAAAAAAGrrXxozuSMasvkVPoYiSd++F0pvOAEE+AYOPvbsqszpMbv/3I8NEIEHZj7h+aLGbdF2SCiXyxYjRGhF56rQXuxIfEed9gfzNpIGjd4rnDdlRhTrKmlNvWtu+OSzZQYTdW/hOx+EzDY/MTMlKdIGZ3YK9zdtGEqptKSEt+egUeZWNcvkun44bOxArxcCAABAfJzgAfRIwc4BAAAAAAAAAAAAAAAA8ei+E+RaFEDl7BwAAAAAAAnQZ+i4wQ2Z/DwfRJGkb96WEw53+gfwDfzpkSerNqsvmXKrHxwgAqu6ukLLdvt4zqhxTzzzosUIEVq5qiu0FzsS37lT/jOs09Jm3kZSfv+To1hXSeyKm2aH19/+2HCi7s2b/2oYsNmuZqYkRdrgzE7hvn4bhlIqLSnBPdQ0MKQyOXOrmmVy13uzEAAAAOLj9A6gRwp2DgAAAAAAAAAAAAAAAIhH950g16IAKmfnAAAAAABIiD4bF/6tMZNvb8zmyz6KIkk979Iptzr9A+ihJUuXheFj9q3arH7z7ff96ACROOOiaz1n1LijT77YQoQIdXWtDu3FjihqGXOAeRtJfVrawrG/nR7N2kpis59dEMplM4r69qdHngx9h483NyUp0tbPjA139hsUSqm0pAT3iw02NbOqW7kxM67Zm4UAAAAQFyd3AD1SsHMAAAAAAAAAAAAAAABAPLrvBLkWBVA5OwcAAAAAQMI0ZvI7NmbzH/goiiRV3rrDxoUPFn3i9A+gh4459ZKqzeqxE4/xgwNE5I2F74Y+LW2eN2r5Me3NdgvLvlxuMUJkyuVyaC92RFF+/5PN24gatOVPwvl/mBHN+kpidz08P3SuXGVQUdem3vJHM1OSYv5vAZmx4Y5+g0IplZaU0J5O9QuDm3cys6pa7jZvFAIAAEBcnNoB9EjBzgEAAAAAAAAAAAAAAADx6L4T5FoUQOXsHAAAAAAACfQfmcL/05jJ3+GjKJJUWXscepKTP4Aemv3k86FPS1vVZvUV193uRweIzPh9f+l5o8bdcMeDFiJE6JLpHaG9mPx+Oukqszayxh1wShRrK8lNvWtuWPz5MoOKunb2JdPMTEmKuPUzY8Nt/QeHUiotKaGdvf5G5lV1K/fJjN3IG4UAAAAQDyd2AD1SsHMAAAAAAAAAAAAAAABAPLrvBLkWBVA5OwcAAAAAQII1ZnJ7NWbzS30cRZL+cbfe87CTP4Ae+HL5irBZ7uCqzek+LW3h7fcW+eEBInPjnQ963qhx4/c7wUKECF12/azQXuxIfGdPfuDrf1c3b+Op++/1y9/dEMX6SnJX3DQ7vP72x4YVdatcLoefT7rI3JSkiBuQGRtu7T84lFJpSQlsfropbNa8vXlVzTK5u7xJCAAAAPFwYgfQIwU7BwAAAAAAAAAAAAAAAMSj+06Qa1EAlbNzAAAAAAAkXMOQ3PqNmdxcH0iRpL/d+pvtFpZ9udzJH0APnHLe1VWd1W37HO9HB4jQl8tXhIGb7+65o4b1aWkLbyx812KEyFx+w6OhvdgRRUO33se8jazMtvuFi6bOjGaNJbnZzy4I5bKZRX1ataor7HHoJHNTkiKuKdMabug/JJRSaUkJbEr/ZrOq2g3LjfQmIQAAAMTBaR1AjxTsHAAAAAAAAAAAAAAAABCP7jtBrkUBVM7OAQAAAAAQg1GjvtuYzZ/UmMl1+UiKJP11R0260KkfQA88+8IrYd1h46o6q68q3uWHB4jUsade4rmjxp3Vfp2FCJG58qY5ob3YEUU7TDzBrI2w3Q8/O5o1lvTunjk/dK5cZXBRl75Y+mXYfvejzE1JirimTGuY3n9IKKXSkhJY65Ctzaoq1pDJ3+clQgAAAIiDkzqAHinYOQAAAAAAAAAAAAAAACAe3XeCXIsCqJydAwAAAAAgIg3Ztk0aMrnXfChFkv6/Zj0xz6kfQIVWdXVV/WPK6wxrC+9/+LEfHyBSzzz/iueOGjds+31D1+rVFiNEZPItj4X2YkcU7XfsxWZthK270fhw0sW3R7POkl7xnqfC518sN7yoSx9+tDiM3HF/s1OSIi6daQ3T+g8NpVRaUsK6u9+gsE42Z1ZVsR+25LfwBiEAAAAkn1M6gB4p2DkAAAAAAAAAAAAAAAAgHt13glyLAqicnQMAAAAAIDLfHzHmew2Z3BU+lCJJPi4P0FPnX3lD1Wf1zvuf4IcHiNy2ux7h+aPGzZj1lIUIEbn61sdDe7Ejin59/i3mbKRttOMh4eJpj0Sz1pLe5JvnhLc/+NQAoy698sbbYdDoPc1OSYq4dKY1FPsPDaVUWlLCmjh4lDlV3f7k7UEAAABIPid0AD1SsHMAAAAAAAAAAAAAAABAPLrvBLkWBVA5OwcAAAAAQKQaM7lCQzb3iY+lSOrNnXnxdU78ACr06oK3Q3pkoeqz+rqb7/fjA0Tuyql3eP6ocQcde7aFCBGZcvsTob3YEUUXTZ0Z1hsxwayNtH2OuTiatRZDl06fFZ6a/7YhRl167On5NfnvQpKkNVc60xqK/YeGUiotKUE93DQwrJfNmVNVrE+mbZQ3BwEAACDZnM4B9EjBzgEAAAAAAAAAAAAAAADx6L4T5FoUQOXsHAAAAAAAEfuP7Pi+DZn8TB9MkdRbe/n1t5z4AVRg9epyaNvn+KrP6b4bjQ+LP1viDwAQuU8+/TysN2JnzyA1rPv37/47AHG49s4nQ3uxI5o2HnuoWRtp6ZG7hDOuuDeq9RZDDz3xauj66jka6s2dD8wK6wxrMz8lKeZ//8u0hun9h4RSKi0pQR254WZmVBVryOYe9tYgAAAAJJuTOYAeKdg5AAAAAAAAAAAAAAAAIB7dd4JciwKonJ0DAAAAACB2hcL/aMzkjm/I5Fb6cIqk3tSY3X/utA+gQr+fdmdNZvXeR5zmxweoEwcde7bnkBo3+av9HIjD1LvmhvZiRzSNP/BUczbiRu18VFTrLZZu+dO88OXylQYadefKqXeYnZIUeelMa5jef0gopdKSEtLcdP8wMLOTGVXFGrL5rb00CAAAAMnlVA6gRwp2DgAAAAAAAAAAAAAAAIhH950g16IAKmfnAAAAAACoE32G5Yc0ZHLP+XCKpN5S98c/Afjn3n5vURiw2a41mdW33feIPwBAnfjTI096DqlxWxd+ZiFCJIr3PBXaix3RdNikyeZs5B1+0tVRrblYmnL7E2HR4i8MNerOSb+7yuyUpMhLZ1rD9P5DQimVlpSQTtpgpPlU1XKPelsQAAAAksuJHECPFOwcAAAAAAAAAAAAAAAAEI/uO0GuRQFUzs4BAAAAAFBH+mxc+LeGbP7Cxmy+7OMpkuq5dYeNC4s+Xuy0D6ACexx6Uk1mdf9Ndw1Lly33BwCoE6u6ukJmm709j9S4eS++ZjFCBK6/9+nQXuyIptMvv8eMjbz1N98jnHvNg1Gtu1i64qbZ4Y23PzbYqCvlcjn89MTzzE9Jirx0pjVM7z8klFJpSQnouXRTaGnewXyqYn1a8tt7WxAAAACSyYkcQI8U7BwAAAAAAAAAAAAAAAAQj+47Qa5FAVTOzgEAAAAAUIcaWtrGNmZzH/qAiqR6bY9DT3LSB1CB6+/4z5rN6sNPPM8fAKDOnHzu1Z5HatyJZ15hIUIEpt/7dGgvdkTVgM12N2cjr23/U6JbdzE1+9kFhht1ZUVnZxi/7y/NT0mKvHSmNVzff0gopdKSEtDF6w8zm6pYQyb/mLcEAQAAIJmcxgH0SMHOAQAAAAAAAAAAAAAAAPHovhPkWhRA5ewcAAAAAAB16t8Ht/6gIZu/20dUJNVjt9zzkJM+gH9i0ceLw6DRe9ZsVj/YMdcfAaDOzH95geeRGrfhqD3Dis5OixESrnjPU6G92BFVW+x8pDkbeeu0tIVfn39LdGsvpu6f9VJY1bXakKNufPrZF2HUuMPMUEmKvHSmNVzff0gopdKSatyLqaaw5dDtzKZq1pzbyVuCAAAAkDxO4gB6pGDnAAAAAAAAAAAAAAAAgHh03wlyLQqgcnYOAAAAAIA615jJ7dWYzS/1IRVJ9VL/TXcNS5ctd9IH8E8ccPRZNZvVQ7acGFat6vJHAKhD2+56hOeSGnf7/Y9YiJBwU++eG9qLHVFVOORMM7YOGrbDQeGiaY9Et/5i6vr7ng5Llq4w6KgbC9/5IDRvvZcZKkmRl860huv7DwmlVFpSjev+Z9FcqmKZ/FPf+c53/sUbggAAAJAsTuEAeqRg5wAAAAAAAAAAAAAAAIB4dN8Jci0KoHJ2DgAAAACAXuA/sm0bNGbzT/uYiqR66PATz3PKB/BPPDDziZrO6hPOvNwfAaBOXTn1Ds8lNW73QyZZiJBwU++aG9qLHVF1+MlXmbF10j7HXBzd+outq255LLz74WeGHXXjsafnh9TICWaoJEVeOtMabug/JJRSaUk1Lj94K3OpijVkczlvBwIAAECyOIED6JGCnQMAAAAAAAAAAAAAAADi0X0nyLUogMrZOQAAAAAAeotRo77bmM2f1JjJdfmgiqSYe3j20075AP6BJV8sC8O237ems/rxZ170hwCoUx998lnou9F4zyY1bJ1hbeHt9xZZjJBg1975ZGgvdkTV6ZffY8bWSemRu4SzrrwvujUYW5dd/2h48fUPDDzqxk13zTBDJakO6pdtDTf1HxJKqbSkGnZ3v0FhnWzOXKpWmfxT3/nOd/7Fy4EAAACQHE7fAHqkYOcAAAAAAAAAAAAAAACAeHTfCXItCqBydg4AAAAAgF6mIdu2SUMm97qPqkiKseat9wqrurqc8gH8A7846eKazuoRO+wfyuWyPwRAHdvrZ6d6Pqlx511xvYUICfaHO54M7cWO6Oq/6W5mbJ203R7HRbkGY+zRp98IHoGpF2defJ0ZKkl1UFOmNdzQf0gopdKSatjEwaPMpGqWadvBW4EAAACQHE7eAHqkYOcAAAAAAAAAAAAAAACAeHTfCXItCqBydg4AAAAAgF6ob3P+fzZm8tN9VEVSbE06Z7ITPoB/4NEnngt9WtpqOqvPuOhafwiAOnfXA7M8n9S4TcYeGMrlssUICTXl9idCe7EjujYfd4QZW0f94ozrolyHMXbnQy+EzpVdhh/RW726HA44+iwzVJLqoP6Z1nBzv8GhlEpLqlEzmgaGdbM5M6lKNWTyc7wRCAAAAMnh5A2gRwp2DgAAAAAAAAAAAAAAAIhH950g16IAKmfnAAAAAADoxRozuUJDNr/Yx1UkxdK8F19zwgfwd3y5fEXYtPWgms/qF19Z4I8BUOdWrlwVBo/+sWeUGvfoE89ZjJBQ19z2eGgvdkTXzgedbr7WUYO33DtceO3DUa7FGJt+79NhydIVBiDRW76iM4ydeIw5Kkl10IBMa7it/+BQSqUl1ahDB21uHlWxH2Zat/U2IAAAACSDUzeAHinYOQAAAAAAAAAAAAAAACAe3XeCXIsCqJydAwAAAACgl/tBc369xkyuw8dVJCW90eMPc7oH8A9MOmeyWQ1A1Rx/+mWeU2rc4SeeZyFCQl196+OhvdgRXYdNmmy+1lk/PvLcKNdirHX/s//Bx0sMQaL3waJPwvAx+5qjklQHDciMDXf0GxRKqbSkGjQnPSD0z7SaR9Uqk+vwJiAAAAAkgxM3gB4p2DkAAAAAAAAAAAAAAAAgHt13glyLAqicnQMAAAAAgK9M+tfGTO6Ihmyu00dWJCW1iybf5HQP4O945vlXwrrDxpnVAFTN3Hklzyk1rmnjQvh8yVKLERLoqlseC+3Fjug6pf1O87XOSo2cEM684t4o12OsXXb9o+HlBYsMQqL3QumNMGCzXc1SSaqD1s+MDXf13zCUUmlJNejYDTYxi6pZc25L7wECAABA7TltA+iRgp0DAAAAAAAAAAAAAAAA4tF9J8i1KIDK2TkAAAAAAPgv62Rzwxuz+ZKPrEhKWn1a2sLCdz5wugfwN6xcuSpsVTjcrAag6kaNO8zzSo277ub7LURIoMm3zAntxY7ounjaI2G9ERPM1zpr2z2Pj3I9xt7sZxcYhkTvwY65Yd1h48xSSaqDBmV2Cn9s2iCUUmlJVe6pdP+wQfNYs6hKNWTzM7wBCAAAALXnpA2gRwp2DgAAAAAAAAAAAAAAAIhH950g16IAKmfnAAAAAADgr/TZuPBvDdn8hY3ZfNnHViQlpfH7neBkD+DvOPfy6YmY1fm9j/PHAOhlLpx8o+eVGjd24jEWIiTQ72+eE9qLHVE2fIeDzdc67NizitGuyZi7f9ZLYVXXakORqF065VZzVJLqpMGZncL9/TYIpVRaUpU7eeAIc6iK/bAlv4U3AAEAAKC2nLIB9EjBzgEAAAAAAAAAAAAAAADx6L4T5FoUQOXsHAAAAAAA/E0N2VyuMZv70MdWJCWhqbf80ckewN/wyhtvh9TICYmY1Vdff7c/CEAv8877i8I6w9o8s9S4l19baDFCwlx50+zQXuyIsh33+pXZWodlt9s/XDR1ZrTrMuZueuDZsGz5SoORqB198sVmqSTVSc3NO4UZTQNDKZWWVMWeSzeFbPOO5lD1esCbfwAAAFBbTtgAeqRg5wAAAAAAAAAAAAAAAIB4dN8Jci0KoHJ2DgAAAAAA/q4fDB33743Z/O0+tiKplq03Yufw6WdfONkD+G9Wry6H/N7HJWJW9x0+Piz6+FN/FIBeaJcDf+25pcadct7VFiIkzBU3zg7txY4o2/sXF5itddo+R18Umx4uhQAAIABJREFU7bqMvSm3PxEWLfbfN4nXqlVdYdeD/Hu/JNVL2eYdw0NNA0MplZZUxc5df7gZVMV+2Ny6mTf/AAAAoHacsAH0SMHOAQAAAAAAAAAAAAAAAPHovhPkWhRA5ewcAAAAAAD8U42Z3F6NmfwSH12RVIsOOPosp3oAf8Pl196emFm952En+4MA9FI33vmg55Ya17z1XmHVqi6LERLksusfDe3Fjig75qxpZmudlh65S/jt7++Pdm3G3hU3zQ5vvrvYgCRan372Rdii7RDzVJLqpGzzjuHhpoGhlEpLqlLz001h06Hbm0FVqiGbu8cbfwAAAFA7TtcAeqRg5wAAAAAAAAAAAAAAAIB4dN8Jci0KoHJ2DgAAAAAAKvKD5vx6DZn8TB9ekVTt7psxx6kewH/z1rsfhgGb7ZqYWX3z3Q/5owD0Usu+XJ6oPan3Pjc9ZjFCQpTL5dBe7Ii2c65+wFyt43bc61dRr8/Yu2T6rPDU/LcNSqK18J0PwpAtJ5qnklQnbdS8Q3i0af1QSqUlVakrB2TNnyrWJzN2I2/8AQAAQG04WQPokYKdAwAAAAAAAAAAAAAAAOLRfSfItSiAytk5AAAAAACoXKHwPxozrb9syOY6fXxFUjUaNHrP0Nm50qkewF8ol8th90MmJWZWp0cWwpKly/xhAHqxI39zoeeXGrf3EadZiJAQK1d2hfZiR9Stv8WeZmu9flC8pS2ceO6N0a/R2Jvx+Kth9eqygUmUHn3iudB3o/FmqiTVSSObx4Q5TQNCKZWWVIVe+qpthmxr/lSrTP4OL/sBAABAbThVA+iRgp0DAAAAAAAAAAAAAAAA4tF9J8i1KIDK2TkAAAAAAOixhuZ8piGbf8EHWCSt7Y477VInegD/TfHWBxI1qw857hx/FIBebtYT8zy/1Li+w8eHDz9abDFCAixbvjK0FzuibvNxR5itddzIsYeGi6c9Ev06jb07ZjwfVnSuMjTx36YkSTVv86Hbh8fT/UMplZZUhab1H2r2VK9y9ztu3vQDAACA6nOiBtAjBTsHAAAAAAAAAAAAAAAAxKP7TpBrUQCVs3MAAAAAAPCN9B016v9oyOTOaszmVvsIi6S11ePPvOhED+AvfPjR4rDhqD0TNavvf+gxfxiAXq5cLodNxh7oGabGXTLlVosREuDzL5aH9mJH1I074BRztc47bNLk6NdpPXTdXU+GT5d8aXASpVPPv8Y8laQ66kdDtwtPpgeEUiotqQrtOGQbs6dKNWRyN3vLDwAAAKrPaRpAjxTsHAAAAAAAAAAAAAAAABCP7jtBrkUBVM7OAQAAAADAt9LYnNuyMZNf6EMsktZ0G+90QCiXy070AP7Cfj8/M1GzesNRe4bOzpX+MACE37ZP9RxT40aNO8xChAT45LNlob3YEXX7H3eJuVrnDRo9MVxw3UPRr9V6aPItc8J7iz43PInO6tXlsM+Rp5upklRHbT102/BUul8opdKS1nI39R9i7lSvcp+h4wZ7ww8AAACqy2kaQI8U7BwAAAAAAAAAAAAAAAAQj+47Qa5FAVTOzgEAAAAAwLeWHlb4vxoyuWt9iEXSmuy37VOd5gH8hbsemJW4WX3MqZf4wwDwtdfffNdzTAJ68tmXLEaosQ8//iK0Fzui7rhzrjdTe0F7/uyc6NdqvXTZDY+GV95cZIASnaXLloftdjvSTJWkOmrbIduGZ1L9QimVlrSWyw/eytypUg3Z/FRv9wEAAEB1OUkD6JGCnQMAAAAAAAAAAAAAAADi0X0nyLUogMrZOQAAAAAAWGMas/mdGzP5j3yQRdKa6OXXFjrNA/izTz/7ImS2+UniZvWjTzznjwPAf2nd61jPMjXu6FPaLUSosXc//Cy0Fzui7pyrHzBTe0GpkRPCWb+/P/r1Wk89/pz/Hkp83nl/UWjeei9zVZLqqNyQrcNz6aZQSqUlrcXu7Dco9DFzqlMm19Un29rPm30AAABQPU7RAHqkYOcAAAAAAAAAAAAAAACAeHTfCXItCqBydg4AAAAAANaofx/c+oPGTO5OH2WR9G3a8cdHO8kD+AtH/ubCxM3qlu32CV2rV/vjAPBfrr3pPs8zNW7AZruGpcuWW4xQQ2++tzi0Fzuib8Bmu5urveG/we31q7pYr/XUjMdfDavLZcOUqDzxzIthvRE7m6uSVEcVBm8Z5qeaQimVlrQW2/Wrf9bMnGqVu9RbfQAAAFA9TtAAeqRg5wAAAAAAAAAAAAAAAIB4dN8Jci0KoHJ2DgAAAAAA1orGTG6vxmzuCx9lkfRNmjztTid5AH8264l5oU9LW+Jm9WkXTPHHAeCvLPliWWjauOCZpsbdeOeDFiPU0GtvfRTaix3Rt0nuMDO1F9T9rHni+TfXxZqtp+6Y8XzoXNlloBKVa264x1yVpDprt8Gjw/x0Uyil0pLWUvc3bRjWyebMnCrUkM2v+Oq3bvBGHwAAAFSH0zOAHinYOQAAAAAAAAAAAAAAACAe3XeCXIsCqJydAwAAAACAteYHQ1tTjZlch4+zSOpJfYePD4s+XuwkD+Ary75cHjYZe2Ai5/WLryzwBwLg/+egY8/2XFPjdt7/BAsRaqi04MPQXuyIvrH7TDJTe0mb5H9aF2u23pp+79Phi2UrDFWicsypl5irklRn7TvoR+GlVDqUJK21Jg4abd5Uq0zut97mAwAAgOpwcgbQIwU7BwAAAAAAAAAAAAAAAMSj+06Qa1EAlbNzAAAAAACwdo0a9d2GTO43X7XSB1okVdKeh538/7J3J15Sl3ei/zN3Mnd+59w55977O7+ZxO4WU8Uqa1W3iqIG96iB6kYtUdQY1JCoQY1bjEs0ahL3GGxcolGMWi7jvkWJS6AQjEhc0ULNIO5xQQFZGrr7+dmOZyaLYFXT1V3f7/f1Ouf9F9RTn4fq5/vwdYoH8JlTz/1VTc7q3fY7xocDwOd6aPZ8v2v6uIbGlrD4tbcsRugjz7/8dmgtFCPf5OOnmakJ6qifXB2LdRu3rrnjD+HdpSsMViKjrW1tGP+tE81VSYpZRw7dLpRSaUlV6uH+Q0I/s6Z3yjQv7zfim//Xw3wAAABQfU7OACqSt3MAAAAAAAAAAAAAAABAdHTdCXItCqB8dg4AAAAAAHpFQ2bclvWZ5he9pEXSF3XbfY86xQP4xB+fWxT6NU2oyVl9xXV3+oAA+Fzr2ttDZpeD/bbp485pvc5ihD7ydOmN0FooRr7jfnadeZqghu/07TDt+lmxWLtx64pb5obFb3xguBIZ77z7QWjcbbLZKkkx64ebjwmlVFpSlTpk2NfNml6qLtN8mqf4AAAAoPqcmgFUJG/nAAAAAAAAAAAAAAAAgOjouhPkWhRA+ewcAAAAAAD0ms3Gjv1/6jK5c+qzuQ4vapH0eQ3YZt/w8crVTvGAxGtrWxt23GdqTc7qfk0TwrvvL/UhAbBeZ1zwa79v+rimbxwS2js6LEboA/Offy20FoqR7+zL7jNPE9bkEy6JxdqNY9NvnBOefektA5bIWPBsKaRG72O2SlLMOn3I6FBKpSVVoVn9h4TNsjmzpjfK5N7/16H5f/EUHwAAAFSXEzOAiuTtHAAAAAAAAAAAAAAAABAdXXeCXIsCKJ+dAwAAAACAXrfJqJbd6rLNb3hZi6S/7cgfXeAED+AT502/oWZn9YHf/4kPCIANer70H37f1ECPzFlgMUIfmPfMq6G1UIx8026YHfptuZd5mqAGbTcpXDjj4Vis37g296nFobPTnCUabrzzd2arJMWws4aMDqVUWlIVOnzYduZMb9XYfIyn9wAAAKC6nJYBVCRv5wAAAAAAAAAAAAAAAIDo6LoT5FoUQPnsHAAAAAAA9Il0U/5/12Vyv/GyFkl/2UOz5zvBAxLvhZcWh81q+OX1d/x2tg8JgC+04z5T/cbp44446QILEfrArPmvhNZCMRaN3PkQ8zRhTTzynNis37h2f/GFsK69w7AlEk4951dmqyTFrIZPunDwFqGUSkvq4eb2HxzSmfFmTS9Ul829PnRo/n96eg8AAACqx0kZQEXydg4AAAAAAAAAAAAAAACIjq47Qa5FAZTPzgEAAAAAQJ+qz+TyddncB17aImnYDgeEtWvXOcEDEq29oyPsccBxNTurh2y3f1i1eo0PCoAvdPGVN/ud08elR+fDsuUfW4zQy2Y+VgqthWIsGrv3D8zThPW1rfYJ51z5QGzWcFy7debTYfWatQYuNW9de3vITznVfJWkmNUvkwuXD24MpVRaUg939NBtzZleapNM86Ge2gMAAIDqcVIGUJG8nQMAAAAAAAAAAAAAAACio+tOkGtRAOWzcwAAAAAA0Oc223LPr9Zlc/d5aYuU7E7++eVO74DEu3TG7TU9q4874xIfEgBlWfLGO6GhscVvnT7uhtsetBihl9396POhtVCMRS2HnWmWJrBxk0+PzRqOc7+5e374cPkqQ5eat/Sj5WGbcVPMV0mKWf2yuXDNoEwopdKSerB56UEhnRlvzvRCdZncK1/K5//RU3sAAABQHU7JACqSt3MAAAAAAAAAAAAAAABAdHTdCXItCqB8dg4AAAAAAGrFP9Q3tkypzzZ/7OUtUjJ74qkXnN4BibbkjXfCwDETa3pWz53/nA8KgLKN/9aJfuv0cRMmn2QhQi/79wefDq2FYiyafMI0szSBbdrYEs645K7YrOM4d9Vt88Lb7y0zeKl5Cxctrvm/eUmSKi+VyYXCwJGhlEpL6sGOGbqtGdNbZXJeVAsAAABV4oQMoCL+VgkAAAAAAAAAAAAAAAAR0nUnyLUogPLZOQAAAAAAqClfzbZsXp/JPenlLVKyGr3nYaGzs9PpHZBYXTNwv+/9uOZndUeHWQ1A+X5duMfvnRroT6++aTFCL7r+nidDa6EYi4772XXmaELbad8TYrOO494Vt8wNr775geFLzbvvobmhobHFjJWkmJXOjA+3DhgeSqm0pB5qXnrQp98tM6b61WVzT3/pS1/6B0/rAQAAQM9zOgZQkbydAwAAAAAAAAAAAAAAAKKj606Qa1EA5bNzAAAAAABQe8aO/XJ9tvmHdZncWi9xkZLROa3XObkDEu26Wx+o+Vl9buv1PigAKvLeBx+FzbbYy2+ePu7Cy2+0GKEXXXXb46G1UIxFZ196jzma4E46/6bYrOW4N/3GOeH5l982gKl5Z188w3yVpBg2ODMu3DdgWCil0pJ6qGOGbmu+9FIN2fG7e1APAAAAep6TMYCK5O0cAAAAAAAAAAAAAAAAEB1dd4JciwIon50DAAAAAICaVZdt2aYu0/yyl7hI8W/RK0uc3AGJ9c67H4TNvz6p5mf1y4tf92EBULH9Dz/db54+bptxU0JnZ6fFCL3k0hvnhNZCMRZNu35W2LRpglma0LYed0Rs1nJSmvv0YkOYmtbe0REmHXGGGStJMWzkqD3Do/2HhFIqLakH+kN6YBiQHW++9EaZ3GxP6AEAAEDPczIGUJG8nQMAAAAAAAAAAAAAAACio+tOkGtRAOWzcwAAAAAAUNO+MnLX/1WXyV1en23u9DIXKZ7tOvFop3ZAok0+5qc1P6u/edDxPigAuuWmux7yu6cGmvfk8xYj9IK2te2htVCMVcN2+JY5muCOOfva2K3puPfQ4y+Fjo5OA5ma9dGyFWHb3PfMWEmKYVuO2iPM7T84lFJpST3QMUPHmC29VF2meYwn9AAAAKBnORUDqEjezgEAAAAAAAAAAAAAAADR0XUnyLUogPLZOQAAAAAAiISGxuZv1GWa3/QyFyl+XTrjdqd2QGLd+cDsSMzqa2/5rQ8LgG5Z/vHK0H/rvN8+fdzxP7nEYoRemXmrQ2uhGKvGNE81RxNcZtdDwyU3zI7duo57dz3yXFi7tt1Qpma9vPj1MGT7/c1ZSYph2476RpifHhRKqbSkjewP6YFhQHa82dIL1WWab/dkHgAAAPQsJ2IAFcnbOQAAAAAAAAAAAAAAACA6uu4EuRYFUD47BwAAAAAAkbFJ07j/ry6Tu9ULXaT4tGlTS3jznfec2gGJtPSj5SGzy8E1P6vTo/Pho2UrfGAAdNt3jj/H758+bsh2+4dVq9dYjFBl7y5dEVoLxVi1x0GnmKMJ78gfXxm7dZ2EbnngqbBy9VqDmZr120fmhYbGFnNWkmLYLiN2DU+lBoRSKi1pIztm6BhzpVfKddSNbBnkyTwAAADoOU7DACqSt3MAAAAAAAAAAAAAAABAdHTdCXItCqB8dg4AAAAAACKnPpPLf9L7XuoiRb99vnOKEzsgsaaeclEkZvXhPzzfhwXARrnvobl+/9RAd9w/y2KEKnv9nQ9Da6EYqyYeea4ZmvBG7PztMO36WbFb20noN3fPDx8uW2U4U7MuvPxGc1aSYtr4ETuH51L9QymVlrQR/SE9MAzIjjdXeqG6TO4KT+QBAABAz3ESBlCRvJ0DAAAAAAAAAAAAAAAAoqPrTpBrUQDls3MAAAAAABBJm2ZzdXXZ3H1e7CJFuxtue9CJHZBIj8xZEJlZ/ehjC3xgAGyUNW1tYcj2+/sN1MdNOuJ0ixGq7JXX3guthWKs+u7Jl5mhClM+WQdxW9tJ6apb54W33l1mQFOTOjo6w7ePPtuclaSYNnH4jmFhKh1KkjaqHwwdY6b0QnWZ5tX/Nnz8VzyRBwAAAD3DSRhARfJ2DgAAAAAAAAAAAAAAAIiOrjtBrkUBlM/OAQAAAABApNVncvm6bPNSL3iRotfXtto7LP1ouRM7IHGWf7wybLXHYZGY1U3fOCS0d3T40ADYaFNPucjvoD5u06aW8NY771uMUEULX3k7tBaKserEcwpmqMLQsQeFX/7m97Fb30np8psfC4vf+MCQpiYtW/5xGDP+u2atJMW0ycPGhhdT6VCS1O3+kB4YBmTHmym9Uab5LE/iAQAAQM9wCgZQkbydAwAAAAAAAAAAAAAAAKKj606Qa1EA5bNzAAAAAAAQeV/N7rVZXab5YS94kaLVocf+zGkdkEgn/fSyyMzqn19ynQ8MgB7x4O//4HdQDTR9xu0WI1TRgoWvh9ZCMVadfdm95qc+bfIJ02K3vpPU9BvnhOdeesugpia98NLiMGCbfc1aSYpp3x+6XSil0pI2oh8MHWOe9EJ12eal/zo0/y+exAMAAICN5wQMoCJ5OwcAAAAAAAAAAAAAAABER9edINeiAMpn5wAAAAAAIC7+ob6xZUp9NrfCi16kaHTv7x5zWgckzrwnnw8NjS2RmdUvL37dhwZAj2hrWxuGbLe/30J93I57f99ihCp67KnFobVQjFXTrp8VNm2aYIYqDN5uUvjFtY/Ebo0nrceffdWwpibddt+jZq0kxbjTh4wOpVRaUjeblx4U+mfGmye9USZ3lEfwAAAAYOM5/QKoSN7OAQAAAAAAAAAAAAAAANHRdSfItSiA8tk5AAAAAACIlfrMNwfWZ3JzvehFqu2GbLd/WL2mzWkdkChdc2+75sMjM6tbJp/kQwOgRx158oV+D9VAzyx82WKEKpk5txRaC8XYNXTsQeanPu3AYy6K5RpPWg/NWxQ6OjsNbWrOcWdcYtZKUkxr+KQLhmwRSqm0pG52zNAx5kmvlFv8pbFjv+wJPAAAANg4Tr4AKpK3cwAAAAAAAAAAAAAAAEB0dN0Jci0KoHx2DgAAAAAAYuj0/1GfyR1dl21e42UvUm32g9N/6aQOSJwzL7o6UrO6cPtMHxoAPeq3jzzu91ANdNp5V1qMUCV3PvxcaC0UY9focUeYn/q0AdvsFy6c8VAs13nSum/WwrCuvcPgpqasaWsLe0w61ryVpJi2aTYXLh/cGEqptKRuNLf/4JDK5MyTXmiTTMv+nr0DAACAjePkC6AieTsHAAAAAAAAAAAAAAAAREfXnSDXogDKZ+cAAAAAACC2GkZOGF6faV7ghS9S7TVr3lNO6oBEeeq5l0K/pgmRmdP9t86HZcs/9sEB0KNWr2kLg7fdz2+iPm7EjgeFtWvXWZBQBTfcuyC0Foqxa+f9TjQ/9V9NPPLcWK7zJHb7Q8+GNv8moMa8+vrbYfOvTzJvJSmm9cvmwvWDRoVSKi2pGx05dDuzpDfKNC/w1B0AAABsHKdeABXJ2zkAAAAAAAAAAAAAAAAgOrruBLkWBVA+OwcAAAAAAPE2duyX67PNP6zL5tq8+EWqjbK7fju0d3Q4qQMSY+3adWGn/NRIzeqjTv2FDw6AqjjyRxf4XVQDPfDo4xYjVMGVt84LrYVi7Go57EyzU/9Veut8uPCah2K51pNY4b4F4eNVbQY4NeV3s+eHhsYWM1eS4vrvycz4cPvA4aGUSkuqsNn9B4fNsjmzpBeqyzbv7KE7AAAA6D4nXgAVyds5AAAAAAAAAAAAAAAAIDq67gS5FgVQPjsHAAAAAACJsEljS1Ndtvl5L36R+r7Tz7/KKR2QKOdfekPkZvVjTzzrgwOgKu5/eK7fRTXQd44/x2KEHtbe3hFaC8VYduAxF5md+qv2m3pebNd7Erv2rvnhw+WrDHJqys+m/ca8laQYNzQzLvyu/+ahlEpLqrDvDNveHOmF6jK5BzxtBwAAAN3ntAugInk7BwAAAAAAAAAAAAAAAERH150g16IAymfnAAAAAAAgMQYM2P2f67LNP6/PNK/zAhip73pm4ctO6YDEeOGlxeFrW+0dqTk9es/DQkdHpw8PgKpYvaYtDNp2ot9GfVx6dD4sW/6xBQk9aNmK1aG1UIxlR5z6K7NTf1X/MRPDhTMeiu2aT2JX3/54eHfpCsOcmtHe0RHyU041cyUpxmVH7Rlm9x8cSqm0pAp6dMCQ0M8M6Y066zMTRnnaDgAAALrHaRdARfJ2DgAAAAAAAAAAAAAAAIiOrjtBrkUBlM/OAQAAAABA4myazW1Rl8095wUwUu+3fcvhTuiAxFjX3h72OOC4yM3qCy+/0YcHQFV978Tz/D6qgW6883cWI/Sgt99bFloLxVh24jkFc1N/16Sjzo/tmk9qV9wyN7z29ocGOjXj3fc/DI27TTZzJSnGbTvqG+HJ9MBQSqUlVdC3h33dDOmF6jK56zxlBwAAAN3jpAugInk7BwAAAAAAAAAAAAAAAERH150g16IAymfnAAAAAAAgkZqapvxTfbb5h3XZXJsXwUi910VX3OSEDkiM6dfcFrk5vWlTS3j9rXd9eABU1e33/d7voxpo3ymnWYzQg1557b3QWijGsrOm321u6u/qP2ZiuHDGw7Fd90ntspvmhJeXvGeoUzMWPFsKX9tqb3NXkmLcLiN2Dc+kB4RSKi2pzGYO2Dxsms2ZIVWuLpNbu0nTuH6esgMAAIDKOeUCqEjezgEAAAAAAAAAAAAAAADR0XUnyLUogPLZOQAAAAAASLRNmsY11mWan/EyGKl3+o8lbzqhAxLhT6++GfpvnY/cnD5o6pk+PACqbulHy0O/pgl+I/Vxmza1hLf//L4FCT3k2UVvhdZCMZb94tpHzE19bgccdX5s132Sm37jnPDcy28b7NSMK66708yVpJi3z/Adw8JUOpQkld0Bw8aaH71RpvlCT9cBAABA5ZxwAVQkb+cAAAAAAAAAAAAAAACA6Oi6E+RaFED57BwAAAAAACReU9OUf6rPNv+wLptr80IYqXqNO+gEp3NAInR0dIa9DvlRJGf1bx953AcIQK+I6l4Zt6647k6LEXrIvGdeDa2FYmxLb503N/V3Ddhmv3DhjIdjvfaT3NynFxvu1ITOzs7w3RPPM3clKeZ9e9jXw4updChJKqsH+28eNs3mzI9ql2lenm7K/29P1wEAAEBlnHABVCRv5wAAAAAAAAAAAAAAAIDo6LoT5FoUQPnsHAAAAAAA8Jm6Uc2Z+mzuKS+FkarTVTfc7XQOSISrb7o3knM6s8vBYd26dh8gAL1i+jW3+Z1UA+2+/7EWI/SQhx9/KbQWirFt5M6HmJv63A485sJYr/2k9/v5r4TOTjOevrf845Vh+5bDzV1Jinknbr5NKKXSksosP3xHs6M3amw+xlN1AAAAUBmnWwAVyds5AAAAAAAAAAAAAAAAIDq67gS5FgVQPjsHAAAAAAD8pbFjv1yfbf5hXbZ5jRfDSD3Xpk0t4Z13P3A6B8Te62+9GwZvu18kZ/XPpv3GBwhAr1n0yhK/lWqkrs8C2Hh3P/p8aC0UY9vW4480M/W5Ddhmv3DRjEdivf6T3v2zXwjt7R0GPX2u9PKSMHDMRLNXkmLe2UO2CqVUWlIZ3TNwaGgwN3qh3OIv5fP/6KE6AAAAKJ+TLYCK5O0cAAAAAAAAAAAAAAAAEB1dd4JciwIon50DAAAAAAA+R312/Mj6TPMCL4aReqaJ3z3NyRyQCJOOOCOSc7qhsSX8x5I3fYAA9Kptxk3xe6kGOm/6DRYj9ICb7v9jaC0UY9tOE483M7XeDjzmolivfxXDHQ8/G9rWthv29Lnb7nvU3JWkmNfwSdMGN4ZSKi2pjJqH72R29E57e5oOAAAAyudUC6AieTsHAAAAAAAAAAAAAAAAREfXnSDXogDKZ+cAAAAAAID1aGqa8k/12dyZXgwjbXyF22c6mQNi76a7HorsnN53ymk+QAB63ann/MrvpRpom3FTQmdnpwUJG+nXtz0eWgvF2DZ+8o/NTK23QdtNChf/5tFYfwdUDDc/8FRYtWatgU+fO+mnl5m9khTzNsvmwg0DR4ZSKi3pC/r3gSPMjd4okyt6kg4AAADK50QLoCJ5OwcAAAAAAAAAAAAAAABER9edINeiAMpn5wAAAAAAgA3YZFTLbl4OI21cX9tq7/DRshVO5oBYe/f9pWHo2AMiO6vvfGC2DxGAXve72fP9ZqqRnnymZEHCRli7rj20FoqxbuKR55iX2mCTT7gk9t8DFcMN9z4ZVqxcY/DTp9ra1oY9Dzze7JWkmDcgOz7cPWBYKKXSkr6g3UfsYm70Qg2ZcVt6kg4AAADK40QLoCJ5OwcAAAAAAAAAAAAAAADo2z25AAAgAElEQVRER9edINeiAMpn5wAAAAAAgA2oz+Yu8GIYaeM65Ac/cyoHxN5hx0X3BfPDdzgwrGlr8yEC0OuWfrQ8NDS2+N1UA516zq8sSNgIH3y0MrQWirFu8gnTzEttsGE7fCtMu35W7L8LKoZr73oifLh8leFPn3rznffCiB0PMn8lKeYNzYwLD/XfPJRSaUkbaMbAUWZGr5QreJIOAAAAyuM0C6AieTsHAAAAAAAAAAAAAAAAREfXnSDXogDKZ+cAAAAAAIANqMvmnvZSGGnjuvOB2U7lgFi768FipOf0GRf82ocIQJ/5+oQj/G6qgUbudFBY195uQUI3LX7jg9BaKMa6759+lXmpL+zwU6+I/XdB/9nVtz8e3vvwYxsAferh4pOhobHF/JWkmLflqD3CvPSgUEqlJW2gHUZ+w8yocnWZ3Nr6ERMaPE0HAAAAX8xJFkBF8nYOAAAAAAAAAAAAAAAAiI6uO0GuRQGUz84BAAAAAADr8ZWRE/6tPtvc6cUwUvcbOGZiWLlqtVM5ILaWfrQ8ZHY5ONKzetErS3yQAPSZH5z+S7+daqRH5iywIKGbnln0ZmgtFGPdiecUzEp9YaN2mRwuuWF27L8P+s+uvHVeePu9ZTYB+tSZF11t/kpSAtpx5G7h6fSAUEqlJa2nSwc1mhe9UF0md44n6gAAAOCLOcUCqEjezgEAAAAAAAAAAAAAAADR0XUnyLUogPLZOQAAAAAAYD0aMs2TvBBG2ri+f8pFTuSAWJv6yZyL8pxu/vYPfYgA9Knrb3vQb6caaarfb9Btc/74H6G1UIx1Z1xyp1mpsjr6zGti/33Qf3fFLXPDa29/aCOgz6xb1x5yB59o/kpSAtp7xE5hYSodSpI+t4Xp/mHLUXuYF1WuLtu89F+H5v/FU3UAAACwYU6xACqSt3MAAAAAAAAAAAAAAABAdHTdCXItCqB8dg4AAAAAAFiP+mzuGi+EkTaumbOecCIHxNbDxScjP6dvu+9RHyQAfaprL/LbqTYatO3EsGr1GosSuuH+2S+E1kIx1p131UyzUmW15Z6Hx/77oL/uspvmhFdee89mQJ9Z8sY7Ycj2+5vBkpSAvjNs+1BKpSWtp/MGb2lW9EJ1meYjPFUHAAAAG+YEC6AieTsHAAAAAAAAAAAAAAAAREfXnSDXogDKZ+cAAAAAAID1qM/kXvMyGKn7DR17QFi7dp0TOSCWln+8Mmy5+6GRntMjdjworGlr82EC0KdaJp/k91MNdf/Dcy1K6Iabf/tUaC0UY92062eFhsYWs1JldeI5hdh/J/TXTb9xTlj4yjs2BPrMPTPnmL+SlJBO3nzrUEqlJX1Oz6X6hxGj9jQrqlxdtvmlL33p9P/hyToAAABYP6dXABXJ2zkAAAAAAAAAAAAAAAAgOrruBLkWBVA+OwcAAAAAAHyOr2ZbNvciGGkjX5571nSncUBsnfDJjIv6nP7ZtN/4IAHoUwsXLfbbqcb6/ikXWZjQDVfeOi+0FoqxLzV6H7NSZbX9Xkcn4juhv++pF9+wKeDvdZKkqnfu4C1DKZWW9DmdPmS0OdEL1TW2jPN0HQAAAKyfkyuAiuTtHAAAAAAAAAAAAAAAABAdXXeCXIsCKJ+dAwAAAAAAPkd9JneUl8BIG9fc+c85jQNiqWu+NTS2RHpGb9rUEpa88Y4PE4A+dfyZrX471ViDt90vrGlrszihAm1r14XWQjERbf71A81Kld2pF/17Yr4b+uvmPr3Y5kCf6Pp37K4TjzaDJSkB9cvkwq8HjQqlVFrS37QgPSAMzowzK6pcXab5YU/XAQAAwPo5uQKoSN7OAQAAAAAAAAAAAAAAANHRdSfItSiA8tk5AAAAAADgc9Rncnd7CYzU/Rp3mxw6OjqdxgGxs2r1mrBt7nuRn9MHH3WWDxOAPvXRshVhwDb7+v1Ugz1cfNIChQq8u3RFaC0UE1Fm10PNSZXdzvudkJjvhv6+WfNfCZ3+PEwfWPTKEr8zJCkhpTPjw+0Dh4dSKi3pbzp+6BhzojfKTBjlCTsAAAD4fE6tACqSt3MAAAAAAAAAAAAAAABAdHTdCXItCqB8dg4AAAAAAPhbY8d+uT7TvMwLYKTu95MLr3YSB8TS6edfFYs5/XDxSR8mAH3q8t/c6bdTjXbcGZdYoFCBP73+fmgtFBPR1uOPNCdVdg2NLeGsS+9OzPdDf9/v5i4KHZ2dNgp63fW3PWgOS1JCGpoZFx7qv3kopdKS/qJ56UEhnRlvTlS/GR6yAwAAgM/nxAqgInk7BwAAAAAAAAAAAAAAAERH150g16IAymfnAAAAAACAv7FJY/P2XvwibVxPPfeSkzggdv743KLQr2lC5Gf06D0PC+0dHT5QAPpMR0dn2Db3Pb+darQROx4U1rW3W6hQpqdefCO0FoqJaIf8ceakKqr5kJ8k5vuhz+++WQtDe7u/QdD7Dv/h+eawJCWkLUbuEealB4VSKi3pLzpi2HZmRJWryzav2WzLPb/qSTsAAAD4e06rACqSt3MAAAAAAAAAAAAAAABAdHTdCXItCqB8dg4AAAAAAPgb9dncmV7+InW/MeO/Gzo7O53EAbHS1rY27LjP1FjM6ekzbveBAtCnHi4+6bdTjTfniWcsVCjT7Cf/FFoLxUS0+4Enm5GqqK9ttU84/+qZifmO6PO765Hnwtp17TYMetXHK1eH7VsON4slKSHtPHLX8HR6QCil0pI+69H+Q0I/86Hq1WVyP/akHQAAAPw9p1UAFcnbOQAAAAAAAAAAAAAAACA6uu4EuRYFUD47BwAAAAAA/I26TPM8L36Rut/5l97gFA6InXNbr4/FjE6N3ie898FHPlAA+tRBU8/026nGO/nnl1uoUKZ7Hn0+tBaKiaj5MPNblTfpqAsS8x3R+rt15jOhbe06mwa96pmFL4evbbW3WSxJCWnv4TuGhen+oZRKS/qsg4aPNR+qXF0m99bQofn/6Wk7AAAA+GtOqgAqkrdzAAAAAAAAAAAAAAAAQHR03QlyLQqgfHYOAAAAAAD4C5uNav4/9ZnmdV78InW/Ra8scQoHxMoLLy0Om225Vyxm9NGnXewDBaBPvfr622HTpha/nWq8zC7fDh0dnRYslOHau+aH1kIxEe33/XPNSFXcoO0mhYuvezQx3xOtv5t/+1RYvWatjYNeddm1d5jFkpSgpgzbPpRSaUmfdd+AYaHBbKh6ddncfp64AwAAgL/mlAqgInk7BwAAAAAAAAAAAAAAAERH150g16IAymfnAAAAAACAv7DJqOYWL3yRut+uE492AgfEyrr29rDHpGNjM6cXPFvyoQLQp8686Gq/nSLSE0+9YMHCF/5e6AjTbyyG1kIy+taxvzAf1a2mnHx5Yr4n2nA33LsgfLyqzQZCr+ns7AwHTT3TLJakBHXmkNGhlEpL+qzxI3Y2G6rfHE/cAQAAwF9zSgVQkbydAwAAAAAAAAAAAAAAAKKj606Qa1EA5bNzAAAAAADAX6jP5qZ72YvU/VqvvtUJHBArl/z632MzoxsaW8LBR50VLr7y5jBr3lNh+YqVPmAAetWq1WvCsB0O8NspIv304hkWLXyBd5euCK2FYmI67KTp5qO6VWbXQ8MlN8xO1PdF6+/6e58MK1ausYnQa95fuiw07jbZPJakhNTwSZcOagylVFrSJ103aKTZ0Att0jSu0VN3AAAA8N+cUAFUJG/nAAAAAAAAAAAAAAAAgOjouhPkWhRA+ewcAAAAAADwF+qzuUVe9iJ18wVljS3htTf/7AQOiI2XF78e0qPzsZ3bmza1hB33mRpOPedX4b6H5oYPPlzmQwegqgq3z/TbKULtMelYixa+wEuvvhtaC8XEdPipV5iP6nbH/vS6RH1ftOGuvWt++GjFahsJveaxJ54N/ZommMeSlJBSmVy4dcDwUEqlJX3S2JG7mQ3VLtN8tafuAAAA4L85nQKoSN7OAQAAAAAAAAAAAAAAANHRdSfItSiA8tk5AAAAAADgM/2aJmziRS9S92uZfJLTNyA2Ojo6P51rSZrjDY0tYdeJR4efXjwjzHvy+bCuvd1CAKBH7b7/sX47RahNm1rCBx8us3BhA/7w7JLQWigmpqN+co35qG63/V5HJ+r7oi9uxp1PhA+Xr7KZ0GvOv/QG81iSEtTmo8aFh/pvHkqptJT4pg1uNBeqXF22ec1XRk74N0/fAQAAwH9yMgVQkbydAwAAAAAAAAAAAAAAAKKj606Qa1EA5bNzAAAAAADAZxoyzZO86EXqflffdK/TNyA2fl24J/Fzfcj2+4cpJ5wbbr/v92H5ipUWBQAb5YmnXvC7KYLd//Bcixc24IE5L4bWQjExHf/z681GdbuGxpZw+rQ7EvWd0Rd39e2Ph/c//NiGQq9o7+gIex16spksSQlqi5F7hHnpQaGUSkuJbmGqf8iO2tNcqHaZ3EmevgMAAID/5GQKoCJ5OwcAAAAAAAAAAAAAAABER9edINeiAMpn5wAAAAAAgM/UZZt/5SUvUvfabIu9wrvvf+j0DYiFJW+8EwaOmWi+/0Wp0fuEg486K9xy98Nh+YqVFgkAFTvyRxfYUyPYhZffaPHCBtx4/x9Da6GYmH50wc1mozaqPQ46OVHfGZXXVbfOC39+f4VNhV7x1jvvh+E7HGgmS1KC2nnkruGZ9IBQSqWlRHfmkNFmQrXLNC/50tixX/YEHgAAAHz6n0ECUL68nQMAAAAAAAAAAAAAAACio+tOkGtRAOWzcwAAAAAAwGfqss0vecmL1L0mHXG6kzcgFjo7Oz+daWb7+kuN3iccfNRZ4Z6Zc8K6de0WDQBf6N33l4avbbW3fTSCTT3lIgsYNvDb4bKbHwuthWJiOn3aHWajNqp+W+4Vzr3qwUR9b1ReV946L7z93nKbC71i5qwnQkNji7ksSUk6yx6+Q3gh1T+UUmkpsf0xNSAMyowzE6re+L08gQcAAACf/meQAJQvb+cAAAAAAAAAAAAAAACA6Oi6E+RaFED57BwAAAAAAPCJTbO5Oi92kbrfTXc95OQNiIXCHb8z1yto1M7fCmdedHX406tvWjwArNdFV9xk34xoJ5w13QKG9fho+erQWigmqrMvu9ds1Ea339TzEvfdUXldccvc8Po7H9pg6BWnnXelmSxJCeu4zceEUiotJbofDB1jHlS5umzuUU/hAQAAwKf/GSQA5cvbOQAAAAAAAAAAAAAAACA6uu4EuRYFUD47BwAAAAAAfKIh0zzJy12k7pUavU9YvmKlkzcg8t7+8/thyPb7m+3dqKGxJew75bRwz8w5Yd26dosJgP/StS807jbZfhnRzpt+g0UM67H4jQ9Ca6GYqM698gGzURvd4O0PCNOun5W474/K6/KbHwuvvf2hTYaqW9PWFnbKTzWXJSlhnTNky1BKpaXENqf/oLBZNmceVPvcdOSE4Z7EAwAAIOmcRgFUJG/nAAAAAAAAAAAAAAAAgOjouhPkWhRA+ewcAAAAAADwibpM7govdpG61+RjfurUDYiFQ37wM3O9B9pqj8PCVTfcHVauWm1RARDunjnH/hjh7rh/lkUM6/HHF14PrYViovrFtY+YjeqRjvjxlYn7/qj8LrvpsfCn19+30VB1CxctDqnR+5jLkpSg+mVy4deDRoVSKi0ltsnDxpoHVa4uk7vck3gAAAAknZMogIrk7RwAAAAAAAAAAAAAAAAQHV13glyLAiifnQMAAAAAAD5Rn80t8mIXyUvWgeS69d5HzfQebsSOB4ULL78xLP1ouQUGkGB7HfIj+2KEe+GlxRYxrMfDj78UWgvFRDXt+llmo3qk0eMOT9z3R5V12U1zwiuvvWezoeouu/YOc1mSElY6Mz7cOWB4KKXSUiJ7oP/Q0GAWVLdM88qGofn/19N4AAAAJJlTKICK5O0cAAAAAAAAAAAAAAAAEB1dd4JciwIon50DAAAAAIDE69c0YRMvdZG6+dKx0fmw/OOVTt2ASHt/6bIwcqeDzPUqNXDMxHDaeVeGN9/xMmyApFn0ypLQ0NhiP4zwHr5uXbuFDOtx68ynQ2uhmLjMdfVUp1x4SyK/Qyq/S2+cExa9+q4Nh6rq6OgM+045zVyWpIQ1YtSeYXb/waGUSkuJrHn4TmZBlavL5o71RB4AAABJ5hQKoCJ5OwcAAAAAAAAAAAAAAABER9edINeiAMpn5wAAAAAAIPEaMs2TvNBF6l7fOf4cJ25A5E054VwzvRf62lZ7h+N/ckl46533LTqAhDjxrOn2wAi3/+GnW8SwHp2dIVxxy9zQWigmrs222NuMVI+0+0GnJPI7pMqafmMxvPCnd2w8VNXbf34/DNvhALNZkhLWtiN3DwvSA0MplZYS1/UDR5kDVS+3+Ev5/D96Kg8AAICkcgIFUJG8nQMAAAAAAAAAAAAAAACio+tOkGtRAOWzcwAAAAAAkHh1mdwVXuYida+7Z85x4gZE2j2fzDHzvHfrv3U+/PSX14blH6+0AAFibNnyj8PAMRPtfRHu4itvtpBhPT5ctiq0FoqJLD16XzNSPdJmW+wdzrtqZmK/S6qs5156y+ZDVd3x29lmsyQlsJbhO4eFqXQoSQls+5HfMAeqXF1jyzhP5QEAAJBUTp8AKpK3cwAAAAAAAAAAAAAAAEB0dN0Jci0KoHx2DgAAAAAAEq8+21zyMhep8gZss29YuWq1EzcgspZ+tDxkdjnYTO+jRux4ULjqhrvDuvZ2ixEghn51/V32u4j3+B8XWsiwHi8teS+0FoqJbOCY/cxI9ViTjjo/sd8lVd6zL71lA6Kqjjz5QrNZkhLY1KHbhVIqLSWuiwZvYQZUubps7j5P5QEAAJBUTp4AKpK3cwAAAAAAAAAAAAAAAEB0dN0Jci0KoHx2DgAAAAAAEq1f04RNvMhF6l6H//B8p22AF+Vqo/v6hCPCPTPnWJAAMdLZ2Rm2bzncPhfh0qPzYU1bm8UM6zHv6cWhtVBMZIO3P8CcVI/VtZ6mXT8rsd8nVd4zi960CVE1y1esDKP3PMx8lqQEds6QLUMplZYS1XOp/mF45ptmQFXLdXxl5PiUp/MAAABIIidPABXJ2zkAAAAAAAAAAAAAAAAgOrruBLkWBVA+OwcAAAAAAIm2SaZlfy9xkbrXbx+Z57QNiKyZs54wy2us/b734/AfS7wcGyAOHn1sgb0t4u3znVMsZNiAux99PrQWiols2A4HmZPq0Y48/arEfp/UvZ5Z5G8HVM/jf1wY+jVNMJ8lKWH1y+TCjEGZUEqlpUR10ubbmAFVri7b/HNP5wEAAJBETp0AKpK3cwAAAAAAAAAAAAAAAEB0dN0Jci0KoHx2DgAAAAAAEq0uk7vcS1ykyhu87X5h9Zo2p21AJC1fsTJssfsh5nkN1n/rfJh+zW2hvaPDQgWIsIOPOsu+FvEuuKxgIcMGXH37H0JroZjIRuz8bXNSPdrW449M7PdJ3e/p0ps2I6rm7ItnmM+SlMAGZsaH+wcMDaVUWkpM89KDQiqTMwOqWu7PAwbs/s+e0AMAACBpnDgBVCRv5wAAAAAAAAAAAAAAAIDo6LoT5FoUQPnsHAAAAAAAJFp9trnkBS5S5U095SInbUBkHXfGJWZ5jbfbfseEZ198xWIFiKDX33o39GuaYD+LeE8+U7KYYT1WrV4bWgvFxJbZ7VBzUj3e6b+8I9HfK3Wvp0tv2pSoira2tZ/+bcp8lqTk1ThqjzAvPSiUUmkpMR0y7Ou+/1Vuk0zL/p7QAwAAIGmcOAFUJG/nAAAAAAAAAAAAAAAAgOjouhPkWhRA+ewcAAAAAAAk1r8NH/+V+mxzpxe4SJX34O//4KQNiKQ5TzwTGhpbzPIItNkWe4Wf/vLaT19kDEB0nH3xDPtYxBu+w4GhvaPDYob1WPLW0tBaKCa2pt2nmJXq8XKHnpHo75W635MLX7cxURWLXlkS0qPzZrQkJbAdR+4WnkkPCKVUWkpED/QfGhp896taXaZ5lqf0AAAASBqnTQAVyds5AAAAAAAAAAAAAAAAIDq67gS5FgVQPjsHAAAAAACJVZ8dv5eXt0iVt/nXJ4W2trVO2oDIWfHxqjB6z8PM8oi1U35qePr5lyxggAhYvaYtDN/hQPtXxJt6ykUWM2zAgoWvh9ZCMbFtsfsUs1I9XnrrfcMvrn0k0d8tdb8nn3/N5kRVXHXD3Wa0JCW0/YfvEF5MpUNJSkjjRuziu1/lGkZOGO5JPQAAAJLESRNARfJ2DgAAAAAAAAAAAAAAAIiOrjtBrkUBlM/OAQAAAABAYtVnc+d7cYtUeT84/ZdO2YBIOvnnl5vjEW2zLfYKF15+Y+jo6LSQAWpY4Y7f2bdi0J0PzLaYYQMefKwUWgvFxNa0x3fNSlWlKSdfnujvljau+c+/ZoOix3V2doYDv/8TM1qSEtpJm28TSqm0lIhmDMr43le7TPMlntQDAAAgSZw0AVQkb+cAAAAAAAAAAAAAAACA6Oi6E+RaFED57BwAAAAAACRWfbZ5jhe3SJX3yJwFTtmAyJn35POhobHFHI943z767PDhRyssaIAatcekY+1XEa9f0wR7LXyB6+99MrQWiomtaY/vmpeqSlvueXiiv1va+OY//5pNih73zrsfhOE7HGhOS1ICa/ikSwY3hVIqLcW+Fz9pm5G7++5XsbpM7qOvjNz1f3laDwAAgKRwygRQkbydAwAAAAAAAAAAAAAAAKKj606Qa1EA5bNzAAAAAACQSAMG7P7PdZnm1V7cIlXW0LEHhLVr1zllAyJl1eo1Ydvc98zxmLTVHoeFBc+WLGyAGjP/6RftUzFor0NPtphhA9auaw/TbyyG1kJy22IPv61UvU77xW2J/n5p45v/3Gs2K3rcbx+ZZ0ZLUkLrl82FmwaOCKVUWop95w7e0ve+yjVkmg/zxB4AAABJ4YQJoCJ5OwcAAAAAAAAAAAAAAABER9edINeiAMpn5wAAAAAAIJHqG8dv7YUtUuUdf2arEzYgcs644NdmeMzabIu9wvRrbgudnZ0WOECNOPLkC+1RMWj6jNstZtiAt99bHloLxUS3xZ7fNS9VtcZP/nHiv2Pa+OY//5oNix53zI9/aU5LUkIbmhkXHuk/JJRSaSnWPZ0eEIZkvul7X9VyT3liDwAAgKRwugRQkbydAwAAAAAAAAAAAAAAAKKj606Qa1EA5bNzAAAAAACQSHXZ3LFe1iJV3uzHn3bCBkTKgmdLoV/TBDM8pn33xPPCylWrLXSA/5+9Ow+TqjoUva3nS85J7vnOcM+5uTk2g3Y1k6BQTYOIMyqKCNWAtmMwSpyNJipqoiYah6gx4lSoOE802mqMonHAONCAA86KVscBxXkWZRB6WN9u7C8JkaEKu7qrdr3v8/z+95G91tq719q1O9lHn3weyofsbm2KQQ2vvumChjV4NvNOSNfWl3SDRx5qvlTear2fOO/aB0p+nOnbN+fZ+RYt2tWixUvDlilroCSValv03zk8legZMuUJKdYdu/EWxnye6zpgzGZO7QEAAFAK7C4B5KTGygEAAAAAAAAAAAAAAADFo/WdIK9FAWTPygEAAAAAQEnqUlld52MtUm713358aGxqssMGFI1ly5aHYbsfaQ6PecP3/Fl49/2PXfAAneiCK262JsWgzXc9yMUMa3Hf7ExI19aXdINHHmbOVF478BeTS36cqX2a8+x8Cxft6vFnXgrdq8aaqyWpRKveZPswrzwRMlKMm1nRO3Q33vNbsvpqp/YAAAAoBXaWAHJSY+UAAAAAAAAAAAAAAACA4tH6TpDXogCyZ+UAAAAAAKAklVVWv+1jLVJu/eLMS+2uAUXlrItvMH+XSFU7TwjzGua76AE6QWNTUxg0YoL1KAad+vurXNCwFtffOTeka+tLusEjDzNnKq9V7nxgyY8ztV+PP/+mxYt2dU76RnO1JJVwP++7ZciUJ6RYt2e/YcZ7HitLppZ07VvzX07uAQAAEHd2lQByUmPlAAAAAAAAAAAAAAAAgOLR+k6Q16IAsmflAAAAAACg5GxQNaq7D7VIuTf7ieftrgFF48XM62HDwePM3yVU7y33Cg/NfsrFD9DB7pox2zoUkx57ep4LGtZgydLlIV1bX/INGXWYOVN576TzbjHe1G7NfWGBRYx209jYFHba6+fmakkq4c7rMyhkyhNSbLup56bGet5LHe30HgAAAHFnVwkgJzVWDgAAAAAAAAAAAAAAACgere8EeS0KIHtWDgAAAAAASk5ZZWovH2iRciu54/6hqbnZ7hpQHB+3bWoKI/Y+xvxdgm04aFy48bb7DAKADrT7QSdZg2LxzPdjz3ywFq+99XFI19aXfENGHWbeVN4b+eOTjTe1a0++uMBCRruZ1zA/bLTZbuZrSSrRulemws09Nw2Z8oQU27buv7Pxnt8y66233vpO8AEAABBndpQAclJj5QAAAAAAAAAAAAAAAIDi0fpOkNeiALJn5QAAAAAAoOSUJVMX+UCLlFsnn3O5nTWgaEyacpO5u4TrOnDMimsAgPxreG3BinnX+lP8nXDGJS5oWIs5z84P6dr6km/QLoeaN5X3yofsHiZd+6Axp3btqXlvWczw90dJUru08YBR4cGKPiFTnpBi2Xl9Bhnr+W5AapgTfAAAAMSZ3SSAnNRYOQAAAAAAAAAAAAAAAKB4tL4T5LUogOxZOQAAAAAAKDllyeq5PtAi5dZjT8+zswYUhZdfeSNstNlu5m6F0yZdbUAA5Nkvf3upNScmPTznaRc0rMXtDzwf0rX1Jd/AEQeZN9UhHXLipcac2r2nX3rLgka7aGxsCiP2PsZ8LUkl3Bb9dw5PJXqGTHlCil3PJXqEjQeMMtbzWTJ1sxN8AAAAxJndJICc1Fg5AAAAAAAAAAAAAAAAoHi0vhPktSiA7Fk5AAAAAAAoKV03r/l+WTK13AdapOwbNGJCaG5usbMGFP7HbJuawsgfTTR366+dNulqAwMgT75ctI2q6TIAACAASURBVCT03nIv600M2nibfcLy5Y0ualiDlpaWMKVuTkjX1pd8A4b/xNypDmlo6ghjTnnp+b+8a2GjXTS8tiAkhtSYsyWphBu7yfZhXqIiZMoTUuw6uu8WxnkeK6tMLfufZM0PnOQDAAAgruwkAeSkxsoBAAAAAAAAAAAAAAAAxaP1nSCvRQFkz8oBAAAAAEBJ6Zocs62Ps0i59etzr7SrBhSF9NW3mrf1jX5z3tUGB0AeXFU73ToTk448aZILGtbiw0+/DOnaekX13+EAc6c6pK4Dx4TTL7nTuFNeeuGV9yxutIsLrrjZnC1JJd6xG28RMuUJKXY9UtEndE+mjPM8VpasPtZJPgAAAOLKLhJATmqsHAAAAAAAAAAAAAAAAFA8Wt8J8loUQPasHAAAAAAAlJQuydG/9GEWKbcef+Ylu2pAwXt1/tuhYvMa87ZW2am/v8ogAWhHLS0tYZuxh1tjYtI9Dz7mooa1eOEv74Z0bb2i+m23n7lTHVbNYWcZd8pbL77yngWOb62xqSmM/NFEc7YklXiTeg8KmfKEFLv22GR7Yzy/ZdZbb731neYDAAAgjuwiAeSkxsoBAAAAAAAAAAAAAAAAxaP1nSCvRQFkz8oBAAAAAEBJ6VKZut1HWaTsS+64f2hubrGrBhS01nlq7AG/MG9rjZ1y7pWhpcWaBtAeHp7zjLUlJvUYukdYsvQrFzWsxQOPNoR0bb2i+myzr/lTHVafbX4ULpo609hTXpo8rT5k5n9gkeNb+8vrb4XEkBrztiSVcBtWpkJdz01Dpjwhxaranv2N8Ty3QdWYrZzmAwAAII7sIAHkpMbKAQAAAAAAAAAAAAAAAMWj9Z0gr0UBZM/KAQAAAABASemSrH7TR1mk7DvprCl21ICCd+XUO83Zyqpz0jcaMADt4ICfn2ldiUkHH3eOCxqycONdT4Z0bb2iem21j/lTHdoxZ1xv7ClvTZ42KzS88aGFjm/toitvMWdLUom3SXLXMLOid8iUJ6RYtVX/nY3x/Hat03wAAADEkd0jgJzUWDkAAAAAAAAAAAAAAACgeLS+E+S1KIDsWTkAAAAAACgZZYPH/LePsUi5NeuJ5+yoAQXtzbffD7223NOcray75ua7DRyAb2HBOx+E7lVjrSkx6fZ7ZrqoYS2WLmsM6dp6tdVj6F7mT3VoO+x1vLGnvHbJtFnh1QUfWfD4VhqbmsLIH000b0tSibdN/53Cs4keIVOekGLT73oPNr7zWbJ6caKq5j+c6gMAACBu7B4B5KTGygEAAAAAAAAAAAAAAADFo/WdIK9FAWTPygEAAAAAQMnYYMCYnXyQRcq+TYeNX/EhSIBC1dLSEvY69NfmbOVU96qx4d6HHjOAANbRmRdcaz2JST2G7hEWLV7qooa1eP2tj0O6tl5tJTarMYeqQ+s2aFz43VX3G3/Ka5fcNGvFfA/fxivz3wqJIdZJSSr19txkWHi5PBEyUkx6LtEj9EnuanznsbLkmMOc6gMAACBu7BwB5KTGygEAAAAAAAAAAAAAAADFo/WdIK9FAWTPygEAAAAAQMnoUll9go+xSNk38bS03TSgoF1Xd4/5WutUj6F7hKeezxhEADn6atmysOmw8daSmHTI8b9zUUMW6p96PaRr69XWhoN2M4eqw9v/2AuNP+W9S2+aFea//YmFj28lffWt5m1JUjhp481DpjwhxaajNt7S2M5vTzvVBwAAQNzYNQLISY2VAwAAAAAAAAAAAAAAAIpH6ztBXosCyJ6VAwAAAACAktGlsrrOh1ik7Ht4zjN204CC9d4HH4eNt9nHfK11rv/248P8Be8aTAA5uOmOB6whMepPf57jooYs3HzPMyFdW6+oi6fODF0HjjGHqsNLDv+JMagO6dKbZoU33vnE4sc6a2puDruOn2julqQSr2vU5b0qQ6Y8IcWiByv6rLiuje/8tcHAMVVO9gEAABAndo0AclJj5QAAAAAAAAAAAAAAAIDi0fpOkNeiALJn5QAAAAAAoGSUJatf8SEWKbv6brtvaGxsspsGFKx9j/iN+Vrfum3HHhE++/xLAwogS7vse6z1Iyb13nKvsPSrZS5qWIuvljWGydNmhXRtvaLOv+5Bc6g6rV+df5txqA7psptnh7fe/8wiyDpreG1BSAypMXdLUonXMzk63FvRN2TKE1IsGr3pDsZ2PktWX+pkHwAAAHFixwggJzVWDgAAAAAAAAAAAAAAACgere8EeS0KIHtWDgAAAAAASkKiquY/ulRWt/gQi5RdP//1hXbSgIJ10x0PmKvVbu15yK9CU3OzgQWwFk+/0GDdiFFHnHieixqy8PpbH4d0bb3aOufK+8yh6rTGHnS6cagO67KbZ4d3PvjcQsg6m3ztH8zdkqQwaMAu4fFEz5ApT0hF3xW9Ko3rfJasXvjD/sP/1Qk/AAAA4sJuEUBOaqwcAAAAAAAAAAAAAAAAUDxa3wnyWhRA9qwcAAAAAACUhC4DUsN8hEXKvhkz59pJAwrSBx99Gvpuu6+5Wu3aeZdNM7gA1uLIkyZZM2LU/Y884aKGLNQ/9XpI19arrTMuvcscqk6r91b7hIumzjQW1WFNqZsT3v1wocWQddLc3BLGHvAL87ckKaQ23SHMS1SETHlCKurmRSWTI43rPFY2oHp/J/wAAACIC7tFADmpsXIAAAAAAAAAAAAAAABA8Wh9J8hrUQDZs3IAAAAAAFASypLVE32ARcryA7Vb7hW+WrbMThpQkH5yzFnmarV73arGhIdmP2WAAazGx58uDIkhNdaMmLTxNvuEZcuWu7AhCzfd83RI19arrVMvut08qk7t2N/eYCyqQ7vi1kfDh59+aUFknbw6/+1QsbnnKElSdTim75YhU56Qir5fbry5MZ3XUrOd8AMAACAu7BQB5KTGygEAAAAAAAAAAAAAAADFo/WdIK9FAWTPygEAAAAAQEkoq0xN9fEVKbt+etIku2hAQbr9T4+Yp5W3+m23b1jwzgcGGsAqXHDFzdaKOH3I+ZSLXNSQhaXLGsPkafUhXav/v5POqzOPqlMb8aMTjUV1eFfd9lj4dOFiCyPr5NLrbjd/S5JWdEHvqpApT0hF3ZyK3qF7ZcqYzmPdBozu55QfAAAAcWCXCCAnNVYOAAAAAAAAAAAAAAAAKB6t7wR5LQoge1YOAAAAAABKQpdk9cs+viJl1z0PPmoXDSg4n3y2MAzYYT/ztPLaruMnhmXLlhtwAH+nsakpDBoxwToRox6e87QLG7Lw2lsfh3Rtvf6u48+uNY+qU9tos93DpGsfNB7V4V37xyfCwi+XWhzJWXNzSxh7wC/M4ZKkUJ5MhTt69AuZ8oRU1O29yXbGdB4rS1ZPcsoPAACAOLBLBJCTGisHAAAAAAAAAAAAAAAAFI/Wd4K8FgWQPSsHAAAAAACx94O+Nf9vl8pUs4+vSGuvx9A9wpKlX9lFAwrOocf/zjytDunksy834AD+zl0zZlsfYtSmw8aHxsYmFzZkof6p10K6tl5/19FnXGcuVad3+MmXG4/qlG64c25YtGSZBZKcvTr/7VCxeY05XJIU+g8YGWZX9A6Z8oRUtE3ruanxnM+SqY979BjxL077AQAAUOzsEAHkpMbKAQAAAAAAAAAAAAAAAMWj9Z0gr0UBZM/KAQAAAABA7G0wYPSWPrwiZdchx//ODhpQcO558FFztDq0B2bONfAA2ux+0EnWhhh13OmTXdSQpZvueTqka+v1d/30lKvMper0th73c+NRndaNdz0ZFi9dbpEkZ5dd/0dzuCRpRTv1Hx5eKK8ImfKEVLRtMWCE8ZzHyipTezntBwAAQLGzOwSQkxorBwAAAAAAAAAAAAAAABSP1neCvBYFkD0rBwAAAAAAsde1svpIH12RsuuO++rtoAEF5dPPvwjJHfc3R6tDqxy+f/js8y8NQKDkZV5507oQs2Y/8bwLG7KwdFljmDytPqRr9fcdctJl5lJ1et2qxoZzrrjXmFSnddOfng5fResE5KK5uSWMGn+ceVyStKIJ/bYJmfKEVLSd1WewsZzf7nfaDwAAgGJndwggJzVWDgAAAAAAAAAAAAAAACgere8EeS0KIHtWDgAAAAAAYq8smZrigyvS2ksMqQlfLlpiBw0oKD89aZI5Wp3SUSefbwACJe+EMy6xJsSogTsdEJqam13YkIXX3vo4pGvr9Q/tf+yF5lMVRPsfe4ExqU7tthnPheWNTRZMcvLyK2+EDQePM49LklZ0bp9BIVOekIqypxI9Q0VytLGct1LNG1SN6u7EHwAAAMXMzhBATmqsHAAAAAAAAAAAAAAAAFA8Wt8J8loUQPasHAAAAAAAxF6XZKreB1ektfeTY35r9wwoKDNmzjU/q1O7+4E5BiJQshZ+sSj03GJP60GMOv38a1zYkKWHnnglpGvr9Q/tecQ55lMVRFW7HGJMqtP7459fCE1NzRZNcnJ2+gbzuCRpRd0rU+GWnpuGTHlCKsoO7re1sZzHyipTJznxBwAAQDGzKwSQkxorBwAAAAAAAAAAAAAAABSP1neCvBYFkD0rBwAAAAAAsdclWf2RD65Ia++2ux+yewYUjC++XByqdp5gflan1n/78eGjTz43IIGSdPmNd1gLYtbzL7/qwoYsXXfHEyFdW69/aOxBp5lPVTCdetHtxqU6vbsfmReam1ssnGRt2bLlYbtxR5jHJUkr2mTArmF2Re+QKU9IRdf0Hn2N4zxWVln9l/XWW299p/4AAAAoVnaFAHJSY+UAAAAAAAAAAAAAAACA4tH6TpDXogCyZ+UAAAAAACDW/u8mo3/oYyvS2ttos93Cwi8W2T0DCsbPfnWB+VkF0eG/+L0BCZSclpaWsPWYw6wDMWrbsUe4sCFLny5cHNK19VpFI/c72ZyqgqnmsLOMSxVE99S/vOL+GbL16JMvhq4Dx5jLJUkr2nHT4eGF8oqQKU9IRdcO/Ycbx3lsg6oxWzn5BwAAQLGyIwSQkxorBwAAAAAAAAAAAAAAABSP1neCvBYFkD0rBwAAAAAAsdZlQGqYD61Ia2+/o063cwYUjAdmzjU3q6C67+HHDUygpDw46ynzf8w6//KbXdiQpWdefjuka+u1iobtMdGcqoKp33b7hYunzjQ2VRA98GhDaGmxhpK9iaelzeWSpL92aN+tQ6Y8IRVdk3oPMobzWupKJ/8AAAAoVnaDAHJSY+UAAAAAAAAAAAAAAACA4tH6TpDXogCyZ+UAAAAAACDWypLVh/vIirT2pv1xhp0zoCB88eXiMHjET0pyLt5wUMqaVKANHXVw+GrZMgMUKBk/Pup083+M6jpwTHjjrfdc2JClOx58IaRr67WKtqg+0ryqguqk8281NlUwPfLkqxZRsvb5wi9Dcsf9zeWSpL82qfegkClPSEXVs4keoVdytDGcr5LVX/yw//B/dfoPAACAYmQ3CCAnNVYOAAAAAAAAAAAAAAAAKB6t7wR5LQoge1YOAAAAAABirUuyOu1DK9Ka6141Nnz86UI7Z0BBOOaUi0pyLk4O2zV88HifMPnczUPvoT4+V4hdfNUtBihQEha888GKZwRzf3wavd/xLmzI0vLGpnDpzbNDurZeq2jgiIPMqyqodjvkDGNTBdVjz71hMSVr0++fZS6XJP218mQq3NGjX8iUJ6Si6rB+WxnD+W28038AAAAUIztBADmpsXIAAAAAAAAAAAAAAABA8Wh9J8hrUQDZs3IAAAAAABBrZcnqP/vAirTmxk34pV0zoCDMfOzZ0HXgmJKci+surwqhoWJF7z/WO0w8dpvQrSplnSqgegzdI7z93ocGKhB7p0262rwfs66qne7ChizNf/uTkK6t12rqt91+5lUVVBtvOz5cPHWm8amC6ql5b1lQydqEo39rPpck/bXKASPDo4leIVOekIqmP/Xoa/zmsdZzb07/AQAAUIzsAgHkpMbKAQAAAAAAAAAAAAAAAMWj9Z0gr0UBZM/KAQAAAABArJUlq9/zkRVpzV163e12zYBO98WixWGzXQ4syXk4tefw0JKpCKFh5V64t18YvcdO1qoC6siTJhmsQKwt/WpZ6Lfdvub8GNW9amz48ONPXdyQpUfmvhrStfVaTYnN9zC3quA68bw641MF1wuvvGdRJSvvf/hJ6LP13uZzSdJf23XTHcO88kTISEXU9v3tZ+axlu6DxiWcAAQAAKDY2AUCyEmNlQMAAAAAAAAAAAAAAACKR+s7QV6LAsielQMAAAAAgNjq2rfmv3xcRVp7r73xjl0zoNNNPC1dknNwt6pUeObuTUNoqFhlLZmKcOuVVaH/trtaswqgrgPHhMeenmfAArFVe/sM833M2ufwU1zYkIMb7pwb0rX1WkUXT50ZukX3w+ZWFVpjDzrNGFXBNXlaffjLmx9ZWMnKNTffbT6XJK3Uz/tuGTLlCalomtR7kLGbx8qSqVOcAgQAAKDY2AECyEmNlQMAAAAAAAAAAAAAAACKR+s7QV6LAsielQMAAAAAgNjaoGrMVj6uIq257cYdYccM6HSPPPpM6FqiH2c/9uhtQmioWGsfz+0dDjt8O2tXAbTLPseE5uYWAxeIpRF7H2Ouj1m3TH/QhQ1Z+uyLJSFdW6/VdO7V95tXVZD13nrfcPHUmcapCq5LbpoV3nz3Uwssa9X6d6YxB/zCnC5JWqmLeg8MmfKEVBQ9m+gReiVHG7t5KzV/vfVO+ScnAQEAACgmdoAAclJj5QAAAAAAAAAAAAAAAIDi0fpOkNeiALJn5QAAAAAAILa6DEgd5MMq0po784Jr7ZgBnWrxkqVh6KiDS/PD30NHhw8e7xNCQ0XWPTAtGap22NUa1slNv3+WwQvEzhPPvGSOj1kVm9eELxYtdnFDlp5reCeka+u1mn6T/qO5VQXbCefeZJyqILvs5tnh3Q8XWmRZq4ZX3wwbbbabOV2S9NcSydFhes++IVOekIqiQ/tubezmswGpYU4CAgAAUEzs/gDkpMbKAQAAAAAAAAAAAAAAAMWj9Z0gr0UBZM/KAQAAAABAbJUlU+f7sIq05p58LmPHDOhUJ5xxScnOwVMmbRZCQ0XOLXy6Vzh+og/TdWbDdj8yNDe3GMBArBx2wrnm+Jh1xC9/78KGHNz50IshXVuv1XT8OdPMrSrYqif8xjhVwXblbY+GTz5fbKFlrc69ZKo5XZK0UlUDdglPVPQMmfKEVPDd3aOfcZvfrnUSEAAAgGJi5wcgJzVWDgAAAAAAAAAAAAAAACgere8EeS0KIHtWDgAAAAAAYqusMvUnH1WRVt+AHfYLzc0tdsyATjP7iedD14FjSnIO3nbXEaHxpR4hNFSsc/dOTYZNtxllTeuk7rx/lkEMxMYHH30aNhw8zvwesx6c9ZSLG7K0vLEpXHrz7JCurddqOvLUq82tKth6bbVPuGjqTGNVBds1tz8evli01ILLGi1btjxsO/YI87okaaVSm+4Q5iUqQqY8IRV8w/rvZNzmr0X/3Tv1b04DAgAAUCzs/ADkpMbKAQAAAAAAAAAAAAAAAMWj9Z0gr0UBZM/KAQAAAABAbHVJVr/soyrS6pv4m4vtlgGdZvGSpWGL0YeU7Bz84M3JEBoqvnUfPt477PPjHaxrndCw3X4amptbDGYgFs67bJq5PWYld/xxaGxqcnFDll5586OQrq3XGjrguIvMryrojjt7qrGqgu6G6XPD4qXLLbqs0WNPzwtdB44xr0uSVuoXGw8NmfKEVPBN6j3ImM1jZZWpCU4DAgAAUCzs+gDkpMbKAQAAAAAAAAAAAAAAAMWj9Z0gr0UBZM/KAQAAAABAXK3fJVm92EdVpNV338OP2y0DOs2JZ11WsvPvhIO2D6Ghot1qyVSEqy7YLGw4KGV96+D+eO9Mgxkoeo2NTaFq5wnm9Zh1+vnXuLghB/fPzoR0bb3W0F4/Pcf8qoJu1P6/NlZV8E3709Phq2WNFl7W6PjTJ5vXJUkr1TXqyl7JkClPSAXdM+U9Qq/kaOM2XyVTMx0HBAAAoFjY8QHISY2VAwAAAAAAAAAAAAAAAIpH6ztBXosCyJ6VAwAAAACAWPq/m4z+oQ+qSKuvx9A9wpKlX9ktAzrFnLkvhK4Dx5Tk/LvR4FR4/ZGNQ2ioaPeeuXvTsMWIXaxzHdjWYw4LTc3NBjVQ1O64r96cHsNe+st8Fzdkqbm5JVxx66MhXVuvNZSacIr5VQVdry33DhdNnWm8quC7/YHnQ1OTvyWwel98uTgM3OkAc7skaaV6J0eFhyr6hEx5QiroDum7tTGbv1q6Vo7u4VQgAAAAxcCOD0BOaqwcAAAAAAAAAAAAAAAAUDxa3wnyWhRA9qwcAAAAAADEUpeq1BAfU5FW34Sjf2unDOgUi5csDVuMPqRk59+zfrNlCA0VeWvh073C/gdub63rwP5470wDGyhqYw74hfk8Zu2899EubMjBm+9+GtK19VpLO+x1nDlWBd/x50wzXlUU3f3IvNDc0mIRZrXufmCOeV2S9I226b9TeC7RI2TKE1LBdkePfsZrfjvVqUAAAACKgd0egJzUWDkAsr7P/PsfHV8U9ek/9GHUa1F/iXoyalbUjKjbo+qipkRNjjojamLUgVG7R+0YVRWViPqvqH/yfxsAoOTuNev8iQIAgDxbvoq/abY2v+3vms9EPdH2N8272u5Rr2n7u+Y5Ub+MOixq76gRUZtH9Yn6n6jvuasHAACgSPdovtf2bNun7Vl3l7Zn38PanoXPaXs2vqbtWfnutmfnJ9qepV9re7Ze1TP3cn+OAFgnzrcDZH8/W2PZAACgA3y2ir9/vtP299EXw9fvUj4UdX/b31FvbPu76vlRp0T9LGq/qFTUNlH9o7pF/Zu7egAAAIB2UFZZvacPqUirb9ofZ/gzL9ApTj7n8pKde6t22DUseq5nCA0Vea0lUxHOO3No6DrQetcR7bLPMQY2ULRezLxuLo9hl994h4sbcvDwE6+EdG291tLmo48wx6rgqz7wNONVRdOMOQ0WYdboJ8ecZW6XJH2j/fttEzLlCamg26b/TsZrnipLpl5db7311ncyEAAAgEJnpwcgJ350HCD7+8yO+tHx5qj3o54PX3+E54aoSVHHR/04fP3xnn5R/+5fBQAgNveadf5EAQBAkVsYlYmqj7o1Kh3166hDoqqjNovaIMp5dAAAAPK977J+2zPokLZn0kPbnlFbn1Vva3t2zbQ9ywJQeJxvB8j+3rfGsgEAQJFbGrUg6vGo6VFXR50RdVTU3lHbRCWi/tkTAAAAAMBqdKmsPsHHVKRV161qTPjw40/9KRbocHOffXnFHFSq8+8frqoKoaGiw7rzuoGhx+ajrX0d0DMv/MUAB4rSxN9cbB6PWRsOGud5D3LQ0hLC1bc/HtK19VpL/XeYYJ5Vwdd32/Hh4qkzjVkVTTOffM1izGp98NGnYeNt9jG/S5K+0aTeg0KmPCEVbGduvJmxmsfKKscMdTIQAACAQmenByAnfnQcIPv7zEL80fHWj/u8GHV31JSok6P2C1//WOQG/tUAAIrmXrPOnygAACgRy6JaX259OOr6qDPD1x833yWqZ9R3PSEAAACwln2V70b1ihoZdVjbs2XrM+Yjbc+cyzx+AxQ159sBsr83rrFsAABQIlqi3o16POrWqAuijo7aPaoy6t88IQAAAAAlq0tlarIPqUirrnr/E/x5FehwS5Z+FbaqPqxk597UnsNDS6YihIaO7cX7+oUhw3ex/uW5I0+aZJADReezz78MPYbuYR6PWfsddbqLG3Lw3kdfhHRtvbKoYuie5lkVRSedf6sxq6Lq6ZfesiCzWtfe/CdzuyTpG5UnU+HOHv1CpjwhFWRPVPQMG1WmjNe8lbrEyUAAAAAKnV0egJz40XGA7O8zi/FHxxdFPRu+/qHIs6MOihoW1cW/KABAQd1r1vkTBQAArNAY9WrUvVGTw9cfvxkd1Tvqu54eAAAASmbv5LtRfaJSUce0PSPeF/Va27MjAPHlfDtA9vfNNZYNAAD4qw+iZkddG3Vy1F5Rg6P+3dMDAAAAEGtllam7fURFWnWTr/2DP50CHe6Uc68s2Xm3W1UqPPunTUJoqOiUPnmyV9ht3x2tgXlso812Cx9+/KmBDhSVS6LnAnN4/Jp+/ywXN+Rg9jPzQ7q2Xmvp/OseNMeqaNrj8LONWxVd8159z6LMKjU3t4Rdx080v0uSvtHAAbuEJyp6hkx5QirI9tlkO2M1T5VVpj7p0WPEvzgdCAAAQCGzywOQEz86DpD9fWbcfnT886gno66POiF8/WHaRNT6/rUBADr8XrPOnygAAGCtloevP54+PersqP2iqqK+56kCAACgaPdIvtN2XmV02/mV69vOsyzxGAxQspxvB8j+frrGsgEAAFl5N2pG1IVRB0dtFfXvnioAAACAWOhSWT3Ph1SkVffq/Lf9eRToUE8+lwndq8aW7Lx73MRtQmio6NSWvdgjHHHkttbBPHbeZdMMdqBotH6Yfeiog83fMavP1nuHpV8tc4FDDm6c/mRI19ZrLf0mfYd5VkXTgB0nGLcquiZPmxVeXfCRhZlVem7eK6Fb1RhzvCTpG+226fbhpfKKkClPSAXXDb36G6d5bIPk6GqnAwEAAChkdngAcuJHxwGyv88slR8d/yxqVtTFUROiKqO+6woAAMjrvWadP1EAAMA6a/2hk+ejbow6JmpY1H960gAAACi4/ZD/HbV91LFRU6NejFrusRaAf+B8O0D299g1lg0AAPhW3oi6K+r0qHFRG3nSAAAAAIpOl8rqRT6iIn2zLVOH+hMo0KGWLVsehu3205Kdd/tsMTp8+ETvEBoqOr2WTEU489dbWA/zVOXw/cPy5Y0GPVAU7n/kCXN3DDvhjEtc3JCDTz5fHNK19cqiiWdNNc+qqPpN+g5jV0XXpTfNCgve+8wCzSodf/pk87skaZX9auPNQ6Y8IRVcL5VXhMoBI43T/FXndCAAVlwOfQAAIABJREFUAACFzO4OQE786DhA9veZpfyj460fpX0q6oqow6M2j/qeqwIAoN3uNev8iQIAANrda1G3Rp0YtUvUDzx9AAAAdNjexw+iRkad1PZs9rrHVACy5Hw7QPb33TWWDQAAaHefRj0QdW7UPlG9o9b3BAIAAAAUpP9J1vzAx1OkVXfGBdf6cyfQoU4//5qSnnevvGCzEBoqCqqrov+mblUp62IeuuO+eoMeKAr7HH6qeTuGzX32ZRc35GDuiwtCurZeWXTIiZeaZ1VU7fuz3xu7Ksouv2VO+OizRRZpvuGzz78M/bcfb46XJH2jbpWpcGOvASFTnpAKrhM23sI4zVNlyeqlGw6o/k+nBAEAAChUdncAcuJHxwGyv8/0o+Mra4yaFzUlar+ofsGPQwIArOu9Zp3bSwAA6BDvtt1//yxqq6h/8UQCAADwrfc5vtN2buTgqOvbzpO0eAQFYB053w6Q/b248+0AANAxFkbNijo7anTU//FEAgAAABSErslRg31ARVp1c+a+4E+bQId5+oWG0L1qbMnOucNGjwiNL/UIoaGi4Jo2ZVD0b5OyNrZzPz7qdAMfKHjzF7wbulWNMW/HrC1Th4aWFu8uQi5uvueZkK6tVxbtc9S55loVVYNGHmLsqmi75vbHwxeLvrJQ8w21t88wx0uSVlmf5K7h4Yo+IVOekAqqh6Lrslul/ch81TVZfaBTggAAABQqOzsAOfGj4wDZ32f60fG1+yDqjqhfhq8/SPvPrhwAgKzuNevcSgIAQKdYEr7+4M3vo8YGH7wBAADIZl/jB1HjoiZFzY5a6vESgHbkfDtA9vfmzrcDAEDnaP0400tR10QdFNXHEwoAAADQKbpUjh7n4ynSN+u15Z5h+fJGf8oEOsSyZcvDsN2PLOl59+FbBoTQUFGw3XHtwLBhlfWxPdtw0Ljw4cefmQCAgnbKuVeas2PYpCk3ubghB58uXBLStfXKstSEU8y1Kq4Piw8cE86aco/xq6Lthulzw5KvlluwWfmUdktLqN7/BPO8JGmV7dB/eHihvCJkyhNSQbXrpjsao3mqrDL1sFOCAAAAFCo7OwA58aPjANnfZ/rR8dy1HkR7MursqB2jvu9KAgBY5b1mnVtHAAAoGK9FTYnaL6qbJxYAAMA+Rvhh1Oi28x+t50CaPToCkEfOtwNkf6/ufDsAABSOD6KmR50QVRX1T55aAAAAgLwrq0wd6uMp0jf78VGn+5Ml0GHOvPC6kp5zf3LwsBAaKgq++2uToXyzlHWyHbv6prtMAEDBWrL0q9B3233N1zGr68Ax4c2333eBQw4ee/6NkK6tV5Ztt/sx5lsVXfsfd6Hxq6LulvueDcsbmyzarOTlV94IGw4aZ56XJK2yI/puFTLlCamgmtxroPGZv1p+OKB6IycFAQAAKER2dQBy4kfHAbK/z/Sj49/eV1Ezo1pfON8u6p9dWQAAK+4169wqAgBAwXo56rKoPaP+2xMMAABQAvsWP4jaK+ryqIzHQgA6mPPtANnfuzvfDgAAheujqD9EHRnVxxMMAAAAkBdllamTfThF+mZXT7vLnyiBDvH8y6+GDQeX7sddE5ulwpv1G4fQUFEU3XV9ZehelbJWtlOj9zveJAAUrOvq7jFXx7DdDjzRxQ05unH6kyFdW68sGzjiIPOtiq4tqo80flX03fXIvNDc0mLhZiUnn3O5eV6StNrSvQeGTHlCKpieT1SE3slRxme+So7+pZOCAAAAFCI7OgA58aPjANnfZ/rR8fa3OGpG1AlRVVHru9IAgBK916xzawgAAEWhOerJqLOjdoz6F080AABADPYpvtN2bqP1/MastmcfAOgszrcDZH8v73w7AAAUj/fD1+8NHBxV5okGAAAAaBdlydT5PpwifbNX57/tT5JA3i1btjxsX3NkSc+3554+NISGiqLq1iurQreqlPWynXrtjXdMBkBBKvU1Oq7V3j7DxQ05+ODjL0O6tl451Gurfcy3Krq6VY0Nv796hjGsou+hJ16xeLOSL75cHJI77m+ulyStsh6Vo8N9PfqGTHlCKpgO67eV8Zm/5jkpCAAAQCGyowOQEz86DpD9faYfHc+/t6Kujtor6n+76gCAErrXrHMrCAAARWlR1N1RP4/q5ekGAAAoor2JPlFHR/0parHHOwAKiPPtANnf1zvfDgAAxak56smos6K2i/qOJxwAAABgnZQlUzf4aIq0cpvvepA/QQId4uz0DSU93w7acWRY/HyPEBoqiq5pUwaFrgOtme3ReZdNMxkABWfO3BfM0TGsYvOa8MUi70FCLuqfej2ka+uVZRde/3D0nDDGnKui7LBfXWEcKxbNfXGBBZyV/OHuh83zkqTVtnX/ncNziR4hU56QCqI7e/QzNvPYBlWjBjotCAAAQKGxmwOQEz86DpD9faYfHe9YTeHrH4Y8NarKFQgAxPxes87tHwAAxMJrUVOiRkf9s6cdAACggPYi/p+oraLOjnrJ4xsABcz5doDs7/OdbwcAgHhYFDU96uCoH3raAQAAALJWlkzd66Mp0sodf/pkf3IE8u65l14NGw4aV9Lz7e1XV4XQUFG0XXj25tbNdmibsYebEICCc9DEs83RMeyIE89zcUMOWlpCuOb2x0O6tl5Zdlr6TvOtirad9v2lcazY9NJr71vIWckeB//KXC9JWm0H9ds6ZMoTUsG0df+djc18law+z2lBAAAACo2dHICc+NFxgOzvM/3oeOfyMVoAIM73mnVu9wAAIHZ87AYAAOjs/Yf/ajvvcn3UZx7TACgSzrcDZH/P73w7AADET1PUk1GnRlV58gEAAADWqEsy9aSPpkgrd/cDc/yZEcir5csbww41R5X0XDtmr+GhJVMRQkNxd+IJW1s726HX33zHxAAUjPc//CRsOHic+TmGPTT7KRc45ODt9z8P6dp65dAxZ15vvlXRVrHFnuGiGx8xlhWLLrlpVnjz3U8t5vxVw2sLPOdJktbYRb0Hhkx5QiqITuszxLjMX++vt+2233FiEAAAgEJiJwcgJ350HCD7+0w/Ol44Wg+zXRs1Oup7rk4AIAb3mnVu8QAAINYao2ZEHRr1P56CAACAPO45bBB1eNSfw9cf3gSAYuN8O0D29//OtwMAQPy9HHVm1EBPQQAAAMA3dKlMzffBFOlvda8aGxZ+scifFYG8OveSqSU913arSoXn7tkkhIaKoq/p5R7hgAO3t4Z+y66YeqeJASgYv5s81dwcwyqH7x+amptd4JCDBx9/JaRr65VDE45Pm3NV1J3wu2nGsmLTZTfPDu999IUFnb8684JrzfWSpNWWSI4Od/foFzLlCanTezTRK3Q3LvNW14HVOzsxCAAAQCGxiwOQEz86DpD9faYfHS9Mi6OmR+0X9W+uVACgSO8169zWAQBAyWj9oZZZUSdEVXgiAgAA2mGfoVvUz6JmRDV67AKgyDnfDpD9s4Dz7QAAUFreiLowaquo9T0VAQAAAOt1SVYv9sEU6W+N2PsYf0YE8mpew/yw4eBxpf2R7uO2DqGhIjZ9+WzPMHzMTtbRb9Heh51icgAKwvLljSG544/NzTHsjAuudYFDDpqbW8KVtz0a0rX1yqFxh5xhzlVRt9shZxrLilVX3vZY+OyLJRZ2Vliy9KswZOSB5ntJ0mobMmBEeLq8R8iUJ6ROb+wm2xuXeaosmbrBiUEAAAAKiV0cgJz40XGA7O8z/eh44VscdWvUnlHfd9UCAEV0r1nnVg4AAEpSS9SjUROjuno6AgAActhb6B51XNTjbc8WABAXzrcDZP9c4Hw7AACUrgVRF0QNjVrfExIAAACUoK6b13zfx1KklfvV767wp0MgbxqbmsIu+xxT0vNs361GhU+e7BVCQ0Wsemv2xmHTbUZZS9exjTbbLXy5yEeugc53290PmZdj2suvvOEChxzMf/uTkK6tV45tv+dEc66KugHDf2IsK3bdcOfcsHjpcos7K9z9wBzzvSRpjY3vt13IlCekTu/S3pXGZN5KfblB1aj/5eQgAAAAhcIODkBO/Og4QPb3mX50vLi0vlhXFzU66ruuYACgwO8169y+AQBAyWuOmhX1s6gfeFICAABWsZ/wn1H7Rc1oe4YAgDhyvh0g+2cE59sBAIBWb0ZdGJX0pAQAAAAlZIOqUd19KEVaubtmzPbnQiBvzrtsWsnPs1dfNDiEhopYNvPWAaF7Vcp6uo7d+9BjJgmg040af5w5OYbtvPfRLm7I0X2zMyFdW68cGzjiIPOuir4zLpluPCt21d37TFje2GSBZ4XxR55mvpckrbHzeg8KmfKE1Kk9n6gIvZOjjMk8VVZZvaeTgwAAABQKuzcAOfGj4wDZ32f60fHi9UnUlKitotZ3NQMABXivWeeWDQAA+DtfRU2P2i/qXz01AQBASe8hfC9qdNtewjKPSwCUAOfbAbJ/XnC+HQAA+Efzok6NKvfUBAAAADG3QdWogT6UIq3cBx996k+EQF689Jf5YaPNdivpOXbY6BGh8eWKEBri28XnDLGermPHnz7ZRAF0qudfftV8HNOumHqnCxxysHx5U5hSNyeka+uVY4nN9zDvqug7YOJFxrNi2fSH54XmlhYLPWH+gndDYkiNOV+StNrKk6kwvWffkClPSJ3aIX23NibzVFmy+g9ODgIAAFAo7N4A5MSPjgNkf5/pR8fj4ZWoX0d1d1UDAAV0r1nnNg0AAFiNhVFXR23l6QkAAEpm32D9qK2jrml7JgCAUuJ8O0D2zw7OtwMAAKvTHPXnqPFR/8sTFAAAAMRQWTK1ow+lSH9ry9Sh/iwI5EVjU1MYsfcxJT/PzvpD/xAaKmJdS6YijJ+wvXV1HRo0YoLJAuhUR59yofk4hm04eFz48OPPXOCQg3mvvhfStfXKsd9fNcO8q1i09bifGdOKbTPmNFjoWeHcS6aa8yVJa2zwgF3CU4meIVOekDqtP/TcxHjMU2XJ6qWJqpr/cHoQAACAQmDnBiAnfnQcIPv7TD86Hi+tPwo5K+rg4EchAYDOv9esc3sGAABkofWl3lOjNvQkBQAAsdwvKIs6IeovHn8AKGHOtwNk/wzhfDsAAJCNhVHXR+0Ytb6nKQAAAIiJDQZUj/GhFOlvHXPKRf4UCOTFhVfWlfwce/Chw0JoqCiJPp7bOyS329Xaug69+fb7JgygU3zy2cKQGFJjLo5hPznmty5wyNGt9z8X0rX1yrGTJ91i3lUs6j54XDjv2j8b14ptjz//psWesPSrZWHoqIPN+5KkNbbPJtuFTHlC6tSG9h9hPOapsuToHzs9CAAAQCGwcwOQEz86DpD9faYfHY+vz6OmRG3lSgcAOules84tGQAAkIPmqBlR+0V931MVAAAU9R7BP0eNbtsraPS4AwDOtwPk8DzhfDsAAJCrl6NOiPqhpyoAAAAocl0HpPb1kRTpb0374wx//gPaXcNrC0JiSE1Jz68VQ0aHBbM2jv5nVJRMD9UNCF0HWltz7ba7HzJpAJ3i4qtuMQ/HtPsfecIFDjn4bOGSkK6t1zp0xClXmncVm476zdXGtWLdvFffs+gTHpr9lDlfkrTWzu4zOGTKE1Kn9auNNzcW81RZsvoepwcBAAAoBHZtAHLiR8cBsr/P9KPjpeGZqEOj/s1VDwB04L1mndswAABgHX0YdW5UhacrAAAoqr2BnlG/j/rYYw0ArMT5doDsnyucbwcAANbV8qg/RA2PWt8TFgAAABShLgNSB/lIivS3XnvjHX/2A9pVY1NT2GXfY0t+fv39GUNDaKgouU48YWvra4798reXmjiADtfU3ByGjDzQPBzDKofvv+J+DMjenGfnh3RtvdahfY8619yr2DRyv5ONa8W6S26aFRa895mFn3DAz88070uS1thGlalwZ49+IVOekDqlmRW9Q7foOjQe81CyunGDqlH/xwlCAAAAOpsdG4Cc+NFxgOzvM/3oeGn5ImpK1ABXPwDQAfeadW6/AACAb6klakbb37K/40kLAAAKcj/gn6J2jJredg8PAHyT8+0A2T9jON8OAAC0h1eiTojyW6IAAABQTLokUz/zkRTp6/pvP96f+YB2N2nKTSU/vw7ecWRY/HyPEBoqSq4lz/cMQ3ceaZ3NoeF7/szEAXS4ex58zBwc08688DoXOOSguaUlXHP74yFdW691aMT4k8y9ik29ttonXDx1prGtWDflljnh488WuQEocW++/X4oH7K7uV+StOa9rgG7hKcSPUOmPCF1SqM33cFYzFNllalDnSAEAACgs9mxAciJHx0HyP4+04+Ol64now6O+r6RAADk6V6zzi0XAADQjt6NOjuqmycuAAAoiH2A/wlff4zyDY8rALBWzrcDZP+s4Xw7AP8fe/fhJ1V5L/A/avLz5ndLbnvdGxcQd2elCsxSVETFggIqs4u9G2s0tthCbFETC8ZgiWshlmjURTcxFqIYuy4iGhVRgdmosRcMIdLr7vM7RG5+Bilndmdmd8+836/X5x/Qc77zPGcfzgGAfFoavvi3DcPsuAAAAKADKKvKnOsDKdIXHXrSRR7vAXk184/vhC223qfk5+vE26tCaEyVbE/ek/Y7m0NdBtSE+QsWGSBAUR3w3fPN4IT25jsfuMAhB+98+JdQW9egFjZoj+PNXiWqH139W/e2Et8v73shLFi01CKgxF3681+Z+5KkDXbwVjuFbHmF1CZd232A+7BAlVVlnnaCEAAAgLbmrzUAOfHScYD460wvHWd21CVRZe4IACDPa816Sy0AAKAAlkfdEzXYzgsAANrk+f+Q1X8DWG57AgCxOd8OEH/P4Xw7AABQKC9HHRG1qd0XAAAAtFOd0tU/8YEU6Ysur73TIz0gb1asXBlGHnx6yc/W0QcOC83ZVAiNpd1xx+/stzaHnp4yzRABiuaPf/ogdO5fY/4msL2POtsFDjl6uGFmqK1rUAur2HZ/81eJ6tDvX+neVkl0zyPTwvIVKy0EStiChYtD1W7fMfslSRtsXPeBIVteIRW9Vysqw5bpUe7DgpRp6txvz05OEQIAANCW/LUGICdeOg4Qf53ppeP8n1Ufu1r10SsfogUA8rXWrLfEAgAACmzVh24Oj/qGXRgAABT0mf83Vp8xec42BABaxPl2gPj7D+fbAQCAQpsdNTbKO0YBAACgvSmrqr7Mx1GkL5r05FSP8oC8GXfjhJKfq5sPyISZj/UOoTFV8s1+oUfoMWQvv7dxP0oZ3T8AxXLuZePN3oRW/+ATLnDIwZKlK8INdz8Xausa1ILG3vSI2avENaTmZPe3SqaJT78RmpubLQhK2D0PPGH2S5I2WHk6Ex6q7B2y5RVS0Tuy91D3YcHKnOYUIQAAAG3JX2oAcuKl4wDx15leOs7avBS++BDt190lAEAr1pr1llUAAECRfBJ1YdR/2Y0BAEBen/V/K+rUqPdtOwCgVZxvB4i/D3G+HQAAKJZlUb+K6ms3BgAAAO1Ep6rqn/owivRFH386xyM8IC9mNL4Ttth6n5Kfq+eO2SGExpRWd+3l2/i9jdlRp11qkABFsWDh4tBj+4PM3gTWbcgBYeGiJS5yyMG0WR+G2roGtbCzxt5l/ipxdRm4d7jytifd4yqZGl5+24KghDU1NYc9DzvT/JckbbDt+o0I0ysqQ7a8Qipqd27Zzz1YoMqqMi84RQgAAEBb8pcagJx46ThA/HWml46zPn+KOi3qX9wtAEAL1pr1llMAAECRLYq6IarSrgwAAFr1jL9b1PjVa2wAoPWcbweIvx9xvh0AAGgLj0ftEbWRnRkAAAC0obJ09ZU+jiJVh767HOaRHZAXK1auDCMPPr3k52rvHfYMf3mpWwiNKa1uyetbhkHD9vC7G6MhmeMNE6Aobp3wO3M3oZ31k+tc4JCjCQ+/EmrrGtTCjvpBrfmrRHbaxbe7x1VSTW/8yKKghL00PRs6968x/yVJG+zY3juEbHmFVNRmlqdCv357ugcLVOeqUV6sDQAAQJvxVxqAnHjpOED8daaXjhPHvKhrojZz1wAAOaw16y2jAACANtIUNTFqa7szAADI6dl+OupXUSttKwAgr5xvB4i/L3G+HQAAaEuvRR0e9XU7NAAAAGgDZVXV1/gwilQdDj3pIo/qgLy44vq7zNWo22u3DqExpTWqu3Gg6yNGXQbUhCVLlxkoQEE1NzeHoaNPNHcT2iuvN7rIIQez5ywItXUNakXVx/zY/FUiW3Vtu8dVSl03YXJ458O/WByUsBPP/pn5L0mKVW33/iFbXiEVtVN7DXH/Fap09TlOEgIAANBW/IUGICdeOg4Qf53ppePkYmn44uNZle4eACDGWrPe8gkAAGgHJkeNsksDAID1PtPfPmpiVLMtBAAUhPPtAPH3J863AwAA7cE7UadG/b92agAAAFBEndLVtT6MIlWHy2vv9IgOaLU3sn8KXQftXfIzdVj18LByVmUIjSmt0ar/LjuPGuG3N0ar7ieAQnp26qvmbULbed+TXeCQoyem/jHU1jWoFW0/+lQzWIms765HucdVct14z3Ph0znzLRBK1Eef/jlUDt7fb4AkaYNVVo0Kj6V6hmx5hVS0Hqzs7f4rUGXpzGtOEgIAANBW/IUGICdeOg4Qf53ppeO0xPKoX0X1dhcBAOtZa9ZbNgEAAO3IK1GHR21ixwYAAH97jr9x1Kio520XAKDgnG8HiL9Xcb4dAABoTz6LujDqP+3YAAAAoAg6patrfRhFqg6Tnpzq0RzQKsuXrwi77neKmRo15b6+ITSmtI7uu2WA6yRG9z38jMECFNRRp11q3ia08Xfc7wKHHCxdtiLceM9zobauQa2o19DDzGAltktvfMh9rpLr1vteCPMXLbVQKFHjbpxg/kuSYrVD3+HhtYpUyJZXSEVru34j3H8Fqku/UT4MCAAAQJvw1xmAnHjpOED8daaXjtMazVETowa4mwCAtaw16y2XAACAdmhG1OFRm9i5AQBQos/vN44aFTXN9gAAisb5doD4exbn2wEAgPZoQdTYqP+0cwMAAIACKquqvtpHUaTq8O4Hn3gkB7TK5bV3mqdRJ3xvpxAaU1pPK2alwja7jXS9bKBV9xRAoXzw8Wdh8wGjzdsEtsXW+4Q5c+e5yCEH02Z9GGrrGtSKrrr9ydC5f405rMR2zJjr3OsqyeoeejksXbbCYqEELV6yNAwacbTfAElSrE7utX3IlldIRev8ntu69wpVuvonThMCAADQFvx1BiAnXjoOEH+d6aXj5ENz1MSoAe4qAOBLa816yyQAAKAdmxF1eNQmdnAAAJTIc/uNV58TmWk7AABF53w7QPy9i/PtAABAe7YgamzUf9rBAQAAQAF0SleP81EUlXqVg/cPTU3NHsUBLfb6rLdD10F7l/w8TW0zKnzwXM8QGlPaQDddvY3f4A109OmXGi5AwVxyze1mbUI79syxLnDI0Z0TXwq1dQ1qReeOqzeDleh2PfAH7nWVbPc98VpY6e8HJem+Sc/6DZAkxapz1M3d0iFbXiEVpWdSPf523bn/8l9ZOvPW1772tY2cKAQAAKDY/GUGICdeOg4Qf53ppePk06qDdBOjBri7AIBoTVBveQQAAHQAM6MOj9rETg4AgIQ+r9949fmQWZb/ANBmnG8HiL+Hcb4dAADoCBZErfr41X/ayQEAAEAedUpnLvdRFJV6ww86zeM3oMWWLVsedtnvZPM06qrLBofQmFKMFr1WGbbaYS/XzXraeZ+TDBigIJYuWxb67HyYWZvQnmh4yUUOOXj347mhtq5BrezYs683g5XoUoMPCD+/61n3u0q2J1/4o0VDCWpubg41R/7Q74AkKVbd03uFp1M9Qra8QipKI/oMc+8VqM361/gIIAAAAEXnLzMAOfHScYD460wvHacgR6uifhvVx10GACW91qy3LAIAADqQmVEHRm1sRwcAQEKe028cdUhU1nIfANqc8+0A8fcyzrcDAAAdybyon0T9ux0dAAAA5EFZVfWlPoiiUu/kc6/02A1oscuuvcMsjdp295FhyetbhtCYUswuPHd71876PkA55EADBiiIux943JxNaAOGHxVWNjW5yCEHE5+eEWrrGtTKqo/5sTmsxHf2uHvc7yrpXp75gYVDCXp91tuhy4AavwOSpFgN77tbmFFeEbJSEbqix0D3XYEqq6q+zIlCAAAAis1fZQBy4qXjAPHXmV46TiGt+scb9VGV7jYAKMm1Zr3lEAAA0AG94e+NAAAk4Bn9sKhXLO8BoN3wvAkg/n7G+XYAAKAjmht1YdS/2tkBAABAK3Sqqr7IB1FU6l1zs3d1AC3z2qy3QtdBe5ulUQ/fURVCY0o5lH28t2tnAy1YuNigAfJu5CFnmLEJbWztHS5wyMH8hUvDdRMmh9q6BrWy7apPNoeV+A448XL3u0q+xnc/s4AoQaddcI3fAUlS7H7Yc3DIlldIBe8PFd3CFlUZ910BKktXv+lEIQAAAMXmLzIAOfHScYD460wvHacYlkeNjypz1wFASa01vagHAADoyKZEDbW7AwCggz2bHxz1tOU8ALQ7zrcDxN/XON8OAAB0ZKs+UjAmalM7PAAAAGiBzaqqf+CDKCr1Jj35vMdsQM6WLVsedtnPh9NXtf+hw0JoTKkF7Vazu2toPb35zgeGDZBXL7+WNV8TWuf+NeHdDz5xkUMOnpv2Tqita1Ae2nK7A81iJb5t9/qe+10l3w33PBc++fM8i4gSM/vPc0P3IX7rJUnx6lKVCRO27BOy5RVSwdt/q13cdwWqrF912qlCAAAAislfZABy4qXjAPHXmV46TjEtihob9R/uPgAoibVmveUPAACQAI9FVdnlAQDQzp/J9/ZcHgDaNefbAeLvb5xvBwAAkuDdqOOiNrHTAwAAgBxsVjXqJB9DUan31jsferwG5OySa243Q6M2H5AJsx7vHUJjSi3oF1dt7TpaTw0vTDdsgLw66dwrzdeEtu+x57rAIQfreUjzAAAgAElEQVQrVzaFm++dGmrrGtTKLhv/sDmskqjLwL3DVbc/6b5XyXdL9Ps5f+ESi4kSU3vrb/wWSJJil07vEV5MbRmy5RVSQRvfrco9V6jS1Rc7VQgAAEAx+WsMQE68dBwg/jrTS8dpC3Ojzoza1F0IAIlea/p4JwAAkBRNUXdEbW63BwBAO3sW3zXqrtVrVgCg/XK+HSD+Psf5dgAAIEmmRe1mtwcAAAAxlfWr/o6PoaiU22LrfcKKlSs9VgNy8srrjWHzAaPN0ajzzt4+hMaUWthnL3SPrqWMa2kd1T/4hIED5M2cufNC+Tb7mq8J7d6HnnKRQw5mvf1pqK1rUB467eLbzWGVTKdfcof7Xoqqe+jlsGz5CguKErI8+v+9ffUJfgskSbE7oPfOIVteIRW01ypSoXt6L/dcQco0OlUIAABAMflrDEBOvHQcIP4600vHaUvvRx0etZG7EQASudast9wBAAASZlnUNVHfsusDAKCNn8H/S9SFUUss0wGgQ3C+HSD+fsf5dgAAIIkei+pr1wcAAAAb0Cmd2deHUFTK7bLfyR6lATlZtmx52Hnfk83QqN477BnmvtwthMaUWlHmgN1cT+vo5zf/2tAB8ubqm+4xWxNajx0OCouXLHWRQw7qH5kWausalIcO/f6VZrFKpn2+e4n7Xlrd756ZEZqbrSlKycNPTPFbIEnKqXE9BoZseYVU0I7uvaP7rUB1HlDdx8lCAAAAisVfYgBy4qXjAPHXmV46TnvwQtT27kgASNxas94yBwAASKg5UadGfd3uDwCAIj973zjq8KhPLcsBoENxvh0g/r7H+XYAACCpmqJ+FfW/dn8AAACwDp2rRo3wIRSVckd+/xKP0YCcXHz1bebn6u68flAIjSm1snGXDHY9raNzLxtv6AB5sWLlyjBwxFFma0L74SU3uMghB5/8eX6orWtQntr9kLPNYpVMA/f4rvte+lLPTXvHwqLE7HfceX4PJEmxK09nwqTKXiFbXiEVrDu79XO/Fa6LnCwEAACgWPwVBiC3P9365QCIvc700nHak4lRFe5MAEjMWrPe8gYAAEi4Wf42CQBAEZ+7D4t6zTIcADokz5AA4u99nG8HAACSbmHUhVHftAsEAACANXQakNnGR1BUyl1wxc0enwGxvfxaNmw+YLT5GTV87+Fh5azKEBpTamWvPLSVa2odnXLeVQYPkBcTH51sria46TPedJFDDiY1zAq1dQ3KU+ndjzaLVTJ16V8Txv3ycfe+9KVmvPWJxUUJaXzrvdB14N5+EyRJsRvSb3iYXlEZsuUVUkGaEbVVek/3WwEqq6p+w8lCAAAAisVfYQBy4qXjAPHXmV46TnuzJOrSqH92hwJAh19r1lvaAAAAJWJSVHc7QQAACvS8vWfUY5bdANChOd8OEH8P5Hw7AABQKt6N2tdOEAAAAL6kc9WoSh9CUSl3S91Ej82AWJYtWx523ucks3N1U+/vE0JjSnmoaVZl6DvUx+7W1tGnX2b4AHmx77HnmqsJbdj+p7rAIQfzFiwJ102YHGrrGpSHrvnV06HLgNHmsUqqU39ym/tf+lLX3z05fDT7c4uMEjLm4uv9HkiScurkXtuHbHmFVLBO6L29e61AfbuqpqfThQAAABSDv8AA5MRLxwHirzO9dJz26qOow6M2cqcCQIdda9Zb0gAAACVkedQ1Uf9mRwgAQJ6es/9z1IVRSy23AaDDc74dIP5eyPl2AACg1DwVtZUdIQAAAES69qv+dx9BUSn36DMvelwGxHLRuFvNzdWdeNLQEBpTymPHHb+za2stHfy9CwwfoNWyb75npia4m+960EUOOXjmpbdCbV2D8tS54+rNYpVco4/9sftfWqOb730+fL5giYVGiZgzd17ouePBfhMkSbHrHPXLbumQLa+QClL9ln3cawWqLF19vtOFAAAAFIO/wADkxEvHAeKvM710nPbu6ag+7lYA6JBrzXpLGQAAoAR9HHV41EZ2hgAAtOIZ+6io9y2vASAxnG8HiL8fcr4dAAAoRSuiron6NztDAAAASt1GZenMch9CUanW+NZ7HpUBG/TS9GzYfMBoczOqcttR4cPneoTQmFIeu/bybVxfa6n6O2MMIKDVxlx8vZma0LbYep+/fdAeiGfJshVhfP2UUFvXoDx15Fk/N49VcvUffqz7X1pLdQ+9HJYtX2HBUSKu++W9fhMkSTnVO71nmJLqHrLlFVLem1meCun0Hu61AlSWrp7uaCEAAADF4K8vADnx0nGA+OtMLx2nI/i/F0J+y10LAB1qrVlvGQMAAJSwZ6L62h0CAJDjs/V+UQ2W0wCQOM63A8TfFznfDgAAlLJPoo6L2tgOEQAAgJLVqar6Ux9CUSnWuX9NWLR4iUdkwHotXrI07FBzgrm5umvGbhtCY0p57qn6fq6vtbTbAacaQkCrzJu/MGy53QFmakI7YcwVLnLIwR/eeD/U1jUoj4087FzzWCX5TPWKWx81A6S1NPGpN0Jzc7NFRwlYsnRZGDTiaL8LkqScyvTZNcwsT4VseYWU977fa4j7rECV9a3p5nQhAAAAheavLwA58dJxgPjrTC8dpyP5NOowdy4AdJi1Zr3lCwAAUOJWRF0T9W92iQAAbOCZ+reiro1aaRkNAInkfDtA/P2R8+0AAAAhTI7qY5cIAABASSpLV0/3ERSVYulhR3gsBmzQBVfcbGaubvDwkWHpG5UhNKaU5/78YnfX2FrabtR3DSGgVX5x5wPmaYKb8ofXXeQQ08qmpnDrfS+E2roG5bF+ux1tHqskO/miW8wAaR1NefUdC48SUf/gE34TJEk595Me24RseYWU9+6v3Mo9VqjS1ec4XQgAAECh+csLQE68dBwg/jrTS8fpiJ6J6uEOBoB2v9ast2wBAAD4m4+jDrdTBABgHc/TR0W9b9kMAInmfDtA/D2S8+0AAABfWBF1TdS/2C0CAABQUsqqMg/5CIpKscwRP/BIDFivl6Znw+YDRpuZq3vkrnQIjSkVqP677Ok6W6P0sCMMIqDFmpubww41J5inCW3H0d/72/9jIJ4Zb30aausalMeuuv3J0KV/jZmskqz6qIvMAWk9zXjrE4uPEtDU1ByGH3Sa3wVJUk5tXpUJ9225VciWV0h5b+t+I91nhekVpwsBAAAoNH95AciJl44DxF9neuk4HdXyqLFRm7qTAaDdrjXrLVkAAAD+wcSornaMAACsfo7eKepey2QAKAnOtwPE3ys53w4AAPCP/hQ1wo4RAACAklGWztzoAygqxY7/wU89CgPWafGSpWH76hPMy9UddMSuITSmVMAOOGxX19oabbXToYYR0GJPTn7ZLE1w4++430UOOah76OVQW9egPDbmpxPMY5Vs/YYdZQ5I6+n6uyeHj2Z/bgFSAp56zr5TkpR72/QbEV6tqAzZ8gopr53Va7B7rEB1rhpV6YQhAAAAheSvLgA58dJxgPjrTC8dp6P7Y9Su7mYAaJdrzXpLFQAAgK9YFDUm6ut2jgAAJfv8/OtRp0YtsDwGgJLhfDtA/D2T8+0AAABrNzGqs50jAAAAiVeWrj7fB1BUiv3oips9AgPW6fyf3mRWrq7rgOqQfbx3CI0pFbBTThnqeluj9LAjDCOgxQ4/5SdmaUIr32bfMGfuPBc5xPTuR38JtXUNynOHn36VmazS/Zh4/5pw+U2PmAXSerr53qlh3oIlFiIl4KATLvDbIEnKueN67RCy5RVSXptU2cv9VbjGOGEIAABAIfmLC0BOvHQcIP4600vHSYLmqJui/sNdDQDtaq1Zb5kCAACwTi9HDbB7BAAouWfnW0e9ajkMACXH+XaA+Psm59sBAADWbW7UcVEb2UECAACQWGVVmSN9/ESlWO2tv/H4C1irF6fNDF0G1JiVq7vw3O1DaEypwF1ywXautzXqv/uRBhLQIu9+8Inf8gR38rlXusghB/c98VqorWtQntv94DFmskq6Ey+42SyQNlDdQy+HZctXWowk3IzGd+w/JUkt6hfdqkK2vELKa9v1G+H+KkBlVdUvOmEIAABAIfmLC0BOvHQcIP4600vHSZJPo/Z2ZwNAu1lr1lueAAAArNeKqLFRm9pFAgAk/pn5P61e+3nJDACUJufbAeLvn5xvBwAA2LCGqC3tIgEAAEikTv0yO/sAikqxex54wmMv4CsWL1kahmSONydX12+nPcO8V7qF0JhSgbv56q1dc2u09chjDCWgRX585a3maIJ7YdpMFznENPsvC0JtXYMK0Fa7fMdMVkmXOfpCs0CK0UPPzgzNzdYkSXfSuVf6bZAk5Vyv9F5hSqp7yJZXSHnr3J7bur8KU/P/9qvewilDAAAACsVfWwBy4qXjAPHXmV46ThLVR/23OxwA2nytWW9ZAgAAEMubUTvaSQIAJPZ5+eAoL0YEgNLmfDtA/D2U8+0AAADxLI4aE7Wx3SQAAACJUjawuouPn6gUe3rKKx55AV9x3thfmJFfqu6GgSE0plSEJt5e5Zpbo8F7HWcoAbn/VXfJ0tBr6CHmaELbed+TXeSQg4eenRlq6xqU58b98vHQuX+NuaySrv+IY80DKWZTXn3HoiTh3v9odijfZl+/D5KknKvus0uYVV4RslKeejLVw71VoMqqMqc7ZQgAAECh+GsLQE68dBwg/jrTS8dJqtlR+7rLAaBN15r1liQAAACxNUWNj/pnO0oAgMQ8J/9m1NiolZa7AFDynG8HiL+Xcr4dAAAgN89FdbejBAAAIEk2KktnFvsAikqtGY3veNQF/IMXp80MXQb4MPr/NXLv3UPTrMoQGlMqQs/+pp/rbo22rz7BYAJyVvfbR83QBHdL3UQXOcT0l88XhesmNITaOuW7My69w0xWydelf00Y98snzAQpZjPe+sTiJOEuGner3wdJUosa22NQyJZXSHlr5767u7cKUTrzrCOGAAAAFIq/tADkxEvHAeKvM710nKRb9Q9MytztANAma816SxEAAICcvR21k10lAECHf0a+XVTW8hYAWM35doD4+ynn2wEAAHK3OGpM1CZ2lgAAACRCWVXmdR9AUak1Z+48j7mAv1u0eEkYkjnefFxd5/7VYeoDfUNoTKlITf5tX9feGg0dfaLhBORsxEGnm6EJLbXtfuHzeQtc5BDTI5Nnhdq6BhWgA04cay5LUWdceoeZIMXshrufC5/8eb4FSoKt2qv03ukQvw+SpJwrT2fCpMpeIVteIeWlC3ps494qSJmmroP2+LZThgAAABSCv7QA5MRLxwHirzO9dJxS8FnUaHc8ABR9rVlvGQIAANAiTVFXRG1qdwkA0OGejf9T1LjVazoAgP/jfDtA/H2V8+0AAAAtNzmqwu4SAACADq9TVeY+Hz9RKdV10N6hqanZ4y3g7869bLz5+KVOOWVoCI0pFbEp9/V17a3RsP1PNZyAnEx9ZYb5meBOu+AaFznENHfeonDdhIZQW6dCNKTmZHNZitr/e2PNBCmHbv3tC2Hh4mUWKgl23W2/9fsgSWpRO/UdHt4oT4VseYXU6p6q7OG+KlCbpauPdsoQAACAQvBXFoCceOk4QPx1ppeOU0rqo/7DnQ8ARVtr1lt+AAAAtMobUVV2mAAAHea5+FZRr1rGAgBr4Xw7QPy9lfPtAAAArbMoatVHHTeyywQAAKDDKquqvtTHT1RK9d/9SI+1gL977sXXQuf+Nebj6roNHhU+ndo9hMaUitjU+/u4/tZov+POM6CAnJww5grzM8G9/FrWRQ4xPTolG2rrGlSAfn7Xs6Fi6/3MZSlqcOZEc0HKsd88Oj2sbGq2WEmopcuWha1HHuM3QpLUos7ouV3IlldIeWmnvsPdV4UonXnQKUMAAAAKwV9ZAHLipeMA8deZXjpOqXk3aid3PwAUZa1Zb+kBAADQasujLozaxE4TAKDdPg/fOHzxYcJllq8AwDo43w4Qf4/lfDsAAEB+TIoqs9MEAACgQyqryhzo4ycqpXbZ72SPs4C/WbR4Sdhu1HfNxi9V+9NtQ2hMqci9+GAf198aHXfW5YYUENvsP88NXQftbX4mtGH7n+oih5g+X7AkXD9hcqita1ABOu+q35jL0uq6Dton/PyOp80GKccef77RgiXBfj3xSb8RkqQW1aUqEyZs2SdkyyukVvejHtu6rwpQWVX10v/qnvlXJw0BAADIN39hAciJl44DxF9neuk4pag56pqoTU0BACjoWrPesgMAACBvpkRV2m0CALS7Z+FbRD1juQoAbIDz7QDx91nOtwMAAOTPZ1E1dpsAAAB0ON+uqunp4ycqpUYf+UOPsoC/+eElN5iLX2rIyJFh2RuVITSmVOSm3t/HNbhGq+5PgLjG3TjB7Exwt9dPcpFDTI9P/WOorWtQgTryzJ+by9KXOnvcPWaD1IJef/MTi5aEampqDiMOOt1vhCSpRaXTe4Q/VHQL2fIKqVU9merhnipU6cy+ThoCAACQb/7CApATLx0HiL/O9NJxStn0qD4mAQAUbK1Zb7kBAACQV/OjjrLjBABoN8/Bj4laYJkKAMTgfDtA/L2W8+0AAAD5d0vUv9p1AgAA0HHst98mZenMYh8/Uan0nVMv9ggLCJNfnB46968xF7/Uo3XpEBpTaoN+96sq1+AaXV57p0EFxLJixcowYPhRZmdC6zbkgDB/4SIXOsQwf9HScMPdk0NtXYMK1LCDxpjN0pc69PtXmg1SC7o++r3+aPbnFi8J9fSUV/xGSJJa3EFb7RSy5RVSq9ux7+7uqQJUls7c4aAhAAAA+eavKwA58dJxgPjrTC8dp9QtiTo1aiMTAQDyvtast9QAAAAoiHuj/sPOEwCgzZ5//1tUnWUpAJAD59sB4u+5nG8HAAAojHeitrXzBAAAoMPolM685OMnKpVOOe8qj6+gxM1fuChss8cxZuKXP9J3xK4hNKbURt127SDX4Rr94s4HDCsglvsmPWtuJrizfnKdixxieurFN0NtXYMKWM8dDzWbpS+1835nmA1SC7v1t1PDgkVLLWAS6qATLvA7IUlqcdd16x+y5RVSqzq/57bupwJUVpX5a69e+/0/ThoCAACQT/6yApATLx0HiL/O9NJx+ML9Uf9lKgBAXtea9ZYYAAAABfNu1BC7TwCAoj/73jrqLctRACBHzrcDxN93Od8OAABQOMujLoza2A4UAACAdq8snRnv4ycqlc7/6U0eXUGJO+PCa83DL9V1YCa89VSvEBpTaqPGXTLYtbhGv574pGEFxFL9nTHmZoKbPtO/L4U4FixaGm64e3KorWtQgbr0xofMZWmNttzuwHDtXc+aEVILu2fStLBiZZOFTALNaHwndBlQ47dCktSiuqX3Ck+neoRseYXU4h5P9XQ/FaiydGaYk4YAAADkk7+sAOTES8cB4q8zvXQc/n/vR+1oMgBA3taa9ZYXAAAABbUi+MgNAECxnnlvFHVq+OJDgwAAuXK+HSD+/sv5dgAAgMJ7LOrbdqEAAAC0a2VVmaN8+ESl0s9uqPPICkrY48/+wSxco5/8aEgIjSm1YeeM2cG1uEar7lWADXkj+yczM8HtfuD3XeQQ09N/eCvU1jWogJ1w/k1ms7SWLrz2fjNCakVPTP2jhUxCnXzulX4nJEktbkSfYWFGRSpkyyukFrdD3+Hup0KUrq510hAAAIB88lcVgJx46ThA/HWml47DP1oZvvgI7SYmBAC0eq1Zb2kBAABQFE9EldmJAgAU7Hn3/0RNsuwEAFrB+XaA+Hsw59sBAACKY3bUcDtRAAAA2q1vpzO9fPhEpdIv7nzA4yooUfPmLwwDRxxlFn6p9M57hvmvbhlCY0pt2LHH7+R6XKPsm+8ZWsAGnXHhtWZmgrvr3t+7yCGG+QuXhBvunhxq6xpUwDJHXWg2S2vpmB9eZ0ZIrWx640cWNAn0wcefhYpt9vNbIUlqcT/psU3IlldILe7cntu6lwpQWVX1h1/72tc2ctoQAACAfPFXFYCceOk4QPx1ppeOw9o9FbWZKQEArVpr1ltSAAAAFM2nUcPsRgEA8v6se3j44oOCAACt4Xw7QPx9mPPtAAAAxdMU9eOoTexIAQAAaIcu2Lgsnfncx09UCt39wOMeVUGJ+t4Pf2YOrjkTxw8MoTGlNm6nvUa4Hr9U5/41YdHiJYYWsF5//XxBSG3rA+VJrcf2B4WFi/wWQByPTWkMtXUNKnBVw48xn6W1NOLQc8wIqZVdP2Fy+HD25xY1CfTjK2/1WyFJanFbVGXCpMpeIVteIbWox1I93UuF+ltmeq9BzhoCAACQL/6iApATLx0HiL/O9NJxWLfPgo/QAkBr1pr1lhMAAABF1Rw1Nmpju1IAgFY/494oakzUSstMACAPnG8HiL8fc74dAACg+J6K+rZdKQAAAO1Op6rqR334RKXQg49O9ogKStCkJ6eagWs0cu/dQ9OsyhAaU2rDlr1RGboOcD1+uardvmNoARt0w+33mZkJ7uxLb3CRQwx/+XxRuG7C5FBb16AC9tNbHg2d+9eYz9Ja6rvrkeaElIduvvf5MG/BEoubhPnr5wtCr6GH+L2QJLW4nfoOD2+Up0K2vEJqUUP6DXcvFaCyqswlThoCAACQL/6iApATLx0HiL/O9NJxWL9VH0i7MPgILQC0ZK1ZbykBAADQJp6I+h87UwCAFj/f/q+oSZaVAEAeOd8OEH9P5nw7AABA2/gwaoidKQAAAO1KWbr6fB8+USn06DMvejwFJWbO3Hmh366Hm4FfqnP/6vDy77YKoTGlNu61R3q7Jteo5sgfGlzAejU1NYfBex1nZia412e97UKHGB5+dmaorWtQgTvpglvMZmmdzxdqws9ufcyskPLQ3ZNeCStWNlngJMy1t/za74UkqVWN6bldyJZXSC3qnJ7buo8K0wwnDQEAAMgXf00ByImXjgPEX2d66TjEMzHqP0wNAMhprVlvCQEAANBm3o/a1u4UACDnZ9sDo96xnAQA8sz5doD4+zLn2wEAANrOiqgxURvZoQIAANAubNZv1BAfPVEp9Mzz0zyaghJz7Jljzb81Ou20HUNoTKkddM/4ga7JNTr1/KsNLmC9fv/0C+Zlght1+A9c5BDD7DkLQm1dg4pQ5qgLzGdpPZ1x6R1mhZSnHp2StchJmEWLl4T0sCP8XkiSWtzmUfdtuVXIlldIOfdIZU/3UYEq65Pp7rQhAAAA+eCvKQA58dJxgPjrTC8dh/jei9ra5ACA2GvNessHAACANvW3j9zYoQIAxH6ufVzUMstIAKAAnG8HiL83c74dAACg7d0f9e92qQAAALS5AQOO+0anqswCHz5R0pv6ygyPpKCE1D/4hNm3Rt0HjwqzX+gRQmNK7aCLztvedblG426cYHgB63Xw9y40LxPcqvUbEOO0yROvh9q6BhWhvrseZT5L6+nAk35qVkh57NXshxY6CXPTXQ/6vZAktaqBfUeGaeWVIVteIeXc4L4j3EcFaLOq6h84bQgAAEA++EsKQE68dBwg/jrTS8chN0uijjQ9ACDWWrPe0gEAAKBduDPqm3aqAADrfJ79z1F3WzYCAAXkfDtA/D2a8+0AAADtQ2NULztVAAAA2lxZunqSD58o6U2f8abHUVAiPpk9J/QaeojZt0bX/WzbEBpTaifVHLib63KN7n3oKQMMWKc/vfdR6DKgxrxMaH12PiwsXbbMhQ4b8NHsz0NtXYOK0NibHjGfpQ204z6nmRdSHrtuwuTw3sdzLXgSZNUeZ9CIo/1mSJJa1fd6bx+y5RVSzp3Zazv3UCFKZ6Y4aQgAAEA++EsKQE68dBwg/jrTS8ehZcZHfcMUAYD1rjXrLRkAAADajVejtrBbBQD4yrPsLlEvWS4CAAXmfDtA/H2a8+0AAADtx4Kove1WAQAAaFNl6eozffhESS/75nseRUEJaG5uDoeedJG5t0ZDRo4My96oDKExpXbQ/Fe3DF0HZlyba/RG9k+GGLBOP7riZrMywV127R0ucojh14++GmrrGlSETjhvvPksbaAttzswXHvXs2aGlMdu/s3z4fMFSyx6EuSO3zziN0OS1Ko6R/2qW7+QLa+QcuqByt7uoYKUadp8wOjNnDYEAACgtfwVBSAnXjoOEH+d6aXj0HINUf9rkgDAOtea9ZYLAAAA7cqcqF3tWAEA/v4ce8eo2ZaJAEARON8OEH+v5nw7AABA+9IcNTZqY7tWAAAA2sS305lePnqipPfO+x97DAUl4Pb6SWbeWnri7nQIjSm1kx6+o8p1uUYV2+wXVqxYaYgBa7Vg4eLQY4eDzMuEtvmA0eH9j/wbVNiQtz+YE2rrGlSk9jj8PDNaitHF1080M6Q8d/ekV8KKlU0WPwmx6nnXdqO+6zdDktSq+vbbI/yholvIlldIsZsVVRVdO+6hAtQvc6zThgAAALSWv6IA5MRLxwHirzO9dBxa54OoQaYJAKx1rVlvqQAAANDurIgaY9cKAHiGHY6LWm55CAAUifPtAPH3a863AwAAtE+/i/qWnSsAAABtoiydecuHT5TkPpk9x+MnSLj3Pvw0dB9yoJm3RocfvUsIjSm1o35w5g6uzTXa67CzDDFgnW69+3dmZYI79syxLnLYgObmEOoeejnU1jWoSPXe6XAzWorRCeeNNzOkAvTYlEYLoASpf/AJvxmSpFZ32FZDQ7a8Qsqpk3pt7/4pROnqB5w0BAAAoLX8BQUgJ146DhB/neml49B6S6KOMFEA4CtrzXrLBAAAgHbrzqhv2r0CACX47HrTqFstBwGAInO+HSD+vs35dgAAgPZr1ccQetq9AgAAUHSd0tW1PnyiJPfZnL969AQJ1tTUHPY55hzzbo22GJQJbz3VK4TGlNpRg4fv4fpco3MvG2+QAWvV3Nwcho4+0axMcM+9+JoLHTZgxlufhtq6BhWpi294yHyWYpY5+kJzQypQr//xY4ughFjZ1GRfK0nKSzd0rwrZ8gopdvds2ce9U5gWdj7N3XgAACAASURBVB069J+cNgQAAKA1/AUFICdeOg4Qf53ppeOQP5dHbWyyAMDf15r1lgcAAADt2vNR37aDBQBK6Ln1ZlEvWgYCAG3A+XaA+Hs359sBAADat1UfeN7dDhYAAICi6pSuGemjJ0pyc+bO89gJEmz8HfebdWvpkh9tF0JjSu2ot57q5dpcS3c/8LhBBqzV01OmmZMJbud9TgrNzc0udFiP5StWhlvveyHU1jWoSB179vVmtBSzgXt819yQCtT1d08OH3/m7xpJ8eCjk/1uSJJaXff0XuHZVPeQLa+QYjWjIhV6p/d0/xSidPUeThsCAADQGv56ApATLx0HiL/O9NJxyK+Hov7VdAGAv6016y0NAAAA2r0Po/rbxQIAJfDMuk/Ue5Z/AEAbcb4dIP7+zfl2AACA9m9l1Ml2sQAAABRN16FD/6lTunqeD58oqc2Z6+OTkFRvvvNBSG27n1m3Rumd9wzzp3ULoTGldtTPLh7s+lxLs9581zAD1uo7p15sTia42+snuchhA6ZOfzfU1jWoiO1+8BgzWorZ5oP2Dtf86mmzQypQt93/Yli8dLkFUQI0NTWH3Q441W+HJKnVjd5qlzCrvCJkpZgd03tH905BylzvtCEAAACt4a8nADnx0nGA+OtMLx2H/JsetbkJA4C1Zqi3LAAAAOgQFkSNspMFABL8vHpElBfNAwBtyfl2gPh7OOfbAQAAOo7xUV+3mwUAAKAoyqqq7/TREyW1uZ/P96gJEmjFypVhr8POMufW0q9vGhBCY0rtqOZsKgwePtL1uUaVg/f/270MsKb3P5odNh8w2qxMaD13PDgsXLTEhQ7rsWDR0nDjPc+F2roGFalr73o2bDnkQHNayqFzxtWbH1IBu/+J10Nzc7OFUQL8/ukX/G5IkvLSuO4DQ7a8QorVbd3S7ptClM68/7WvfW0jpw0BAABoKX85AciJl44DxF9neuk4FMZHUQNNGQBKfK1Zb0kAAADQYax6odsYu1kAIIHPqk9dvdYBAGhLzrcDxN/HOd8OAADQsTwS9S07WgAAAApus/Soah8+UVKb+/l8j5kgga65ud6MW0uj9t89NGdTITSqPTXlvr6uz7W0zzHnGGbAWl007lZzMsFdcMXNLnLYgEefy4baugYVsXPG2WNKufadM642P6QCN/W1dy2MEmKvw87y2yFJanWp9KjwZKpHyJZXSBvs9fJU6BZdM+6dQjSqr9OGAAAAtJS/mgDkxEvHAeKvM710HApnYVSNSQNACa816y0HAAAAOpxfRH3DrhYASMAz6q9H1VreAQDthPPtAPH3c863AwAAdDyvRXW1qwUAAKCgug4d+k+d0tXzfPRESeyvny/wiAkSZkbjO2GLrfcx49aoy4BMmPZQnxAaU2pnnXbajq7RtXT1TfcYaMBXLFq8JPQaeog5mdA2HzA6vPfhpy50WI9P58wPtXUNKnIHnHi5OS3l2G6H/ND8kIrQ2x/MsUBKgGeen+a3Q5KUl/bqMyzMKq8IWSlGh/beyX1TiNLV5zhtCAAAQEv5qwlATrx0HCD+OtNLx6GwmqLONG0AKNG1Zr2lAAAAQIf0+6h/s7MFADrw8+l/j3rcsg4AaEecbweIv6dzvh0AAKBj+iRqkJ0tAAAABVWWztzhwydKYp/PW+DxEiTIihUrw8iDTzff1tIZp+0YQmNK7axFr1WG7oNHuUbX0iuvNxpqwFfc8ZtHzMgEd+yZY13ksAH3PjY91NY1qMgN2uMEc1rKsT67fsf8kIrQTb95PsxbsMQiKQH2OeYcvx+SpLx0efdBIVteIW2wG7pXuWcKUTozxUlDAAAAWspfTABy4qXjAPHXmV46DsXx86iNTR0ASmytWW8JAAAA0GG9HtXZ7hYA6IDPpsuiplnOAQDtjPPtAPH3dc63AwAAdFwLo/ayuwUAAKBgOvevHu7DJ0pi8+Yv9GgJEmRs7R1m21rqsd2o8NkL3UNoTKmdNWH8QNfoWuq548FhZVOToQZ8xa77nWJOJrg/vDrLRQ7r8cd3Pwu1dQ0qcj+79bHQpX+NOS3lWOfovhn3yyfMEakI3f3wK2HFSs9ROroXp830+yFJykup9KjwZKpHyJZXSOttWnllKE9n3Dd5L9P0P1uN+l+nDQEAAGgJfzEByImXjgPEX2d66TgUz31R3zR5ACihtWa9n38AAIAO7cOovna4AEAHei7dO+o9yzgAoB1yvh0g/t7O+XYAAICObWXU8Xa4AAAAFMZ++21SVpX5wIdPlLT++vkCj5UgIabPfCt0HbS32baWxl+5dQiNKbWzmrOpsHNmhGt0LR19+mWGGvAVk1+cbkYmuD0PO9NFDus7EbKyKdz+wB9CbV2Ditz3fnSTOS21sDE/nWCOSEXqyRfetGBKgENOvMjvhyQpLw3vu1uYWZ4K2fIKab3t02cX90wBKkuPOsJhQwAAAFrCX0sAcuKl4wDx15leOg7F9XzUf5s+AJTIWrPeTz8AAECHNzdqR7tcAKADPJMeHDXH8g0AaKecbweIv79zvh0AACAZxkZtZKcLAABA3pVVVV/mwydKWp/NmetxEiTAsmXLw877nmyuraXtR44My96oDKExpXbWpDurXKPr6LZ7HjbYgK846rRLzcgE98DvG1zksB4vzfgg1NY1qA0acdi55rTUwo4442pzRCpiM9/+1KKpg5s+863QuX+N3xBJUl66tMegkC2vkNbbld0Hul8KUFlV9a+dNAQAAKAl/LUEICdeOg4Qf53ppeNQfG9GVZpAAJTAWrPezz4AAEAiLI06wE4XAGjHz6P3jlpi2QYAtGPOtwPE3+M53w4AAJAct0V9w24XAACAvCrrW9PNh0+UtD74+DOPkiABLvzZLWbaOnrynnQIjSm1wzIH7OYaXUd/eu8jgw34B6vW7ZsPGG1GJrSBI44KK1asdKHDOixavCz84tdTQm1dg4rctXc9G7pvf7BZLbWwEYeeY5ZIRezGe54Lf5670OKpgzv69Ev9hkiS8lJFelR4PNUzZMsrpHX2fEW30KUq457Je5kFlZUjNnXaEAAAgFz5SwlATrx0HCD+OtNLx6FtfByVNoUASPhas95PPgAAQGI0RZ1stwsAtMNn0aetXqsAALRnzrcDxN/nOd8OAACQLA9F/bMdLwAAAHnVqap6sg+fKEm9/e5HHiNBBzf15TdClwE1ZtpaOvKYXUJoTKkd1nBvP9foOhqSOd5gA77ikqtvMyMT3A233+cih/V49LlsqK1rUBt0/lX3mtNSK+q329FmiVTkbn/gxbBk6QoLqA5s1pvvet4tScpbu/XZLcyoSIVseYW0zoZF14n7Jf+VpTPDnDQEAAAgV/5SApATLx0HiL/O9NJxaDsLonY1iQBI8Fqz3s89AABA4oy14wUA2tFz6DGWZwBAB+F8O0D8vZ7z7QAAAMnzYtR/2/UCAACQN537ZQ7x4RMlqVUfJwQ6rkWLl4QhmePNs7W0xaBMePvpXiE0ptQOO+CwXV2n6+jy2jsNN+AfLFm6LGy106FmZELrscNBYf6CRS50WIePPpsXausa1EYdcsoVZrXUirr0rwlX3f6keSIVud89MyM0N1tHdWQnnv0zvyOSpLz14x7bhGx5hbTOftRjW/dKASqrqr7aSUMAAABy5a8kADnx0nGA+OtMLx2HtrU0qsY0AiCha816P/UAAACJdH3Uxna+AEAbPn/eKOpqyzIAoANxvh0g/p7P+XYAAIBkmhHVyc4XAACAvKisHLFpp6rMbB8/UVKaPuNNj4+gAxtz8fVm2Tq69MLtQmhMqR320sQ+rtH1NOvNdw034B/U3feY+Zjgxt04wUUO69DU3BwmPPxKqK1rUBu17V7fM6ulVnb2uHvME6kNeumN9y2mOrC33/0odB24t98RSVJe2qIqE36f6hmy5RXSWnsk1cu9UoDK0pm3nDQEAAAgV/5KApATLx0HiL/O9NJxaHsroo4wkQBI4Fqz3s88AABAYt0V9Q27XwCgDZ49fz3qNssxAKCDcb4dIP6+z/l2AACA5HonqtLuFwAAgLwoq6q+1MdPlJRenDbToyPooJ6d+mro3L/GLFtL6Z32DPNf3TKExpTaWc3ZVNhrv91dp+to6OgTDTfgK3Y74FQzMqH12P6g8NfPF7jIYR1emfVhqK1rUBt1+c2/D13sOaVWd+RZPzdTpDbougkN4f1P/mpB1YGdceG1fkckSXlrpz7Dw4zyVMiWV0hrbVC/ke6VAvTtqpqeThoCAACQC38hAciJl44DxF9neuk4tA/NUd83lQBI2Fqz3k88AABAov0u6pt2wABAEZ87bxp1n2UYANABOd8OEH/v53w7AABAsn0S1dcOGAAAgFb7dtXeXTulMyt9/ERJaPKL0z02gg5o/oJFYdCIo82xdfTbWwaE0JhSO+w3Nw9wja6ncTdOMOCAfzD15TfMxwR36c9/5SKHdVi4eFkY/+spobauQW3UsWdfb1ZLeaj6qB+ZKVIbdctvp4YFi5ZaWHVQ7380O3QdtLffEklS3rqgxzYhW14hrbVTeg5xnxSgsn6Zs5w0BAAAIBf+QgKQEy8dB4i/zvTScWhfxppMACRorVnvpx0AACDxnon6ll0wAFCEZ87fimqw/AIAOijn2wHi7/+cbwcAAEi+uVHb2QUDAADQap3SmXt8/ERJ6PFn/+CR0f/H3p24SVXeCf+Oybwz72SW30zmzWTSoNhVrCJSDSjuQgSVCN2AIi4xajQaY1ziHpcYNa5xt3GPEpdG2n3fUWkEFFEEgW5RUVABFQVk6/X5FV5JJkSWU921dt33dX3+AKsP3/M8px5PQQE64ZyrzbCNVD56cGipjYdQp3xr9cwuYYfBP3adbqK69xYYcMB6jj7tMvOxndZ5pwPCZ0uXuchhI56ZNDdUVtUohw3Y/2TzWkpDex5wYri5erK5IuWo+5+dEZqbWyyuCtSp51/vXiJJSltbl5WHZ+I9Qm1pTPpG93bp5d9JBipJVLzslCEAAACp8O0IQEq8dBwg+jrTS8ch/1xmOgHQTtaa1W7rAAAARWHdS1u/ZycMAGTwefP/S/aGZRcAUMCcbweIvgd0vh0AAKA4fJVsgJ0wAAAAbdKx9/Ad/PiJ2kMPPTXR4yIoMM+89Kr5tZG27FseZjy5bQh1ceVhl1+4s+t0Ew064EQDDljPx4s/C536jTQj22mXVt7lIoeNzb8ly0JlVY1y2NV/mhA6bb+feS2loa132C/Uvr84jBlntki5atIb71tgFagPFi6yL5YkpbUB2+0dZpfGQ21pTFqv2bF46NF7qH8n6S5R0dipd8V/OGkIAABAVL4dAUiJl44DRF9neuk45Kcbkm1hSgFQ4GvNard0AACAojEj2ffthgGADDxr/u9kb1luAQAFzvl2gOj7QOfbAQAAiseqZIPthgEAAGiTkkTFy34ARYXeXfc/7VERFJClXy4PiUGHmV8b6bRTdw+hLq487JPJ3UPnHYe5TjfRjX96yJAD1nNp5V3mYzut794/C1+tXO0ihw1oam4J9zw+PVRW1SiHnXD+7ea1lMbemvNueH32QvNFymHvL/zcQqtAnXDO1e4lkqS09rse/UNtaUz6Rj/ddg//RjJRonx/pwwBAACIyjcjACnx0nGA6OtMLx2H/HVzsm+bVAAU8Fqz2u0cAACgqMxNVmJHDACk8TnzD5LNsswCANoB59sBou8FnW8HAAAoLmuTldsRAwAA0GolZeXlfvxEhd4NYx/0mAgKyDGnX252baQeuw4Nn73WLYS6uPKwn/9igOt0E8V3HBW+WLbCkAP+95vM+vqw3Y8ONSPbWZ36jQyjjzk3TJsx10UOGzF99sJQWVWjHLfPoWeb21Iau+eBZ76ecRNenWfGSDnq1vunhBUr11hsFaB58xeGrfqOcD+RJKWtrcvKw9Ode4Ta0pi0Xjd2K/NvJCOV3+aUIQAAAFH5ZgQgJV46DhB9neml45Dfbk32bdMKgAJda1a7lQMAABSd2mQd7IoBgDQ8Y/6fZLMtrwCAdsL5doDo+0Hn2wEAAIpPfbLhdsUAAAC00nnfLikrn+XHT1TIXT7mHo+IoEA89OTL5tYmuu2aHUKoiysPq76lr2t0M5183nWGHLCe8Y+8YD4WeF13GR32PujX4RenXx7GjH0wvPLazLBi5SoXN2zCipVrw83Vk0NlVY1y2HV3vxw673SgWS6lsTMvuvHrOdfU3BweeO4ts0bKUfc/+1Zobmmx6CpAx57xB/cTSVJaG9xrcJgdi4fa0pj016bHOodOZeX+jaS5krKKj771rW9t4ZwhAAAAUfhWBCAlXjoOEH2d6aXjkP/WvfDgH0wsAApwrVntNg4AAFCU3k+2tZ0xANCG58tbJptnWQUAtCPOtwNE3xM63w4AAFCcGpLtZ2cMAABAq5SUVYz2Aygq5M69/FaPh6AALPnsi9BzwCHm1kYaMHSf0Dincwh1ceVZH9b0CN13HuY63Uwz3n7HoAPWM+Tgk83HAqi0//5hjxHHhZ/9+uJw4dV3hLsfeCZMnjYrLFryuYsYWuHxl2eHyqoa5bjTL60y46U0V3H4GX+ddWvWNoa7Hp1m3kg5avKM+RZdBWjuvA9Cxz7D3VMkSWnt4u7bh9rSmLRe5b329O8jIw3bzilDAAAAovCtCEBKvHQcIPo600vHoTDcnew7phYABbbWrHYLBwAAKFrvJetkdwwAtOLZ8tbJ3recAgDaGefbAaLvC51vBwAAKF6NyUbbHQMAANAK5327pKx8lh8/UaH26/Ou9WgICsBPT7jQzNpEL93XO4S6uPKsxrnxMOyAvVyjm2nvg35tyAHree3NOeZjnrTNHoeEIQefHA5LrsVOv3BMGHPHA+GxZyeFV5N/ow8/Whyam1tcsJAmtfOXhMqqGuVBFUdd4B4gpbluuxwYWlr+d93wxfJV4Zb7ppg5Uo6a/9FSi68CdOTJl7inSJLSWiwxLEyIdw+1pTHpr13afXv/PjJQSe/y05wxBAAAIArfiACkxEvHAaKvM710HApHdbJ/MLkAKKC1ZrXbNwAAQFH7MNnWdsgAQArPlbdM9p5lFADQDjnfDhB9b+h8OwAAQHFrSnaQHTIAAAAp65ioONgPoKhQW/cjhEB+q3rwWfNqU3Ps6IEh1MWVh116wc6u0Qjd+8jzBh2wnl+eeYX5mMG27Ds8JAYdHgaPPjEcevwF4dfnXRsurbwr/LHqsfDYs5PCtBlzwyeLPw9Nzc0uRsiSNWsbwh8fmBoqq2qUB/Uc8FP3CykDLfh4yXqz78NPvghjxk0yd6QctG7dsXJ1vUVYgZk5993Qsc9w9xRJUlob2mtQmFsaC7XSn3s53t2/jQxUUlYxwQlDAAAAovCNCEBKvHQcIPo600vHobCMTfZt0wuAAllrVrt1AwAAFL15yTrYJQMAEZ4pd0j2ruUTANBOOd8OEH1/6Hw7AAAATclG2yUDAACQmlGjvtMhUT7Hj6CoEDvg6HM9EoI8tvCTT0P3XQ8yrzZS6Q7l4f2Xe4RQF1eeNfWR7cJWfctdp5up54BDwpq1fsQZ+F+LP10aOm0/0oxMsU79RobEoMPDj0YdH/b/+dnhF6dfHs657JZwza3jw72PPB+enzgtzJr7Xljy2RehqbnZhQZ55plXakNlVY3yoHOvfsB9RcpQz7782jfm34zaj8weKUc9+PzM0NLSYiFWYH56woXuKZKktHdF936htjQm/bVdeu/t30aaKykrr/+vbuX/5pAhAAAAm+PbEICUeOk4QPR1ppeOQ+H5Y7Jvm2AAFMBas9ptGwAAgKR3kv3QThkA2MTz5B8km2PZBAC0Y863A0TfIzrfDgAAwDoNycrtlAEAAEhJSVnFMD+CokJs3Y/OA/mpubkljDr6HLNqE11+4c4h1MWVZy1/o2voP3iIazRCV940zrAD1nPFjVXmY7Jt9jgk7DT06LDvoaeGQ4+/IJx47jXh/CtvD9f/8b4w7uHnwjMvvRpee3NOeHf+R2HZ8q9cOFDAPvjki1BZVaM8af9jL3EfkjLUdbfdt8E5+NJr88wfKUdNnfmBxViBeWNWnXuKJCntdU0MCxPj3UJtaUz6ulN67OzfRgb6YWJYhROGAAAAbI5vQwBS4qXjANHXmV46DoXp1mRbmGIA5Plas9otGwAAgD+rTfY/dssAwAaeJX8/2duWSwBAO+d8O0D0faLz7QAAAPxFfbJ97ZYBAABISUlZ+Ut+BEWFVmLQYR4FQZ668U8PmVObqN+gH4dVMzuHUBdXnnX0Lwa6RiPUfbeDwrLlXxl2wP9+Q1nf8PX6vD3MuG67HJj8bzk87DzsmDDk4JPD6GPODUefdlk47cIx4aJrxoYxdzwQ7n7gmfDYs5PCxKkzwltz3g0ffrTYXIQi09DYFO58dFqorKpRntRz4GHW6lKG+uWZV2xwFjY3t4SHX5hlBkk5aMy4mrBg0ZcWZQXmoGPPc1+RJKW9Yb32DHNLY6FWSlbdpZd/F5koUXGj04UAAABsjm9CAFLipeMA0deZXjoOhesaUwyAPF9rVrtdAwAA8DfeSvZfdswAwN88R/5/yWZaJgEARcD5doDoe0Xn2wEAAPhba5MNsWMGAAAgso6Jodt3KKto8UMoKqS26jvi6x9uBfJL3XsLQqz/KHNqEz18R5/kBxVXnnXTlf1dnxG78qZxhh2wngeeeDEn82jEEWeGY06//OuOP/uqcPqFY77unMtuCRdd+6evWzezxtzxQLjpzofD3Q88Ex55piY8N3FaeOW1meGtOe+G9z/8OCz+dGlY8dUqf0ggspenvRsqq2qUJ5199f3W6VIGG7j/8Rudh2vqG8Pdj71uFkk56I8PTg0rV9dbmBWQqW/Mdl+RJGWka7v1DbWlMSnMjsVD98S+/l2kvfL5ThcCAACwOb4JAUiJl44DRF9neuk4FLZLTTIA8nitWe1WDQAAwN+Znuw/7JoBgOSa4HvJZlgeAQBFwvl2gOj7RefbAQAA+HvrfvRtd7tmAAAAIutQVl7lR1BUaC39crnHQJBHGhubwpBDTjGfNtHwAweHltp4CHXKp157tFfo1K/cNRqh7rsdFJYt/8rAA9az76GnZn0e9Rp4aFhb7wfkgexb9NmKMGZcTaisUr603zG/t1aXMlinfiNDfX3DRufil8tXh1vvn2IeSTnooednhpaWFgu0ArLfUWe5t0iS0l7XxNBQE+sWaktjUvhJzwH+XWSgkl7l3ZwuBAAAYFN8CwKQEi8dB4i+zvTScSh8Z5lmAOTpWrPabRoAAIANmJLsX+2cAaConx9/N1mNZREAUEScbweIvmd0vh0AAIANWfej0v3snAEAAIjkB70rti4pq1jrh1BUSNW9t8AjIMgjF193p9m0ibbsWx7eemrbEOriyqOWvNo9lA38sWs0YlfeNM6wA9bzxqy6nMyjS66/y4cPZF1Tc0uoemJ6qKyqUZ50/T0TQ88Bh1qrSxludt38Tc7Hj5csCzfeO8lcknLQtFm+JykkNa++5b4iScpI+207MNSWxqRwfbe+/k1koj4VJzldCAAAwKb4FgQgJV46DhB9neml49A+nGiiAZCHa81qt2gAAAA24rlk/2T3DABF+ez4H5M9ZTkEABQZ59sBou8bnW8HAABgYz5L1sPuGQAAgEg6JCqu9EMoKqQmT5vl8Q/kiWkz5oat+o4wmzbRmaftFkJdXHlU45zOYfiBg12fEeu+20Fh2fKvDDxgPb86+6qsz6N1a44FHy/x4QNZN2XG/FBZVaM86jdXjrdWl7LQA0+8uNkZOeudT8wlKQeNGTcpfLRkmYVaARlxxJnuLZKkjHRDt7JQWxpTkfdqrEvYKlHu30SaK0lUPOVkIQAAAJviGxCAlHjpOED0daaXjkP70JzsIFMNgDxba1a7RQMAALAJDyb7jh00ABTVc+PvJBtvGQQAFCHn2wGi7x2dbwcAAGBTPkq2tR00AAAAm7VVr33/s0Oi/HM/hqJC6bFnJ3n0A3lg5ao1YaehR5tLm2ibXYeGpa93DaEurjzqjNN2c32m0FU332vgAev5bOmyUNp//6zPoyNPvsSHD2Tdos9WhDHjJoXKqhrlUSN+fqG1upSFLrpmbKRZOfH198wmKQfd/uDUsGpNvQVbgZgwabp7iyQpM99HJoaGqbGuobY0piJvUK/B/k2kuZJExZof9h36XacLAQAA2BjfgACkxEvHAaKvM710HNqPhmT7mmwA5NFas9rtGQAAgM1Y95KBLeyiAaAonhlvkexWyx8AoEg53w4Qff/ofDsAAACbMy/Z/9hFAwAAsFkliYpT/BiKCqXbxz3usQ/kgVPPv95M2ty8um77EOriyqPuv62vazOFtt/nyLB6zVoDD1jPVTffm5OZNHHqDB8+kFWNTc3h7sdeD5VVNcqjrr9nYuixx6HW61IW+smvzo80L1taWsLjL882o6Qc9PALs5L/Bq3bCsWQQ05xf5EkZaQjeu4RaktjKvLO6dHfv4dMlBg+xMlCAAAANsa3HwAp8dJxgOjrTC8dh/ZldbLdTTcA8mStWe3WDAAAQATX2EUDQFE8M77csgcAKGLOtwNE3z863w4AAEAUbyX7TztpAAAANqlz533+qSRRMc+PoagQuuiasR75QI49+/Jr5tFm+lH53qFxbjyEOuVLbz21bYjtUO76TKEnX5hs4AHraWxsCn32OiLr82jAyONCi1+KB7Ls5dffDZVVNcqzzvzDeGt1KUv12+dnkWdmfUNjuOfx6eaUlIOmz15o4VYgnn5xqvuLJClj3d2ld6gtjamIe6zzNv4tZKCSsoprnSwEAABgY3z7AZASLx0HiL7O9NJxaH+WJUuYcADkwVqz2m0ZAACAiE6zkwaAdv28+DeWOwBAkXO+HSD6HtL5dgAAAKKamOyf7aYBAADYpJI+w4f6MRQVQseddaXHPZBDS79cHhKDDjePo5Nt5QAAIABJREFUNtNL1b1DqIsrT1o8tVvoN+jHrs0UOuDocw084BseempiTmbSHeOf8OEDWbVw8ZehsqpGeVjFURdYr0tZ7ItlKyLPzi9XrA633j/FrJKy3A3jJoVPPl1uAVcAWlpawuDRJ7q/SJIyUp/eQ8KbpZ1DbWlMRdrcZL177+vfQ/qrdaoQAACAjfHtB0BKvHQcIPo600vHoX36JNnWphwAOV5rVrslAwAAEFFLssPspgGgXT4rPvjP93oAgGLmfDtA9H2k8+0AAACk4tFk37GjBgAAYJNKyioe92MoyvdGHnmWRz2QQ0efdplZtJmO/sXAEOriypO+mtElDB6+l2szhTr1GxnmzvvAwAO+oeLwM7I+k7rtcmBYsXKVDx/ImvqGxjD24ddCZVWN8qzr7pkYuu/+E2t2KYtNef3tlGboBx8vDWPGmVdStlu3dllb32ghVwAee3aS+4skKWOdtM0uobY0piLu5z13828hA23Vb2TMqUIAAAA2xDcfACnx0nGA6OtMLx2H9mtOsu+ZdADkcK1Z7XYMAABAChqS7WVHDQDt6jnxj5LVW+YAADjfDpDCXtL5dgAAAFJ1kx01AAAAm9SxbFjnkrKKtX4QRfncTkOP9pgHcuTeR543hzZTvP+wsGBSjxDq4sqDmuZ2Dkcc9SPXZoqd94fbDDzgG96a825OZtLZl9zswwey6rnJdaGyqkZ52CkX32W9LmW5kUeeFRqbmlKao9PeXmBmSTnoyZo5FnIFoLm5JQzc71fuMZKkjLRlWXl4sMu2obY0piLttq4J/xYyUEmi4pdOFQIAALAhvvkASImXjgNEX2d66Ti0b1OTfde0AyBHa81qt2IAAABStCJZwq4aANrFM+JeyZZZ3gAAfM35doDo+0nn2wEAAGiN0+2qAQAA2KSSsoqL/SCK8rnS/vuHlpYWj3kgyxZ8vCR03/Ugc2gzXXnRTiHUxZUnnfObXV2XKZYYdFhYvmKloQd8w4nnXpOTuVQ770MfPpA17y/8PFRW1ShP2+uQM63ZpRx0wVW3pzxPn54019ySctCc9xZb0BWAB594yf1FkpSxdt1u7zC7NB5qS2MqwmbEOoety8r9W0hzJYmKB50oBAAAYEN86wGQEi8dB4i+zvTScWj/Hkn2HRMPgBysNavdhgEAAGiFj5N1srMGgIJ+PlyabJFlDQDAXznfDhB9T+l8OwAAAK2x7genD7OzBgAAYKN+sN3gfykpK1/oR1GUz336+Zce80AWNTe3hP1/frb5s5m2H/TjsGpm5xDq4sqD/njNDq7LVvTE85MNPeAbPv9ieYj1H5X1mTT6mHN9+EDWrFnbEG5/cGqorKpRHnbV2Alh6x32t2aXclDHPsNT3is2NDaFqiemm19Slru5enL4cvlqC7s819TcHHYedox7jCQpY53To3+oLY2pSCvvtad/B2mupKz8y2+NGuUH7QAAAPgG33oApMRLxwGirzO9dByKw40mHgA5WGtWuwUDAADQSnOSfc/uGgAK8tnwfyWbazkDALAe59sBou8rnW8HAACgtRqS7WV3DQAAwEaVlJUf6EdRlM+9Neddj3ggi24Y+6DZE6HH/lQWQl1cedCE8YnQqa9rMtVO+d31Bh6wQdfeVp2TufTUhKk+fCBrnpw4J1RW1ShPO+asG63ZpRzWdZfRoe69BSnN1S9XrA633j/FDJOyXPXTb4bm5haLuzw3dvyT7i+SpIy1dVl5eLpzj1BbGlMRdkH3/v4dZKK+5f2dKAQAAODv+cYDICVeOg4QfZ3ppeNQPE419QDI8lqz2u0XAACANpiY7J/ssAGgoJ4L/99kr1jGAAB8g/PtANH3ls63AwAA0BbLk/WywwYAAGCjSsoqJvhRFOVrT74w2eMdyJK6dz8Msf6jzJ7NtN8hg5IfVlx50Myne4auOw1zXabYjvv+PKxYucrQA76hsakp9NvnZ1mfSzsMOSo0NTf7AwBZMWveolBZVaM8bpfhx1u3Szlu9xG/DF+tXJ3SfF2w6MswZtwkc0zKcpNnzLfAy3Nr6+tDYtDh7i+SpIw1uNfgMKc0HmpLYyqynuq8jX8DGaikrPxspwkBAAD4e77xAEiJl44DRF9neuk4FI91/+PUcJMPgCyuNavdfgEAAGije5NtYZcNAAXxTHiLZHdbvgAAbJDz7QDR95fOtwMAANBWHyXrYJcNAADABm3Ze1jPkkR5gx9GUT52w9gHPdqBLKivbwiDR59o7mymrfqWh9nPbhtCXVw5bv7LPUJiwL6uyxTbsu/wMHnaLEMP2KBHn52Uk9lUefv9PnwgK5YuWxVuGv9KqKyqUZ52yc1Phi37DLd2l/KgX555RcpzdtrbC8wyKcuNGVcTFi7+0kIvz111873uLZKkjHZ5t+1DbWlMRVhZ7x/7N5DmSsrKX3SaEAAAgL/n2w6AlHjpOED0daaXjkNxWZ1sB9MPgCytNavdegEAAEiDs+2yAaAgngn/zrIFAGCjnG8HiL6/dL4dAACAdHg92XfttAEAANigkkT5dX4YRfnYGb+/wWMdyIKLrhlr5kTo7DN2C6Eurhy3eGq3sONeQ1yTreiCq2438ICNGnHEmVmfS6X99w+fLV3mwwcyrqmpOdz75BuhsqpGedwhJ15h3S7lUbePezzlefv0pLnmmZTl7njo1bBmbaMFXx77ctlXoesuo91bJEkZq2tiWJgY7xZqS2Mqso7qubt/A2mupKy8/gfbDf4XpwkBAAD4W77tAEiJl44DRF9neuk4FJ9PknU0AQHIwlqz2m0XAACANGhJdpCdNgDk/dmDFssWAICNcr4dILU9JgAAAKTDfcm2sNsGAADgG763wz7/XpKoWOTHUZRvHfiL33qkAxn26ptzwlZ9R5g5m2mbXYeGpa93DaEurhy2/I2uYfDwvVyTrWjg/seHtfX1hh6wQW/Xvp+T2XTSb6/14QNZ8dJr80JlVY3yvMReR1q7S3lUp+1Hfv3cKBUNjU2h6onpZpqU5Z6cOMeCL8+de/mt7i2SpIw2stePQm1pTEXWTd36uP4zUMeyYfs4TQgAAMDf8k0HQEq8dBwg+jrTS8ehOL2R7F9MQQAyvNasdssFAAAgTdYk29FuGwDy8llwv2SrLFcAADbJ+XaA6PtM59sBAABIpwvstgEAANigjomKo/wwivKtHff9ucc5eeat2fN8CO3IVytXh52GHm3eRGjs9duHUBdXDls9s0sYfuBg12Mr6r7rQWHe/IWGHrBRp55/fU7m05uz3vHhAxn33oLPQ2VVjfK8s6++39pdysP67fOz8NnSZSnN3S9XrA633j/FbJOy3Ox3F1n45bEFHy8JnfqNdG+RJGW0W7qWhdrSmIqo12NdwlaJctd/uktUXOkkIQAAAH/LNx0AKfHScYDo60wvHYfi9Xiy75iEAGRwrVntdgsAAEAarfufmLey4waAvHoOvHWyxZYpAACb5Xw7QPS9pvPtAAAApFNLskPtuAEAANiA877doaziDT+Oonxqq74jQkNDo0c6eWLd3+Jnv77YB9GOnPK7682aCA0s3yc0zo2HUKdc1Tinc/jJET9yPbaijn2Ghyeen2zgARu1bPlXofNOB2R9Pg099DQfPpBxX61aG257YEqorKpRnldx1AXW71KeNuroc0JjU1NK83fBoi/DmHGTzDcpi91cPTl8sXy1BWAeO+6sK91XJEkZbdve+4bXY11CbWlMRdTgXoNd/2mupKx8hnOEAAAA/C3fcgCkxEvHAaKvM710HIrbpSYhABlca1a71QIAAJBmbyX7V7tuAMiLZ8D/lmyW5QkAQCTOtwNE32863w4AAEC6rU22i103AAAA39CxT8XefhxF+dZ7H3zscU6emPrG7BDrPyqsWVvvw2gHnnnpVTMmYpMf2i6EurhyVPPczuGXxw1wLbayK28aZ+ABmzRm7IM5mU/3PTbBhw9kVEtLCA+9MDNUVtUoz7vu7pdD110Osn6X8riLr7sz5Tk87e0FZpyU5cY/9WZoam6xEMxTs+a+554iScp4x/bcNdSWxlRE/abHjq799Nfy39sO+4GThAAAAPyFbzkAUuKl4wDR15leOg4cZBoCkKG1ZrXbLAAAABnwULIt7LwBIKfPf7dIdp9lCQBAZM63A0TfczrfDgAAQCYsTtbRzhsAAIBv6FBW/owfR1E+9ULN6x7l5Imrbxn/9d/k5Slv+jAK3OdfLA+JQYeZMRH6xbEDQqiLK0e11MbDGaft5lpsZUecdFFo9kPKwCY0NTeH/j8+KuvzabsfHRrq6xv8AYCMenXmh6GyqkYF0PG/u936XcrzOvYZHp5+cWrKs/jpSXPNOSnLTX5zvoVgHjvo2PPcVyRJGW3LsvJwf+dtQ21pTEXSQ122de1nYh+cqDjYKUIAAAD+wjccACnx0nGA6OtMLx0H1iTrZyICkIG1ZrXbLAAAABlyjp03AOT0+e/5liMAAClxvh0g+p7T+XYAAAAy5Y1k/2z3DQAAwHo6JEb07lBW3uwHUpQv3XzXwx7j5InRx5z79d/kgqtu92EUuJ/9+mLzJULx/sPCwld6hFAXVw5qqY2Hc87czbXYyvYYcVxYsXKVgQds0lMTpuRkRl1y/V0+fCCjPl6yLIwZNylUVtWoANpt5EnW8FIB1GP3g8P8BZ+kNI8bGptC1RPTzTopi40ZVxMWLv7SgjBPTZw6wz1FkpTxdum9d5hdGg+1pTEVQbNj8dCj91DXfrpLVNzuFCEAAAB/4RsOgJR46ThA9HWml44D63yY7PumIgBpXmtWu8UCAACQIc3Jhtp9A0BOnv1W/PleDABAdM63A0TfdzrfDgAAQCbdafcNAADAN6z7YRA/kKJ86dQLKj3CyQMNDY2h804HfP03GTDyOB9IARv38HNmS8SuuninEOriylEX/XZn12Er22aPQ8K8+QsNPGCz9jvqrKzPqK36jggLPl7iwwcyZtWahnDHQ6+GyqoaFUAX3/xk2LLPcOt4qUDac9QJYfWatSnN5eVfrQm3PTDFzJOy2Lq10Jq1DRaGeWqfg052T5EkZbzzuvcPtaUxFUk/6TnAdZ/mSsoqPnKCEAAAgL/w7QZASrx0HCD6OtNLx4G/qEn2jyYjAGlca1a7vQIAAJBBK5JtYwcOAFl97ts92TLLEACAlDnfDhB97+l8OwAAAJl2gh04AAAA6+nYe98OHRIVq/xIivKh8sNO9/gmD0x9Y/Z6f5cPFi7yoRSgDz9aHLrvepDZEqHtB/04rJ7ZJYS6uHLQReft7DpsZZ13OiC8+uYcAw/YrNl183Myp448+RIfPpAxLS0t4ZEJs0JlVY0KpNHHXWodLxVYJ/322pTn84JFX4Yx4yaZe1IWe3Ki50P56uGnJ7qfSJIyXiwxLEyIdw+1pTEVQdd06+u6z0Alvcq7OUUIAADAOr7dAEiJl44DRF9neuk48LeuMRkBSONas9qtFQAAgAyrTfb/2YUDQFae+f5nsnmWHwAAreJ8O0D0/afz7QAAAGRaY7KBduEAAACsp0Oi4kI/kKJ8qMfuB3t8kweuuXX8en+XO8Y/4UMpMM3NLWG/o84yVyL2xJ19QqiLKwddcv4ursFWtvUO+4UXX5lu4AGRnHzedTmZVZNee8uHD2TM5Dfnh8qqGhVI198zMfTY41BreakAu/eR51Oe0a+/vcDsk7Lc2/MWWSDmoabm5rDzsGPcTyRJGW/fXoPC3NJYqFW7b0q8a+jomk97JX3Kj3OCEAAAgHV8uwGQEi8dB4i+zvTSceDvHWY6ApCmtWa12yoAAABZ8Giyb9uJA0BGn/d+J9lTlh0AAK3mfDtA9D2o8+0AAABkw6fJOtmJAwAA8Fff32bUv5YkKhb5kRTlQ4s/XerxTY4d+Ivfrvc3OfT4C3woBWbMHQ+YJxE74CeDQqiLKwdddsHOrsFWtlXfEeGxZycZdkAkS79cHmL9R2V9Vg0YeVxoaWnxBwAyYv5HS0NlVY0KqJMu/JO1vFSgrVtLzq6bn/KsfnLiHPNPymI3jX8lfLF8tYViHrp93OPuJ5KkrFTZrU+oLY2pCNptu71d82mv/CEnCAEAAFjHNxsAKfHScYDo60wvHQf+3ppkfUxIANKw1qx2WwUAACBLzrETB4CMPu+90HIDAKBNnG8HiL4Hdb4dAACAbHkz2T/bjQMAAPBXJYnhx/qBFOVDE6fO8Ogmhxobm0LnnQ5Y728S33FUWL1mrQ+nQMx5Z34o7b+/eRKhrfqWh7nP9wyhLq4sd/mFO7sGW1nHPsPDfY9NMOyAyK69rTon82rs+Cd9+EBGLFuxJtxy35RQWVWjAmrgqFOs56UCbrfhx4avVq5OaV6vrW8Mdz46zQyUstj4p94MTc0tFox5Zt33K70GHup+IknKeNskhoZXY11CbWlM7byTtvFda9pLVCz/1h57/IMThAAAAPhmAyAlXjoOEH2d6aXjwIZ8kOx7piQAbVxrVrulAgAAkCXNyfa2GweAjDzrHZSsyXIDAKBNnG8HiL4Pdb4dAACAbLrRbhwAAID/NWrUd0rKKt72QynKdX+sesxjmxya8fY7G/y7PD9xmg+nANTXN4RBB5xolkTs3LN2DaEurix3xe93cv21oZvvetiwAyJrbGwK/fb5WdZnVbddDgwrVq7yBwDSrqmpOYx/6s1QWVWjAuqyW58OW/YdYT0vFXjH/eaKlOf2Z1+uDDeNf8UslLLY5BnzLRrz0JU3jXMvkSRlpaN67h5qS2Nq593VdTvXeybqM2xHBwgBAADwrQZASrx0HCD6OtNLx4GNWfdihS1MSgDasNasdjsFAAAgi5Ym62RHDgBpfc67ZbLPLDMAANrM+XaA6HtR59sBAADItsPsyAEAAPirH/auGO5HUpTrTrtwjEc2OXTbPY9u8O9y1iU3+XAKwIVX32GORKznbvuGL6Z3DaEurizVUhsP5521i+uvDV13230GHZCSh5+emJN5dc6lt/jwgYx4fuo7obKqRgXWISf8wXpeaieNf+SFlGf3rHc+MQulLDZmXE34eMkyC8c88/kXy0PnnQ5wL5EkZbyOycZ16RVqS2Nqx70V6xy2Lit3zae5kkTFuU4PAgAA4FsNgJR46ThA9HWml44Dm3KaSQlAG9aa1W6lAAAAZNmUZP9oVw4AaXnG+3+SvWJ5AQCQFs63A0TfjzrfDgAAQLatTpawKwcAAOAvtihJVEzzQynKZT/+yake2eTQsWds+IeudxhylA8nz7325pywVd8R5kjE7hqzfQh1cWWpprmdwym/3t2114auvc37rIDUlR92evZ/tLXP8DBv/kIfPpB2b89bFCqralRgXX/PxNBz4GHW9FI7qcvOo0PdewtSnuHPTakzE6Usduej00JDQ5MFZJ4565Kb3EskSVmpf+99wsxYPNSWxtSO27fXINd7mispK3/J0UEAAAB8owGQEi8dB4i+zvTScWBT1h34G2RaAtDKtaaXEAAAAJALV9uVA0BanvFWWlYAAKSN8+0A0fejzrcDAACQC+8k+3c7cwAAAL7WITF8iB9KUS6L7zgqNDb5scdc2X6fIzf6t2nND+aSHStXrQm7lP/CDInYXiP2Dk1zO4dQF1cWWvdZn3DCHq69NnTNreMNOiBlb856Jycz68Bf/NaHD6TdkqVfhRvHvxIqq2pUYJ16yT3W9FI7a+D+x4fVa9amNMcbGptC1RPTzUUpi7007V2LyDzz4UeLw1Z9R7iXSJKy0lk9dgq1pTG1437bfUfXeporKatY23HHUf/s9CAAAEBx840GQEq8dBwg+jrTS8eBzVmcrMTEBKAVa81qt1EAAAByxHfGANC257ujLScAADyrAMjRntT5dgAAAHLl4WRb2J0DAADwtQ6J8ol+LEW5rHbehx7X5MCiJZ9v8u9yw9gHfUh56uTzrjM7UmjKQ9uFUBdXFmqY3TkcefRA110buvY277ECWue4s67Mydx6+sWpPnwgrVataQhjH34tVFbVqAAbOOoU63qpHbbuWVSqvlyxOtx832SzUcpiH3z8hcVknjn2jD+4j0iSslKnsvLwbOceobY0pnbaw523da1not7lA50cBAAAKG6+zQBIiZeOA0RfZ3rpOBDFhGTfNjUBSHGt6WUEAAAA5MryZJ3tzgGgVc92uyb7ynICACCtnG8HiL4vdb4dAACAXPqV3TkAAABf+2Fi2GA/lKJc9sATL3pUkwOPPjtpk3+XkT/7jQ8pDz01YYq5kULH/WqPEOriykKrZ3YJBx++p+uuDV11872GHNAqSz77Imy9w35Zn1s7DDkqNDU3+wMAadPc3BIefH5mqKyqUQH2+xufCFv2GW5tL7XTqh99IeW5/s4Hn5qPUha746FXw5r6RovKPDK7bn7oaH0kScpS5b32DLWlMbXTZsfioXtiX9d6+jvfyUEAAIDi5tsMgJR46ThA9HWml44DUZ1tagKQ4lqz2u0TAACAHHo92T/aoQNASs91/ynZdMsIAIC0c74dIPre1Pl2AAAAcmltsoQdOgAAAF8rKSt/yQ+lKFedf+XtHtXkwO+u+OMm/y5b9R0RPlu6zAeVRxYt+Tz0HHCIuRGxLjuWh48ndw+hLq4Mt/yNrmHEgYNcd23oqpvvNeSAVrt8zD05mV1j7njAhw+k1YRX54XKqhoVaCN+foG1vdSen7PsPDrUvbcg5dn+0rR3zUgpiz37Sq1FZZ4Zfcy57iOSpKx1Q7eyUFsaUztt9LYDXedpriRR8bJTgwAAAMXNNxkAKfHScYDo60wvHQeiaky2i8kJQAprzWq3TwAAAHLsD3boAJDSc91rLR8AADLC+XaA6HtT59sBAADItXeS/ZtdOgAAAN/qmBi+hx9LUa464OhzPabJgaGHnrbZv03VQ8/5oPJEc3OLH99MsWsv3TGEurgy3JJXu4e9RuztmmtDV98y3pADWq2+viH03vOnWZ9dsf6jwtIvl/sDAGkzo/bjUFlVowLtqrETQmzHUdb3UjvvR6OOD6vXrE1pvjc1N4fqp980K6Us9s6Hn1lc5pEJk6a7h0iSsta2vfcNr8e6hNrSmNphl3fb3nWe5krKKtb+sO/Q7zo5CAAAULx8kwGQEi8dB4i+zvTScSAVC5J9z/QEIOJas9qtEwAAgBxrSTbULh0AIj3THfLneycAAOnnfDtA9P2p8+0AAADkg9vs0gEAAPhah0T5834wRbmo54BDQkuL893ZVF/fELbeYb/N/m0OP/H3Pqw8cdOdD5sXKbTT3kPC2rc7h1AXVwb7YGKPsPM+Q1xzraxjn+Fh7PgnDTigTaoffSEnM+yk317rwwfSZsGiL8MN4yaFyqoaFWiHn3atNb5UJJ3yu+tTnvMrVq0Ntz0wxbyUstSt908JXyX/3ZEf1n3/tceI49xDJElZ67htdg21pTG1wybEu7vGM1BJWcWeTg0CAAAUL99kAKTES8cBoq8zvXQcSNUDpicAEdea1W6bAAAA5IFPk/3QTh0ANvk8t0OyzywbAAAyxvl2gOh7VOfbAQAAyBcH26kDAADwrZJExc5+LEW5av6CTzyiyaIZb78T6e9S2n//8NXK1T6wHKud92GI9R9lVqTQU3eXhVAXVwab8eS2Ybs99nW9tbKt+o4I4x5+zoAD2mzIIafkZI6tW08CpMPyr9aE2x6YGiqralSgXX/PxLDdnkdY50tF1H2PTUh53n/w8VIzU8pij0yYZaGZR8aOf9L9Q5KUtbYsKw8Pd9421JbG1A7r13uI6zzdJSoudGoQAACgePkWAyAlXjoOEH2d6aXjQGscY4ICEGGtWe2WCQAAQJ54Mdl37NYBYIPPcr+d7HnLBQCAjHK+HSD6PtX5dgAAAPLFV8m62K0DAADwrZJExVN+MEW56MEnXvKIJov+VP1U5L/NE89P9oHl0Nr6+rDnqBPMiRQafeieIdTFlcEm3t87dNtpmOutlXXqNzI88MSLBhzQZlOnv52TOTbsp6f78IG0aGhoClVPTA+VVTUq4E668E/W+VKR1WXn0eGd9xemPPcnz5hvbkpZbPa7iyw488TqNWtDzwGHuIdIkrLWwO32CrNj8VBbGlM76+c9d3ONp7tEeY0TgwAAAMXLtxgAKfHScYDo60wvHQdaddQs2bamKACbWWtWu2UCAACQR860WweADT7LPccyAQAg45xvB4i+T3W+HQAAgHzyarL/Y8cOAABQ5Dr2Hr6DH0xRLjr38ls9nsmiU8+/PvLf5oRzrvaB5dA5l95iRqRQp74VYe7zPUOoiytD3X9b39CpX7nrrZVtvcN+4akJUww3IC1+fuqlOZll9z/+og8faLOWlhAef3l2qKyqUYG328gTrfWlImzPUSeENWvrU5z9LeHhF2aZnVKWurl6cli2Yo2FZ5644Krb3T8kSVnt8m7bh9rSmNpZN3Yrc32nuZKy8vofbDf4X5waBAAAKE6+wQBIiZeOA0RfZ3rpONBabyf7vyYpAJtYa1a7XQIAAJBHGpNtb8cOAOs9x+2brMEyAQAg45xvB4i+V3W+HQAAgHxzvh07AAAA3+qQKH/ej6Yo2w099DSPZrJorwNPivy32WaPQ0JDQ6MPLQcmTJoeOvYZbkak0G/P2jWEurgyVOXlOyavSddZa+u2y4Gh5tW3DDcgLT5a9Gno1G9k1mfZdj86NKytr/cHANps8pvzQ2VVjQq8313/sH2rVMSdfcnNKc//Vavrw+0PTjVDpSz14PMzQ0uLtWc+WPjJp2GrviPcPyRJWatrYliYHO8Waktjake9Fu8Stiwrd42nuR8mhg12YhAAAKA4+QYDICVeOg4QfZ3ppeNAW1xqkgKwibVmtVslAAAAeWZOsn+2aweAr5/hfjdZreUBAEBWON8OEH2/6nw7AAAA+WbdjyPvaNcOAABQ5Nb9UIgfTFG2K+2/f6ivb/B4JgvW1teHTtuPTOnv80LN6z64LPv8i+UhMejAhYY2AAAgAElEQVRw8yGFeg/YNyx/o2sIdXGluaa5ncPZZ+zmOmtDPQccEqbP9P82Aenz+2vG5mSeXT7mHh8+0Gaz310cKqtq1A7a97BzrfelIu/pF6emfB/4aMmycMO4SeaolKXemPuRBWieOPLki907JElZ7bCeu4fa0pjaWQN67e36TnMlZeUXOTEIAABQnHx7AZASLx0HiL7O9NJxoC2akw0wTQHYyFqz2q0SAACAPHS1XTsAfP0Mt9KyAAAga5xvB4i+X3W+HQAAgHz0XrJ/s3MHAAAoch0S5a/70RRluzdnvePRTBa8Masu5b/Nr8+71geXZUecdJG5kGJVN/YLoS6uNLfyrS7hsCMHusbaUP8fHxXene/Hi4H0Wb1mbdh2wE+yPs869RsZPln8uT8A0CYffvJFuGHcpFBZVaMC74rbnwtb77C/Nb9U5G2zxyHho0Wfpnw/eP3tBWaplKVuHP9KWLpslYVoHpg8bZZ7hyQp643r0ivUlsbUjjppm51d22mv/BWnBQEAAIqTby8AUuKl4wDR15leOg601fxk/26iArCBtWa12yQAAAB5qCXZPnbuABT589vBf74nAgCQHc63A0TfszrfDgAAQL660c4dAACgyJWUVYz2gynKdrff+7jHMllwx/gnUv7b9Nj94NDQ0OjDy5I773vKTEixvUfuHZrndg6hLq40tmhKt68/W9dY6xu436/CJ4s/N9iAtLrr/qdzMtOOOuVSHz7QJkuXrQq33DclVFbVqB108Al/sOaX9HUHHH1uaG5O/Z0eT0ycY55KWWr8U2+Gpmbv3skHg0ef6N4hScpq/XvvE2aVxkNtaUztpLFderu201xJorzh+9uM+lcnBgEAAIqPby4AUuKl4wDR15leOg6kw+0mKgAbWGtWu0UCAACQpz5K9j27dwCK9NntfyRbYDkAAJBVzrcDRN+3Ot8OAABAPhtq9w4AAFDMRo36TkmiYp4fTlE2++WZV3gkkwUnn3ddq/4+EyZN9+FlwfwFn4Suu4w2E1KoY5+KMPWR7UKoiyuNzX5229Bv0I9dY21o6KGnhS+WrTDYgLTbc9QJOZlrr7w204cPtNrK1fVh7MOvhcqqGrWDrv7ThOTe9SDrfkl/rfL2+1O+N6xZ2+jeIGWxqTM/sCjNA+Mefs59Q5KU9X7bfcdQWxpTO+mN0s5hK9d1Js4d7O3AIAAAQPHxzQVASrx0HCD6OtNLxwFrMAAytdasdnsEAAAgj91j9w5AkT67vdcyAAAg65ytAoi+b3W+HQAAgHy2JNkP7OABAACKWEmi4pd+NEXZrO/eP/NIJgv2PujXrfr7nHzedT68DGtoaAxDDj7ZPEix44/fI4S6uNLYhPGJ0G2nYa6vNnT4ib8Pa9bWG2xA2r00+c2czLWB+/0qtLS0+AMArdzrNIV7n3ojVFbVqJ10xKnXWfdLWq9O/UaG6TNrU75HfPzp8jBm3CSzVcpCNyT/rS3+fIXFaY7V1zeExKDD3DskSVktlhgWXox3D7WlMbWTBvUa7NpOcyVlFZc4LQgAAFB8fHMBkBIvHQeIvs700nEgXT5N9n2TFYC/WWtWuz0CAACQ53y3DECxPbcd7fYPAOAZBECe712dbwcAACDf3WcHDwAAUMQ67bHH/y1JVCzywynKZh9+tNgjmQxqbGoKsf6jWvW32WaPQ0JDQ6MPMYMuvu5OcyDFuu40LCya0i2EurjS1B+v2SFs2bfc9dWGTrtwzNfzFiATfnrChTmZbX+qfsqHD7RKS0tLePzl2aGyqkbtpOvufjn0HHCotb+kb7TT0KPDipWrUr5XvDrzQ/NVylJ3PTotNDR6bpVrl1Xe7b4hScp6o7YdGGpLY2onnbrNzq7rNFeSqJjitCAAAEDx8a0FQEq8dBwg+jrTS8eBdBpvsgLwN2vNardGAAAA8txnyf7bLh6AInlm+/+SLXH7BwDICefbAaLvX51vBwAAoBDsbxcPAABQxErKys/xwynKZvc9NsHjmAx65/2Fbfr7TJg03YeYIVNefzts2Xe4OZBi11/WP4S6uNJQw+zO4YzTdnNdtaGOfYaH6267z0ADMmb+gk9ysl7otsuBYcXKVf4AQKu8+Nq8UFlVo3bUL86+2fpf0kY74ZyrU75XtLS0hAefe8uMlbJUzfT3LVJzbPGnS8PWO+znviFJynpjuyZCbWlM7aC7u/R2Tae7REXj93bY59+dFgQAACguvrUASImXjgNEX2d66TiQbvuZrgD8ea1Z7bYIAABAARhnFw9AkTyz9QJaAIDccb4dIPr+1fl2AAAACsFnyf7bTh4AAKBIbdVr3//skKhY4cdTlK1OvaDS45gMeuSZmjb9fU489xofYgYsX7Ey7DDkKDMgxXbeZ0hY+3bnEOriamNfTO8aRv1kkOuqDa37EdwHnnjRQAMy6pzLbsnJjPvtH27z4QOtMn32wlBZVaN21PX3TAyJvY60B5C0yVqzP/5q1dpw2wNTzFopC40ZVxM++XS5xWqOHfebK9wzJElZb/veQ8LMWDzUlsZU4L0V6xw6lZW7rtNdYvgQpwUBAACKi28sAFLipeMA0deZXjoOpNunyb5vwgKQvB9Uuy0CAABQIEbayQPQzp/XVrjdAwDklPPtANH3sM63AwAAUCiq7OQBAACKWElZxbV+OEXZavcRv/QoJoMuq7y7TX+fbrscGFavWeuDTLNjz/iDf/+t6NmqRAh1cbWxOc/1DDvuNcQ11Ya22eOQMHnaLMMMyKgVK1eF7rselPUZ17HP8PDu/I/8AYCU1c3/NIwZVxMqq9SeOvGCO+wBJG22devWDz9anPK9472Fn5u1Upa6+/HXQ1NTs0VrDk2fWeueIUnKSWf12DHUlsbUDtqn1yDXdPq73ElBAACA4uIbC4CUeOk4QPR1ppeOA5lwtwkLQPJ+UO2WCAAAQIFYlOx7dvMAtNNntf+VbLHbPQBATjnfDhB9H+t8OwAAAIVkpN08AABAkfph36HdO5RVtPjhFGWjjn2Gh8+WLvMoJkOOOOmiNv+NHnmmxgeZRnfd/7R/+63owJ/uGUJdXG3ssT+VhS47lrum2tCO+/48vPP+QsMMyLjb7nk0J3Pu4F/+zocPpOyDj5eGG+6dFCqratTO6j/0WPsASZEaeuhpobGxKeV7yEvT3jVvpSw1ecZ8C9ccWzcr3TMkSdkulhgWXox3D7WlMRV4Z/bYyTWd5koSFVOdFAQAACguvq0ASImXjgNEX2d66TiQKSNMWYCiX2tWux0CAABQQO60mwegnT6rHec2DwCQc863A0TfxzrfDgAAQCFZlOx7dvQAAABFqkOi/Hk/nqJs9dizkzyKyZCdhx3T5r/P4Sf+3geZJu+8vzB03ukA/+5TrFO/8jDvxW1CqIurlbXUxsOYP+wYtuxb7ppqQ0MOPjl8+vkXhhmQcS0tLWG34cfmZNZNmDTdHwBI7WTBZyvCzdWTQ2VVjdpZp182zj5AUkpdWnlXyveRpqbmcO+Tb5i7Uha6YdyksOTzryxgc+ihJ192v5Ak5aQDtv1RqC2NqcC7t0sv13OaK0mUN/yw79DvOikIAABQPHxbAZASLx0HiL7O9NJxIFM+SfafJi1AUa81q90OAQAAKDDD7egBaGfPaYe5vQMA5AXn2wGi72WdbweA/5+9O4+uqjwU/l97p9/7u++df++6twhiTphEIQlhkMEioggCCaAoaG0dWtRSldaxVrHWoQ5FrQZFxalKkIgTVXEeCCKCKAhI4kRRVGSSQWRIcp7fwevyvbZVzknOfD6ftb5r9Z+uhrP3eZ69n/N0bwAg19ztjh4AAKBA7V1WeaSXpyhdnXfZTZZhUuCzbdtD624jWnx82vYYFTZ8utkH2kI7d+4Kg8ZM8J1vRr+5qG8I9cVqZp8taR9OHjfAudTCjj/9N2HrZ58bzIC0eOrFBRkZ6/pVnhaamqIOABC3DZu2hakzXw5V1bXKww4a5R5WUmK1KR8Ral9Z0qz5ZMqMl4y9Uhqa/vhrodF9X8Y0NDSG7oNPMmdIkjLSXe1LQl1RRDncG5HiECkd7nxOdiUVA+wUBAAAKBx+rQBIiIeOA8R/nemh40Aq3WKkBSjoa80aUyEAAAA55v1Y/+SuHoA8WaP951irTe8AAFnB/naA+O9n7W8HAAAgFx3hrh4AAKAQ9e//t63KKld7eYrSUZ/hp1iCSYHXltYn7RjdXTPbB9pCE6+Z6vvejEoHDA1bXu8QQn2xmtG7L3QOAyoGO5da2BU3/CE0edkwkEZjTp2YkfHujumP+vCBuG3euj3c8dAroaq6VnnYRdc/EFp3G+F+QFLClR9+Uti4aUvC88qytz82/kpp6pU3VrmYzaDrb5thvpAkZaQeJUPCG5HiUFcUUQ43tMuhzuck16q0YqKNggAAAIXDLxUACfHQcYD4rzM9dBxIpd3/59Z+RluAgr3WrDEVAgAAkIOudVcPQJ6s0VaZ1gEAsob97QDx38/a3w4AAEAuWhnrH93ZAwAAFKBWpRUXe3mK0tUHH621DJNkNbOeTdrxGXni+T7QFnj+pUVeRt7M7rulewj1xWpGT1WXhv36DXMetaB9ex4ZZjzyrEEMSKv6d1Zl5LqhU7+xYetnnzsAQFw+37Er3Pvoq6GqulZ52oCjz3JPIKnZnfyLK5o1vzz5Up0xWEpDN02fG9Zu3OqiNkPWb9wcIr1Gmy8kSRnpV/sdGOqKIsrhdh9D53LSe8ouQQAAgMLhlwqAhHjoOED815keOg6kWl2sfzDiAhTktWaNaRAAAIAc1Bir3J09ADm+PtvjyzkNAIDsYH87QPz3tPa3AwAAkKsuc2cPAABQgPYpH/m9VqUVu7w8Relo+sNPW4JJsiur7kna8WndbURYtXqND7UZ1m3YFEoPPcH3vBkNGTUoNK1oF0J9sRKoMfaZTbq8d2hTXuE8akH7H3xcmLdwqUEMSLtzL52ckXHv4mum+vCBuOzc1RhmzH49VFXXKk+78LqZX6wDuC+Q1JKqH0p8vXfHzoZw9yMLjcVSGrpv9muhqSnq4jZDfnHxDeYKSVJGipQOD88Xdwp1RRHlaPe37+JcTnoVW7/Tv//f2ikIAABQGPxKAZAQDx0HiP8600PHgXS4wIgLUJDXmjWmQAAAAHLUq7H+xt09ADm6Nvu3sV4znQMAZBX72wHiv6+1vx0AAIBc1RCrxN09AABAAWpVVnm/l6coHY2/YJIlmCT7ydlXJvUY/X6qZ60kKhqNhmN/+mvf8WbUultlWPToASHUFyuBNi7qEI49YaBzqIUdPGp8WLV6jUEMSLtNm7eG9n2OycC8OyK8+6cPHQBgjxqbouGR55aGqupa5XH9j/q5+wJJLW73de17qxK/xlyzfku46b65xmMpDb26/AMXuBlS9/aqL+7FzReSpEx09AGHhLqiiHK0ZUXFIVI63Lmc5L7XbUS5XYIAAACFwa8UAAnx0HGA+K8zPXQcSIcdsToadQEK7lrTg14AAADIZWe6uwcgR9dmzzGNAwBkHfvbAeK/r7W/HQAAgFw2P9Z33eEDAAAUmL27DT/Ey1OUjkoPPSFEo1FLMEk0cPQZST1GfYaf4hglaMofHvb9bmYTJvQPob5YCfTGE/uHAwcNcf60sGN/enHYsnWbAQzIiMl3PZiRse9HZ1zqwwf2qLEpGh59cXmoqq5VHnfBpBr3BZKS1ogTz4/NH00JzzkLl71vTJbS0M0zXgobN1sHy5Qjf3yBuUKSlLHual8S6ooiytGGdTnUeZzsulVOsEsQAACgMPiFAiAhHjoOEP91poeOA+nyXKy9jLwABXWtWWP6AwAAIIdtidXaHT4AObYuu0+sraZxAICsY387QPz3tva3AwAAkOt+4g4fAACg8Oy1d2nlCi9QUTpaVvee5ZckaWqKhkiv0Uk/RvMWLvXhxumNFe+EfXse6bvdjDr2Hh7WzO8YQn2x4mzm1PJQ3Gu486eFnXvp5NDQ0GgAAzKiobEx9Bzy44yMfy++/LoDAHyraDQannypLlRV1yrP6zfyTPcGkpLaDVPvb8a8E8LDzy41Lktp6P4nF39xrUf6Pf7sPPOEJClj9SgZEt6IFIe6oohysF/ud6DzOMm1Kq2YaYsgAABAYfALBUBCPHQcIP7rTA8dB9LpWCMvQEFda9aY+gAAAMhxD7nDByDH1mUfNX0DAGQl+9sB4r+3tb8dAACAXLcx1n+6ywcAACgwe5dWXuAFKkpHVXfMtPySJKtWr0nJMTrjwut8uHHY9vn20H/keN/rZjb5dweGUF+sONr2RrswYUJ/500LK+p1VLjvkWcMXkBG/fGpuRkZAwcc+TMvUAe+1e4x4ql5daGqulZ53vnXzHB/ICnpte0+Kixe9lbC889nn+8MUx+Yb3yW0tDrK1a76M2AhsbGUH74SeYKSVLG+tV+B4a6oohysPvad3EOJ781dggCAAAUBr9QACTEQ8cB4r/O9NBxIJ3WxPoXoy9AwVxr1pj6AAAAyAND3eUDkCNrsiNM2wAAWcv+doD472/tbwcAACAf3OkuHwAAoMB8r3zYPnuXVTR5gYpS3aiTL7D0kiTPv7QoJceo+MDRYfOWz3zAe3DWr2/0nW5mfYcMCTuXtQuhvlh76O3nO4eBFYc7b1pYt0EnhteW1hu4gIwbeeL5GRkH75n5hA8f+EbRaAjPzH8rVFXXqgDqU3m6ewRJKengUePD9h07E56HVq7eYHyW0tCUGS+FTVu2u/jNgElTppsnJEkZK1I6PLxQ3CnUFUWUYy2JtAv7llU4j5Nd6dD2dgkCAADkP79OACTEQ8cB4r/O9NBxIN1+Z/QFKJhrzRrTHgAAAHngnVj/4E4fgCxfj/1fsd4zbQMAZC372wHiv8e1vx0AAIB8EI11kDt9AACAAtOqtPJFL1BRqmvbfVTYvOUzyy9JcHv1H1N2nO6ume0D/haznprr+9yCnr2vNIT6Yu2hmVPLQ/sDvSitpVX86NzwybqNBi4g45aueDcj4+B+3z82bPvci9OBb/bCwndCVXWtCqDzrrnPPYKklDbxmqnNmovmvPqucVpKQzOfWhKiUde/6fbRmvVf/DZmnpAkZarj9u8f6ooiysEO73qYczjJtSqrOMkOQQAAgPzn1wmAhHjoOED815keOg6kW0OsLkZggIK41qwx7QEAAJAnfulOH4AsX4/9tekaACCr2d8OEP89rv3tAAAA5ItFsf7G3T4AAEAB2buk4ideoKJ09Ngz8yy9JMHul9Sm6hgNOe4sH/A3WLV6Teh00Fjf5WZ27AkDQ6gv1re0Y1m7MPGCfs6XJHT6r64N23fsNHABWeHMi67PyFh42fV3+fCBbzTn1XdDVXWtCqTeFePdJ0hKaa27jQjPzV2U8HzU2NQU7pv9mrFaSkNL3/rIRXAGnPTzK8wTkqSMdl/7LqGuKKIc6+zOfZy/ya608g47BAEAAPKfXyYAEuKh4wDxX2d66DiQCc8YgQEK4lqzxpQHAABAntgWq627fQCydC12ny/nKgAAspf97QDx3+fa3w4AAEA+OcXdPgAAQAGJlI/+l1alFZ97iYpS3dmX3GjZJQlS/RLGN99a6UP+M7t2NYQjfnC273Ez27dHRXjn+c4h1BfrG3o79vkMrDjc+dLC2nYfFe6471GDFpA11m3YFCK9Rqd9PNynfGRYtXqNAwD8VfMWrwxV1bUqkM664h73CpLSUvnhJ4VPN21NeF7auHlbmDLjJWO2lOJuqZkXNm/d7mI4zZ6bu8gcIUnKaH1KBoflRZFQp5zqDx1KnL9JrlVZ5Vt2CAIAAOQ/v0wAJMRDxwHiv8700HEgU44yCgPk/bVmjekOAACAPHKfu30AsnQt9iHTNABA1rO/HSD++1z72wEAAMgnG2L9f+74AQAACkirssr7vURFqa7boBNDNBq19NJChx1zZkqP00VX3+ZD/jO//t3tvsMt6LKL+4ZQX6xv6P7bykP7AyucKy2s9NATwvxFywxYQFa59pb7MjImnvyL3/rwgb9q/pI/harqWhVIN06bE7ofcYr7BUlp66fn/65Z89Piug+N21IaevjZpS6I06ypKRp6DxtnjpAkZbQrO/UIdUUR5VCvFbUL+zh3k17bHkf8lx2CAAAA+c0vEwAJ8dBxgPivMz10HMiU92P9o5EYIK+vNWtMdwAAAOSZQ9zxA5Bl67CHmZ4BAHKC/e0A8d/r2t8OAABAvrnJHT8AAEAB+V5J5QgvUFE6em1pvWWXFup00NiUHqP9vn9s2Pb5dh/0l56tfTW07jbC97eZlQ4YGra83iGE+mL9WVsXtw9nnNHfeZKEhhx3Vlj98VoDFpBVGhoaQ/nhJ2VkXHz51WUOAPAXXnljVaiqrlUB9dOJt7lfkJT2Hpo9p1nz1Kznlxm7pTS0/J01LozT7Mbb7zc/SJIyWsfSYeGVSPtQVxRRDjWg6yDnb7IrrTjKDkEAAID85lcJgIR46DhA/NeZHjoOZNKlRmKAvL7WrDHVAQAAkGd2P/jqb931A5Ala7B/H6vO9AwAkBPsbweI/37X/nYAAADyTWOsMnf9AAAABaJz59F/v3dp5TovUVGqu/z3d1t2aYFNm7em5Tjd+8CTPuyYj9asD10GHO+724Luv608hPpi/VlLZh8Q+g0Z4hxJQudeOjns2tVgwAKyzgOPPZ+RcfGQ0aeHaDTqAABfM+/1laGqulYF1A33vBD2H/Aj9wyS0t5+3z82rP54bcJz1dZtO8JtM182hksp7tb7Xw6ffb7TBXIard+4ORT1OsocIUnKaKd2PijUFUWUQ53Zua9zN8m1Kqu83g5BAACA/OZXCYCEeOg4QPzXmR46DmTS9lhtjcYAeXutWWOqAwAAIA+Nd9cPQJaswf7ctAwAkDPsbweI/37X/nYAAADy0Qvu+gEAAApIq9KKKV6iolTXr/I0Sy4tsHTFu2k5TgOOOj1Eo9GC/qwbGhvDyBPP971tQUOOHBSaVrQLob5YXxatKw63X98z7NujwjnSwiK9RofpDz9tYgCy1hE/ODsj42P1Q8ZG4OtqF70bqqprVWD96Kzr3TdIBViXgSdkxd8x5tSJzVpbrP/TWmO4lIZm165wkZxmp513jXlKkpTR2pRVhFnt9g91RRHlSFM7lDp3k11p5SK7AwEAAPKbXyQAEuKh4wDxX2d66DiQadOMxgB5e61ZY5oDAAAgD62L9S/u/AHI8Prrv8Vab1oGAMgZ9rcDxH/Pa387AAAA+WqEO38AAIAC0bps+GAvUVE6WvH2nyy5NNPs515O23F6+dVlBf1ZX1l1j+9rS17MVl4RXn+sSwj1xfqydQs6huNOGOj8SEI9h/w4LF72lkkByFqvLqnLyPjYZcDxYfuOnQ4A8JU5r74bqqprVWBNuvOZ0K73GPcOUgE29ISLwpDjL8iKv2XqtFnNmruefKnOWC6lofc+8OyfdJq3cKl5SpKU8QZ1PSysKIqEOuVECyMdQpuyCuduMiutaPyPjhX/ZIcgAABA/vKLBEBCPHQcIP7rTA8dBzItGquPERkgL681a0xzAAAA5Kmr3PkDkOH11+tNxwAAOcX+doD473ntbwcAACBfvRPrH9z9AwAAFIB27Qb/w96llVu8SEWp7tpb7rPk0ky3TZuVtuM07pyrCvZznjN/cWhTPsL3tQWd9fPvh1BfrC97oaYklB481LmRhH7ws0vCps1bTQhAVjvl3KszMkb+9sZ7fPjAV15Y+E6oqq5VAXbkKZe5d5AKtEOOPidcd/dzoevAkzL+t0R6jQ71776f8Py1Y2dDuPvhBcZzKcXdFfue7drV6KI5TaLRaOg/cry5SpKU8W7q0C3UFUWUI/UtOdx5m+Rad6s83A5BAACA/OUXCYCEeOg4QPzXmR46DmSDebH2MioD5N21Zo0pDgAAgDy1M1Y7d/8AZGjtNRJrh+kYACCn2N8OEP99r/3tAAAA5LMJ7v4BAAAKRKuyyvu9REWp7rBjzrTc0ky/ufaOtB2ntt1HhY/WrC+4z3jdhk2h7LATfFdbUKc+w8PaVzqGUF9c8G1f2j5c+Mt+u1/O5dxoYfuUjwyTpkwPTU1RkwGQ1T74aO0X11HpHicL9doN+EvRaDQ883J9qKquVQF2xZTHYnPCke4hpAKtd8X4L8aCidc/mBVjwZDjzgoNjY0Jz2Xvf/ypMV1KQ7WL3nPxnEa3TZtlrpIkZbySkqHh9aJ2oa4oohzop/v3c94mvYrf2B0IAACQv/waAZAQDx0HiP8600PHAddwAKTqWrPG9AYAAEAem+HuH4AMrb0+aBoGAMg59kYBxH/fa387AAAA+WxjrP+wAgAAAFAA9i6t+KEXqCgd/emDjy25NMP4Cyal9ThdPXlaQX2+TU3RMPa0i31HW9gt1/YMob644FvxzP7h0MrDnRNJqPzwk8L815abBICccMmkOzIyVp523jU+fCBEo9Hw9Lz6UFVdqwJt0HHnu4eQCrjSQSd/NR6ceM4NWfE3XX/bjGbNaXNefde4LqW4ydPnhrUbtrqITpPNWz4L7Xofbb6SJGW8czr3DnVFEeVAN3Usc84mv6fsDgQAAMhffo0ASIiHjgPEf53poeNAtngv1j8YmQHy6lqzxvQGAABAnutnBQCANK+79okVNQUDAOQc+9sB4r/3tb8dAACAfHedFQAAAIAC0Lrz6H/fu7SywUtUlOpuvvshyy3NMHrchWk9Tl0POT7s2LmzYD7f3S/59f1sWf2GDAk7l7ULob64YGta0S7cfn3PsG+PCudEEjrmlIvC2vUbTQBATtj62eeh00FjMzJeLly8wgGAAtfYFA2za1eEqupaFWgTr38wtO42wn2EVMB16Hfs18aFw8ael/G/ad+eR4Y331qZ8LzW0NgUpj26yPgupbgZs18P0ajnAaXLhIm/N19JkjJe27KK8Gxxp1BXFFGWN7e4g3M22ZVWbv7O6NF/Y25MbcEAACAASURBVIcgAABAfvJLBEBCPHQcIP7rTA8dB7LJ2UZmgLy61qwxtQEAAJDnXo61l1UAANK05rpXrAWmXwCAnGR/O0D897/2twMAAJDvdr88ub1VAAAAgALQqrTyRS9SUaqrPOE8yy3N0H/k+LQfq5pZzxbEZzv/teWhbfdRvp8t7LkZpSHUFxds78/dL4w69jDnQjJe6Bf7PlbdMdNLfYGcctu0WRkZMweP/YUPHwrcrobGMOv5ZaGqulYFXN8RZ7iXkAq8NuUjw43T5nw1Lky685mw/8HHZ/zvGjRmQmiIzVWJWrtxa7j5vrnGeCnFLa5b7YI6TV5dUme+kiRlRUcfcEioK4ooByorOcI5m+Radx15gN2BAAAA+ckvEQAJ8dBxgPivMz10HMgmn8b6d6MzQN5ca9aY2gAAACgAR1oFACBNa67HmHYBAHKW/e0A8d//2t8OAABAIbjPKgAAAEABaFVaebaXqCj1L3gdET5Zt9FyS4I69Rub9mN18Kjxoakpmtef67oNm0L54Sf5brawE398SAj1xQXbzKnloWPv4c6FJNR98EnhldffNOgDOaWxqSn0HjYuI+Pm/X98zgGAArZjZ0OY+dSSUFVdqwJuwmV3u5eQ9EWT7nrma+PD+dfMCG3KR2b+75oyvVnz3MKl7xvnpRQ3ZcZLYfPW7S6s0+SwY840X0mSsqJ7O5SEuqKIsrzj9z/Y+ZrsSip+YncgAABAfvIrBEBCPHQcIP7rTA8dB7LN5UZngLy51qwxrQEAAFAA6mP9rZUAAFK83vo3sVaYdgEAcpb97QDx3wPb3w4AAEAh2P3y5G5WAgAAAPJc67Lh7bxEReno7prZllsS8Pn2HRk7VrOfezlvP9empmgYe9rFvpMtrKhnRVj54n4h1BcXXOsWdAwnjxvgPEhSY06dGNau/9SgD+Scx5+dl5Fxs2TgD8OOnTsdAChQ2z7fGaY//lqoqq5VAXfDPS+ELgNPcD8h6Ysuu/mxvxgnjjvjmoz/XW27jwpL3nwn8d1q0RAefHqJ8V5KcX98fpmL6zTZ/duY+UqSlA316Xp4WF4UCXXK6q7s1MP5muxKK2+3OxAAACA/+RUCICEeOg4Q/3Wmh44D2eazWP9lhAbIi2vNGtMaAAAABeJEKwEApHi9dZzpFgAgp9nfDhD/PbD97QAAABSK2VYCAAAACkCr0op3vUhFqW7MqRMttSRg5fsfZexYHfGDs/P2c7168jTfxyT020v6hlBfXHA9M700lA04wjmQpJdrT5oyPTQ1RQ34QE4addIvMzJ+/u7mah8+FKjNW7eHe2YtDFXVtSrwjj3jGvcUkr7qwmvv/4tx4sZpc0K/kWdm/G877Jgzw65dDc2a8265f54xX0px77y/zkV2Gmz97PPQse8Yc5YkKSu6qmOPUFcUURb3x3adnavJb7mdgQAAAPnJrxAACfHQcYD4rzM9dBzIRjcaoQHy4lqzxpQGAABAgVgd639ZDQAgRWut/0+s9023AAA5zf52gPjvg+1vBwAAoJAMsBoAAACQ5/YurbzDS1SU6tr2GBU2btpiqSVOC15/M6PHa878xXn3mT43d1FoUz7C97GFlR48NGxZ3D6E+uKCafNrHcK5Zx/k+CepnkN+HBYuXmGgB3LWkuVvZ2T83LfnkeGTdRsdAChAGzZtC3c+9Eqoqq5VgXfFlMdi88FR7iskfdVZV9zzV8eLq257InTod2zG/75rbprWrLlv2dsfG/elFHdH7Ppyx84GF9tpcN5lN5mzJElZUafSoWFBcftQVxRRlrY8Uhw6lA53via1iqa2JZX/ancgAABA/vELBEBCPHQcIP7rTA8dB7LRrljFRmmAnL/WrDGlAQAAUEAmWA0AIEVrreeYZgEAcp797QDx3wfb3w4AAEAheSXWXlYEAAAA8lir0uE/8hIVpaO7a2ZbaonT7OfmZ/RYHT3uorz6PD9csy50GXC872ESevD28hDqiwum52tKQvnAoY59kvrRGZeGjZu2GOSBnDb+gkkZGUNP/9W1PnwoQB9+sincev/Loaq6VgoDx5zjvkLS1/rphbd+45hxzpXTQptuIzL697XtPiosXvZWs+bAR19cbuyXUtyLC99xwZ0Gy+tXmrMkSVnTGfv1DXVFEWVxFV0GOleTXOtulYfbHQgAAJB//AIBkBAPHQeI/zrTQ8eBbPUHozRAzl9r1pjOAAAAKCDrYv2zFQEAkrzO+i+x1ptmAQBynv3tAPHfC9vfDgAAQKGpsCIAAACQx75XPmwfL1FROqr40bmWWeI0/eGnM368Fi5ekRefZUNDYxhx4vm+g8n4Dh9zWIjWFYdQn/9tWdw+nHv2QY57El+iPWnK9NDUFDXAAznt40/Wh7Y9RmVkLH196VsOABSYlas3hCkzXgpV1bVSOOfKae4tJP1FJ559w7eOHUedekXG/8aDR40PO3buTHge3LZ9Z7j9gfnmACmFTZ5eGz5et8WFdxoMO/4c85YkKSvaJ9aTxfuFuqKIsrQL9uvtXE1+v7Y7EAAAIP/49QEgIR46DhD/daaHjgPZqilWFyM1QE5fa9aYzgAAACgwF1sRACDJ66yXml4BAPKC/e0A8d8L298OAABAoXkj1netCgAAAOSxvcsqVnqJilJd624jwnurPrTUEoeb734o48frpJ9fkRef5YVX3er7l4TalFeEJU8cEEJ9cd73Qk1J6HHoEY57kuox+OSw4PU3DexAXrjihj9kZCwd/sNzffhQYN58d0246b65oaq6Vgo33PtiKDn0JPcXkv6iMT+7ao/jR8+hp2X877yy6p5mzYfvfbDePCCluOmPvxaamqIuwFNsxiPPmrckSVnTkV0OCXVFEWVp09p3dZ4muValFU/YGQgAAJB//PoAkBAPHQeI/zrTQ8eBbDbTSA2Q09eaNaYyAAAACszmWP9uVQCAJK2x/kesLaZXAIC8YH87QPz3w/a3AwAAUIjGWBUAAADIY3uXVd7lRSpKR7+7udoySxyuqro348eqdbcR4c23Vub05zjrqbm+d0nqnLO/H0J9cV63+bUO4dyzD4qd+453sjpxwuXh001bDepAXvh8+45wwME/yMh4+tDsOQ4AFJB5i1eGqupa6at++Ivr3F9I+qtVnnTJHseQy25+NER6HZ3Rv7Nt91Hh9aVvNWtefGb+W+YCKcUtWv6Bi/AU275jZ9j/4OPMXZKkrOmeDl1DXVFEWdhrRe3CPqUVztMk1qqs4tPvfOfi79odCAAAkF/8+gCQEA8dB4j/OtNDx4FsFo1VYrQGyNlrzRpTGQAAAAXoEqsCACRpjfUK0yoAQN6wvx0g/vth+9sBAAAoRG/G8hxZAACAfNWqpPIEL1JROuo9bFyIRqOWWvbg/Mtvzorj9YOfXZKzn+F7qz4MnfqN9b1LQp36DA9rF3QMob44b3t6elkoHzjU8U5SkV6jw9Rps4z3QF65u2Z2RsbUboNODA0NjQ4AFIDGpqbw1Et1oaq6Vvqqq257InZ9fbT7DEl/tUHHnhfXWHLKr6Zk/G8dcOTPws6duxKeH3fuagx3P7zAnCClsCkzXgqbtm53QZ5iF151q7lLkpQ19el6eFheVBzqiiLKwvp3HeQ8TXL/VVrR2e5AAACA/OKXB4CEeOg4QPzXmR46DmS7+43WADl7rVljGgMAAKAAbYr1b1YGAGjh+up/xNpiWgUAyBv2twPEf09sfzsAAACF6hgrAwAAAHnqP7sOL/ISFaWrV15/0zLLHpx67tVZc7xefPn1nPv8tu/YGQaNmeD7lqRuu75XCPXFednaBR3DuFMHOM5J7JDRp4c331ppIAfySlNTNHx/5E8zMq5ed+sMBwAKwI6dDeHBZ94IVdW10tca/IML3GdI+sb6jTwz7vHk0LHnZfzvvfz3dzdrnnz/40/NCVKKm/X8MhflKbZ0xbvmLklSVnVlpx6hriiiLGx8537O0STXqqziJLsDAQAA8otfHgAS4qHjAPFfZ3roOJDtorFKjNgAOXmtWWMaAwAAoED92soAAC1cX73cdAoAkFfsbweI/57Y/nYAAAAK1fJY37U6AAAAkKdalVV84EUqSkfnXjrZMssejD3t4qw5XoPH/iI0NUVz6vP72a+u9V1LUgcPGxwa3mwXQn1xXhWtKw4zp5aHAw4a5jgnqTblI8Ll198Vdu1qMIgDeefpOQszMrYW9ToqrNuwyQGAPLd56/Yw7dFXQ1V1rfS1zrlyWmjdbYT7DUnfWPngcXGPKZPufCbs1//4jP69+5SPDIveqGvWfPns/LfMDVKKe+tPa12cp9igMRPMX5KkrKlj6bCwoLh9qCuKKMu6qUM352iSa1VWcZudgQAAAPnFrw4ACfHQcYD4rzM9dBzIBfcbsQFy8lqzxhQGAABAgdr9AK1/szoAQDPXVv891mbTKQBAXrG/HSD++2L72wEAAChkx1gdAAAAyFN7l1bM8iIVpaPO/Y8LO3butMzyLYYef3ZWHbMHHns+Zz67KX942Pcsib1wf0kI9cV51araTmHMDwc6vkmsx+CTw7yFSw3eQN46etxFGRlfJ0z8vQ8f8twn67eGOx6cH6qqa6Wvdf0fng8HHHKC+w1Je1hnPT6hseXcq6aH1t1GZPRvPnjU+LBz566E58yduxrCXQ8vMEdIKWz3demOnQ0u0lPo9uo/mr8kSVnV6Z37hbqiiLKsOcUdnZ9JrlVZxVI7AwEAAPKLXx0AEuKh4wDxX2d66DiQC6Kxuhq1AXLuWrPGFAYAAEAB+7XVAQCaubZ6mWkUACDv2N8OEP99sf3tAAAAFLLlsb5rhQAAACAP7V1WeYkXqShdPfr0S5ZZvsWAI3+WVcer++CTwvYdO7P+c5szf3Fo232U71iSOnncgBDqi/OmphXtwr039Qgdeg93fJPYuHOuCp9u2mrgBvL3l7H6lRkbY99Y8Y4DAHnsvQ/WhykzXgpV1bXSX3TUab91vyFpj0V6HZ34+HLqFRn/u6+qurdZc+fK1RvMEVKKe37B2y7UU2jDp5vDvj2PNIdJkrKmfcoqwlPt9gt1RRFlWSUlQ52jSa2iKVI++l/sDgQAAMgffnUASIiHjgPEf53poeNArqgxagPk3LVmjekLAACAArYp1r9ZIQAgwXXVf431qWkUACDv2N8OEP+9sf3tAAAAFLqjrRAAAADkodbdKkZ6iYrS1YkTLrfE8i16HfHjrDtmN931YFZ/Zu9/+EnoMuB4368kVdSzIrz34n4h1BfnRSue2T8MHX2YY5vEOvUbG+594EkDNpD3Jkz8fUbG2ZEnnu/Dhzy2uO7DMHn63FBVXSv9RRN//2BoUz7SfYekPda624hw47Q5CY0xN9zzQug+eFxG/+62PUaF5fUrmzWHPj2v3lwhpbDJ02vDmvVbXLCn0LhzrjKHSZKyqoouA0NdUURZ1pgDDnZ+JrnvlQ4/zO5AAACA/OEXB4CEeOg4QPzXmR46DuSKplidjdwAOXWtWWP6AgAAoMBdZIUAgATXVX9t+gQAyEv2twPEf29sfzsAAACF7o1Ye1klAAAAyDP/WVK5r5eoKJ0vTt3w6WbLLN+gy4Djs+6Yde5/XPh009as/Lw+27Y9DBx9hu9WErv60j4h1BfnfA1vtguTrzkw7NujwnFNYiNPPD+8/+EnBmsg761ZuyHs2/PIjIy1jz79kgMAeaixqSk8M/+tUFVdK/3Vbpw2J/Qcepr7DklxN+nOZxIeay69aVYo6nVURv/uQWMmhIaGxoTn0h07G8KdD71izpBS2IwnXg/RaNTFe4o8M2eh+UuSlHXd26Ek1BVFlEVd0qmnczPJtSqtmGh3IAAAQP7wiwNAQjx0HCD+60wPHQdyyZ1GboCcutasMXUBAABQ4NbH+kerBADEuab6j7HWmT4BAPKS/e0A8d8f298OAAAAIQy1SgAAAJB/9mpVVvGpF6koXd1x36OWWL5BpNforDxm519+c9Z9Vrtf7nnquVf7TiWx8oFDw7Y32oVQX5zTLfxjl3DwsMGOaRJr231UmDRlemhsajJQAwXhihv+kJHxtsfgk0NDY6MDAHnm8x27woPPvBGqqmulb+yEs37v3kNSQl0+5bFmjTcnn1eV8b/9prsebNacunL1BnOGlOKWvf2xC/gU2X2/323QieYwSVJW1afr4WF5USTUKWuqad/FuZnkWpVVPG5rIAAAQP7wiwNAQjx0HCD+60wPHQdyya5YbY3eADlzrVlj6gIAAIBwulUCAOJcU/25aRMAIG/Z3w4Q//2x/e0AAAAQwhyrBAAAAHmoVVnF816konR12DFnWmL5K5qaoqF1txFZeczalI8IC15/M6s+r+tvm+H7lOQeur08hPrinG3L6x3CBecdFDtfKxzPJNZ72Lis+/4DpNJn27aHzv2Py8iYW3XHTAcA8sy6Tz8Ldz+yIFRV10rf2BVTHguRnqPdf0hKqIm/f7DZ487Bo8/K6N/ervfRYeX7HzVrbn3qpTpzh5TCps58OWzfscuFfIpc/vu7zWGSpKxrUsfuoa4ooixpSaRd2KfM793JrFVZxYbvfOc7e9kdCAAAkB/82gCQEA8dB4j/OtNDx4Fcc53RGyBnrjVrTFsAAAAQ3o/1d1YKANjDeurfxVpl2gQAyFv2twPEf49sfzsAAAD8t75WCgAAAPJMq9KK67xIRens1SV1llj+zNbPPs/qY3bI6NNDQ0NjVnxWL8x7LexTPtJ3KYlVHnNYiNYVh1Cfmz09vSx0P/QIxzLJnXHhdeGzbdsN0EBBmTptVkbG3Ha9jw4bN21xACCPvL1qXZgy46VQVV0rfWv9j/q5+w9JCXfe1dObPe5cPfWp0LHfsRn9+0ePuzBEo9GE59ftOxrCHQ++Yv6QUtjzC952MZ+qe4SVH5jDJElZ1wGlQ8OiSLtQVxRRljSg6yDnZrIrHdre7kAAAID84NcGgIR46DhA/NeZHjoO5Jptsf6PERwgJ641a0xbAAAA8IXjrRQAsIf11BNNlwAAec3+doD475HtbwcAAID/9kcrBQAAAHmmVUnlCV6ionR25kXXW2L5M+s2bMr643b9bTMy/jm9s3J16HTQWN+jJNamvCIsmX1ACPXFOdd7L+4Xjj1hoOOY5Loecnx44vn5Bmag4DQ0NoYDh/4kI2PveZfd5ABAHlm0/IMweXptqKqWvr3xE29zDyKpWU247O4WjT9nXXFPaN1tREb/DdMeeLJZ8+x7qzeYQ6QUtvs6ds36LS7qU6TyhPPMY5KkrOu8/fqEuqKIsqTxnfs5L5Pc90pHjLU7EAAAID/4pQEgIR46DhD/daaHjgO56NdGcICcuNasMWUBAADAF96M9V2rBQB8w1rqXrGWmy4BAPKa/e0A8d8n298OAAAA/y0aq9RqAQAAQB75Xsnwvl6ionQW6TU6bNzkpYz/05q1G7L+uLXtMSosefOdjH1G6zZsCr2HjfMdSnLnn3NQCPXFOdX2pe3DpMt7h6KeFY5hkjtu/CVh7fqNBmWgID3yZG1Gxt7W3UaEt1d+4ABAHtjV0Bger30zVFXXSnvs6qlPhQ59x7oPkdSsTrvwlhaPQ5U/viSj/4ZOB439Yk20OZ6cu8JcIqWw+59cHKJR1/epMO2BJ81jkqTs279ROjzMKe4Y6ooiyoJu7FjuvExyrUorr7U7EAAAID/4pQEgIR46DhD/daaHjgO5aPcm3P9tFAfI+mvNGlMWAAAAfKXCagEA37CWOso0CQCQ9+xvB4j/Ptn+dgAAAPi/7rFaAAAAkEf2KR/5PS9RUbq75Z6HLbH8D6s/XpsTx63/yPHh8+070v75bN+xM1T86FzfnSTXud+wsOHVDiHUF+dMT08vCwcOGuL4JftF1v3GhnsfeDJEvS0XKGBH/ODsjIzBx5/+Gx8+5IFPt3weqh9bFKqqa6W4OuToc9yLSGp2J55zY4vHoevveT6UHHZyRv8dJ//iimauFe4Kdzw433wipbDl73zsIj8Ftny2LbTrfbS5TJKUdZ2w//dDXVFEWdCzxZ2ck8mutGKO3YEAAAD5wS8NAAnx0HGA+K8zPXQcyFUTjOIAWX+tWWO6AgAAgK/MtVoAwDespb5smgQAyHv2twPEf59sfzsAAAD8Xw2x2loxAAAAyB977V1auc2LVJTO+lacGqLRqGWWL61avSZnjt0vr7g5rZ9NY1PTFy/Y9b1Jfnf8vmcI9cU50UfzOoVxpw5w3FLQmFMnhg8+WmsgBgravIVLMzYO176yxAGAHPfe6g3h1vtfDlXVtVJcnfqrW9yLSGpRx51xTVLGo4uueyC06T4qo/+WPz41t1nz79ur1plTpBQ2debLYfuOXS72U+D0X11rLpMkZV2tY81qt3+oK4oow62I1bl0mPMymZVWbvtO//5/a3sgAABA7vMrA0BCPHQcIP7rTA8dB3LVylh/YyQHyOprzRrTFQAAAHxNLysGAPzZOmof0yMAQEGwvx0g/ntl+9sBAADg635nxQAAACCPtCqrXOZFKkp3ta8sscTypZXvf5RTx276w0+n7bOZeM1U35cUNGD44NDwZrsQ6ouzut1/4+3X9wwdeg933JJcu95Hh8l3PhCamqIGYaDg/eiMSzMyFh8y+vQQjRqHIVft/v7OW7wyVFXXSnH321seD8W9j3FPIqlFHXnK5Ukbl44Zf1VG/y1dBhwf1m/c3Ky5eHbtCnOLlMJeWPC2i/4UmLtgiblMkpSVDekyMNQVRZQFjepyiHMyybXuOvIAuwMBAAByn18ZABLioeMA8V9neug4kMtGGckBsvpas8ZUBQAAAF9TbcUAAOuoAAAFyf52gPjvle1vBwAAgK/b/TKTf7ZqAAAAkCf2Lq2Y5SUqSnennHu1JZYvvb3yg5w6dpFeo8OSN99J+edy672P+K6kqBdqSkKoL87qXn6oaxgwfLDjlYJGnfTLsPL9jwy+ADHvrFwd2pSPyMh4POORZx0AyFHbtu8KDz3zRqiqrpXi7sZpc8JBR05wTyKpxQ078eKkjU033Pti6H7EKRn990yY+Ptmz8dTH5hvjpFS1OTptWHthq0u/pMsGo2GPsNPMZ9JkrKy2zuUhLqiiDLcBfsd6HxMcq3KKk60OxAAACD3+ZUBICEeOg4Q/3Wmh44DuWyOkRwgq681vQwWAAAAvq4hVhurBgB8uYa6z5dzAwAA+c/+doD475ftbwcAAIC/dLpVAwAAgDzRqrTiOi9RUbpr231UWLN2gyWWmPp3VuXc8es55MfhozXrU/aZPP7svNCmfITvSgr6yakHx0664qxt7YKO4cwz+4fW3RyrZNex75jwh/tnf/HiVgD+2zmXTs7ImFwy8Idhx86dDgDkoE82bA13P7IgVFXXSgl14jk3ui+RlJQGHXteUsenS6oeDm17HJnRf9ML815r1rz81p/WmmOkFFbzxOvBUmLyTZoy3XwmScrKepQMCcuKikNdUUQZ7N72Jc7HpFcx2e5AAACA3OcXBoCEeOg4QPzXmR46DuS6HkZzgKy91qwxTQEAAMBf+K1VAwC+XEO92rQIAFAw7G8HiP9+2f52AAAA+EvvxfobKwcAAAB5YO/SijO8QEWZ6PrbZlhiiVnx9p9y8vgNOOr08OmmrUn/POYtXBqKDxztO5KCinsND6tqO4VQX5x1NbzZLtxybc/Qqc9wxyoFHT3uovD+h58YcAH+h3UbNmXsmuO6W10HQy5a9vbH4eb75oaq6lopoS67+dFQ1Oso9yaSktL3j/x50sepH/7iuoz+m3od8ePw2bbtzZqfH69901wjpbDl76xxI5BkH3y0NrQpH2FOkyRlZb/t1CPUFUWUwRZF2oc2ZRXOxyTWqqxygd2BAAAAuc8vDAAJ8dBxgPivMz10HMh19xjNAbL2WrPGNAUAAAB/YWOsf7RyAFDw66f/b6wNpkUAgIJhfztA/PfM9rcDAADAX1dh5QAAACAPtOo2YpiXqCgT9Rzy49DY1FTwKyxvvfdBzh7Dih+dG7Zs3Za0z2Lh4hWhQ99jfD9S1KTLe4dQX5x1zZlZEgZUDHaMUtDu79PdNbNDNBq1nA3wZ353c3VGxuZIr9Fh/cbNDgDkkJ27GsOTL9WFqupaKeFumDYnHDjsp+5PJCWt3WNKsseqG3ePVcPHZ/TfNfGaqc2ap7d9vjNMnfmyOUdKUVMfmB+272xwU5Bkx5xykTktBbWO1ber3xokqSV1LB0WFkY6hLqiiDKY+Sy5tSqr3NG58+i/t0MQAAAgt/l1ASAhHjoOEP91poeOA7luV6zWRnSArLzWrDFNAQAAwF91mpUDgIJfPx1vOgQAKCj2twPEf89sfzsAAAD8dc9ZOQAAAMgDrUtG9PQSFWWq2c/NL/gVlvdWfZjTx/CwY84Mn6zb2OLP4fWlb4VOB431vUhR3Q89Imx7o10I9cVZ03sv7hdOOW2A45Oijh53UVi1eo1lbIC/4vPtO0KXAcdnZHw++zdVDgDkkE82bA33zFoYqqprpWb1gwnXuj+RlNRKB52ckvHqspsfDUW9jsrYv2uf8pFh8bK3mjVfr3jvE3OOlMJeWPiOG4Mke/CxF8xpKepH+38/jOpyiM9CklrQhM59Ql1RRBns5Nh85lxMbm3KKrrbIQgAAJDb/LoAkBAPHQeI/zrTQ8eBfHCZER0gK681a0xRAAAA8FetiLWX1QOAgl07/W6sOtMhAEBBsb8dIP77ZvvbAQAA4JuVWj0AAADIcf/ZdXiRF6goU4088fyCX11ZtXpNzh/H3sPGhbq3VzX7M5i7YEno2HeM70QKm3V3txDqi7OibW+0C5Mu7x2KelY4NimoQ99jwl0zHg/RaNTyNcA32D1OZmKMbt1tRKh/Z5UDADlicd2H4eb75oaq6lqpWV143cywT49R7lMkJbX9vv+DlI1bPz5/ckb/bYeP/XloaGxs1rz9yHNLzT1Sipo8vTasWb/FDUIS9ItGbgAAIABJREFUbd+xM3Q6aKx5LQXtU1oRZrXbPwzrcqjPQ5Ka2b5lFeH54k6hriiiDHVVxx7OxSTXqnTEaXYIAgAA5Da/LgAkxEPHAeK/zvTQcSAfrIv1D0Z1gKy71qwxRQEAAMA3OszqAUDBrp0ONg0CABQc+9sB4r9vtr8dAAAAvtltVg8AAABy3P/pPPp/e4GKMtmiN+oKenXlwzXr8uI4RnqNDndMfzREo9GE/v1/fGruF/9d34XUNXLMoSFaVxxCfWbb/TfMnFoeSg8e6rikqNHjLgyrVq+xbA3wLRqbmkKf4adkZJw+bvwlDgDkgO07GsKjLy4PVdW1UrO77u7nQteBJ7lPkZSCNbijUzp+ff/In2f033frvY80a/7+dMvnYcqMl8xBUoqqeeL1kODSP3tw7qWTzWspaswBB4clkXZhaJdDfR6S1MyOP6B/qCuKKEM90m5/52GyK6283Q5BAACA3OaXBYCEeOg4QPzXmR46DuSLsUZ1gKy71qwxPQEAAMA3etDqAUDBrp0+YhoEACg49rcDxH/fbH87AAAAfLNtsf7NCgIAAECOa1Vaud1LVJSpTjn36oJeXflk3ca8Op6jTr4gzF+0bI//7oaGxvCba+8IrbuN8D1IYfuUV4TlTx0QQn1xRlv8+AFh+NGDHJMU1aHvMeHOGY+FqDfbAuzRzEefz9h4/cK81x0AyHJr1m8Jf5i1MFRV10otavAPLnCvIikl7V5Lu3HanJSNX1feOjsU9zkmY/++dr2PDu9/+Emz5vGFy943B0kp7M1317hhSKJFb9SZ11LYQ+0PCEsi7cIRXQ71eUhSc+47Ys1qt3+oK4ooAy0rKg77llU4F5NYq9KKN+wOBAAAyG1+WQBIiIeOA8R/nemh40C+eNGoDpB115o1picAAAD4Rg2x9raCAFBw66ZtYjWaBgEACo797QDx3zvb3w4AAADf7nQrCAAAADmuVVnFB16ioky1T/nIsGp14b6Mcf3GzXl5XEed9Mtwe/UfwzsrV3/1b21sagp1b68K98x8IvStONX5n4YuOO+gEOqLM9aa+R3DmWf2D627ORapavS4Cwt6DAVIRDQaDQOOOj0j4/Xu/93d//tA9lpc92G46b65oaq6VmpRp114i3sVSSlt0l3PpHQc++mFt2b033fyL65o1lzeFLvevu/x18xFUoqa+sDLYfuOBjcOSXTwqPHmtRQ1pMvAUFcUCYsj7WL/+VCfiSS1YCxVZhrQdZDzMJmVVjT+Z9fD/tEOQQAAgNzlVwWAhHjoOED815keOg7kkwOM7ABZda1ZY2oCAACAb3WxFQSAgls3vdT0BwBQkOxvB4j/3tn+dgAAAPh2b8bayyoCAABADtu7rPI1L1FRJrvo6tsKdmVly2fbCuIYt+9zTIj0Gu18T2Od+w0LG17tEEJ9cdrbtbxduP36nqFj7+GORaqOb//jQvVDT4doNGqJGiBOTzw/P2PjdvWDTzkAkKW2btsRHnr2jVBVXSu1uEtvmhUiPd37SkptV972RMrHs4Fjzsnov3H3tXtzfLxuc5g83XwkpaoXF77jBiKJqu6YaV5LYdPadw11RZGwONIuDOlyqM9EkprRXe1LvhhLlf5O27+fczDJfa98RD87BAEAAHKXXxUAEuKh4wDxX2d66DiQT240sgNk1bVmjakJAAAAvtVHsf7OKgJAwayZ/l2sD01/AAAFyf52gPjvn+1vBwAAgD37vlUEAACAHLZ3WeVTXqCiTNa+zzFh46YtBbmq0tQUDa27jXAeKOndeWOPEOqL01q0rjg8dHt56HXYEMcghf3ojEvDx5+stywNkKDKE87LyLjd9ZDjw46dOx0AyEJvr1oXps58OVRV10ot7oZ7Xww9jjjNPYuklHfZTX9M+Zh29e1PhQ79js3Yv7HH4JPDZ9u2N2t+f2HB2+YlKUVNnj43rP/0MzcSSbL647WhTbnfh1LVgK6DwoqiSKiLtSjSPhza5TCfiyQlWJ+uh4flX46lSm/XdSx3Dia7bpUT7BAEAADIXX5VAEiIh44DxH+d6aHjQD7Z/aCGfzK6A2TNtWaNqQkAAAD2aKRVBICCWTM92rQHAFCw7G8HiP/+2f52AAAA2LPpVhEAAABy2N6lldO9QEWZruqOmQW7stKu99HOASX3ZZEVg0PDiuIQ6tPXokcPCCPGeCllKis//KQw+7mXLUcDNMPcBUsyNn7/7uZqBwCyzM5dDeHpefWhqrpWSlqjTrnMfYuktDTx+gfTMq6dccmdGf13XjLpjmbO843hzodeMTdJKerhZ5e6oUiiUSf90tyWwm7pUBbqiiJftCjSPhzSdZDPRZIS7NqO3b8aS5W+Zrfr7PxLcq3KKqbZIQgAAJC7/KIAkBAPHQeI/zrTQ8eBfPMToztA1lxr1piWAAAAYI+esooAUDBrps+b9gAACpb97QDx3z/b3w4AAAB7tjPWf1pJAAAAyFF7l1be4QUqynTdBp0Ydu1qKMiVlZKBP3QOKKnNe6hrCPXFaendFzqHU04b4HNPYW3KR4RzL50ctn72uaVogGYac+rEjIzhkV6jw9r1Gx0AyCLvf/xpuOvhBaGqulZKWmddcU9o3W2E+xdJaemXv5uRtvHtsLHnZezfuU/5yLB0xbvNmu/feX+d+UlKYStXb3BjkSR/uH+2uS2F9SoZHJYXRULdl70aaR8O7nq4z0aSEqhryRFhcaTdV2Op0tPySHEoLh3uHExircoq37JDEAAAIHf5RQEgIR46DhD/daaHjgP5ZpHRHSBrrjVrTEsAAACwR9FY7awkAOT9emnHL8d8AAAKk/3tAPHfQ9vfDgAAAPE530oCAABAjtq7rOImL1BRNlQz69mCXFXpM/wUx19J69TTDg6hvjjlbVzUIVx+cZ+wb48Kn3sKO+yYM8PrS9+y/AzQAouXvZWxcfzcSyc7AJAlGhubwrzFK8Pk6bWhqlpKXlfeOjt06DvW/YuktHX2b+9N2xh39dSnQvu+YzL2bx16/Nmhqal5z0V57MXl5ikpRd0za2FobGpyk5EEGzdtCfv2PNL8lsImdeoe6ooiX/VKpH3oW3K4z0aSEuii/Q782liq9DS4y6HOv+QWbVtS+a92CQIAAOQmvygAJMRDxwHiv8700HEgH5Ua4QGy4lqzxpQEAAAAcbnMSgJA3q+XXmW6AwAoaPa3A8R/D21/OwAAAMRn94td97KaAAAAkINalVZe6+UpyoYGjj4jRKPRgltVOeyYMx1/JaXiXsPD+3P3C6G+OGXtWt4u3H59z9Cp7zCfeSqP5YGjw6Qp00NDQ6OlZ4AWOvkXv83IWN6mfER4908fOgCQBdZ/+lmY/vhroaq6VkpqN9z7Yug17KfuYSSltTN+c2dax7rxE2/L6L/3jvsebdb8v2XbjnDL/fPMV1KKWly32o1Gkpxw5mXmtxRWUjI0vBEpDnVFka96ubhD6FUy2OcjSXHWvnR4eDnS4WtjqVLfmZ37Ov+SXKuyyoF2CQIAAOQmvyYAJMRDxwHiv8700HH+f/buO8qqKl/0ffdJ75xz733jjnHfPfccgloBQUCoAhUxYwIUiiSK2mbbrG0b0DbbtnY3tglBDJglWIqKWUBUQFQQEREoBMWMmMi5qn6vtHvcToa9d+28P58xvv+dMc5g7dVzzjVruhYUo5uM8AB5sdasNSUBAABAQr75D5b/0W4CQNHulf5TU5+a7gAASprz7QCJP0c73w4AAACJ28NuAgAAQAFqUd3vGh9PUb406aVZJbejMuC4C/32SkvXX9M9YnFFRmqsq4gn7q2O7j0Pcq0z3JGnXxkffrLCdjNAGixZ9lG07to/J+P5Cef81g8AOVbf0BivvfVB3DJ+RowYO11Ke/2Ov9IzjKSsd+qld2R9vNv30PNz9u9tt8fhsXzFlymtBd6s+8R8JWWoOx5+JTZu2uKhIw0efWaa+S3DXdNu56grK/+rppe3jZ069XZ9JCnBTm+/x9+Npcpst2zfxb2X5lpU9TvPKUEAAIDC5K8JAEnx0nGAxNeZXjoOFKNvDt3+P0Z5gJyvNWtNSQAAAJCwXnYTAIp2r7SvaQ4AoOQ53w6Q+HO08+0AAACQuDvtJgAAABSgFlU1l/l4ivKl3keeG42NjSW1o3Lc2Vf77dXsuh3QOzbObxOxuCLtzXikU/Qa2NN1znAd9jkyHpjwnG1mgDQ665Ibcjauz5q70A8AOfTFynXx4DNzY8TY6VJGOvWS2zzHSMpJJ14wMutj3u/veDYqdjssZ//mk4cOS2k98M0280OT3jRvSRnqpdlLPXikwYaNm2L73Q8zx2Wwjp0PjnnllVFXVv5XTatoG10693aNJCmBtqmuiecr2v3dWKrM9c31du+ltxbVNWOcEgQAAChM/poAkBQvHQdIfJ3ppeOANSEAmVpr1pqOAAAAIGEP2k0AKNq90kdMcwAAJc9ZJoDEn6OdbwcAAIDErWvqf9hRAAAAKDAtq/td4OMpyqemTJtdUjsq515xs99dze6p+7pELK5Ia4untI+TT+3h+ma4Vl36x1mX3BBfrVxtixkgjd59/5PYdqeBORnbDz7qPD8A5Eh9fUO89tYHccv4GTFi7HQpI10+/NHYbpdDPM9IyknHnntjTsa+ky++Naf/7skp7hl/uXKddYGUoUaOmxFfrVrvISQNzrz4enNchruq3S5RV1b+dz1f0S527HyQayRJCXREx32+cyxVZlrUVLuqg9176ayqZqFTggAAAIXJXxIAkuKl4wCJrzO9dBwoVk8b5QFyvtasNR0BAABAwjY39f/ZUQAoun3S/2hqi2kOAKDkOd8OkPiztPPtAAAAkJzj7SgAAAAUmJZVNb/w8RTlU72POCcaGxtLZjfl6pvu9burWR36s/0jFlekrY9e3iGGnrdnbNO1xvXNcLv1PTmmvfqmbWWADDhl6LCcje/PTH3FDwA5sPyLNTHmyTkxYux0KWNdd/eU6NjjWM8zknL3Ifuz/pCzMbDH4HNz9u/udtCJsX7DxpTWCDPeeM8cJmWox56f70EkDabOmGOOy3Dtq/rE3LLKqCsr/7smV+wQHasOdp0kKYEmVHb8zrFUmalmx/3cd+msqqb+/3Q64L85KQgAAFB4/CUBICleOg6Q+DrTS8eBYtXQVGsjPUBO15q1piMAAABIyll2FACKbp/0XNMbAADhfDtAMs/SzrcDAABAcqbbUQAAACgwLaprTvHxFOVb33xAsFTccs8jfnOl3DZda2Lh5A4Riyua3Zez28bVl+8WZbvUuLYZbtudB8bVN90bmzZvtqUMkAEL31kWrbv2z8kYv0e/U6OhodGPAFm0ZWt9TJ/zbowcNz1GjJUy181jpsXeg37pmUZSTht86jU5Gwd/e9szUb7r4Jz927/ZS0l1rXDvxNnmMilDvf/J1x5KmmlrfX103u9o81yG+3W7blFXVv6dPVXZIdpVHew6SdKP1HvH/b93LFX6O6/9bu67dNel765OCgIAABQef0kASIqXjgMkvs700nGgmF1spAfI6Vqz1lQEAAAASXnLjgJA0e2TzjO9AQAQzrcDJPMs7Xw7AAAAJK+dXQUAAIAC0qJLzek+nKJ8q+aYoSWzk/LgxOf95kq5S361R8Tiima19s02MfLaXaNt976uaRY65OcXx+KlH9hGBsigI0+/Mmfj/H0PPeMHgCz6+LNVcf/js2PE2OlSxhty5jDPNJJyXr8Tf53TsfDEC0bm7N++3S6DYsmyj1JaM7z/6dfmMilDjXlyTjQ0NHo4aaZLfne7eS7Dta/qE2+UVUZdWfl39mibjtGmyt9JJOnHumf7qu8dS5Xebtu+2j2X5lpU9T/VSUEAAIDC468IAEnx0nGAxNeZXjoOFLMlRnqAnK41a01FAAAAkLROdhUAimaPtKtpDQCAP3G+HSDx52nn2wEAACB5V9lVAAAAKCAtq2rO8uEU5WMvzpxbEjspk6fN9nsrpTrseXB8PWf7iMUVKbVlQWU8cMvO0Xmfg13PLFR9wLHx0BNTo7HRB2YBinVt1Wnfo2Ljps1+BMiCjZu3xguzlsSIsdOlrHTOb+6LVl36e7aRlPMOPvbSnI6HN4+ZFrv3PzNn//4hp1yW8vrhuZfrzGlShpq3+BMPKc30+rw681wWumKHblFXVv69TajsGJXVfV0rSfqB9ujUMxaWVfzgeKr0NLWinXsuzbWo7ne7k4IAAACFx18RAJLipeMAia8zvXQcKHZdjfYAOVtr1pqGAAAAIGm/s6sAUDR7pNeZ1gAA+BPn2wESf552vh0AAACS935TP7WzAAAAUCBaVtf80odTlI/1P+7CkthJmbdgid9bKXXfiJ0jFlck3daFlfHALTtH1/0Odh2z0LY7D4yrbrg71q7bYOsYIMMWvrMsdul9Ys7G/OtuHedHgCyoe29FjJ7waowYO13KSlfcPDHKdx3s+UZSXnTAkRfmfFz8zagno6zbITm7Bk9MmpHSGmL9xi1xx8OvmNukDPTN/7Y2btrqYaUZGhsbo3ufk8x1GW6Hzn3ijbLKqCsr/97GtukU21XXuF6S9APd3LbrD46lSk+Lmmpb1cc9l8ZaVPWb7aQgAABA4fFXBICkeOk4QOLrTC8dB4rddUZ7gJytNWtNQwAAAJC0D5v6BzsLAAW/P/oPTX1sWgMA4E+cbwdI/Jna+XYAAABITXc7CwAAAAWiReea8304Rfna9NfmFf0uyudfrvRbK+kOHNAz6hdVRiyuSLitCyvj4dFdY/fevV3DLDXoxIuibskHtosBMmzr1vq4/YGJUdn90JyN+d/8//5q5Wo/BmTQlyvXxcOT5sWIsdOlrHXtXZOiQ49jPN9Iypt6DD43L8bHY8+/KWfXYOdeJ8T6DRtTWk8sWLrc/CZlqGmvv+uhpZmGjRxjrstCl7XbNerKyn+w0dtXxTaulSR9b1069475ZRU/Op6q+R284/7uuTTWoqrfxq5dT/pnpwUBAAAKi78gACTFS8cBEl9neuk4UOw+beofjfgAOVlr1pqGAAAAICV72lkAKPj90f1MZwAA/AXn2wESf6Z2vh0AAABSc7OdBQAAgALRsqrvr3w4RfnawON/VfS7KI2NjVHW7RC/t5LqlUc7RSyuSKiGRZXxxL3VsUfv3q5dtj4kd+Bx8dATU7/93zcAmdPQ0BhPTZkZew04Ledj/0W/vdUPAhmytb4hXnvrgxg1fkaMGDtdylrD738xutec7hlHUl61e/+z8mKMvHnMtNi1b+7GyGuG35fy2uLhSW+a56QMdMu4GfHVqvUeYJrhnfc+MtdlobZVfeL18jZRV1b+g93ctmu0rq5xzSTp+9bk7Xb+0bFUze/s9ru539Je305OCwIAABQWf0EASIqXjgMkvs700nGgFOxnxAfIyVqz1hQEAAAAKRllZwGg4PdH7zKdAQDwF5xvB0j8mdr5dgAAAEjN5039k90FAACAAtCiuuYSH0xRPjd52uyi30np3uckv7US7vQz9o5YXPGjNSyqjCfurY49D+rlumWpbXceGJcOuyPWrttgixggg7Zs2RrjJ06JvQecnhfj/zZdB8SyDz/1w0AGLPv4q7h34qwYMXa6lPUOOvoSzzmS8q5ufU7Nm3HyyhETY9udBuXkOmy3y6BYuuzj1E61fb02Ro6bYa6TMtATLy7wENNMPQ//pfkuC12yQ7eoKyv/0X7TbhfXS5K+p/ZVfWJOeWVC46lSb+T2Xdxv6a6q5minBQEAAAqLvx4AJMVLxwESX2d66ThQCu404gPkZK1ZawoCAACAlHzV1L/YXQAo2L3Rf21qpekMAIC/4Hw7QOLP1c63AwAAQOp62V0AAAAoAC2r+13hoynK5/YdfGbUNzQU9S7KoBMv8lsroSp37RsfvbxDxOKK761hUWU8cW917HVwL9csiw0+6ZJYvPQD28IAGfTZ51/FyLsnRNeex+fVHHDahX/w40CarVyzIZ58aUGMGDtdyklH/fIGzzmS8rLqnifm1Xg55IxhObsWQ065LOW1xouzl5rvpAz14XLvOGqOW+55xHyXhXbo3CfeKKuMurLyH+1XO3R3zSTpe7qoaYxMZCxV6j1X2d69luZaVNXc4LQgAABAYfHXA4CkeOk4QOLrTC8dB0rB6qb+zagPkPW1Zq0pCAAAAFLW1+4CQMHujR5iGgMA4G843w6Q+HO18+0AAACQuvvsLgAAABSAFtU1V/toivK9Byc+X9S7KGdefL3fWQl10+92jVhc8Z01LKqMJ+6tjr0P7uVaZbEuBx4XDz0x1XYwQIZs3LQ5Jj43PY4566rYpuuAvJsHWnXpHwvfWeaHgjTZsrU+Xnvrgxg1/uUYMXa6lJPOvureaN00vnvekZSPdexxbF6NmcPvfzE67398zq7HU1NmprTm2LR5a9w54VXznpSBxjw5JxoaGz3cpOjTz76M1l2tRbPRr9t1i7qy8oQ6u/1urpkkfUeV1X3jlfLtEx5PlXwLyyq+vc7ut/TVorrmRacFAQAACou/HgAkxUvHARJfZ3rpOFAqBhn1AbK+1qw1/QAAAEDKxtldACjYvdEJpjEAAP6G8+0AiT9XO98OAAAAqVvb1L/bYQAAAMhzLapqhvtoivK9rj2Pj42bNhftLsqwkWP8zvrRuvfsHZveroxYXPFXNdZVxORx1XHggJ6uUxbbbpdB8dub74/1GzbaCgZIs4aGxnht7sIYetXIaLfH4Xk9Hxz7i9/4wSBN6t5bEXc98lqMGDtdyllX3Dwxyncd7JlHUt7Wbq8j827svOi62mjVpX9OrsfOvU5IeW9mwdLPzH1Shpr/zqcecJrhkJ9fbM7LQh2rDo555ZVRV1b+oy1q6ucd9nTdJOk7Or39HgmNpUq9Azsd4F5LZ1X9Vv/kJz/5qRODAAAAhcNfDgCS4qXjAImvM710HCgV4436AFlfa9aafgAAACBl68MHbgAKcV/0vze1wTQGAMDfcL4dIPFna+fbAQAAoHkG2WEAAADIcy2r+t3loykqhEbd+2jR7qA89MRUv7F+tGceqI5YXPF/a6yriMnjqqPnwJ6uT5Y79KRLY/G7H9r+BUizRUvej9/ceE/s1Ov4gpkT5rxV54eDZlrx1dp4eNK8GDF2upTTfn/Hs9Fhn6M880jK69rsPiQvx9A+x12es2vyuxH3p7QGaWyMpjXIm+ZAKQONfviV2Lh5q4edFI19ZJI5L1tzSLudo66sPKEWlFfEER33cd0k6W/aprompla0S3g8VfKd3n4P91qaa921f4UTgwAAAIXDXw4AkuKl4wCJrzO9dBwoFWub+jcjP0BW15q1ph8AAABolgF2GAAKbl/0MNMXAADfwfl2gMSfrZ1vBwAAgOYZa4cBAAAgz7Wo7veQD6aoEOqwz5Gxes26otxBmfNWnd9YP9iQo/eLWFzxbQ2LKuPJ+6pj/349XZss17Xn8fHQE1Nt+wKk0dt178UfRo2N/QafVXDzwmEnX+oHhGZYv2FzTHllcYwYO13Kedfd83x07XWS5x5JeV95t0Pzcxy9+/lou+eRObkmZd0OiXff/ySl9cjnX6+NkeNmmAulDDTjjfc89KRo1eq1345t5r3MV1V1ULxdVhF1ZeUJ9c3/bf+O+7l2kvQ3Hd1x74THUiXfDW27us/SXVXNIU4MAgAAFA5/OQBIipeOAyS+zvTScaCU9DfyA2R1rVlr6gEAAIBmecAOA4B9UQAAioLz7QCJP1s73w4AAADNs7apf7PLAAAAkMdaVtc854MpKpSuvuneotxBWblqrd9X39u2XfvFoikdYuvCynh4dNfYp08v1yXLVXY/NK67dVxs2LjJli9AMzU0NMa8hUu/HVf3GnBaQc8PL896yw8KKdiytT5mzf8gbntoZowYO13KecMfeCn2GPALzz6SCmOfaKdBeTuennH5nTm7LoefennKa5MXZy81H0oZaNT4l2PNuo0egFJ0wjnXmPey1HVtd4q6svKEm1deGb123N+1k6S/qHV1TTxR2T6p8VSJ92RlB/dZmmtRXXO1E4MAAACFw18NAJLipeMAia8zvXQcKCX3G/kBsrrW9PFYAAAAaJ41Tf2rXQaAgtkT/bf448fJAADgbznfDpD487Xz7QAAANB8NXYZAAAA8ljLqpqZPpiiQqm82+D45LMvinIHpeM+P/Mb6zv71dA94uHRXWP33r1djyzXqkv/OHnosPjo089t8wI0Q31DQ7w2d2FcOuyOqD7g2KKYI/ocdb4fFpLU0NgYby9ZHnc9+lqMGDtdyotuHjMteh91kecfSQW1V5HP42qPwefm7No8M/WVlNYomzZvjTsnvGpelDLQ5JmLPQil6IlJM8x7WWqnTr1jQVl51CXRnPI2sU+nnq6fJP1FA3fcN6mxVIm3oKwiyqpq3GdprEV1zdNODAIAABQOfzUASIqXjgMkvs700nGglKwOH6AFyOZas9bUAwAAAM3Wxy4DQMHsiQ4wbQEA8D2cbwdI/Pna+XYAAABovnvtMgAAAOSxFlU1b/lgigqpX1x6Y1HuoNQcM9Tvq++scte+rkMO6nPU+fH6vDrbuwApWvHF1zF+4pQ4eeiwaLfH4UU3T0yeNtuPDEn4cPnKGPvUnBgxdrqUVx1yyjWefyQVXMMfeClvx9Vrbns6yncZnJPr0u2gE2PDxk0prVUWLP3MvChloJHjpsfnX6/1QJSCjZs2R9vdh5j3stTNbbtGXVl5Ur1Svn3s2rmX6ydJf1Ftmx2THk+VWD06HegeS2Mtqmo+dWIQAACgcPirAUBSvHQcIPF1ppeOA6XmYKM/QNbWmrWmHQAAAGi2u+0yABTMnugDpi0AAL6H8+0AiT9fO98OAAAAzbeyqX+x0wAAAJCnWlbVvO+DKSqkWnXpHzNnzy+6HZTzrrzZ7yvlQbv1PTmemjLTti5AkuobGmLewqUx8u4J0f+4C79dsxXrXHHAYb+NUmwhAAAgAElEQVSIxsZGPzokYPkXa+KRKW/FiLHTpbzrhKGewyUVZjfcOzWvx9djz70pZ9dm2MgxKa1ZvlnePzzpTfOjlIEef+FtD0YpOu3CP5j3slT3Tr1iYVlF1JWVJ9W0irbRpXNv11CS/tSBnQ5IeixVYp3UYU/3WJrbdueD/tOpQQAAgMLgLwYASfHScYDE15leOg6UmruM/gBZW2vWmnYAAACg2XzgBqAw9kP/pamvTVsAAHwP59sBEn/Gdr4dAAAA0qO3nQYAAIA81aK65isfS1Ghte/gM2Pr1vqi2j25a9yTflsph22/+2Fx3a3jYtPmzbZzARK04ouvY/zEKXHy0GGxw15HlMyc8fikGX58+BFfrVofT01bGCPGTpfysjOvuCtadenvWUhSQfaHOyfn9Rg7fMy02Omgk3Nybcq6HRLLPvw0pfXL51+tjZHjZpgnpQz00WcrPSSl4KkpM817WezWtl2irqw86Z6vaBcdqw52DSXpT93TpnNK46l+uN+129n9leZaVfft5dQgAABAYfAXA4CkeOk4QOLrTC8dB0rNl039kxkAICtrzVrTDgAAAKTFgXYaAPJ+P7S36QoAgB/gfDtA4s/YzrcDAABAeoy20wAAAJCP9t77n1pW92v0sRQV5Mft7nusqHZPXp3ztt9VykHb7jQwhl41Mr74apVtXIAfsX7Dxnhx5hvxmxvviQOHnB2tuvQvuXljv8FnRUNDo5sBvseadRvjhVlLYuS4GTFi7HQpL7tg2Lim54BBnockFWy/u+PZvB9rL7vxkWjddUBOrs/xv7wm5bXMi7OXmiulDFT77FwPSynYsHFTVHY/1NyXpXbr3CsWllVEXVl50j1V2SHaVvVxHSWpqT069Ux5PNX391CbHd1faa5F55rzHRwEAAAoDP5iAJAULx0HSHyd6aXjQCnaywwAkJW1Zq0pBwAAANLiZjsNAHm/HzrKdAUAwA9wvh0g8Wds59sBAAAgPVY09Q92GwAAAPLMNl0H/JcPpahQa7v7kFi+4sui2T1ZvWZdtOrS328rZbEhp1wWi5a8b/sW4HvUNzTEvIVLY+TdE74dM8u6HVLyc8ezL7zqxoDvsGbdpnhh1pK4ZdyMGDF2upS3XXbjI1HR/TDPQ5IKuqtvfaogxtxBJ1+ds2v04sw3UlrTbNq8Ne6c8Ko5U8pA73zwhQenFJx0/u/NfVnsru2roq6sPKUmVHaMiqq+rqMkNTWqbXXK46m+uznlldHKvZXWWlTV3OfkIAAAQGHw1wKApHjpOEDi60wvHQdK0TAzAEBW1pq1phwAAABIiw/sNADk9V7oT5v6yHQFAMAPcL4dIPHnbOfbAQAAIH12sdsAAACQZ1pW9+3kQykq5E4ZOqyodk92PfjnflcpC+094PSYMm22LVuA7/DBx5/FAxOei5Ob1lk77HWEeeMvOuhn50VjY6ObBP7CmvWbYuprS+KW8TNixNjpUl535YiJsf0e5jZJhd9VIx8viHH3xvteiA49jsnJNeox6IzYWl+f0vpmwdLPzJtSBrr/idnR0OCZOlmPPTvN3JfF9tmxZywqK4+6FHugTefYrrrGtZRU8u3SuXcsaMZ4qu9up6br6v5KZzVznRwEAAAoDP5aAJAULx0HSHyd6aXjQClaZAYAyMpas9aUAwAAAGnT0W4DQN7uhVabpgAA+BHOtwMk/pztfDsAAACkz6/tNgAAAOSZll367usjKSr0Xpw5t2h2T0445xq/qZTBOu93dNz/8LNR39BguxagyTfj4VuLlsboMY/Hz8/7XXTa9yjzxQ80c/Z8Nw38yYaNW2Lmm8ti1IMvx4ix06W876pbHo+2exxhPpNUFF0+/NGCGX/Pveb+nF2nux98KqV1TmNjxEOT3jR/ShnorcWfephK0tp1G6K822DzXxYb06ZT1JWVp9wt23eJ1tU1rqWkku+Gtl2bNZ7q7zusYw/3VhprUd1v00/23vufnB4EAADIf/5aAJAULx0HSHyd6aXjQKlqYxYAyPhas9Z0AwAAAGnzK7sNAHm7F3qZaQoAgB/hfDtA4s/ZzrcDAABA+rxhtwEAACDP/FdV/8N9KEWF3u41p8SmzZuLYvdk+OiH/KZSBtpul0Fx6bA7Ys3a9bZpgZK2tb4+5i1cGiPvnhDHnHVVtN/7SPNEgp0ydJgbCJqsWbcpXnp9aYx68OUYMXa6VBD99rZnosM+R5vPJBVNl9zwcEGNw/sNOT8n1+mb552vV61Jac3z+VdrY+S4GeZRKc3d+cirsWVLvQerJJ1wzjXmvyzWd8f9oq6svFnd2LZrtHItJZV41Z0PivllFc0eU/XnfrVDd/dWmvvPqpr2Tg8CAADkP38pAEiKl44DJL7O9NJxoFSdbRYAyPhas9Z0AwAAAGkzw24DQN7uhc42TQEA8COcbwdI/Dnb+XYAAABIn8amWtlxAAAAyCOtqvud6SMpKoZuvOPBotg9eXnWW35PKY216tI/Tr3g2vjwkxW2Z4GStHrNunh++uvx25vvjwHHXRhl3Q4xP6TQjj2Oik8++8INRUlbtXZjTHv93Rg1/uUYMXa6VDD9/o5nY8f9jjWfSSqqLrz2wYIai3972zNRvsvgnFyrS4fdkfL658VZS8ylUgZ67a0PPGAlacJTL5j/stzjlR2irqy8WV3erptrKank+227nZs9nurPjd6+yn2V5lpU9zvM6UEAAID85y8FAEnx0nGAxNeZXjoOlKopZgGAjK81a003AAAAkDYNTf2HHQeAvNsH/a/440fIAADghzjfDpD4s7bz7QAAAJBeJ9txAAAAyCMtq2t+7SMpKoYqdh0cHy//vOB3TtZv2Bjb7jTQbyqloSGnXBbzFi61JQuUjK1b678d9+558Ok4+7KbYu8Bp0erLv3NCc2svNvgmDV3oRuMkvXF1+ti8szFMXLcjBgxdrpUUF1716SoOuAE85mkomvo78YW3Jh81C9vyMm12nbngfHOex+ltA7atHlr3DnhVXOqlOZuq50Z6zdu9rCVhDVr10dZt0PMgVnsiI77RF1ZebM7u/3urqekkq5D1cHxRlllWsZUlcfUinbuq3RX1e8qpwcBAADyn78UACTFS8cBEl9neuk4UKq2NPU/zQQAGV1r1ppuAAAAIK2OtuMAkHf7oCeangAASIDz7QCJP2s73w4AAADp9YQdBwAAgDzSsqrfKB9JUbF0+kXXFcXuyYFDzvZ7Ss2oz1Hnx4xZ82zFAkXvw09WxGPPTosr/nBn9D/uwqjYdbB5IM1tu/PAeGrKTDcbJemjz1bGxKnz/++H76VC67p7psROvU8xn0kqys695v6CG5eHP/BSVB1wQk6u15GnX5nymmjB0uXmVSkDvTh7qYeuJB191lXmwCy2TVVNPF/RLurKypvVoqaO77CXayqppLu8Xbdmj6f687yyfVVf91V6e8zpQQAAgPznrwQASfHScYDE15leOg6UskPMBAAZXWvWmmoAAAAgrcbbcQDIu33QR0xPAAAkwPl2gMSftZ1vBwAAgPTa0NS/2nUAAADIEy2r+k30gRQVS6269I85b9UV/O7Jr64Z5feUUmifgafHE5NmRGNjo21YoCitWr02Hnt2Wpxx8fVRtf8xxv4MV9n90Jg6Y44bj5LyzTpq6YdfxEPPvfmdH76XCqXr7pkS3fqcaj6TVLT94qp7CnJ8vuDa8d/u4ebimk2ZNjvF9VHEg8/MNb9Kae6W8TNi5ZoNHsKS8ODE582BWe7k9ntGXVl5s1tQVhEDOu7rmkoq2dpW9YnZ5dunZUxVeRzY6QD3VRprUVXzrtODAAAA+c9fCQCS4qXjAImvM710HChlt5kJADK61qw11QAAAEBafdnUP9h1AMibPdB/amqV6QkAgAQ43w6Q+PO28+0AAACQfgfYdQAAAMgTLatqXveRFBVTfY8e+u2H4AvZI0+96LeUkqh7n5Pi4SdfiIaGRluvQNFZsuyjGHXvo3HIzy+ObXcaaNzPUl0OPC5en1fnBqRkbNlSH2/WfRL3Tpz9gx++lwqh6+6eEjsfdIr5TFJRd8bldxbsON37qItycs32GnBa05pna0prpU8/X22OlTLQszMWeRhLwspVa2Pbne0NZbPtqmtiZkXbqCsrb3bzyivjwE4HuK6SSrahO3RPy3iq8ji1wx7uqfTW+L/a1vwPJwgBAADym78SACTFS8cBEl9neuk4UMreNxMAZHStWWuqAQAAgLTb2a4DQN7sge5uWgIAIEHOtwMk/rztfDsAAACk3zC7DgAAAHmiZXW/z3wgRcXWo89MK+idkxVffB2tuvT3W0o/0o49joqRd0+ITZs323IFikZ9Q0O8NndhXH3TvbHPwNON9zlo8EmXxOdffu1mpCSsXrsxZr65LO54+JWEP3wv5XPX3T0ldj7oFPOZpKLvtEtuL9ix+tq7JkWb3Ybk5Lrddv9jKa+bnpm+yFwrZaDlX6zxYJaEI067wjyY5c5v3z3qysrT0qyKNrFbp56uq6SSrKKqb7xSvn3axtRS7tp2O7mn0l2Xvrs6QQgAAJDf/IUAICleOg6Q+DrTS8eBUtfGbACQsbVmrWkGAAAA0u4iuw4AebMHeoVpCQCABDnfDpD487bz7QAAAJB+b9p1AAAAyANdu570zy2raxp8IEXF1i69T4yNmzYX9O7JPgNP91tK39P2ux8WV990b6xZt95WK1AUvvx6ddQ+/nycdP7vo90ehxvrc/VRz10Hx8i7J0RDQ6ObkqL3+VdrY/LMxXHLuBkpffheyseuvWtSdO11kjlNUkl00kWjCnrMPmHozTm5bjvsdcS3z1+pWL12Y4x68GVzrpTmHpnylge0JIyZ8Jx5MNt/j6jqE3PK20RdWXlaml7eNqo7H+TaSirJzmy/R9rG01LukTYd3U/prkv/k5wiBAAAyG/+QgCQFC8dB0h8neml40CpO91sAJCxtWataQYAAADS7gW7DgB5swf6smkJAIAEOd8OkPjztvPtAAAAkH7ffIzwv+w8AAAA5Nh/Vg/c1sdRVKzdeMeDBb17csnvbvc7Sn/TdrsMiqFXjYwvvlplixUoeAsWL4vhox+KvkcPjdZd+xvnc9zgky6JZR9+6sakqG3ZWh8Lln4WDz4zt9kfvpfyrWGjJ0V1zxPNaZJKphMvHFnQ4/bNY6bFTgednJNrd8Fvbkl5PTVz7jLzrpSB3v/0aw9sCfry69Wx7U4DzYVZ7qp23aKurDxtPVexQ7SrOti1lVR6f+utrolpFW3TOqaWYnPLKqN107V0T6WvFlU1w50iBAAAyG/+QgCQFC8dB0h8neml40Cpe8xsAJCxtWataQYAAADSbnNT/93OA0DO9z//36a2mJYAAEiQ8+0AiT9zO98OAAAAmfEzOw8AAAA51qKq324+jqJibfvdD4sVXxTuhxifmfqq31H6U998JPSsS26IDz9ZYVsVKFgbN22O56e/Hr+6ZlTs3OsE43uetEvvE2PCUy9EY2Ojm5SitXL1hpj55rIY/fAraf3wvZQv/X70c1F1oLlVUml1wtCbC378vviGh6N1l/5Zv3bbdB0QCxYvS2ldtWVLfdz1yGvmXynNjXv6jfBYnrjDTr7UXJjlOnc+ON4uq4i6svK09WibjlFR1df1lVRyndJ+z7SOp6Xazp17u5/SWIvqmhecIgQAAMhv/joAkBQvHQdIfJ3ppeNAqVvT1D+bEQAystasNc0AAABARvSx8wCQ8/3PAaYjAACS4Hw7QOLP3M63AwAAQGbca+cBAAAgx1p06X+oj6OomDvn8uEFu3Oyes262HangX5HlXStuvSP0y78Q7z3wSe2U4GCtHzFl/HAhOfi2F/8Jiq7H2psz6Pa731k3HLPI7Fp82Y3KkWpvqEhlnzwRUycOj9jH76X8qHf3/FsdN7/eHObpJLruPOHF8U4XnP8FTm5foNPuiTlddbbS5abg6UMVPfeCg9yiZ68rX3GXJiDbmzbNerKytPaPW06xzauraQSa5vqmnihol3ax9RS67COPdxP6ayq5kunCAEAAPKbvw4AJMVLxwESX2d66ThAxJ5mBICMrDVrTTEAAACQETfZeQDI+f7nLaYjAACS4Hw7QOLP3M63AwAAQGYsb+qndh8AAAByqGV1zS99HEXFXOuu/eOtRUsLdvfkm4+7+h1Vqh1z1lUxf9G7tlGBgtLQ0Bhvvv1OXHvLmOh1+DnRqkt/Y3qe1X7vI+O6W8fFqtVr3bAUpZVrNsTLb7wXoye8mpUP30u57DejnoyOPY41v0kqyY47b3hRjOXX3T0ltt/jiJxcw6efn5nSequxsTHGP/2GuVhKc/dOnBX1DQ0e6hLw+ZdfxzZdB5gPs9yunXvFwrKKqCsrT2sj2naJVq6vpBLrpPZ7pn08LbUu2GE391K6zxdV17RwkhAAACB/+esAQHL/OZqZAyDhdaaXjgNEXGlGAMjIWrPWFAMAAAAZscDOA0DO9z8Xm44AAEiC8+0AiT9zO98OAAAAmdPR7gMAAEAOtazqd50Po6jYO+TnFxfszsntD0z0G6rkGnLKZTF3/ju2ToGCsW79xm8/xn7uFTdH1f7HGMvztM77HR0j754Qa9dtcNNSdDZvqY+691bExKnzs/7heylXXX7To9F2zyPNcZJKtmPPvbFoxvRTL7ktJ9dw95pTYsuWrSmtvz7+bJX5WMpAby3+1ANeggaecJH5MAfduX3nqCsrT3tX7NDN9ZVUUm1TXRMvVLTLyJhaKt3Sttq9lOZadenX00lCAACA/OUvAwBJ8dJxgMTXmV46DhDxghkBICNrzVpTDAAAAGREY1P/YfcBIGd7n/9lKgIAIEnOtwMk/tztfDsAAABkzml2HwAAAHKoRVXNwz6MolLoxZlvFOTOyQcff+b3U8k05JTLYu78d2yZAgXhk8++iLsffCqOOO3yKOt2iHE8j9v/0F/E2Ecnx8ZNm924FJXGxohPP18dL8xaErfVzszph++lbPer6x6Mit0OM89JKumOPufGohnXbx4zLXbte3pOruOdY59IeT329LSF5mUpzd316Guxtb7BA18C7hr3pPkwB+3X6YCoKyvPSGe33801llRS/bzDnhkbU0uhZyvau4/SXIuqfuc5SQgAAJC//GUAICleOg6Q+DrTS8cBIjY29a9mBYC0rzVrTTEAAACQMYPsPgDkbO9ziGkIAIAkOd8OkPhzt/PtAAAAkDkP2n0AAADIoRZV/Wb7MIpKod5HnhuN33x1vgD1GHSG31BF3ZBTLou589+xVQrkvYXvLIsbbn8weh9xTrTq0t8Ynsdt03VAnHDOb+PlWW+5cSk6K1dviNfe+iDue3x23nz4Xspm51x9f2y3yyHmO0kl31G/vKGoxvfLbnwkWufgOWvHHkfF6jXrUlqXrV67MUaNf9n8LKW5uYs+9uCXgOUrvozWXe1P5aLaNjtGXVl52lvU1PEd9nKNJZXOPn51TbxQ2S4jY2optKCsIrZtuobupfTVorrfvU4SAgAA5C9/GQBIipeOAyS+zvTScYA/2tOsAJD2tWat6QUAAAAyZrjdB4Cc7X2OMg0BAJAk59sBEn/udr4dAAAAMmdFUz+1AwEAAJAjLav6feHDKCqVnpn6SkHunvz25vv9firKfnbGlTF3/ju2SIG8Vd/QEK/NXRhX33Rv7DXgNGN3AdS15/Hf/l4fffq5G5iisnb9pniz7uN46Lk38/bD91I2OuvKu2PbnQaZ8yTpm32Vs68vunG+73GX5eRaXn3jPSmv02a88Z45Wkpzdz7yamzZWu9BMAH9jr3AnJiDBnXsEXVl5RlpQVlFDOi4r+ssqWQ6ocNeGRtTS6HdO/d0H6W3N5wkBAAAyF/+KgCQFC8dB0h8neml4wB/dIlZASDta81a0wsAAABkzDy7DwA52/tcaBoCACBJzrcDJP7c7Xw7AAAAZFZbOxAAAAA58F9d+/x7y+p+jT6KolJp38FnRkNDY8HtnCxYvMzvp6KpVZf+cdzZV8ebb79jWxTIS+s3bIynn58Zv7j0xui4z8+M3QVQebfBccrQYfHizLkFudaD77Nx09aoe29FTJw6P0aOy/8P30uZ7oShN3/7PGHuk6Q/duQv/lB0Y/21d02Kit0Oy8kzxUeffp7Smm3Llvq465FXzdVSmpuz4CMPhQm4/YGJ5sRc/J2jqWcrd4i6svKM9GZ5Zey/4wGutaSSaJuqmphckbkxtdg7qsM+7qM01qKq38afDB78j04UAgAA5Cd/FQBIipeOAyS+zvTScYA/mmxWAEj7WrPW9AIAAAAZ882Lxv6XHQiArO97/u8/jcEAAJAM59sBnG8HAACAfHGSHQgAAIAc+M/q/jv4KIpKrUeeerEgd096HHKm308FXeuu/eOYs66KeQuX2g4F8s7Xq9bEuMcmfztOffMxdeN2/rftTgPjiNOuiAcnPh9r1q53E1M0Nm7eGnXvrYgnX1oQt4ybUXAfvpcy1ZAzh5n/JOlvOuKsPxTlmH/c+cNzcj3PuPj6lNdw89/51HwtpbnRE16JzVvqPST+iI8+/TxadelvXsxBJ3XYM+rKyjPWrIo2sVunnq61pJLouA57Z3RMLeYu2aGbeyjdVR3cxolCAACA/OSvAgBJ8dJxgMTXmV46DvBH3/wHev9iZgBI61qz1vQCAAAAGdXPDgRA1vc9DzH9AACQAufbAZxvBwAAgHwxxg4EAABADrSq7tvLB1FUanXvc1Js2bK14HZPbrj9Qb+fCrJtdx4YZ11yQyxZ9pFtUCCvrFy1Nh56Ymocc9ZVsd0ug4zZBVLvI86J0WMej8+//NpNTNFYs25TzFv8STz2/Py4ZdyMgv7wvZTuhj/wUvQ59jJzoCR9R4efOaw4x/4x06K654lZv56tuvSPeQuWpLSea2xsjLFPzTF3S2lu1vwPPDAmoNfh55gXc9B21TXxSvn2UVdWnrFmVGwfXTr3dr0lFX3bVNXE5IodMjqmFmujt69yD6W5FtU1NU4UAgAA5Cd/EQBIipeOAyS+zvTScYA/625mAEjrWrPW1AIAAAAZdb0dCICs73vebPoBACAFzrcDON8OAAAA+eJTOxAAAAA50KK65hQfRFEpNmbCcwW3e/L+R8u//bCr308F80HJXQbFWZfcEO998IntTyBvfL1qTTz0xNQ45qyrYtudBxqvC6Qeg86I624d9+16CIrFV6vWx5wFH8WEyfOK7sP3Urq67p7nY89BZ5sLJel7GnLGsKKdAy64dnxO9kIHnXhRyuu7jz5baf6W0tztD70SGzdv9QD5I66/bbx5MUddtMOuUVdWntGerdwh2lUd7HpLKvqO6bBXxsfUYmxqRTv3T/q7wIlCAACA/OQvAgBJ8dJxgMTXmV46DvBn/l4KkN61Zq2pBQAAADJqth0IgKzve841/QAAkALn2wGcbwcAAIB8Um4XAgAAIMtaVPe7xsdQVIrt1Ov42LR5c8HtnvQ56ny/n/K+trsPiV9ff1d89vlXtjyBvLB8xZdx17gnY+AJF0Xrrv2N1QVSj0POjOtuHRdLl33sJqYo1Dc0xIfLV8ZLs5fGPY/NKuoP30vp6Jpbn4qqA08wJ0rSDzTkjN8X9Vyw/5ChObmuk16alfKa78mXFpjHpTT36rz3PVD+iAWLl5kXc1THzgfH/LKKqCsrz2gTKjtGeVVf11xSUbdNVU08V9k+42NqsbWwaR6qMEektRbV/e51ohAAACA/+YsAQFK8dBwg8XWml44D/NmjZgaAtK41a00tAAAAkFFbmvp3uxAAWdvz/G9NbTX9AACQAufbAZxvBwAAgHxyhF0IAACALGtRXTPGB1FUqt0x5vGC2z0ZM+E5v53yts77HR3X3TouVq5aa6sTyLmvV62Jex58OgYcd2G07trfOF0IH8zsOiAGnXhR3Hb/Y/H+R8vdxBSF1Ws3xttLlsezMxbF7Q/NLKkP30vN6eIbHo62exxhfpSkH+mw035X1PPBNbc+FdvtckjWr+s+A0+PrfX1Ka3/VjWt/0aNf9l8LqWx22pnxoZNWzxg/ohdD/65uTFH3dS2a9SVlWe8e9p0jm1cb0lF3lEd987KmFps9eh0oPsnjbWo7jfLiUIAAID85K8BAEnx0nGAxNeZXjoO8GcrzAwAaV1r1ppaAAAAIOP2tAsBkLU9zx6mHQAAUuR8O4Dz7QAAAJBPhtuFAAAAyLKW1TUv+yCKSrVO+x4Va9dtKKjdk3XrN0bb3Yf4/ZRX7db35Bg95vHYuGmzLU4gpzZt3hyTXpoVJw8dFtvtMsgYXQBV7Do4jjnrqnhgwnPx+Zdfu4kpeBs3bY0lH3wRL8xaEvc+NqukP3wvpdq519wf5bsMNk9KUgINPvW3RT8vDDljWE6u7X0PPZPymnD6nPfM6VKam/nmMg+cP+LSYXeYG3PU7p17xqKy8qjLQte33ck1l1TUta6uiWcq22dlTC2mju+wl/snrdWs/clPfvJTpwoBAADyj78GACTFS8cBEl9neuk4wF/bzuwAkLa1Zq1pBQAAADLufLsQAFnb8/yVaQcAgBQ53w7gfDsAAADkk1l2IQAAALKsRXW/j30MRaXc8NEPFdwOynm/HuG3U17U6/Bz4qEnpkZ9Q4OtTSBnGhoaY/pr8+KXl98U7fY43PhcAFXtf2ycf9XImDJtdmzavNlNTEHbuGlLvPfRlzF9znvx4LNzY+Q4H7uXmtNx5w2P1l36my8lKcEOOeWaop8bbrzvheiwz1E5eG45Jtau25DSGnHT5q0xesIr5nYpjd1WOzPWb9ziIfQHzJg1z9yYw8a26RR1ZeVZ6Vc77OqaSyrqjuywd9bG1GLp1+26uXfSXIud+rV2qhAAACD/+GsAQFK8dBwg8XWml44D/LUhZgeAtK01a00rAAAAkHET7EIAZG3P8zHTDgAAKXK+HcD5dgAAAMgn33z04N/tRAAAAGRJ+/aD/0VjOVsAACAASURBVKVldU2Dj6GolGu/95GxZt36gtpBmTv/Hb+dclbrrv3juLOvjlfnvG07E8ipRUvej19ff1d0OfA443MB1GPQGXHN8Ptizlt10dDQ6AamYK3fuDmWfPBFTHv93Xjw2bkxcpyP20vpaPj9L8bBx15qzpSkJBt08m9KYp4484q7cnJ9h40ck/K68c26j83xUpqbPuc9D6U/YGt9/bd/8zI/5mhO3nHfqCsrz1qnt9/DdZdUtLVq6unK9lkdVwu9+7fv5N5J933YpV9PJwsBAADyj78GACTFS8cBEl9neuk4wF+70ewAkLa1Zq1pBQAAADLuU7sQAFnb81xu2gEAIEXOtwM43w4AAAD5Zg87EQAAAFnSumv/Ch9CkfrFiLseLrgdlD5Hne+3U1bbfvfDYuhVI+Od9z6yhQnkzObNW+KJSTNiyCmXGZvzvMruh377O40e83h8+MkKNy8Fqb6+IZZ/sSbmLf4kJs9cHPc/PtuH7KUMNOzOSdG93xnmT0lKoUEn/6Zk5os9Bvwi69e3YtfB8clnX6S2lmxoiHsnWj9K6WzUgy/Hug2bPaz+gDMvvt78mKNaNfVcZfuoKyvPSgvKK+KwDj1ce0lF2+Ed98namFoMTato675Jd136ne1kIQAAQP7xlwCApHjpOEDi60wvHQf4a6+aHQDSttasNa0AAABAVmxjJwIg4/udZaYbAACawfl2AOfbAQAAIN+cZycCAAAgS1p26buvD6FI/WLHHkfFuvUbC2oH5bFnp/ntlJWqDzg2rrt1XKxctdbWJZAzyz78NK6+6d7otO9RxuY8rnufk+LSYXfEtFffjM2bt7hxKSiNjY3x1ar1Uffeipj2+rsxYfK8bz/Y7sP1Uma77MZHosM+5ndJSrWBJ11VMnPGFTc/Fq27Dsj6NT7n8uEprzHrlq0w30tp7qXZSz3A/oAnJ79sfsxhp7TfM+rKyrPWvPLK6NnpANdeUlHWqqmnKjtkdVwt5BY1VVnd172TxlpU1dzmZCEAAED+8ZcAgKR46ThA4utMLx0H+Gubm/pXMwRAWtaataYVAAAAyIpD7UQAZHy/c4jpBgCAZnC+HcD5dgAAAMg3D9mJAAAAyJIW1TXH+RCK9MdGj3m8oHZQttbXxy69T/TbKWP1PuKceOiJqbF1a70tSyBnc91TU2bG4adeHq269Dc252E77HVEnHT+72Pso5Nj+Yov3bQUjA2btsRHn62MN+s+iamvLYmHnnszbqud6QP1UpY77bI7YrtdDjGnSlIz6n/ir0tq7qg54YqsX+PWXfvHwneWpbTubGyMGP/0G+Z9KY2NGv9yrFm/yYPt91i7bkOUdbPGzlXlVX3jtfI2UVdWnrVmVbSJ7p16uf6SirLDOvTI6pha6PXodKD7Jp1V1Ux3shAAACD/+EsAQFK8dBwg8XWml44D/L1dzRAAaVlr1ppSAAAAICuusxMBkPH9zutNNwAANIPz7QDOtwMAAEC++dBOBAAAQJa0rO53hQ+hSH9sp17Hx+bNWwpqF2XkPY/47ZTWvvnY5hkXXx9vzF9smxLImXXrN8btD0yMXXqfaGzOs1p16R+9Dj8nfjfi/nht7sLYWl/vhiWvrV2/KT7+bFUsWLo8ps95LyZOnR93PfKqD9FLOe7mMdPikFOu+XZeMb9KUvPqd+KVJTWH/OHOyVGx22FZv84/O+PKlNekH3z6tflfSnNTX1vigfcHfDNmmSNz12Xtdo26svKsNr28bVRVHeT6Syq+v0k0NbGyQ9bH1ULtmA57uW/SWVXNl04WAgAA5B9/BQBIipeOAyS+zvTScYC/d6oZAiAta81aUwoAAABkxVQ7EQAZ3+980XQDAEAzON8O4Hw7AAAA5KP/bTcCAAAgC1pW19ztQyjSnxsz4bmC2kFZvWZdtNvzcL+dmt0uvU+M4aMfii++WmVrEsiZlavWxu9HPBDt9z7S2JxHVR9wbJx1yQ3x8JMvxOdfrnSjkle2bKmPr1atjw+Xr4z573waM954L556aUGMfWpOjHrwZR+bl/KwP9w1OfY+5JfmWElKU/1OvLLk5pJjzr0xJ9f61Tlvp7xufez5+dYBUhq7ZfyMWL12o4fi73H/w8+aI3NYp84HxdtlFVFXVp7VnqlsH22r+vgNJBVdgzv2yPqYWqhd1m5X90ya+z+dBvyH04UAAAD5xV8BAJLipeMAia8zvXQc4O/dboYASMtas9aUAgAAAFnxzcvRfmo3AiBje50/bcoLiwEAaA7n2wGcbwcAAIB8dKDdCAAAgCxoUd1vqo+gSH9ut74nR31DQ0Htolx7yxi/nVKu/3EXxhOTZsTW+npbkkDOrF23Ia6/bXy02/NwY3Me1Ga3w+KoM38dtz8wMeqWfOAGJeu2bK2Ptes3xRcr18XHn62KpR9+EW+982m8Ou/9mPzK4njs+fkx5sk5cVvtTB+Tlwqsi294ODrsc7T5VpLSubdz4q9Lbj4Zfv+L0XHfY7N+rfsde0HKa9wVX621FpDS3JRX3/EA/T2Wr/gyWnXpb57MYTe37Rp1ZeVZb3ybHWO76hq/gaSia2Jlh5yMq4XW6LZV7pc016qq/95OFwIAAOQXfwUASIqXjgMkvs700nGAv/e6GQIgLWvNWlMKAAAAZE2Z3QiAjO11VppmAABoJufbAZxvBwAAgHx0gd0IAACALGhRVfOuj6BIf93jk2YU1C7KylVro90eh/vtlHDt9jw8Lrt2dCxd9rFtSCCn6hsa4v6Hn40dexxlfM5h23QdEH2OOj9+P+KBeOX1t2PLlq1uTr77f7P1DbFh45ZYtWZjfP7V2vhw+cp498MvY8kHX8Q7738eby9Z/n+bu+jjmLPgo2+b/faHMfPNZTF9zrvxwqwlMfmVxfHsjEXx5EsLYuLU+fHwpHkx9qk5cdejr8Wo8S/7OLxUpB0/dERss/NAc68kpbkBP7+qJOeVs668OyfX+7kXX0t5Pf1c0xrYmkBKXyPHzYiVazZ4WP8evQ4/xzyZw/bs1DMWlZVHXQ66pW11tK6u8TtIKqoGdeyRkzG10JpUuYP7Jc21qOp/qtOFAAAA+cVfAACS4qXjAImvM710HODvbWrqn80SAM1ea9aaUgAAACBrBtqNAMjYXuehphkAAJrJ+XYA59sBAAAgH423GwEAAJBpgwf/Y4uqmi0+giL9dQf97LyC20n53Yj7/Xb60XofcU48MOG5WL9ho+1HIOden1cXPQ//pfE5R+3W9+S48OpR8fTzM2PV6rVuyBK1fuOW+GrV+vhw+cqoW7Yi3qz7OGbOXRZTXlkcT7zwdtQ+Ozfue3x2jJ7waowaP8NH2yWl1PX3TI0DjrzQ/Pv/s3ffUVaVecLv35l1577rzr135n3XuvfOdAFqnSLHUxSKCgYUBRSqChBFFMXcGNA2x1bMWRpaEEHFQCNFgwkTCgoNqAgGgpSiKIoJCZJDhedir55Zvj2Gc07tOmefqs9nre/fM13P6f3s/ePpvSWpnhpwzs2Ndo85qPS8rP+9jxh0Qaipqc3o/vv7LTvDWPfVUqTNWlDp4f5n3DV2sn0yx01t0SFUFiZy0o2tu1oDSQ2up1q0z9l1NV9aUVgU9i0u9XuJsIJk6WgHDAEAAOLFvwAApMVLxwFSv8/00nGAn9bRLgFQ53vNCtsJAAAAZM1NphEA9TbrvM02AwBAHTnfDuB8OwAAAMTRh6YRAAAA9axJh/5NfQBF+uneWLw8ryYpG7/fElofcqK103+pQ4+hYeQ9D4ePVn9h5AjEQlV1dbjngSlhn5L+rtNZrFW3weHUETeFJ6a/HNas/cYPsVH8d60mbNy8Paz5amNYvurr8Mb7n4VZCyvD9FfeD5OeXhTunzLfB9gl1Xsj//h0SB59hr1Ykuqxgefc0mj3metGTQ9NO5dn/W/+55mvZXyfPnfxx+4RpAi7f8pf/vrsy3/17rKP7JM5blD7HqGyMJGzLmzbzTpIalD1b39ETq+r+dLBHXv5vUTbK04YAgAAxIt/AQBIi5eOA6R+n+ml4wA/bZhdAqDO95oVthMAAADImpmmEQD1Nut8yTYDAEAdOd8O4Hw7AAAAxFHN3v5vEwkAAIB69JtO/br5+In005064qa8m6aMeWiatdNfa1ZSHspPuzI8Mf3lsHPXbqNGIDa2btsR+p1yuWt1lvaCY4deGu4d/2R4f8WqUFNT6wfYAO3ZUx3WbdwaPvpsXXh72edh1sLKMO3l98JDM970cXVJOe+314wP+x1wnH1Zkuq54357a6Peb3oPvSbrf/OD+p699168KqN7+B0794Tx0xa6V5Ai7JWFHxoQ/NQJ3JrakOx5qr0yhzXd26zmbUJlYSInrdzbsHaHWgtJDappLTrk7LqaL53QvoffSoQVJMu+dMIQAAAgXvwLAEBavHQcIPX7TC8dB/hpf7BLANT5XrPCdgIAAABZ85VpBEC9zTq/sc0AAFBHzrcDON8OAAAAcdXdRAIAAKAeNU2WDfEBFOlnPnTXuTx8+MnneTVJ2blrd9i/9xnWrxF3cL9zwj0PTAlr1vrfmgDxs3v3nnDCOde5XtdjbQ4dEn57+Z2h4tnZ4bsN3/vRNSBbtu8Kn325Mbyzcm14bdGq8NSrS8MjT73l4+mSYtm9k+aEY0651t4sSVlq0PBbG/W+c9v4F8J+BxyX9b/7w1NmZnx/v2jZGvcMUoSNnTI/bN660/DgJ1x8/Wh7ZY47r233UFmYyFnLC4tCaYcjrYWkBlNZhyNyel3Nhy5vc5DfSsQlSgb9q1OGAAAA8WH6D5AWLx0HSP0+00vHAX7aXLsEQJ3vNStsJwAAAJBV/2YiARD5nLPA9gIAQAScbwdwvh0AAADi6nwTCQAAgHrUJFl2tY+fSD/fpSPH5N00peLZ2daukdX6kBPDiGvvC/PefC/U1tYaKQLxnfhfc6/rdj3UY+D54eZRk8LCt5eFqupqP7Q8t3tPVVi3YWuoXP1tmLf4k/DMnGXhoRlv+ki6pLzp2nunhQ5HDrNHS1IWO+Hc2xv9/jP4/Duy/ndP9jw1bNu+M6P7/j1V1eHhGW+5d5Ai7LVFqwwVfsLzry60V+a4omS/sDjRIlQWJnLWkr3/97t37GU9JDWYKlp0yOl1Ne7d37Kz30nUde53oFOGAAAA8WH6D5AWLx0HSP0+00vHAX7aersEQJ3vNStsJwAAAJBVPUwkACKfcx5tewEAIALOtwM43w4AAABxNc5EAgAAoB4VJEvH+/iJ9PMVdj0urFu/Ka+mKTU1taH3iRdbvwbevvsPCMMuvDk8N2t+2LV7tzEiEHtPvTDX9TuqD/EeOCicfP7I8MjU58Oatd/4ceWxLdt3hU++WB/efP+z8Nzry8Okpxf5ELqkvG3M5Hnh5IvuCc1K+tuvJSnLDT7/jka/D9336JzQ6pCTsv63HzVhasbPA8s++so9hBRh455cELbtMCv/e1u37Qj7HTDQfpnjbm59QKgsTOS0BUWtQudOfayHpAZRaYcjc35djXPPtWjrdxJxBcWlpzllCAAAEB+m/wBp8dJxgNTvM710HODn/ZudAqBO95oVthIAAADIqvNNJAAin3P+zvYCAEAEnG8HcL4dAAAA4mqeiQQAAEA9KkiWvuTjJ9Ivd9+DU/NuovLOsg9Ds5Jy69fA+mFNjzvrmvBoxYth/cbNRodA3vj62/Wh3eEnuZbXoWTPU8OIa+8Lz82a/9ePIZN/fviw96drN4S3lq4JM+euCA/PeNNHzyU1mO6Y8FI4ZMBF9mxJylGDz7/TfrS3s68el/W/fatug8N3G77P6BmhprY2TJ652NpJEfaXJZ8YQPyEwb/9vf0yx+3fqU/4oLAoVBYmctpLzduE1sljrYmkBtH05u1zfl2Na+8nmodmxaV+JxFWUFx2m1OGAAAA8WHyD5AWLx0HSP0+00vHAX7eEXYKgDrda1bYSgAAACCrxplIAEQ+55xgewEAIALOtwM43w4AAABxtdFEAgAAoB41SZat9PET6Zcr6XV6qKqqzrupyuU33W/9GkDNSspD+WlXhomTnw3frNtgXAjkndra2nDi8Otd09Nsn5L+YcDpV4X7H5keVq76zA8pz+zeUxXWfLUxLFq2Jjz72vIwcfobPm4uqcE2YuQjoflBg+3fkpTDTrzgTnvS3sZMnhc69z4r63//m+57JONnh1VrvrN2UoQ9MHVB2LFzj8HE3/nh3xfsl7nv8ZYdQ2VhIudNa9EhJJL9rImkvG9Q+x6xuK7Gtc6d+vidRFhBsmyGU4YAAADxYfIPkBYvHQdI/T7TS8cBft4FdgqAOt1rVthKAAAAIKvmmUgARD7nXGh7AQAgAs63AzjfDgAAAHH276YSAAAA9eMfmiTLtvv4ifTrPTtrft5NVDZ9vzV0PGKo9cvDmpWUh7JhV/z1Q5dff7veeBDIa9Off821PcU69BgaLrjm3vD0S/PC95u3+vHkkc1bd4bK1d+GeYs/CVNfejfcP8WHzCU1/O6dNCcce+p19nBJikFDRtxtb/pbl90+Oet//0TXQeGrbzKf4f151nvWToqwN9771KDi73z6+Vf2yxg0sH2PUFmYiEWPtEyGfZKl1kVSXtd0b883bxeba2vcKm9/pN9JhBUUly5zzBAAACA+TP4B0uKl4wCp32d66TjAzxtnpwCo071mha0EAAAAsmqjiQRA5HPOTbYXAAAi4Hw7gPPtAAAAEGdHmkoAAADUg3/r2P//8+ETKbX6n3ZlXk5VnnphrvXLk4oOHBSGXXhz+NOMWWHd+o1GgkCDsHXbjtD56NNc53+hg/qeHa67c0KY9+Z7oaqq2o8mD1RV14Qvv/0+vL3s8/Dsa8vDg9Pe8NFySY2uK+96MrTvMcxeLkkx6aQL77Y//agegy7J+hpceuMfM37GWLv3+cK6SdH14LSFYdfuKgOMv3NY//PsmTmuWXFpeK1561BZmIhFd7XuYl0k5X0ntzs8NtfVuHV+2+5+IxFWkCzd8d/+2/X/6LQhAABAPJj6A6TFS8cBUr/P9NJxgJ83z04BUKd7zQpbCQAAAGTdv5lKAEQ242xqWwEAICLOtwM43w4AAABxdoGpBAAAQD1omuy7vw+fSKm3vHJ1Xk5Wzr7sDusX0zr0GBpGXHtfeG7W/LB12w5jQKDBuXnUJNf7v6uw63FhyLk3hIefnBk+//JbP5I8sKeqOnz+9abw1tI14Zk5y8K4qQt8pFxSo+2+R+eE0jNuCE07l9vXJSlOH5K/6F771I8a+cdnQrOS/lldg327DAgff7o24+eO515fbu2kCHt72ecGGn9n5D0P2zNj0O/aHhwqCxOx6aK23ayLpLyuWXFpeLmoTayurXHp9tb7+41E3L8XD9jXaUMAAIB4MPUHSIuXjgOkfp/ppeMAP2+jnQKgTveaFbYSAAAAyLojTCUAIptxHm1bAQAgIs63AzjfDgAAAHH2gKkEAABAPWiSLB3koydS6l06ckxeTlbWrd8UOvQYag1j0L77DwgDTr8q3Pfg1PDOsg9DTU2t0R/QYK1e82Uo7Hqc6//eftiHR1x7X3hu1vywZdt2P46Y27m7Knzy+fowb/EnYeqL74b7p8z3QXJJ2ttVd08NHY4cZm+XpBg29KJ77VV/V99hv8/6Opxz+Z0ZP4es37Rt77OHdZOiauL0N8KeqmpDjh+Z9+Z79swY1CrZN7yfaB4qCxOxaOXeTml/mLWRlNed1u6w2FxX49QTLTr5fURcQbK0p9OGAAAA8WDqD5AWLx0HSP0+00vHAX7Zb+wWABnfa1bYRgAAACDrLjCVAIhsxnmRbQUAgIg43w7gfDsAAADE2V9MJQAAAOpBQbLsEh89kVKv6MBB4fvNW/NyujLzlQXWMEcd1v+8cO0dD4ZZcxeFbdt3GvUBjcZJ541stNf+pp3LQ+8TLw53jZ0c3lv+UaipqfWDiLEfPrK95quNYcE7q8PUF9/1IXtJ+rtGPfZa6H/WjX/d3zzjSVI8O+Xi++xZf9ftE14K+x1wXNafBd//4OOMn01mLay0dlKEvbNyraHHj+zevSe0OPgE+2YMurdVl1BZmIhNywuLQt8OPa2NpLxtn2RpmFPUOlbX1jg0d+/fxO8j2gqSZec6bQgAABAPpv4AafHScYDU7zO9dBzglx1qtwDI+F6zwjYCAAAAWTfaVAIgshnnWNsKAAARcb4dwPl2AAAAiLNvTCUAAADqQUGydLSPnkjp9fCUmXk7YbnspvutYZZbsrTSaA9olBYsWtrorvnNDzo+DLvw5vDE9JfD19+u9yOIsZra2rBuw9awZMUX4Zk5y8K4Jxf42Lgk/UxX3PVk6HjkaZ7vJCnmDbtklH3rJxo0/Lasr8UpI27K+Fll05YdYeyU+dZOiqiHZ7wVqqprDEJ+5IfZlX0z9x3W8ehQWZiIVUsSLUL3jr2sj6S87bdtD4ndtTXXfVBYFBLJfn4fEVaQLL3PaUMAAIB4MPEHSIuXjgOkfp/ppeMAv+x0uwVAxveaFbYRAAAAyLoXTCUAIptxzrKtAAAQEefbAZxvBwAAgLj7F5MJAACAiDVJlj7roydSeh05aETeTld27d4djjrhQuuYpQ7qe7aRHtBo9Tvl8kZxre905ClhxLX3hedmzQ/btu+08DG2afOO8P6HX4bnXl8exlcs9HFxSfqV7nlkdig7c2Ro2rnc850k5UGnXTra/vVT+9mk2aFltxOzvh7vLPsw42eX2W9+ZO2kCFv60VeGIj/yyNTn7ZsxaXrz9qGyMBGrXi9qHdp3Otb6SMrL9isuDfOLWsbu2prrunfs5fcRYQXFZTOdNgQAAIgHE3+AtHjpOEDq95leOg7wy26xWwBkfK9ZYRsBAACArPvIVAIgshnnatsKAAARcb4dwPl2AAAAiLtikwkAAICIFRSXvuejJ1L6LVlambcTlg8/+Tw0P+h465iFrrtzgpEe0Ci9MHthg76+9xlycRg1YWpYXul/2xdne6qqw+dfbwrzFn8SHn3mbR8Sl6Q0Ov/6h0Kr7kM810lSHnXaZaPtYT/TsEtGZX09hpx7Q8bPMlu27Qrjnpxv7aSImvT0olBdU2tQ8jdr1n5j34xJQ9sfFioLE7HruRZtQ/PiftZIUl42ok23WF5bc9ng9of7bURYQXGZlykDAADEhIk/QFq8dBwg9ftMLx0H+GVT7RYAGd9rVthGAAAAIOuq9vZPJhMAdZ5v/u97q7atAAAQEefbAZxvBwAAAHNMAACAxqYgWfq9j55I6XfpyDF5PWV55uW/hKady61lPffWux8Y6QGNTnVNTegx8PwGdT1vVlIeyk+7Mtz/yPSwes2XFjnGvt2wNby97PMw/ZX3w9gpPkIvSel2+4MvhiNOuNTznCTlYadf/kd72c80+vHXQ7sep2Z9Td5csjzjZ5vXF62ydlKEffDJN4YmP3JI+XB7Zwzap7g0LChqFSoLE7HrsZad9v7/Z40k5V+JZL/wRqJlLK+tuerStgf7bURZsqyqpORsL1MGAACIAdN+AC/rAain+0wvHQf4Ze/YLQAyvtessI0AAABAThSZTADUeb7ZynYCAECEnG8HcL4dAAAA4u4qkwkAAIAI7dup7H/44ImUWS0OPiFs2bY9ryctt//xcWtZj3UvGx5qa2uN9IBG508zZjWMj9qW9A/lp10ZJk5+Nnz73UYLG1NV1TXh07UbwmuLVoVHnnrLh8IlKcPGTJ4Xzrzy/pA4YJDnOUnK08644o/2tF9o+LXjs74mJ5xzXcbPOtt27A4PTF1g7aSIevzZt83rf+S6OyfYO2PS1W0ODJWFiVh2b6su1khSXnZp24Nje23NRaNalfhdRFxBx/KWTh0CAADknmk/QFq8dBwg9ftMLx0H+GVb7RYAGd9rVthGAAAAICd6m0wA1Hm+2dd2AgBAhJxvB3C+HQAAAOLuIZMJAACACDVJ9u/kYydS5j3+55fyetJSU1Mbhl14s7Wsp/4w0TttgMZnz56qcECfM/P22l104KBw5iW3hxnPvx42b9lmQWNq89adYfmqr8PMuSvCuCd9ZF6S6to190wLJX3O8RwnSXneWVeNta/9QmMmzwude52V9XVZ+PayjJ995i3+xNpJEfbRZ+sMVf7mtQVL7J0xqUOnY8KKwqJQWZiIZVe1Ocg6Scq7Wib7hcWJFrG9tma76c3b+11EXEHn8r5OHQIAAOSeaT9AWrx0HCD1+0wvHQf4df9mxwDI6F7TC0gAAAAgN843mQCo83zzItsJAAARcr4dwPl2AAAAiLu5JhMAAAARKiguLfWxEynz+px0Sd5PW7Zu2xH6DLnYekZc0YGDwncbvjfOAxqdx6a9mHfX7H1K+och514fKp6dHbZs224RY6i2NoSv1m0O899ZHZ54brEPgUtSRN0x8eVwzCnXhqadyz3HSVID6LfXjLe//UqX3Pp41tdlwBlXZ/wstH3n7vDA1AXWToqoKS+8Y8jyNzt37f7rv2PYP+PR+JbFobIwEctW7u2MdodaJ0l511VtDozttTXbvZVo4TcReaW/c+oQAAAg90z7AdLipeMAqd9neuk4wK/rZscAyOhes8IWAgAAADlxn8kEQJ3nm2NsJwAARMj5dgDn2wEAACDuvjSZAAAAiFDT4rILfOhEqluVq9bk/cRl/cbN4ZDy4dYzwq6+7QGjPKDRqaqqDgcee1beXKt7DDw/3P/I9PDtdxstXgzV1taGr9ZtDvMWfxIefuotH/+WpAgb/cTccOaV94cWBw/2/CZJDajzrp9on0uhbuUjsr428958L+NnowXvrLZuUoStXrvB0OVvTjpvpP0zJvXpcGSoLEzEthWFRaGs/RHWSlJe1Tp5bHinsHmsr6/Z7Ie/h99FlJWOdeoQAAAg90z6AdLipeMAqd9neuk4wK872Y4BkNG9ZoUtBAAAAHLiaZMJgDrPN2faTgAAiJDz7QDOtwMAAEDcxw4LoAAAIABJREFU1e7t/zCdAAAAiEiT4tK7fehEqlu3jn6sQUxdPv38q9DpyFOsaQTtu/+A8NkXXxvlAY3O439+KfbX6O5lw8M9D0wJq9d8acFiqKq6Jny6dkN4ZeGH4cFpb/jYtyTVQ5ffMSUkjzrDs5skNcBGjHzEXpdC1947LTTtXJ7VtSk99fKMn5N27toTxk9baO2kiJr64rsGMH/z0J+es3/GqBebtw2VhYnYtiTRPBzW8WhrJSmvuqFN11hfW7NZzw5H+U1EWbL0VacOAQAAcs+kHyAtXjoOkPp9ppeOA/y6q+0YABnda1bYQgAAACAn3jGZAKjzfHOp7QQAgAg53w7gfDsAAADkgxamEwAAABEpKC6b5mMnUt06oM+ZoaamtkFMXT746NPQocdQ61rHrr3jQSM8oNHZs6cqdD3mzFhelwu7HhfOvfLusGDR0lBbW2uxYmbnrqpQufrb8NL8lWF8hQ/FS1J9ddv4F8NRJ17hmU2SGnAX3/yYPS/FeuZgT5wzf0nGz01vvP+ZdZMi7POvNxnI7PXJZ1/aP2PUOW0PCZWFiVi3oKhVSCaPsV6S8qb2yWPD+4nmsb++ZqPT2h3mNxFlydLPnToEAADIPZN+gLR46ThA6veZXjoO8OvG2TEAMrrXrLCFAAAAQE6sN5kAqPN800saAACIkvPtAM63AwAAQD44wnQCAAAgIgXFZYt87ESqewsWLW0wk5fllatDu8NPsq4Z1rr7iWH9xs1GeECj88T0l2N3TU72PDX8YWJF2LDJdTlutmzbFd6r/DLMeHVpuH/KfB/0lqR67J5Js8Og4beF/Q44zjObJDXwLr1tsr0vxW4e+1xoVtI/q+tzzMmXhtra2oyeoXbtrgoT/vyGtZMi6qlXlxrO/M2Bx55lD41JiWS/sDjRIlQWJmLdcy3ahqK9/79aM0n50m2t94/9tTUbXdfmQL+HaKv9TUnff3byEAAAILdM+QHS4qXjAKnfZ3rpOMCvm2nHAMjoXrPCFgIAAAA583+aTgBkPNv8v2wjAABEzPl2AOfbAQAAIB8MM50AAACISJPi0m996ESqexdfP7pBTV+Wrvw4tDv8JGubQY9Mfd74Dmh09uypCl2POTM21+If/n+ZPP3lsHv3HosTI5u37gzvVX4Zpr/yvg94S1IWGv3E3HDGFX8MLbsP8awmSY2kK+560h6YRmWnj8z6Gs2auyjjZ6pFy9ZYNynCvlm/xbBmr8tuut8eGqNuaXNAqCxMxL6JLZOhWXGpNZOUFyWTx4TlhUV5cX2tz8a1KvZ7iLx+HZ08BAAAyC1TfoC0eOk4QOr3mV46DvDrltoxADK616ywhQAAAEDOtDKdAMh4ttnWNgIAQMScbwdwvh0AAADywXWmEwAAABH4TUnff25SXFbrIydS3Wvd/cSwc9fuBjWB+Wj1F2H/3mdY3zQqPfXyUFNTa3wHNDpTnn4lFtfhVt0Gh7GTZoRdu3dblJjYuHl7eGvpmvDEzMU+2C1JWeyimx4NnXqe7jlNkhpZ19wzzT6YRndMeCnsd8BxWV2jXif+LtTWZjY/3L2nOkyc/oa1kyLq5QWVBjd7PTdrvj00Ru3fqU/4oLAoVBYmYt/vWx9ozSTlTfe06pIX19b67Nnm7fwWom+g04cAAAC5ZcoPkBYvHQdI/T7TS8cBft0mOwZARveaFbYQAAAAyJmjTCcAMp5t9rKNAAAQMefbAZxvBwAAgHzwoOkEAABABH5T0re1D5xI0fX0S/Ma3BRm7dfrwmH9z7O+KdSq2+Cwes2XRndAo1NTUxsO7X9uzq/Dhw84L6z69AsLEgNbtu8K71V+Gaa/8r6PdEtSlrtu1PTQrfwCz2iS1Ej7/agZ9sM0G3jOLVlfpxdmL8z4eWvJii+smxRR90+ZHzZv3dno5zibvt8a9inpbx+NUU+07BQqCxN50dntDrFmkvKiLh37hBV5cm2trxYnWvgtRF2y31VOHwIAAOSW05oAafHScYDU7zO9dBwgNf9i1wBI+16zwvYBAAAAOXO66QRAxrPNs2wjAABEzPl2AOfbAQAAIB+8ZDoBAAAQgaady3r5yIkUXadddEuDnMRs2LQ5DDj9Kmv8Kz3z8l+M7YBG6flXF+b8Gtz6kBPDmrXfWIwc2rlrT1i+6usw/ZX3fZhbknLQTfc/G4466crQtHO55zNJasTdMOYZ+2Ka3fXwrJA4cFBW1+nIQSNCTU1tRs9ee6qqw8Mz3rR2UkT9ZclqQ529jjn5UvtojBrUvkeoLEzkRcsKi0LvDj2tm6S86I+tOufN9bW+apXs67cQZcmyh50+BAAAyC0TfoC0eOk4QOr3mV46DpCadnYNgLTvNStsHwAAAJAzN5hOAGQ827zRNgIAQMScbwdwvh0AAADywQrTCQAAgAg06Vx+to+cSNGV6DoobNm2vUFOY/bsqQqX3vhH6/wzXXfnBCM7oNHqc9IlOb8Oz3j+dQuRA7t2V4XK1d+GmXNXhLFT5vsYtyTloFsfeD4cc+q1oVlJf89mkqRw87iZ9scMOuG8O7K+Vs/Omp/xs9i7K9daNymixk9b+Nf5RmN3+x8ft4/GqH32Nr+oZagsTORFi4pahP079bF2kmLfwR17hQ8Ki/Lm+lofHdHxaL+FCCsoLn3d6UMAAIDccooTIC1eOg6Q+n2ml44DpKaXXQMg7XvNCtsHAAAA5MxE0wmAjGebD9lGAACImPPtAM63AwAAQD7YYjoBAAAQgYLislt95ESKthnPv96gpzIP/em5sO/+A6z1jzrtoltCdU2NkR3QKM19492cX4dPHH69hciiquqasGrNd2Hm3BVh3JPzfYBbknLUnQ/NCgPPuSXs22Wg5zJJ0n922/gX7JMZdO+kOaFFt8FZXaseA88PNTW1GT2XVe99Lpv09CJrJ0XUkhVfNPp5z8K3l9lHY9Y1bQ4MlYWJvGlW8zahVbKvtZMU+x5sWZxX19eoG9rucL+DKEuWrXH6EAAAILec6ARIi5eOA6R+n+ml4wCpOcWuAZD2vWaF7QMAAABy5jnTCYCMZ5vP20YAAIiY8+0AzrcDAABAvvhnEwoAAIA6KigunewjJ1K0nf67Wxv8VOadZR+GA489y3rvrfy0K8OOnbuM6oBG6/izr8vpdXi/AwaGjz9dayHqWVV1TVi15rvwwrwPwripC3xwW5Jy2N0PvRIGn39HSHQ93jOZJOm/dOdDs+yXGXbyRfdmfb1enPNGxs9pSz/6yrpJEfXIU2+F6praRj372bOnKrTsdoK9NEYVdzomrEgUhcrCRN70RItOYR9rJynmHdrx6LAyj66tUXd5m4P8DiKttKZ5897/3QlEAACA3HG6EyAtXjoOkPp9ppeOA6TmMrsGQNr3mhW2DwAAAMiZRaYTABnPNhfbRgAAiJjz7QDOtwMAAEC+2M+EAgAAoI6aFJfN94ETKdoSXQeFrdt2NPjJzPebt4YzL7m9Ua91+WlXNoq1Bvg57y77KOfX4ptHTbIQ9aS2NoSv1m0Ory1aFR6cttBHtiUpx9350KwwaPhte585j/fsLUn62e55ZLZ9M8Pue3ROaNV9SFbXq9eJv9v77FWb0TNbdU1teOzZt62dFFErV3/b6GdBp4y4yV4asx5r2SlUFibyqntbdbF2kmLfpBb5d32NqlGtSvwGIq6gY3lLJxABAAByx0lPgLR46ThA6veZXjoOkJq77RoAad9rVtg+AAAAIGfWmE4AZDzb/MI2AgBAxJxvB3C+HQAAAPJFVxMKAACAOiooLv3CB06k6HvqhbmNZkIz/fnXQtvDTmp0azz4t78PW7ftMKIDGrUzLr4tp9fiNocOCZu3bLMQEdu0ZUd48/3PwqPPLPJRbUmKQXdMeCkMPOfmUNj1OM/bkqRfbdTjr9k/69Cwy/6Q9TV7dd7bGT+/rfj4a+smRdSUF95p9DOhiZOftZfGrBPa9QiVhYm867y23a2fpFjXs8NReXl9jaKKFh38BiKuaXG/3k4gAgAA5I4TnwBp8dJxgNTvM710HCA1j9s1ANK+16ywfQAAAEDO7DSdAMhorvkPe9tlGwEAIGLOtwM43w4AAAD5otSEAgAAoA5KSs7+pybJ0mofOJGi74yLb2tUU5pv1m0Ip110S6NZ30tHjglVVdXGc0CjtnrNl6FZSXlOr8f3PTjVQkRk1+6qULn62/DMnGU+pC1JMemOiS+HgefcEvY74DjP2ZKklBszeZ59tA6Nfvz10O7wU7K6Zn2HXpbxs1xNTW149JlF1k6KqDVfbWzU86EPP15jL41Z++xtQVGrUFmYyKtWJIrCwPY9rKGkWPenFh3z7voaRfOLWlr/iCtIlp3rFCIAAEDuOP0JkBYvHQdI/T7TS8cBUjPLrgGQ9r1mhe0DAAAAcupfTSgA0p5r/k/bBwAA9cD5dgDn2wEAACBfnGVCAQAAUAf7dBmQ8HETqX4qOnBQ2LZ9Z6Ob1syauygc1PfsBruuhV2PCw8/OdNYDmCva24bn9NrcrvDTwpbtm23EHVQW1sbPv96U3hl4YfhgakLfDxbkmLSzeOeD/1O+33YZ/8Bnq8lSWnVrKS/vTSCzrpqbNbXbu4b72b8bLf0w6+smxRRz8xZ1ujnRSW9Trenxqzr2hwYKgsTedc7hc1D9469rKGk2HZsh555eX2tayv3lkj28xuItNK7nUIEAADIHSdBAdLipeMAqd9neuk4QGres2sApH2vWWH7AAAAgJxqaUIBkPZcs7XtAwCAeuB8O4Dz7QAAAJAvrjWhAAAAqIMmnUp7+LCJVH+9MHtho5zY7Ny1O4yaMDW07n5ig1rPQ8qHh6UrPzaSA9hr0/dbQ4uDT8jpdXnMQ9MsRIY2fL89LHzv0/DQjDd9MFuSYtQ19/05HHXiFaFZSX/P1JKkjNrvgOPsqRE0+om5of0Rw7K6dgPOuDrjZ7zq6prwyFNvWTspor7buK1Rz40u+v0f7Kkxq7jTMWFFoihUFibyrteLWof2yWOto6TY9lSL9nl5fa1r3Tr2tv4RVpAsm+EUIgAAQO44EQqQFi8dB0j9PtNLxwFS87VdAyDte80K2wcAAADkVHcTCoC055qH2T4AAKgHzrcDON8OAAAA+WK0CQUAAEAdFBSXnubjJlL9dfH1oxv15Gbj91vCLX94NBQdOCiv13HfLgPCdXdOCNt37DSOA/iP6fzEaTm9NnfoMTRs3bbDQqRh6/ZdYcmKL8LkmUt8IFuSYtYVdz0ZDhv4O8/RkqQ6V3TwCfbWiDr32gezvn5vLlme8TPfuyvXWjcpol5Z+GGjniFVPDvbnhrDnmjZKVQWJvKyPzdvH/YtLrWOkmLZie0Pz9vra106rn0P6x9ppe86hQgAAJA7TocCpMVLxwFSv8/00nGA1FTv7R/tHABp3WtW2D4AAAAgpwaaUAD4N3QAAGLB+XYAz+YAAACQL6aaUAAAANRBk+KyG3zYRKq/Oh15SqipqW30E5xv1m0IN4+aFFp3PzH/PqI1/PrwwUefGsMB/EhVVXXo0vv0nF6fx06aYSFSUFtbGz7/elN4af7KMHbKfB/GlqQYNfrx18M51zwQkkef4flZkhRZrboPsc9G1JjJ80JxrzOzPovM1J69z+oPTX/T2kkRNPbJ+WHr9l2Ndp709bfr7akxbHD7w0NlYSJvG92qs3WUFMuaFZeG2UWt8/oam0kj2nSz/lGWLNviFCIAAEDuOCkKkBYvHQdI/T7TS8cBUvc/7RwAad1rVtg6AAAAIKfONqEASHuuOdz2AQBAPXC+HcD5dgAAAMgXr5hQAAAA1EGTZNnDPm4i1W/vLvvICOdvtmzdHu6fNCMc3O+c2K9bv1MuD68tWGLRAH7C9Odfy+k1Otnz1LBj5y4L8Qs2bdkRFr73aXh4hg+qS1LcumPiy2HIiLtCq0NO8swsSYq8tocNtd9G2IiRD2d9DZcsrcz4WfDt5Z9bNymiFr77aaOeLR1SPty+GrP22duColahsjCRtw1v191aSopl57Q9JK+vr5l0e+v9rX3E/aak7//jJCIAAEBuODEKkBYvHQdI/T7TS8cBUldo5wBI616zwtYBAAAAOXW5CQVA2nPNq2wfAADUA+fbAZxvBwAAgHzxtgkFAABAHRQky2b7sIlUv901drIRzt+pra0Nc994Nwy/4q7Q/KDj4/NBwpL+4bSLbglvLF5ukQB+Qe8TL87p9frBJ56xCD+huromrFrzXXhmzjIfv5akGHbtvdNC75OvDvvsP8CzsiSp3upw5DD7boSNmTwvlPQ5J6treMqImzJ+Lty9pzpM+PMb1k6KoAenLdz736mqRjtnuvKWcfbVGHZ9666hsjCRt60oLAp9OhxpLSXFrsJkaXgj0TKvr7Hp9ljLTtY+4pp2Kj/ASUQAAIDccHoUIC1eOg6Q+n2ml44DpK7YzgGQ1r1mha0DAAAAcupWEwqAtOead9g+AACoB863AzjfDgAAAPniYxMKAACAOihIln7swyZS/dbrxN8Z4fyCbdt3hqdenBfOuPi20Krb4Jys0RGDLgh/mFgRvlm3wYIA/IqFby/L6b7a+ejTws5duy3Ej2z4fntY+N6nYeJ0H06XpLg1+vHXw7nXPhj2P2a452NJUlYq7nWmPTjiLrr50ex+iL1zeVi68uOMnxHffP8z6yZF1Lsr1zbaedOzs+bbV2NYl059wgeFRaGyMJG3LSpq8df/HNZTUty6rO1BeX19TbdZzdtY94grKC4d7CQiAABAbjhFCpAWLx0HSP0+00vHAVJ3hJ0DIK17zQpbBwAAAOTUWBMKgLTnmuNtHwAA1APn2wGcbwcAAIB8sd6EAgAAIGPX/2NBceluHzaR6v8jqF9/u94YJwV79lSFBYuWhltHPxYGnH5VKDpwUL2sSatug8PQC24MDzz2dPj086/84QHSMOzCm3O6r4579CmLsNfuvXvm8lVfh6kvvusj15IUw24b/2IYfP4doWX3IZ6LJUlZrWvf4fbiiBszeV7o0vvsrK7jmZfcnvHz4s5dVWH8tIXWToqgSU8vCjU1tY3zZO7GzX/99y17a/ya3KJjqCxM5HUzm7cLiWQ/6ykpVrVM9g1LEi3y/hqbau8nmoem1j3akmVXO4sIAACQG06UAqTFS8cBUr/P9NJxgNQNsHMApHWvWWHrAAAAgJyaYkIBkPZcc6rtAwCAeuB8O4Dz7QAAAJAvqvf2D6YUAAAAGWjSoX9THzWRstMT0182xslAVVV1eP+Dj0PFs7PDLaMmhWEX3hx6Hn9haH/4ySn93ZsfdHzoMfD8MPSCG8MNdz8Upj4zOyxb+Umoqq72xwXIwCeffRmaleTuY7qtDzkxbNm2vVGvwZfrNodXFn4Yxk1d4OPWkhSzRk+eFy688ZFw2MDfhWY+Pi9JylHdykfYl+uhC2+alNV1/OHZu3LVmoyfHRe8s9q6SRH10WfrGu0c6od/j7G3xq8h7Q8PlYWJvO/+lp2tp6TYdVPrrg3iGptq7Tsda90jrKC4dILTiAAAALnhdC9AWrx0HCD1+0wvHQdI3Rl2DoC07jUrbB0AAACQUy+aUACkPdf0Ym0AAOqD8+0AzrcDAABAPvkXUwoAAIAM/KZTv24+aiJlp7Mvu8MIJ2K7du8O6zduDp998XV4/4OP/7OPVn8Rvlm3IezYucsfCSBiV906Lqf76a2jH2uUf/fde6rD8lVfhydfeMfHrCUpht02/oVw8kX3hLaHDfX8K0nKeT2Ov8T+XE916fPbrK7leVfdnfFz5Pade8IDUxdYNymCfpjHNFbX3zXR3hrD9ikuDQuLWoXKwkTed1HbbtZUUqzq1OnYsLywqEFcY1OpZ4ejrHuUJUtfdRoRAAAgN5zuBUiLl44DpH6f6aXjAKm7xM4BkNa9ZoWtAwAAAHLqTRMKgLTnmotsHwAA1APn2wGcbwcAAIB8so8pBQAAQAaaJsuG+KiJlJ3aH35yqKmpNcYBIG9t+n5raH7Q8TnbSwu7Hhe+WbehUf3NN3y/Pcxb/EkYX7HQR6wlKWaNfvz1cMHIh8IhAy8KTTuXe+6VJMWmo0660l5dT4248ZGsruU+Jf3DJ599mfEz5Q/Pk9ZNiqa133zfKOeBs+YusrfGtBvadA2VhYm8b0WiKPRvf4Q1lRSr/tCqpEFcY1NpaPvDrHmklX7qNCIAAEBuOOELkBYvHQdI/T7TS8cBUneTnQMgrXvNClsHAAAA5FSlCQVA2nPNj2wfAADUA+fbAZxvBwAAgHzSyZQCAAAgA02S/a7yQRMpey1d+bExDgB5a/TEaTndRy+5YUyj+DtXVdeElZ98E6a9/J6PVktSDLvmnopQdvrI0PygwZ5zJUmx7Nhh19mz66kxk+eFzr3Pyup6XvT7P2T8fLl1+64w7sn51k6KoOdeX9Eo54Fbtm4P+3YZYH+NYV069gkfFBaFysJE3rc40SLs36mPdZUUmw7q2LvBXGN/rUvbHmzNoyxZWl1ScvY/OZEIAACQfU74AqTFS8cBUr/P9NJxgDT+56d2DoC07jUrbB0AAACQU1+ZUACkPdf8xvYBAEA9cL4dwPl2AAAAyCeHmFIAAABkoCBZ+oCPmkjZa+ykGcY4AOSlqqrq0KX36TnbQ5t2Lg8ffvJ5g/4bb9qyIyx879MwcfqbPlYtSTHr9gdfDMMuGRU69zrLs60kKfaVn3mj/bseGzHy4ayu5777DwhffLUu42fNOW+tsm5SRG3cvKNRzgX7Dr3M/hrT/tSiY6gsTDSIXm7eNrRM9rOukmLTpJbJBnON/aXuad3Fekdcs5LyIicSAQAAss8pX4C0eOk4QOr3mV46DpC6CXYOgLTuNStsHQAAAJBT35tQAKQ919xi+wAAoB443w7gfDsAAADkk16mFAAAABkoSJa96IMmUvYacu4NxjgA5KVpz83J6R467MKbG+TftaamNnz8+Xfh6dnLfJxakmLWPZNmh+HXjg+HDLgoNOtc7plWkpQ3DRp+m728HhszeV4o7nVmVtf0+rsmZvzcuXnrzjB2ynxrJ0XQvMWfNMq54G1jHre/xrST2x0eKgsTDaaJLZOhqXWVFJP6dOjZoK6xP9fkFh2td8T9JtnvKCcSAQAAss8pX4C0eOk4QOr3mV46DpC6yXYOgLTuNStsHQAAAJBTe0woANKea1bZPgAAqAfOtwM43w4AAAD5pNyUAgAAIANNkmUrfdBEyl7NDzo+7N69xygHgLxz9OCLcrqHvvXuBw3q77lj556wZMUX4dGnF/kotSTFqFGPvxYuvGlS6HXyVWG/A47zHCtJystOGnGXfb2eu+CGh7O6pi0OPiFs2LQ542fQVxZ+aN2kCBo/bWHYvafxvefp9YXv2F9j2r7FpeGNRMtQWZhoMF3R5mBrKyk2TW/evkFdY3+q2UWtrXX0neNEIgAAQPY55QuQFi8dB0j9PtNLxwFSN8POAZDWvWaFrQMAAABy7n8zpQBIeab5320bAADUE+fbAZxvBwAAgHwyxJQCAAAgff/QJFm23cdMpOz2xuLlRjkA5JX5i97P6d7Z75TLG8zfct3GreG1RavCA1MX+Bi1JMWk0Y+/Hi666dFw9ElXhsQBgzy3SpLyvmGXjLLH13NjJs8LxUefmdV1vXf8kxk/i27cvCPcP8W6SVH0XuWXjW42uG37zrBvlwH22Jg2svUBobIw0WD6oLAoHNe+h7WVFItO2Hs9akjX2J9q+d7rbrPiUusdZcnSOxxJBAAAyD4nfQHS4qXjAKnfZ3rpOEDqXrJzAKR1r1lh6wAAAICc+xdTCoCUZ5r/w7YBAEA9cb4dwPl2AAAAyCdnmlIAAACk6d+Tg/5fHzORst9dYycb5QCQV04dcVNO984XZi/M679fTU1tWLXmu/DMnGU+Pi1JMWnU46+FC2+aFPoMvToUHXyCZ1VJUoPqrCvH2u+z0PnXP5TVde3QY2jYsXNXxs+mL81fad2kCHr82bdDbW3jmw/2HXqZPTamde3UO6wsTITKBtSSRPNwUMfe1ldSzmu6t5eat2lQ19ifqlOnY613lCXLpjiVCAAAkH1O+gKkxUvHAVK/z/TScYDUzbNzAKR1r1lh6wAAAICc+3dTCoCUZ5oFtg0AAOqJ8+0AzrcDAABAPhlhSgEAAJCmZsWlXXzMRMp+A8642igHgLyxes2XoVlJec72zUPKh4eamvz8UvGOnXvCkhVfhElPL/LRaUmKQfdMmh3O+/2E0HPw5aGw63GeTyVJDbbh102w92ehMZPnheTRZ2R1bR+eMjPjZ9TvNm2zblJEfbp2Q6ObEd4yapI9NsY92aJDqCxMNKheLWoTWib7WV9JOe+sdoc0uGvs39e7Q09rHWmlC5xKBAAAyD6nfQHS4qXjAKnfZ3rpOEDqFts5ANK616ywdQAAAEDOFZpSAKQ802xu2wAAoJ443w7gfDsAAADkkytMKQAAANLUpLhsoA+ZSNmv+UHHh6qqauMcAPLC9XdNzOm++cT0l/Pub7Zuw9bwysIPw7gnF/jQtCTluDsmvBTOumpsOPy4i8O+XQZ6JpUkNYouvPER9wFZ6vzrs/vMfOCxZ4Wq6sxnyzPnrrBuUgQ9M2dZo5sRvjrvbXtsjBva7vBQWZhocD3QqrP1lZTz9ikuDfOKWjXI6+x/dGq7Q611hBUUl37hVCIAAED2Oe0LkBYvHQdI/T7TS8cBUrfCzgGQ1r1mha0DAAAAcq6dKQVAyjPNjrYNAADqifPtAM63AwAAQD65wZQCAAAgTQXFpRf7mImUm95b/pFxDgCxt33HztDm0CE52y87HjE07Nq9Oy/+VrW1IXy6dkN46tWlPi4tSTlszOR54br7pocTL7gzdDnmnNC0c7lnUElSo+vS255wX5DFe49OR52R1fWd8fzrGT+7frN+i3WTImrD99sb1Zxwy9btYZ+S/vbZmLZvcWl4K9EiVBYmGlwXtO1ujSXlvEvaHNyPMTWgAAAgAElEQVQgr7H/0ZVtDrLOUZYsrS4pOfufnEwEAADILid+AdLipeMAqd9neuk4QOo+tXMApHWvWWHrAAAAgJzb35QCIOWZZlfbBgAA9cT5dgDn2wEAACCf3GVKAQAAkKaCZOloHzNpOJ103kh/hzzqoT89Z5wDQOw9/ueXcrpf3nn/5Nj/japrakLl6m/Dn55f4oPSkpSj7nt0Trjo5kdD32G/D60PPckzpySp0XfV3VPdI2Sx834/Iavr2/P4C0NtbW3Gz7EzXl1q3aQIev3tjxvdrLDPkIvtszHu9tb7h8rCRINrRWFR6NOhpzWWlNNaJvuFxYkWDfI6+0P3tSqxzhH3b53K9nMyEQAAILuc+AVIi5eOA6R+n+ml4wCpW2vnAEjrXrPC1gEAAAA5d7ApBUDKM83utg0AAOqJ8+0AzrcDAABAPrnPlAIAACBNTZJlz/iQSQP5gE+3E8K27TvDYf3P8/fIk8698m7jHABi78hBI3K2V+67/4Dw9bfrY/u32bFrT1iy4ovwyFNv+ZC0JOWgm8fNDMMuGRW6lY8I+3YZ6DlTkqQfdf3op9wvZLHRk+eFDkcOy+oaz/7L4oyfZz9du8G6SRH0wNQFYefuqkY1K7zh7ofsszGuR8ejQ2VhokH2RlHL0KHTMdZZUk67oU3XBnud/VOLjtY44poWlx7qZCIAAEB2OfELkBYvHQdI/T7TS8cBUveNnQMgrXvNClsHAAAA5NwhphQAKc80D7dtAABQT5xvB3C+HQAAAPLJGFMKAACANBUUl77nQyYNo8MHnPfXp+PllatDousgf5M86IA+ZxrnABBrC99eltO98ryr74nl32Xj5u1hzlurwripC3xAWpKy2B0TXgrDrx0fep18VWjZfYjnSkmSfqGbxz7n/iHLnXXV2Kyu8cAzr67Ts+2fnl9i3aQIenfl2kY1L3z59bfsszHv+ebtQmVhokH2ZIsOYR9rLCmHtU8eG5YmihrkNXZ2UWtrHHn9TnYyEQAAILuc+gVIi5eOA6R+n+ml4wCp+87OAZDWvWaFrQMAAABy7nBTCoCUZ5pH2jYAAKgnzrcDON8OAAAA+WSsKQUAAECaCpKl3/uIScNoyLk3/OcT8mPTXvQ3yZO++ma9kQ4AsXXWpbfndJ98d9lHsfp7fLVuc5g5d4UPRktSlrrzoVnhwpsmhYHn3BK69D47NO1c7jlSkqQUu2PCS+4nstzoJ+aGNocNzeo6v/3eyoyfcT/45BvrJkXQo88sCrW1tY1mXrjp+62hWYlnszg3ok23UFmYaLBd37qrdZaU0+5t1aVBXl+XJopCU+sbbcmyq51MBAAAyC6nfgHS4qXjAKnfZ3rpOEDqNto5ANK616ywdQAAAEDO9TSlAEh5pnm0bQMAgHrifDuA8+0AAACQT8abUgAAAKQhUTLoX33EpOF06Y1//F+eks+76m5/lzzouVnzjXQAiKWvvlkf9u0yIGd7ZL9TLo/F36GmpjasWvNdmPbyez4ULUn13J0PzQojRj4cys4cGZJHnRGadvahdkmSMu2eSbPdX+SgYZeMyuo6n3HxrXV63p309CLrJkXQZ19ubFRzw6NOuNBeG+PadOoblhUWhcrCRINs5d5OaN/DWkvKWQd26h0+aKDX2fbJY61xhBUkSx9wOhEAACC7nPwFSIuXjgOkfp/ppeMAqdti5wBI616zwtYBAAAAOdfLlAIg5ZlmH9sGAAD1xPl2AOfbAQAAIJ88ZEoBAACQhibF/Tr6iEnD6d7xT/4vT8lbt+0Ih5QP97eJeSPvedhIB4BYuvP+yTndI596cV5O//Pv3lMVlnzwhQ+MS1I9dtPYZ8M5V48Lx5x6bejU87TQtHO550RJkiJq9OR57jdy0H2Pzgktug3O2jo3KykPH63+IuNn3yUrvrBuUgQ99/ryRjU3vO7OCfbamDexZTJUFiYabIsTLcL+nfpYa0m5u862apjX2R4dj7a+EVZQXPqC04kAAADZ5eQvQFq8dBwg9ftMLx0HSN12OwdAWveaFbYOAAAAyLljTSkAUp5p9rVtAABQT5xvB3C+HQAAAPLJJFMKAACANBQUl/XzEZOG09RnZv+XJ+UVH34aEl0H+fvEuEFnX2ukA0Ds7N69JyR7npqz/bGk1+mhqqo6J//Zd+zaE95auiZM+PMbPgotSRF276Q54Yo7p4RTLr4vHHH8ZaFl9yGeCSVJqqf27TLQ/UcOGzLirqyu98XXj878+X9PdXhwmudfKYo2bdnRaGaHz7+60H4b8wa27xEqCxMNuheatw2JZD/rLSknHdnxqAZ5bT2hXQ/rG2EFxWXLnU4EAADILqd/AdLipeMAqd9neuk4QBpHU+0cAGnda1bYOgAAACDnSk0pAFKeaZbZNgAAqCfOtwM43w4AAAD55AlTCgAAgDQ0LS67wEdMGk4LFi396afl6S/7+8S4NocOCbW1tcY6AMTKn2e+ltP9cfTEaVn/z7xl+64wb/En4YGpC3wIWpLq2Ogn5oYbRj8VzrnmgVB25sjQpffZoVnncs+AkiRlqeYHDXZPksPueWR2SBx4fNbWe9/9B4S1X6/L+Hl4/jurrZsUQQv2/nepsVi3fpP9Nubt88O/HRe1CpWFiQbd/S07W29JOauiRYcGd129oG13axtlybItTicCAABkl9O/AGnx0nGA1O8zvXQcIHXVdg74/9m7zyipqkTh+/dZ97nPWs+n530/3TsNqFVNjtUNiKgYEBURqhsQTOgYEHMYs6Ij5oAYQDAxioEBzAFzZkBUxoAIlI5jQsecRSR07wd9Z93X6zWcU111quv077fW/9tdV6tPWWfvs/ecDbHGmre4dQAAAEDFjfSUAiDyM81RbhsAAJSJ/e0A9rcDAABANZnjKQUAAEAM7erykx1ikp7efOcfvzhjPvzUKf5GrbhV//jIYx0AWpUR+55YsftidsCY8MlnXyb6eZ9fvirMmLvQAdCSVERTb34qTLz0tnDgSVeEYb8/LdTvfFDo0HekuZ4kSRWsx3b7GKdUuN0OOS/Ra37WJdcVPSf+evV35sRSCZp5++KwfkNTm3l+OHD4BPfcVt6kbgNCIZNNfRN6DHK9JVWk0T23T91v6tldB7i2JW6TXrv+v3YoAgAAJMfuX4BYvHQcIPo400vHAWJw5wCINda8xZ0DILLF/5yjS5KiBUB0u3lKARD5meZubhsAsXhGIUnRa2/EDWB/O4D5uSRVvMVuGwCR3eIpBQAAQAzt6hpucYBJOmpf3xi+W7v2F2fM36xeE7ZuONTfqpX24BPPeKwDQKuxdPnfKnpfPG7StEQ/7/eHHV9722KHP0tShKZc/2g4efLcMP7k6WHE/n8M/XY5JGzSf5R5nSRJray6nccbu1S4C699MGzaf3Ri17zroD3D1998W/Tc+JGnX3XdpBK08u8ftJlniEdMvMQ9t5U3oM/QsDKTDYWUtyxTG7bvvZNrLin5fTrf7/Wo7Z6q39SrutS7tqUuN7KPHYoAAADJsQMYIJYx7hwAkceZXjoOEIM7B0CsseYt7hwAkXnpOID1cwDr5wDWzwGsnwMAYH5ufg5gfg5QvrGm/e0A0dnfDgAAEEdNXcNzDjBJR7kh+/3mrHnpitfDZpuP9vdqhU25ao7HOgC0Gsf88fKK3heXv/pmop93+evvO/RZkn7SlFmPhomX3hYOnnhVGH3wuWHb0X8IPbbbN7SvbzSHkySpChrYcIQxTSuo4YAzE73u186+p+i58Seff+OaSSVo3gMvtplniLPm3e+eWwXd0alnKGSyqe+p2q6hW5/hrrmkxDuwxzap+j29c+N9w3UtbTV1DSPsUAQAAEiOHcAAsTgUDCD6ONNLxwFicOcAiDXW9NJxgOi8dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HKN9Y0/52gOjsbwcAAIijXV3DBw4wSUfDxh0faeZ81Y13+Xu1xoOWjj3fYx0AWoVPP/8yZAeMqdg9cbeDJib+mec9+KJDnyW12abMeixMnHJLmHDqlWHUweeEQaOOCd223cc8TZKkKm+7MccZ67SCzr3qvtCh78jErvvA4RPChqamoufH9zzxiusmlaAPPvmqTTxHfKXwhntuFXRQj0GhkMm2iWZ16hPau+aSEm6zunxYXNs5Nb+lCzd+Fte1tNXU5w+3QxEAACA5dgEDxOJQMIDo40wvHQeIwZ0DINZY00vHAaLz0nEA6+cA1s8BrJ8DWD8HAMD83PwcwPwcoHxjTfvbAaKzvx0AACCq9luM+d/t6hqaHWCSjiaccGGkmXNzc3PY96iz/c1aWd8fdgoArcG0P91a0Xvig088k+jn/fCTrx32LCn1XXzdI2HipbeFI86YGcYdMyXs+vvTw1aNR4Ue2+0b2tc3mpNJkpTCho471TiolTR0n4mJXvv5jywqeo686oPPXTOpBD26+NU28RxxQ1NT6DpoT/fdVl7n3IjwUrZjKGSybaLjum3puktKvFO6DUzN7+iKTG3YtC7vupawmlz+ArsUAQAAkmMXMEAsDgUDiD7O9NJxgBjcOQBijTW9dBwgOi8dB7B+DmD9HMD6OYD1cwAAzM/NzwHMzwHKN9a0vx0gOvvbAQAAovpd3+FdHV6Sns6YPDPy7PmjTz4PuSG/93drRX1/kP2XX33j0Q4AFfX9QbgDho2v2P1w4PAJP/w7JOmxZ15z2LOkqu+SWY+HSdPuDseee2PY/4RpYeRBZ4ftxx4XcjseGDbbfDdzLkmS2mD5AycZJ7WSzrzirh+e/yZ17Rv2O6lF8+R5D7zoukkt7Mq5i8K3a9a1ieeJex56hvtuFXRFl/pQyGTbRMs3tlPvHV13SYnWI7drWJrtmJrf0r59dnFdS1muYY5digAAAMmxExggFoeCAUQfZ3rpOEAM7hwAscaaXjoOEJ2XjgNYPwewfg5g/RzA+jkAAObn5ucA5ucA5Rtr2t8OEJ397QAAAFG1r2/Y2eEl6enqm+6KNYN+YtHziR7kqd/u2RdXeLQDQEU98PgzFb0XXnXjXYl+3u/Wrg9X3/K0w54ltdqmzl4QLrjmgTBxyq3hqLOuD/udcHkYc+h5Yei4U8NWjUeGPkP2D9nNx5hPSZKk/9bYwy4wnmpFDd79+ESv//MvF4qeK7/21keumVSCXlixqk08T5xy1Rz33SqoodfgUMhk20wLaruErrldXXtJiXZJl36p+R3dpdcQ17Sk5RfZpQgAAJAcO4EBYnEoGED0caaXjgPE4M4BEGus6aXjANF56TiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OUL6xpv3tANHZ3w4AABBVu/rGCQ4uSU/zH1kUexZ91iXX+du1oube/ahHOwBU1O4Hn16x+2DHgWPDF19+nejnXfrqew55lpRo02YvCBfOfChMmnZ3OOmiOeGoM68P40+aHvY66uIw8qCzwtBxp4ZtRv8h9NvlkNB1m3GhQ32juZIkSSqqfY65xPirFTXx0tsSvf4Hn3hR0XPl5ubmcNM9S1w3qYV9/9/Rxv+cUu/Jp190362COtTlw4LaLqGQybaZZnXOhfauvaQE26LP0LAyJb+h+/bc1jUtYTV1+VV2KQIAACTHTmCAWBwKBhB9nOml4wAxuHMAxBpreuk4QHReOg5g/RzA+jmA9XMA6+cAAJifm58DmJ8DlG+saX87QHT2twMAAERVU5c/1+El6enFZa/FnkWvW7c+7LLXsf5+raTzpt7o0Q4AFfPaG6tC+/rGit0Hjz/risQ/85/ve94hz1KEpsx6NEyccms47LRrwn7HXRb2OPKiMPrgc/9bex81OYw7Zko44MQrwviTp4dDT782HHHGzHDsOTeG48+/OZw8eV6YeOltYdK0u8I5V87f2H3h4use+aFLb3i81X7+abMX/Oe/5//37z3/h89x4oVzwjHn3PDD5/z+837/2ccedkFoGH9WGLbvaWGHPU4MWzUeFfoPOzT03uGA0GnLPcx7JElSYh108gxj2VbWVo1HJnb9N+03Krzz3odFz5eXvvqeayaVoFUffJ76Z4pffb06dOjb6N5bBU3qNiAUMtk21WE9tnbtJSXaTZ17p+L38/juW7qepSyX39C374R/s1MRAAAgGXYDA8TiUDCA6ONMLx0HiMGdAyDWWNNLxwGi89JxAOvnANbPAayfA1g/BwDA/Nz8HMD8HKB8Y0372wGis78dAAAgqpq6hpsdXpKePvrks6Jm0m+8/V7ovNXu/oatoPHHXeDRDgAVM/H8qyt6H1y28u+Jft73PvzC4c7SrzT15qfCUWdeH7Yfe1zo0G9Uor8Hm22+W6gduPsP9dhun43tG3oO3i/0GzrhhwYMPzRs1XjUr7bt6D+EHfY4cWMn/OL/Tb9dDvnP/5/f12fHA3/4Z3XdZu8f/tnZzceYp0iSpKrtiDNmGte2so4998ZEvwNnTrmu6Dnz+g1NYebti103qYU9uHBlm3iuOGTs0e69VdBWvYeGQibbplqWqQ3b9d7Z9ZeUWA29Bqfi9/OCrv1dzxL3730aNrNTEQAAIBl2AwPE4lAwgOjjTC8dB4jBnQMg1ljTS8cBovPScQDr5wDWzwGsnwNYPwcAwPzc/BzA/BygfGNN+9sBorO/HQAAIKp2dQ0LHVySjjIDdgtNTc3Fz6bveczfsRW0w5ijPNoBoCK+/ubb0GWrPSp3yOB+JyX+mR9eVHC4s/QzTZu9IBw56brQe4f9jdElSZKquOPOu8n4thWOtXM7HpjYd6Dr1nuGr75ZXfS8+Zmlb7luUgubMXdhWP3t2tQ/Wzz53Cvde6ukezr2CIVMtk31eG3X0Dk3wvWXlFj3d+xe9b+dMzvnXMsS97s+I7ayUxEAACAZdgQDxOJQMIDo40wvHQeIwZ0DINZY00vHAaLz0nEA6+cA1s8BrJ8DWD8HAMD83PwcwPwcoHxjTfvbAaKzvx0AACCqmrqGdx1cko62HHFwi2fUh5x4kb9lhavdYkxoamr2eAeAxN1wywMVvQfecd+TiX7eNd+tC1fOW+RwZ+knnX7p7aH/sEONzSVJklLQxCm3GuO2wg4+9cpEvwfX3Hx30XPnb9esC1eZO0st7vnlq1L/bPG2+U+491ZJR3TfOhQy2TbXlV3qXH9JiXVQj0FV/7t5d8cermWJq6lvHGunIgAAQDLsCAaIxaFgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA+caa9rcDRGd/OwAAQBTdu4/5X+3q8k0OLklHYyec3uIZ9ZdffRP6Dz3Q37PCvfv+Rx7vAJC4nff8Q8Xufb0H7xPWrl2X6Od9fsUqhzpLP2rqzU+FccdMCR36jTImlyRJSklnT7/HWLeVjr27bTMuse/BgGHjw/oNG4qePz/+7N9cN6mF3XTPktDcnO5ni2+tet+9t0rq1md4eCVTGwqZbJvrgB7b+A5ISqTN6vJhcW3nqv7NXFTbxbUsdfUNx9itCAAAkAw7ggFicSgYQPRxppeOA8TgzgEQa6zppeMA0XnpOID1cwDr5wDWzwGsnwMAYH5ufg5gfg5QvrGm/e0A0dnfDgAAEEX7uhEdHVqSno754+UlmVU/+fSLoX19o79pBVvwzEse7wCQqL8uLVT03nfBFTcl/plvvvevDnWW/tmkaXeHfkMnGItLkiSlrAuvfdB4t5U27phLEv0u3PvwwqLnz59+sdo1k0rQO+9/nvpnjLkh+7n/Vkl/6twnFDLZNtdL2Y5hy947+w5ISqRTum1R1b+Zy7O1YZNc3rUsbRfZrQgAAJAMu4IBYnEoGED0caaXjgPE4M4BEGus6aXjANF56TiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OUL6xpv3tANHZ3w4AABDF73IjdnRgSXqaPGN2yWbWp114jb9pBZs1736PdwBI1DF/vLxi971N+o4Mq/7xUaKf9+1/fOYwZ+mfHXXW9SG7xRjjcEmSpBR2+Y1PGvO20qbMejTRcfiwcce3aB5912PLXDephT3wl5Wpf8Y4/rgL3H+rpN17bh8KmWyb7MHa7iGbG+F7IKns9cztGl7O1lb1b2bvPsNcyxJWU5efbbciAABAMuwKBojFoWAA0ceZXjoOEIM7B0CssaaXjgNE56XjANbPAayfA1g/B7B+DgCA+bn5OYD5OUD5xpr2twNEZ387AABAFO1zDeMdWpKebr79oZLNrNd8tzZsN+pwf9cKdfal13u8A0Bivvjy61Cb4EHeP+3AY89L/DPfv2CFw5zV5pt681Nh5EFnh/b1jcbgkiRJKWzTfqONe1t5oyacneh34q9LC0XPo99Y9YlrJrWwGXMWhm++XZvq54xX3nCne3C1jBPq8uHZbKdQyGTbZJO79vM9kJRIl3TpV9W/l4N77+Q6lrCauvwTdisCAAAkw85ggFgcCgYQfZzppeMAMbhzAMQaa3rpOEB0XjoOYP0cwPo5gPVzAOvnAACYn5ufA5ifA5RvrGl/O0B09rcDAABE0S7XcLZDS9LTE4ueL+ns+uWVr4dN+4/yt61Ah59yscc7ACTm2tn3VPS+t+CZlxL9vKu/XRtmzF3oMGe16SZf93AYmD/c2FuSJCnFdd56L2PfVt55V98fOvQdmdh3YsIJFxY9l25uDuGme5a4blIL++vyVal+zvjXpQX34Crqwi79QyGTbbPt03Nb3wNJZW/LPkPDyir+rdy95/auYwmrqWt4zW5FAACAZNgZDBCLQ8EAoo8zvXQcIAZ3DoBYY00vHQeIzkvHAayfA1g/B7B+DmD9HAAA83PzcwDzc4DyjTXtbweIzv52AACAKGpy+ZscWpKeXv37OyWfYU+deau/bQUadeCpHu8AkIjm5uaw7cjDK3bP22bkYT/8OyTpuWVvO8RZbbpzrpwfeu2wn3G3JElSyvt+zGf82/rbae+TE/tObNJ3ZHjnvQ+Lnk+/uPJd10xqYTfesyQk/CgsUWvXrgvZAWPch6ukIb12DIVMts32QqZjGNBnqO+CpLJ3c6c+VftbeXj3rV3D0vaN3YoAAADJsDsYIBaHggFEH2d66ThADO4cALHGml46DhCdl44DWD8HsH4OYP0cwPo5AADm5+bnAObnAOUba9rfDhCd/e0AAABRtMvl/+LAkvT0zeo1JZ9hNzU1h9HjT/X3TbiBwyd4vANAIhY993JF73l/+vO9iX7e5ubmcMPdzznEWW22iVNuCZ233suYW5IkqQ3Uf9ghxsBV0BlT7wzt6xsT+16ce9msoufUa9dtCNfc+rTrJrWwd97/PNXPGxv3P9l9uIp6uGO3UMhk22x3d+wRNq3L+y5IKmuNPXeo2t/JP3bdwjUscdm+Y/6PHYsAAADlZ3cwQCwOBQOIPs700nGAGNw5AGKNNb10HCA6Lx0HsH4OYP0cwPo5gPVzAADMz83PAczPAco31rS/HSA6+9sBAACiqKnLr3JgSTrqsd3eZZtlv/3uB6Hr1nv6Oyd5iM6AMaG5udkjHgDK7tCTJlfsftd5q93DV1+vTvTzvrHqE4c3q8123Hk3hezmY4y3JUmS2kiDRh1tHFwlfX+tkvpedN927/Dtmu+Knlc/ueR110xqYQ8tKqT6eeM5l81yH66iTug+MBQy2TbdpG4DfBcklbX2G3uwY7eq/I2c2qXeNSxx/5HLd7djEQAAoPzsDgaIxaFgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA+caa9rcDRGd/OwAAwG/p3n3M/2pXl29yYEk62mmPY8o6055z1yP+zgn36edfesQDQFl9f6/JDNitYve6k86ZkfhnvueJVxzerDbZYaddEzr0HWmcLUmS1IYasseJxsJV0nHn3ZTod+PPdz5S9Lz686++DdPnuGZSS7py7sKw5rt1qX3m+MDjz7gPV1H1fXYJKzPZUGjDrcjUhl17DfF9kFTWJvQYVJW/kbM79Xb9SlxNLj/ErkUAAIDys0MYIBaHggFEH2d66ThADO4cALHGml46DhCdl44DWD8HsH4OYP0cwPo5AADm5+bnAObnAOUba9rfDhCd/e0AAAC/pUPfxlqHlaSn/Y4+p+yz7e//Gf7WybX81Tc94gGgrKZff3tF73UrXkv2XvfVN9+F6XMWOrxZba4DT5wW2tc3GmNLkiS1sYb9/jTj4SqqfueDEvtu7LTHMS2aX9/zxCuumdTClr76XmqfOX786Rfuw1XWbR17hkIm26b7S7ZL6Jrb1fdBUtnarC4fFmc7V93v40Mdu7t+pS6X39euRQAAgPKzQxggFoeCAUQfZ3rpOEAM7hwAscaaXjoOEJ2XjgNYPwewfg5g/RzA+jkAAObn5ucA5ucA5Rtr2t8OEJ397QAAAL+lpq5hB4eVpKeJ519d9tn2hx9/Frpvu7e/d0I9umCJRzwAlE1TU3MYOHxCxe5zI/c/OfHP/PRLbzq0WW2uff5waWhf32h8LUmS1AYbdfA5xsRV1KGnXZ3o9+PZF1cUPb9+673PXDOphc25/4VUP3vcKn+Ie3EVdWiPrUMhk23zXdO5zvdBUlk7tdsWVffb+Hy2k2tX6nIjTrFrEQAAoPzsEgaIxaFgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA+caa9rcDRGd/OwAAwG+pqcsf4LCS9DT9+tsTmXHfNv8Jf++Euvn2hzziAaBsnnz6hYre5+56cEGin3dDU3O47o5nHNqsNtUeR1xkXC1JktSG2/uoycbFVdTUm58KXQbtndj349CTJrdonn3z/L+6blIL+/DTr1P77PHo0y9zL66iuuZ2Da9kakMhk23z/b7HNr4TkspWz42/ty9nq+/3tmPdCNevlOUaptm1CAAAUH52CQPE4lAwgOjjTC8dB4jBnQMg1ljTS8cBovPScQDr5wDWz+kold8AACAASURBVAGsnwNYPwcAwPzc/BzA/BygfGNN+9sBorO/HQAA4Le0q8uf5bCS9HTnAwsSm3Xvf8y5/uYJdOk18zziAaBsDjz2vIrd43JD9gvr1q1P9PO+9vbHDmtWm2rsYRcYU0uSJLXxxp803di4ytrrqMmJfT827T8qfPDRp0XPs5e++p5rJrWwJ577W2qfPV4/7z734irr+s65UMhk23zPZzuFvn128Z2QVLYu69K36n4bB/QZ6tqVsJpcwx12LQIAAJSfXcIAsTgUDCD6ONNLxwFicOcAiDXW9NJxgOi8dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HKN9Y0/52gOjsbwcAAPgtNbn8jQ4rSU/PvrgisVn3hx9/Fnpst7e/e5mbdPGfPOIBoCze//CTsGm/URW7x100fXbin/nOR192WLPaTHseeZHxtCRJksJRZ15nfFxlXfSnh8Om/Ucn9h2ZPKP4+fm6dRvCNbcudt2kFvT9f0PrNzSl8vnji8tecy+ussb12C4UMllt7LaOPcMmubzvhaSytFWfncPKKvtd3KXXDq5dCavJNTxj1yIAAED52SkMEItDwQCijzO9dBwgBncOgFhjTS8dB4jOS8cBrJ8DWD8HsH4OYP0cAADzc/NzAPNzgPKNNe1vB4jO/nYAAIDf0i6XX+CwkvT03gcfJzrzvuO+J/3dy9yxZ0z1iAeAsphy1ZyK3d869G0Mq/7xUaKf97Mvv3VQs9pMvz/uMmNpSZIk/dBJF80xRq7Chv3+tMS+I70H7xPWrl1X9Hz7L8//3TWTWljhjQ9T+fxx3br1ITNgN/fjKiqTy4fns51CIZPVxk7sNtD3QlLZmt2pd1X9Jo7rsZ3rVspy+XfsWgQAACg/O4UBYnEoGED0caaXjgPE4M4BEGus6aXjANF56TiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OUL6xpv3tANHZ3w4AAPBbvj+kw2El6WjTfqPC+g0bEp99jz/uAn//Mnbgsed7xANAyW1oagoDho2v2P1tv6PPSfwzO+RbbaX9j59qHC1JkqT/bNK0u42Tq7BJU+8M7esbE/ue3HHfk0XPt7/4ek2YPsc1k1rSHY++nNrnkMPGHe9+XGVN7VIfCpmsNrZ8Y0N67eh7Iaksjeo1uKp+E4/svrXrVspyDev/ZcyYf7VzEQAAoLzsFgaIxaFgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA+caa9rcDRGd/OwAAwK/p23fCv7XL5Tc4rCQdbb7L+IrMvj/65LPQY7u9XYMytdtBEz3iAaDkHnry2Yre3x5ZsCTRz7t+Q1OYedtihzQr9R144rTQvr7ROFqSJEn/2YUzHzJWrtK2ajwyse/J8H1OaNG8e/5Ty10zqYV99uW3qXwOeer5V7kfV1n5XjuEQiarf/Z4bdfQKTfCd0NSyWu/sYc6dq+a38Mzug5w3Urcpv2H/YfdiwAAAOVltzBALA4FA4g+zvTScYAY3DkAYo01vXQcIDovHQewfg5g/RzA+jmA9XMAAMzPzc8BzM8ByjfWtL8dIDr72wEAAH7NJv1GZR1Skp5G7n9yxWbgd9z3pGtQpnba4xiPeAAouXFHnFmxe9vmu4wPG5qaEv28K//+gcOZlfoOPf3a0L6+0RhakiRJ//8h7RvHh1NnLzBertKOPntWot+Xl155reh59zvvf+6aSS3s6ZfeTOcu3nsec0+usjrU5cPC2s6hkMnqn03p0s93Q1JZOrj7oKr5Lby0S1/XrMT9ru/wersXAQAAystuYYBYHAoGEH2c6aXjADG4cwDEGmt66ThAjP+5gjsHgPVzAOvnANbPAayfAwBgfm5+DmB+DlC2sab97QDR2d8OAADwa9rVjxjskJL0dPipUyo6Cx9/3AWuQxkaMGy8RzwAlNS7738UNuk7smL3tstnJr/eeetDLzmcWanu+PNvDpv0H2X8LEmSpP9Sx4F7GC9XcdNmLwi9d9g/se/L0adf1qK595z7X3DdpBZ0/Z3Phubm5tQ9i3z17++4J1dh53TdPBQyWf2ovXpu57shqeRlcyPCs9lOVfE7eEOnPq5Ziaupaxhh9yIAAEB52TEMEItDwQCijzO9dBwgBncOgFhjTS8dB4jOS8cBrJ8DWD8HsH4OYP0cAADzc/NzAPNzgPKNNe1vB4jO/nYAAIBfU1OX398hJenp3MtvqOgs/KNPPgs9txvnWpS4roP29IgHgJI6f9pNFbuvbdp/VPjw488S/bwff/6Ng5mV6k6ePC9stvluxs6SJEn6b/XaYT9j5ipvv+MuT+z7khmwW/j40y+Knn8ve+0frpnUwt55//PUPYtsamoOXbfe0325ytq+906hkMnqRz2b7RR69xnm+yGp5J3ebYuq+B28t1N316v0HWz3IgAAQHnZMQwQi0PBAKKPM710HCAGdw6AWGNNLx0HiM5LxwGsnwNYPwewfg5g/RwAAPNz83MA83OA8o017W8HiM7+dgAAgF/Trq7hTAeUpKfr591X8Zn4vLsfcy1KXPv6xrChqcljHgBKYt269SE3ZL+K3dcmnHBh4p/5ief+5lBmpbYzLr8z1A7c3bhZkiRJP9uA4YcaN1d5U2Y9FrIDxib2nbl8ZvF7lNdvaAozb1vsukkt6OFFhVQ+kxwz4TT35SrswY7dQiGT1Y+a3al3aO+7IanE9e4zLCzP1Lb638BFtV1cr9I3ye5FAACA8rJrGCDesp47B0DkcaaXjgPE4M4BEGus6aXjANF56TiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OUL6xpv3tANHZ3w4AAPBrauoabnBASXp6+KnnKj4Tb25uDrsffLrrUeK+/Oobj3kAKIl7H15Y0XvagmdeSvTzrlu3IVx969MOZVYqO+fK+aHLoL2NlyVJkvSLbbfbscbOKahx/FmJfWf6DT0grN+woeh5+MIX3nDNpBZ01bxFYe269al7JnnuZbPcl6uwk7sNDIVMVj/pyO5b+35IKnlXdalv9b9/yzfWoS7vepWyXMOVdi8CAACUl13DALE4FAwg+jjTS8cBYnDnAIg11vTScYDovHQcwPo5gPVzAOvnANbPAQAwPzc/BzA/ByjfWNP+doDo7G8HAAD4NTV1+ScdUpKeXim80Spm42++849Qu8UY16SEffzpFx7zAFASYyecXrH72dYNh4bm5uZEP++y1/7hQGalsov+9HDoOXg/Y2VJkiT9arvsM9H4OQWdM+Pe0L6+MbHvzfxHFhU9D//i6zVh+hzXTGpJy19/P3XPJL//XXFfrr769d4lrMxkQ0H/pZeztWHL3jv7jkgqaUN7DamK38CeuV1drxJWk2u4w+5FAACA8rJrGCAWh4IBRB9neuk4QAzuHACxxppeOg4QnZeOA1g/B7B+DmD9HMD6OQAA5ufm5wDm5wDlG2va3w4Qnf3tAAAAv6ZdLv+WQ0rS0xdfft1qZuTT/nSra1LCPvjoU495AGixt1a9n+gh3D/tqhvvSvwzz3vgRYcxK3VdduMTYcDwQ42TJUmS9JuNPvhcY+iUtP2Y4xL73uxxyB9bNBe/+/FlrpnUgm5/ZGnqnku++/5H7stV2p2deoZCJqufdG+n7mGTurzviKSSdk/HHq3+929Q751dq5KWX2T3IgAAQHnZOQwQi0PBAKKPM710HCAGdw6AWGNNLx0HiM5LxwGsnwNYPwewfg5g/RwAAPNz83MA83OA8o017W8HiM7+dgAAgF+07bb/s12uYb0DStJR5612b1Uz8vXrN4QhY492bUrUO+996DEPAC127mWzKnYvyw4YEz79/MtEP+/7H3/pIGalrmmzF4TBux9vjCxJkqRIjTvmEuPolHTCBbMT+960r28Mb7z9XtHz8dff+dg1k1rY519+m7pnk7khv3dvrsKO7r5VKGSy+plO7DbQd0RSSRvfY5tW/9vX0Guwa1XCanINf7OBEQAAoLzsHAaIxaFgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA+caa9rcDRGd/OwAAwC/5994jMg4oSU/b73Zkq5uVv/TKa2GTviNdnxLUkgNMAeB76zdsCHU77lexe9lRp12a+Gd+ZPGrDmFW6mocf5bxsSRJkiJ30CkzjKNTVN3O4xP77pxz2ayi5+NNzc3h+jufdc2kFvTMy2+l7vnkuCPOdG+uwnr1GRaWZ2tDIZPVT1qeqQ3b997J90RSydqsLh8WZzu36t++/Xts61qVslzDV3YwAgAAlJfdwwCxOBQMIPo400vHAWJw5wCINdb00nGA6Lx0HMD6OYD1cwDr5wDWzwEAMD83PwcwPwco31jT/naA6OxvBwAA+CXt+jRs54CS9LTXYZNa5cz89IuudX1K0Kuvv+0xDwAtct+jT1f0XvbsiysS/bzfrV0frpq3yCHMSlX7HXeZsbEkSZJidfRZ1xtLp6iDTp6R2Hen9+B9wtq164qelz+z9C3XTGpBN9z9XGhuTtfzyYumz3ZvrtJu6dQ7FDJZ/Uz3dewRNq3L+55IKlmTug1o1b97x3bfynUqce23GPO/7WIEAAAoH7uHAWJxKBhA9HGml44DxODOARBrrOml4wDReek4gPVzAOvnANbPAayfAwBgfm5+DmB+DlC+sab97QDR2d8OAADwS2rq8vs7nCQ9nXj29FY5M1/97ZowcPgE16iFvVJ4w2MeAFpkr8MmVew+tv3oIxL/vC+ufNcBzEpVR589K3SobzQ2liRJUqxOnjzPeDpFXXbjE6F2y90T+/7c+cCCouflX6/+Lkyfs9B1k1rQux98karnkw88vti9uUo7pPugUMhk9QtN7LaF74mkklXXZ1hY3op/887uOsB1KnH/3qdhM7sYAQAAysfuYYBYHAoGEH2c6aXjADG4cwDEGmt66ThAdF46DmD9HMD6OYD1cwDr5wAAmJ+bnwOYnwOUb6xpfztAdPa3AwAA/JJ2dQ2THE6Sni69Zl6rnZ0/smCJa9TCXlz2msc8ABRt1T8+Ch36NlbsPnbd3PmJf+Y/3/e8w5eVmiZOuSVs2n+0cbEkSZJid+YVdxtTp6yRB52V2Pdn9PhTWzQ3v/fJ5a6Z1IIeXfxq6p5RujdXZ91zw8PyTG0oZLL6mZZvbHDvnXxXJJWsmV1yrfY3b3rneteo1PXND7CLEQAAoHzsIAaIxaFgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA+caa9rcDRGd/OwAAwC9pV9cwy+Ek6enWex9v1TP0g0+8yHVqQUteWukxDwBFmzxjdsXuYR0Hjg1ffvVNop931QefO3hZqemCax4IXbfZ25hYkiRJRXXxnx4xrk5ZZ8+4J7Svb0zsO/Tq628XPT9/891PXTOpBV19y9Nh3foNqXpO2XvwPu7PVdpNnXuHQiarX+ihjt1DJpf3XZFUknbtNaTV/t7N7tTbNSpxNXUNI+xiBAAAKB87iAFicSgYQPRxppeOA8TgzgEQa6zppeMA0XnpOID1cwDr5wDWzwGsnwMAYH5ufg5gfg5QvrGm/e0A0dnfDgAA8Etq6vJPOJwkPS167uVWPUP/6JPPQrdt9nKtiuzpJcs85gGgKBuamkK/oQdU7B52/FlXJP6ZH1y40sHLSkWX3vB4qB96kPGwJEmSiqpDfWOYNnuBsXUKGzTq6MS+R2dMnln0/Ly5OYQb7n7ONZNa0KtvfpSqZ5V7HXaGe3SVdkCPbUIhk9WvNKnbAN8VSSXr/o7dW+Vv3fyOPVyfEtc+1zDeLkYAAIDysYsYIBaHggFEH2d66ThADO4cALHGml46DhCdl44DWD8HsH4OYP0cwPo5AADm5+bnAObnAOUba9rfDhCd/e0AAAC/pF1d/k2Hk6Snt9/9oNXP0q+bO9+1KrJnXljuMQ8ARXlkwZKK3sOWrng90c+7es3aMGPuQocuq+qbNntBGLLHicbCkiRJKrrOW+1pbJ3Sjjrr+sS+R9222St8u+a7oufpS5a945pJLejeJ15J1bPK86fd5B5dreOK3IiwNNsxFDJZ/UIrMrVhl15DfF8klaSDuw9qlb91C2s7uz4lrqYuP9EuRgAAgPKxixggFoeCAUQfZ3rpOEAM7hwAscaaXjoOEJ2XjgNYPwewfg5g/RzA+jkAAObn5ucA5ucA5Rtr2t8OEJ397QAAAD9r223/Z7tcw3qHk6SjDn0bw9q161r9LH1DU1PYec8/uGZF9MKyVz3mAaAo+x9zbsXuX7vsfVzin3fJKw7rVjra7ZDzjIMlSZLUovoM2d/YOqVNnb0gdNt2n8S+S7fe+3jR8/TVa9aGGXMXum5Skc2Ys/CH/47SYv4ji9yjq7iZXXKhkMnqV3qiY9fQsW6E74ukFpfNjQhLsp1b3e/cK5na0N71KWk1dQ2X28gIAABQPnYRA8TiUDCA6ONMLx0HiMGdAyDWWNNLxwGi89JxAOvnANbPAayfA1g/BwDA/Nz8HMD8HKB8Y0372wGis78dAADg5/xH3ahNHUySnup23K9qZup/XVoI7esbXbeYvVJ4w2MeAGL74KNPw6b9RlXs/vXnOx5O9PM2N4dww91LHLisqu/giVcZA0uSJKnFbTH8MOPrFLfXURcn9l1q2O+kFs3X7//LCtdMakEvFd5LzfPKt9/9wD26ihvXY7tQyGT1G53Xtb/vi6SSdE7XzVvl71zn3HDXp5Tl8nPtZAQAACgfO4kBYnEoGED0caaXjgPE4M4BEGus6aXjANF56TiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OUL6xpv3tANHZ3w4AAPBz2ucat3UwSXoase+JVTVbP/aMqa5bzF57Y5XHPADEdvnMWyp27+q69Z7hm9VrEv28b733qYOWVfWdNHlu2KT/KGNgSZIktbjBux9vjJ3iLpz5UOjQL7m5w4rX3ix6vv7O+5+7ZlILuuXBF1PzvLK5uTl033Zv9+kqLZsbEV7MdAyFTFa/0opMbRjWa4jvjKQW17fPLmF5trbV/c713/jv5fqUrpq6/BN2MgIAAJSPncQAsTgUDCD6ONNLxwFicOcAiDXW9NJxgOi8dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HKN9Y0/52gOjsbwcAAPg5NbkRv3cwSXo69KTJVTVb//jTLxyYF7O33/3AYx4AYvn+gNotRxxcsXvXSefMSPwzz39quYOWVdVdcM0Docsg42RJkiSVpvyBk4yzU96Oe5+c2Pdp4vlXt2jOfvO9f3XNpBb0+Zffpua55e4Hn+4+XcXN6FwfCpmsfqMna7uGTrkRvjOSWtysTn1a3W/cTr13dG1K23I7GQEAAMrHbmKAWBwKBhB9nOml4wAxuHMAxBpreuk4QHReOg5g/RzA+jmA9XMA6+cAAJifm58DmJ8DlG+saX87QHT2twMAAPycmlz+DIeSpKdzL5tVdTP26+bOd+1i9I8PPvGYB4BYnlr8YkXvXUtXvJ7o5/169Xdh+pyFDllW1XbZTU+EfrscYuwrSZKkkrXXURcba6e8kyfPTez71HXQnmH1t2uKnrc/v2KVaya1oGdffjs1zy2/X9d0n67exvTcPhQyWUVoctd+vjOSWlxDz8Gt7vdt7MZ/J9emhOXyn9jJCAAAUD52EwPE4lAwgOjjTC8dB4jBnQMg1ljTS8cBovPScQDr5wDWzwGsnwNYPwcAwPzc/BzA/BygfGNN+9sBorO/HQAA4Oe0yzVc52CS9HTd3PlVN2Pf0NQUdt7zD65fxD7+9AuPeQCI5eATL6rYfev7e3zSnln6lgOWVdXtPO4U415JkiSVtINOmWGs3Qaq23l8Yt+pP9/5SNHz9jXfrQtXzl3kmklFdtM9S1Lz3PKuBxe4T1dxm9Xlw1+znUIhk9VvtHJj+V47+N5IalHtN/Zwx26t6vftoB6DXJvS1ty374R/s5sRAACgPOwmBojFoWAA0ceZXjoOEIM7B0CssaaXjgNE56XjANbPAayfA1g/B7B+DgCA+bn5OYD5OUD5xpr2twNEZ387AADAz6mpa3jcoSTp6ZEF1XmQ3pKXVob29Y2uYYS++ma1xzwARPbp51+GzIDdKnbfuuGWBxL9vE3NzeH6O591wLKqtn2PvdSYV5IkSSXv2HNuNN5uA40/eXpi36lh445v0fz9oUUF10xqQe9//FUqnl2+9sYq9+kq77IufUMhk1WEnujYNdTmRvjeSGpRh3ffulX9tp3QfaDrUuI61OVr7GYEAAAoDzuKAWJxKBhA9HGml44DxODOARBrrOml4wDReek4gPVzAOvnANbPAayfAwBgfm5+DmB+DlC+sab97QDR2d8OAADwc9rVNbzhUJL0tOK1N6t25n7sGVNdwwit+W6txzwARHblDXdW7J7VceDY8NXXqxP9vK+/87GDlVW1HX/+zaFD35HGvJIkSSp5p116mzF3G+jSGx4P2S3GJva9ennl60XP39/78AvXTGpBTy15PRXPLjc0NYXaLca4V1dxI3sODoVMVhE7p+vmvjeSWlSn3IjwfLZjq/ldO7eb37VSV9M7X2c3IwAAQHnYUQwQi0PBAKKPM710HCAGdw6AWGNNLx0HiM5LxwGsnwNYPwewfg5g/RwAAPNz83MA83OA8o017W8HiM7+dgAAgP9mzJh/rcnl1zmUJD19+dU3VTtz//jTL0K3bfZyHX+lDn0bQ1NTs8c8AETS3Nwcthl5WMXuW3844/LEP/Pdjy9zsLKqsnOunB86DtzDmFeSJEll6YJrHzTubiM1jD8zse/VKedd2aI5/J/ve941k4ps5m2Lw4aUrBcNG3e8e3UVt0ldPizJdg6FTFYRWpGpDTv13tF3R1LL5ndd+7ea37XpnetdkxLXvr5hZxsaAQAAysOuYoBYHAoGEH2c6aXjADG4cwDEGmt66ThAdF46DmD9HMD6OYD1cwDr5wAAmJ+bnwOYnwOUb6xpfztAdPa3AwAA/NTv+g7fxIEk6anroD2rfvZ+3dz5ruWv1GO7vT3iASCyZ55/paL3rSUvrUz0837+1bcOVVZVdukNj4e6ncYb70qSJKksdahvDFNnLzD2biOdecVdof3Ga57Ed6vbNnuFNd+tLXoe/1LhPddMakFvvfdpKp5hHn/WFe7XVd7lXfqGQiariD3csVvYrC7vuyOp6Dbvs0tYkaltFb9pN3fq45qUulx+XzsaAQAAysOuYoBYHAoGEH2c6aXjADG4cwDEGmt66ThAdF46DmD9HMD6OYD1cwDr5wAAmJ+bnwOYnwOUb6xpfztAdPa3AwAA/FT7uvw2DiRJT0PGHl31s/cNTU1hhzFHuZ6/0NYNh3rEA0BkR068pGL3rO1HH5H45130whsOVFZVtuOeJxnrSpIkqWx13nov4+421sD84Yl9v+6478mi5/HfrV0frpq3yDWTiuyRp19NxTPM6+bOd7+u8kb1GhwKmaxidEq3gb47klrUzZ36tIrfs3s7dnc9SlxNn/wJdjQCAACUh13FALE4FAwg+jjTS8cBYnDnAIg11vTScYDovHQcwPo5gPVzAOvnANbPAQAwPzc/BzA/ByjfWNP+doDo7G8HAAD4qXa5/L4OJElP+x19Tipm8AufW+p6/kIj9j3RIx4AIvnyq29Cx4FjK3bPunb2PYl+3g0bmsLM259xoLKqrn2Pvcw4V5IkSWWtfuhBxt5trENPuzqx79fuB5/eovn8I4tfdc2kIrv61qfD+g1NVf8c85kXlrtfV3mb1OXDkmznUMhkFbFXMrVhyz5DfX8kFd3ontu3it+zhbWdXY9Sl8tfaEcjAABAedhZDBCLQ8EAoo8zvXQcIAZ3DoBYY00vHQeIzkvHAayfA1g/B7B+DmD9HAAA83PzcwDzc4DyjTXtbweIzv52AACAn6rJ5f/oQJL0NPH8q1Mzix93xJmu6c+071Fne8QDQCR/+vO9Fbtfbbb56PDJZ18m+nkLb37oMGVVXadcPC906DfKOFeSJEllbZvRfzD+bmNdfuOTodOWeyTy/Wpf3xjeWvV+0fP5dz/4wjWTWtDr73xc9c8xv/pm9Q+/Je7Z1d3ULvWhkMkqRnd26hk2yeV9fyQVVYe6fHiiY9eK/5Yty9S6HqUu1/AnOxoBAADKw85igFgcCgYQfZzppeMAMbhzAMQaa3rpOEB0XjoOYP0cwPo5gPVzAOvnAACYn5ufA5ifA5RvrGl/O0B09rcDAAD81PcHcTiQJD3NmHVHambxr72xKmzab5Tr+pOOOu1Sj3gAiGTH3Y+u2P3q8FMuTvzz3v7IUgcpq6q68NoHQ5dBexvjSpIkqewN2/c0Y/A2WMP4sxL7jk25ak6L5vQ33bPENZOK7MGFK1PxLHPg8Anu2VXe6F6DQyGTVcyO7L6174+kojum+1at4resY90I16O03WVHIwAAQHnYWQwQi0PBAKKPM710HCAGdw6AWGNNLx0HiM5LxwGsnwNYPwewfg5g/RwAAPNz83MA83OA8o017W8HiM7+dgAAgJ+qyTU85jCS9HTPwwtTNZM/+dwrXdefdMbkmR7xAPCbnn+5UNH71aLnXk708376xWqHKKuqmnrzU2GLEYcb30qSJCmRxhx6vnF4G2zStLsT+471G3pA2NDUVPS8/rllb7tmUpFdOW9RWLtuQ9U/zzzw2PPcs6u8Tery4a/ZTqGQySpGS7MdQ7/eu/gOSSqqLrnh4aWNvyOV/i2r6zPM9Shlufxf7GgEAAAoD7uLAWJxKBhA9HGml44DxODOARBrrOml4wDReek4gPVzAOvnANbPAayfAwBgfm5+DmB+DlC+sab97QDR2d8OAADwUzW5/N8dSJKenn+5kKqZ/CeffRm6DtrTtf1Rl14zzyMeAH7TcZOmVexeNXD4hNDc3Jzo531qRTxXXAAAIABJREFUyesOUVZV1TD+LGNbSZIkJdZ+J1xuHN5GGzD80MS+Z08tfrHoef3Xq78L0+csdM2kInv1zY+q/nnmlKvmuGenoKld6kMhk1XM5nTqFdr7/kgqsou79qv479h2vXd2LUpZLr/CjkYAAIDysLsYIBaHggFEH2d66ThADO4cALHGml46DhCdl44DWD8HsH4OYP0cwPo5AADm5+bnAObnAOUba9rfDhCd/e0AAAD/xZgx/1qTy69zIEl6+vDjz1I3m7/iuttc2x81a979HvEA8Ku+Wb0mdNlqj4rdq6Zff3uin3f9hqZw7W2LHaCsqumwP15rXCtJkqREO+KMPxmLt9EmnHpVYt+zw06+uEXz+7seW+aaSUU2/6nlVf9M84HHF7tnp6DRPbcPhUxWRbR/j219hyQV1ZZ9hoaVFf4NG9FrB9eipOU/tKkRAACgPOwwBojFoWAA0ceZXjoOEIM7B0CssaaXjgNE56XjANbPAayfA1g/B7B+DgCA+bn5OYD5OUD5xpr2twNEZ387AADAj9X0a+jgIJL0lBmwW2hqak7dbP67tWvDgGHjXeN/dteDCzziAeBX3Xz7QxW7T23af1T46JPPEv28y19/3+HJqpomTb0zbLb5bsa1kiRJSrSTJs81Hm+jXXrD4yG7xdhEvmfZAWPC5198XfT8/tU3P3LNpCKbMXdhWLN2fVU/03z73Q/cs1PQpnX58Ndsp1DIZBWzJdnOoWduV98jSUU1t1Oviv6G7d1jW9ehlOUa1v/Lv/zL/7CzEQAAoPTsMAaIxaFgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA+caa9rcDRGd/OwAAwI/9rm/j1g4jSU9b5Q9J7Yz+zgcWuMb/7OklyzziAeBXDd/nhIrdp8Yfd0Hin3fegy86PFlV0SWzHg99huxvTCtJkqTEO3vGPcbkbbj8AZMS+65dN2d+0fP7DRuawrW3LXbNpCJb/voHVf1Ms7m5OXTZag/37RQ0rUvfUMhkVURXdan3HZJUVHv32Laiv1+HdB/kOpS4Tfs0/D92NgIAAJSeHcYAsTgUDCD6ONNLxwFicOcAiDXW9NJxgOi8dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HKN9Y0/52gOjsbwcAAPixdnUN+ziIJD3tfvDpqZ3Rf3+QXuP+J7vOG3vnvQ894gHgFxX+9nZF71NPPv1Cop/3w0++dmiyqqah4041npUkSVJFuvSGx43J23B/vPyOxL5rQ8Ye3aJ5/hPP/c01k4rs7seXVf2zzeH7nOC+nYLG9Nw+FDJZFdnuPbb3PZIUu03q8mFRbZeK/Xad2G2g61DiOvRtrLWzEQAAoPTsMgaIxaFgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA+caa9rcDRGd/OwAAwI/V5BpOdxBJejr2jKmpntU//3IhtK9vbNsHIfUdGdav3+ARDwC/6IzJMyt2n+o/9MCwoakp0c/72DOvOTRZVdH4k6ebs0iSJKkiZQeMNSZX6LfLIYl955at/HvR8/wPPvnK9ZKKbPqchWH1mnVV/Wzz+DOnuXenoM3q8uH5bKdQyGRVRE/XdgldcsN9lyTF7vRuW1Tst+vsrpu7BiWufZ/Gze1sBAAAKD27jAFicSgYQPRxppeOA8TgzgEQa6zppeMA0XnpOID1cwDr5wDWzwGsnwMAYH5ufg5gfg5QvrGm/e0A0dnfDgAA8GPt6vIzHUSSnqZcNSf1M/uDT7yoTV/j/kMP9HgHgF+0bt360HvwPhW7T11y9dxEP+/ajZ/36luedmiyWn2nX3Z72LTfaHMWSZIkVaSeg/czLlc46OQZiX3nTrvgmhbN9+fc/4JrJhXZstf+UdXPN2fOvse9OyVN71wfCpmsiuzCLv19jyTFrq7PsLA8W1uR362pXepdg1KXa9zFzkYAAIDSs9MYIBaHggFEH2d66ThADO4cALHGml46DhCdl44DWD8HsH4OYP0cwPo5AADm5+bnAObnAOUba9rfDhCd/e0AAAA/1i6Xf9RBJOlp3t2PpX5m/8bb74VN+41qs9d41AGneLwDwC+a/8iiit2jNuk7Mrz7/keJft6lr77nsGS1+i6Z9XjovcMB5iuSJEmqWAPzhxub64e5SXbA2ES+cz222zt8t3Zt0fP9F1ascs2kIrvrsWVV/XxzwTMvuXenpLE9B4dCJqsiW5GpDTv03tF3SVLsZnXOVeR36/qN/1x//1I3YpydjQAAAKVnpzFALA4FA4g+zvTScYAY3DkAYo01vXQcIDovHQewfg5g/RzA+jmA9XMAAMzPzc8BzM8ByjfWtL8dIDr72wEAAH6sJtfwN4eQpKeFzy1tE7P7P5xxeZu9xkdOvMTjHQB+0d6Hn1mxe9Tvjzo78c/75/ued1iyWn077X2KuYokSZIq2pA9TzI21w/t+vvTE/ve3f3QX4qe769esy7MmLvQNZOKaPqcheHbjf8NVauPPvncvTslbVaXDy9kOoZCJqsiu79j97CJ75KkmI3uNbgiv1m3d+zp71/q6huOsbMRAACg9Ow0BojFoWAA0ceZXjoOEIM7B/B/2bvvKCuqhOHX87333nXX+9217lr3/vN+NqCe0+TUpwmCioqKAYFuogETjoFRHHXMCuoYx6wDKgYMqAxiBjMqCmICIwq0WQcjIhJFQve+yHrHO45hqrrr1Dl9zvOs9fvfripO7V17W0WssaaXjgNE56XjANbPAayfA1g/B7B+DgCA+bn5OYD5OUD+xpr2twNEZ387AADA/++c/6iorv3eh0hKp4+XfFEWs/slny8N2243rCzP8SXX3OnxDgC/6IuvloWtuw8p2D3qiWdfTvXv/eyrFT6UrKLvsJPHm6dIkiSp4A0+4jzjc21p3JX3pHbdjTzmnCbN+x+evdA5kxrZ2+817/XCrrsd7P5dIt3QtjrUZbJqQsd27ONakhSrVtU14ZnK9qn/Xs1s3cHxT7pc7fn2NgIAACTPbmOAWHwUDCD6ONNLxwFicOcAiDXW9NJxgOi8dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HyN9Y0/52gOjsbwcAAPiHllUDWvgISQl9GKf74LB+/YaymeGf+Zfry/I8T7nvCY93APhFV980rWD3p257HhY2btqU6t878/k6H0lW0X+sfuueQ81VJEmSVPAOOuEKY3T9WPVeR6S2ZvHZl183et7/wZJlzpfUyKbPeqtZP+cccdQ49+8S6eDOu4S6TFZN6LVM61BVNcD1JClWJ3fcIfXfq5eybR37xKu5zu5GAACA5NltDBBv6c6dAyDyONNLxwFicOcAiDXW9NJxgOi8dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HyN9Y0/52gOjsbwcAAPiHrboP7uMDJKVTtz0PK6sZ/ldfLw+tt9+37M7z7Bdf93gHgJ9paGgIOwwaXbD70yXX3Jnq37vu+w1h4rTnfSRZRduVt80KXXYfZZ4iSZKkouiYcTcap+vHDj3p6tSuvWtvva/Rc//6hoZwy/0vOWdSI7pu6tzw3fcbmu2zznGX3Oj+XSK1yQ0KC7KVoS6TVRO6vl0315OkWHXKDQhvZdL9/V24uZaOfbLlaqbZ3QgAAJA8O44BYvFRMIDo40wvHQeIwZ0DINZY00vHAaLz0nEA6+cA1s8BrJ8DWD8HAMD83PwcwPwcIH9jTfvbAaKzvx0AAOAfWlbVHOgjJKXToENOLbtZ/nlX3lJ25/mDjz/zeAeAn3l+3oKC3ZtadR8cPvn0y1T/3lcXLfGBZBV1exx4ujmKJEmSiqbTLp1qnK4fu3TSzNCqx9BUrr1dh/+xSfP/51790DmTGtnC979sts8677zvCffvEmpym6pQl8mqiQ3rspvrSVKsJrarTv23qm1uoGOfZLmap+xuBAAASJ4dxwCx+CgYQPRxppeOA8TgzgEQa6zppeMA0XnpOID1cwDr5wDWzwGsnwMAYH5ufg5gfg6Qv7Gm/e0A0dnfDgAA8A8V1TVjfYSkdDr6tMvKbpb/zbcrQ7sd9y+bc7xNz6Fhw4aNHu8A8DPHjr2yYPenA44+J/W/986HXvFxZBVtR515vfmJJEmSiqoLJj5irK6ftOu+J6d2/S1Y/H7j1wBWrHW+pEb20DNvN9tnnfPfWOz+XUId2WmnUJfJqonNqmwfsrlBrilJkevfZffUf6t6dO3v2Cdazet2NwIAACTPjmOAWHwUDCD6ONNLxwFicOcAiDXW9NJxgOi8dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HyN9Y0/52gOjsbwcAAPiHiuraG32ApHS68OrbynKmf+m1U8rmHO8+4jiPdgD4mVWr14bW2+9bsPvTQzPnpvr3fvL5ch9GVtF2wXUPhex2I8xPJEmSVDS17DY4jL/jWeN1/aTjz7s1tWvwnMsmNek5wLTHX3fOpEZ03V1zw7r1G5vl887Va77bcv9yHy+NOuYGhoWZbKhTkxvbobdrSlKsnqjskOrvVN8ueznuSZar+bvdjQAAAMmz6xggFh8FA4g+zvTScYAY3DkAYo01vXQcIDovHQewfg5g/RzA+jmA9XMAAMzPzc8BzM8B8jfWtL8dIDr72wEAAP6hRXXtTB8hKZ1unfZIWc70V65aEzrucmBZnOMxZ1zu0Q4APzP57scKdm/qutvBYcOGdD/O++icRT6MrKJs/B3Phh57H2VuIkmSpKKqXZ+Rxuv6+fzlztmh7eZrI41rMNfv0LBx06ZGPwdY8O7nzpnUyBZ/8GWzfebZa58j3MdLqLvbdA11maya2NuZyrBD171cU5Iid2zHPqn+Tg3o0s9xT7Jc7Vq7GwEAAJJn1zFALD4KBhB9nOml4wAxuHMAxBpreuk4QHReOg5g/RzA+jmA9XMA6+cAAJifm58DmJ8D5G+saX87QHT2twMAAPxDRXXtuz5CUjo9OWd+2c72x0+6pyzO8Q9/JwD8q/4jTyzYven8q25N9W9d+936cN1dc30UWUXZ0KPONy+RJElS0dVjn9HG6yr4HGbW3Fcb/Szg+/Ubw/XTnnfOpEb08OyFzfaZ54FjznUfL6H+2LFPqMtklUB3t+kaWrqmJEWsbW5geCPbOrXfqP067eq4J1zL3iP+0w5HAACAZNl1DBCLj4IBRB9neuk4QAzuHACxxppeOg4QnZeOA1g/B7B+DmD9HMD6OQAA5ufm5wDm5wD5G2va3w4Qnf3tAAAA/+1/VORq1/kASem0+L2Py3a2v/a7dSHX79CSP8dPPPuyRzsA/MQP9/9C3pve/XBJqn/vvLc+8UFkFWUnXXRHaNltsHmJJEmSiq7d9jvZmF2/2J/HP5DadTjmjMub9DzgibmLnTOpEU286/mwfsPGZvnc89wrbnEfL6FyuX3C4kw21CmRDu20s+tKUuSubNcjtd+nw/0+JV+XIS1tcQQAAEiWnccAsfgoGED0caaXjgPE4M4BEGus6aXjANF56TiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OkL+xpv3tANHZ3w4AAPCDVtU1FT4+UlqtWr22rGf8Eyc/UPLn+JNPv/RoB4CfOOvSmwp2Xxp6+Jmp/q0NDQ1h8vR5PoisouuSmx4PbfuMNCeRJElSUVZ7xHnG7frVuvcfncp1WNl7RFi1pvFrGB9/9o3zJTWydz5a2iyfe/7t/pnu4yXWjNadQl0mqwR6Mds2tMsNdF1JilTfrnul9vt0fMcdHfOEq6iqzdnlCAAAkCw7jwFi8VEwgOjjTC8dB4jBnQMg1ljTS8cBovPScQDr5wDWzwGsnwNYPwcAwPzc/BzA/Bwgf2NN+9sBorO/HQAA4AdbVQ3a0cdHSqcOO48s+xn/2u/Whc59DyrZc9xmh/1CfX2DRzsA/GjDho2hy64HF+zedN8jz6T69364ZJkPIavomjBlTthl+J/MSSRJklS0HXLiVcbu+tUOO2V8atfiXdOfavQzgfqGhnDz/S85Z1Ijenzu4mb57HPe64vcx0usUzpuH+oyWSXUpe16uq4kRW5G606p/Dad0aG34510VTW72uUIAACQLLuPAWLxUTCA6ONMLx0HiMGdAyDWWNNLxwGi89JxAOvnANbPAayfA1g/BwDA/Nz8HMD8HCB/Y0372wGis78dAADgBy1ztSN9fKR02mO/4035N7v02ikle44HHnyKEwzAT0x/4rmC3Zc67DwyfLfu+1T/3hnPvO1DyCq6Dj7hSvMRSZIkFXXHnjPJ2F2/2uU3Pxm26TEslWtxxFHjmvRc4Nn57ztnUiO64e4XwqZN9c3u2ee3K1a7j5dYvar2DnWZrBJqUaYy7NFlD9eWpEgd2WmnVH6bLmrf0/FOuK2qagfb5QgAAJAsu48BYvFRMIDo40wvHQeIwZ0DINZY00vHAaLz0nEA6+cA1s8BrJ8DWD8HAMD83PwcwPwcIH9jTfvbAaKzvx0AAOAHLXK1Z/r4SOk06vgLTPk3W75iVWizw34leY5PPneCEwzATxxw9DkFuy+Nu+TGVP/WVWu+D9dOnetDyCqqxl51b2jVY6j5iCRJkoq6M66YZvyu36zf/qemci227DY4/P2zrxr9bODzpSudL6mRffTpN83y+WfV7oe4l5dYT7TuGOoyWSXUQ5uP59a5GteWpH9bNjcovJJtk/ffpfHtujneCVeRG3SoXY4AAADJsvsYIBYfBQOIPs700nGAGNw5AGKNNb10HCA6Lx0HsH4OYP0cwPo5gPVzAADMz83PAczPAfI31rS/HSA6+9sBAAB+UJGrucHHR0qncRffaMr/38ZdcmNJnuObpsxwcgH40ZLPl4ZW3QcX7L606N2PUv17X3jjIx9AVlF15W2zQufdRpmLSJIkqej7yw2PGcPrNzvxgttTux4n3HxPk54P3D5jvnMmNaJZL7/bLJ+BDj9yrHt5iXVWh96hLpNVgo3p2Me1JSna3LB9z7z/Jt3ctsqxTrpczfF2OQIAACTLDmSAWHwUDCD6ONNLxwFicOcAiDXW9NJxgOi8dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HyN9Y0/52gOjsbwcAAPhBi+qaJ3x8pHSaOPkBU/7/9tmXX4dteg4tuXM87/VFTi4AP7ri+qkFuycNPPiUVP/WTfUN4Zb7X/IBZBVVex90pnmIJEmSir5W3YeE8VPmGMPrN5uw+RrpsPNBqVyTfYeOadIzghff/Ng5kxrRpPteCg0NDc3uGejpF050Py+xdu26Z6jLZJVgr2TbhI65ga4vSf+2HbruFRbn+TdpWpsujnXCVeRqzrbLEQAAIFl2IAPE4qNgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA/saa9rcDRGd/OwAAwA9aVNe84+MjpdOMmXNN+f/JceOuKqnzu+12w8L369c7sQBsUV/fEHoPOLJg96W/3T8z1b/33Y+X+vixiqpjxt1oDiJJkqRmUYddDjaGV6SG/+Gi1K7LNxe93+hnBMtXrnW+pEb22dKVze456C1TH3Y/L7Fabm52ZftQl8kqwS5r38P1JSlSd7fpmtffo4dbd3Kcky5Xe4VdjgAAAMmyCxkgFh8FA4g+zvTScYAY3DkAYo01vXQcIDovHQewfg5g/RzA+jmA9XMAAMzPzc8BzM8B8jfWtL8dIDr72wEAAH73u3P+oyJXu87HR0qnVxfUmfL/k7r3Pgktuw0umfM76JBTnVQAfjT7xdcLdk9qt+P+Yc3adan+vQ88tcCHj1U0XTDx4ZDtta85iCRJkppFvQYeYxyvSJ17zfTUrsuzL5vUpOcEdz32mnMmNaK5r33Y7J6DznnpDffzEuwv7XuGukxWCbYoUxl27bqn60vSv+3gTn3z+nv0bGV7xznpcrU32+cIAACQLLuQAWLxUTCA6ONMLx0HiMGdAyDWWNNLxwGi89JxAOvnANbPAayfA1g/BwDA/Nz8HMD8HCB/Y0372wGis78dAACgVXVNhQ+PlFZLly035f8Xo46/oGTO73lX3uKEAvCjY06/vGD3pFPPvzbVv3X5yu989FhF0/g7Z4ftBhxt/iFJkqRm0x4HnGYsr8j16P+HVK7Lqt0PCRs3bmr0s4LXFn/qfEmNaPL0+c3uOegXXy1zPy/BBnXZPdRlskq4+1p3Di1dX5L+TdtU14QXs23z9lv0SraN45xwFbmae+10BAAASJZdyACx+CgYQPRxppeOA8TgzgEQa6zppeMA0XnpOID1cwDr5wDWzwGsnwMAYH5ufg5gfg6Qv7Gm/e0A0dnfDgAAUJGr3cGHR0qnTK/hob6+wZT/X8x/Y3HJnONHnnrBCQVgi29XrA7ZXiMKdk964+13U/17n3v1Ax89VtE0/A8XmX9IkiSpWTV09AXG8orcqJP+mtq1+dSc+Y1+VrDmu/Xh2qlznTOpES37dk2zehba0NAQ2vc5wD29xNq6uia8km0T6jJZJdwhnXdxjUn6t53TvlfefocWZSpDq82/845zguVqnrLTEQAAIFl2IgPE4qNgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA/saa9rcDRGd/OwAAQMuqmgN9eKR02rHmD6b7v2Lo4WeWxDn+6uvlTiYAW9wy9eGC3Y/23P+EVP/WjZvqw033vuiDxyqKTv7LlNCy22DzD0mSJDWrRp30V+N5Re6Smx4PrboPSeXa/OPYK5v0zODBp99yzqRGNO+tT5rd89CBB5/inl6CXde2W6jLZJVwL1a2DW1zg1xjkn6z6qp9wsJsZd5+i9rlBjrOCVaRq51vpyMAAECy7EQGiMVHwQCijzO9dBwgBncOgFhjTS8dB4jOS8cBrJ8DWD8HsH4OYP0cAADzc/NzAPNzgPyNNe1vB4jO/nYAAICK6pqxPjxSOu03+izT/V/x9HOvNPvzu/3Ao5xIAH605/4nFOyedNu0R1P9Wxd98KWPHasouvTmmaFdn5HmHpIkSWp2HXfuLcb0itVOw9J57tBux/3Duu/XN/qZwcL3PTOQGtNdj73W7J6HHn/W1e7pJdjBnfqGukxWeeic9r1cY5L+/Zpfm6q8/Q51q+rvGCdYRa72PTsdAQAAkmUnMkAsPgoGEH2c6aXjADG4cwDEGmt66ThAdF46DmD9HMD6OYD1cwDr5wAAmJ+bnwOYnwPkb6xpfztAdPa3AwAAVFTX3OTDI6XTSX+eYLr/KxoaGkLfoWOa9fk9duyVTiQAWyxY/H7B7kett983rFy1JtW/954n3vCxYxVFu+17inmHJEmSmmXjrrzHmF6xOnrcDaldnw8/+Xyjnxl8v35jmDjteedMakSr1nzfrJ6J/nXS3e7pJVjb3MDwdqYy1GWySrgfjmvvqr1dZ5J+s+Gdd83b79COVXs5xolWs9RORwAAgGTZjQwQi4+CAUQfZ3rpOEAM7hwAscaaXjoOEJ2XjgNYPwewfg5g/RzA+jkAAObn5ucA5ucA+Rtr2t8OEJ397QAAAC1yNU/56EjpdOUNd5nu/4bJdz/WrM/vD//9APCDsX+5oWD3oxPO/muqf+vXy9f4yLGKotFnTjTnkCRJUrPtkklPGNcrVldNnhUyvYancn0eefLFTXp28Ohzi5wzqREtePfzZvVMdMbMue7pJdqUNl1DXSarPHRnmyrXmKTfrFV1TXi2sn1efoP26LKHY5xgFbmaDXY6AgAAJMtuZIBYfBQMIPo400vHAWJw5wCINdb00nGA6Lx0HMD6OYD1cwDr5wDWzwEAMD83PwcwPwfI31jT/naA6OxvBwAAqMjVvufDI6XTtOlPm+7/hjVr14UOO49stuf37boPnUQAwvr1G0KnvgcW7H708uuLUv17n5n3no8cq+BddP0jIdt7hDmHJEmSmmVb9xwaJkyZY2yv2O154OmpXKOVm+dbq9d81+hnB+///WvnS2pEM555u1k9F134zkfu6yXamI59Ql0mqzw1rMturjNJv9mpHbbPy+9Prd+fxNuq+8D/abcjAABAcuxIBojFR8EAoo8zvXQcIAZ3DoBYY00vHQeIzkvHAayfA1g/B7B+DmD9HAAA83PzcwDzc4D8jTXtbweIzv52AACg3J3zHxXVNet9dKR0en7eAtP9f+PcK25plue2y64Hh/r6BicQgDBj5tyC3Y92GTImNDSkdz/asHFTuPGeF3zkWAVtwpQ5YYfaP5pvSJIkqdnWaddDje3VqE688PbUrtN7H36m0c8PNm2qDzfd+6JzJsVs4l3Phw0bNjWb56Jrv1sXWnYb7N5eglVX7RMWZ7KhTnlpVmX7sG11jWtN0q/vR9n8O7wwD78/B3Tu6/gm3Nbdh2xlvyMAAEBy7EgGiMVHwQCijzO9dBwgBncOgFhjTS8dB4jOS8cBrJ8DWD8HsH4OYP0cAADzc/NzAPNzgPyNNe1vB4jO/nYAAKC8VfSobeWDI6XVx0u+MN3/Nz759MvQqnvz++DemDOvcPIA2OKgY88t2P3ohjseTPVvfevdz33gWAXvkBOvNteQJElSs2772mON7dWoxt85O7TtMzKV6/SQ485v0jOEp1961zmTGtEHf1/WrJ6N9tz7cPf2Eu3h1p1CXSarPHVyxx1cZ5J+s5vbViX+23N4p50d24T7X9WDO9jxCAAAkBw7kgFi8VEwgOjjTC8dB4jBnQMg1ljTS8cBovPScQDr5wDWzwGsnwNYPwcAwPzc/BzA/Bwgf2NN+9sBorO/HQAAKG9bdavdyQdHSqdW3QeHDRs2mu5HMOr4C5rd+b334WecOADCF18tC1t3H1KQe9G22w0Ly5avTPXvnfbY6z5urIL25/EPhG16DDPfkCRJUrOu/8Fjje/V6GqPOC+V63SbnkPD8hWrGv0TrscxAAAgAElEQVQMYcmX3zpfUiN66qV3m9Xz0f1Gn+XeXqKd2aF3qMtklafezLYO1VX7uNYk/WrDuuyW+G/PsR37OLZJ121QbzseAQAAkmNXMkAsPgoGEH2c6aXjADG4cwDEGmt66ThAdF46DmD9HMD6OYD1cwDr5wAAmJ+bnwOYnwPkb6xpfztAdPa3AwAA5a1FruYQHxwpnbrteZipfkSz5r7arM5tq+6Dw9ffrHDiAAgTbr6nYPejI0++ONW/9YuvV/qwsQra+Dtnhx79/2CuIUmSpGbfAX+81BhfjW7sFXendq1Oue+JRj9HaGgI4bYH5zlnUsxuvu+lzf9+GprN89EzLpro3l6i7dp1z1CXySqPXde2m2tN0q/vS6muCXMq2yX6u3Nqh+0d24RrWT1obzseAQAAkmNXMkAsPgoGEH2c6aXjADG4cwDEGmt66ThAdF46DmD9HMD6OYD1cwDr5wAAmJ+bnwOYnwPkb6xpfztAdPa3AwAA5a0iV3O2D46UTjWHnmqqH1F9fUPoPeDIZnNu+x94kpMGwBa7DBlTsPvR08+9kurf+uSL7/iwsQraiKMvMs+QJElSSXT0uBuM8dWkuu5+WCrX6r5HndWkZwlzX/vQ+ZIa0Rdfr2o2z0dvvHO6e3uJ1nJzz2XbhbpMVnlq8eb27tLP9SbpVxvboXeivzt/7tDLcU24iura/ex4BAAASI5dyQCx+CgYQPRxppeOA8TgzgEQa6zppeMA0XnpOID1cwDr5wDWzwGsnwMAYH5ufg5gfg6Qv7Gm/e0A0dnfDgAAlLcWudpbfHCkdDrm9MtN9WO4+qZpzebcXnbdFCcMgDDv9UUFuxd13+v3YVN9fWp/6/frN4brpz3vo8YqWGdcPi206jbYPEOSJEkl0Q/jW+N8NaX9j700lWu1VffB4cul3zT6ecLS5audL6kRvfjGR83mGelTc+a7t5dwl7brGeoyWeWxh1p3DK2qa1xvkn6x6qp9wsJsZWK/OZds/l13XBNvtB2PAAAAybEzGSAWHwUDiD7O9NJxgBjcOQBijTW9dBwgOi8dB7B+DmD9HMD6OYD1cwAAzM/NzwHMzwHyN9a0vx0gOvvbAQCA8lZRXTvLx0ZKpwv/OtlUP4aly5aHbXoObRbndt7ri5wwAMLJ504o2L3o4mvuSPVvfaPuUx80VsG6avKs0GX3UeYYkiRJKpkuuelxY301qQsmPhJadhucyvV6898eatIzhb898qpzJsVs6qOvNZtnpB9+8pl7ewk3uPPuoS6TVZ47tNPOrjdJv9qdbasS+72Z0K67Y5pwW1XXnmrHIwAAQHLsTAaIxUfBAKKPM710HCAGdw6AWGNNLx0HiM5LxwGsnwNYPwewfg5g/RwAAPNz83MA83OA/I017W8HiM7+dgAAoLy1qK75yAdHSqfbpj1qqh/T4Sf+pejPa8ddDgwbN21ysgDK3Nrv1oX2fQ4oyL3oh49m//Cx2jT5ALYK2cBRZ5tfSJIkqWTadrvhYcKUOcb6anK9Bh6dyjVbO+q0Jj1TeHnBJ86X1IhWrl7XLJ6T/rBmtu12w9zjS3XcUl0TXs22DnWZrPLY3Mq2IZsb5JqT9Isd0LlvYr83k9rmHNOEq6iuudCORwAAgOTYnQwQi4+CAUQfZ3rpOEAM7hwAscaaXjoOEJ2XjgNYPwewfg5g/RzA+jkAAObn5ucA5ucA+Rtr2t8OEJ397QAAQBnbZZf/vUWudqMPjpROT86Zb6of0zPPv1r053X0qZc6UQCEex6aVbB70dDDz0z1b13y5bc+ZKyCdeIFt4eW3QabX0iSJKlkqtrjcGN9JdJhp0xI5Zr9YU625POljX6u8M2Ktc6X1IjefOezZvOsdJchY9zjS7gb2laHukxWee6Ujtu73iT9YttU14QXs20T+a2Z2qaLY5p0udprbHoEAABIjt3JALH4KBhA9HGml44DxODOARBrrOml4wDReek4gPVzAOvnANbPAayfAwBgfm5+DmB+DpC/sab97QDR2d8OAACUr/+qqt3Wx0ZKq8XvfWyqH9Om+vrQfa/fF/V5nfrgk04UAGH4kWMLdi+6e8bTqf6tj89d7EPGKkiX3TIztOsz0txCkiRJJVXf4Sca7yuRLrnp8dCq2+BUrttrb7u/Sc8Wpjz8qnMmxWzGM283m2elhx53vnt8CTeq086hLpNVnnst0zp0zg1wzUn6xc5r3yuR35rprTs5nglXkau5w65HAACA5NidDBCLj4IBRB9neuk4QAzuHACxxppeOg4QnZeOA1g/B7B+DmD9HMD6OQAA5ufm5wDm5wD5G2va3w4Qnf3tAABA+WpRVdvXx0ZKq1Vr1prqN8KFV99WtOd06+5DwtJl3zpJAGXuk0+/DC1T+mj1v9a+zwFh7XfrUvtb165bH667a64PGasg7b7/qeYVkiRJKrlqjzjPeF+JtePg41K5bvc64E9Ner7w0oKPnS8pZhOnPR82bqpvFs9Lz75sknt8Cdc+NyAszFaGukxWee7y9j1cc5J+sV5Ve4fFCfzOzGzdwfFMvJoH7HoEAABIjh3KALH4KBhA9HGml44DxODOARBrrOml4wDReek4gPVzAOvnANbPAayfAwBgfm5+DmB+DpC/sab97QDR2d8OAACUr4rqmsN8aKR06rDzSNP8Rnrng78X7Xnd/w9nO0EAhMuum1Kwe9Gp51+b6t86/+2/+4ixCtIfxt5gXiFJkqSSbNRJVxvzK7GOOO3a1K7ddz9c0ujnC8u+XeN8SY3o48+WN4vnpTf/7SH3+BLv/jadQ10mqzy3MFsZ+nTdyzUn6Re7u02XJv/OzK1s61gm30y7HgEAAJJjhzJALD4KBhB9nOml4wAxuHMAxBpreuk4QHReOg5g/RzA+jmA9XMA6+cAAJifm58DmJ8D5G+saX87QHT2twMAAOWrRXXtn31opHTaY7/jTfOboP+BJxXleZ1y3xNODkCZq69vCL32OaJg96JXF9Sl9rc2NIQwefp8HzBW6l10w6Mh23tf8wpJkiSVZMeff5txvxLrsltmhlbdh6Ry7V5147QmPWeY8vArzpkUs9mvvN8snpk+NWe+e3yJd2qH7UNdJqsUuqNtV9ecpF9sVKedm/wb82q2tWOZcBW52hftegQAAEiOXcoAsfgoGED0caaXjgPE4M4BEGus6aXjANF56TiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OkL+xpv3tANHZ3w4AAJSviurayT42UjoddsKFpvlNcPPfHiq6c7pNz6Fh+YpVTg5AmZvz0hsFuxftMmRMqn/rx5994+PFSr0JU+aEPkOON6eQJElSyfbn8Q8Y+yvRdhp2QirX7h77Hd+k5wwvvfmx8yXF7PYZ85vFM9P3PlriHl/i7dJ1z1CXySqlajvv5rqT9LOyuUHhlWybJv2+LMxWOpYJV5GrWWDXIwAAQHLsUgaIxUfBAKKPM710HCAGdw6AWGNNLx0HiM5LxwGsnwNYPwewfg5g/RwAAPNz83MA83OA/I017W8HiM7+dgAAoHxV5Gpn+9hI6TTu4htN85tg2fKVYZseQ4vqnB507LlODADh2LFXFuxedP3tD6b6tz48e6GPFyv1Rp10tfmEJEmSSraW3QaHqybPMvZXoo0+c2Jq1/BHf/+80c8Zvl6+xvmSGtG3q74r+mem69dvCK26D3avL+UxzOaey7YLdZmsUujx1h3C1q47Sb/Qxe17Nvk3ZtvqGscy2T606xEAACA5dikDxOKjYADRx5leOg4QgzsHQKyxppeOA0TnpeMA1s8BrJ8DWD8HsH4OAID5ufk5gPk5QP7Gmva3A0RnfzsAAFC+WuRqP/GhkdJp4uQHTPObaOQx5xTVOb17xtNOCkCZW7V6bajsPaIg96Fteg4NX3+zIrW/dfXa78O1U+f6cLFS7c8Tpm++1oeZT0iSJKlka9tnpLG/Eu+KW58KW/ccmso1fO2t9zXpecMdD813zqSYvfnOZ83i2WnPvQ93ry/xrmjfI9Rlskqpozrt5LqT9LN26rpXk39f2ucGOJaJVrPUrkcAAIDk2KkMEIuPggFEH2d66ThADO4cALHGml46DhCdl44DWD8HsH4OYP0cwPo5AADm5+bnAObnAPkba9rfDhCd/e0AAEB56t79qP+jRa5mkw+NlE4PP/m8aX4T/e2BJ4vmfGZ6DQ+rVq91UgDK3B33Pl6we9ERJ12c6t/60oKPfbRYqTb+ztmhR/8/mEtIkiSppOs18Gjjf+WlviNOSuUa3uegk5v0vOGFNz5yvqSYzXjm7Wbx7HTYEWe615d4IzrvGuoyWaXUi9m2oW1ukGtP0s+a3rpTk35fcrl9HMcky9WutfMRAAAgOXYqA8Tio2AA0ceZXjoOEIM7B0CssaaXjgNE56XjANbPAayfA1g/B7B+DgCA+bn5OYD5OUD+xpr2twNEZ387AABQnlp1H1zpQyOl1Rtvv2ua30Tfrlgdtuk5tCjO5+//dJETAkAYdMipBbsXPTlnfmp/Z31DQ7j1gZd9tFiptt+Yi80jJEmSVPLteeAZxv/KS8eMuzGVa7hlt8Hh0y+WNvqZw9JvVjtfUswmTns+bNxUX/TPTk8+d4J7fYlXmRsUFmQrQ10mq5Qa16GXa0/Szzqq405N+m3pXbW345hwvxsx4n+z+xEAACAZdioDxOKjYADRx5leOg4QgzsHQKyxppeOA0TnpeMA1s8BrJ8DWD8HsH4OAID5ufk5gPk5QP7Gmva3A0RnfzsAAFCeKqprd/eRkdJq2fKVpvkJOPiP5xXF+Xzw8TlOBkCZe/+jTwt2H8r1GxU2btqU3t/69699sFipdvbV94dW3YeYR0iSJKnk2++Yi80BlJeuvG1W2KbnsFSu45umzGjSc4c7Zsx3zqSYffz58qJ/fjp+0j3u9WXQnW2rQl0mq5R6M9s6VFft49qT9JNaVw8Kr2VaN/q3pW/XvRzHhPt/t9v7/7b7EQAAIBl2KwPE4qNgANHHmV46DhCDOwdArLGml44DROel4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA/saa9rcDRGd/OwAAUJ5a5mqP8JGREvqAzfb7muIn9aRgxtNFcT7XrF3nZACUuQuuvq1g96K/TLgj1b91+qy3fKxYqTX+ztmhx95HmUdIkiSpLDrqzInmAcpbu+13cirX8ZDDTm/Sc4cXXv/I+ZJiNueVD4r++en0J55zry+DxnTsE+oyWaXY+HbdXHuSftaV7Xo0+ndl7y79HMOEa1VdU2H3IwAAQDLsVgaIxUfBAKKPM710HCAGdw6AWGNNLx0HiM5LxwGsnwNYPwewfg5g/RwAAPNz83MA83OA/I017W8HiM7+dgAAoDy1yNWe7yMjpVPfoWNM8ROyYuXqsE2PoQU9n8ecfrkTAVDmNm7aFHL9RhXkPtSy2+DwwcefpXfvXb0uXDvVh4qVXvsfe6k5hCRJksqmUy+Zah6gvHXsOZPS+WB898Hhq6+XN/rZw1fLVjtfUsxunzG/6J+hvrnwPff6MqhH1/6hLpNVii3KVIa+XfZy/Un6Sf267NHo35XaLrs5hglX0XVwW7sfAQAAkmHHMkAsPgoGEH2c6aXjADG4cwDEGmt66ThAdF46DmD9HMD6OYD1cwDr5wAAmJ+bnwOYnwPkb6xpfztAdPa3AwAA5akiV3OHj4yUTgcde64pfoKGHzm2oOdz7rw3nQSAMvfknPkFuw8N/f0Zqf6tz7/2oQ8VK7XOGf9AaNVjqDmEJEmSyqaLrn/EXEB566rJs0Km1/BUruXbpj3apOcPk6fPd86kmH276ruifoa6YuVq9/oyaWbrDqEuk1WKTWnT1bUn6Wc90rpTo35T9uu0q+OXcFt1H9jN7kcAAIBk2LEMEIuPggFEH2d66ThADO4cALHGml46DhCdl44DWD8HsH4OYP0cwPo5AADm5+bnAObnAPkba9rfDhCd/e0AAEB5alFdO9dHRkqnMy6aaIqfoBvueLBg53KHQaNDQ0ODkwBQ5g4/8S8FuxdNm/50an/npvr6cPN9L/lIsVJp/J2zQ/f+o80fJEmSVDa16jE0jJ8yx3xAeW2PA05L5Xre96izmvQMYu5rHzpfUszeevfzon+O2mHnke75ZdD57XuFukxWKTeoy+6uP0k/6Y8d+zTq9+SQzrs4fgnXsrpmZ7sfAQAAkmHHMkAsPgoGEH2c6aXjADG4cwDEGmt66ThAdF46DmD9HMD6OYD1cwDr5wAAmJ+bnwOYnwPkb6xpfztAdPa3AwAA5amiuvZTHxkpna699T5T/AR9vOSLgp3LiZMfcAIAytzyFatCptfwgtyH2u64X1izdl1qf2vdR1/5QLFSa+Rxl5k7SJIkqazqsvsocwHlvePOvTWV63nr7kPCsuUrG/0M4ouvVzlfUswenbOo6J+l7rn/Ce75ZdCALv1CXSarlJvRulNo6fqT9E+1zw0IC7KVsX9Pjuq4k+OXdLnafex+BAAASIZdywCx+CgYQPRxppeOA8TgzgEQa6zppeMA0XnpOID1cwDr5wDWzwGsnwMAYH5ufg5gfg6Qv7Gm/e0A0dnfDgAAlJ/Wrff+P1tU19T7yEjp9ODjc0zxE7bLkDGpn8dMr+FN+igoAKVh0pQZBRtTnHzeNan+rfc9+aYPFCuV/jzhwbB1z6HmDpIkSSqr+gw53nxAee/qO54J2e1GpHJN/+2BJ5v0HGLy9HnOmRSjG+55IdTXNxT1s9TDT7zIPb8M2rq6JrySbRPqMlml3AGd+7oGJf2k69p2i/1bclyHHR27hKvoNnhfOyABAACSYdcyQCw+CgYQfZzppeMAMbhzAMQaa3rpOEB0XjoOYP0cwPo5gPVzAOvnAACYn5ufA5ifA+RvrGl/O0B09rcDAADlp0VuQBsfGCmtXl1QZ4qfsAuuvi3183jM6Zc78ACEPfY7vmBjilfeTG9M8c2KtT5OrFQaP2VO6LHPaPMGSZIklV0DDzvHnECptMcBp6VyTR907LlNehbx3KsfOl9SzD5furKon6Wec9kk9/wy6ca21aEuk1XKPVXZIWzt+pP0Tw3o0i/2b8mpHbZ37BKuorrm93ZAAgAAJMOuZYBYfBQMIPo400vHAWJw5wCINdb00nGA6Lx0HMD6OYD1cwDr5wDWzwEAMD83PwcwPwfI31jT/naA6OxvBwAAys9WVYP39IGR0uqrr5eb4idszktvpH4en5+3wIEHKHMLFr9fsPFE36FjUv1bZ89/34eJlUoHnXClOYMkSZLKsoP/dJU5gVLp2HMmpXJNb7vdsLBy1ZpGP4v44uuVzpcUs5cXfFLUz1MnTZnhnl8m/b7TzqEuk1UBOqrTTq5BST/WcnNPV7aP9Ttydvvejl3y5+GPdkACAAAkw85lgFh8FAwg+jjTS8cBYnDnAIg11vTScYDovHQcwPo5gPVzAOvnANbPAQAwPzc/BzA/B8jfWNP+doDo7G8HAADKT4vq2tE+MFI6ZXuNCA0NDab4Cft+/fpQ2XtEaudxh0GjnUcAwrhLbizYmGLi5AdS+zs3bqoPN937og8TK++de830sE3PYeYNkiRJKsuOP/828wKl0pW3zUpt7nXfI8806ZnEbQ/Oc86kGN07882ifp762KyX3PPLpM65AWFRpjLUZbJKueey7UI2N8h1KOnHTu64Q6zfkYva93Tcki436Aw7IAEAAJJh5zJALD4KBhB9nOml4wAxuHMAxBpreuk4QHReOg5g/RzA+jmA9XMA6+cAAJifm58DmJ8D5G+saX87QHT2twMAAOWnorr2Ih8YKZ12HnKM6X2e7Df6rNTO4/W3P+iAA5S5DRs2hi67HlyQ8cQ2PYaGpcuWp/a3Lnz/Cx8lVt6bMGVO6D3wGHMGSZIklW3nXTPD3ECpteuIk1K5rg8/8aImPZOY88oHzpcUo+umzg3rN2ws2meqb9d96J5fRs1o3SnUZbIqQCd23NE1KOnHOlcNCAszlZF/Q65s18NxS7pc7QV2QAIAACTD7mWAWHwUDCD6ONNLxwFicOcAiDXW9NJxgOi8dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HyN9Y0/52gOjsbwcAAMpPi+qav/nASOk08phzTO/z5Jpb7k3lHGZ6DQ/ffLvSAQcoc4/NerFg44mmfpA6rmmPv+6jxMp7h5x4tfmCJEmSyrZW3YeE8XfONjdQao0ee30q13Zl7xFhzdp1jX4m8emXK5wvKWYfLFlWtM9UV65a475fRp3VoXeoy2RVgF7JtgntcwNch5J+bFK7XOTfkGvadXPMEq6iuvavdkACAAAkw+5lgFh8FAwg+jjTS8cBYnDnAIg11vTScYDovHQcwPo5gPVzAOvnANbPAQAwPzc/BzA/B8jfWNP+doDo7G8HAADKT4tczQs+MFI6nXL+tab3efLmwvdSOYdjzrjcwQYgHHbChQUbT8ycPS+1v/OrZat9jFh57/xrZ4RttxtuviBJkqSyrfNuo8wNlGqX3/JkaNV9SCrX9yNPvdDo5xINDQ1h0n0vOmdSjJ6d/35RP1ftsPNI9/4yqX+XfqEuk1WBOrt9b9ehpB8b2mW3yL8fN7atdsySLld7sx2QAAAAybB7GSAWHwUDiD7O9NJxgBjcOQBijTW9dBwgOi8dB7B+DmD9HMD6OYD1cwAAzM/NzwHMzwHyN9a0vx0gOvvbAQCA8lORq/3CB0ZKp/GT7jG9z5P6+oZUPsT3+lvvOtgAZe7rb1aEbXoOLchYonqPUWHjpk2p/a2zXn7Xx4iV1yZMmRN6DxpjriBJkqSybpdhfzI/UOrtNPT4VK7v48+6uknPJma+UOd8STG686FXivrZ6p77n+DeXyZtvblXs21CXSarAvRmtnXI5fZxLUraUqvqmjCnsl2k34/b2uYcs6TL1UyzAxIAACAZdjADxOKjYADRx5leOg4QgzsHQKyxppeOA0TnpeMA1s8BrJ8DWD8HsH4OAID5ufk5gPk5QP7Gmva3A0RnfzsAAFBeWvYe8Z8tqmsbfGCkdLr/kWdN7/No5DF/zuv5G/r7MxxkAMJNU2YUbCxx4V8np/Z3rt+wMdxw9ws+Rqy8dtjJ480TJEmSVPYNOfJ88wOl3uGnXZPK9d2570FhU319o59PvPfJ186XFLOVq9cV7bPVw0+8yL2/jJrUNhfqMlkVqEvb9XQdSvqxc9r3ivTbMaVNV8cr4Sqqax+2CxIAACAZdjADxOKjYADRx5leOg4QgzsHQKyxppeOA0TnpeMA1s8BrJ8DWD8HsH4OAID5ufk5gPk5QP7Gmva3A0RnfzsAAFBe/lf14A4+LlJazXt9kel9Hl1x/dS8nr8nnn3ZQQYg7LHf8QUbS7z30ZLU/s433/nMR4iV1y6Y+EjI9BpuniBJkqSy7/DTrjFHUOpdctPjoVW3walc4y+9+najn09s2LgpTLzreedMitHC978o2mer51w2yb2/jDqq406hLpNVgVqYqQw9q/q7FiVtqVfV3mFxhN+Ou9t0cbwSriJX+7RdkAAAAMmwgxkgFh8FA4g+zvTScYAY3DkAYo01vXQcIDovHQewfg5g/RzA+jmA9XMAAMzPzc8BzM8B8jfWtL8dIDr72wEAgPLSsnrQ3j4uUlp9/uUy0/s8evaF1/N27vrUHh3q6xscZIAyt/Cdjwo2jhhy2Omp/q1/e+RVHyFW3powZU7YofaP5giSJEnS5k65eIp5ggpS70FjUrnGz7vyliY9o5g+6y3nS4rR43MXF+3z1UlTZrj3l1HVVfuEukxWBey6dtWuRUk/dl/rzv/2d2N6606OVdLlal6wCxIAACAZdjEDxOKjYADRx5leOg4QgzsHQKyxppeOA0TnpeMA1s8BrJ8DWD8HsH4OAID5ufk5gPk5QP7Gmva3A0RnfzsAAFBeKnKDj/ZxkdJp2+2Ghfr6BtP7PFq1em1o1X1wXs7f5Lsfc4ABCOdcNqlgY4m7pj+V2t/52VcrfIBYee33p15jjiBJkiT9d3+54VHzBBWkQ0+6OpVrvE/t0U16TrHg3c+dLylGN9//UtE+X31s1ovu/WXWzNYdQl0mqwK1eHN9u+zlWpS0pSM77fRvfzcea93RsUq+1+yCBAAASIZdzACx+CgYQPRxppeOA8TgzgEQa6zppeMA0XnpOID1cwDr5wDWzwGsnwMAYH5ufg5gfg6Qv7Gm/e0A0dnfDgAAlJcWuZpLfFikdNph0GhT+xTsNuKPiZ+7XL9Dw7rv1zu4AGVu48ZNoWr3Qwoyjmi34/5hzdp1qf2tM5+v8wFi5a0Lr38kZLcbYY4gSZIkbS7Ta3iYMGWOuYIK0kWb52ctuw1O5Vp/98MljX5Osea79c6XFLNl364pymesby58z/2/zLqww3ahLpNVAbuzbZVrUdKW2uYGhTezrX/zN+PpyvaOVdLlahbZBQkAAJAMO5kBYvFRMIDo40wvHQeIwZ0DINZY00vHAaLz0nEA6+cA1s8BrJ8DWD8HAMD83PwcwPwcIH9jTfvbAaKzvx0AACgvLXI103xcpHTab/RZpvYpOP6sqxM/d9fedr8DC0B44tmXCzaOOPm8a1L7O7/7fkOYeNfzPj6svDRhypzQZ8jx5geSJEnSf9d976PMFVTQuvcfncq1fu2t9zXpecW0x153vqQYvfnOZ0X5jHXpsm/d/8uswZ13D3WZrApc/y79XI+StjShXfff/L2YU9nOcUq+D+2CBAAASIadzACx+CgYQPRxppeOA8TgzgEQa6zppeMA0XnpOID1cwDr5wDWzwGsnwMAYH5ufg5gfg6Qv7Gm/e0A0dnfDgAAlJeK6tp5PixSOp187gRT+xRMnPxAouet/U4HhFWr1zqwAIQjTrq4YOOI+W8sTu3vfHXREh8eVt464vRrzQ0kSZKkf2qPA04zV1BBO/C4y1K51mtHndak5xUvL/jE+ZJi9OicRWT+3R4AACAASURBVEX5jLWhoSFkeg03BiijsrlB4c1s61CXyaqATW3TxfUoaUsDuvT7zd+Ll7JtHaeEq8jVfG4XJAAAQDLsZAaIxUfBAKKPM710HCAGdw6AWGNNLx0HiM5LxwGsnwNYPwewfg5g/RwAAPNz83MA83OA/I017W8HiM7+dgAAoLy0qK5Z6uMipdNVN04ztU/B7BdfT/S8XXH9VAcVgLB8xaqCfex15yHHbPnYbFrufOgVHx5WXvrLDY+GbO99zQ0kSZKkf2r/Yy8xX1BBO//aGalc6626Dw5Lly1v9POKpctXO19SjG6698VUnynGsf3Ao4wByqw721SFukxWBW6fLv1cj5JCy83Nqmz/q78Vr2VaO04JV1Fd861dkAAAAMmwmxkgFh8FA4g+zvTScYAY3DkAYo01vXQcIDovHQewfg5g/RzA+jmA9XMAAMzPzc8BzM8B8jfWtL8dIDr72wEAgPLxX133+L98WKS0uuehWab2KVi67NvEzlnbHfcLy1esclABCLdMfbhgY4jrbrs/tb/zk8+X++iw8tZOQ08wL5AkSZL+paPH3WC+oIJX1e/3qVzvUx98sknPLSZPn+98STFa+s3qonzWOuyIM40ByqwTOu4Y6jJZFbh7W3d2PUra0pkdtv/V34qFmUrHKOEqcrXr7IQEAABIht3MALH4KBhA9HGml44DxODOARBrrOml4wDReek4gPVzAOvnANbPAayfAwBgfm5+DmB+DpC/sab97QDR2d8OAACUj1ZVgzr5sEhp9dKrb5vapyTX79BEztlF4293MAHYov/IEwsyftim59CwdNny1P7OR+cs8sFh5aWjx91gTiBJkiT9QmOvuNucQQVv2OgLU7nef/+ni5r03GL2/PedLylGry1aUpTPWo8de6UxQJm1Y9e9Q10mqyJoYJd+rklJoVtV/7AoU/mrvxVb52ocp2Rr+N3vfvc/7IYEAABoOruZAWLxUTCA6ONMLx0HiMGdAyDWWNNLxwGi89JxAOvnANbPAayfA1g/BwDA/Nz8HMD8HCB/Y0372wGis78dAAAoHy2qagb4qEhpteTzpab2KRlx1Lgmn6/2fQ4Iy1escjABCHXvfVKw8UNTPzYdx9rv1ofr7prrg8NKvEtvnhna7Li/OYEkSZL0C11x69PmDSp4p182LZXrvfX2+4Z1369v9LOLv3/xrfMlxeihZ94uyuetF42/3RigDJtT2S7UZbIqcPe17ux6lLSlqW26/OpvRWVukGOUcC17j/hPuyEBAACazo5mgHj/e507B0DkcaaXjgPE4M4BEGus6aXjANF56TiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OkL+xpv3tANHZ3w4AAJSPraoHHeujIqXTNj2Gho2bNpnap+Tk865p+sdsr5/qQAKwxflX3VqwMcQTz76c2t85761PfGxYeWnvg840J5AkSZJ+obZ9RpozqCiaMGXOlusxjet+5ux5jX52UV/fEG6690XnTIrYDXe/sOXfTbG5bdqjxgFl2BXteoS6TFZFUE2X3V2TksKhnXb+1d+J9rkBjlHCbd1lwP9jNyQAAEDT2dEMEIuPggFEH2d66ThADO4cALHGml46DhCdl44DWD8HsH4OYP0cwPo5AADm5+bnAObnAPkba9rfDhCd/e0AAED5aFFdc7mPipROvQccaVqfovGT7mnS+eqw88iwYuVqBxKAsHHTplC9x6iCjB9y/Q4NGzduSuXvbGhoCJOnz/OxYSXeKRdPCS27DTYnkCRJkn7pufGgMeYNKpr6Hzw2lev+5POuadIzjMfnLna+pBh98fXKonvmOnP2POOAMmz/zn1DXSarIuj+Np1dk5JCNjcovJJt84u/E12r9nGMEm7r7kO2shsSAACg6exqBojFR8EAoo8zvXQcIAZ3DoBYY00vHQeIzkvHAayfA1g/B7B+DmD9HAAA83PzcwDzc4D8jTXtbweIzv52AACgfFTkau71UZHSafiRY03rU/TAY3OadL7GT7rHQQRgi6fmzC/Y+OHCv05O7e/8cMkyHxlW4l19+zOh066Hmg9IkiRJv9I+h44zd1DRdNy5t6Ry3Vftfkior29o9DOMdz5a6nxJMZr/9t+L7pnr23UfGgeUYW1zg8LCTGWoy2RVBA3uvLvrUlK4ol2PX/yN6NG1v+OTcP/VdVDGbkgAAICms6sZIBYfBQOIPs700nGAGNw5AGKNNb10HCA6Lx0HsH4OYP0cwPo5gPVzAADMz83PAczPAfI31rS/HSA6+9sBAIDy0SJX84qPipROJ5z9V9P6FL3+1ruNPle5foeGNWvXOYgAbDH61EsLNn5476Mlqf2dDz3zto8MK/GGjb7AXECSJEn6jQ76/9i78yipqwTB985Uz+meN+ctZ97M6zYTtCLYlDWSdMEVcV8wEpB0LdQSxVJLLZeiLJeyLDdcEBUVF0RREBEV911RFFAURRENRUVFCy1EQEAgycz70DfP07YKv19GxpK/+HzO+f7T53TbGQtx7+/ec+8frjJ3UNl01e3PhS23Oagon/05b+Va/Axj7br14YZJL3nPpIg98Oy8snvmunTZCuOACm1Kpx4hl0qrDHqgY3efSUlhrx57/ey/Edv32tfr08r9Wybb1W5IAACA/NnVDBCLS8EAoo8zHToOEINfDoBYY02HjgNE59BxAOvnANbPAayfA1g/BwDA/Nz8HMD8HKBwY0372wGis78dAACoHNWZ7FcuFUlOI2+cZFpfRF993fLL+Mbf87gXEIDvLV+xMqS3ry/J2GHAb88q2t/5zaq14XqXUauVO+/q+0L72oHmApIkSdJGOuVvt5k/qKza9aDTivLZv3T0nXk9y5j67FveLyliN06eERqbmsvquWtzc3Po0KfeWKAC+/PWfUIulVaZdFCP3X0uJYUnO3b9yb8PO/Xax2vTym1e27+33ZAAAAD5s7MZIBaXggFEH2c6dBwgBr8cALHGmg4dB4jOoeMA1s8BrJ8DWD8HsH4OAID5ufk5gPk5QOHGmva3A0RnfzsAAFAZ/vt2+/4fLhRJVnc/+IxpfRE1NTWHLbcZFPt92nXgiWH9+kYvIADfG3/P4yUbO0x64Omi/Z0z5y50wbBatWsnTg+1+x1vHiBJkiRtor+OftAcQmXV0OGji/LZ3+uQU/N6ljE397n3S4rR4iUryu7Z607Z3xkLVGD79Nwr5FJplUkPd+oa2vlcShXfGVvv+JN/H3bruY/XppWrytTtaEckAABA/uxsBojFpWAA0ceZDh0HiMEvB0CssaZDxwGic+g4gPVzAOvnANbPAayfAwBgfm5+DmB+DlC4sab97QDR2d8OAABUhuqaA3u6UCRZzZj9lml9kfXa48jY79Pjz83ywgHwgwOGnFmScUPnnQ4JK1d9W5S/sbGpOYy7/2WXC6tVO/L0UeYAkiRJ0iZq33tAuPbO580hVFaNuPnx0G7DZ7PQn//v/huLv/yqxc8zvlm1xvslxWjO/EVl9+x10NCzjQcqsC02NCfdMeRSaZVJ9d37+WxKFV73XgeE+f/h34Y9eu7ltWnteh+4ux2RAAAA+bOzGSAWl4IBRB9nOnQcIAa/HACxxpoOHQeIzqHjANbPAayfA1g/B7B+DgCA+bn5OYD5OUDhxpr2twNEZ387AABQGTbPHFjnQpFk9clnX5jWF1m/wSfHeo/6D/ljaG5u9sIB8L0PP/68ZOOGMy8YXbS/8/1PlrhYWK3aJTc+GlLbDzYHkCRJkjZ1cXm/o80hVJZts++wonwH7pr6dF7PNCY99rr3S4rYw8+/XXbPX08860rjgQrtts6ZkEulVSY93LFraOdzKVV84zv1+tG/Dfv22NPr0tpl6va3IxIAACB/djcDxOJSMIDo40yHjgPE4JcDINZY06HjANE5dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HKNxY0/52gOjsbwcAACpDdSZ7igtFktMWtQPD+vWNpvVFNvi4cyK/R+16Dwivzn3XiwbADy6+ZnzJxg6z33inaH/n1GfecrGwWrVdDvqDOYAkSZIUob6DTzOHUFl26O8vL8p34LgzR+T1TGPm3IXeLyliN0+ZGZqbm8vq+esFI8cZD1RoJ3fdOeRSaZVRh3Tr57MpVXiHdd/tR/8uHNBjT69L63eQHZEAAAD5s7sZIBaXggFEH2c6dBwgBr8cALHGmg4dB4jOoeMA1s8BrJ8DWD8HsH4OAID5ufk5gPk5QOHGmva3A0RnfzsAAFAZqjLZUS4TSU7b7jvUlL4Ejh8e/eLPk84e6QUD4AeNTU2hdp9jSjJu2HXgiUX7O79e8a1LhdWqnXjuzcb/kiRJUsQOOv4i8wiVZeeNuq8o34Gtdj4srF/f2OLnGp99udz7JcXoH1+vLKtnsGPGTzUeqNB27LVvyKXSKqOe6NA1tK/J+nxKFdyWG/4NeCXd6Yd/F+p67O51aeXa9coeYUckAABA/uxwBojFpWAA0ceZDh0HiMEvB0CssaZDxwGic+g4gPVzAOvnANbPAayfAwBgfm5+DmB+DlC4sab97QDR2d8OAABUhuqa7FQXiiSnQcf82ZS+BE47/5pI70/HHQ4Ony3+hxcMgB9MmzGnZOOG62+/v2h/54tzPnShsFqtK299OnTe6TDjf0mSJClivzvnJnMJlW1d+w4pyvdg1mtvt/i5RlNTc7h5yizvlxSxubnPy+oZ7NTHXjAeqNDabWhGhy4hl0qrjDqkez+fT6nCG7HVtj/8m3CQfxNavc0zdUPtiAQAAMifHc4AsbgUDCD6ONOh4wAx+OUAiDXWdOg4QHQOHQewfg5g/RzA+jmA9XMAAMzPzc8BzM8BCjfWtL8dIDr72wEAgMpQXZN9w4Uiyenkc64ypS+B4RdeH+n9uWasZ7QA/NhJf76yJGOGLbcZFL5c8nVR/sb1jU1h7L0unlbrtd+Qs439JUmSpBidM+pecwmVbdljzi/K9+Diq2/P6/nGY9Pf8X5JEXvsxXfK6hnszFfnGQ9UcKO71IZcKq0y6pGO3UI7n02potut5z4//JtwSLd+XpNWbvOaA39vRyQAAED+7HAGiMWlYADRx5kOHQeIwS8HQKyxpgNtAKJz6DiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OULixpv3tANHZ3w4AAFSGqprsMheKJKfLr59oSl8C5464eZPvzQ79h4W169Z5sQD4wTcrV4eOOxxckjHDUadcWLS/850Pv3CZsFqt4SPuCu16DzD2lyRJkiL23fh51PjnzCdUtp1+8R1F+S7sefCpeT3fmLdgsfdLitjY+14uq+ewH378uTFBBffbbn1DLpVWmTWg+x4+n1KF90jHbt//e3DEhn+nvR6tW1Wm7kw7IgEAAPJnlzNALC4FA4g+znToOEAMfjkAYo01HToOEJ1DxwGsnwNYPwewfg5g/RwAAPNz83MA83OAwo017W8HiM7+dgAAIPm27FX3f7lMJFnddf9TpvQlcMHIcZt8bx5/bpYXCoAfmXDfkyUbMzz6zMyi/Z1TnpzrMmG1SlffMS1073e0cb8kSZIUo279jjKfUFl3zR3Ph19vN7go34e/f/FVi59vrFy91vslxWjp8tVl8xx21eo1xgQVXM9e+4dcKq0y6/5O3X0+pQrv5K47f//vwVHddvV6tHJVNdlz7YoEAADIn13OALG4FAwg+jjToeMAMfjlAIg11nToOEB0Dh0HsH4OYP0cwPo5gPVzAADMz83PAczPAQo31rS/HSA6+9sBAIDkq+qZrXGZSLJ6YdYbpvQlcMm1d2z0ffnN7y/wIgHwEwN+e1ZJxgvdd/tNaGhYX5S/ccmyVS4RVqs1+HeXGPNLkiRJMdut/gzzCZV9uw0+vSjfh4n3PZnXc46Jj7zm/ZIiNm/B4rJ6Fttlp0ONCyq4Jzt2DblUWmXWfj329PmUKrite/UP81IdwtBuu3o9Wr8L7IoEAADIn13OALG4FAwg+jjToeMAMfjlAIg11nToOEB0Dh0HsH4OYP0cwPo5gPVzAADMz83PAczPAQo31rS/HSA6+9sBAIDkq645cJCLRJLVR598bkpfAhddffsvvicd+tSHTz77wosEwI98vGhxaNd7QEnGC+dednPR/s5psxe4RFit0vnXTg3tawca80uSJEkxG3zCpeYUKvuOGX5dUb4Px54xIq/nHC/O+cj7JUXsqRm5snoeu+vAE40LKrgRW20bcqm0yqwJnXr5fEoV3tjOmTCs6y5ei1auqiZ7sV2RAAAA+bPTGSAWl4IBRB9nOnQcIAa/HACxxpoOHQeIzqHjANbPAayfA1g/B7B+DgCA+bn5OYD5OUDhxpr2twNEZ387AACQfFU12dNdJpKc2vUeENauW2dKXwLnXHrTL74v14z1XBaAnxp546SSjRneeveDovyNDQ2N4aYpM10irLwbPXF62O6AE4z5JUmSpBZ0wrk3mVeo7LtozKNF+T502enQ0NCwvsXPOj5dvMz7JUXs9gdml9Xz2Pph5xoXVHD13fuFXCqtMmz3nnv7jEoV3OAN/z6f1HVnr0Xrd7ldkQAAAPmz0xkg3nKcXw6AyONMh44DxOCXAyDWWNPhNgDROXQcwPo5gPVzAOvnANbPAQAwPzc/BzA/ByjcWNP+doDo7G8HAACSryqTvdZFIsmp996/NZ0vkTP+Ovpn35NdBpwQ1q1r8AIB8CPNzc1hxwOPL8l4Yff6k4v2d857/+8uEFardNQZVxvvS5IkSS3svKvvM69Qm6jXnr8tyndi5qvzWvyso7GxKdw4eYb3S4rYytVry+aZ7O/Pucq4oILrlDkwzE91CLlUWmXW2M4Zn1GpgttiQ0O67ea1aOWqMtlRdkUCAADkz25ngFhcCgYQfZzp0HGAGPxyAMQaazp0HCA6h44DWD8HsH4OYP0cwPo5AADm5+bnAObnAIUba9rfDhCd/e0AAEDyVWeyD7lMJDlljxpuOl8iJ/35yp+8H+16DwgzZr/lxQHgJ155452SjRdunvBg0f7OyY+/4fJg5d3FNz4aUtsPNt6XJEmSWlD73gPC1XdMM7dQm2jgcRcW5Xtx0dW35/W84+Fpb3u/pIi9/8mSsnkm+7erxhkbVHj3dewecqm0yqx3N7Rzz318RqUKrmPNgV6H1i5Td51dkQAAAPmz2xkgFpeCAUQfZzp0HCAGvxwAscaaDh0HiM6h4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA4caa9rcDRGd/OwAAkHxVmexbLhNJTif9+UrT+RIZevolP3k/zvjraC8MAD/rjxdeX5KxwpbbDgpLli4vyt+4eMkKFwerVeo7+DRjfUmSJKmFdd/9aPMKtZnOvHRiUb4Xu9efnNczjzff+9z7JUVs+msfls0z2Rtuv9/YoMI7e+s+IZdKqwy7vnNvn1FJasWqMtmb7IoEAADIn93OALG4FAwg+jjToeMAMfjlAIg11nToOEB0Dh0HsH4OYP0cwPo5gPVzAADMz83PAczPAQo31rS/HSA6+9sBAIDkq87UfeMykeR06eg7TedLZMBvz/rRe1Gz19Fh+YqVXhgAfmLtunVh610PL8lY4ZjTLina3/n0rPdcHKy8O/EvtxjnS5IkSXnU7+AzzC3UZrr2zudDerv6onw3Fv39Hy1+5rHsm2+9X1LE7nnijbJ5Ljvl4eeMDSq8/XrsGXKptMqw+ekOYbte+/mcSlJrlam71a5IAACA/NnxDBCLS8EAoo8zHToOEINfDoBYY02HjgNE59BxAOvnANbPAayfA1g/BwDA/Nz8HMD8HKBwY0372wGis78dAABIts1r+/8PF4kkqzvvfcJ0vkT6HHDcj96Lx5+b5UUB4Gc99NRLJRsrPP7cy0X5G9euWx9unDzDxcHKqytvfTp03vlw43xJkiQpj+pPuNT8Qm2q3erPKMp3Y8J9T+b17OPOh171fkkRumHSS6FhfWNZPJedNmOOsUGFt2VNNryR6hhyqbTKsJFdtvE5laRWqiqTvcPOSAAAgPzZ8QwQi0vBAKKPMx06DhCDXw6AWGNNh44DROfQcQDr5wDWzwGsnwNYPwcAwPzc/BzA/BygcGNN+9sBorO/HQAASLb2NdltXCSSrL67DI7ia25uDqntB//wPvxu+OVeFAB+0VGnXFiScULP3YeEhob1Rfkb33j3M5cGK+/2P/JcY3xJkiQpz0447xbzC7Wphv7puqJ8N4aefklezz6ef/UD75cUsc++XF4Wz2XnvfuhsYHC+E69Qi6VVhk2P9Uh1PTa3+dUklqjTN0kOyMBAADyZ8czQCwuBQOIPs506DhADH45AGKNNR06DhCdQ8cBrJ8DWD8HsH4OYP0cAADzc/NzAPNzgMKNNe1vB4jO/nYAACDZqjPZwS4SSVYLFi4ynS+Br75e8cN70H2334QlS5d7UQD4Wd/9Rmy57aCSjBP+csXYov2ddz06x4XByqvhI+4K7XoPMMaXJEmS8p0LXnO/OYbaVBff+GhRvhtb7XxYWN/Y2OJnHx99ttT7JUXstbc/LYtns1/8Y6mxgcIfuu4Ucqm0yrRLt9rW51SSWqGqTPZeOyMBAADyZ9czQCwuBQOIPs506DhADH45AGKNNR06DhCdQ8cBrJ8DWD8HsH4OYP0cAADzc/NzAPNzgMKNNe1vB4jO/nYAACDZqjJ1Z7pIJDm16z0grFm7znS+BN7OffTD+zD18eleEAB+0diJD5VsrPDd71UxLPpimcuClVfX3vl86LXnMcb4kiRJUp61rx0YrrnjefMMtbl67TW0KN+RV+e+2+LnHw3rG8OYu2d4v6QIPfz8/LJ4Nrt+w/f2u/VUY4TKbrce+4RcKq0y7c10x9A9c4DPqiTlW6buQTsjAQAA8mfXM0AsLgUDiD7OdOg4QAx+OQBijTUdOg4QnUPHAayfA1g/B7B+DmD9HAAA83PzcwDzc4DCjTXtbweIzv52AAAg2aozdde5SCQ5ZfY8ylS+RKY+9sL378GxZ4zwYgCwUfsednpJxgn7HHZa0f7GJ15612XByqsjTrnC+F6SJElqhXrucYw5htpkg4ZdWJTvyFU33Z3XM5AHnp3n/ZIidMu9s0Jzc3k8n+2+22+MESq89jXZ8Fq6U8il0irTzt9qe59VScqzqprso3ZGAgAA5M+uZ4BYXAoGEH2c6dBxgBj8cgDEGms6dBwgOoeOA1g/B7B+DmD9HMD6OQAA5ufm5wDm5wCFG2va3w4Qnf3tAABAsn13gYaLRJJT/yF/NJUvkUuuvSPU7HV0+Hr5N14MAH7Rex9+WrJxwq13PVyUv3H1mnVhzN0vuSxYLe6SGx8Nv95usPG9JEmS1ArtfsiZ5hlqk5156cSifEcGHfPnvJ6DvP7OIu+XFLGvV6wui2e0uw06yRhB4dbOvUIulVaZNifdMXTJ9PdZlaT8esrOSAAAgPzZ+QwQi0vBAKKPMx06DhCDXw6AWGNNh44DROfQcQDr5wDWzwGsnwNYPwcAwPzc/BzA/BygcGNN+9sBorO/HQAASLbqmrr5LhFJTr8bfrmpfIkMOflv4dkXX/NCALBRF18zviRjhF9vd1D46usVRfkbX337U5cEK692qz/D2F6SJElqpQ45aYR5htpk1975fEhvV1/w78iW2wwK36xa3eLnIF8tW+X9kiI2/4MvyuIZ7eDjzjFGUDi1604hl0qrjDuz644+q5KUR1U12Wl2RgIAAOTPzmeAWFwKBhB9nOnQcYAY/HIAxBprOnQcIDqHjgNYPwewfg5g/RzA+jkAAObn5ucA5ucAhRtr2t8OEJ397QAAQLJV19StcpFIcrr46ttN5Uvk6lsmexEA2Kimpuaw7b5DSzJGOPaMEUX5G5ubQxj/4KsuCVaLO+VvtxnXS5IkSa3YSeePNddQm61f/RlF+Z48M/3VvJ6H3P7AbO+XFKFnX36/LJ7TnvCnK4wRFPr23DvkUmmVcbPSnUMqk/V5laSWlsm+aGckAABA/ux+BojFpWAA0ceZDh0HiMEvB0CssaZDxwGic+g4gPVzAOvnANbPAayfAwBgfm5+DmB+DlC4sab97QDR2d8OAAAk17/2HPj/uEQkWd0++TFT+RJoamoOq1av8UIAsFHTX55bsjHCk8+/UpS/8ePPl7ogWC1u1PjnQte+Q4zrJUmSpFbs/Gummm+ozTb0T9cV5XvylyvG5vU85LlX3vd+SRG669E5ZfGc9tzLbjZGUGhfkw2zO3QKuVRaZdzQbrv6vEpSC6uqyb5idyQAAED+7H4GiMWlYADRx5kOHQeIwS8HQKyxpkPHAaJz6DiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OULixpv3tANHZ3w4AACRXdW12e5eIJKtnX3zNVB4AytCSZavCoOPOL8n4oNceR4b16xuL8nc+8sJ8FwSrxR10/MXG9JIkSVIr1r52YLj2zufNN9Rmu+iGh4vyXek3+OS8nocs+GSJ90uK0PWTXgzrGhpL/qz2mrH3GCfo+8Z2zoRcKq0y7qmOW4f2NVmfV0lqSZm6OXZHAgAA5M8OaIBYXAoGEH2c6dBxgBj8cgDEGms6dBwgOoeOA1g/B7B+DmD9HMD6OQAA5ufm5wDm5wCFG2va3w4Qnf3tAABAclXV1B3iEpFk9d4Hn5jKA0AZ+WbV2jBt9oIwavy0kNp+cEnGBxeMHFeUv3Xl6rXh+kkvuSBYLeqvox8I7WsHGtNLkiRJrVivPY8x31Cbr9tuRxb8u9Ku94DwxT+WtviZyJq168P1k7xXUpQWfbGs5M9sJ973pHGCvu/krjuHXCqtMm9Qj919XiWpBVVlsm/ZHQkAAJA/O6EBYnEpGED0caZDxwFi8MsBEGus6dBxgOgcOg5g/RzA+jmA9XMA6+cAAJifm58DmJ8DFG6saX87QHT2twMAAMlVncme5RKRZLVy1bem8gBQBtasbQgz5y4MY+6eqtefxQAAIABJREFU8f1lscefc2PJxgfvvL+wKH/zy2997GJgtajRE6eHHetONp6XJEmSWrk9Dh1uzqE23wFHnVeU78u9j0zL67nI3Y+97v2SIvTa/EUlf3b7+HOzjBP0fbv03CfkUmmVeXd36uHzKkktKVP3rt2RAAAA+bMjGiAWl4IBRB9nOnQcIAa/HACxxpoOHQeIzqHjANbPAayfA1g/B7B+DgCA+bn5OYD5OUDhxpr2twNEZ387AACQXFWZ7E0uEUlOPfoNMY0HgBJrWN8Y5sxfFG6eMvNHl8XuNOCUkowP9jv89KL83U3NzeG2qa+4GFgt6vhzbjSelyRJkgrQISddZs6hNt/vzx9blO/LKeeOyuvZyItzPvJ+SRF6bPo7JX+G+/Lr840T9H3tNvRKulPIpdIq8/bouZfPrCTFrCpTt8DuSAAAgPzZGQ0Qi0vBAKKPMx06DhCDXw6AWGNNh44DROfQcQDr5wDWzwGsnwNYPwcAwPzc/BzA/BygcGNN+9sBorO/HQAASK7qmrqnXCKSnPY74gzTeAAokcam5vD2gsXh1vtf/slFsZfe9Fho33tAScYH4+5+pCh//wefLnEpsFrUleOeDp13Osx4XpIkSSpAp/ztNvMOtfmuGPdUaFeE5yqZPY8Ozc3NLX42svCzpd4vKULjpr5S8me57334qXGCfmhs50zIpdIq827oUuPzKklxy2Q/tjsSAAAgf3ZIA8TiUjCA6ONMh44DxOCXAyDWWNOh4wDROXQcwPo5gPVzAOvnANbPAQAwPzc/BzA/ByjcWNP+doDo7G8HAACSqyqT/cAlIsnpuDNHmMYDQJF9d9fygk+WhDseevUXL4o94tQrSzI2+PV2B4Wly1YU5XV48Ll5LgVWi+p/9F+M5SVJkqQCddGYR807lIhq9zu+KN+Z9z74pMXPRhoaGsMNk17yfkkRWrl6bUmf6S5Zutw4QT90UtedQy6VVpk3P90hbNNzP59ZSYpRVabuc7sjAQAA8menNEAsLgUDiD7OdOg4QAx+OQBijTUdOg4QnUPHAayfA1g/B7B+DmD9HAAA83PzcwDzc4DCjTXtbweIzv52AAAgoerrf1VVk13nEpHk9LerxpnGA0ARfbp4WZj02OubvCQ2s/fQkowNjh9+eVFeh+Ur14TrJ7kMWPE796opoV3vAcbykiRJUgFK9zk4jJ443dxDiWjw7y4pyvdm7MSH8npGMuXJud4vKUIffLqkpM91G5uaQvtaz6T0/7VTr31CLpVWG+jirbfzmZWkWGX/YYMkAABA/uyWBojFpWAA0ceZDh0HiMEvB0CssaZDxwGic+g4gPVzAOvnANbPAayfAwBgfm5+DmB+DlC4sab97QDR2d8OAAAk0+a1/bdweUiyGjfpEdN4ACiCv/9jRbjv6TcjXRB7zqh7SzY2eGb6q0V5PWa8/pHLgBW7aydOD7X7DjOOlyRJkgrUDtmTzD2UmP44YmJRvjdHnnJhXs9IZr35sfdLitDMNxaW/Blv175HGC/o+9ptaFa6c8il0irz5qY7hq179fe5laSIVdXUfW2HJAAAQP7smgaIxaVgANHHmQ4dB4jBLwdArLGmQ8cBonPoOID1cwDr5wDWzwGsnwMAYH5ufg5gfg5QuLGm/e0A0dnfDgAAJFO7zIC+LhBJVk8+/4ppPAAU0JdfrQwPPjcv1gWxdcdeUJJxQWbPo8L6xsaCvyaNTU1h7H0vuwxYsTv6jGuM4SVJkqQCNuDYv5l7KDFde+fz4dfbDS7496bTjoeEhob1LX5OsuiLZd4vKUJTn3mr5M96d647wXhBP3RT55qQS6XVBjqz644+s5IUsapMdrkdkgAAAPmzexogFpeCAUQfZzp0HCAGvxwAscaaDh0HiM6h4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA4caa9rcDRGd/OwAAkExVveqOdoFIsnrn/YWm8QBQAMtWfBueeOnd+Bc+T3ghdN758JKMCy6++vaivDa5hV+6CFixu+yWJ0K6z8HG8JIkSVIBG3b2jeYfSlS7DDq1KN+dl1+f3+LnJI2NTWHM5BneL2kT3XTPzNDU3FzSZ77Zo4YbL+iHTuy2c8il0moDzUp3DqlM1udWkqKUqVthhyQAAED+7KIGiMWlYADRx5kOHQeIwS8HQKyxpkPHAaJz6DiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OULixpv3tANHZ3w4AACRTdU3dBS4QSVbfrFxtGg8ArWjVt+vCtNkLwg2TXmrR5bCnXnh7ycYF7334aVFeo/ueftNFwIrdXof9yfhdkiRJKnDnjrrX/EOJasgfrirKd+eKGybm9axk6jNveb+kCH21bFVJn/0edcqFxgv6oZ167htyqbTaSMd229XnVpKilKn7xg5JAACA/NlNDRCLS8EAoo8zHToOEINfDoBYY02HjgNE59BxAOvnANbPAayfA1g/BwDA/Nz8HMD8HKBwY0372wGis78dAABIpqpM9g4XiCSnrn2PMIUHgFayZu36MOP1j8KNk2fkdTHsHocOL8m44IAhZxbldVq6fLULgBW7My+dYPwuSZIkFbj2tQPDNXc8bw6iRPWXq+8vyvdn0DF/zut5yavzPvV+SRGa/8EXJX0GfNr51xgz6IfabWhWh84hl0qrDfRUx61D+5qsz64kbbLsSjskAQAA8mdXNUAsLgUDiD7OdOg4QAx+OQBijTUdOg4QnUPHAayfA1g/B7B+DmD9HAAA83PzcwDzc4DCjTXtbweIzv52AAAgmaoz2RddHpKc9jnsNFN4AMhTw/rG8Orbn4abp8zK+1LYkbc9G7bc9qCSjAvG3/N4UV6vF179wAXAitW1dz4feu5xjPG7JEmSVOBq9jnWHESJa/TE6aHzzocX/Pvz6+0OCt+uWdvi5yV//8cK75cUoednLyjps+ALR91mzKAfNaZLTcil0mojDeqxu8+tJG26VXZIAgAA5M/uaoBYXAoGEH2c6dBxgBj8cgDEGms6dBwgOoeOA1g/B7B+DmD9HMD6OQAA5ufm5wDm5wCFG2va3w4Qnf3tAABAMlXV1H3m8pDkdOwZI0zhAaCFmpqaw9sLFodxU19ptUthh/7pupKMCdLb14flK1YW/DVb39gUbrl3lguAFatDf3+5sbskSZJUhPYdco45iBLZ3of/qSjfoRmz32r5c6bm5nDTlJneL2kTTXlybkmfCV837l5jBv2oE7rtHHKptNpIkzr18LmVpE2VqVtthyQAAED+7LIGiMWlYADRx5kOHQeIwS8HQKyxpkPHAaJz6DiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OULixpv3tANHZ3w4AACRPx477/nN1TbbJBSLJ6YKR40zhAaAFFnyyJEx4+LVWvxS2T/8TS3Px55+uKMrrNv+DxS7/VawuuuHhsOW2Bxm7S5IkSUXoyNNHmYcokQ07e0xRvkNXjrkrr+cmD0972/slbaIxk2eEpqbmkj0Xvuv+p4wZ9KN26rVPyKXSakPt0nMfn11J2khVmbo1dkkCAADkz05rgFhcCgYQfZzp0HGAGPxyAMQaazp0HCA6h44DWD8HsH4OYP0cwPo5AADm5+bnAObnAIUba9rfDhCd/e0AAEDyVPXIdnF5SLIaN+kRU3gAiOHTxcvC5CfeKMiFsBfd8HBo13tAScYE02bMKcrrV6jXTsltl4P+YNwuSZIkFak/jphoHqJEdslNjxXlOzRo6Nl5PTd5/Z1F3i8pQkuWrSrZ8+FHn5lpzKAf1W5Dszt0CrlUWm2kkV228dmVpI1UVVO31i5JAACA/NlxDRCLS8EAoo8zHToOEINfDoBYY02HjgNE59BxAOvnANbPAayfA1g/BwDA/Nz8HMD8HKBwY0372wGis78dAABInnY1B+7r8pBk9fT0V03hASCCL79aGR54dl5BL4M99PeXlWQ8ULvPMaGxqakor6FLfxWn359/qzG7JEmSVMQuv/UpcxEltm79jir4dyi1/eCwZu26Fj87+cdSz06kKL3z4Rcle0780uw3jRn0k27rnAm5VFptpDfTHcPWvfr77ErSL1RVk11nlyQAAED+7LwGiMWlYADRx5kOHQeIwS8HQKyxpkPHAaJz6DiA9XMA6+cA1s8BrJ8DAGB+bn4OYH4OULixpv3tANHZ3w4AACRPVWbACS4PSVa5BZ+YwgPARixb8W144qV3C34R7OiJ04tyufPPdenoO4vyWj73yvsu/VXkRt7+bNhq1yOM2SVJkqQitXXfIeYiSnT7H3luUb5LM1+d1+JnJ83NIYy972Xvl7SJnn/1g5I9L5737ofGDfpJp3fdKeRSabWhzth6R59dSfqFqjLZBrskAQAA8mcHNkAsLgUDiD7OdOg4QAx+OQBijTUdOg4QnUPHAayfA1g/B7B+DmD9HAAA83PzcwDzc4DCjTXtbweIzv52AAAgeapr6i53eUiyWrV6jSk8APyMVd+uC9NmLwg3THqpKBfB/umKu0s2HliwcFHBX891DevDTffMdOmvIjfwuAuN1yVJkqQitlv9GeYiSnQnnHtTUb5LI2+clNczlMdefMf7JW2iKU/NLdlz408++8K4QT9pzx57hVwqrTbU9A5dwhY+u5L082Xq1tslCQAAkD87sQFicSkYQPRxpkPHAWLwywEQa6zp0HGA6Bw6DmD9HMD6OYD1cwDr5wAAmJ+bnwOYnwMUbqxpfztAdPa3AwAAyVNVUzfF5SHJqefuQ0zfAeA/WLtufZg5d2G4cfKMol4Ee8BR55VkPJA9anhRXtc33/vchb+K3PnXTA3tawcas0uSJElF7JATR5iPKNGNuPnxonyX6oedm9czlLfe+7v3S9pEYybPCE1NzSV5frzim1XGDfpJW9Rkw5vpjiGXSqsNdWj33Xx+JennymQb7ZIEAADInx3ZALG4FAwg+jjToeMAMfjlAIg11nToOEB0Dh0HsH4OYP0cwPo5gPVzAADMz83PAczPAQo31rS/HSA6+9sBAIDkqc5kX3N5SHLa/zdnmr4DwP+yvrEpzJm/KNxy76yiXwJ79Z3TQrrPwSUZD0y478mivL53PTrHhb+K1OiJ08P2/U8wXpckSZKK3Ml/HWdOosTXvd/RBf8upbevD2vXrWvxM5Sly1d7r6QIfbVsVUmeIzc1NYctagcaO+gn3d2pR8il0mpD3dOpp8+uJP1s2Sa7JAEAAPJnZzZALC4FA4g+znToOEAMfjkAYo01HToOEJ1DxwGsnwNYPwewfg5g/RwAAPNz83MA83OAwo017W8HiM7+dgAAIHmqM9mvXBySnI4ffrnpOwAVr6m5Oby9YHG4beorJbsA9vfnjy3JWKBDn/rwzcrVBX+NP/9yuYt+FblhZ48xVpcSWFVNdml1TXas10KSpPLtwhseMidR4jvg6POK8n2a9drbeT1LKeVzKqmt9O6HX5TsmXLXvkcYO+gnnb11n5BLpdXG6tdzb59fSfppzXZJAgAA5M8ObYBYXAoGEH2c6dBxgBj8cgDEGms6dBwgOoeOA1g/B7B+DmD9HMD6OQAA5ufm5wDm5wCFG2va3w4Qnf3tAABAsqRr6/9Pl4Ykq4uvGW/6DkBFW/DJkjDh4ddKfgHsboNPL8lY4KSzRxbldX5qRs5Fv4rUyNufCV12PtxYXUpc2abqzID9vnu2sHlmwGEb/mervCaSJJVX6e0PDqMnTjcvUeI74dybivKduuqmu/N7ljLTsxRpU01/7cOSPVfeof8w4wf9pGyPPUIulVYba1SXWp9fSfqZ7JQEAADIn13aALG4FAwg+jjToeMAMfjlAIg11nToOEB0Dh0HsH4OYP0cwPo5gPVzAADMz83PAczPAQo31rS/HSA6+9sBAIBkqepVl3FpSLK6Y8rjpu8AVKRPFy8L9zzxRllc/nr52KdC+9qBJRkLvDDrjYK/1mvWNoQxk2e46FeRqjv2AuN0KYFVZbLn//vnC5vX9t9qw/98vtdGkqTyqU//E81JVBGNuOWJonynDh52Xl7PU95esNj7JW2ie596s2TPl/c97HTjB/2kDpkDw/xUh5BLpdWGmrfhPeueOcBnWJL+Q5ttttl/slsSAAAgP3ZrA8TiUjCA6ONMh44DxOCXAyDWWNOh4wDROXQcwPo5gPVzAOvnANbPAQAwPzc/BzA/ByjcWNP+doDo7G8HAACSpV3v7ECXhiSraTPmmL4DUFG+XLoyPPjcvLK6/PXoM64uyTigdp9jQmNTU8Ff89ffWeSSX0Xqr6MfCO1rBxqnS8nr6c3q63/1H58x/N9dsv97dSY72esjSVJ5VHfMBeYlqpi67350wb9THfrUh3XrGlr8PGXp8tXeK2kT3XTPzNDc3FyS58yHHH+e8YN+tgc7dgu5VFptrD923cHnV5L+Q5ttdv5/tlsSAAAgP3ZtA8TiUjCA6ONMh44DxOCXAyDWWNOh4wDROXQcwPo5gPVzAOvnANbPAQAwPzc/BzA/ByjcWNP+doDo7G8HAACSpaome7pLQ5LVBws/M30HoCJ8s2pNmDZ7Qbh+Uvld/rrNvsNKMg647LoJRXntJzz8mkt+Fakd6042RpeSVqbuk81r+/+PjT1rqO49YFhVJtvg9ZIkqbQdd9YN5iWqmA446ryifK9eeeOdvJ6pjL1vlvdL2kRfr/i2JM+bh/3xMuMH/WwXbrVdyKXSamPN6NAlbFGT9RmWpH/XZvX1v7JbEgAAID92bwPE4lIwgOjjTIeOA8TglwMg1ljToeMA0Tl0HMD6OYD1cwDr5wDWzwEAMD83PwcwPwco3FjT/naA6OxvBwAAkqU6UzfapSHJqV3vAWHN2nWm7wAk2rdrG8LMuQvDmLtfKstLX/86+oGSjQU+WPhZwV//Txcvc7mvInXSX24xRpcSVlVN3dr2Ndltojxv2Lx33S5VmezfvW6SJJWuc6+aYm6iiunEc28uyvfq6lsm5/Vc5ZEX5nu/pE30/idLSvLc+cy/XWf8oJ/tkO79Qi6VVhvsiG59fYYl6d+1Wd++/2S3JAAAQH7s4gaIxaVgANHHmQ4dB4jBLwdArLGmQ8cBonPoOID1cwDr5wDWzwGsnwMAYH5ufg5gfg5QuLGm/e0A0dnfDgAAJEtVTd0jLg1JTjV7HW3qDkBiNTQ0hjnzF4Wbpsws60tfDzr+4pKMAwb+9qyivA+PTX/H5b7aZKPGPxe69h1ijC4lrV7Z4+I8c/i3TP3/rM5kn/HaSZJU/NrXDgxX3znN/EQV04hbnijKd+vQ3/0lr+cqc95Z5P2SNtGsuQtL8vz5oqtvN4bQz9Y10z+8m0qHnNpcUzr18BmWpH9Xbe2w/2K3JAAAQH7s5gaIxaVgANHHmQ4dB4jBLwdArLGmQ8cBonPoOID1cwDr5wDWzwGsnwMAYH5ufg5gfg5QuLGm/e0A0dnfDgAAJEtVTd3bLg1JTtmjhpu6A5A4jU3N4e0Fi8Ot979c9he+jp44PWy16xElGQfcNfXpgr8Xq79dF264+yWX+2qT1Z9wifG5lLiyt7XowUPfvv+04X/3yg3/N5q9hpIkFa9eex5jbqKKq+cevy34d6vjDgeHhob1LX62snjJCu+VtIkefv7tkjyHvmbsPcYQ+sWe7Ng15FJptcH69dzbZ1iS/v/5TMd9/9luSQAAgPzY1Q0Qi0vBAKKPMx06DhCDXw6AWGNNh44DROfQcQDr5wDWzwGsnwNYPwcAwPzc/BzA/BygcGNN+9sBorO/HQAASJT/VJ2pW+3SkOR00tkjTd0BSIym5uYw/4PF4fYHZreZC1/PvHRCaS5A2+Hg8M2q1QV/T2bP+8TFvtpkF97wUNhi20HG51Kiyr7Rrk/9f83nAcSG/zsHVWfqVngtJUkqTrsMOtX8RBVX/6P/UpTv15y3ci1+ttLY1BTGTJ7h/ZI20m1TXynJ8+hxkx4xhtAvNnKrbUIulVYb7JoutT7DkvS/2rJv33+xXRIAACA/dncDxOJSMIDo40yHjgPE4JcDINZY06HjANE5dBzA+jmA9XMA6+cA1s8BADA/Nz8HMD8HKNxY0/52gOjsbwcAAJJjy233/zcXhiSry66bYOoOQCJ8unhZmPTY623uwtd9f3N2ScYAp5w7quDvSXNzcxj/4GwX+2qT9R18mrG5lKCqarLL2tcO6NAazyGqMwd0qspk3/K6SpJU+Nr1HhDOG3WfOYoqqhP/cktRvl833vFAXs9Y7n/mLe+XtIm+XdNQ9GfSkx981hhCv9hR3XYNuVRabbC30h1C10x/n2NJ2tCWffv+ix2TAAAA+bHDGyAWl4IBRB9nOnQcIAa/HACxxpoOHQeIzqHjANbPAayfA1g/B7B+DgCA+bn5OYD5OUDhxpr2twNEZ387AACQHNW9D+zjwpBkNfG+J03dAWjTFi9ZEe5/+s02edHrqPHPhdT2g0syBnjxlTcL/t58tOgrF/pqk/3hwvHG5VKyaq6qqTuwNZ9F/GvPvf5bVU12otdWkqTCt/PAU81TVFFddssTRfluDT390ryescx682Pvl7SJFn2xrOjPph97dqbxg36x3r32C7lUWm2007ru6HMsSRvavLb//2bHJAAAQH7s9AaIxaVgANHHmQ4dB4jBLwdArLGmQ8cBonPoOID1cwDr5wDWzwGsnwMAYH5ufg5gfg5QuLGm/e0A0dnfDgAAJEe7TN3hLgxJVtNfnmvqDkCbtHT56vDES++26Ytejz/nxpL8/m+//7Ghqam54O/Rw9PedqGvNtq1dz4feuxxtHG5lKQydRcV6plEde8Bw6pqsuu8zpIkFbbTL77TfEUVVfd+hZ+X9trjyLyesXz8+dfeK2kTvfHuZ0V/Rv3CrDeMHbTxtfgOXUIulVYb7LkOW4V2PsOSFNr1qf+vdkwCAADkx45vgFhcCgYQfZzp0HGAGPxyAMQaazp0HCA6h44DWD8HsH4OYP0cwPo5AADm5+bnAObnAIUba9rfDhCd/e0AAEByVNVkz3FhSLL6eNFiU3cA2pRvVq0N02YvCNdPavsXve404JSS/P5fOeauorxP1096yYW+2miHn3KFMbmUoKoydc9uVl//q0I+l2hfk92muia70OstSVLhqtn72DB64nRzFlVM+w05u+zXY9Y1rPecRdpET896r+jPql+f956xgzbaDZ17h1wqrTZatscePseSKr6OHff9ZzsmAQAA8mPnN0AsLgUDiD7OdOg4QAx+OQBijTUdOg4QnUPHAayfA1g/B7B+DmD9HAAA83PzcwDzc4DCjTXtbweIzv52AAAgOapqsre4MCQ5ta8dEBoa1pu6A9AmrFnbEGbOXRjG3D0jEZe8XnrTY6F97wFF//1vt+G/mc8lzlF99165zFcb65IN34FfbzfYuFxKSpnsp/+Wqf+fxXg28d1/Z8N/82mvuyRJhev4s8eYt6hiOu6sG4ryvZry8HN5PWu5+7HXvV/SRvruO1Js73+0yLhBG+2krjuHXCqtNtpNnWt8jiVVfLW1w/6LHZMAAAD5sQMcIBaXggFEH2c6dBwgBr8cALHGmg4dB4jOoeMA1s8BrJ8DWD8HsH4OAID5ufk5gPk5QOHGmva3A0RnfzsAAJAcVZm6Z10Ykpy23XeoaTsAZa9hfWOYM39RuHnKzERd8vqbP4wsye//QceeXfD3rLGpOYy7/2WX+Wqj7XnocGNyKSFVZbINm/c6cKeiPqCor//Vhv/uCK+/JEmFaatdfxNGjX/O3EUV0QXXPVCU79XwC6/P63nLC69+4P2SNtKYu1/6/rlkMf39i6+MG7TRduuxT8il0mqjzd9Qz177+yxLqug22+z8/2zHJAAAQH7sBAeIxaVgANHHmQ4dB4jBLwdArLGmQ8cBonPoOID1cwDr5wDWzwGsnwMAYH5ufg5gfg5QuLGm/e0A0dnfDgAAJEd1Td1HLgxJToOGnm3aDkDZ+u4C1LcXLA633v9yIi95zew1tCS//5MffLbg7937H//DRb7aaH+6fFJo13uAMbmUkKoydSeW6jlFu0zd4VWZ7LfeB0mSWr8jTrnC/EUV0eiJ00OnnQ4t+Heq3+CTPW+RCtxXy1YV9Rn2N6tWGzNoo22xoTdSHUMulVYbbfjWO/gsS6ro7JYEAADInx3hALG4FAwg+jjToeMAMfjlAIg11nToOEB0Dh0HsH4OYP0cwPo5gPVzAADMz83PAczPAQo31rS/HSA6+9sBAICE6Nv3n6oy2QYXhiSnU8+72rQdgLLT3Nwc3vnwizD+gdmJvdz13FH3luS3v9OOh4RVq9cU/D2c+sxbLvHVL3bthBdCZu+hxuNSQqqqqZtQ6scVVTUDdqjK1C32fkiS1Lql+9SHy8c+ZR6jiqhf/RkF/061rx0Qlq9Y2eLnLStXr/VeSZsot/DLoj7Lbmpq/v67bdygjTW5U4+QS6XVRpveoUvYIpP1WZZUoWWbbJgEAADIn53hALG4FAwg+jjToeMAMfjlAIg11nToOEB0Dh0HsH4OYP0cwPo5gPVzAADMz83PAczPAQo31rS/HSA6+9sBAIBk+Ndedb92WUiyGnnjJNN2AMrKp4uXhUmPvZ74y13rjv1bSX77Tz3v6oK/h1+v+NYFvtpoR59xtbG4lJCqMtm3/rXnXv+tHJ5ZtOt1QHVVTd1s74skSa1bduhfzWNUEf3mD1cV5Tv17Iuv5fXcZfyDs71f0kaaOXdh0Z9pd9npUGMGbbTzt9o+5FJpteEG9djdZ1lSpa4BNNgxCQAAkD+7wwFicSkYQPRxpkPHAWLwywEQa6zp0HGA6Bw6DmD9HMD6OYD1cwDr5wAAmJ+bnwOYnwMUbqxpfztAdPa3AwAAyVDd+8DdXRiSrCY/+KxpOwBlYfGSb8L9z7xVERe7XjvhhdB558NL8tv/4itvFvy9fHHOhy7w1S922dgnQ7rPwcbiUhLK1H2zeW3/rcrpucWWffv+S1VN3XjO4axsAAAgAElEQVTvjyRJrVf72oHhwusfMp9R4vvzlZOL8p267LoJeT13eWpmzvslbaRHp79T9GfbtfscY8ygjTa4e7+QS6XVhhvXOeOzLKkiq6qpW2vHJAAAQP7sEgeIxaVgANHHmQ4dB4jBLwdArLGmQ8cBonPoOID1cwDr5wDWzwGsnwMAYH5ufg5gfg5QuLGm/e0A0dnfDgAAJMPmmbqhLgxJVjNfnWfaDkBJLV2+Ojzx0rsVdbHrqRfeXpLf/e8ud21sairo+7m+sSmMvXeWC3z1i+035BzjcCkZNW/ooHJ9flGdyZ5aXZNt8j5JktQ67X7ImeYzSnzXTngh/Hq7wQX/Pg0+7py8nr3MW7DY+yVtpAkPv1b0Z9x9B55kvKCN1jXTP7ybSoec2mzz0x1C7177+TxLqriqMtlv7ZgEAADIn93iALG4FAwg+jjToeMAMfjlAIg11nToOEB0Dh0HsH4OYP0cwPo5gPVzAADMz83PAczPAQo31rS/HSA6+9sBAIBkqM7UXejCkGT16edfmrYDUBLfrF4bps1eEK6f9FLFXey656HDS/K7P+K6Owv+vr774Rcu79UvdvbIe0K73gOMw6VkdHm5P8Ooqqk7sDpTt8J7JUlS/n03jj/risnmNUp8fQ48qeDfp447HBzWr29s8bOXpctXe6+kjfTd8+bGpqaiPus+YMiZxgvaZM922CrkUmm14c7euo/PsqRKbJUdkwAAAPmzaxwgFpeCAUQfZzp0HCAGvxwAscaaDh0HiM6h4wDWzwGsnwNYPwewfg4AgPm5+TmA+TlA4caa9rcDRGd/OwAAkAxVNdmJLgtJTltuMyisb2w0bQegqNasbQgz5y4MY+6eUZGXuo687dmw5bYHleS3f8HCRQV/f6c8OdflvfrZRk+cHrbd/3fG4VICqqrJTtusb99/ahPPMXoO6FydqXvX+yZJUv59N57/blxvfqMkV3/CJUX5Ps19+/28nr+MvXeW90vaSEuXry7qM+/Bx51jrKBNdm2X3iGXSqsNN7NDl7BFTdbnWVJllalbYcckAABA/uweB4jFpWAA0ceZDh0HiMEvB0CssaZDxwGic+g4gPVzAOvnANbPAayfAwBgfm5+DmB+DlC4sab97QDR2d8OAAAkQ3UmO9OFIclph/7DTNkBKJqG9Y1hzvxF4eYpMyv6Qtdjz7q+JL/7/Yf8seDv8ZJlq1zaq1/suLNuMAaXElBVpm7xFrUDN29LzzLada3/7xv+f3/a+ydJUv6d/Ndx5jdKdKddNL4o36VbJj6U1zOYR16Y7/2SNtKCT5YU9dn3kadcaJygTfa7rruEXCqtNt4h3fr5PEuqrDWBmrqv7ZgEAADIn13kALG4FAwg+jjToeMAMfjlAIg11nToOEB0Dh0HsH4OYP0cwPo5gPVzAADMz83PAczPAQo31rS/HSA6+9sBAIBk+O7ybBeGJKeDh51nyg5AwTU2NYe3FywO4+5/2YWuG+pz4Ekl+d0ff8/jBX+vp81e4D3Wz3bluKdDp50ONQaX2vrlmZlsw+a963Zpkw806ut/teH//xHeR0mS8qvbbkeGa+983jxHiW3kbc+Edr0HFPy7NOyPl+X1DGbO/EXeL2kjzZ73SVGfgR8//HLjBG2yXXvuHXKptNp4Ezr38nmWVFllsl/ZMQkAAJA/u8kBYnEpGED0caZDxwFi8MsBEGus6dBxgOgcOg5g/RzA+jmA9XMA6+cAAJifm58DmJ8DFG6saX87QHT2twMAAP8ve3ceJUV5KPxfb+7+u+ee++YuCT0DZhpcAHG6Z3BfcEncAt0jOO56YyQYd+MS14gRNbigBkVcESOIiGLcUVSUACqKioqM4oYbKioKIutM/TD3vnmNQVNFT/V0VX8+53z/uss5TlWfepainuSr3ar5n2ryxTYHhqSnE8++3JQdgNi0tQXB3Nc/CG68c6aDXP+3c0feW5aDmb9e3ZZ7B4s+XRLr9V65cnVw9YQZrrPWWuGws42/pXQcnnlc0tc2OuWKh2XyhRWupyRJ696hJw03z1Gqy/3osNh/Rw27HlrSOsx7H37mWknf0gPTW8q6Fv6Lwb81RtBfrXO+EMzKdgta6rJKcHPXtHn9Hu5pSVVU4UNvTQIAAJTOW+UAkTgUDCD8ONNHxwEi8OQAiDTW9NFxgPB8dBzA/jmA/XMA++cA9s8BADA/Nz8HMD8HiG+s6f12gPC83w4AACTf9/NN3R0Ukq4uvWa8KTsAsXhrwaLglvufcYDr1zrg2Is65Jk/6OQLYr/mL7zynmustXb28DuCzo17GX9LSS9XuCUt6xuZXHGbNS1wXSVJWrc23Ha/YNjoh813lNr6HXpWWX5L8995f53XYVatbg2uvGWa6yV9Q7fc90xZ18PP+M3VxggK1c0bbha01GWV8AZvsqX7WVLV9OVaurcmAQAASufNcoBIHAoGEH6c6aPjABF4cgBEGmv66DhAeD46DmD/HMD+OYD9cwD75wAAmJ+bnwOYnwPEN9b0fjtAeN5vBwAAkq8mV9zTYSHp6rZ7ppiyA9CuFixcHEx86HkHt35D9T/8aYc88x949MnYr/34+591jfUXXT52arB14Shjbyn5zfnPHs3/kqY1jk6Nfbus+e96xrWVJGndOvDYi8x5lNqOOPPqsvyO7rh/qrUYKaZGjp8etLW1lW1d/LzLRhsfKFRndt8yaKnLKuE9nt0o6JIvuKclVUWZXPFdb00CAACUzhvmAJE4FAwg/DjTR8cBIvDkAIg01vTRcYDwfHQcwP45gP1zAPvnAPbPAQAwPzc/BzA/B4hvrOn9doDwvN8OAAAkX6ahcJTDQtLVk8++ZMoOQLv4+NOlwaRpcx3Y+i2deeltHfK8r9/lkGDVqtWxXv8FCxe7xlprR551rXG3lPRyxcXfzzd1T+M6R6fGvv9ckyuMd50lSYpe1633DYbd8JB5j1LZuSPvKcvvaPBF15W0HvPozHmul/QtfbZkWdnWx4ddNc74QKHq32vnoKUuqxS0z6Y7u6clVUWZfOFtb00CAACUzpvmAJE4FAwg/DjTR8cBIvDkAIg01vTRcYDwfHQcwP45gP1zAPvnAPbPAQAwPzc/BzA/B4hvrOn9doDwvN8OAAAkX02uOMxhIelqwQcfmbIDUJIlS5cHU2bOC0aMm+ag1r/SXj87p0Oe96Ue0BzG5Mdfdo31F1164yNB9z4HG3dLST8ws6Fpn5Qvd6y/5r/z7DW1ud6SJEVr3yOHmvsotW203QGx/4aKPzmlpPWYl15737WSvqU33/24bOvkV46eaGygUG2c6xu8VNc1aKnLKuFdv1G9e1pSdZQrvOmtSQAAgNJ54xwgEoeCAYQfZ/roOEAEnhwAkcaaPjoOEJ6PjgPYPwewfw5g/xzA/jkAAObn5ucA5ucA8Y01vd8OEJ732wEAgOTL5IoTHRaSnn6wxYCgtbXNlB2AdbJs+apgxnNvBCPHT3dAa4guHzs12GSHgzrkmf/C3NdivReWr1gVXOU+0Fra++fnG3dLiT8sszisatY88sV9M7niMtddkqTw1W25d3DBdQ+Y/yiV9Rnwi9h/Q9ktm4NVq1av85rMx58uda2kb+mZue+Ubb189Pj7jA0Uuge7dQ9a6rJKeHPW1Kt+T/e0pGrodW9NAgAAlM6b5wCROBQMIPw400fHASLw5ACINNb00XGA8Hx0HMD+OYD9cwD75wD2zwEAMD83PwcwPweIb6zp/XaA8LzfDgAAJF9NvviMg0LS03bFI0zXAYhs5arVwcwX5gdXT5jhYNYInXDeTR3yvN+l+djY74nnWt5xjfUXDbnyrqDL5v2Nu6Uklyv8obFx0N9V07pHbb6ww5r/7o9cf0mSwtf/8HPNgZTKDjj2orL8hp6f++o6r8m0tQXW6KRv6eEnXinfG8J3PWxcoNBdtnFj0FKXVQr6RY9t3NOSUl8mV3jVW5MAAACl8wY6QCQOBQMIP8700XGACDw5ACKNNX10HCDCPynw5ACwfw5g/xzA/jmA/XMAAMzPzc8BzM8BYhtrer8dIDzvtwMAAMmXyRcWOSwkPR1w5GDTdQBCa21tC16ctyAYNfFJB7KuQ7sddFqHPO9H3nhH7PfGzffOco31F+3YfKIxt5Ts3q+t/3FNNa59dG5s6lqTK851D0iSFK4Neg8IfnP1feZBSl0n/WZMWX5Dv5twf0nrMnc8/LzrJX1Dtz34XNnWz+9+cJpxgUI3qOf2QUtdViloctfu7mlJVVDhZW9NAgAAlM6b6ACROBQMIPw400fHASLw5ACINNb00XGA8Hx0HMD+OYD9cwD75wD2zwEAMD83PwcwPweIb6zp/XaA8LzfDgAAJFuXXj/+Pw4JSVe/HDLCdB2Av6qtLQjmzV8Y3HTXUw5iXccuvfGRoG7Lvcv+rO/SuFfwwcJPYr0/3n5/kWusv+jkoWONt6Uklyuuqs019anmNZDaHs3fzeQLU9wPkiSFq/DTs82FlLqGjX4oqG1oiv33c+LZl5e0NjPjuTdcL+kbuva2x8u2jv7wH542JlDotqnfPWipyyol/bDXj9zXktK+ZzDXm5MAAACl80Y6QCQOBQMIP8700XGACDw5ACKNNX10HCA8Hx0HsH8OYP8cwP45gP1zAADMz83PAczPAeIba3q/HSA877cDAADJ1qmxb4ODQtLV5ddPMF0H4Fu9+e4nwbj7nnEAa4kdeeY1HfKsP+joX8d+j0yaNtc11p81fOzUIL/rQONtKcFlcsWTrIKst16PHs1/n8kXb3RPSJL01+vcu39w7sh7zYmUuup/+NPYfz87Nx9T0trMa2995FpJ39LSL1aUZS19xlMvGBMo/NgpXwhmZTcMWuqySkHDNuntvpaU9ubYMQAAACidt9IBInEoGED4caaPjgNE4MkBEGms6aPjAOH56DiA/XMA++cA9s8B7J8DAGB+bn4OYH4OEN9Y0/vtAOF5vx0AAEi2mnxxgENC0tXvJ001XQdgrd7/aHFwx8PPO3S1ndp+wPGpfNYvXbYiGHnLNNdYf9Zhv7zcWFtKdr9fb7311rcK8pX1kFzhuJp8odW9IUnSt7fnIWeaEyl1fXlfx/3b6dzYFCz+fOk6r88sWbrctZK+pXfe/7Qsa+qznm8xHlCkbt5ws6ClLqsUNCvbLcjm+rmvJaW2TK7wvJ0CAACA0nk7HSASh4IBhB9n+ug4QASeHACRxpo+Og4Qno+OA9g/B7B/DmD/HMD+OQAA5ufm5wDm5wDxjTW93w4QnvfbAQCAZMvkiic5KCRdfXm4GwB81aLPvggmTZvrsNV27ILrHgg6N+5V9uf8JtvvHyxbviLW++WpF99yjfVnDbvh4WCjbfc31pYSW+Hl726x+79aAflLtbniAZl8YYV7RJKkb+7Lue+vr7jT3EipauCpI8ry+5nx1AslrdHccMeTrpf0Db3wyntlWVt/seV14wFFavAmWwYtdVmlpJ/03MF9LSm1ZfKF5+wSAAAAlM5b6gCROBQMIPw400fHASLw5ACINNb00XGA8Hx0HMD+OYD9cwD75wD2zwEAMD83PwcwPweIb6zp/XaA8LzfDgAAJFtNvnClg0LS1YcfLTJdB+CPPv9iRfDIk/OCK8dNc9BqO/eTE3/bIc/5k4eMiPWeaWsLghvvfMo11p/Vf9AQ42wpuX3eub5fT6sf3yyTK25Tkyt85F6RJOmb2/WAU8yNlKrOumxiWX47I0ZPLGmd5r6pL7le0jf02FOvlmWNfd4bbxsLKFL79twpaKnLKiXdsmEv97Wk1JbJF2faIQAAACidt9UBInEoGED4caaPjgNE4MkBEGms6aPjAOH56DiA/XMA++cA9s8B7J8DAGB+bn4OYH4OEN9Y0/vtAOF5vx0AAEi2TK54v4NC0lPXrZqDtrY203WAKrdy5ergyefnB1eNn+6A1ZjqvefhHfKsf/LZl2K9d95892PXV3/WuVfeHXTZvL+xtpTUcoVDrHz8dd/PFXqs+Vu96Z6RJGnt1TY0BWddNtEcSalp+NipQd2We8f+2xl08gUlrdM8Pedt10v6hu6a8mJZ1trnv/O+sYAiVV//46ClLquUNHdNm9fv4d6WlNam2R0AAAAonbfWASJxKBhA+HGmj44DRODJARBprOmj4wDh+eg4gP1zAPvnAPbPAeyfAwBgfm5+DmB+DhDfWNP77QDheb8dAABItpp8scUhIelpx/5HmaoDVLHVrW3Bi/MWBNdPfMLBqjE25Mq7/nigeLmf81v3HRS0tbXFeg/d89gc11h/1k7NJxpnSwktkysMt+oRXpfGvTrV5Iqz3DuSJK29L+cG5khKU1sXj479d7P57oeVtE7z9vuLXCvpG7rprqfKsub+wcJPjAMUueldNw5a6rJKSad338p9LSmdewj54iN2BgAAAErn7XWASBwKBhB+nOmj4wAReHIARBpr+ug4QHg+Og5g/xzA/jmA/XMA++cAAJifm58DmJ8DxDfW9H47QHjebwcAABJt/UyuuMxBIenp4GPOMVUHqEJtbUEwb/7C4Hd3PeVA1TK071FDO+Q5f8nVt8R6Hy1ZujwYMW6aa6w/dfLQscbYUlIPw8wVn+jRo/nvLXtE8589mv8lky/e4x6SJGntnT7sVnMlpaYBh59Xlt/N+x9+vM5rNStXrg5GjHOtpLV15bhpQWtrW+xr74s+XWIMoMhdv1F90FKXVUr6Q3bjoEuu4N6WlMJ9hMIkuwIAAACl8xY7QCQOBQMIP8700XGACDw5ACKNNX10HCA8Hx0HsH8OYP8cwP45gP1zAADMz83PAczPAeIba3q/HSA877cDAADJ1TlfyDgkJGWHmv7mKlN1gCrz1oJFwbj7nnGQahnbdOeflP0ZX9vQFMx/5/1Y76Unnn/T9dWfGj52apDfdaAxtpTICh/U9Nqr1qrHOmpu/k5NrjjSfSRJ0l+2ff/jzJeUmo799aiy/G4mTXmipPWam++d5XpJ39CnS5bFvv7+xbLlxgCK3C+7bx201GWVogq9dnFvS0pfucJdNgQAAABK5012gEgcCgYQfpzpo+MAEXhyAEQaa/roOEB4PjoOYP8cwP45gP1zAPvnAACYn5ufA5ifA8Q31vR+O0B43m8HAACSq1N9v20dEpKurhw90VQdoEosWLg4mPjQ8w5PLXOnXTy+Q57x/Q87Pdb7qbWtLbjhjiddY/2pgaeOML6WknkI5upMvriLFY/SZXKFs9b8TdvcV5Ik/XmnXDjOnEmpaOi1k8rym7ngijElrdk89MQrrpf0Db21YFHs6/CtrW2e/4pcodcuQUtdVinqyo0a3NuSUlcmV7zdTgAAAEDpvNEOEIlDwQDCjzN9dBwgAk8OgEhjTR8dBwjPR8cB7J8D2D8HsH8OYP8cAADzc/NzAPNzgPjGmt5vBwjP++0AAEBy1eT7HeSQkHR194PTTNUBUu6Tz5YGk6bNdWhqB1X46eAOecbffMfkWO+rV99a6PrqTw274eFgo233N76Wkliu32lWO9pPJl/4aU2uuMq9JUnS/2v7/seZNyk1de9zcOy/mf2PGFzSms0Lr7znWknf0Je/j3LYYPP+xgCK1Ea5vsHcumzQotT0fLZrsPGa6+r+lpSu/YTiOLsAAAAApfNmO0AkDgUDCD/O9NFxgAg8OQAijTV9dBwgPB8dB7B/DmD/HMD+OYD9cwAAzM/NzwHMzwHiG2t6vx0gPO+3AwAAyZXJFX/lkJB0NXvOPFN1gJRasnR5MGXmvGDEuGkOTO2gho95LNhwm/3K/nzvtvU+weLPl8Z6f935yAuusf5U/8PPNbaWknkA5p1rpvrrW+1o57WTfKGQyRW+cI9JkvT/On3YreZOSkW77Hdy7L+X7jscELS1ta3zms2HHy9xraRvaNozr5dlbX7jbffz/FfkHuraPWipyypF/bzH9u5tSakqky/eaAcAAACgdN5wB4jEoWAA4ceZPjoOEIEnB0CksaaPjgOE56PjAPbPAeyfA9g/B7B/DgCA+bn5OYD5OUB8Y03vtwOE5/12AAAguWpyxVEOCUlXHy/6zFQdIGWWrVgVzHjujWDk+OkOSu3gjhsyukOe70edPizWe+zTJcuCEeNcX/1PQ668K+jcu7+xtZS0wy9zxXkb1Bf/zUpHPGrzhR0y+cIi95okSf/TjnufYP6kVHTgcReX5Tfz2pvvrvO6TWtrW3CVdUFprd079aWyrNFvtvPBnv+K3IiNGoKWuqxS1IQNe7m3JaWswnVW/wEAAErnTXeASBwKBhB+nOmj4wAReHIARBpr+ug4QHg+Og5g/xzA/jmA/XMA++cAAJifm58DmJ8DxDfW9H47QHjebwcAAJIrky886oCQ9LTxtvuZpgOkyKrVrcGsOW8H1972uANSK6Qf7vfLDnnGPzrj2VjvtenPvO766k/t1HyisbWUsDK54rJOjX0brHLEq3N9v56ZfPEd95wkSf/TGZfeZg6lxHfi+TeV5fdy5wN/KGnt5rYHZ7te0lq6+d5ZZVmr7737Tz37FbljemwXtNRllaLmrql3/R7ub0kpqjDCyj8AAEDpvPEOEIlDwQDCjzN9dBwgAk8OgEhjTR8dBwjPR8cB7J8D2D8HsH8OYP8cAADzc/NzAPNzgPjGmt5vBwjP++0AAEBy1eSK8x0Qkp52aT7WNB0gBVrb2oIX5y0IbrjjSQejVlDDRj8UbLD5gLI/3xt2PTRY3doa2/325f/v629/wjXWHzt56FjjaimBZeqLP7HCUR7fqy/+oCZfeNl9J0lSMdhlv5PNo5T4Lr5+clDb0BT77+W8395Y0vrNH2a95npJa+mq8dPLsma/Tb/DPfsVuR/1+lHQUpdVyvpl963d35LSs7eQK1xq1R8AAKB03nwHiMShYADhx5k+Og4QgScHQKSxpo+OA4Tno+MA9s8B7J8D2D8HsH8OAID5ufk5gPk5QHxjTe+3A4Tn/XYAACCZGhsH/V1NrrDaISHp6SfHnWuaDpBwr761MBhz99MORK3ABp0+skOe7+ddNjrWe+7lNz50ffXHho+dGuR3G2hcLSXv0MurrHCU139t2u97a/72z7j/JEnVXm1DU3D25b83n1Li67njIbH/Xg44crD1GymmPv9iRezr9jsNONqzX5GryxWCOXVdg5a6rFLUg926u78lpakLrfgDAACUztvvAJE4FAwg/DjTR8cBIvDkAIg01vTRcYDwfHQcwP45gP1zAPvnAPbPAQAwPzc/BzA/B4hvrOn9doDwvN8OAAAkU+fGpq4OB0lXv7rwWtN0gIRasPCz4PbJsx2CWsFtUzymQ57vc+e9Geu9577T/+2wU64wppYSViZfnNmt2+7/YIWj/P6zR/O/rLkGD7oPJUnV3q4HnmY+pcS3874nxf5b2XTHg0pav/n406WulfQNvfvBp7Gv3/9wn+M897VO3b1hj6ClLquUtWOv3dzfktJRrjjEaj8AAEDpvAUPEIlDwQDCjzN9dBwgAk8OgEhjTR8dBwjPR8cB7J8D2D8HsH8OYP8cAADzc/NzAPNzgPjGmt5vBwjP++0AAEAyZXKFHzogJF1dM+ZO03SAhPnyQNxJ0+Y6/LTCG3rN/UHnhqayP9v3OPDE2O8/11dfNmz0w8FG2x1gTC0lqEy+8PH3NutXZ3Wj43Trtvs/rLkWt7ofJUnV3Jdz5XOuuMu8SonuwGMvKsvv5b33P1rnNZy2trbgqvHTXS9pLb302vuxr+PvccAJnvtapy7apHfQUpdVyhqyyRbub0np2GfIFc6y0g8AAFA6b8MDROJQMIDw40wfHQeIwJMDINJY00fHAcLz0XEA++cA9s8B7J8D2D8HAMD83PwcwPwcIL6xpvfbAcLzfjsAAJBMNfWFnzkgJF3d/8gTpukACbF46fJgysx5wYhx0xx8moAOOv6SDnm2jxp3T6z34WNPver66o/1P/xc42kpURVaa/P9dreyUQGam7+TyRWuck9Kkqq5PQ8507xKie6E824qy2/lgUefLGkdZ8IDz7le0lp6Yvabsa/n9z34ZM98rVMDe+4QtNRllbJmdN046JIruMclJb9c4VSL/AAAAKXzVjxAJA4FAwg/zvTRcYAIPDkAIo01fXQcIDwfHQewfw5g/xzA/jmA/XMAAMzPzc8BzM8B4htrer8dIDzvtwMAAMmUyRfPd0BIuprz8hum6QAVbtnyVcGM594IRt4y3YGnCSq/68CyP9c32Lx/8NEnn8V2L65a3Rpce9vjrq+Cc0feE3RZc78ZT0vJKZMr/sqqRmVZc11OcW9Kkqq1zo17rZlX3Gt+pcR28fWTg9qGpth/K8OuGlfSWs6UmfNcL2ktPTC9JfZ1/b0OPdUzX+vUdpvtFrTUZZXCCr12cY9LSv5eQ75wgtV9AACA0nk7HiASh4IBhB9n+ug4QASeHACRxpo+Og4Qno+OA9g/B7B/DmD/HMD+OQAA5ufm5wDm5wDxjTW93w4QnvfbAQCAZKrJFcc5ICRdLV6y1DQdoEKtXLU6mDXn7eCaCY876DRhnT38jg55rh92wvmx3pNzXl3g+uqP7bTPicbSUqIOuSzes956g//GqkblyTQUjqrJF1rdp5KkaqzfoWeZXynR9dzx4Nh/Jz/9RWlrPS+88p5rJa2lWyc9G/v6fvOgMz3vtU51zheCZ+q6BS11WaWs4Rs3uMclJb5O+X5HW9kHAAAonbfkAaJtvXlyAIQeZ/roOEAEnhwAkcaaPjoOEJ6PjgPYPwewfw5g/xzA/jkAAObn5ucA5ucA8Y01vd8OEJ732wEAgGTK5AtPOiAkPfXoc6ApOkAFam1tC16ctyAYNfFJB5wmtAGHn9shz/b7H3k81ntz/KRnXV8FJw8daywtJalc4c3M5k3/bkWjctXmigdkcoWV7ldJUrXVZfP+wW+uvs88S4lt531Piv13ssUeA0tay1mwcLFrJa2la297PPUO7qUAACAASURBVPZ1/v2PGOx5r3Xu1g17BS11WaWsZ+q6BdlcP/e4pGTX0DTIqj4AAEDpvC0PEIlDwQDCjzN9dBwgAk8OgEhjTR8dBwjPR8cB7J8D2D8HsH8OYP8cAADzc/NzAPNzgPjGmt5vBwjP++0AAEAy1eQLHzogJD3tvv8JpugAFWbe/IXBTXc/5WDTBHf52KlB9x0OKvtzveeOBwYrVqyM7d784KMlrq+C4Wvu7/yuA42lpYSUyRWXdWpoarSaUfky+eIuNbniYvetJKnaahp4jrmWEtuBx15Ult/Jx4s+W+f1nFWrW4MR46a5XtJaWrZiVaxr/Qcfc45nvda5czbZMmipyyqFHdxzR/e4pGTvO+QLh1rRBwAAKJ035gEicSgYQPhxpo+OA0TgyQEQaazpo+MA4fnoOID9cwD75wD2zwHsnwMAYH5ufg5gfg4Q31jT++0A4Xm/HQAASJ7vbfaj/8/hIOlq4IlDTdEBKsRbCxYF4+9/1mGmKejkoWM75Ll+5tBrYr1HH3nyFddXwWGnXGEcLSWoTrniYVYzkqM213fzmnzhQ/euJKma2qD3gGDotZPMt5TITjjvprL8TqY+8VxJazpj73na9ZLW0gcfLYl1PfXQ48/zrNc6d3DPHYOWuqxS2OiNcu5xVU+5wtNretPfIl3V1hcOtJoPAABQOm/OA0TiUDCA8ONMHx0HiMCTAyDSWNNHxwHC89FxAPvnAPbPAeyfA9g/BwDA/Nz8HMD8HCC+sab32wHC8347AACQPLWb7bWpw0HS1TmXjDJFB+hgH368JPj9wy84xDRF7XnImR3yXJ89Z15s9+nyFauCq2+d4fpWecNGPxxstN0BxtFSQsrkC9dayUie7+ebutfkivPdw5KkamrA4eeZcymRXTTqwbL8RkaMnljSus4D01tcL2ktvfLmh7Gu/f/spKGe81rntqzfPWipyyqFzVnTprkfu89VLb1e09Bvq0y+sMLfIkXlCj7ADAAA0A68QQ8QiTUpgPDjTB8dB4jAkwMg0ljTR8cBwvPRcQD75wD2zwHsnwPYPwcAwPzc/BzA/BwgvrGm99sBwvN+OwAAkDyZfLGfw0HS1ahx95iiA3SQxUuXB1NmzgtGjHN4aZq67KYpQXar5rI/03fsf1Ss9+vsl991fRUMOPxcY2gpMYdaFmdt0KfPP1rJSKbv5/tvkMkVXnUvS5KqpewWzcHF108271Ii69Hn4Nh/I0eeenFJ6zqz5rztWklr6ek1v404ffnb9ZzXula7plnZbkFLXVYp7Kge27nPVSXr1IXV3brt/g+ZXPFEf4/01CnXr2gVHwAAoHTepAeIxKFgAOHHmT46DhCBJwdApLGmj44DhOej4wD2zwHsnwPYPwewfw4AgPm5+TmA+TlAfGNN77cDhOf9dgAAIHlqcoVjHQ6SriZPfcoUHaDMli1fFcx47o1g5C3THVyawo4efF2HPNNH3HB7rPftzffOcn2rvHNH3hN02by/MbSUgDL54iddevfPWsVItg023/P7mXzhBfe0JKla2u+YC829lMh23ufk2H8fO+x1ZEnrOvPf+8S1ktbSo0+9Guua6jFnXOIZr5K6dcNeQUtdVils4oabusdVNXVq7LvJeuutt34mV7zd3yMl5Zr2sIIPAABQOm/UA0TiUDCA8ONMHx0HiMCTAyDSWNNHxwHC89FxAPvnAPbPAeyfA9g/BwDA/Nz8HMD8HCC+sab32wHC8347AACQPJlc4VKHg6SrlnnzTdEBymTV6tZg1py3g2smPO7A0hS3U/OJZX+ed2ncK3jv/Y9iu3ff/eBT11bBTvucZPwsJaJCa0194cdWMNLhvzbt971MrvC8+1qSVA1ttO3+wWW/m2L+pcR1wLEXx/776NzYFHy+dNk6r+18sWylayWtpXsemxPrnsAJg4d7xqukzt9k86ClLquUtkX9Hu5zVUWZfLHfl2udG9QX/y2TK7zmb5KKa7qL1XsAAIDSebMeIBKHggGEH2f66DhABJ4cAJHGmj46DhCej44D2D8HsH8OYP8cwP45AADm5+bnAObnAPGNNb3fDhCe99sBAIDkqckXf+9wkHRVyiGMAITT2tYWvDhvQTDqjicdVJryLhr1YNC5d/+yP8/3P2JwrPfwg9NbXN8q7+ShY42dpcRUOMfqRbpkNm/695pc4Wn3tiSpGjrslCvMwZS4jh9yY1l+HzOffamk9Z0brE1Kf9G4+56JdV31l0NGeL6rpA7t2SdoqcsqpZ3SfRv3uaqiTL5wwv9d6+zU2Lchkysu83dJdp0aittbuQcAACidN+wBInEoGED4caaPjgNE4MkBEGms6aPjAOH56DiA/XMA++cA9s8B7J8DAGB+bn4OYH4OEN9Y0/vtAOF5vx0AAEieTK442+Eg6al+l0NMzwFi9taCRcHN985yQGmVdNgvL++QZ/rt906J7R5etnxlMHL8dNe3ihs+dmqQ322g8bOUiAoPrLfe4L+xepE+G9QX/60mV5jhHpckpb1eu/wkuHzNHMRcTEnqN1ffX5bfx6hb7ilpjefuR190vaSvde1tj8e6P3DqeSM931VS2222W9BSl1VKu69bD/e5qmXd+sqvrnXW1Bd+5m+S7DrnC72t2gMAAJTOW/YAkTgUDCD8ONNHxwEi8OQAiDTW9NFxgPB8dBzA/jmA/XMA++cA9s8BADA/Nz8HMD8HiG+s6f12gPC83w4AACRPTa642OEg6anvwSebngPEZMHCxcHEybMdTFplbdn3yLI/zzfedr/gi2XLY7uXZ730tmtb5Q08ZYSxs5SEcsX5nRr7/oeVi/T6zx7N/5LJFx51v0uS0t6xv77BXEyJq9vW+8X+2zjx7MtLWuN5fPabrpW0llauXB3b2upp54/0bFdJdVnT7Gy3oKUuq5S2zWa7uddVDU3++lpnJle4yt8luXWu79fTij0AAEDpvG0PEIlDwQDCjzN9dBwgAk8OgEhjTR8dBwjPR8cB7J8D2D8HsH8OYP8cAADzc/NzAPNzgPjGmt5vBwjP++0AAECyfHk4t4NB0tVRp11seg7Qzj75bGkwadpch5FWYeeOvCeobWgq+/P8hMHDY72nx9z9tOtbxV0y+pFgo+0OMHaWKrxMvri8tr5pCysXVbE28881+cID7ntJUprbsu+R5mNKXNsUj4n9t7HHgSeWtMYzb/5C10paSx9/ujS2tdUzfnO1Z7tK7vfdNg1a6rJKaad139p9riqo8MbX1zl79Gj++zX/s2n+Nsnse5v1q7NaDwAAUDpv3QNE4lAwgPDjTB8dB4jAkwMg0ljTR8cBwvPRcQD75wD2zwHsnwPYPwcAwPzc/BzA/BwgvrGm99sBwvN+OwAAkCw1jYUtHQySri64YozpOUA7WbJ0eTBl5rxgxLhpDiKt0vY75sIOeZ4//vSLsd3Xby1Y5NpWefseOdS4WUpGh1u1qB7/c+Bs4Q73vSQpzZ160XhzMiWqpoHnxP676Lb1PkFra9s6r/MsWvyFayWtpfnvfRLb+uqZQ6/xXFfJXbxJ76ClLquUNqlrD/e5qqBC6wZ9+vzj19c5/2vTft/L5Atv+/skry+vnZV6AACA0nn7HiASh4IBhB9n+ug4QASeHACRxpo+Og4Qno+OA9g/B7B/DmD/HMD+OQAA5ufm5wDm5wDxjTW93w4QnvfbAQCAZOmUa9rfwSDp6uY7JpueA5Ro5crVwZPPzw+uGj/dAaRV3ma7/LTsz/It9xxY0mHKf819U19ybau4odfcH/xgi72Nm6UKL5MvjLViUX0aGwf9XSZfnOA3IElKazvtc5J5mRLVoNOvKstv44233itpreeaCTNcL+lrzXl1QWzrq7+68FrPdZXc4T22D1rqskpx2262u3tdqe/7+abua30XrbFvQyZX+MLfKFl9d4vd/9UqPQAAQOm8hQ8QiUPBAMKPM310HCACTw6ASGNNHx0HCM9HxwHsnwPYPwewfw5g/xwAAPNz83MA83OA+Maa3m8HCM/77QAAQLJk8oUzHAySrqbPfN70HGAdrW5tC16ctyC4/vYnHDyq4MxLJnTIs/yiK8fGdo8v/WJFcOUt01zfKm7PQ840ZpYqvEyuOLtTY99/tmJRpfr0+dtMvjjGb0GSlMZqG5qCISPuMjdTctaGLr2tLL+N+x95vKT1ntsnz3a9pK/1xPNvxrbGOvii6zzXVXI7b7Zr0FKXVYo7vfvW7nWlfy27oanvt7yPdqi/UbJqbBz0dxboAQAASudtfIBIHAoGEH6c6aPjABF4cgBEGmv66DhAeD46DmD/HMD+OYD9cwD75wAAmJ+bnwOYnwPEN9b0fjtAeN5vBwAAkqUmV7zewSDp6u33PjQ9B4iorS0I5s1fGPzurqccOKo/VRx4Toc8y199453Y7vWZL8x3bau4s347Mejc0GTMLFVyueLiTo19N7FaUfXWr8kXRvhNSJLSWN9DB5ufKTH99nePBp0b94r9d3HpNeNLWu957OlXXS/paz30xCuxrbGeffH1nukquR/kC8Gcuq5BS11WKe3Bbt3d60p9tfniMX/lnbTL/Z0SszexyrI8AABA+/BWPkAkDgUDCD/O9NFxgAg8OQAijTV9dBwgPB8dB7B/DmD/HMD+OYD9cwAAzM/NzwHMzwHiG2t6vx0gPO+3AwAAyZLJF6Y4HCQ9bbB5/2B1a6vpOUAEby1YFNxy/zMOGtWfNXzMY8FG2x1Q9md506Gnxnavt7W1BTfeOdP1reK273+cMbNU2bXV5Pv1t1LB/1o/ky9e5nchSUrdGnbvAcEF104yR1Niqv/RYbH/Ln7+ywtLWvOZ8+r7rpX0tX7/8AuxrbP+etgoz3S1S/d16xG01GWV4rap3929rnSXKw771hXOPn3+1ntpibmWiy3JAwAAtA9v5gNE4lAwgPDjTB8dB4jAkwMg0ljTR8cBwvPRcQD75wD2zwHsnwPYPwcAwPzc/BzA/BwgvrGm99sBwvN+OwAAkCw1ueJ8h4Okp20LPzc1Bwjpg4+W/PFgTQeMam2dcO7vOuRZPub2B2K7519/+yPXtoo7eehY42Wpwsvki+dbpWAt6zZD/D4kSWlr36OGmqcpMf3owFNj/03sNODoktZ8Pvx4iWslfa0xdz8d2zrrkEtv8DxXu/TbjRuDlrqsUtxp3bdyryvda9q54sS/tr6Z2bzp39f8777u71XxvW81HgAAoH14Qx8gEoeCAYQfZ/roOEAEnhwAkcaaPjoOEJ6PjgPYPwewfw5g/xzA/jkAAObn5ucA5ucA8Y01vd8OEJ732wEAgOTo1m33f6jJF1odDJKe9j9isKk5wF+xaPEXwaRpcx0sqm9t1wNPK/tzPLtlc/DZ4s9ju/fvnvKia1ulDR87NcjvOtB4Warsw0cfXq+5+TtWKlibmlxxiN+JJClNbbjNfsGlNz5ivqZEdNDxl8T+m9igd/9gxYqV67zms3p1azBi3DTXS/pKV42fHts663mXjfY8V7t0dI/tgpa6rFLcg926u9eV8grPhlnf7NTQ1JjJFb7w96roa/mGlXgAAID24U19gEgcCgYQfpzpo+MAEXhyAEQaa/roOEB4PjoOYP8cwP45gP1zAPvnAACYn5ufA5ifA8Q31vR+O0B43m8HAACSI9OrsLFDQdLVqeeNNDUH+AbLlq8MZjz3RjDylukOFdW39uXB3nVb7l325/gRp1wU2/2/eOlyhytXcT877UpjZamCy+SKC7o07tXJKgXfZs29corfiyQpTR168nDzNSWiE8+/qSy/iTkvv1HS2s+Yu592vaSv9cWylbGstZ732xs9y9Uu7d7rh0FLXVYpb9v63dzvSvHaduHTsOubtfWFA/3NKrhc4SWr8AAAAO3DG/sAkTgUDCD8ONNHxwEi8OQAiDTW9NFxgPB8dBzA/jmA/XMA++cA9s8BADA/Nz8HMD8HiG+s6f12gPC83w4AACRHbb7f7g4GSVcjbrjd1Bzga1auWh3MmvN2cM2EGQ4SVaiOOPPqDnmOP/yHp2P7Hcx47g3Xtkq79MZHgk12OMhYWarcQ0dXdqrvt60VCsLI1BdO9ruRJKWlnjv9dzB87FTzNlV8Q6+dVJbfxO33Tilp7ee+qS+5XtLX+vDjJbGstf7m8ps8y9Uudcv3C16q6xq01GWV4k7vvpX7Xamutkfzd0Ovb+aKl/ibVWi54iwr8AAAAO3Dm/sAkTgUDCD8ONNHxwEi8OQAiDTW9NFxgPB8dBzA/jmA/XMA++cA9s8BADA/Nz8HMD8HiG+s6f12gPC83w4AACRHJlc80sEg6eruB6eZmgP8r9bWtuDFeQuCUROfdICoIrV9/+PL/gzP/fC/g1WrV8fyW1i95rcwauITrm2Vtv8xFxonS5VcQ/F4qxNEUZMrnu63I0lKS0cPvt68TYloo233j/33cN5vbyxp/eeJ2W+6VtLXeu3tj2JZbx16xU2e42q3JnftHrTUZZXivrzG7nWluU6NfRtCL2726fO3a/5vJvu7VWC5wh+svgMAALQPb/ADROJQMIDw40wfHQeIwJMDINJY00fHAcLz0XEA++cA9s8B7J8D2D8HAMD83PwcwPwcIL6xpvfbAcLzfjsAAJAcNbniMAeDpKvZL71qag6wxhvvfByMuftpB4cqchdcOyno3LhX2Z/hZ110XWy/h1fe/NC1reL7ObtFs3GyVLmHVI63MsG6yOQKg/2GJElpaPM9f27upkS03V7Hxf57OOTYISWt/7xs/Uf6i2a//G4s660XXDHGc1zt1pUb54OWuqxS3nab7eZ+V5obEGVts7ZH83czucKr/m4V14NW3gEAANqHt/gBInEoGED4caaPjgNE4MkBEGms6aPjAOH56DiA/XMA++cA9s8B7J8DAGB+bn4OYH4OEN9Y0/vtAOF5vx0AAEiOmnzhDoeCpKtPP1tiag5UtXc++DSY8MBzDgzVOnfICZd1yDP8+bmvxva7uOOh513bKq3vT84yRpYqtsLL391i93+1MsE6r+nkikP8jiRJaej0Ybeav6ni6z9oSOy/hS32GFjS+s/CRZ+7VtLXmv7M67Gst54//Hee4Wq3Tuy+TdBSl1XKO6P7Vu53pbZMrnhi1LXNTo19N8nkCp/6+1VUv7fqDgAA0D68zQ8QiUPBAMKPM310HCACTw6ASGNNHx0HCM9HxwHsnwPYPwewfw5g/xwAAPNz83MA83OA+Maa3m8HCM/77QAAQHJkcsXZDgVJT913OMC0HKhaHy36PLj70RcdFKqSa9zj8LI/w3cacHRsv41PPvvCda3Szr78zqBz417GyVJl9nnn+n49rUpQqppc4QK/J0lS0tv1wNPM4VTxHX7GVbH/FmobmoLFS5au8xrQ6tWtwYhx01wv6Ss9MG1uLGuu51022jNc7Vah1y5BS11WKe+hrt3d70pvueIV6/TOWr7YryZfaPU3rJjrOM6KOwAAQPvwVj9AJA4FAwg/zvTRcYAIPDkAIo01fXQcIDwfHQewfw5g/xzA/jmA/XMAAMzPzc8BzM8B4htrer8dIDzvtwMAAMlRkysudjBIetp9/xNMy4Gq8/kXK4IpM+c5MFbt0q+v+H2HPMOvGHVbbL+RP8x6zbWt0voM+IUxslSxh1MWDrEiQXvJ5ApD/a4kSUmuc+/+wQXXTjKPU0V3xrBby/J7eOq5uSWtA425+2nXS/pKEyfPjmXN9ZxLRnmGq93qXt83aKnLqgrabrPd3PNK63r3Xev+3lq/0/wNK+U6Fq+32g4AANA+vN0PEIlDwQDCjzN9dBwgAk8OgEhjTR8dBwjPR8cB7J8D2D8HsH8OYP8cAADzc/NzAPNzgPjGmt5vBwjP++0AAEAy/Nem/b7nUJB0NejkC0zLgaqxctXqYNact4OrJ8xwOKjarX2OHFr253dtQ1Pw1rsfxPI7WbW6Nbjutsdd2yrslxeMMz6WKrRMrjDcigTtbP2aXPFyvy9JUpLb7+gLzeVU0V164yN/XMOJ+7dw022TSloLum/qS66X9JXG3P10LOuuZ198vee32rVpXTcKWuqySnmndd/a/a609kwpa5uZfGGsv2EFlCteYakdAACgfXjLHyASh4IBhB9n+ug4QASeHACRxpo+Og4Qno+OA9g/B7B/DmD/HMD+OQAA5ufm5wDm5wDxjTW93w4QnvfbAQCAZKhp6LeVQ0HS1bmXjTYtB1KvtbUteHHegmDUxCccCqp27fKxU4OeOx5S9ud386AzY/u9zH3tfde2Su/l3rsPMj6WKrBMrvhEjx7Nf29FghisX5MrjvQ7kyQltY23PzAYPuYxczpVdD13PDj238KZQ68paS3o8dlvulbSV7p6woxY1l3Puug6z2+1a7/bqD5oqcsq5d29YQ/3u9JZrriwlIXN2q2a/6kmV3ja37KjK1xkmR0AAKB9eNsfIBKHggGEH2f66DhABJ4cAJHGmj46DhCej44D2D8HsH8OYP8cwP45AADm5+bnAObnAPGNNb3fDhCe99sBAIBkqK0vHOhAkHR14633m5YDqfbWgkXBzffOchioYunUi27pkOf3LXc+FNtvZsIDz7m2VdjPz7ja2FiqwDL5wsffqy/+wGoEMVq/Jlcc6fcmSUpqR551rTmdKrodBvwi9t/B3j87o6S1oJff/NC1kr7WylWr233d9cyh13h2q107u/uWQUtdVlVQ7/o93PNKY221WzX/UykLm10a9+qUyRff8bfs0H5tiR0AAKB9eOMfIBKHggGEH2f66DhABJ4cAJHGmj46DhCej44D2D8HsH8OYP8cwP45AADm5+bnAObnAPGNNb3fDhCe99sBAIBkyOSKv3IgSLp6dMYzpuVAKr3/0eJg4kPPOwBUsVb46dllf3Z33ao5WPz50lh+NwsXfe66VmGX3TQl6NHnYGNjqeIqtHbK9fuRlQjiN/hv1txzo/3mJElJbMu+R5jXqaIbcPi5sf8ONtv54NLWgz6xHiR9vU+XLGv3tdfTf3OVZ7fatf/uuUPQUpdVFXR0j+3c80pltfl+3drhPbZtMvnicn/PDirX7zTr6wAAAO3Dm/8AkTgUDCD8ONNHxwEi8OQAiDTW9NFxgPB8dBzA/jmA/XMA++cA9s8BADA/Nz8HMD8HiG+s6f12gPC83w4AACRDTb5wg0NB0tXr8981LQdSZfHny4PJM1528Kdib/iYx4KNtjug7M/uI0+9OLbfz5SZ81zbKuzA4y42LpYqsEy+cKZVCMqmufk7mVzhJr89SVISO/OSCeZ2qtgGnX5VWX4Hn3y6eJ3Xg1avbg1GjJvmeklfacHCz9p97fWUc6/03Fa7tv1muwUtdVlVQeM27OWeVzqrL+7YLu+y5QqH+Ht2ULnCcRbXAQAA2od/AQAQiUPBAMKPM310HCACTw6ASGNNHx0HCM9HxwHsnwPYPwewfw5g/xwAAPNz83MA83OA+Maa3m8HCM/77QAAQDJkcsXHHAqSnjo3NgUrVqw0LQdSYdmKVcGM594IRt4y3aGfKksnnPu7Dnl+P/yHp2P5Da1ctTq4ZsIM17bKuvD6B4PsVs3GxlKFlckX7l1vvcF/YxWCsmpu/s6ae2+s36AkKWntcfDp5neq2M4YNqEsv4OZz75U0rrQmLufdr2kr/TaWx+1+/rryUNGeG6rXeuSLwQv1nUNWuqySnlzsl2D7vV93fdKYf0Oar/32QqX+nt2QA1NgyysAwAAtA//EgAgEoeCAYQfZ/roOEAEnhwAkcaaPjoOEJ6PjgPYPwewfw5g/xzA/jkAAObn5ucA5ucA8Y01vd8OEJ732wEAgGTI5IvvOBQkPW2xx0BTciDxVre2Bc+1vBtce9vjDvtUWdv1wFPL/uyu3+WQYNWq1bH8ll545T3XtQorHHa2cbFUaeWK8zs19v0PKxB0iObm76y5B8f5LUqSklSXzfsHF1z3gDmeKrJLRj8S1DY0xf47uPmOySWtC9079SXXS/pKX66VtrcTz77cc1vt3n3degQtdVlVQT/puYN7XilcC+93Wnuua2byhXv9Xctdv4MsqgMAALQP/yIAIBKHggGEH2f66DhABJ4cAJHGmj46DhCej44D2D8HsH8OYP8cwP45AADm5+bnAObnAPGNNb3fDhCe99sBAIDKt0GfPv9Yky+0OhAkPQ0YeLopOZBYbW1BMG/+wuDGO59yyKfK3qU3PhJkt2gu+7P7rIuui+03Nf7+Z13bKmvIiLuCzo17GRdLFVQmX1zeOV/obQWCjtTYOOjvanLFO/0mJUlJ6sBjLzLPU8XWo8/Bsf8Gzr1sdEnrQo/PftO1kr7Sk8/Pb/f1118M/q1nttq9KzZuCFrqsqqCrt0o755XCiuMaM91zS69fvx/MvniK/6uZW2AFXUAAID24V8GAETiUDCA8ONMHx0HiMCTAyDSWNNHxwHC89FxAPvnAPbPAeyfA9g/BwDA/Nz8HMD8HCC+sab32wHC8347AABQ+b6fb+ruMJB0deLZl5uSA4n01oJFwfj7n3W4pzqsI8+6tkOe3bNfejWW39SChYtd1ypsp31OMiaWKq2GpkFWH6gEPXo0/31NrnCX36UkKSltssNBwfAxj5nrqSLbfsDxsf8GDj3+vJLWhl5+40PXSvpKU2bOa/c12ON+dZlnttp/v7/7NkFLXVZV0OxstyCb6+e+V7rKFe9s73XNTK/Cxpl8YZG/b3mqbSjuZjUdAACgffjXAQCROBQMIPw400fHASLw5ACINNb00XGA8Hx0HMD+OYD9cwD75wD2zwEAMD83PwcwPweIb6zp/XaA8LzfDgAAVL6a+sKPHQiSri67drwpOZAoH3+6NJg0ba5DPdXh7dh8Ytmf2zv2Pyq239bkx192XausUy+6xXhYqrAy+eKNVh6oJBv06fOPNfnCA36fkqSkdMzZo8z3VJH1P/zc2O//7YpHlLQ2tPCTz10r6Svd+9icdl+DFU/IFwAAIABJREFUPfqMSzyv1e41bbpL0FKXVZW096Y7ue+VrnLFWfG931Zo9Tcuw75GrriNlXQAAID24V8JAETiUDCA8ONMHx0HiMCTAyDSWNNHxwHC89FxAPvnAPbPAeyfA9g/BwDA/Nz8HMD8HCC+sab32wHC8347AABQ+WpyhWMdCJKuJt77qCk5kAiff7EimDJzXjBi3DQHeqrDu3jU5KDL5v3L/ty+/PoJsfy+lq9YFVw1frprW0VdPnZqsGXfI4yHpYo6eLLwfKfGvv9s5YFKU7tV8z9lcsXH/E4lSUlo68JR5nyqyH522pWx3/8b9O4frFixcp3Xh1avbrX2Kn2lCQ881+7rsEeddrHntdq9zer3DFrqsqqSLtm4t/teKavwQWzvuOWLp/j7xl9tY7GXVXQAAID24V8LAETiUDCA8ONMHx0HiMCTAyDSWNNHxwHC89FxAPvnAPbPAeyfA9g/BwDA/Nz8HMD8HCC+sab32wHC8347AABQ+TK5wqUOBElXT89uMSUHKtrKVauDJ5+fH1w1frqDPFUxHXbKFeU/kKyhKXjr3Q9i+Z09O/cd17XKOuqsa42FpUoqV1zcqbHvJlYdqFTf3WL3f83kik/5vUqSktBZv51o3qeK6/Rht5bl/n/5tbdKWiO66e6nXC/pf7vxzpntvg77819e6FmtWHoiu1HQUpdVFfRkdsOgS67gvleaatugT59/jGtdsyZXHOVvHG/fqy/+wAo6AABA+/CvBgAicSgYQPhxpo+OA0TgyQEQaazpo+MA4fnoOID9cwD75wD2zwHsnwMAYH5ufg5gfg4Q31jT++0A4Xm/HQAAqHw1ueKdDgRJVx9+9IkpOVCRWlvbghfnLQhGTXzCAZ6quLYuHFX2Z/bePzsjtt/bzffOcl2rqOE3PRr03PEQY2Gpgg4NrW0o7GXFgUr3/Vzzf9bkCi/5zUqSKr0f/+RX5n6quIaNfjiobWiK/f6/7+EZJa0R3Tv1JddL+t9G3jK93ddhB518gWe1Ymnchr2ClrqsqqQ9ev3Qfa9U1aV3/2xca5q1WzX/UyZfnOnvHF+dGvv+h9VzAACA9uFfDwBE4lAwgPDjTB8dB4jAkwMg0ljTR8cBwvPRcQD75wD2zwHsnwPYPwcAwPzc/BzA/BwgvrGm99sBwvN+OwAAUPky+cILDgRJTxtus2/Q1tZmSg5UnDfe+TgYc/fTDu5URXb+1feV5RDkvzgU8/eTY/m9vf3+Ite1yjrkhMuMhaXK6kKrDSRFbf2Pa9bcs6/73UqSKrkfbLF3cPGoyeZ/qri69zk49vt/+HUTSlonevy5N1wr6SstX7GqXddiB5441LNasXRe9y2ClrqsqqQhm2zpvleq6lTfb9u41zQzucJ7/tbx1K3b7v9g5RwAAKB9+BcEAJE4FAwg/DjTR8cBIvDkAIg01vTRcYDwfHQcwP45gP1zAPvnAPbPAQAwPzc/BzA/B4hvrOn9doDwvN8OAABUvPVrcsWlDgRJTzs3H2M6DlSUBQs/C257cLbDOlXRHXT8JWV/ZnfdqjlYvGRpLL+7SdPmuq5V1JcHy3fdZl9jYalCyuQLj67Xp8/fWm4gSTo3NnV1CK0kqdI79KTh5oCquLbvf3zs9/5xv7qspHWil9/40LWSvtInn7XvmuxPf3G+57RiaWDPHYKWuqyqpEe6buK+V6qqbSjsFfeaZk1Dv60y+eJyf+923+NYYcUcAACg/fiXBACROBQMIPw400fHASLw5ACINNb00XGA8Hx0HMD+OYD9cwD75wD2zwEAMD83PwcwPweIb6zp/XaA8LzfDgAAVLYujXt1ciBIyg4WPf4803GgIiz+fFkwadpch3QqETXs9rOyP7OPOOWiWH57/z979x0mR3kg+hqvz+4er8/Zu+vds1g9I/A0QiAhabpnEBI5iihVjwRDtEDkHGyiCUZgDDJGBBEFIhlEEMmACSYjQOScGkwGkYMBERS/O7DsXp/rQNVMV6d63+f5/XWes7ZV3fOl6qrPvpgbTr/kbtc1Q43d8RfmwVL99Hb/YpSz20Ajah02dkhLIXrf91iSVK8VRm1vDai6q7TDkal/9keP379Pe0XvfvipayX9SW+8/ceK7sdO2Pso47RSac1h64ZyW14ZauX29Xz21TTlitEu1djT7PnPGu/fu8IVovftlgMAAFSOXxQAJOKlYADx55keOg6QgJEDINFc00PHAeLz0HEA5+cAzs8BnJ8DOD8HAMD63PocwPocIL25pvvbAeJzfzsAAFDf+rWPWdkLQZqrn/96muU4UFPz5i8I9z/xajj90nu8oFMN0cSTr67JmH3zzAdT+Q4+9NRrrmuGOur034Ulho8zD5bq4kWTpfmtxWg1Ow00stbC6OE9n+VPfKclSfXazyZfai2oumrb/U9O/XO/7Kpb9G2/dt4C10r6k55/5d2K7sduvdcvjNFKpXxhTHg6v1Qot+WVkQ4ctJLPvpqmXCE6vFp7mi3F6Dj/5pU864hesVMOAABQOX5ZAJCIl4IBxJ9neug4QAJGDoBEc00PHQeIz0PHAZyfAzg/B3B+DuD8HAAA63PrcwDrc4D05prubweIz/3tAABAfWsplsZ7IUhzdfZF11qOAzWxaFEI5ZfeCedceb8Xc6qh2nS3SVUfr9vX3jrMn78gle/h+Vc/6LpmqFFbHGgOLNXNS0JL+9lloCn2itpLa/R8nr/wvZYk1WMbjD/EWlB11X7HXFiVz/47733Ypz2jc668z/WSvumx8uyK7slusevhxmil1k0DBoVyW14Z6cqlh/jcq4mKTqvahmZ393dzhehG/+YVOusoRk/aJQcAAKgcvzAASMRLwQDizzM9dBwgASMHQKK5poeOA8TnoeMAzs8BnJ8DOD8HcH4OAID1ufU5gPU5QHpzTfe3A8Tn/nYAAKC+tRRLE70QpMlerHXnA5bjQNW9/vZH4ZLrH/FCTjVkQ9aaUPXx+rBjz0rlu/jK7A9d0wx1yOTLQmtHlzmwVA8VSlf3LLG/Y5eBZpErlsb0fK7n+35LkuqtJYdvHCafe4s1oeqmo8+4riqf/XseeKJPe0ZX3Py46yV906zHXq7onuy47Q82Riu1zlimI5Tb8spIz7QtFYYUNvLZV1OUK5SuqOZ+5g9WWP+fe/5zn/ZvX4nzjmiWHXIAAIDK8SsDgES8FAwg/jzTQ8cBEjByACSaa3roOEB8HjoO4PwcwPk5gPNzAOfnAABYn1ufA1ifA6Q313R/O0B87m8HAADqW65YOt8LQZqr51541XIcqJqPPvk8XHfn017EqYbtZ5Mvrcl4/dhTz6fynfyd72OmGjlmd/NfqR5eDlosPf/VCzvtMNB8e0bRdj2f8UW+55Kkemu7A06xJlTddPL0meFHK2yS+uf+/Bk39GnP6Nb7nne9pG+67f7K7s2OHr+/8VmpdeCglUK5La8MtfWQ1X321RwVoruqvp85NFomV4w+8u/f16Lf2x0HAACoHL82AEjES8EA4s8zPXQcIAEjB0CiuaaHjgPE56HjAM7PAZyfAzg/B3B+DgCA9bn1OYD1OUB6c033twPE5/52AACgvrUUS3d7GUjz1NrRFT7/4kvLcSB18+YvCPc88lI47ZK7vYRTDV20/cSqj9erdu2ayvfy08++DKde7DuZlfY56nzzX6kOyhVKX+SGRUW7CzTxvtGBvuuSpHqruO4O1oWqq776TKb9uf/5r6f1ad/ooadfd62kb7p+5jMV3Zddd/N9jM9Kre4ha4ZyW14Z6rSBHT77ao6982Lp+VrsZ/Zr71q3pRAtcA36cu4RXW5nHAAAoHL86gAgES8FA4g/z/TQcYAEjBwAieaaHjoOEJ+HjgM4Pwdwfg7g/BzA+TkAANbn1ucA1ucA6c013d8OEJ/72wEAgPqWK5RmeyFI81RYZ4KlOJC6l9/4IJz/2we8fFMN35TpM8PAVbas+ng9ZdplqXw373viFdc1I53c89ktjNre/Feqj8bbWaDZtRRKk33XJUn11iGTZ1gfqm5ae/P9U//Mb7nbxD7tG/3h1fdcK+mbrrrliYruy6658R7GZqVWZ/sGodyWV4Z6YKmlwxKFyOdfjV+h9HHN7oVrj/Z3DfrUeXbFAQAAKscvDwAS8VIwgPjzTA8dB0jAyAGQaK7poeMA8XnoOIDzcwDn5wDOzwGcnwMAYH1ufQ5gfQ6Q3lzT/e0A8bm/HQAAqF+tI7u/11IsLfIykOapNOFAS3EgNX/85Itwze1PeemmmqZ9j76g6mN1a0dXePWNtyv+/Vy4aFE496r7XdeMtPMhZ5j7SnVRdJqdBTLiOy2F0tm+85KkemqjbQ6zPlTd1L3r0al/5lcas3Of9o7e+3COayV908XXP1LRvdkVR+9kbFZ6Zwo9Pdo2IJTb8spQ6w4b5fOv5vgbNrL7e7Xa0GwpRtNcg96VK0RTbIkDAABUjl8gACTipWAA8eeZHjoOkICRAyDRXNNDxwHi89BxAOfnAM7PAZyfAzg/BwDA+tz6HMD6HCC9uab72wHic387AABQv/q3j1nOy0Caqz0POd5SHKi4RYsWhfufeDWcfsndXrippmr98YdUfazeeIeDU/mevvDae65pRppywR1huTW2NveVal70aC1fCApV19393VyhdKXvviSpXmobsUmYfN4t1omqi3Y++PTUP/NLLj8uzJ+/oNd7R/N6/v+6VtJ/du5V91d0b7Zzve2MzUq1awYsF8pteWWoQweN8NlXU/TD4rgla7WdueTqq//PXKF0n+uQvFwx+qUNcQAAgMrxSwSARLwUDCD+PNNDxwESMHIAJJpreug4QHweOg7g/BzA+TmA83MA5+cAAFifW58DWJ8DpDfXdH87QHzubwcAAOpXrlga42UgzdVxp19kKQ5U1Jdz54erb3vSizbVdJ14we0hP7K76mP1RVfdnMp31fc0O22z74nmvVLNXyhZ+nDxYWPa7CqQNa0ju7/XUohm+jsgSaqXdjjoVOtE1UU/O+7SqnzmX33j7T7tH51z1f2ul9TTGZfeU9G92aFrjjcuK9WmLNMRym15ZahrBwz22VdT1NretUIt9zOXHL7hD3PF6HXXImGFMT+zGw4AAFA5fo0AkIiXggHEn2d66DhAAkYOgERzTQ8dB4jPQ8cBnJ8DOD8HcH4O4PwcAADrc+tzAOtzgPTmmu5vB4jP/e0AAED9ailEe3sZSHN16dW3WooDFTN33vww48ZHvWRTTdkeh0+r+jidH9EdPvn0s4p/V//46Rfh1Itd0yw0+bxbwtIrb27eK9W0aGFLoWsDOwpk1RJDN/rXXDF60t8CSVI91LnBztaKqouOO/vmqnzm75j1aJ/2kK68+XHXS/qmBQsWVmx/dtlVtjAuK9X2G7xSKLfllaGe7am9fSOffzV8uWJpTK33M1vbu1bIFUpfuB7x61ccs4edcAAAgMrxiwSARLwUDCD+PNNDxwESMHIAJJpreug4QHweOg7g/BzA+TmA83MA5+cAAFifW58DWJ8DpDfXdH87QHzubwcAAOpXrlg6yctAmqt7H3rKUhyoiLnzFoTLfv+Yl2uqaVtz032rPk7vcsCxqXxf73nkJdc0I2222yRzXqn2TbSbQNb1L0a5lkL0ir8HkqR66NATLrdeVF00YMXNU/+8nz/jhj7tId163/OulfRNcz6fW7H92R+tsLExWanWPWTNUG7LK2PtuNyqPv9q+FoLpR3qYT+zpTjmx65H/HKFMdvYBQcAAKgcv0oASMRLwQDizzM9dBwgASMHQKK5poeOA8TnoeMAzs8BnJ8DOD8HcH4OAID1ufU5gPU5QHpzTfe3A8Tn/nYAAKB+5Yql33kZSHM1++33LMWBPlu0aFH43Z1Pe7GmmrbJ594Slhg+rurj9M0zH6z493XBwoXh7Cvuc10z0LHTbgr5FbrNeaVaVohuWay7+7t2E2CxxX5YiAbniqUP/W2QJNW6Mdv+3JpRddGI0bum/nk/8vhz+rSP9NDTr7tW0jd98MfPKnae0trRZUxWqg1v3yCU2/LKWGcNLPr8q+HLFaND6mU/s+e/z7GuSdzGjLMDDgAAUDl+mQCQiJeCAcSfZ3roOEACRg6ARHNNDx0HiM9DxwGcnwM4Pwdwfg7g/BwAAOtz63MA63OA9Oaa7m8HiM/97QAAQP1qKUTPeBFI89Q2YpOwcOEiS3Ggz+586AUv1VRTt+NBp1V9nB621vgwf/6Cin9fyy+/45pmpGi7iea8Ui0rRK/16xz973YS4P/TWoxWyxVKX/gbIUmqZfkVusPx591m3aiat8H4g1P/vG//06P7tI/0wmvvuVbSN81+548V2Z+dO3ee8Vipt0QhCo/nB4RyW14Z6uGea75kMfIdUEOXK0RT6mc38/C/aylE17ou316/wphRdr8BAAAqxy8TABLxUjCA+PNMDx0HSMDIAZBorumh4wDxeeg4gPNzAOfnAM7PAZyfAwBgfW59DmB9DpDeXNP97QDxub8dAACoW9/JFaLPvQykeVq1a1fLcKDPnn7hLS/UVNO3UmnPqo/Th/7qzFS+s1fc/LhrmoGOOu3a0H/5cea8Uq1e/FmM5rZ0RiNsI8Cfy3V0bdpSjBb6WyFJqmU7/uw0a0fVvK32+nXqn/W1u/fq0z7Sex/Nca2kb3rx9fcrsj/7yZzPjMWqStcNWC6U2/LKWBsNXcfnX41dIbqknvYy853d/09LofSsa/NtZyJdK9r5BgAAqBy/TgBIxEvBAOLPMz10HCABIwdAormmh44DxOeh4wDOzwGcnwM4Pwdwfg4AgPW59TmA9TlAenNN97cDxOf+dgAAoD61tm/U4kUgzdWWu020DAf65P2P5oQzLr3HCzXV1E0684bQ2tFV9XH6saeer/h39sOPP3NNM9KorQ4y35Vq+QLJjmh3uwjw17V0lPbxt0KSVMtW2GhXa0fVvD0nnpP6Z33plTYLixYt6vVe0rz5C1wr6ZueefHtypyrfPixsVhV6bSBHaHcllfGOnLZET7/avRurre9zNywroG5YvSRa/PXax02dohdbwAAgMrxCwWARLwUDCD+PNNDxwESMHIAJJpreug4QHweOg7g/BzA+TmA83MA5+cAAFifW58DWJ8DpDfXdH87QHzubwcAAOpTv47Sql4E0lz97OjTLcOBXps3b0G48HcPeZmmmr6tf3pC1cfo1cfunsr39s4HX3BNM9BhJ14RWju6zHelGpUrRtPtIMC3aylGx/mbIUmqZUeeco01pGraz0+6siqf9Xfe+7BP+0nnXnW/6yX19Mizb1Rkj/bNt983DqsqHTRoxVBuyytj3ThgkM+/GrtC9FBd3jPX3rVuz3+3Ba7RX27x9tKP7HgDAABUjl8pACTipWAA8eeZHjoOkICRAyDRXNNDxwHi89BxAOfnAM7PAZyfAzg/BwDA+tz6HMD6HCC9uab72wHic387AABQn3LtpQleBNJcnX7+VZbhQK/9/p6yF2kqEy2//k5VH6NPmlb5s7V58xeEMy+71zXNQKuM3dtcV6pd5X9bJvrfdhAglu/kCtFv/N2QJNWqTXebZA2pmnb8ebdV5bP+wKPP9GlP6cpbnnC9pJ7ufezliuzTvvL6W8ZhVaXNh6wRym15ZbDlh23gO6CGLVeIXqzXzcyWjtI+rtFfrnVw9w9sdwMAAFSOXykAJOKlYADx55keOg6QgJEDINFc00PHAeLz0HEA5+cAzs8BnJ8DOD8HAMD63PocwPocIL25pvvbAeJzfzsAAFCfWoqlI7wIpLm67pZZluFArzz/yrteoqlMdMQpV1f/pWMdXeG12e9U/Hv79AtvuaYZaP9J081zpVpVKH2SGxotY/cA4hswYP1/zBVLt/kbIkmqRYNXHx9Onj7TWlI1beDKW6T+WZ9xza192lO67f7nXSuppzse+ENF9mmfe/E147Cq0krD1gvltrwy2G7LreI7oIYtV4w+qut75wqls12nP6+zc6e/t9sNAABQOX6pAJCIl4IBxJ9neug4QAJGDoBEc00PHQeIz0PHAZyfAzg/B3B+DuD8HAAA63PrcwDrc4D05prubweIz/3tAABAfcoVSxd6EUhz9eSzL1qGA4l9/sW8cPaV93mJpjLRZrtPqvr4PG77g1P57l5646OuaQZaYaNdzXOlWlWIPFgAeuEHK6z/z7lC9IS/I5KkWnTApIusJVXThm+4S+qf8+NOv6hPe0oPP/26ayX1dOPdz1Zkn/ar81ljsKrREsUoPNW2VCi35ZWxzh1Y8B1QAxctXKy7+7v1upfZ2bnT3+eK0R2u05+ejZQ+scsNAABQWX6tAJCIe3cB4s8zPXQcIAEjB0CiuaaHjgPE56HjAM7PAZyfAzg/B3B+DgCA9bn1OYD1OUB6c033twPE5/52AACgPrUUolleBtJcffzJHMtwILHrZz7jBZrKTEPXnlD18fmiK2+q+Pf2nfc/dT0z0J4TzzHHlWr30sjJdg2g9xZvL/0oVyi95e+JJKnabTD+EOtJ1bR1tzww9c/5Hocc36d9pRdfe9+1knq6+rYnK7JX+/ATZWOwqtbvlxoUym15ZaxH2gaEJYqR74AattbB3T+o573Mfp2j/z1XiF50rf7rfCR6zQ43AABAZfm1AkAiXgoGEH+e6aHjAAkYOQASzTU9dBwgPg8dB3B+DuD8HMD5OYDzcwAArM+tzwGszwHSm2u6vx0gPve3AwAA9amlWHrby0CapyFr/NgSHEjs6Rfe9vJMZaZDJl9W9fE5P6I7fPzJnIp/d2+7/3nXtMmbMn1maF9nW/NcqTYvjJw1eHD3P9g1gL7p19HV2fOdmuPviiSpmrWN2CQcf95t1pWqWd27HpP653zM1gf0aV/p/Y/muFZST5fe8GhF9mrvfegpY7Cq1pkDi6HcllcGW2/YKN8BNWz9O7uWqvt76Apj2+1l/me5QvSE3W0AAIDK8osFgES8FAwg/jzTQ8cBEjByACSaa3roOEB8HjoO4PwcwPk5gPNzAOfnAABYn1ufA1ifA6Q313R/O0B87m8HAADqz+LDRn2/pVha5GUgzdMGW+1rCQ4k8ulnX4azLr/XyzOVmbp2OLLq4/POBxxb8e/u3Hnzw9QZs1zTJm+HA081x5Vq09v9i1HOrgFURr/CmFJLIVrgb4skqZrteuhU60rVrB1/dlrqn/Gha47v097S/AULXSupp/OvfrAi+7V3zHrU+KuqdfCgkaHcllcGO3jQir4DathaC6OHN8JeZs9/143dS9dTIbrLzjYAAEBl+dUCQCJeCgYQf57poeMACRg5ABLNNT10HCA+Dx0HcH4O4PwcwPk5gPNzAACsz63PAazPAdKba7q/HSA+97cDAAD1p7WzNNSLW5qrXQ441hIcSOS3tz7pxZnKTCdPnxmWXe3HVR+fb7rzgYp/dx9/brZr2uSdeMHtYVANPq+SF0VGC/oVxoyyYwCV1fPd2tvfGElSNVt13N7WlqpZ+0+aXpXP+Sefftan/aVzr7rf9VLmO/OyWRXZr73+1lnGX1Wt8cutEcpteWWwy5Ye6jughq1fe9e6DbOXWSxNdFZSutquNgAAQGX51QJAIl4KBhB/numh4wAJGDkAEs01PXQcID4PHQdwfg7g/BzA+TmA83MAAKzPrc8BrM8B0ptrur8dID73twMAAPWnX3upy4tbmqujp/zGEhyI7Ynn3vTSTGWq/Y65sOpj85A1fhzmzZtf8e/vRdc97Jo2eVvtfZz5rVSbDrRbAOnIFUsn+RsjSapWrR1d4ZipN1hfqib98ozrqvI5f/LZF/u0v3TFzY+7Xsp8p158V1i0qO/7tZdde5vxV1Vr1WHrhXJbXhns6Z4GFsb4HqghyxWjzRtoK/M7LYXokmxfr9L5drQBAAAqyy8XABLxUjCA+PNMDx0HSMDIAZBorumh4wDxeeg4gPNzAOfnAM7PAZyfAwBgfW59DmB9DpDeXNP97QDxub8dAACoPy3F6Cde3NJcXXjF7y3BgVg+/ezLMHXGLC/NVKbacOtDqz42HzrpzIp/f2e/80fXs8k77pybw1IrbmZ+K1W7QunqnqXyd+wWQEq6u7/71ffM3xtJUrX68T7HW2OqJk2ZPjP0X35c6p/x626Z1ac9pt/fU3a9pJ7mzV/Q5z3b82fcYOxV1fpRMQpPt+VDWZls4yFr+h6oIcsVunZtpK3MxYeN+n5LMXo0u9crmmJDGwAAoLL8egEgES8FA4g/z/TQcYAEjBwAieaaHjoOEJ+HjgM4Pwdwfg7g/BzA+TkAANbn1ucA1ucA6c013d8OEJ/72wEAgPrTUiid4sUtzdXM+x6zBAdiuX7mM16WqUx14gW3h/zITas+Nj/65PMV//7e5IXHTd/GOx9lbitVvejl1sHdP7BTAOlqHdn9vVyhdK+/OZKkatS+znbWmKpZQ9aakPpnfOoFv+3THtOsx152raSePvtibp/3bE8770pjr6raLUsNCuW2vDLY0csO9x1QY1YoHdxoe5n9Okcv0fPf/e2MXrOJdrMBAAAqy68XABLxUjCA+PNMDx0HSMDIAZBorumh4wDxeeg4gPNzAOfnAM7PAZyfAwBgfW59DmB9DpDeXNP97QDxub8dAACoP7lidJ0XtzRXr7z+liU48K1effNDL8pU5tpz4jlVH5dXG7tbxb+/X3w5L5x+6T2uaRN3zNTrw5LDNza3lapYrhB9nmsvFewSQHUs0Tm2X64Yve7vjySpGh16/GXWmqpJq4zdO/XP989/Pa1P+0xP/uEt10rq6aNPPu/zvu3kMy427qqqTRtYCOW2vDLYjQMG+Q6oQYuOa8S9zH7tY1bOFUtfZvB6/cRONgAAQGX5BQNAIl4KBhB/numh4wAJGDkAEs01PXQcID4PHQdwfg7g/BzA+TmA83MAAKzPrc8BrM8B0ptrur8dID73twMAAPWnpVgqe2lL87RE59g5Gw3LAAAgAElEQVQwf/4CS3Dgb5q/YGH4zTUPelGmMtdam+1X9bH5pGmVP0t7+JnXXc8mb8OtDzW3lapcrhhtZ4cAqis3LCr2fP/m+BskSUq70g5HWGuqJo3Z9uepf763/+kxfdpneuXND10rqad3P/y0z/u2Rx5/jnFXVe3ny44M5ba8MlqhsKHvgRqvQunshr2/rhBtnblzk/bSBLvYAAAAleVXDACJeCkYQPx5poeOAyRg5ABINNf00HGA+Dx0HMD5OYDzcwDn5wDOzwEAsD63PgewPgdIb67p/naA+NzfDgAA1JvD/y5XLH3pxS3N08iNdrT8Br7VvY+97CWZylyTz701LLn8xlUdl1s7usJrs9+p+Hf4wmsf+u//XSdPnxmOO/vmcNTpvwuHnHB52O+YC8Meh08LOxx4avjxPseHTXY5Ooye8POwzhYHhjU33Tes3LXX13VusHNYfv2dQvs624bl1tg6DFrtx2GpFTf7uq/+e/+l/z3/9f/+/2/plTb/+v/GV/+3vvq/OXLM7l//Z6y12X5f/+dutM1hobTdEV//d/nqv9OOB50W9px4Tth/0vRw2IlXhKPPuC5MPu9Wn9NvOuKU34b+nWPNbaVqvhiyGJ1lfwBqo6UQdfd8Dxf5WyRJSrOlV948TLnwTmtOVb2v9kHS/nyvv8VP+7TP9MEfP3OtpJ5mv/txn/dtDzzqNOOuqto2y60Wym15ZbRtl1vd90CNtxdfKF3ZyHuZPf/9j8/S9WrtiMbawQYAAKgsv2IASMRLwQDizzM9dBwgASMHQKK5poeOA8TnoeMAzs8BnJ8DOD8HcH4OAID1ufU5gPU5QHpzTfe3A8Tn/nYAAKC+5JYv9ffSluZq050Os/wG/qaPPvk8nH7JPV6Sqcy108GnV31cHrfdz3r9XZ07d154bfY74YFHnwnX3HR3mDb9mvCLE84N2/10Uhg5ZvcwdO0JIT9y06aax/TvHBsGrrxFaF9nu7BSac+w7lYHhXE7HxW22ffEsOthZ4UDj704HHHK1eGE829r6s/qWpvtZ14rVbNC6eElV1/9f9ohgBruTxWiw/09kiSl3V5Hnmt/RFVvz4nnpP7ZHrrm+D7tF8+bv8C1knp6ZfaHfT5/2eOQ4425qmprDVs3lNvyymgnL9Ppe6CGK1eMbm/ojczu7u/mCtGNmblm7aU17F4DAABUll8yACTipWAA8eeZHjoOkICRAyDRXNNDxwHi89BxAOfnAM7PAZyfAzg/BwDA+tz6HMD6HCC9uab72wHic387AABQX1oLXat7aUtztd8RJ1t+A3/Tb2990gsylclW7tqr6uPy9Ct+/1e/i/PnLwgvvjI73DLzwXDmhVeHnx19eth6r1+EdTbdO7SvvbV5zbfUNmKT0D5q+7D6xj8Jpe2OCON/csLXL6o+5ITLw3Fn39ywn9ODJ88IrR1drrFUtRd4lj5cYvlxebsDUHPf6flOzvB3SZKUZmtttp/9EVW9w064oiqf788+/6JPe8bTrrjX9VLm+8Or7/X5/GX7nx5tzFVVG1gYHcpteWW0e5caGFp9D9Roe/KF0uONvpG5ZHvpX3r+t5Qzcb3aSwVb1wAAAJXllwwAiXgpGED8eaaHjgMkYOQASDTX9NBxgPg8dBzA+TmA83MA5+cAzs8BALA+tz4HsD4HSG+u6f52gPjc3w4AANSXXDHa1ktbmqsp0y6z/Ab+qvLL73g5pjLZpLNuDP07uqo6JudHdIcP//hJePWNt8Mdsx4N5156XTjs2LPCj/c4Iqwc7RKWXH6cuUuq//6bhuJ6O4R1Nj8gbLbbpLDrYWeFQ064PBx/3m11/VldqbSn6ydVr0W5jq7RdgagPvTrHP1PLYXoIX+bJElptcTwceG4c262T6KqNvncW6vy+X7+pdf7tG986Q2Pul7KfM+8+Hafz2A23+XnxlxVvXvzA0O5La+MtnL7er4HaqwK0WtNcb/d0GiZXDH6qNmv1+LtpR/ZuQYAAKgsv2YASMRLwQDizzM9dBwgASMHQKK5poeOA8TnoeMAzs8BnJ8DOD8HcH4OAID1ufU5gPU5QHpzTfe3A8Tn/nYAAKC+tBRKv/DSlubqqhtmWn4Df9HcefPDOVfd7+WYymTb7Hti1cfkJYePC20jNjE/qcMGrfbjsHLXXqG03RFhh4NODQdPnhFOOP+2mn9Of/rL37g+UhXLFaNf2hWAOtunGjq2NVeI3vQ3SpKUVjv+7DT7JKp6+ZGbpv7Zvv2eh/u0d3z9Xc+4Vsp8j5Vn9/kcZszWBxhvVfVmLD00lNvyymh7DVrZ90ANVvRps+xltnaU1mspRAua+Xot2V76F7vWAAAAleUXDQCJeCkYQPx5poeOAyRg5ABINNf00HGA+Dx0HMD5OYDzcwDn5wDOzwEAsD63PgewPgdIb67p/naA+NzfDgAA1JdcMZruhS3N1SNPPmf5DfxFdzz4ghdjKrMtv+HO5gn6m7V2dIUha00Ia2++f9hiz2PD3keeG46Zen3VPqMnT58ZOtbb0bWQqlUhumWx7u7v2hWA+tPa3rVCrlD6wt8qSVIarTpub/skqnrFdXdI/bN94RW/79Pe8V0Pv+RaKfM9+NRrfT6HWbt7L+Otqt4Jy3SGclteGe28pdt9D9RwdXbu9PfNspfZ0lHap3mvVbRwscUO/zs71gAAAJXlFw0AiXgpGED8eaaHjgMkYOQASDTX9NBxgPg8dBzA+TmA83MA5+cAzs8BALA+tz4HsD4HSG+u6f52gPjc3w4AANSXXKF0nxe2NFcffPSx5TfwZz7442fhtIvv9mJMZbLDp1xljqBet8yqW4U1N903bLXXr8P+k6aHyefdksrndLdDz/TvLVWpXDF6ffFhY//DjgDUr9ZCacue7+sif7MkSZWuf+fYcOy0m+yXqKqtvslPUv9s/+qUC/u0f/xYebZrpcw367GX+3wWs+LonYy3qnr7DV4plNvyymiP5QeEHxUj3wU1VK2Du3/QTHuZLYXS2c15llL60E41AABA5flVA0AiXgoGEH+e6aHjAAkYOQASzTU9dBwgPg8dB3B+DuD8HMD5OYDzcwAArM+tzwGszwHSm2u6vx0gPve3AwAA9aWlGL3rhS3N07KrbmHpDfxFV9/2pJdiKjOdPH1mOPSEy8Pmex4blt9w59Da0WWeoMq96K/n89S+znZhowmHhV0OmRp+ecZ1ff7MTrngjrDcGlv795Wq8RLIQjQvVyitZDcA6l+uGP3S3y1JUhptf8DJ9k9U1cZs+/PUP9d7HXpCn/aPX3z9fddKme/Oh17o81nMsLXGG2tV9TZbbs1Qbssrw20wdB3fBTXWPv3ypf7NtI85eHD3P/T877q7Ca/VS3apAQAAKs+vGgAS8VIwgPjzTA8dB0jAyAGQaK7poeMA8XnoOIDzcwDn5wDOzwGcnwMAYH1ufQ5gfQ6Q3lzT/e0A8bm/HQAAqB//tkz0v72spbnaYMufWnoDf8YLUZWFTjj/trDXEeeGDbc5NCyz6lbmBapqg1b7cVh3q4PCDgeeGo46/XeJP78T9j/Jv6NUrQrR3nYDoFEc/nctxegqf7skSZVuxdIe9lJU1bba69epf67HbX9wn/aQ3/3wU9dKme+We5/r83nMUiO7jbWqeiu3rxfKbXlluIMGrei7oIaqX+foZZttJ/M/hoxZvKVQerXJrtUj9qgBAAAqzy8bABLxUjCA+PNMDx0HSMDIAZBorumh4wDxeeg4gPNzAOfnAM7PAZyfAwBgfW59DmB9DpDeXNP97QDxub8dAACoHy2Fse1e1tJc7XLAsZbewP9lwcJF4cJrH/JCTDVlk868IUzY/6Sw6ri9wxLDx5kLqG4astaEEG13eNjryHPD5PNu/Zuf4+PPuy0MXGVL/25SNSpEl9gJgMbyfwZ3/69cMXrM3zBJUiVr7egKk8660d6Kqtauh05N/XM9cqMd+7SP/MXc+a6VMt8Ndz3bx/OYhV+PMcZaVbsfFaPwdH6pUG7LK6NNX3qY74Iaqn4dXZ3NuJeZay8Vev73zWmW65Qrlm6zQw0AAFB5ft0AkIiXggHEn2d66DhAAkYOgERzTQ8dB4jPQ8cBnJ8DOD8HcH4O4PwcAADrc+tzAOtzgPTmmu5vB4jP/e0AAED9aCmOGedlLc3VpFMusPQG/i+PPPO6l2GqqTr27JvCzoecEVbf+Cehf+dY47/qvv4dXWHE6N3ChH1PDMdMveHPPtOb7f4r/05SVYqe+8EK6/+znQBoPD8sjluy53v8tr9jkqRKNmHfk+yzqGodeOzFqX+mlxw+LixYuLBPe8lTL5vleinTXX3bk336Dn3y6WfGWNWsO5ZaNpTb8spoj+cHhCWLke+CGqbWYrRak9+Lt6gZrlOuEF1udxoAAKDy/LoBIBEvBQOIP8/00HGABIwcAInmmh46DhCfh44DOD8HcH4O4PwcwPk5AADW59bnANbnAOnNNd3fDhCf+9sBAID6kSuU9vWylubq4t/ebOkN/LfPv5wXzrzsXi/DVMM36cwbwrb7TQkjx+weWju6jPlq3JcE9nx+h2+4a5iw/0nh2LNvCsdOuynkR2zq30ZKvzk/LESD7QJA4+rXPmblXLH0pb9nkqRKNWL0rvZcVLWOOv26qnyuZ7/9Xp/2ky+67mHXS5nu8pse79N36O13PzDGqmZduHR7KLflleFGDR3lu6DGqVDasJn3Mnv+N05skut0tp1pAACAyvMLB4BEvBQMIP4800PHARIwcgAkmmt66DhAfB46DuD8HMD5OYDzcwDn5wAAWJ9bnwNYnwOkN9d0fztAfO5vBwAA6kdLMTrNy1qaq3sfesrSG/hvtz/wBy/CVMN27LSbwrb7TQkjR+8WWju6jPNquvp3jg1D1prg30KqQq3t0VZ2AKDx5QpjtvE3TZJUsTliR1c4+ozr7MGoKk258M7Qvwr7Ww88+kyf9pOvveMp10uZ7uLrH+nTd+jFV2YbY1WzJi07PJTb8spw+w1eyXdBjVMhavYH+X4nVyxd1vjXqTTZrjQAAEDl+YUDQCJeCgYQf57poeMACRg5ABLNNT10HCA+Dx0HcH4O4PwcwPk5gPNzAACsz63PAazPAdKba7q/HSA+97cDAAD1I1eIbvSylubqrXfet/QGvvbBHz8Lp118txdhqrFeMDx9ZtjvmAvD2psfEPovP87YLkmqQNGpVv/QPHq+07/2d02SVKnG73O8/RhVrWVX2yr1z/RVN8zs057yHQ++4Fop0/3mmgf79B164tkXjK+qWXsMXiWU2/LKcBcMHOa7oIYp116a0Oz7mK0ju7+XK5QebOjrVIwOtSMNAABQeX7lAJCIl4IBxJ9neug4QAJGDoBEc00PHQeIz0PHAZyfAzg/B3B+DuD8HAAA63PrcwDrc4D05prubweIz/3tAABA/cgVS897WUvztNTI7rBo0SJLb+BrV9/2pJdgqmE69ITLQ2mHI8LSK21uTJckVe6Fj4XSgwMGrP+PVv/QRLq7v5srln7nb5wkqRJ1brCzfRlVrRGjd039M33KOZf3aU/54adfd62U6c6+4r4+fYfufegp46tqVteQtUO5La8M92jbgLCE74IapH7FMXtkYSuzX+foJXr+977tOgEAAPCn/MoBIBEvBQOIP8/00HGABIwcAInmmh46DhCfh44DOD8HcH4O4PwcwPk5AADW59bnANbnAOnNNd3fDhCf+9sBAIA68fVLiKO5XtbSPK25yZ6W3cDXXnrjAy/AVN33q7NuDFv/9IRQGLW9cVySVPFyxdKHi7eXfmTxD81nyfbSv+QKpT/4WydJqkS/OO0a+zSqSqO2ODD1z/Ohk87s077y86+861op0029bFafvkM33n6fsVU1a/lhG4RyW14Zb61h6/o+qFE6MCt7mf3ax6ycK5a+bMTr1FoobWk3GgAAoPL80gEgES8FA4g/z/TQcYAEjBwAieaaHjoOEJ+HjgM4Pwdwfg7g/BzA+TkAANbn1ucA1ucA6c013d8OEJ/72wEAgPrw1cvFvaSludruJ0dbdgNhwcJF4cJrH/ICTNVt+0+aHtbefP/Qv3Os8VuSlFaLch1do638oXm1dpaG9nzX5/h7J0nqa1vudZz9GlWljXc+KvXP8077/6pPe8tvvfeJa6VMd/ol9/TpO3Tp1bcaW1Wz+hej8ER+qVBuyyvD/WTwSr4PaowKpV9kaS8zV4y2a8Tr1K+9a1070QAAAJXn1w4AiXgpGED8eaaHjgMkYOQASDTX9NBxgPg8dBzA+TmA83MA5+cAzs8BALA+tz4HsD4HSG+u6f52gPjc3w4AANSHXCFax4tamqsjJp9j2Q2Ex8qzvfxSddfk824N2+5/cmgftb0xW5KUerli6Rirfmh+rYXSlv7mSZL6WnHdHezdqCptu9+U1D/PpQkH9mlvec7nc10rZb6+OGv6NcZW1bQbBwwK5ba8Mtx5Awu+C2qMPfxC6fgM3qd3QqNdp36dozvsQgMAAFSeXzsAJOKlYADx55keOg6QgJEDINFc00PHAeLz0HEA5+cAzs8BnJ8DOD8HAMD63PocwPocIL25pvvbAeJzfzsAAFAfcsVoFy9qaa7On3GDZTdk3Lx5C8LZV97nxZeqm4485Zqw8c6/DEutuJmxWpJUnZdxFqPbF1t99f9h1Q9Z2d8qneRvnySpr008+bf2cZR6ex15buqf5fyI7vDFl3N7vb+8aNGicOrFrpWy3YKFi3r9HTru9IuMq6pp0wYWQrktrwz3cH7psEQh8n1Q/e/jF6KpmdvI7O7+bq5Y+l0jXad+naOXsAMNAABQeX7xAJCIl4IBxJ9neug4QAJGDoBEc00PHQeIz0PHAZyfAzg/B3B+DuD8HAAA63PrcwDrc4D05prubweIz/3tAABAfWgpRr/2opbm6o5Zj1p2Q8bd9/grXnqpmjdl+syw5xFnh5VKe4bWji5jtCSpmi/ifHPJ4Rv+0IofsqOzc6e/bylEd/kbKEnqS5vv8St7Okq9w064oiqf57sfeLxPe8zTLr/X9VKmmzdvQa+/P4cde5ZxVTVt4qARodyWV8ZbY9h6vg+q/738YjQ9i3uZS7aX/qXnf3+5Ua7T4sNGfd8ONAAAQOX5xQNAIl4KBhB/numh4wAJGDkAEs01PXQcID4PHQdwfg7g/BzA+TmA83MAAKzPrc8BrM8B0ptrur8dID73twMAAPWhpRhd5UUtzdUrr79l2Q0Z9tnnc8PUGbO89FI168Tf3B62O+CUsNwaWxuXJUnVr1Ca31roWt1qH7Jnic6x/XKF6E1/CyVJvW3Y2tvZ21HqHXf2zVX5PP/ihHP7tM98yfWPuF7KdF98Oa/X35+9DzvRuKqatuNyq4ZyW14Zb69BK/s+qBH6bVb3MnNDo2Vyxeijer9GuUL0uZ1nAACAdPjVA0AiXgoGEH+e6aHjAAkYOQASzTU9dBwgPg8dB3B+DuD8HMD5OYDzcwAArM+tzwGszwHSm2u6vx0gPve3AwAA9SFXjJ70kpbmacnlx4X58xdYdkOG3f7AH7zwUjVp8nm3hAn7nhiWWXUrY7IkqWb1K5YOsNKHLO9zda2YK0Zz/T2UJPW2I075rX0epd4yq2yZ+md56Jrjw9y58+wzS71szudze/39mbD3UcZU1bQNhq4Tym15ZbxpAwu+D2qEbs7yXma/wphRLYXS/Lq+RoXoNbvOAAAA6fCrB4BEvBQMIP4800PHARIwcgAkmmt66DhAfB46DuD8HMD5OYDzcwDn5wAAWJ9bnwNYnwOkN9d0fztAfO5vBwAA6sJ3Wgqlz7ykpXlaOdrFkhsy7KNPPg+nXXK3F16qqv3qrBvD5nv8KuRHbmosliTV+uWO1361zrXUh2zr+Vuwt7+JkqTettVev7bfo9RbZezeVfk8X3vT3b3eay6//I5rpUz38adf9Pr7M3bbg4ypqmlD2jcK5ba8Mt6D+YGhfzHynVC97+nPyvxeZjH6SZ1fp0fsOAMAAKTDLx8AEvFSMID480wPHQdIwMgBkGiu6aHjAPF56DiA83MA5+cAzs8BnJ8DAGB9bn0OYH0OkN5c0/3tAPG5vx0AAKi91vaNWrykpbnacreJltyQYTfc9ayXXapqTTz56rDB+ENC/+XHGYMlSfXQS0sM3ehfrfSBr7QUo4v8XZQk9ablN9zZvo9Sb9zOR1Xl89y17UG93mv+7Iu54dSL73a9lNk+/PjzXn9/1u7ey5iqmvdwfulQbssr460ybD3fB9V1uUL0hJ3MxRZrKZTOqePrdLMrBAAAkA6/fABIxEvBAOLPMz10HCABIwdAormmh44DxOeh4wDOzwGcnwM4Pwdwfg4AgPW59TmA9TlAenNN97cDxOf+dgAAoPZaC12re0lLc3XIMVMtuSGj3n7/Ey+6VFU64pSrwzpbHBhaO7qMvZKkOnnxZumLfh1dnVb5wH9ZfNio73/1Ul5/IyVJSftqv+OYqdfbA1Kq7Xro1Kp9pm+7++Fe7zlfc/tTrpcy23sfzen1d2f4+tsbU1XzrhmwXCi35ZXxdh+8iu+D6nxvP3rRTuZiiw0YsP4/9vx73F2X16kQXeIKAQAApMOvHwAS8VIwgPjzTA8dB0jAyAGQaK7poeMA8XnoOIDzcwDn5wDOzwGcnwMAYH1ufQ5gfQ6Q3lzT/e0A8bm/HQAAqL3WQmkHL2lprs688GpLbsio3976pBddKtWOPuO6sNE2h4X+nWONuZKk+qqjaycrfODP9r2KYwbkitFH/k5KkpK27f4n2wtSqk0668bQ2tFVlc/zBlv+NCxatKhXe87Pvfyu66XM9s77n/b6vGbplTYznqrmTR1YDOW2vDLeGct0+D6o3nvbLuZ/6tc5+t97/j1eqrtrVCid7OoAAACkw68fABLxUjCA+PNMDx0HSMDIAZBorumh4wDxeeg4gPNzAOfnALWfZ25i2ABINteUJEmSUmiyqTZAfHZ2AdzfDpAS97cDAAC1lyuWjvGClubqpjsfsOSGDHpl9gdecqn0XvJ75g0h2u7w0H/5ccZaSVLdlStEF1jdA3997yuKev5WLPL3UpKUpFXG7m1PSKlXXG+Hqn2mr7r+zl7tOy9YuDCce9X9rpcy2Zvvftyr7838BQtCa0eX8VQ1b+KgEaHcllfGm7nUMr4Pqvfm2MH8k73M9lLhq3+TOrtGE10ZAACAdPgFBEAiXgoGEH+e2W3YAIjPyAGQaK7poeMA8XnoOECyueZCQweA83OAFOaZ4wwbAAAAAEAjsbMLkOgs6BIjB0Bs7m8HAABqL1csXeYFLc3Vcy++ZskNGbNoUQiX3PCIl1yq4v36nJvCxjv/Miw5fGNjrCSpLssVoycXHzbq+1b3wN/SUigd5W+mJClJ/TvHhuPOudn+kFJt452PqtpnurDONuHjT+b0av/54Wded72UyV5/+6NefWfe//BjY6nqol0GrxrKbXkpFAob+k6onlu02GKH/50dzD/ZyyyOGffVv0u9XKN+xTF7uCoAAADp8CsIgES8FAwg/jyz27ABEJ+RAyDRXHOGkQMgNg8dB0g215xn6ABwfg6QwjyzZNgAAAAAABqJnV2ARGdB040cALG5vx0AAKi9lmLpES9oaaYXfXaFL+fOteSGjCm//I4XXKqiTT7v1rDZ7pNCfoVu46skqX4rlD7p1zl6WSt74Ft1d3+3pRj93t9OSVKSdj10qn0ipdoBky6q6mf6kGOm9mr/ed68BeGsy+91zZS5Xnnzw159Z156dbZxVHVRaehaodyWl8KWQ9bwnVBd169z9D/ZwPyz+/km1s31KXRt4YoAAACkw68gABLxUjCA+PPMbsMGQHxGDoBEc80ZRg6A2Dx0HCDZXPMLQweA83OAFOaZow0bAAAAAEAjsbMLkOgs6DdGDoDY3N8OAADU3lcvIfeCluZp+PrbW25DxixYuCj85poHveBSFenk6TPDTgefHgausqVxVZJU9+WKpc2s6oG4csO7/q2lGL3s76ckKW5rb76//SKlvhc3aLUfV+0z3b+zKzzw6DO92od+9Nk3XDNlrpdef79X35fHnnreOKr6uHegfYNQbstL4ahlV/CdUF23xNCN/tXu5Z/5Tq4QXV4P16dfYcwolwMAACAdfgkBkIiXggHEn2d2GzYA4jNyACSaa84wcgDE5qHjAMnmmnMMHQDOzwFSmGduYNgAAAAAABqJnV2ARGdB5xo5AGJzfzsAAFBb/zFkzOJeztJcde90qOU2ZMxj5dlebqmKdMjky8IKG+1qPJUkNUS5Yukkq3ogqZbC2PaWQukzf0clSXFqG7FJOPGC2+0bKdW6dz26qp/rFUfvFD6Z81nifegFCxeFC699yDVTpnr+1fd6dW5zx6xHjaOqi5YoRuHp/FKh3JZXxrtq6SG+E6rrvrp/zc7ln2sd2f29lkL0UM3PY4ZFRVcDAAAgHX4JAZCIl4IBxJ9ndhs2AOIzcgAkmmvOMHIAxOah4wDJ5pofGzoAnJ8DpDDPXNewAQAAAAA0Eju7AInOgqYZOQBic387AABQW/3ax6zs5SzN1X5HnGy5DRkyb/6CcPaV93m5pfrU0WdcF0ZtcWBo7egylkqSGqJcoXTf4MHd/2BVD/RGrhht52+pJClu+xx1vv0jpdqRp1xT9X25fSf27izp5Tc+cM2Uqcovv9Or78q1N91tDFXddOdSy4ZyW14Z78m2pUJbIfKdUN3Wr3P0EnYt/7LF20s/ailG77o+AAAAzcmvIQAS8VIwgPjzzG7DBkB8Rg6ARHPNGUYOgNg8dBwg2VzzQ0MHgPNzgBTmmWsbNgAAAACARmJnFyDRWdBUIwdAbO5vBwAAaqulEG3t5SzN1SnnXG65DRny8NOve7Glet0J598WNtt9Ulhy+MbGUElS41SI3vcCR6DPe2LF6Fx/UyVJcdpw60PtIyn1Rozereqf7WtvurtXe3Esl1sAACAASURBVNLX3/WMa6bM9PQLb/Xqe3LhFb83hqpuumTpoaHclpfCusNG+U6ojvf9N1rajuVf11qMVssVonm1uj79Okf/k6sAAACQDr+GAEjES8EA4s8zuw0bAPEZOQASzTVnGDkAYvPQcYBkc813DR0Azs8BUphnrmHYAAAAAAAaiZ1dgERnQacaOQBic387AABQWy3F6EgvZ2muevsSRKDxzJ03P0y7/F4vtlSv2u3QM8Oyq21l7JQkNVjRwpZC1wZW80BfLT5s1Pd7/q487e+qJOnbGrjyFmHK9Jn2k5Rqexw+rQaf7c3Ccy+8mnhf+vMv54Wzr7jPdVMmevL5N3t1fnPqeVcaQ1U3Hb/M8qHclpfCPoNX8p1Q3dY6bOwQO5bfdo9faedaXJtcIfrcvz4AAEB6/CICIBEvBQOIP8/sNmwAxGfkAEg015xh5ACIzUPHAZLNNd8ydAA4PwdIYZ65imEDAAAAAGgkdnYBEp0FTTFyAMTm/nYAAKC2WorRRV7O0lw9+eyLltuQEfc/8aqXWipxR53+u7DK2L2NmZKkxqxQ+oWVPFAp/dvHLNfzt2WOv6+SpG/rwGMvtq+kVJsyfWYYstaEqn+2V+3aNXzy6WeJ96afe/ld102Z6LHy7F6d3xw95TfGT9VNBwxaMZTb8lI4a2DRd0J1W7/O0R12K2Pd53dq9c9lotf8ywMAAKTHLyIAEvFSMID488xuwwZAfEYOgERzzRlGDoDYPHQcINlc81VDB4Dzc4AU5pkjDBsAAAAAQCOxswuQ6CxospEDIDb3twMAALWVK5Ye8HKW5uqTOZ9ZbkMGfDl3fjjr8nu91FKxO3n6zLDDQaeGthGbGC8lSQ1Zz/r1tsW6u79rJQ9UdG+svTTB31hJ0rc1dsdf2F9S6n21d1eLz/eEvY8KCxcuSrxHfdM9ZddNTd9j5Td6dYaz78STjZ+qm8YPWT2U2/JSmLXUMr4Tqt86xoy0UxnD6qv/j1yhdGtVr02h9LB/eAAAgPT4VQRAIl4KBhB/ntlt2ACIz8gBkGiuOcPIARCbh44DJJtrlg0dAM7PAVKYZw4zbAAAAAAAjcTOLkCis6BfGDkAYnN/OwAAUFu5YvSBl7M0T8PWGm+pDRkx67GXvdBSsTvsxCtC5wY7GyslSQ1brlh6Y/FhY//DKh5IQ0sxOtffWknS32q5Nba2x6TUO/GC28PAVbasyWf8+KmXJN6jnjtvQbjgmgddOzV1jz77Rq/OcLbd55fGT9VN6wwdFcpteenrOto38L1QXdZa6FrdLmU8/TpH/3vPv9lLVbw+N/tXBwAASI9fRQAk4qVgAPHnmd2GDYD4jBwAieaaM4wcALF56DhAsrnmI4YOAOfnACnMMwcYNgAAAACARmJnFyDRWdDBRg6A2NzfDgAA1E7r4O4feDFLcxVtc4ClNmTA51/OC1Mvm+WFlvr2F/H+5vawyS5Hh/6dY42TkqSGLVeI5vXr7FrFKh5Iy+LDRn2/5+/N0/7mSpL+Vj8/6Ur7TUq9CfufVJPPd//OrnDrXQ8l3qt+94NPw+mX3O3aqWl79Nk3enWO89WZrbFT9dKQwkah3JaXvm78cmv4Xqgu69feta5dygT3/HWWhrYUo0+rcn0KpYv9iwMAAKTHLyMAEvFSMID488xuwwZAfEYOgERzzRlGDoDYPHQcINlc825DB4Dzc4AU5pk5wwYAAAAA0Ejs7AIkOgvax8gBEJv72wEAgNppbe9awYtZmqs9DzneUhsy4K6HX/QyS31r+0+aHoasNcH4KElq+HKF0r5W8EDa+rePWa7nb84cf3clSX+trfb6tT0npd6UC++s2Z7e4NW3Ci+9OjvxfvUTz7/p2qlpe+TZN3p1jrNytIuxU3XVI20DQrktL4Vjlh3uO6H6PAcolsbYoUymX3upq6UYLUz9+hRKJ/vXBgAASI9fRgAk4qVgAPHnmd2GDYD4jBwAieaaM4wcALF56DhAsrnmTYYOAOfnACnMM//FsAEAAAAANBI7uwD/L3t3AiVVeSd+P/4zb+adzDvLOzP/OFRDsAtBRJaqbkEkRNxXqGqWEkVRXIlL3HdiJIqCKFExLO5LJGC7a1ziigT3fcG0+27c17iA0M8fmXd8h0Dk3u6u7lu3Pp9zvufMcmZOTlddfs99blU9sZ4F7WtyAETm8+0AAEDH6ZwrjnEwS7qaNnuuW21Iuc+/WBxmX36Pwyz1NzvjkjvDDrsfHzrXNZiNkqTKP0gzV7x6+e3rWu7ggfaQ6Vcc599eSdLfauDQ/e09qV068IQLOux9/pPCz8IHH30Se9/6zgee99oplT36zOstepbT86c7m51KVDet2ys01WalcP26G7gmlNRG2p1swX5mrnh8O7w2E/2lAQAAyse3IwBicSgYQPR1ZsnYAIjO5ACItdZsNDkAIvOj4wDx1prXGR0Anp8DlGGd+QNjAwAAAACoJHZ2AWI9C9rV5ACIzOfbAQCAjpPJFX7pUJZ0ddWNd7nVhpSb/9ALDrLU32zCtMbQe/NxZqIkKRVlcsXns/Wlf3H3DrSn5f/+XOzfYEnS6upSPzycfuFt9qBU9s6esyD0336/DnuvF3Y/Knz51eJY+9bLljWHq29/0uun1PXIM6/Hfo6zePESc1OJ6/weudBUm5XCotpuIZsb5rpQ4uqcK46xM9kiay3/+zWW87XplB92oD8zAABA+fh2BEAsDgUDiL7OLBkbANGZHACx1pqNJgdAZH50HCDeWnOu0QHg+TlAmdaaXxsdAAAAAEClsKsLEOs50EiTAyAyn28HAAA6TiZXuNTBLOnqkSeb3GpDin36ly/DrHkLHWSp1R60O+7wM0OXDUeYh5KkVJTJFb/sVD+0zp070N7W7rvVPy7/d6jJv8WSpNV1wAnn24tSu/SLX18RutQ1dNh7fdzBk8LSZcti7V9//sXicMl1D3r9lKoeWfR67Gc5b739vpmpxHVSzwGhqTYrrWi7Plu6LpTExtqZbJnOA0v/kMkVHyrba5Mr+KFlAACAMvINCYBY7FUBRF9nlowNgOhMDoBYa81GkwMgMj86DhBvrXmB0QHg+TlAmdaanxodAAAAAEClsKsLEOs50HYmB0BkPt8OAAB0nJpc4V6HsqSr9z/8xK02pNgd9z/nEEut0smzbwwDhx1gDkqSUlWnXHEvd+1AR+lUP7Quky9+5d9jSdJft93Y4+xHqd0q7vmrDn2/Tzw9/m9Qfvzpl+GCq+/3+ik1PbLo9djXwVN/etHMVOI6oNfg0FSblVZ0+PqDXBdKXJl8YQ+7kq3az/xxTb7wTjlem875wib+wgAAAOXjGxIAsTgUDCD6OrNkbABEZ3IAxFprNpocAJH50XGAeGvNs40OAM/PAcq01vyz0QEAAAAAVAq7ugCxngNtYnIARObz7QAAQMcp12Ea6ph6Dt7ZbTak2EeffhFmzl3oEEut1IEnnB+6bTzaHJQkpezwzOJl7tiBjpbJFw7zb7Ik6a/r8ZOdw9lzFtiXUrs07eLbQ89Ndu3Q9/z5c66PvZf99vufhnMa7/UaKhU9vOj12NfA/HsfMzOVuEb22Tw01WalFZ3bI++6UPLqV9jHjmQr9zNzxUGZfPGrNn9m07ehh78uAABA+fiWBEAsDgUDiL7OLBkbANGZHACx1pqNJgdAZH50HCDeWnOS0QHg+TlAmdaazxodAAAAAEClsKsLEOs5UM7kAIjM59sBAICO8W8Dtv1nh7Kkq213PsxtNqTYrfc0OcBS//+BuhfdEbbe5RjzT5KUujK5wpOd6of+0F07kABr1eQK1/u3WZL0100440r7U2q3Djzhgg59v3epbwg33XFv7P3sV978IMycu9BrqIrv4adfi/3+v/rG+ealEtegvtuEptqstKL53Xq6LpS8ZwP5ws9sR7Zepl9xXFu/Ntn60r/4ywIAAJSPb0kAxOJQMIDo68ySsQEQnckBEGut2WhyAETmR8cB4q01jzA6ADw/ByjTWvMBowMAAAAAqBR2dQFiPQfqanIARObz7QAAQMfoVD+0zqEs6Wr8UVPdZkNKffDx52HGXIdX6r869vTLw/qb7Gr2SZLSV674SaZvQw937EBSrN13+I8yucJb/o2WJP3Pdvr5VHtUatc23/HIDn3PdxtYCg889kzsfe1FL/zZ66eK76GnX4v93j9vzvXmpRJXba4QnqntFppqs9KKNsjt4NpQouqUH3ag3ci2kckVprfV65LJF79a/v9yLX9VAACA8vFNCYBYHAoGEH2dWTI2AKIzOQBirTUbTQ6AyPzoOEC8tebeRgeA5+cAZVpr3mJ0AAAAAACVwq4uQKznQP9icgBE5vPtAABAx8jUNezoUJZ0Nfns37rNhpT6wz1NDq/UivY+ZkbosuEIc0+SlM5yhVHu1oGkqelX3HT5v09L/TstSfrvBuywn30qtWtTL7g19Bg8pkPf9z1/unN4uuml2HvbDz71qtdQFd1DT78W+33/zTNb81JJbGG3HqGpNiutqKH3Fq4LJau64iF2ItvIkCF/V5Mr3N42z22Kr/qDAgAAlJdvSgDE4lAwgOjrzJKxARCdyQEQa63ZaHIAROZHxwHirTVHGR0Anp8DlGmtOc/oAAAAAAAqhV1dgFjPgdZa3lLTAyASn28HAAA6Rk1u2LEOZUlXv7v6VrfZkEIfffJFmDF3ocMrq7wzLrkzbLPrseadJCm1ZXKFM9ypA0mVyRcn+7dakvTfdalrCFMvuNWeldq1QyZd0uHv/bqt9wivvvF27D3u+Q8+7zVUxfbQU6/Ffs8fedIM81KJrLF7n9BUm5VWdNT6G7sulLBnBMXD7UK24X5m/4Z/z+QKL7TB6/KQvyYAAEB5+bYEQCwOBQOIvs4sGRsA0ZkcALHWmo0mB0BkfnQcIN5acwujA8Dzc4AyrTVnGx0AAAAAQKWwqwsQ+1nQh6YHQCQ+3w4AAHSMmlzxQoeypKt7H3rKbTak0G33PuvgyirvlNk3hvrtxpt1kqQ0H5Z5f69epR+4UwcSa8iQv6vJFe71b7Yk6b/b/xfn2rdSu7f97r/o8Pf+oGHjw7vvx/+M+PwHn/caqiJ78KlXY7/f9zz0FLNSiezs9epDU21WWtH5PXKuCyWto21Ctq1O9UN7ZnKFj1v1uuQKN/hLAgAAlJdvSwDE4lAwgOjrzJKxARCdyQEQa63ZaHIAROZHxwHirTXrjQ4Az88ByrTWnGx0AAAAAACVwq4uQOxnQS+aHgCR+Hw7AADQMWryxYUOZElXb779nttsSJmPPv0izJi70MGVVdwhJ10Sum082pyTJKW4wrs1fYZ3dpcOJN2PNxyRrckVP/XvtiTpm7be5Vh7V2r3fn3xnaHvFnt0+Pt/250PC5/+5fNYe93NzSHcfv9zXkdVXA8+9WrsZzsNexxjViqRHb/+wNBUm5VWtKDbeq4LJapMvjDBDmTbW/53LdTkC8ta/Nrkihf4KwIAAJSXb0wAxOJQMIDo68ySsQEQnckBEGut2WhyAETmR8cB4q01uxkdAJ6fA5RprXmM0QEAAAAAVAq7ugCxnwU9YnoAROLz7QAAQMdYcXC5Q1lSU3ajUli2rNltNqTM7fc969DKKu3sOQvCrodMC53rGsw5SVKKKyzrXFfcxh06UCky/Yrj/NstSfqm7oN2CtPnLLCPpXbvhLOuCesMGNXh18CofSaErxYvjr3nfdeDz3sdVVE9+NSrsd/ng4v7mZVKZON7/TQ01Walb+vdbwfXhhJTJlf4pd3HMu1p5gsTWvy65Asn+wsCAACUl29MAMTiUDCA6OvMkrEBEJ3JARBrrdlocgBE5kfHAeKtNf/N6ADw/BygTGvN8UYHAAAAAFAp7OoCxH4WdIfpARCJz7cDAADtL1tf+hcHsqSrzUYe6BYbUuaTz74MM+cudGhlFXb6BbeFn448xHyTJFVDE92hA5Vm+b9djf79liR907HTLreXpQ5pn2NmJuIa2OeIKWHpsmWx9r2bm0O4/b5nvY6qmB548tXYz3d6DdnFnFQiG95789BUm5W+bWSfzV0bSlCFE+08ls1aNbnCvBa9LrnCwf58AAAA5eVbEwCxOBQMIPo6s2RsAERncgDEWms2mhwAkfnRcYB4a83vL2+p8QHg+TmAZ+gAAAAAQDWzqwsQ+1nQFaYHQCQ+3w4AALS/zrmh/R3Gkq72OORkt9iQMnc+8JwDK6uwSbN+H/pusafZJklKf7nC7d8rlb7vDh2oNF37Ff+1Jld81b/lkqTRB0yxn6UOa9tdj0vEdXDUSTNi7303N4dw+33Peh1VET3w5Kux3t9ff700dK5rMCeVyAb12zY01Walbzt2/Y1dG0pMmXzhZDuPZfys4MDSP2TyxQfjvy7F0f56AAAA5eVbEwCxOBQMIPo604FgADGYHACx1pqNJgdAZH50HCD+evMd4wPA83OAMqwzNzE6AAAAAIBKYVcXIPazoN+YHgCR+Hw7AADQ/jrnimMcyJKuJp5+gVtsSJFP//JlmDlvoQMrq6xjp10euv9kJ3NNklQNh2O+3ql+6H+4OwcqVSZf3KImX1jm33RJqu7qtxtvT0sd1hmX3BlyW++ViGth6ow5sffAm5ubw233Puu1VOK7/4lXYr2333nvQzNSia17blhoqs1K33Zhj5xrQ8kpVzjVrmOZ9zQ3LHZZ/rd+O9br0q+wmb8cAABAefnmBEAsDgUDiL7OLBkbANGZHACx1pqNJgdAZH50HCD+evNJ4wPA83OAMqwz1zM6AAAAAIBKYVcXIPazoONND4BIfL4dAABofzX54kQHsqSriy6/0S02pMhdDz7vsMoq6+cTLwxd+4800yRJqS+TKyzJ5Bs2dmcOVP7+WuF0/65LUnXXua4hnHreLfa21GFNmnlD6DZodCKuhwvn/T72Pnhzc3O44/7nvJZKdPc/+Uqs9/WiZ182I5XoHs52D021WWlF93Xr4bpQcsoVTrXjWH6ZXHFQJl/8Kurr8p+5Qi9/NQAAgPLyzQmAWBwKBhB9nVkyNgCiMzkAYq01G00OgMj86DhA/PXmbcYHgOfnAGVYZ/6r0QEAAAAAVAq7ugCxnwXta3oAROLz7QAAQPvL5AtzHMiSrubf+6hbbEiJzz7/Ksyat9BhlVXUuMPPXHEIs3kmSaqSgzEPdlcOpMG662779zX5wmP+bZek6m7/X5xrf0sd2hGTLwtd6od3+LXwzf5m4/V3tGhP/J5HX/JaKrE99NRrsd7Pd93ziPmoRHfTur1CU21W+ra+/bZ3bSgpzw5OtePYPpb/rXeL+rr8uM8O/6+/GAAAQHn59gRALA4FA4i+ziwZGwDRmRwAsdaajSYHQGR+dBwg/nrzMuMDwPNzgDKtNb80PgAAAACASmBHFyD2c6Ci6QEQic+3AwAA7S+TKz7kQJZ09fJrb7nFhpSY/9ALDqqskqbPWRAKe040xyRJ1dS1y29J13JXDqTFf+YKvTK5whf+fZek6m373X5hn0sd3thDfp2I66Fr/xHhrnseadG++COLXvdaKpF9896MY+61t5mPSnQXd+8Xmmqz0reVem/m2lAyyhVOtdvYjp8dzBfPXNNrkskXFnumAwAAUH6+PQEQi0PBAKKvM0vGBkB0JgdArLVmo8kBEJkfHQeIv96cZnwAeH4OUKa15mvGBwAAAABQCezoAsR+DjTQ9ACIxOfbAQCA9pfJFT52IEt66rrhiPD110vdYkMKfPb5V2HWvHscVFkF/friO8MmIw81xyRJVVTh2X8bsO0/uyMH0qZzvvhz/8ZLUvW2/pCx9rqUiLbZ9dhEXBM9fjI6PPbUcy3aH3/qubfCjLleSyWrR//0Rqz38fTzrzAfleimrtc/NNVmpW87bv2Brg0lpal2GtvRkCF/t/xvfut3vSaZfPENfygAAIDy8w0KgFgcCgYQfZ1ZMjYAojM5AGKtNRtNDoDI/Og4QPz15lHGB4Dn5wBlWms+ZHwAAAAAAJXAji5A7OdAtaYHQCQ+3w4AALSvtfsO/5GDWNLVxkP3dXsNKXH3wy84pLIKmnLuzaFu233MMElS9ZQrfl6TH9bXHTmQUmvV5At/8O+9JFVvJ8243p6XOryzLp0fBg47IBHXRN/Nx4ZXXv9zi/bIn3vl3TBz3kKvqRLTE8++Ges9PGHyOWajEt0RvQaFptqs9G0Xd+/n2lBSmmqbsX117lX6t0yu+Px3PNt5xF8JAACg/HyDAiAWh4IBRF9nlowNgOhMDoBYa81GkwMgMj86DhB/vbm78QHg+TlAmdaavzc+AAAAAIBKYEcXIPZzoB+aHgCR+Hw7AADQvjrVNwx2EEu6GrP/CW6vIQU+/3JxmH35PQ6pTHknz74x9N5snPklSaqqMv2K49yNA2nWJV/IZPKFD/ybL0nV2V5H/8a+lxLRaRfeGvpskYy9x0HDxof3P/ykRXvlr7z5ob1yJaannnsr1vt3r8Mmm41KdLv1HhKaarPSt92f7eHaUDLKFU61y9gRnyMc2jOTK3y82mc7+cKN/kIAAADl51sUALE4FAwg+jqzZGwARGdyAMRaazaaHACR+dFxgPjrzW2NDwDPzwHKtNa8wPgAAAAAACqBHV2AFj0L+tQEAVgjn28HAADaVyZf2NNhLOnquMmz3V5DCvzxkRcdUJnyfvWb60LPTXYxuyRJVVUmXzzXnThQDTr3K+zi331Jqs622Okoe19KTJNm3hC6/2SnRFwbw/c4Jny1eHGL9svffPeTcN6V93lN1eEteuHPsd67Q8ceaTYq0W3XZ8vQVJuVViqX2971oSQ01Q5jB+1r1hW3qckVlq7ymuSKF/rrAAAAlJ9vUQDE4lAwgOjrzJKxARCdyQEQa63ZaHIAROZHxwHirzd7Gx8Anp8DlGmtOdH4AAAAAAAqgR1dgBY9C3rGBAFYI59vBwAA2lcmX5zsIJZ0dc5vr3V7DRXu8y+XhNmX3+OAyhR3wvRrQo/BY8wtSVKVVXis88DSP7gTB6po3+0K//ZLUvXVfdBO4ew5C+yBKTEdderc0HXDkYm4Pn521NSwbFlzi/bNP/j483DJtQ96TdWhPfPi27HetwO229tsVKKr77ddaKrNSis1ss/mrg8loal2FztOTa5wzF+/JplcYYq/DAAAQPn5JgVALA4FA4i+ziwZGwDRmRwAsdaajSYHQGR+dBwg/nrzn4wPAM/PAcq01tzL+AAAAAAAKoEdXYAWPQv6gwkCsEY+3w4AALSvTK5wpYNY0tUtd93v9hoq3L2Pv+xwyhT3izOuXHG4spklSaqqcsVPM30K67kLB6pJp/qh/5HJFf9sDkhS9XX8GVfZB1OiOvjEi0KX+uGJuD5OPvPiFu+df/7F4nD5zY95TdVhPfvyu5Hfr8uWNYeu/UeYi0p0P84XwqJst9BUm5W+7Yheg1wfSkJT7S528GcK84U5K70mdcVD/FUAAADKzzcpAGJxKBhA9HVmydgAiM7kAIi11mw0OQAi86PjAC1bc35ihAB4fg5QhnXm1sYHAAAAAFAJ7OgCtOhZ0PkmCMAa+Xw7AADQvjK5wpMOYklXz77wqttrqGCLl3wdzr3iPodTprQJ0xpDt0GjzStJUrXVXJMfNsIdOFCNOtcVt/mvfwfNA0mqpsYe8mt7YUpc4yfMDp3rGhJxjVx0+Y0t3kNf8vXScMP8RV5TdUjPv/pe5Pfqex98bCaqIlrYrUdoqs1K3zZzvbxrQ0loqp3FjtV1yJD/O5MvPPDfr8ny/3onfxUAAIDy820KgFgcCgYQfZ1ZMjYAojM5AGKtNRtNDoDI/Og4QMvWnE8ZIQCenwOUYZ25vvEBAAAAAFQCO7oALXoWdIIJArBGPt8OAAC0q7VqcsXPHcSSnr45DPHLrxa7vYYK9tBTrzmYMqUdOWVOqN1olHklSarCCqe7/Qaq2fJ/B883CySpuvrpiEPshymRjTnotERcI103HBFuvP3eFu+jNzc3h/kPPu81Vbv34mvvR36fLnr2ZTNRFdHV3XuHptqs9G23rLu+a0NJeK5wml3FBOxr9hneOZMrvPXNa5LJF7fwFwEAACg/36YAiMWhYADR15klYwMgOpMDINZas9HkAIjMj44DtGzNeZMRAuD5OUAZ1pn/aHwAAAAAAJXAji5Ai54F7WGCAKyRz7cDAADtp1P90B87hCVdDdhub7fWUMG+XrosXHDV/Q6mTGGHTbo0dO0/0qySJFVfucK99fX7/l/uwIFqtnbfrf4xkys+by5IUvW0zoBR4axL59sXUyIbvs+JibhOflw/PFx7y4JW7ak/3vSm11Tt2stvfBD5/XnHHx82E1URzVovH5pqs9K3LVpeba7g+lBHN9WuYjLU1A0bmMkXv/rPXKGXvwYAAED5+UYFQCwOBQOIvs4sGRsA0ZkcALHWmo0mB0BkfnQcoGVrztlGCIDn5wBlWmt+YIQAAAAAAElnNxegRc+BtjRBANbI59sBAID2U1M3bHOHsKSr0eOPd2sNFezxpjccSpnCDj7xotBlwxHmlCSpCiu807nfDjXuvgG+973OuYYhy/9dXGY2SFL1dPTUufbGlMjOnrMgbLXLMYm4Trr2HxFuvvO+Vu2rN730Tpg5b6HXVu3Sq299GPm9+btrbjMPVRGd2HOj0FSblVZq0z7buD7U0c8XTrOjmByZfsVxneqH/oe/BAAAQPn5RgVALA4FA4i+ziwZGwDRmRwAsdaajSYHQGR+dBygZWvOCUYIgOfnAGVaaz5uhAAAAAAASWc3F6BFz4F6mCAAa+Tz7QAAQPvJ5As/cwhLujr2lFluraFCLVvWHC659kGHUqasIyZfFn7cf4QZJUmqvnKFpZl8cQt33gD/cy+ueKYZIUnV0+gDptgfU2KbftndYfDwgxNxrXTtPyLcfOf9rdpff+WtD8Osefd4bVX2Xn/7o8jvyzPPu9w8VEV0YK/Boak2K63UXhts1ECriwAAIABJREFU4vpQB1c4zW4iAAAA1ci3KgBicSgYQPR1ZsnYAIjO5ACItdZsNDkAIvOj4wAtW3PuZoQAeH4OUKa15g1GCAAAAACQdHZzAVr0HOiHJgjAGvl8OwAA0H4yueKvHcKSrs697Dq31lChFr3wZwdSpqzjpjWG2o1GmU+SpKosky9McNcNsLJO9UN/mMkXnzMnJKk6Gjh0f3tkSnRnXHJn2Gj5+zQJ10vX/iPCzXfe36o99lfe/DDMmneP11Zl7c13Po78njzm5FnmoSqi0b03C021WWmlJvUc4PpQBz9jKE62mwgAAEA18q0KgFgcCgYQfZ1ZMjYAojM5AGKtNRtNDoDI/Og4QMvWnJsYIQCenwOUaa053QgBAAAAAJLObi5Ai58FvW2KAHwnn28HAADaT02ucIODWNLV7QsecmsNFai5uTlcdsPDDqRMUcefeVXIDtzRbJIkVelhl4Wbvve9E/6Xu26AVXXOFzapyReWmReSlP661A8P0y6+w16ZEt1pF94a+m25ZyKumXUGjAx/mP9Aq/baX3z9/TBz3kKvrcrWn9/7JPL7cc9DTzEPVRFt2meb0FSblVZqbvc+rg91bLniJDuJAAAAVCPfrACIxaFgANHXmSVjAyA6kwMg1lqz0eQAiMyPjgO0bM2ZMUIAPD8HKNNa82AjBAAAAABIOru5AC1+FrTQFAH4Tj7fDgAAtJ+afOFZB7Gkq5defdOtNVSg515512GUKeqkGdeHHoPHmEuSpCqt8G7X/tv/pztugL8tky+eZV5IUnV06KRL7Jcp8Z163i2h7xZ7JuKaWWfAyHDLXfe3ar/9xdfeDzPnLfTaqiy98/5nkd+L2+96hFmoimiD3A6hqTYrrdSD3bq7PtTRTbSLCAAAQDXyzQqAWBwKBhB9nVkyNgCiMzkAYq01G00OgMj86DhAy9acay3vL8YIgOfnAGVYa+5ghAAAAAAASWc3F6DFz4IuNkUAvpPPtwMAAO1kyJC/y+QKSxzCkp669h8Rvv56qVtrqECX3/yYwyhT0inn3BR6DRlrLkmSqrXmTF3DUDfcAN+tU/3QH2ZyxefNDUlKf8P3OcmemSqiyefcHDbYdLdEXDfrDBgZ/jD/gVbtub/42vth5ryFXlu1ee99GP33V+u32dMsVMX0RHbd0FSblVaqb7/tXR/qsDK54vF2EQEAAKhGvlkBEItDwQCirzNLxgZAdCYHQKy1ZqPJARCZHx0HaPm68wljBMDzc4AyrDPXM0IAAAAAgKSzmwvQ4mdBx5siAN/J59sBAID20Tk/bF2HsKSrnzbs57YaKtDLb3zgIMqUdOp5t4Tem48zkyRJ1Vuu+Bt32wAR9+ZyDUNq8oVl5ockpbu6bfexb6aKadKs34eem+ySiGundqNR4fYFD7Vq7/2F194LM+ct9NqqTfvg488jvf+WLWsOXTccYRaqYrq92/qhqTYrrVRD7y1cH+qwMvnCBDuIAAAAVCPfrgCIxaFgANHXmSVjAyA6kwMg1lqz0eQAiMyPjgO0fN15lTEC4Pk5QBnWmT9Y3lJjBAAAAABIMru5AC1+FrSzKQLwnXy+HQAAaB81uYbtHMKSrnY76CS31VCBrrz1cQdRpqDTL7gt5LbayzySJFVzizoPLP2Du22AOPtzxbPND0lKd13qGsK0i+6wf6aK6cTfXB96DB6TiOundqNR4c6Fj7Rq//35V98LM+cu9Nqqzfroky8ivffeff9Dc1AV1eXd+4Sm2qy0UoevP8j1oY7saLuHAAAAVCPfrgCIxaFgANHXmSVjAyA6kwMg1lqz0eQAiMyPjgO0fN15qjEC4Pk5QJnWmi8ZIwAAAABAktnJBWjxc6ANTRGA7+Tz7QAAQPuoqSse4gCWdDXx9AvcVkOFeePtjx1CmYLOuOTO0H/7n5lFkqSqLZMvLM70LeTdaQPEs3bfrf4xkyu8aJZIUro7bNKl9tBUUU2cfk3o/pOdEnH9dBtYCgsffKJV+/AvvPZemDl3oddWbdKnn38V6X331J9eNANVUc3sUReaarPSSs1Y/r5wfajDnjvkikfYPQQAAKAa+YYFQCwOBQOIvs4sGRsA0ZkcALHWmo0mB0BkfnQcoOXrzn2MEQDPzwHKtNb8gzECAAAAACSZnVyAFj8H+ldTBOA7+Xw7AADQPjK5wmyHsKSrS6+42W01VJjr7nzKIZQV3tlzFoTNdjzcHOrAutQ1hPU32TUMHHZA2HbX48JOB54axh83Kxw9dW6YcMaVK5o06/crmjCtMRx28qVhv1+cE8YdflYYvs9JYcioQ0PvzceFLvXD/T0lqaWHW/YrHOkuG6BlavoVN13+b2mzeSJJ6a203yn20VRxHX/mVaHboNGJuIa6L//P8eBjz7RqL/6F194LM+cu9Nqq1X351ZJI77lb737QDFRFdVLPjUJTbVZaqVu69XJ9qAMrHGrnEAAAgGrkGxYAsTgUDCD6OrNkbABEZ3IAxFprNpocAJH50XGAlq87NzNGADw/ByjTWnOGMQIAAAAAJJmdXIBWPQt6zyQB+Jt8vh0AAGgfmVzxbgewpKs/PvCE22qoIO988JkDKFPQyPGTzKB2qMfgMWHADvuFrcccveIg6r2PnhGOmHxZOGnm9WH6b+e3yWs5/bK7w8Szrw3jJ8wOhT0nhvrtxocu9cP9/SVpDS2/t7zje9874X+5ywZouZpccZaZIknpbeCwA+yjqSKbMK0xZAeWEnEd9Ry8c3j86edatSf/7CvvhhlzF3pt1aq+Xros0vvtwnm/NwNVUR3Sa1Boqs1KK7VoeevkC64RdUy5wkF2DQEAAKhGvmUBEItDwQCirzNLxgZAdCYHQKy1ZqPJARCZHx0HaPm6s8YYAfD8HKBMa82DjREAAAAAIMns5AK06lnQPSYJwN/k8+0AAED7qMkX3nEIS7p68+333FZDBblpwTMOoKzw9jl2pvnTRnXdcGTot9VeYdPS4WH4PieGPY6cHg6ddEmYePZ14cxL7+qw1/jM394VjjltXtjpwKlh4ND9Q5f64V4vSfofZfKFD2r6DO/sDhugdbL1pX/J5ItvmC2SlN59j7MunW8/TRXZMaddHmo3GpWIa2mDTXcJi559uVX78s+8+LbXVS1uxtw/Rn6vTTrzYjNQFdXY3kNCU21WWqUhfbd2jahjnj/kivvbNQQAAKAa+ZYFQCwOBQOIvs4sGRsA0ZkcALHWmo0mB0BkfnQcoHVrzw+NEgDPzwHKsM7cyhgBAAAAAJLMTi5Aq54FnWeSAPxNPt8OAACUX6Z/w787gCVdrbvxjqG5udltNVSIDz/5fMXhiw6hrNyOnDIndKkfbgbFKDtwx7DhtvuGLXc+OpT2OyXsc+zMcNSpc8Pkc24OZ89ZUBGv+7SL7wgHn3hRKO75q7DBpmO9rpKUK/gyPUBb7dfli8PMFklKb0efNs+emiq2o6fODesMGJWIa6nv5mPDsy++1qr9+UUvvO11VYs6p/HeyO+z/Y4+zfxTRbV9ny1DU21WWqXdN9jENaKOarwdQwAAAKqRb1oAxOJzzADR15klYwMgOpMDINZas9HkAIjMj44DtG7teY9RAuD5OUAZ1pk1xggAAAAAkGR2cgFa9SzoUJME4G/y+XYAAKD8OtU3DHb4SrracseD3VJDBbn9vmcdQFnB/eo314ZuG482f1ZTj8FjwsBhB4Ttxh4Xdv751LDf8eeFCdOuCKddeGsq3wu/OOPKUNpvcui35R5ef0lVWOEid9cAbasmV5xrvkhSOtvl4NPtq6miO+rUuWGdAaMScT3ltxoXXn7trVbt0T/2pze8rordBVfdH/k9Nmy3o8w/VVQD+20bmmqz0ir9sudA14g6pM654t52CwEAAKhGvmkBEItDwQCirzNLxgZAdCYHQKy1ZqPJARCZHx0HaN3a8zyjBMDzc4AyrTU/NEoAAAAAgKSyiwvQqudAW5skAH+Tz7cDAADlV9OvsI8DWNLVvkee6pYaKsRfvlgcZs1b6ADKCm3qBbeG3puNq+qZ8+P+I0Ju673C5qOPCKX9TgnjJ8wOE6ZdEaZddHtVvzcmnn1d2PnnU0PfLfawNpGU+jK5wov/vl7hn9xdA7SttfsO/1FNrvC+WSNJ6WvIqEPtraniO2rK78I6A0Yl4poasN3e4fW33m3VXv1DT73mdVWsLrnuocjvr/xW48w/VVQ9csNCU21WWqXz18u5RtQxzyHyhT3sFgIAAFCNfNsCIBaHggFEX2eWjA2A6EwOgFhrzUaTAyAyPzoO0Lq15yFGCYDn5wBlWmveY5QAAAAAAEllFxegVc+BakwSgL/J59sBAIDyq8kVpzmAJV1N+c1v3VJDhVj46EsOn6zQzrp0fhg47IDqOUBx8JiwcfHAsMPux4fdDjsjHDrpkjBp5g1h+pwF3g9r6Nhpl4fCnieEboNGW6dISmGFZZ3qGwa7swYo175dYTezRpLSV3bgjuFseypKQUdN+V1YZ8CoRFxXg4aND39+5/1W7dff98QrXldF7nc3PhLpfbV48ZLQpb7B/FPF9VjtuqGpNiut1K3rru/6UEc11k4hAAAA1ci3LQBicSgYQPR1ZsnYAIjO5ACItdZsNDkAIvOj4wCtW3tubZQAeH4OUKa15rlGCQAAAACQVHZxAVr9LOgj0wRgtXy+HQAAKL9MvnCTw1fS1eXX3eGWGirA4iVLw7lX3OfwyQrsm0OPt9n12NTNj851DWGDzXYPm+94ZBi13+QwfsLsMGHaFWHaRbd73dugsy6dH34+8cKw6ajDQpc6h6hKSkm5wqnuqgHKvHeXK9xi5khS+vrlmVfbL1EqOnLKnLDOgFGJuK6GDD8gvPfBx63at7/nsZe9ropU4y2PRXpPvfzaW+aeKrI7uvUMTbVZaaUW1XYLXfMF14javUy+ONouIQAAANXINy4AYnEoGED0dWbJ2ACIzuQAiLXWbDQ5ACLzo+MArVt71hglAJ6fA5RprXmIUQIAAAAAJJVdXIBWPwu61zQBWC2fbwcAAMqvJl942QEs6eqhx//klhoqwCOLXnfwZIW26yG/rvhZ0W3Q6LBx8cBQ2Gti2PvoGeG4aY3hjEvu9Pq2U6fMvjGU9jsl9Bg8xtpFUuUeYpkrPrHuutv+vbtqgPJau19xnZp84TOzR5LS1R5HTrdHotR05JQ5YZ0BoxJxbW035rDw2V++aNXe/fyHXvC6ao1dc/uTkd5PCx98wtxTRdbYvU9oqs1KqzSo7zauEbV7nfoVG+wSAgAAUI184wIgFoeCAURfZ5aMDYDoTA6AWGvNRpMDIDI/Og7Q+vXnh8YJgOfnAGVYZ25llAAAAAAASWUXF6DVz4LOM00AVsvn2wEAgPLqVD/0hzX5wjIHsKSr9z/8xC01JNzSZcvCRdc84ODJCuyoU+eGLvXDK2YmfPOfNb/13mGrXY4Jux4yLRw26dIw+ZybvZYJafpv54f9jj8vDBy6vzWMpIoqky8srskN7+euGqB91OQKB5s/kpSuttr5aHsjSlVHTpkT1hkwKhHX1877nRCWLPm6VXv4dz7wvNdV39kN85+O9F6ad93t5p4qslnr5UNTbVZapdG9N3ONqP3LFbe3QwgAAEA18q0LgFgcCgYQfZ1ZMjYAojM5AGKtNRtNDoDI/Og4QOvXnwuNEwDPzwHKsM7sZJQAAAAAAEllFxeg1c+CDjZNAFbL59sBAIDyyvQt5B2+kq56DdnF7TRUgEUvvO3QyQrs1PNuCesNHpPYGdBj+X+2n444JIwcPyns94tzwi/PujpMv+xur12F9M3rtd3Y40KXDUdY00iqgAMsC8e4owZoR6XS9zP5wgNmkCSlp56b7Go/RKnriMlzQtf+IxNxjR1w3LTQ3Nzc4j38b/5vb1n4J6+r/mY3//FPkd5L02bPNfdUkU3qOSA01WalVTpq/Y1dI2r3MvniFjYIAQAAqEa+dQEQi0PBAKKvM0vGBkB0JgdArLVmo8kBEJkfHQdo/frzbOMEwPNzgDKtNf9snAAAAAAASWQHF6DVz4E2MU0AVsvn2wEAgPLqnCuOcfhKuho69ki305Bw35zjOef3jzh0ssKaPmdB2Lh4YGL+ve8+aKfw0xGHhB33nxIO+tVFYfI5N3udUtKUc28OI8dPCtmBJWsbSUlt4fdKpe+7owZoX5m+hXxNrvi1OSRJ6WnSrN/bC1HqOurUuaHbxqMTcY39atqFrdrLX7psWbjmjie9rlptt933bKT30eETzzbzVJEd1usnoak2K63SjB51rhG1e53qGwbbHQQAAKAa+eYFQCwOBQOIvs4sGRsA0ZkcALHWmo0mB0BkfnQcoPXrzz2NEwDPzwHKtNa8yTgBAAAAAJLIDi5Aq58D/fPylpkoAKvw+XYAAKC8avKFEx2+kq5+PuHXbqch4V56/X0HTlZgo/ab3GH/tnftPzIMHHZAGDn+5PDziReGSbNu9JpUQdMuvj2MPfSMsP4mu1rjSEpQhc+61Dd0czcN0GF7eaebRZKUnsZPmG0PRKls4tnXhl5DxibiOpt1yTWt2s9fvGRpuPzmx7yuWqX5D70Q6T00evzxZp4qst032CQ01WalVbqhey/XiNq9zrmh/e0MAgAAUI188wIgFoeCAURfZ5aMDYDoTA6AWGvNRpMDIDI/Og7Q+vVnzjgB8PwcoExrzZONEwAAAAAgiezgArTJs6DnTRSAVfh8OwAAUF6ZfPEKh6+kqzPOvdztNCTcVbc94cDJCuuQSZeEznUN7fZv+fqb7Bq23PnoMO7wM8OEaVeE6Zfd7XWo4r55/fc9bnbovdk4ax1JHV9dw77upAE6zv/uVfp/anLFV80kSUpHO4w73t6HUtuU824Jddvu0+HX2Tf7ulfdeFer9vS/+GpJuOyGh72uWql7Hn0p0vvnJ4WfmXmqyIb22TI01WalVXoiu27oki+4TtS+5Yb3szMIAABANfLNC4BYHAoGEH2dWTI2AKIzOQBirTUbTQ6AyPzoOEDr158/WN5XRgqA5+cAZVhrjjJOAAAAAIAksoML0CbPghz2C7Aqn28HAADKK5MvPu3wlXR13R/+6HYaEuzt9z912GSFNWnWjaHboNFl/be735Z7hGF7/DIc8MvzwuRzbvZ312qbftndYfxxs0LvzcZZ80jqkDL5wo3LbyPXcicN0OH7ecPMJUlKR3232NOeh1LdtIvvCIOHH9zh11rX/iPC/HsfbdXe/seffRkuvPp+r6u+7YEnX13j+6a5uTnUbjTKzFNFNqjvNqGpNiuttrp+27lO1K51qh/a064gAAAA1ci3LwBicSgYQPR1ZsnYAIjO5ACItdZsNDkAIvOj4wBtswZ9xEgB8PwcoAzrzKxxAgAAAAAkkR1cgDZ5FnSMiQKwCp9vBwAAymjIkL/L5ItfOXwlXS169mW305BgNy54xmGTFdRZl84P9duNb/N/qzfYdLewza7Hhr2PmRFOOecmf2vF6uw5C8KBJ5wf+mwxztpHUvuVK7734/rhndxIAyRDJle8ynySpMqvc11DOP3C2+x3KNVNn7MgDN3jhA6/3tbdeMfw8BNNrdrff+eDz8I5jfd6XbWiRxa9vub3zHsfmneq2NbLDQ1NtVlptTX03sJ1onZt7b7Dau0IAgAAUI18+wIgFoeCAURfZ5aMDYDoTA6AWGvNRpMDIDI/Og7QNmvQ84wUAM/PAcqwzlxreR8aKQAAAABA0tjBBWiTZ0HbmCgAq/D5dgAAoHwyfRt6OHglXXWpbwhffrXY7TQk1EeffBFmzHXQZCVV2LNtDnvttvHosOXOR4fxx80KU8692d9WbXMg8WV3r3hPbbDpWOsgSWUvU9ewo7togOTo3G+Hmppc8RMzSpIqv8NP+a19DlVFOx04NXSua+jQ663v5mPDS6++2ap9/tff/ijMmrfQa6rw5LNvrfH98uhTz5p1quieyK4bmmqz0iod3OsnrhG1a9/shdkRBAAAoBr5BgZALA4FA4i+ziwZGwDRmRwAsdaajSYHQGR+dBygbdag+xspAJ6fA5RprXmXkQIAAAAAJI3dW4A2eQ70HyYKwCp8vh0AACifTrlhRQevpKuNh+7rVhoS7M4HnnfQZAW1/y/Pa/mhXnUNoW6bfcKo/SaHo0+bF6bPWeBvqrJ11qXzw+6Hnxm6D9rJekhSWcrki1e4gwZIns754s/NKUmq/MYcdJr9DVVN+x43K3SpH96h19zg4n7ho48/a9Vef9NL73g9FZ558e01vleuv3WhWaeK7s5uPUNTbVZapWnrbegaUbvWqX7of9gNBAAAoBr5BgZALA4FA4i+ziwZGwDRmRwAsdaajSYHQGR+dBygbdagA40UAM/PAcq01pxmpAAAAAAASWP3FqDNngW9bqoArMTn2wEAgPKpyRePdvBKutrlgF+5lYaE+vzLxWHWvHscNFkhnTz7xpAdWIr1b3CXuobwk4aDwl5H/yZMOfdmf0e1e9MuuiOU9jslrDNglHWRpDas8O7afYf/yB00QAKVSt/P5IsPmlWSVNltWjrcvoaqqoN+dVHouuHIDr3udtz3+PD110tbtef/yDOvez2rvOdefW+N75NZl1xj1qmiu6J7n9BUm5VW6Zv3hmtE7dm/r1f4J5uBAAAAVCPfwgCIxaFgANHXmSVjAyA6kwMg1lqz0eQAiMyPjgO0zRr075f3lbEC4Pk5QBnWmqONFAAAAAAgaezeArTZs6ArTRWAlfh8OwAAUD41+eLFDl5JVyecdr5baUio+x5/2SGTFdL0OQvCwGEHRPp3t0v98DB4+MFh72NmhKkX3Orvp0Q05dybww7jjl/x/rQ+ktTaMnUNO7p7BkiuTnUN9TW5wlIzS5Iqtx6Dx9jPUNV15JQ5oXajUR167R1z8qxW7/v/8ZEXvZ5V3KtvfbjG98gvppxr1qmiO6dHPjTVZqVVerBbd9eI2rVevUo/sBMIAABANfItDIBYHAoGEH2dWTI2AKIzOQBirTUbTQ6AyPzoOEDbrUMfMFYAPD8HKMM6s6uRAgAAAAAkjd1bgDZ7FnSkqQKwEp9vBwAAyqcmV3jYwSvp6rdX3uJWGhJoyZKl4bwr73PIZIW0y0GnrfHf2/7b/yzsfcyMcNqFt/qbKbFNPPu68NMRB1sjSWpxmXzxCnfOAJWwx1f8jbklSZXdKbNvtJehqmvCtCvCuhvv1KHX3oVzf9+qvf/m5hB+f/cir2eV9vb7n67xPbL7QSeZc6rsNUrP/qGpNiuttt65HVwnaq+av/e9761lFxAAAIBq5JsYALE4FAwg+jqzZGwARGdyAMRaazaaHACR+dFxgLZbh55lrAB4fg5QprXmm8YKAAAAAJAkdm4B2uw50E9NFYCV+Hw7AABQJqXS9zO5whcOXklX9z38tFtpSKDH/vSGAyYr5SDXM64MXTYcsdp/Y7MDdwzFPX8VfnnW1f5WqqgOPvGisMFmu1srSYpZ4d21+w7/kZtngOTr2q/4r8v/3X7H7JKkyu3AE863h6GqbOL0a8J6P92lw669rhuOCHff91ir9v+XLFka5t70qNezCvvo0y/W+P7YbOSB5pwqusPXHxSaarPSatum71auE7VLmVzxSzuAAAAAVCvfxACIxaFgANHXmSVjAyA6kwMg1lqz0eQAiMyPjgO03Tp0jLEC4Pk5QJnWmlcbKwAAAABAkti5BWiz50D/sLwlJgvAt3y+HQAAKI9O9UN7Onglfb37/kdupSFhli1rDhdf+6ADJiugMy+9K/TdYs9V/m3tv/3Pws8mnLPif+/vpErtrEvnh10OOi3UbjTKmklStEMq6xp2dOcMUDlqcoXdzC9JqtxGjJ9k/0JV26RZvw8bbLZ7h11/fTYbG15/691WPQf45LMvwwVX3e/1rLI+/3LJGp8PZTcqmXOq6PbYYEhoqs1Kq+2b94frRO3yvCJf+MDuHwAAANXKtzEAYnEoGED0dWbJ2ACIzuQAiLXWbDQ5ACLzo+MAbbcOzRorAJ6fA5RprXm0sQIAAAAAJImdW4A2fRb0sMkC8C2fbwcAAMrjmwPSHbySrtbfZIzbaEigppffcbhkhTR8n5NW+nd1o6H7h4NPutjfRqlqynm3hB12Pz50rmuwfpL0XV3rrhmg4qyVyRfuMsMkqTIbOOwA+xaq6k4975aQ32bvDrsGt97pkPDlV4tb9SzgrXc/CbPm3eP1rKKWLlv2ne+JN99+z4xTxTe89+ahqTYrrbYJ6w90nahdyuQLr9v6AwAAoFr5NgZALA4FA4i+ziwZGwDRmRwAsdaajSYHQGR+dBygbdeibxstAJ6fA5RhnTnEWAEAAAAAksTOLUCbPgv6jckC8C2fbwcAAMqjJl840cEr6WrYbke5je5gzc3N/gis4vJbHnO4ZAV0zGmXhy51DaHz8jYZeeiK/97fRWnu6NPmhX5b7WUNJWk1Fd5du+/wH7lrBqg8neuLfWpyxa/NMkmqvNYZMCpMn7PAnoWqutMvvC1suO2+HXYdHnFi6z+/vuiFP3stq6TZl9+zxvfDfQ8/bcap4tus79ahqTYrrbaZPepcJ2qv5xbP2vkDAACgWvk2BkAsDgUDiL7OLBkbANGZHACx1pqNJgdAZH50HKBt16LXGS0Anp8DlGGd+cPlfW20AAAAAABJYecWoE2fBY01WQC+5fPtAABAedTkC9c4dCVdHXrCWW6jO9iyZc1h4aMvheZmfwv+yxvvfOxwyQrozEvvCn232CP022qvcPTUuf4mqpqmX3Z3GHPQ6aFr/5HWUpK+LVPXsKM7ZoAK3vPLFaeZZ5JUmf3yrKvtV6jqO/3C28KG2+7bYdfh7665rdXPBe584DmvZRV00TUPrPG98M37yXxTpVfXb7vQVJuVVtu16/Z2nai9etSuHwAAANXKNzIAYnEoGED0dWbJ2ACIzuQAiLXWbDQ5ACLzo+MAbbsWPdZoAfD8HKBMa83nKXtkAAAgAElEQVRHjRYAAAAAICns2gK06XOgdU0WgG/5fDsAAFAemVzhRYeupKsZF13lNjoBrr79yXDTgmfC0mXL/DEIN969yOGSFdDo/aeEXQ4+PUy/7G5/D1VlJ828PgwefrD1lKSQyRevcLcMUNn+fb3CP2VyxTfNNUmqvPY5ZqZ9Cml5p194W6jfdt8OuQ6zG5XCM8+93KrnAkuXLguNtzzmtUx5v7vxkTW+Fyaf/VvzTRVfNjcsNNVmpdX2YLfurhO1Vwvt+gEAAFCtfCMDIBaHggFEX2eWjA2A6EwOgFhrzUaTAyAyPzoO0LZr0cFGC4Dn5wBlWmueZbQAAAAAAElh1xagzZ8FvWm6AKzg8+0AAEDb+7cB2/5zTb7Y7NCVdHXLXfe7jU6A+594ZcVhetff9XT4eukyf5Aq9tGnX4QZcx0smfTOunR+OGX2jf4W0vL2+8U5ocdPdraukqq0TL7wwY96D1vbHTNA5cvki6PNNkmqvHYYd7z9Cen/6/QLbgv12+7bIdfiZqN+Hr78anGrng98+pcvw/lX3ee1THFX3vr4Gt8HPztqqvmmVPR4dt3QVJuVVtt6uaGuE7VHt9rxAwAAoFr5VgZALA4FA4i+ziwZGwDRmRwAsdaajSYHQGR+dBygbdeiP1je58YLgOfnAGVYa440WgAAAACApLBrC9Dmz4LmmS4AK/h8OwAA0PY65xqGOHAlfb3w8htuoxPglTc//PZAvatvfzIsWbLUH6VK3f3QCw6WlFSRBxZvN3aCtZVUhWXyhT3cLQOkRyZXvMN8k6TKKr/N3vYmpL/ap6rbdp8OuR6Pmzy71c8IXn3rwzBjrtcxrd1w19NrfA9sN+Yw802paH63nqGpNiutts36bu06UXt0rd0+AAAAqpVvZQDE4lAwgOjrzJKxARCdyQEQa63ZaHIAROZHxwHafj16l/EC4Pk5QBnWmf97ec3GCwAAAACQBHZtAdr8WdD+pgvACj7fDgAAtL1MrniEA1fSVdf+I8LXXy91G50AXy3+eqVDEhtveSx8ufx/RvW9D85pvNfBkpIqtsNP+W1Yf5NdrbOkKimTL8xffqu4lrtlgPT4z1yhVyZXWGLOSVLl1KWuIZxxyZ32JaT/0bSLbg/1243vkGvyD/MfaPWzgvsef9nrmNJuvbdpja//+puMMd+Uiq5bd4PQVJuVVtvYDTZ1nag9nmHMsdsHAABAtfLNDIBYHAoGEH2dWTI2AKIzOQBirTUbTQ6AyPzoOEDbr0cnGi8Anp8DlGmtuch4AQAAAACSwI4tQJs/B9rAdAFYwefbAQCAtleTL/zOoSvpatMRB7iFTpDf3fjISgfrXX7zY+HLr5b4w1SRh59+zaGSklJxaPG2YydYa0lpP4wyV/iiJrdDd3fKAOmTyRfPMuskqbI6eupcexLSX3XahbeGum32affrse/mY8M7733YqmcFy5qbwxW3Pu51TGF3P/TCd772H378qbmm1HRx936hqTYrrbaj1t/YdaLyP8fIF86z0wcAAEC18s0MgP/D3n1HSVXmif/XCTu7s7vf+e7ub8exG3S7xISEasA4KobRMVEFaolxRsesY54ZcXSMmMWAI8bBLNKmMStmQAURFQyUYmKMGECSpKafb6P7211Xur3VXbf7Vt3X65z3OfvHptOXO5/n3qeqnpI4FAwg+jqzYGwARGdyAJS01mwwOQAi86PjAOVfj25pvADYPweIaa05wngBAAAAAJLAG1uAsu8DrdzcTBMGwOfbAQCAGNTW51536Ep1tf+xZ3mETpAnnpv+rcP1Rj3wQvhy4RJ/nBRoXNYUrr1rokMlJVVNRw+9Pqy96Z7WXFK1lh1wgqdkgOq0Ws8d/6W2PveJeSdJldM+x1zkXYS0gs77y5jQa+vfVOT+2xdzF4Yrb3vGdayynp3ybqvX/cWX3zDXVDVdsnbfUKzLSCvs4uZ/H+4TxV1Nff4Sb/oAAABIK9/OACiJQ8EAoq8zC8YGQHQmB0BJa80GkwMgMj86DlD+9ejfN7fQiAGwfw4Qw1pzsPECAAAAACSBN7YAsewF3WHCAPh8OwAAUGaZvoWf1Nbnmxy6Ul2dNfwGj9AJUnxn5goP2Lv5vufD/C8X+wOl9PpLUiV3wchHwrZ7DbHukqrtIMpsfkrfvgf90JMyQPWq7TPwIDNPkiqnbfY43nsIqYXOuuL+sM7me3f4fXnvmPHt3jeY9tbHrmGV9cJr77V6ze96cKy5pqrptHU2CMW6jLTCGtbs6T5R/HsZ9fmzveUDAAAgrXw7A6AkDgUDiL7OLBgbANGZHAAlrTUbTA6AyPzoOEA8a9JxRgyA/XOAGNaZPzNeAAAAAIAk8MYWIJa9oCNNGACfbwcAAMqsNjtweweuVF8N9zzmETpB5sxb2OIhezfd+3yYt2CRP1IVG/3giw6UlFS1HXnatWHNTXa3/pKqoWyusUvvgRt4Sgaodqd8rzabn2z2SVJl1Gvr33j/ILXSKZfcFdbYeHCH3pfZX/w6zP5iXrv3Dh4aP801rKJeffOjVq/3xVePNtdUNR3b/eehWJeRVtjTa6ztPlHs1dTnTvKODwAAgLTy7QyAkjgUDCD6OrNgbABEZ3IAlLTWbDA5ACLzo+MA8axJzzBiAOyfA8S01iwaMQAAAABAZ/O2FiCWfaDeJgyAz7cDAABlVpvND3PgSvX1wsuve4ROmJF3TWzxoL0b7pkU5s5f6I9Uhd6f+YXDJCVVfede/VDYbJejrcGkij+EMn+xJ2SAdKipH7hx83/2N5l/kpT8uvQZGC687nHvH6RWOmHY6PAfG+zaoffm0Sdf0u79gy8XLgnX3DHBNaySps/4tNXrfcwpl5hrqpp+s97moViXkVbYtObWyA5wryjm/Yzcsd7wAQAAkFa+oQFQEoeCAURfZxaMDYDoTA6AktaaDSYHQGR+dBwgnjXpFkYMgP1zgJjWmpcZMQAAAABAZ/O2FiCWfaCVm/vIlAFSzufbAQCA8qrJ5qc4cKX6DtmcO2+BR+iEeXDctFYP27v+r8+FufMX+kNVmfueetVhkpJS0aU3jw17H31h6NpvZ+sxqRLL5mf8e/fCP3lCBkjTO8HcjWagJFVGJwwb7d2D9B0defq1oWufgR16b46bOKXdewjFd2a6flXS3z6a3eq13vk3J5hpqpp26blVKNZlpBbbtNcv3SuKtZr63CHe7gEAAJBWvqEBUBKHggFEX2cWjA2A6EwOgJLWmg0mB0BkfnQcIJ416d81N8+YAeyfAxDDWnOgEQMAAAAAdDZvawFi2wu62ZQBUs7n2wEAgPL5aY8Bq9TW55scuFJdbbD9AR6fE+il4gffeeDejfdOCvO/XOyPVSVmz/0yXDbKQZKS0tWJF90eem69rzWZVGn1zu3oCRkgXbrW52pq63PzzEFJSn77/+FS7xykCB1w/GUdem9uXTgyNC5b1u69hPufetX1q4Jmft7676r22XY/M01V09a9tgnFuozUYoPX29K9orjbx9s9AAAA0sq3NABK4lAwgOjrzIKxARCdyQFQ0lqzweQAiMyPjgPEty69z5gB7J8DEMM685+bW2LMAAAAAACdydtagNj2gvY1ZYCU8/l2AACgfLr0zu3loJXqa58jTvf4nEAzP5sX6dC9m++bHL5c6PPw1eDJSW86SFJSKrvwusfDDr86ybpMqpSyuVs9HQOkU/MMGGIWSlLy22nfk71vkCK2+xHndej9edMdD7d7L2HugkXhytuecf0qvNlzv2zxGn+5cFHo0megmaaqqW/v7UOxLiO12DHdN3GvKNa69MkN8mYPAACAtPItDYCSOBQMIPo6s2BsAERncgCUtNZsMDkAIvOj4wDxrUuPMmYA++cAxLTWHG/MAAAAAACdyZtagNj2gWqaazJpgBTz+XYAAKB8arP5UQ5bqb7OvPg6j88JtGxZU7iyIdqhiKMeeCEsXLTUH62CLb9+V4x+2kGSklLd4adcEzIb7mZ9JiW5bH7Oan0HrerpGCCdVu/f/++b58HbZqIkJbv1dzjEewaphHb41Ukddn/23vpXYe78Be3eU3hx2vuuXYW3cHHL+3rF6TPMM1VV3eoHhGJdRmqxC9bp515RrNXU57f2Zg8AAIC08k0NgJI4FAwg+jqzYGwARGdyAJS01mwwOQAi86PjAPGtS7sbM4D9cwBiWmueYswAAAAAAJ3Jm1qAWPeCXjFpgBTz+XYAAKA8Vu27049r63PzHLZSfd1+3xMenxPqrsemRj58b/RDL4ZFrRzAR7I9/8rfHCIpSc2dcdk9oX7bA6zRpMSWO8bTMUC61WZzBfNQkpLd6uvvEobfPNZ7Biliw296KmycO7zD7tEzL76u3XsKjcuawk33Pu/6VWgjbh3f6vV96IkJ5pmqrimZbqFYl5FW2I1r9XKfKNa61uf6easHAABAWvmmBkBJHAoGEH2dWTA2AKIzOQBKWms2mBwAkfnRcYB416Z/M2oA++cAxLDO3NiYAQAAAAA6kze1ALHuBV1k0gAp5vPtAABAedTWD9jZQSvV2dRpb3p8TqgJU94t6RC+28a8FJYsbfSHqzDLljWF6/76nIMkJek/u+j6x8N2+5xonSYlrJpsbupK/fv/wNMxQOqtXJvNjTMbJSnZnXrp3d4xSCV07jUPh3X779Mh92dmw0KY+emsdu8tvPXeZ65dhXbtXRNbvbZX3PBXs0xV19g11g7Fuoy0wh7qtq77RPHub/TMre2VHgAAAGnl2xoAJXEoGED0dWbB2ACIzuQAKGmt2WByAETmR8cB4l2bjjRqAPvnAMSwzvx+c7OMGgAAAACgs3hTCxDrXtAOJg2QYj7fDgAAlEdtNj/KQSvV12p9B4WFixZ7fE6oGR/OKvkgvvueejUsW9bkj1dBpr090yGSkrSCDhwyIqzebxdrNikZNXWpz23uyRiA5bpkd1p/+WwwHyUpuR36p6u9W5BK7E8X3xFWX79j3kWdfmF5fk/z7sdfdu0qsFsffKHV6/q70/9slqnquqfbeqFYl5FW2It13dwnivuzUat6owcAAEBa+bYGQEkcCgYQfZ1ZMDYAojM5AEpaazaYHACR+dFxgHjXprsbNYD9cwBiWmveYdQAAAAAAJ3FW1qAWPeB/rG5RaYNkFI+3w4AALRfl40K/1Bbn5vnoJXqa/NBh3l0TrBFi5eGy0aVfhjfI8+87o9XQUY/+KJDJCWplcOM19vy19ZtUidXk83d4MkYgP9p+WwwIyUpue1y8FDvFaQ2dOAJIzrkHl1zk8Hhs1lz2r2/8Oms+W3aR1LndvfjL7d6XQftN8QsU9V1w1q9Q7EuI7XYOtkd3SuKrVX77vRjb/MAAABIK9/WACiJQ8EAoq8zC8YGQHQmB0BJa80GkwMgMj86DhDv2vQnzS0xbgD75wDEsNb8jVEDAAAAAHQWb2kBYt8LetC0AVLK59sBAID2q60fsLNDVqqzA447x6Nzwo164IU2Hcg3bvJb/ngV4IOZXzhAUpK+o2HXPhq2KBxn7SZ1UjXZ3Berr7/DzzwZA/CN94U9B3WpzeYXmJWSlMw22/ko7xSkNrb9Pn/skPv03D/fVJZ9hgfHTXPdKqwxTxdbvaY9t9zHLFPVNXztPqFYl5FarH+vbd0riqdsfulKK620srd5AAAApJVvbACUxKFgANHXmQVjAyA6kwOgpLVmg8kBEJkfHQeIf336pHED2D8HIIZ15k+bW2bcAAAAAACdwVtagNj3gg43bYCU8vl2AACg/WqzuXsctFKdXXD5LR6dE+7J56a3+VC+Sa/8zR8w4Rx2KUnRuvTmsWHw4eeGLn0GWsNJHX7gZO4oT8UArPCdYX3+VLNSkpLZWj/fw/sEqY1ddP3jIbvt/rHfp+tstkeYO39Bu/cZPp0133WrsMZNfrvF6/n57DnmmKqyM9bZMBTrMlKLFXps6V5RLNXU52d5iwcAAECa+cYGQEkcCgYQfZ1ZMDYAojM5AEpaazaYHACR+dFxgPjXp8cZN4D9cwBiWmtOMG4AAAAAgM7gDS1A7PtAqzXXZOIAKeTz7QAAQPv8tMeAVWqyuSUOWqnO7h0z3qNzwhXfmdmug/lemf6RP2JCzV2wKIwYNd4BkpJUQkcPvT5kNtzNOk7qsMMmcy/37XvQDz0ZA7AiXTYq/ENtNj/DzJSkZHbOVQ96lyC1sVMv/WtYvd8usd+nN93xcFn2G+598lXXrYJ6/tX3WryWE1541QxTVXbcupuEYl1GarHDu2/qXlFM5d7xFg8AAIA0860NgJI4FAwg+jqzYGwARGdyAJS01mwwOQAi86PjAPGvT9c2bgD75wDEtNY8ybgBAAAAADqDN7QAHbIXNMXEAVLI59sBAID2WbU+/wcHrFRvb7z9nkfnhJszb2G7DuYbMWp8ePeDz/0hE+iZl95xeKQktaGTL74zrLfFPtZyUvw1rdp34KaeigFoTW029yszU5KS2TFDr/ceQWpHex99Yez36Q57/64s+w0ffTrXNaugXn3zoxav5S13jjHDVJUdsN7moViXkVrstHU2cK8olmqyuane4AEAAJBmvrUBUBKHggFEX2cWjA2A6EwOgJLWmg0mB0BkfnQcoGPWqK8bOYD9cwBiWGf2Nm4AAAAAgM7gDS1Ah+wFnWniACnk8+0AAED71GZzrzlkpTqr23DXsLSx0aNzBRh518R2Hc53ZcMz4ZNZ8/whE2Rp47JwzR3POjxSktrY+SPHhE3yR1jTSfF2nSdiACJYuTabe97clKTkteeR53uHILWjS28eGzbOHR77vfpK8e2y7Dvc+ehU161Cevv9z1u8jqdfONIMU1W2a48tQ7EuI7XYFWv3ca8onrK5cV7fAQAAkGa+uQFQEoeCAURfZxaMDYDoTA6AktaaDSYHQGR+dBygY9aow4wcwP45ADGtNd8xcgAAAACAjubtLECH7ANtZOIAKeTz7QAAQNut2nvAzx2wUr1tM/goj80V4sFx09p9QN/IuyaGufMX+WMmxKtvfuTgSElqZ8NveirstO/J1nVSDNVkc1/8tMeAVTwVAxBFTX1+a/NTkpLX1rv/wfsDqZ2dMeKesHq/XWK9V08696qy7DsU35npmlVIH306t8Xr+KsjzzDDVJX9stc2oViXkVrszjV7uFcUz35Hfe4Bb+8AAABIM9/cACiJQ8EAoq8zC8YGQHQmB0BJa80GkwMgMj86DtAxa9QtjBzA/jkAMa01LzNyAAAAAICO5u0sQIfsA32vuY9MHSBlfL4dAABou9ps/i8OWKnefnvihR6bK8RLxQ/KckjfLfdPDosWL/UHTYBRD7zg4EhJKlP7/f7S0LXvIOs7qZyHTPbO/d4TMQClWH5AsRkqScmqx1b7em8glaHBh58T673ac8t9QuOyZe3ed1jauCxcffuzrlkF9MW8hS1ex00GHGyGqSrbpPd2oViXkVrs6TXWdq8onrK5W725AwAAIM18cwOgJA4FA4i+ziwYGwDRmRwAJa01G0wOgMj86DhAx6xRf9jcLGMHsH8OQAxrze2MHAAAAACgo3k7C9Bhe0EjTR0gZXy+HQAAaJvVe+f/b219fr4DVqq3S/9ym8fmCjHzs3llO6jvzkenluVwRtru/Y+/cGikJJW54866MWQ23M0aTypPb3frtt2PPBUDUIouffM9a7O5RnNUkpJT1z4Dw8U3POG9gdTOlt9H623xq1jv18lTi2XZf3hq0puuWQW0ZGnjCq/f4sVLwmp9B5lhqsp69d4hFOsyUou9VrdGWL0+535R2avJ5q705g4AAIA08+0NgJI4FAwg+jqzYGwARGdyAJS01mwwOQAi86PjAB23Tr3O2AHsnwMQwzrzh83NMnYAAAAAgI7k7SxAh+0F7WjqACnj8+0AAEDb1GZzRzlcpbp7ZOwkj80VYtmypnDF6KfLdljfw08X/VE70QNjX3NopCTF0J8uuiOsveme1nlSew+Y7DNwN0/EALTtfWJ+pFkqScnqTxff4Z2BVIaOPO3aWO/V80fcXJb9h89mz3e9Et7y/b6WTJv+rtmlqi2THRCKdRmp1fr12t79ohjKXeCtHQAAAGnm2xsAJXEoGED0dWbB2ACIzuQAKGmt2WByAETmR8cBOm6dOsDYAeyfAxDTWvMGYwcAAAAA6EjezAJ02D7Qj5r7wuQBUsTn2wEAgDZZubY+97qDVaq7jz/53GNzBbnr0allPbRv4tQZ/qidYO78heGyUeMdHClJMXXWFfeH3tvsb60ntf1wyaeXPw96JAagLWp7DupSm80vME8lKTkddtJV3hdIZejSm8eGftsfEtu9uv2ex5ZtH+Kme593zRLc9X99rsVrd++Y8WaXqrqX69YIxbqM1GI79PyFe0VlryabO9lbOwAAANLMNzgASuJQMIDo68yCsQEQnckBUNJas8HkAIjMj44DdNw6dfkBN3OMHsD+OQAxrDXzxg4AAAAA0JG8mQXo0L2gm0weIEV8vh0AAChdlz75XzpYpbrrs+1+HpkrzIQp75b94L43ZnzqD9vBnn7hbYdGSlLMDbv20bBJ/ghrPqn0mmr7DNjIEzEA7VFTnzvTTJWk5LTbYed4VyCVqWOGXh/bvdqlz8DwyWezy7IPMW7yW65Xgmt46MUWr91FV402u1TVPZtZKxTrMlKL7bdef/eKyl82d6Q3dgAAAKSZb3AAlMShYADR15kFYwMgOpMDoKS1ZoPJARCZHx0H6Ni16i1GD2D/HIAY1pk/am6O0QMAAAAAdBRvZgE6dC9okMkDpIjPtwMAAKWrzebucbBKdbfvUUM9MleYdz+cVfaD+64Y/XSY+fk8f9wOsrRxWbjm9mcdGilJHdDwG58M2+41xLpPKulgyfwoT8MAtNe/brDd/6mtz31itkpSMtpqt997TyCVsX7bHxLb/frwkxPLshcxI4b9JJWve598pcVr99sTLzS7VNWN6bZuKNZlpBYbsu7G7hXF0IC9vbEDAAAgzXyLA6AkDgUDiL7OLBgbANGZHAAlrTUbTA6AyPzoOEDHrlV3MXoA++cAxLTWvNXoAQAAAAA6ireyAB26D/QPzc03fYCU8Pl2AACgNKv0zv9HbTbX6FCV6u7CK31WutIsWrw0XDaq/If3XX/3c+HLhUv8gTvAK9M/cmCkJHVgl948NhQOPdvaT4pQTTa/cPmzoCdiAMqhS33+CPNVkpJRr61/4x2BVMYO+uPlsd2vl1xTnt9/b2xcFq5seMb1SmiPPvt6i9duuz2ONbtU1d25Zo9QrMtILTZs7X7uFZW/bH4Hb+sAAABIM9/iACiJQ8EAoq8zC8YGQHQmB0BJa80GkwMgMj86DtCxa9UfBwfcAPbPAYhnrWkPHgAAAADoMN7KAnT4XpDPyANp4fPtAABAaWqzuXMdqlL9PTbueY/MFeiW+yfHcoDfnY9MCY3LmvyBK/T6SZJab7/fDQ9d+gy0BpRaPVQyd66nYQDKpW/fg35Yk829acZKUufXte+gMPzGJ70fkMrURdc/HjIb7hbL/XrIH84r237EvU++4noltKdfeHuF16ypqSms9fPBZpequhvW6h2KdRmpxW5q/jfiXlG5q6kfuLG3dQAAAKSZb3EAlMShYADR15kO9AIogckBUNJa0w+GA0TnR8cBOn69ervxA9g/ByCGdeaPm5tv/AAAAAAAHcFbWYAO3wsabPoAKeHz7QAAQHSr9NrmH2vqc587VKX6+/TzLzwyV6Annpse2yF+y/93E5/3Pp7tsEhJ6sQOPvGKrw4Stw6UVlTuk0zfwk88EQNQTl2y+T3NWElKRqdccpd3A1IZ2+HXJ8Vyr26x8+Fl25OYMOVd1yqhvTDt/RVesw8+/tTMUtU3Yq0+oViXkVrsoTW6u1dU9mp65tb2pg4AAIA0800OgJI4FAwg+jqzYGwARGdyAJS01mwwOQAi86PjAB2/XnXADWD/HIC41pq3GT8AAAAAQEfwRhagw/eB/qm5BSYQkAI+3w4AAES3av2A3zpQpfrbYPsDPC5XqOI7M2M9yG/q6x/6I8fk/qdedVikJHVyR552bVht/Z2tB6X/faBkNn+Yp2EAyu+U79XU514yayWp8zv8lGu8F5DK2BGnjozlXl29385haWNjWfYkps/41LVKaG+8+8kKr9lTz75oZqnqO2ed9UOxLiO12HNrrOleUdn7Wbbw797TAQAAkGa+yQFQEoeCAURfZxaMDYDoTA6AktaaDSYHQGR+dByg49er/9DcHCMIsH8OQAxrzZ2NHwAAAACgI3gjC9Ape0G3mkBACvh8OwAAEFGh8P2abO5NB6pUf/sfe7bH5Qo1Z97CWA/yGzFqfHjv49n+0GU2d/7CcFnz39ZhkZLU+f3u7JtD3Ya7WhNK/3/Z3Gsr9e//Aw/EAMShtnduR/NWkjq/3X97rncCUhk7f+SY0KXPwFju189nl+f3NGfN+dK1SmgffLLiazxy1H1mlqq+P627USjWZaQWm9bc6vU594vKWVPfvgf90Fs6AAAA0sy3OQBK4lAwgOjrzIKxARCdyQFQ0lqzweQAiMyPjgN0zpr1BiMIsH8OQAzrzB8150fBAQAAAIDYeSML0Cl7QQNMICAFfL4dAACIprZ+wM4OU0lHw6+5zeNyBRt558RYD/O75o4JYd6CRf7QZTT+hbcdFClJCeqEYaPDGpsMti6UlpfN7eppGIBY3zlmc2PNXEnq3Lbe/Q/eB0hlrvcv9ovlfn3nbx+WZV+iqakpXDH6adcqgc2Zt3CF12zImZebWar6ju6+SSjWZaRWq++9g/tFZdwDyc/xdg4AAIC0820OgJI4FAwg+jqzYGwARGdyAJS01mwwOQAi86PjAJ2zZv2lEQTYPwcgprXmNUYQAAAAABA3b2MBOmUf6IfNfWoKAVXO59sBAIBoarO5Zxyoko6eevZFj8sV7MFx02I/0O+2MS+FxmVN/thlsGRpYzlljGEAACAASURBVLj69mcdFClJCevUS/8a1tl8b2tDpbqabG7qSiud8j1PwwDEadW+Azc1dyWpc8tuu793AVKZ22zno2K5X6e8Or1s+xO33D/ZtUpgjY3LVni9Bu43xMxS1XfAepuHYl1GarWte23jflEZy73j7RwAAABp5xsdACVxKBhA9HVmwdgAiM7kAChprdlgcgBE5kfHATpnzfr95j42hgD75wDEsNbcyggCAAAAAOLmbSxAp+0FXW4KAVXO59sBAIDvVttnwEYOUklHXfoMDLO+mOtxuYK9VHy/Qw71G/v8W/7YZfDyGx86JFKSEtoZI+4J6/bfxxpRqa2mz8CdPA0D0CHvHrO5e81eSeq8uvbbOQy/6SnvAqQytt3ef4zlfh03cUrZ9iduHzPFtUpYf7ljwgqvVVNTU1h38z3NLFV9g3tsGYp1GanVduuxlftF5ewFb+YAAABIO9/oACiJQ8EAoq8zC8YGQHQmB0BJa80GkwMgMj86DtB569bhxhBg/xyAGNaZ32vuPWMIAAAAAIiTt7EAnbYXtJkpBFQ5n28HAAC+W019/jYHqaSjjXY80KNyhfv4s7kddrjf9Bmf+oO30y33T3ZQpCQluKGX3xfW3Xxv60SlrppsfoInYQA6Sm12UO/a+twyM1iSOq9TL73bewCpjOV+c2os9+ojYyeVbX/i3idfca0S1q0PvrDCa/X+R5+YVUpFO/b8RSjWZaRWO6T7Zu4Xla9s7lFv5gAAAEg73+gAKIlDwQCirzMLxgZAdCYHQElrzQaTAyAyPzoO0Hnr1g2NIcD+OQAxrTUvMIYAAAAAgDh5EwvQaftAKzf3jkkEVDGfbwcAAFq3Wr+dM7XZXKPDVNLR/see7VG5wi1b1hSuGP10hxzud2XDM2HWnAX+6G30/sdfOCRSkiqgoSPuDetuvre1olLVqtkB23gaBqAj1dTnbzKDJanzOuLUkd4BSGVswH4nx3KvPj5+ctn2KMY8XXStEtZ9T726wmv12LjnzSqlov69tg3FuozUan9cdyP3i8pWTX3+Nm/lAAAASDvf6gAoiUPBAKKvMwvGBkB0JgdASWvNBpMDIDI/Og7QuWvX6UYRYP8cgBjWmfXGEAAAAAAQJ29iATp1L8hBwkA18/l2AACgdbX1uREOUklPF1012qNyFbjz0akddsDfLfdPDksbl/mjt8FD46c5JFKSKqShI+4N626+t/Wi0nGIZDb/lCdhADpa174D16jJ5paYxZLUOe1+xHme/6UytuOv/xTLvfrkMy+WbY/iyUlvulYJ64nnVvw7qZdde4dZpVTUt/f2oViXkVpt2Nr93C8q435I7kpv5QAAAEg73+oAKIlDwQCirzMLxgZAdCYHQElrzQaTAyAyPzoO0Llr15ONIsD+OQAxrTVfMooAAAAAgLh4CwvQqftAazfXZBoBVcrn2wEAgJb9tMeAVWqyuS8dpJKeHh07yaNyFXh2yrsdesjfw08X/dFLtODLxWHEreMdEilJFdSZV9wf1ttiH2tGVX1dsgP7exoGoDMsP8jYLJakzmnbPY/37C+VsR1+dVIs9+q4iVPKtk/x1PNvulYJa9Irf1vhtfrtiReaVUpFa2V3CsW6jNRq162Vdb+obNXU58/yRg4AAIC0880OgJI4FAwg+jqzYGwARGdyAJS01mwwOQAi86PjAJ27du3SXKNxBNg/ByCGteYxRhEAAAAAEBdvYQE6fS/oGdMIqFI+3w4AALSspj5/tkNU0tVHMz/zqFwF3v1gVocf9PfK9I/84UswceoMB0RKUgV2xoh7wjqb72XdqCou97AnYQA67V1kv3zXmvr8IvNYkjq+Ptsd6LlfKmPb7/PHWO7Vp5+bWrZ9iicnvelaJaxpb328wmu1zeCjzCqloi7NvZpZIxTrMlKL3dNtPfeLytaq9fk/eCMHAABA2vlmB0BJHAoGEH2dWTA2AKIzOQBKWms2mBwAkfnRcYDOX7+OMY4A++cAxLDO/LfmFhlHAAAAAEAcvIUF6PS9oANNI6BK+Xw7AACwYv+6wXb/p6Y+N9shKump99a/8phcJRYtXhouG9WxB/1dPvrp8Oms+f74ESxb1hSuvWuiAyIlqUIbevn9Yb0t9rF+VHXWN7ehp2EAOlNtNv9nM1mSOr66DXf1zC+VsV/ufUIs9+qEya+Uba/iieemu1YJ628fzf7WdVra2PjVf0abVUpLkzJrhWJdRmqxp9dY272isrVqNr+/t3EAAACknW93AJTEoWAA0deZBWMDIDqTA6CktWaDyQEQmR8dB+j89esexhFg/xyAmNaadxhHAAAAAEAcvIEF6PR9oH9qbp6JBFQhn28HAABWrDabG+IAlXS1zxGne0yuIrfcP7nDD/u7+b7JYWnjMn/87zB9xqcOh5SkCu+My+4Ja226pzWkqqts7h5PwgB0tq71uZqabO5Ls1mSOr5zr37IM79Uprbd64RY7tOJL75Wtr2KxydOd60S1udfLPjWdXr9rb+ZUUpVT3RbJxTrMlKLvdrcatmc+0VlqUuf3CBv4wAAAEg73+4AKIlDwQCirzMLxgZAdCYHQElrzQaTAyAyPzoO0Pnr179vbpaRBNg/ByCGteZOxhEAAAAAEAdvYAESsRd0vYkEVCGfbwcAAL5t9f79/74mm//IASrp6s8jb/eYXEUen/hGpxz49+SkN/3xv8Odj051OKQkVUEnX3xnyGy0m3WkqqWmmt75rKdhAJKgJpu/0GyWpI7v+PNv9bwvlalt9jg+lvv0+SnFsu1VPDbhDdcqYS1e0vit63T3w+PMKKWqe7qtF4p1GanVemR3dL+oLK3ad+Cm3sQBAACQdr7dAVASh4IBRF9nFowNgOhMDoCS1poNJgdAZH50HCAZa9g/G0mA/XMAYlhn/qC5D4wkAAAAAKDcvIEFSMRe0BYmElCFfL4dAAD4tprswEMdnpK+Jr00zWNyFXn1zY867dC/t9//3AVowedfLHAwpCRVUScMGx3qNtzVWlKVXzZ3rydhAJJi1b47/X+19bl5ZrQkdWwH//Fyz/pSmdp69z/Ecp+++PIbZduvePTZ112rBHXlbc+s8Dqd++ebzCilqpvX7BWKdRmp1Tbvta37RWWpptfAtbyJAwAAIO18wwOgJA4FA4i+ziwYGwDRmRwAJa01G0wOgMj86DhAMtawfY0kwP45ADGtNc82kgAAAACAcvP2FSAR+0ArNzfdVAKqjM+3AwAA/0v//j+oyebecnhKulpjo0JYvHiJx+Qq8vkXCzrt4L9r7pgQFny52EVYgScnvelwSEmqso4984bQtd/O1pSq6Fbtk9/MwzAASVKTzZ1jRktSx1Y49GzP+VKZ2mq338dyn055tXyfY3/kmdddqwR1832TV3idfnPMWWaUUtWVa9WHYl1GarWBPbZ2v6gsrdZzx3/xFg4AAIC08w0PgJI4FAwg+jqzYGwARGdyAJS01mwwOQAi86PjAMlZx75oLAH2zwGIYZ25VnNNxhIAAAAAUE7evgIkZi/oRFMJqDI+3w4AAHxTTe/8vg5OSV+7Hui9VzW6+vZnO+3wv7sff9kF+F+WLGkMV932jMMhJakKO/K0kaFrn4HWlarIaupzEz0JA5C4d5TrD/y32mx+jlktSR3XNnsc7xlfKlNbFo6L5T59pfh22fYsxjxddK0SVEv7ahvvdJAZpVR14dr9QrEuI7Xa/utt7n5ROfZGFq+00korewsHAABA2vmWB0BJHAoGEH2dWTA2AKIzOQBKWms2mBwAkfnRcYDkrGMPMZYA++cAxLTWfMxYAgAAAADKyZtXgMTsA/2suSUmE1BFfL4dAAD4HwqF79fW5153eEr6On/EzR6Rq9DyA/g68wDAl4ofuAj/w9Q3PnQwpCRVcQf98YrQpc9Aa0tVXKtmB+Q9DAOQRLXZ/BlmtSR1XH23P9jzvVSm+u9yTCz36WtvvFO2PYuHx09zrRLUoxPe+NY1mr9gofeNSl1nrrtBKNZlpFb7ffeN3S9qdzX1+fe9fQMAAICvfkQHgOgcCgYQfZ1ZMDYAojM5AEpaazaYHACR+dFxgOSsY/+puTlGE2D/HIAY1pq7GksAAAAAQDl58wqQqL2g0SYTUEV8vh0AAPhvtfX5fRycks7GTnjJI3IVmjh1RqceAHj5rU+HT2fPdyH+06gHXnAwpCRVeXsddYG1pSqrbH7aSiud8j1PwwAk0Wo9d/yXmmzuCzNbkjqmzEYFz/ZSmdp8l2NiuU+L02eUbc/iwXHTXKsENWHKu9+6Ri+8/Lr5pNR14robhWJdRmq1oets4H5RGcq96O0bAAAAfPUDOgBE51AwgOjrzIKxARCdyQFQ0lqzweQAiMyPjgMkay17mdEE2D8HIIZ15g+ae99oAgAAAADKxZtXgETtBW1hMgFVxOfbAQCA/1QofL+2Pl90aEr66rbxbmHR4sUekavQjA9ndfohgLfcPzksbVyW+mvxwcwvHAopSSlp54POsMZUxbRqNr+/h2EAkqy2Pne6mS1JHdd514zxbC+VoU0HHRXLPfrG2++Vbd/igXGvuVYJ6uU3PvzWNbrlzjFmk1LXcetuEop1GanVhq/dx/2icjTGmzcAAAD46gd0AIjOoWAA0deZBWMDIDqTA6CktWaDyQEQmR8dB0jWWrZ7c03GE2D/HIAY1pqnGU0AAAAAQLl46wqQuL2gV0wnoEr4fDsAAPC1Ltn8ng5MSWe/OvIMj8dVatHipYk4CHDs82+l/lo8NH6aQyElKSVdevPYsO2ex1tnKvHVZPMfrd6//997GgYg0e8suxf+tTabn2t2S1LHdMKw0Z7tpTL084FHxnKPvvXuB2Xbt7h/7GuuVYJ694NZ37pGfzrvarNJqevw7puGYl1GarXr1+ztflEZ9khyN3rzBgAAAF/9eA4A0TkUDCD6OrNgbABEZ3IAlLTWbDA5ACLzo+MAyVvPjjOeAPvnAMSwzqxpbonxBAAAAACUg7euAInbCzrSdAKqhM+3AwAAy53yvZr63MsOTUln146+3+NxFbv5vucTcRjg3z6andprsODLxWHEreMdCilJKeriG54IG+x4qLWmkn1gZO/c7z0LA1AJaurzZ5ndktQxHXLilZ7rpTK0Sf6IWO7Rd9/7qGx7F/c99aprlaBmzfnyW9eocNBJZpNS137r9Q/FuozUan/t1sP9ovaXzQ/z1g0AAAC++vEcAKJzKBhA9HVmwdgAiM7kAChprdlgcgBE5kfHAZK3nt3TeALsnwMQ01rzLuMJAAAAACgHb1wBErcP9JPm5ptQQBXw+XYAAOCrg2kHOzAlvZXzAD6S57EJbyTiMMDr754UlixtTOU1mDh1hgMhJSmFnfeXMaHHlvtabyqph0XOyfQt/MTTMAAV8e5y/YH/1jy75prhkhR/u//2XM/0UhnaaMDhsdyjf/tgZtn2Lu594hXXKkEtbVz2rWvUa6t9zCalrsE9tgzFuozUao+vsY77RWXYJ8kN8dYNAAAAvvrxHACicygYQPR1ZsHYAIjO5AAoaa3ZYHIAROZHxwGSt579u+Y+NqIA++cAxLDW3NZ4AgAAAADKwRtXgETuBV1tQgFVwOfbAQCAlVauyeamOjAlnW028FCPxlXulekfJeZAwHGT30rd339ZU1O49q6JDoSUpJR22p//GtbYeLB1pxJX8zPgOR6FAagkzfPrPDNckuJv271O8DwvlaENdzoslnv0g48/Ldv+xT1PvOJaJaSRd0381vX5aOZn5pJSWb7nVqFYl5FabXJmTfeL2t2q2fz+3rgBAADAVz+cA0B0DgUDiL7OLBgbANGZHAAlrTUbTA6AyPzoOEAy17RDjSjA/jkAMawzV25umhEFAAAAALSXN64AidwLyppQQBXw+XYAAEi72vr8Lg5LSW9/Ou9qj8ZV7rPZ8xNzKOBlo8aFDz+Zk6q///QZnzoQUpJS3h/OuSV07beztacSU019flHX+lyNp2EAKskqvQb9tDabX2CWS1K89dvhYM/yUhnaYMdDY7lHP/z4s7LtX9z9+MuuVUK6fcyUb12fR8dOMpeUyrbpuU0o1mWkVpvW3Or1OfeM2rlXkst54wYAAABf/XAOANE5FAwg+jqzYGwARGdyAJS01mwwOQAi86PjAMlc09Y0t9iYAuyfAxDDWvNQIwoAAAAAaC9vWwESuxf0hCkFVDifbwcAgJRbuaY+95LDUtLb+OemeDSuck1NIVx127OJORjwpvueD42Ny1Lz97/r0akOhJQkhcNOvjp06TPQ+lMJOSgyf71HYQAqUU02f6FZLknxtsYmgz3HS2Wo3w4Hx3KPfvLZrPLtXzxm/yIpPfLM69+6Phdeeau5pFS2aa9fhmJdRvrOevTe0T2j9tVnwEbetgEAAMBXP5oDQHQOBQOIvs4sGBsA0ZkcACWtNRtMDoDI/Og4QHLXtTcaU4D9cwBiWGf+uLnPjCkAAAAAoD28bQVI7F5Q3pQCKpzPtwMAQJp16ZMb5KCU9NZji73D0sZGj8YpcPfjLyfqcMBnX3onFX/3WXMWOAxSkvRfDT78XGtQJaIu2Z3W9zQMQCVaff0dflaTzX1pnktSvF3wl0c8x0vtrN92B8Vyf342a07Z9jDufHSqa5WQJkx991vXZ/9jzzKTlMr69d4+FOsy0ne2Se/t3DNqV6v12znjbRsAAAB89aM5AETnUDCA6OvMgrEBEJ3JAVDSWrPB5ACIzI+OAyR3XdvHmALsnwMQ01rzHGMKAAAAAGgPb1oBErsP9L3miiYVUMF8vh0AAFJs5dpsfrKDUtLb70671GNxSkyY8m6iDgccMWp8+GTWvKr/u499/i2HQUqS/qtLbx4bfrHH8dah6tRqsvkJHoUBqGQ19flLzHRJircTh93mOV5qZ322OzCW+/Pz2XPKtodx5yNTXKuE9NpbH3/r+my4wwFmklJZ9+xOoViXkb6z7Xtu7Z5Ru/q3tXP/7E0bAAAAfPWjOQBE51AwgOjrzIKxARCdyQFQ0lqzweQAiMyPjgMke2071qgC7J8DEMM6s7a5JUYVAAAAANBW3rQCJHov6EiTCqhgPt8OAABpVVOfH+CQlHT32LjnPRanxLsfzErcAYGjHnghNC5rqtq/+dLGZeHq2591GKQk6RtddP3joX5bB+KqMxuwt6dhACpZbc9BXWrqc4vNdEmKr8NPucYzvNTO4nr/88WceWXbx7h9zEuuVUJ6f+YX37g2s76Yax4ptdVlc6FYl5G+s917bOGeUZuryeYXessGAAAAX/NtG4CSOBQMIPo6s2BsAERncgCUtNZsMDkAIvOj4wDJXtvuYlQB9s8BiGmtOcqoAgAAAADayltWgETvA/1zc1+YVkCF8vl2AABIq5psfpKDUtLbOpvtEZYsWeqxOCUWLlqayEMCJ738t6r9m097e6aDICVJK2zo5feFNTYZbE2qzujjbt22+5GnYQAqXW197hpzXZLia5+jL/T8LrWz3tvsH8v9OXf+grLtY9z28EuuVUKaO3/hN67N2AkvmUdKda/WZUJR+o4O6r6Z+0VtL5uf4Q0bAAAAfM23bQBK4lAwgOjrzIKxARCdyQFQ0lqzweQAiMyPjgMke237/ebeMq4A++cAxLDW7GdUAQAAAABt5S0rQOL3goaZVkCF8vl2AABIo9psfgeHpKS7I0680CNxytx07/OJOyTw8lvHh8+/WFCVf+/bxjiMUpLUcseeeWPo2megdak6+pDIoZ6GAaiOd5s7rlmbzTWa75IUT7n9T/XsLrWzHlvuG8v9ueDLheX75OhDL7pWCWjEreNDU1PTN67NiOvuNI+U6p7PrBmKdRmp1X7ffWP3i9pcTTY/wRs2AAAA+Jpv2gCUxKFgANHXmQVjAyA6kwOgpLVmg8kBEP2rIyYHQOLXt0cbV4D9cwBiWms+bVwBAAAAAG3hDStA4veB/qO5pSYWUIF8vh0AANJo+eEgDklJdw89McEjcco8+uzriTws8PYxU6rub/3Z7PkOgpQkfWd7H32hdak6sNyyVXoNqPM0DEC1qM3mbjXfJSmetiwc57ldamfrbL5XLPfn0qWNZdvLGP3gi65VArrhnknfujaHDbnAPFKqG5dZOxTrMlKrnbHOBu4XtbmabP5Ob9cAAADga75pA1ASh4IBRF9nFowNgOhMDoCS1poNJgdAZH50HCD569t/bO5TIwuwfw5ADGvNvHEFAAAAALSFN6wAFbEXdJOJBVQgn28HAIC06dIn/0sHpKS79bbYKyxevMQjccq8/MaHiT0wcNrbM6vqb/3UpDcdBClJ+s4uvXls+MUex1ufqoPKPexpGIBqUtM7n22ecU1mvCSVvz7bHei5XWpn3Tbevez35mp9B5V1L+PWB15wrRLQXx97+VvXZvNBh5lHSnUPd+seinUZqdWGr93H/aL27Jlc5u0aAAAAfM03bQBK4lAwgOjrzIKxARCdyQFQ0lqzweQAiMyPjgNUxhr3NCMLsH8OQAzrzJWbe9nIAgAAAABK5Q0rQEXsBfVsrsnUAiqMz7cDAEDKrFxTn5vocJR0N+TMyz0Op9Ann89L7IGBI++cEBYtXloVf+eljcvCVbc96yBIqUobdu1jYejl94UTL7o9/O7sm77RkaddG357yjX/1eEnXx0OGHLZVy3/r488beRX/31Dzh/91f/8GSPuCWddcX+4YOQj4ZIbnvT3TWkXXf94qN/2AGtUxV8250voAFSdmvrc/ea8JJW/bhvv7pldamf/scGuZb8319xkcFn3M265f7JrlYAenzj9G9dl3vwvQ9e+A80jpbq7u60XinUZqdWuW7O3+0VtrqY+d5I3awAAAPA137QBKInPYwNEX2cWjA2A6EwOgJLWmg0mB0BkfnQcoDLWuP+2/GtlxhZg/xyAGNaavzayAAAAAIBSebsKUDF7QfeZWkCF8fl2AABIk5r6XM7hKHruxdc8DqfQsmVN4YrRTyf20MCxz79VFX/n19762CGQUgU1/KanwtDL7wt/OOeWcPAfLw+DDz835PY/NWy71wlhs12ODuvvcGjoufW+Yc1Ndg9d+8R/kOny/zu9f7Ff2GjA4WHL3X4XBux38lf/Px14wohw7Jk3hlMvvTtcdP3jrl2Vtfzf4BqbDLZOVYzlZnbvXvg7T8QAVJtV+w7c1JyXpHjy/kFqX3G8S+y55T5l3c+48d5JrlUCev7V975xXSa++Jo5pNR365o9Q7EuI7XaXWv2cL+oza2aze/vzRoAAAB8zTdtAEriUDCA6OvMgrEBEJ3JAVDSWrPB5ACIzI+OA1TOOvcSYwuwfw5ADOvMHzb3rrEFAAAAAJTC21WAitkL2szUAiqMz7cDAECKrFxTn3vJ4SjpbpMBB4empiaPwyl1+5gpiT008LJR48Ons+dX/N/4todfcgiklLDOuerBcNxZN4YDh4wIux12Tvjl3ieEjXY6LKy7+d6xHG7bEXXbePew/g6HhG33GhJ2/+154dA/XR1OuvC2cPENT7jmFdrRQ68PXSr036Mqodz5HocBqFa12dxYs16Syt+pl97teV1qY8NvfDKW+7Lfdr8p637GdX99zvVKQG+8+8k3rsvIUfeZQ0p9I9fKhmJdRmq1x9dYx/2itpcduL23agAAAPA137IBKIlDwQCirzMLxgZAdCYHQElrzQaTAyAyPzoOUDnr3K7NLTa6APvnAMSw1jzK2AIAAAAASuHNKkBF7QWNN7mACuLz7QAAkBa12VzBwSgadsUoj8IpNm7y24k+OPCOR6ZU9N/3s9nzHQApdWIXXf94OHHYbeHAISNC/oDTwib5I0K3jXdP1Zzv2mdg6Ln1vmHr3X8fBh9+bjjytGvD2Vc+4N9HhTTowNOtVxVLP8vmunsiBqB633kO3N68l6Tyd9xZN3pWl9rYsOsejeW+/HnukLLuaVxzxwTXKwF9/Nncb1yXY065xBxS6huxVp9QrMtIrfZsZi33i9pcTe981ls1AAAA+Jpv2QCUxKFgANHXmQVjAyA6kwOgpLVmg8kBEJkfHQeorLXu9UYXYP8cgBjWmT9u7hOjCwAAAACIyptVgIraCxpgcgEVxOfbAQAgFQqF79dmc685GCXddekzMLw94wOPwin2xrufJP7wwOI7Myv27/vkpDcdACl11MG01z4Wjh16Q9j9t+eGrXb7feix5b5fzTnzfsWtvdleYcvCcWHPIy8Ivzv75nDR9Y/7d5TAht/4ZOi7/cH+zaq8ZXPPeyAGoMqt3DzzXjD3Jam8HTDkMs/qUhs79+qHYrkvtyocUdY9jSsbnnG9EtCXC5d847psM/goc0ipb9g6/UKxLiO12tTMGu4Xtbmf9hiwildqAAAA8DXfsgEoiUPBAKKvMwvGBkB0JgdASWvNBpMDIDI/Og5QWWvd9ZprMr4A++cAxLDWPNnoAgAAAACi8lYVoKL2gVZu7mXTC6gQPt8OAABpUFuf38ehKMrve7zH4JSbM29h4g8PHHnnhLBo8dKK+9suWdoYrrrNAZRSXJ115QPhsJOuCrnfnBrqtz0gdOkz0GxvR137Dgob7nRo2OvI88MfhzWE4Tc95d9ZQho64t6Q2XA3/05VvrK5ozwRA1DtVs0O3MPcl6Tyttth53hOl9rYmVfcH8t9uf1ex5V1X2PEqPGuVyd3ZcMz37gmixYvDquvv7M5pNR3xjobhGJdRvrOVq/PuWfUhn2T/NKVVjrle96oAQAAwNd8ywagJA4FA4i+ziwYGwDRmRwAJa01G0wOgMj86DhA5a13bze+APvnAMSwzvxJc7ONLwAAAAAgCm9VASpuL2h30wuoED7fDgAA1a5v34N+WJPNvelgFN1696Megwl/uWNC4g8RHDf5rYr7u7765scOgJTK1KU3jw2nDL8r7Pf74WGbvYaEdTff2xxvoa59B4V1++8TNtrpsLDV4N+FAfud/NWh1/sed3E49KQrJG7rpwAAIABJREFUw7Fn3hBOuvC2MPTy+8K51zwcLhj5SBh23WP+nSW8w0++2r9vle1gyFV6Dfqpp2IAql7//j+orc+9Y/5LUvnabu8/ekaX2thpf747lvty0H5DyransaypybVKQKMeeOEb12XKq9PNIKm5E9bdKBTrMtJ31j27k3tGJVdTn3vPyzQAAAD4b75hA1ASh4IBRF9nFowNgOhMDoCS1poNJgdAZH50HKDy1rvrLf/6nxEG2D8HIIa15unGFwAAAAAQhTeqABW3D/S95l42wYAK4PPtAABQ7Wp75w50KIrW2XSPsODLhR6DCfc++WriDxEcMWp8+Gz2/Mp6w/LQiw6AlNrRRdc/Ho48/dqw475/CutsvrfZ/T9aa9M9wyb5I8IOvz4p7H7EeeGQE68Mx583Kpx5xf1h+E1P+fdTpS2/F/z7V/sPhszf54kYgNS8A83mjjL/Jal8bZz/redzqY396eI7Yrkvdz/k5LLtaSxZ2uhaJaAHx037xnW56Y6HzSCpuWO7/zwU6zLSd7Z+7+3dM2rL3slz3qQBAADAf/MNG4CSOBQMIPo6s2BsAERncgCUtNZsMDkAov8klskBUJFr3juMMMD+OQAxrDP/b3OzjTAAAAAA4Lt4owpQkXtBe5hgQAXw+XYAAKhm3bpt96PabH6GQ1E05MzLPQLzledenlERBwne8ciUivmbfjp7vsMfpTY09PL7wn6/Gx42HXRUWL3fLqme0136DAzrbfGrsPkux4SdDx4aDjxhRBhy/uhwwchH/FtJaRff8ETIbru/dazaezDkYE/FAKTFv3cv/FPz7JtlDSBJ5Wn5ewrP51LbOmHY6Fjuy18feUbZ9jUWLlriWiWgCVPe/cZ1Wb6fawZJ+XBI981CsS4jfWdb9Pqle0all83f7U0aAAAA/DffsAEoiUPBAKKvMwvGBkB0JgdASWvNBpMDIDI/Og5QmWveHs0tM8YA++cAxLDWPN0IAwAAAAC+i7epABW5D/S95l42xYCE8/l2AACoZqvWD/itA1G0vKnT3vQIzFdmfDirYg4TnD7j04r4mz7x3HSHP0oRuvTmsWHI+aPDzgcPDb1/sV9qZ3LXvoNCdpv9w3Z7/zH8+riLwx/OHRWGXfuYfyP6VqcOvyv8xwa7WsuqrYdCLlil1zb/6KkYgDSpqc+daR3w/9i7Eyipyjvh/yaZzMw7eeed/Cc5MTYY062iUZRqGre4a4xLoArQEve4J2pwixvGDXeDRiPiEhFxQaXdEMUNBUVAFFEQ0QZRFFAURQTZ6e7nX5CoIDR1q6nbXVX9+ZzzPWfOmZyZULdv/Z57b1U9kpSn+xcduq68l+P6XMq9c66+L5bz8sSzr8nbc42vFi5xrAqgmmmfrnZcfnfkWWaQlOnorXcLNeUVUtb232Zv54xyriyRvNVdNAAAAPiWb9gA5MSmYADR15lpYwMgOpMDIKe1ZrXJARCZHx0HKN517yPGGOD5OQAxrDN/nGmuMQYAAAAArIu7qQBF+yzoUFMMKHA+3w4AAKVqo6qO/1WWSH5sQxTtf9iZLn/5xuKly4tmM8G7B48NtXV1Bf16LlteG/7x4GibP0rr6NKbBoduJ18dtt7jqBY5h9vudXTY74jzw7Hn3BT+cl11uOGe4f4uFLnjzultPavGbQpZmXrQVTEALc0m2x3w88wMXGItIEn56arbnnRtLjWiMy+/O5Zzsvtf/pa3Zxtfzl/sWBVAn3w+/9vnTcuWh/IdDjJ/pEyHtd0j1JRXSFk7qO2ezhnl/vwkkbzIXTQAAAD4lm/YAOTEpmAA0deZaWMDIDqTAyCntWa1yQEQmR8dByjedW/bTHVGGeD5OQAxrDUvM8YAAAAAgHVxJxWgaJ8DfT/TRJMMKGA+3w4AAKWqLJE6y2YoWtE9Dz3t8pfV3Pv4a0WzoeD4mpkF/VpOmjrLxo/SWrqm7zPh6D//PXQ44A8tauau2PR0z/Tp4YRzrg9X3/JwGPjk2PDYsInhoWcnhIFPvxHuGTw29B/0avjHgy/7O1Gkeg8YEXbtepo1rXLfFLJ954NdFQPQIu+JViZvtxaQpPzU49qBrs2lRnRqz36xnJNnXXpT3p5tzPlyoWNVAC1ZuvybYzL+rSlmj/Sv0m33DDXlFVLWjmq7u3NGudcueYI7aAAAAPAt364ByIlNwQCirzPTxgZAdCYHQE5rzWqTAyAyPzoOUNxr30eMMsDzcwBiWGf+ONNcowwAAAAAaIg7qQBF/SzoMJMMKGA+3w4AAKXoJ1sk/7tVZXK2zVDUZuduYf6ChS5/Wc3Q0ZOLZkPBvg+9vNqmggV3Z+XpN2z8KP2r6+8aFk6+4B9htwPPCBtXdWkRc3bzX3cLh518cbix74Nh7Ph3wvLltZHfP2rr6sOCRUvD53MXhOmz5obJH8wOEyZ/FMZM+GDl+/TDQyeEOx99xd+WwpW3PRkqdkxb2yp6idTCDbfd50eujAFoiTaq6rhlq8pknTWBJK1/p1zc13W51IhW3CON45y84Op/5O3ZxqdzvnKsmrl+j4xZ7ZjcOXCI2SP9q9Q2e4Wa8gopaydvvYtzRjlX1r5zR3fQAAAA4Fu+XQOQE5uCAURfZ6aNDYDoTA6AnNaa1SYHQGR+dByguNe+22aqM84Az88BiGGteYlRBgAAAAA0xF1UgKJ+DvSDTG+ZZkCB8vl2AAAoRWWVyb/YCEUrOv+qW136soYJkz8qqo0FR77+fkG+jrNtOimtrOdNg0Lq+J6hYseDS36uVuyQDof88aJwY98Hw9jx74Tly2tjf6+prasLc+cvCtNnzQ1vvTsrvDTuvTDo+Ymh70Mv+/trQZ14/q3Wtoq+IWRl6kFXxQC0ZK0SqcesCSRp/Tv6zze4Jpca0Qk9bo7lnLzs+jvzds/x49nzHKtm7pHn3lztmJx24Q1mj/Sv9t/mN6GmvELK2llb/do5o5zbqH3nKnfPAAAA4Fu+XQOQE5uCAURfZ6aNDYDoTA6AnNaa1SYHQGR+dByg+Ne/9xpngOfnAMSwzvy/mT41zgAAAACAtXEXFaDonwWlTDOgQPl8OwAAlJpN2qV+XFaZ+sJGKGrdvnOY/N50l76s4ZPP5xfVxoK3PDAqzPtqccG9jsNffdfGj2qx3ThgROh+Sb/w61T3lfOmlOfpngd1D5dce0cYPmpcWLR4SUG9Dy1YtDR88PEXYdykGeGZUTXh3ide8/dZwu1x0JnWuIpUWWXyEFfGALRkG7VP7WpNIEnr30F/vNL1uNSIjjm7dyzn5F/7DMjbfcXps+Y6Vs3csFfeXe2Y7N7lFLNH+le/2WafUFNeIWXtoi13dM4o537WttOG7p4BAADAt3y7BiAnNgUDiL7OTBsbANGZHAA5rTWrTQ6AyPzoOEDxr39/mWmpkQZ4fg5ADGvNM40zAAAAAGBt3EEFKIlnQaNMNKAA+Xw7AACUmlaJ1GU2QdGKuv3hQpe9rFVtXV245YFRRbW54NDRkwvqNVy2rDbcVj3axo9qcV1/17BwzFk3hq33OKpk52ebnbuF4/98dbh/0NDw8SefF917/KLFy8J70z8PL417Lwx86o3Q5/6R/nZLpGtufzpsttMh1rlaZ2WJ5LKKqvT/uDIGoKUrS6TGWhtI0vq1/5Hnux6XGtGRZ1wfyzn59775+/33aTPnOFbN3OvvzPzmeMybvyC0bt/Z7JH+1W7b/jbUlFdIWbt6y+2cM8rxGUpq8QYbbPA9d84AAADgW75dA5ATm4IBRF9npo0NgOhMDoCc1prVJgdAZH50HKA01sB9jDTA83MAYlhn/memD400AAAAAOC73EEFKIlnQbuaaEAB8vl2AAAoJRtVdfxpq0Rqvo1QtKKnho1x2UuDHnxmfFFtLtjn/pfCnC8XFszrN2nqLJs+qkV1Td9nQvqkq8Kmv+5WkjOzat9jw3lX3BKGjRwXlixdWlLv98uW1YYPP/4ivDx+Wnjgydf9PRd5J190u3Wu1l0i+ZwrYwDYYIPW7ZKHWxtI0vq1S5fTXItLjeiwU3vFck7eevegvN0znDr9M8eqmZs2c843x+PFl98wd6RV2mnb/UJNeYWUtd5bVDlnlFNlidS77poBAADA6nyzBiAnNgUDiL7OTBsbANGZHAA5rTWrTQ6AyPzoOEBprIF/lmm+sQZ4fg5ADGvN44w0AAAAAOC73D0FKJlnQU+bakCB8fl2AAAoJa0qk71sgqIV7XDA8aG2rs5lLw0a8dp7RbfB4JARbxfM6/fgM+Nt+qgW0V/7PhsO+dM1oWKHg0tuVu554J/CFX+/K7zyxtuhvr6+xbz/z1+wOEyY/FEY9PzEcPMDI/2dF2G/OeQc6101XCJ5qitjANhgg6qqE39YVpmcYX0gSY2vct/jXYdLjSh90lWxnJN3DhySt3uENdM+dayaubnzFn1zPG64faC5I61SVbv9Q015hZS1O9q0c84o12coz7lrBgAAAKvzzRqAnNgUDCD6OjNtbABEZ3IA5LTWrDY5ACLzo+MApbMOvtJYAzw/ByCGdeYPMr1trAEAAAAAq3L3FKBkngW1y2QzY6CQ+Hw7AACUil9UddmoVSK10CYoWlGf/o+45GWdinXDxE8+n9/sr92cLxfa8FEl3zW3Px1Sx18aNtnuwJKZjb/c/sBw6EkXh34PPBFmfDzbIMhYsnR5mPLB7PDMyHfCbdWj/e0XSX+949nQZpfDrHm11n7RoWuFq2MA+KdWidT51geS1PhWXHu6Dpdyr+uJl8VyTt736NC83RecNPUTx6oZu/mBkaGurv6b43HM6VeYO9IqtW33u1BTXiFl7YHNt3HOKNf6u2MGAAAAq/NpaoCc2BQMIPo6M21sAERncgDktNasNjkAIvOj4wClsw7+caY5Rhvg+TkAMaw1DzLWAAAAAIBVuXMKUFLPggaabEAB8fl2AAAoFa0qk31sfqIVbbpjOnzx5XyXvKzT3PmLinKjwUeee7PZX7uXxr1v00eVbNf1fz50O/nq8MvtDyqJmbhJh67hsJMvCQ889lyYN3+BN/91WLasNtS8/2l4bNhE50IRdNIFt1n3ao3KKlNvuTIGgG9tVNXxp2WJ5CLrBElqXK3bdw433vui63Apx5LHXhLLOfnIkBfydi/wzckfO1bN2L1PvLba8Uj85mhzR1qlLRIdQ015hZS1wZtt7ZxRjiUvdccMAAAAVucT1AA5sSkYQPR1ZtrYAIjO5ADIaa1ZbXIAROZHxwFKay18ltEGeH4OQAzrzO9lGmO0AQAAAABfc+cUoKSeBW2eaZnpBhQIn28HAIBS8IsOXSvKKpNLbX6iFZ1zWR+Xu0Ry+0MvF+VmgzM+mdtsr1ltXX244+ExNn1UybVig+RjzroxtNn50KKfgxtXdQ4HnfCXcPeDT4U5c+d5s2+EL+YtDKNefz/0e8T7XSG3c+dTrX313c0ge7k6BoDVlSWSt1kjSFLju/ofT7kGl3Js/yP/Esv5OOS50Xm7//fGOzMdq2bsiRcnfXMsZs6abd5I36ki0SnUlFdIWXt+0y2dM8qtdskT3C0DAACA1fnUNEBObAoGEH2dmTY2AKIzOQByWmtWmxwAkfnRcYDSWgv/e6Z3jTfA83MAYlhr7pip3ngDAAAAAFZw1xSg5J4F3WC6AQXC59sBAKAUlCWSd9v8RCtq3b5zmPL+DJe7RPLYsIlFudngw0MnNNtrNnX6ZzZ8VMl19tUDQrt9jiv6GbjngX8Kfe58OHwye443+Dypq6sP7834vGjnRal3WZ/BYZMOB1oD65s2atf5t66OAeA79023SW6RmZP11gqS1LguuP4h1+BSju3V7axYzsfnRozN232/sW9Nd6yasVGvv//NsRj87EjzRvpOG1cmQ015hZS1lyq2cM4ox89UpfZ1twwAAABW59PSADmxKRhA9HVm2tgAiM7kAMhprVltcgBE5kfHAUpvPXyw8QZ4fg6Ae68AAAAAQJzcMQUouedA/1+mz004oAD4fDsAABS7jdt12rpVIllr8xOt6KhTL3OpS2Qvj59WtBsOzvhkbrO8ZoOHv2XDR5VMl9/yRNjz4D8X9dzb4YDjw3W33h8+nPmJN/WYfT53QRj+6rvhloGjnD8FVLdTrrEG1srKKlNLNqrq+F+ukAFgTWWJ5NPWC5LUuE6/7C7X31KO7dLltFjOx5GvTsjbvb4xEz5wrJqxSVNnfXMsLrv+TvNGWktvlW8aasorpHX26qabO1+UUz9PJLdypwwAAABW5xPSADmxKRhA9HVm2tgAiM7kAMhprWljV4Do/Og4QGmuiV8y4gDPzwGIYZ1ZnmmJEQcAAAAAuGMKUJLPgs4w4YAC4PPtAABQ7FpVJh+18Ym+btSrb7rUJbKp0z8r2g0HH3mu6f/Wv1q4JPS5f6QNH1X03Xjvi+Hw064Nm2x3YFHOuk13TIfuf/lbeOmVCaGurn7Nc3XBojBz1uzw9pRpYcLbU1f+50aMGR+eHj4mPP7syPDIkBfCfY8OXfk/f91Tw15e+Z9Z0eixE8OkydNW/t9Y8X+L1S1YtDSMeO29cMvAUc6nAujvd78Qttn7aOtghbJE6nlXxwCwdq0rO+1nvSBJjeuEHje7/pZybLsDTorlfJww6d283eMb9fr7jlUz9tHsed8ci67HnW/eSGvp9fLNQk15hbTOJlRs5nxRTv1ki+R/u1MGAAAAq/PJaICc2BQMIPo6M21sAERncgDktNasNjkAIvOj4wCluSbeIVO9MQd4fg5ADGvNXkYcAAAAAOBuKUBJPgf690xTTDmgmfl8OwAAFLPW7Tpv36oyVW/jE61o30PPcJlLTuYvWFLcmw5++mWTvl5jJ0632aOKvguvfzi03++Eopxze6W7hx5X3hLuHzQ03Hr3oHBxr77h5POuDV2P7RF27XxS2HavI8MmHbrm/f/vJtt1De32Pirs1uXk0Omoc8KR3S9d+d+jT/9HwuBnR4bxb00Jn38xr8XNkAWLloYRr70Xbhk4yrnVzJ111QBrYYVWiU49XCEDQIO+1yqReseaQZJy77BTe7n2lnKs3W+OjeV8nDptZt7u7b342lTHqhlbuHjZyuNQW1cX2uzczbyR1tKYijahprxCWmdvl28aWjtfFLGyytQXbpEBAADAmnyrBiAnNgUDiL7OTBsbANGZHAA5rTWrTQ6AyPzoOEDprovvN+YAz88BiGGd+eNMnxlzAAAAANCyuVsKULLPgrqackAz8/l2AAAoZq0SyedsfKKve3jIcJe55OyOh8cU7aaDg56f2GSvU319CHcPHmuzRxVtN977YkifdGXYuKpLUc641u07F/x/x81/3S3sle4efn/qZaHndf3C/YOGhgmT3g2LFi8p6Tkyf8GS8OzoGudZM/fbw3tYD7fwWic6bucKGQAatlFlpz9ZM0hS7iWPvcR1t5RjW+52eCzn4yez5+Ttnt7zY6Y4Vs1U34de/uY4vD1lmlkjNdCITbcINeUVUtZ+WZl0zihSZZXJ8e6QAQAAwJp8owYgJzYFA4i+zkwbGwDRmRwAOa01q00OgMj86DhA6a6LN860yKgDPD8HIIa1ZndjDgAAAABaNndKAUr6WdAIkw5oRj7fDgAAxaqsMrW3TU/0dVX7HhuWL691mUvOBg9/q6g3H/x49rwmeZ2mz5prs0cVbT1vGhQ67HeiedlMbVzVOeza+aTwp7/8LfS7/4nwxsQpYdmy5SU3T2bP+So88tybzrlm6prbnw6b7tTNOddSS6Tmb5BO/8BVMgA07CdbJP97xcy0dpCk3Nqr21muu6Ucq9jh4FjOxwULF+ftXt5TL73jWDVTK+6hfu2+R541a6QGGrbplqGmvELK2haJjs4ZRXyWknzcHTIAAABYk2/UAOTEpmAA0deZaWMDIDqTAyCntWa1yQEQmR8dByjttfGVRh3g+TkAMawzf5jpbaMOAAAAAFoud0oBSvpZUFWmOtMOaCY+3w4AAEXqe2WJ1Bibnujr+vR/xCUujTLmzQ+KevPBx4e/1SSv0zOjamz2qKKr94AR4bhzeodfbn+QWVlgle9wUOhyzHmh180DwuixE8OSpUtLZq5Mmzkn9B/0qnOwGVpxvju/WmrJZ1wiA0B2rRKp3tYNkpRbO3Q8yTW3lOM92dbtO+f9XNy4qnOor6/P2z28x4ZNdLyaqRfHTv3mOJx9WR+zRmqgpzfdKtSUV0hZ26bdAc4ZRX2W0sfdMQAAAFiTb9QA5MSmYADR15lpYwMgOpMDIKe1ZrXJARCZHx0HKO218X9l+sC4Azw/ByCGtebeRh0AAAAAtFzukgKU/LOg20w7oJn4fDsAABSjjdqlOtvsRF+31e6Hh/kLFrrEpVHen/F50W9A+PncBbG+RouXLg+3DBxls0cVVdf1fz7sfcg55mSRtOmO6dDtDxeG2+4ZFKZN/7joZ8vSZctXbg7b537nYlN244ARIbHPcc6pFlhZInmRq2QAyO7nlZ1/lZmd9dYPkhS9rfc4yjW3lNN92ediORe33OXQvN6/e+jZ8Y5XMzVxyrf3f/fpdppZIzXQ4M22DjXlFVLWOmy7v3NG0Uokz3N3DAAAANbkGzUAObEpGED0dWba2ACIzuQAyGmtWW1yAETmR8cBSn993M24Azw/ByCmteZDxh0AAAAAtEzukAKU/HOg/830uYkHNAOfbwcAgOJz8ffLKlNv2fBEX9fr5gEub2m0BYuWFv0GhENHT471NZow+SMbPaqouqT3Y6Hdb44xI4u4PbqeEq64oX8Y92ZNqK+vL9oZ89HseeGewWOdl03YmVfc4xxqibXvtJfrZACIJjM7h1o/SFL0frn9Qa63pRy66ranYjkXO+x3bF7v2903ZJzj1Ux9PHveP5/PLVwcNunQ1ayRGuihzdqGmvIKKWu/brefc0aRat0uebg7YwAAALAm36gByIlNwQCirzPTxgZAdCYHQE5rzWqTAyAyPzoO0DLWyMOMPMDzcwBiWGdunGmBkQcAAAAALY87pAAt4lnQKSYe0Ax8vh0AAIpNq8rUkTY70ddt/utuYc7ceS5vWS/9HnmlqDcgvPmBkWH+giWxvT4PPPm6jR5VNJ3as1+o2D5tRpZQO3U8Mfy1z4Aw+b3pRTljli2vDS++NtX52YTteuDpzp0WVFkiuWzDbff5kStlAIhmo0SnlDWEJOXW3/oPc70tReyS3oNiOQ/36Jrfz5jfNehVx6uZWrJ0+cpjMGLMeDNGWkf3bb5tqCmvkLK257a/dc4oUhu1T+3qzhgAAACsybdpAHJiUzCA6OvMtLEBEJ3JAZDTWrPa5ACIzI+OA7SMNfJWK37my9gDPD8HIIa15oVGHgAAAAC0PO6OArSI50DfzzTW1AOamM+3AwBAMamqOvGHZYnkezY70dddcu0dLm1Zb0+8OKnoNyF8adx7sbw2s+d8ZZNHFU1HnP630Lp9Z/OxhPvtIaeHfg88EeZ/tbDoZs30WXNDv0deca42xebNNz4aNq7q4pxpIZVVpl51pQwAOUinf9AqkfzAOkKSonfFrUNcb0sR63HdwFjOw45Hnp3Xe3W3P/Sy49UM9R/06jfH4Lpb7zdjpHV01+btQk15hZS1/bf5jXNGkdqwXeqXbowBAADAmnybBiAnNgUDiL7OTBsbANGZHAA5rTWrTQ6AyPzoOEDLWSdfb+wBnp8DEMM68z8yTTb2AAAAAKBlcXcUoMU8C/p1pnqTD2hCPt8OAADFpCyROtlGJ/q68h0OCrM+/dylLevtlTc/LPqNCG8dOCosXrIs76/NC2On2uhRBd+N974YksdebDa2oCp2SIdTL7g+THznvaKaNwsXLwuPDZvovG2COh7jPaHllOzjShkAcpOZoedaQ0hS9C64/iHX2lLEzrzinljOw0P+eFFe79PdfP9Ix6sZenz4W98cgxXH1IyRGq5vm0SoKa+QspbcZm/njLKXSC2vqjrxh+6KAQAAwJp8mwYgJzYFA4i+zkwbGwDRmRwAOa01q00OgMj86DhAy1kn/79MHxt9gOfnAMSw1uxk7AEAAABAy+LOKECLehZ0t8kHNCGfbwcAgGKxUVXH/ypLJD+22Ym+7pzL+risJS8++GhOSWxGOPat6Xl9XZbX1oXbH3rZRo8q6K6/a1jYtevp5mILLnX0ueGZF14J9fX1RTFzVvz3HD1+mvM35q7p+0yo2OFg50gLqHUidbyrZQDI+T7rT8sSqcXWEpIUrbOuute1thSx7pf0i+U8PO7Mq/L67MOxap5GvTFt5TGorasLW+x8iBkjraOb27QPNeUVUtbSbfd0zihK77sjBgAAAGvn2zQAObEpGED0dWba2ACIzuQAyGmtWW1yAETmR8cBWtZa+UijD/D8HICY1pqPGX0AAAAA0HK4KwrQop4D/TzTXNMPaCI+3w4AAMWiVWXqXJuc6Ot+UdUlfDBjlsta8mLh4mUlsRlhv0dfCbV19Xl7XWqmfWqTRxV01/V/PuzY6RRzUSvbK909PDxkeFheW1sUs2fKh5+FWweOci7H2OGnXevcaAGVbZusdLUMAI2515q801pCkqJ1ykW3u86WInbi+bfEch6eftHfPRMqgVY8d1ph4jvvmS9Slm7YoirUlFdIWTti6z2cM8peIvmcu2EAAACwdr5NA5ATm4IBRF9npo0NgOhMDoCc1prVJgdAZH50HKDlrZeHGn+A5+cAxLDO/EWmr4w/AAAAAGgZ3BUFaHHPgv5o+gFNxOfbAQCgGGzSLvXjssrkHBud6JtNLM+/ziUtedV/0KslsSHh5A9m5+01efS5N23yqILt2juGhg4H/MFM1Brt1PHEMPCx50NdXX3Bz55PP/8q3PnoK87pmLrhnuFhq92PdF6UcGWVqSVbbZX+d1fMAJC7Vu077Wg9IUnROubs3q6zpYgd/ecbYjkPL7j6H3m7J/fl/MWOVTM1+4t//k5UvweeMF+kLP11i+1CTXmC9Db3AAAgAElEQVSFlLXjtt7NOaMIz1OSt7sbBgAAAGvnmzQAObEpGED0dWba2ACIzuQAyGmtWW1yAETmR8cBWt56ebNMi41AwPNzAGJYa55p/AEAAABAy+COKECLew70/UwjTUCgCfh8OwAAFINWidRlNjnR17Vu3znUvPuhS1ry6skRb5fEhoQPPjM+L6+HTSVVyF3bb2io2u9EM1HrbO/0qWHYyHEFP3/mL1wSBjwxzrkdUydf8A/nQylvAplIjXW1DACNV1aZHG9NIUnZO6T7X11jSxFbcb7EcR5e1fuevN2Pm/3FV45VM9Tn/pGhtrZu5TE4+bxrzRcpS1dvuV2oKa+QsnbS1rs4Z5S9RKce7oQBAADA2vkmDUBObAoGEH2dmTY2AKIzOQByWmtWmxwAkfnRcYCWuWa+0AgEPD8HIIZ15g8yjTMCAQAAAKD0uSMK0CKfBbXNtMwUBGLm8+0AAFDoNty2y89aVSa/ssmJvu7YM650OUvejX1reslsTDjrs/nr/Xq8PH6aTR5VkF135/Ohw/5/NA8VuYNPvDC8+c7Ugp5BS5YuDw8PneAcj6HeA0aEyt8e71wo0coqU/9wxQwAjVdWmfyjNYUkZa/z8Ze6xpYi1vUPl8dyHt7U76G83Yub+emXjlUzNOCJ1745Btvtd5z5ImXpyi23CzXlFVLWTt9qZ+eMIjxPSR7iThgAAACsnW/SAOTEpmAA0deZaWMDIDqTAyCntWa1yQEQmR8dB2iZa+Z/zzTJGAQ8PwcghrVmh0y1xiAAAAAAlDZ3QwFa7LOgq0xBIGY+3w4AAIWurDJ1gw1OtGqvT5zscpa8+/DjL0pmY8JnRtWs12tRX18f7nz0FZs8quC6rv/zYfvfnWQWKud+UdUlXNSrb/hqwaKCnUPLa+vC4OFvOddjqHvPO5wHpVoieZorZgBovP/dfr//16oy+ZV1hSStu32P6OH6WorY735/YSzn4Z0Dh+TtPty0mXMcq2boqZfeWfn6z5w122yRInTZljuEmvIKKWtnb7WTc0ZZa92u8/buhAEAAMDa+SYNQE5sCgYQfZ2ZNjYAojM5AHJaa1abHACR+dFxgJa7bt41U71RCHh+DkAMa82/G4MAAAAAUNrcCQVosc+B/k+mqSYhECOfbwcAgEL288qum5RVppbY4ERfd8gfL3IpSywWL1lWMhsT3vzAyLBg0dJGvxbTZ821waMKrt4DRoTdDzrDLNR6VbnP0eHBx4cV7Cyqra0Ljw9/yzkfw/tH+31PcA6UYBslOu3jqhkA1k9ZInmbdYUkrbvdDjzD9bUUsX0OPTeW8/ChJ4bn7R7c5A9mO1bN0KsTP1z5+j/65ItmixShnltuH2rKK6Ss9fjVTs4ZZX+eUtXxp+6CAQAAwNr5Jg1ATmwKBhB9nZk2NgCiMzkAclprVpscAJH50XGAlr127msUAp6fAxDDOvO/M80wCgEAAACgdLkTCtCinwXtaxICMfL5dgAAKGStEql+NjfRqo18dYJLWWJz12NjS25zwsZ4ZlSNDR5VcB188tXmoPLWcWdeGT6b82VBzqLauvrwxIuTnPd57tSed/rbL8Fat/tdK1fNALB+Nqrq2N66QpLW3XYHnOTaWorYbgeeEct5+NSwMXm7/zbx3VmOVTP03vTPV77+f7nqNrNFitDFW+4QasorpKyd/6sdnTNad4nUfHfAAAAAoGG+RQOQE5uCAURfZ6aNDYDoTA6AnNaa1SYHQGR+dBygZa+d/yfTDOMQ8PwcgBjWmr8zCgEAAACgdLkLCtDinwXdbRoCMfH5dgAAKFRl2yS3aJVILbfBib7ud0ee5TK2icxfsLBF/rufeumdktmcsP+gV0N9fX3Or8HSZbXh1oGjbPCoguq0S+8Mrdt3NguV19rtfVR4bsTYgpxHtbV14bFhE53/eaz3gBGhw/5/9LdfQpUlkl+6agaAPN2HrUy9an0hSQ3Xdq+jXVtLEdux48mxnIcjX52Qt3tvr78z07FqhubOX7Ty9d+n22lmixShC3+1Y6gpr5CydtGWOzpntO7nKZXJ8e5+AQAAQMN8ewggJzYFA4i+zkwbGwDRmRwAOa01q00OgMj86DiA9XNH4xDw/ByAmNaa9xiHAAAAAFCa3AEFaPHPgX6caaaJCMTA59sBAKBQlSWSD9ncRKv2zAuvuIxtAnO//Co8/9JrLfLfPm7SjJLaoHDazDk5vwaTps6yuaMKqstvfjxU7HCwOahYat2+c7i4V9+wdOmygptJy2vrwoPPjvc+kMdOu/ROf/elVCI52lUzAOTHRonUcdYXktRwm/66m+tqKWKVvz0+lvNw/FtT8nbfbcybHzhWTdytA0eF+vr6MH/BwvCLqi5mixSh83+1Y6gpr5CydsmvdnDOKEvJR939AgAAgIb5BhFATmwKBhB9nZk2NgCiMzkAclprVpscAJH50XEAVqyhBxiJgOfnAMSwzrSZIgAAAACUKHdAAciMg04mIhADn28HAIBCtHFlskOrylS9jU30dXunT1252Rrx63HlLWHK+zNa5L99+qy5JbVJ4RMvTsr5NXhk6AQbPKpg6j1gRNgpeYo5qNjbp9tp4YMZswpuLi1cvCzcM3is94M8vqd02O9Ef/Olswnkna6cASA/Ntx2nx+VJZJfWl9I0tpr3b5zuDFzTenaWsre1nscFct5+O60/D23emnce45VEzfw6TdWvvYvjH7DXJEi1uNXO4Wa8gopa5dtuYNzRusukbrO3S8AAABomG8QAeTEpmAA0deZaWMDIDqTAyCntWa1yQEQmR8dB2DFGvonmT4xFgHPzwGIYa1pM0UAAAAAKEHufgLwr2dB95uKQJ75fDsAABSiVpXJZ2xsolV7/NmRLmGbwJT3Z4Rf7XZYqK2ra5H//sVLl5fUJoV97h8Z5i9cEvnf/+VXi23uqILqmLNvNAPVZG29x+HhpVcmFNxsWvHe3PfhMd4T8tTpl9/l771EKkskL3LlDAB5vB+bSN1kjSFJDder37Ouq6UIVeyYjuUc/GT2nLzdbxv2yhTHqol7bsyUla/9tbfcZ6ZIETvnVzuFmvIKKWtXbrmdc0brbKPKTn9y5wsAAAAa5ltEADmxKRhA9HVm2tgAiM7kAMhprVltcgBE5kfHAfh6HZ00FgHPzwGIaa35gLEIAAAAAKXFnU8A/vUc6CeZPjEZgTzy+XYAACg0rSuTu9nURKu250HdQ11dvUvYJnD4KT1D12N7tOjX4K7HXi2pjQpfefPDyP/2Ff9ZmzuqULri1iGhYvu0Oagm7RdVXUKfOx8uuNn08ex54ZYHRnpvyFMdDviDv/fS6EhXzwCQP60qO21rfSFJDXfpTYNdU0tZuvHeF0Pr9p1jOQcXLFyct3ttT498x/Fq4t6c/PHK1z594gVmihSxs7b6dagpr5CydvWW2zlntO4SqQPc+QIAAICG+RYRQE5sCgYQfZ2ZNjYAojM5AHJaa1abHACR+dFxAKylAc/PAYh7nfnTYDNFAAAAACgp7nwCsMqzIN8VBfLJ59sBAKDQlCVSL9vURKv2xNBRLl+bwLCR41a+3hf36tuiX4cnR7xdUhsV9h/0aqivr4/0b7978FibO6pg2vXA081ANVvnXNYnLF9eW1DzacXGs94b8tPpl9/l77wE2qh9aldXzwCQX60SqXHWGZK09npcN9A1tZSla25/Opbzb+OqzqGurj5v99kGD3/L8WriPp49LyyvrQ2b/7qbmSJF7Mytdg415RVS1npt2cE5o3U/T6nquKW7XgAAANAw3yQCyIlNwQCirzP9UCJADkwOgJzWmtUmB0BkfnQcgFXX0j/LNNt4BDw/ByCGtabPCAAAAABACXHXE4DvPAt60HQE8sTn2wEAoJBslOiUsqGJVu03B58W6uvrXb7GrLauLuyV7r7yNX94yPAW/Vq8OvHDktus8MOPv8j67/7o0y9t7KiC6cwr7jED1ewdc/oVYenSZQU1o54fM8V7RB7qPWBEaPebY/ydF3llHVIbu4IGgPwqS6ROts6QpLV3+mV3uaaWsnTJjY/Gcv5ttfvheb3H9vDQCY5XE9bn/pFh2fLaMGHSu+aJlMvaY6udQ015hZS1v23RwTmjdVW/ye67/6e7XgAAANAw3yYCyIlNwQCirzNtmAWQA5MDIKe1ZrXJARCZHx0H4Lvr6ZTxCHh+DkBMa80BxiMAAAAAlAZ3PAH4znOgn2b62IQE8sDn2wEAoHBc/P2yRPJNG5po1Z58frRL1yZw58Ah37zmU96f0aJfi/dnzim5DQufHVWT9d/9/JgpNndUQdR7wIhQue/xZqAKom5/uDAsXLS4YGZUbW1deODJ171X5KHjz+vjb7yIK6tMLl1x/egaGgDya5N2qR+XJZKLrDckac1OvuAfrqelLJ371/tjOf92Tv4xr/fY7nd/rUm7b8i4la973wGDzRMph7pvtUuoKa+Qsvb3LaqcM1rH85TUTHe8AAAAYN18mwggJzYFA4i+zkwbGwDRmRwAOa01q00OgMj86DgAa1tT32lEAp6fAxDDOvN/Mn1oRAIAAABA8XPHE4C1PAv6baZ6UxJYTz7fDgAAhaJVZacjbGiiVdun22mhvt79n7jNm78gbLPnkStf8zY7dwu1dXUt+vX4auGSktuw8NaBo8LSZbUN/puXLa8Ntz042uaOKohOPP9WM1AFVeroc1fOykIx58uFK9/XvV+sXzfcPTxsvvMh/saLtuQ0V9AAEI+yRPJuaw1JWrPjzr3J9bSUpe4974jl/Ot45Nl5vb9212OvOl5N2NDRk1e+7sf/+WrzRMqhU7baJdSUV0hZ671FlXNGDZdIvuRuFwAAAKybbxQB5MSmYADR15lpYwMgOpMDIKe1ZrXJARCZHx0HYG1r6v+b6V1jEvD8HIAY1pp7B5spAgAAAEDRc7cTgAaeBd1qSgLryefbAQCgEFRVnfjDskTyPRuaaNWeGvayy9Ym0PO6ft+85l2P7eEFyej78JiS27Tw7fc+afDfWzPtUxs7qiC64Z7hYcvdDjcDVXDte+gZYd78BQUzp956d5b3jDx0yJ+u8fddpJUlUmNcRQNAPFonOu9uvSFJa3bk6X9zLS1l6fhz+8Rz/nW/NK/31m6rHu14NWHjaz4KdXX1oe0eR5gnUg6dtPUuoaa8QsrazW3aO2fU8POUytRd7nYBAADAuvn2DEBObAoGEH2dmTY2AKIzOQByWmtWmxwAkfnRcQAaWlfvnKnWqAQ8PwcghrXm341JAAAAAChu7nQC0MBzoB9lmmxSAuvB59sBAKAQlCVSJ9vMRKu276FnhPr6epetMftw5iehfIeDvnndL+7V14uS8diwiSW3aeEjz73Zov69Ks6OPecmM1AFW6ejzgkLFy0umFk1ZMTb3jfWs2v6PhM22e5Af9/F2SBX0QAQm++VVaamWG9I0up1O+Vq19JSlg479dpYzr9TL7g+b/fUauvqHasm7qNPvwyTJk8zS6QcO3GrXUNNeYWUtdvaVDpn1GBllckL3OoCAACAdfPtGYCc2BQMIPo6M21sAERncgDktNasNjkAIvOj4wCsa239V6MS8PwcgBjWmf+ZaaJRCQAAAADFy51OANbxLKhDpmWmJdBIPt8OAADNrfWO6f9TVpmaaTMTrdrTw8e4ZG0Cx5155Wqv+8NDhntRMka9Ma0kNy6c99XiNf6tCxYtDX3uH2ljRzV7Nw4YEdruebQZqILu96deFpbX1hbErFqYef++/aGXvX+sZwf8/gJ/28W4CWQieZsraQCIT6tEpx7WHJK0el1OuNR1tJSlLidcFsv5d3Gvvnm9p+ZYNW1Lly0PfQcMNkukHDth611DTXmFlLW+bRLOGTX8PKV954Pd6QIAAIB18+0ZgJzYFAwg+jozbWwARGdyAOS01qw2OQAi86PjAKxrbf0fmcYbl4Dn5wDEsNaszLTUuAQAAACA4uQuJwBZngVdZloCjeTz7QAA0NxaJZLn2chEq7bvoWeE+vp6l6wxGz124hqv/ZT3Z3hhMiZ/MLskNy4cO3H6Gv/W1ybNsKmjCqKTLrjNDFRR1P0vfwt1dYWxTnn7vU+8f6xnPW96LLRu39nfdvHV05U0AMRnk+0O+HlZIrnMmkOSvu2A31/gOlrK0n5H/iWW8++G2wfm7X7anC8XOlZN2L2Pv7bydT/uzKvMEinHjt16t1BTXiFlrV+bhHNGDVbWLpVwpwsAAADWzbdnAHJiUzCA6OvMtLEBEJ3JAZDTWrPa5ACIzI+OA5Btfb1NpsVGJuD5OQAxrDXPNy4BAAAAoDi5wwlAludAP8z0qokJNILPtwMAQHPapF3qx2WVyTk2MtGqPfPCKy5XY1ZXVx/2P+zM1V73Njt3C7V1dV6cjC/mleamivcNGbfGv/XeJ16zsaOavd4DRoTEPseZgSqarup9T8HMrMeGTfQ+sp7teuDp/q6LbRPI9slTXE0DQLxaJZKDrTsk6dt+c8g5rqGlLO1+4BmxnH/9Bz6Zt3tpH336pWPVhD0zqmblM8m2exxhlkg5dvTWu4Wa8gopa3dt3s45o4aq33DbfX7kLhcAAACsm2/PAOTEpmAA0deZaWMDIDqTAyCntWa1yQEQmR8dByDKGvtkIxPw/ByAGNaZ38801MgEAAAAgOLjDicAEZ4FVWSaZ2oCOfL5dgAAaE6tEqnLbWKiVdv/sDNDfX29y9WY3T9o6Bqvfddje3hh/mXF3+Bt1aNLcgPDOV8u/ObfOeuz+TZ1VEH05yvvMQNVVLVu3zk8/uzIgphZX361ONzywCjvJevRWVfd6++6yNoo0flQV9MAEPN928rUgdYdkvRtux54umtoKUvb/+6kWM6/QU+PyNu9tPdmfO5YNWGvvzMzTJo8zRyRGtGRbXcPNeUVUtbubdPOOaO1VlaZmukOFwAAAGTn2zMAObEpGED0dWba2ACIzuQAyGmtWW1yAETmR8cBiLrOfsTYBDw/ByCGdeaGmWYZmwAAAABQXNzdBCDis6CDTU0gRz7fDgAAzeVnbTtt2KoytcBGJlq1oSPGulSN2YKFi0PlPkev8dpf3KuvF2cVDz47viQ3MHzlzQ+/+Te+8Oq7NnVUQbTnwWeZgSq62uzcLUye+mFBzKzRb0zzXrKetdvnOH/XxbQRZPvOHV1RA0C8Nttsv/8oq0zOsfaQpH+2Y8eTXT9LWdpm76NjOf9efPmNvN1HmzR1lmPVhM34ZG7oO2CwOSI1oiO23iPUlFdIWbtv822dM1r7s5TK1DB3uAAAACA735wByIlNwQCirzPTxgZAdCYHQE5rzWqTAyAyPzoOQNR19o8zfWB0Ap6fAxDDWnO/TPVGJwAAAAAUD3c2AcjhWdCdJieQA59vBwCA5tIqkeptExOt2v6HnRnq633GN27X3HTvWl//h4cM9+Ks4oWxU0tyA8N7n3ht5b+vtq4+9H34ZZs6qtm7+vanw8ZVXcxBFWW7pE4K8+YvaPaZtWxZbbjz0Ve8p6xHv//zDf6mi6jWlcndXFEDQBPcv61M9rH2kKR/Vrnv8a6fpSxtulO3WM6/ie+8l7f7aOMmzXCsmrDFS5eH48680hyRGtGhbfcINeUVUtYGbL6tc0ZrL5G6xd0tAAAAyM43ZwByYlMwgOjrzLSxARCdyQGQ01qz2uQAiMyPjgOQy1p7l0zLjU/A83MAYlhr/s3oBAAAAIDi4a4mADk8B/pRpndMTyAin28HAIDmsGG71C/LKpNLbWKiVXtuxFiXqTH7+JPPw2Y7HbzW13/K+zO8QKuYNHVWyW5i+NncBeHdDz+zoaMKokO7/9UMVFF3zOlXhPr6+mafW++894n3lPWoV79nwy+26+pvukgq2zZZ6aoaAOLXul3n7a09JOmfbb3HUa6fpXV044ARoXX7zrGcfzM+np23e2ij35jmeDVRdw8eG+rq6jPvn4ebI1Ij6rb1nqGmvELK2r1t2jlntPZnKZXJM93dAgAAgOx8cwYgJzYFA4i+zkwbGwDRmRwAOa01q00OgMj86DgAua63LzI+Ac/PAYhhnfnDTGOMTwAAAAAoDu5qApDjs6BtMi0yQYEIfL4dAACaQ6vKVH8bmGjV9j/szFBfX+8yNWan9Lh2ra9/m527hdq6Oi/QKj79/KuS3cjw5QkfhMdfmGRTRzV7vQeMCFvtfqQ5qKKv/8Anm31urVhG3TdknPeW9WifQ8/191wkta7stJmragBoovu4idQ71h+SlAqb73yIa2dpHf2177OxnX8LFy3O2z20Ya+863g1UU+99E54q+Z9M0RqZOm2e4aa8gopa/e02dY5o7VW1r5zR3e2AAAAIDvfnAHIiU3BAKKvM9PGBkB0JgdATmvNapMDIDI/Og5AruvtH2QaboQCnp8DEMNac7NM841QAAAAACh87mgC0IhnQd1NUCACn28HAICm9vNEcqtWiWStDUy0asNGjnOJGrPXJ04Ordt3Xuvr3/XYHl6g76itrQs33z+yJDcyvPPRV0r236bi6swr7jEDVRK12blb+HDmJ80+u6ZO/8x7y3p01lUD/D0XST9r22lDV9YA0DRaJZLnWX9IUir8Yruurp2lddTzpkGxnHu/3P7AvN4/e3LE245XE/XapBmh74DBZojUyA7cZq9QU14hZe2uzds5Z7TWyrZJbuHOFgAAAGTnmzMAObEpGED0dWba2ACIzuQAyGmtWW1yAETmR8cBaMyae8NMHxmjgOfnAMSw1kxlqjdGAQAAAKCwuZsJQCOfBfmsP5CNz7cDAEBTK0ukHrZ5iVat45FnuzyNWX19feh8zHkNHoOLe/X1Iq3FfUPG2fhQirH9jzzfHFTJ1PW480NdXfN/P2ngU294f2lkvQeMCFvv+Xt/z0VQRVX6f1xZA0DTaLVNl9atKpN11iCSlAo33vOC62epgc7r9UAs513lPkfn9d7ZI0MnOF5N1PRZc8NxZ15pfkiNrHPbvUNNeYWUtf5tEs4ZrVkitbyq6sQfurMFAAAA2fnWDEBObAoGEH2dmTY2AKIzOQByWmv6oW2A6PzoOACNXXfvnmm5UQp4fg5ADGvNG4xRAAAAAChs7mQC0MjnQP8309smKbAOPt8OAABNaePKZIdWlal6G5ho1V58+Q2XpzF79KkR6zwGDw8Z7kVai6GjJ9v4UIqpG+4ZHip2TJuDKqluHzC42WfXtJlzvMesR4edeq2/5SJow233+ZGrawBoOpn5O9QaRJJS4do7hrp2lhro1J53xnLe7ZXuntd7Z/cNGed4NVELFi0Nbfc4wvyQGllym71DTXmFlLU72yScM1qjssrUFHe0AAAAIBrfmgHIiU3BAKKvM9PGBkB0JgdATmvNapMDIDI/Og7A+qy9zzVKAc/PAYhhnfnDTC8ZpQAAAABQuNzJBGA9ngW1zbTANAUa4PPtAADQlGzAqu924PHnuzSN2ZKlS8MOBxy/zuMw5f0ZXqi1GF8z08aHUkx173mHOaiSa7OdDg7Tpn/c7PPr/idf9z7TyK7+x1Nh46ou/p4LvE123/0/XV0DQFPe0+10hDWIJKXC5bcMce0sNdAJPW6O5bzrelx+nyP2e/QVx6sJumvQq+GtmvfNDmk9SrXdK9SUV0hZu6NNO+eM1qisMjnEHS0AAACIxrdmAHJiUzCA6OvMtLEBEJ3JAZDTWrPa5ACIzI+OA7A+a+/vZXrYOAU8PwcghrVm60yzjVMAAAAAKEzuYgKwns+CDjVNgQb4fDsAADSVssrU3jYu0Xd75Y23XZrG7O99q9d5DNrs3C3U1tV5odZi5qdf2vxQiqm9DznHHFRJdvRplzf7/Hrn/U+9z6xHe6T/7G+5wNtg993/zRU2ADSdjao6/lerRGq+dYiklt7FNz7qullqoCNO/1ss591xZ16V1/tmtzww0vFqgp4Z+U64fcBgs0Naj7q03SvUlFdIWevbJuGc0RqVJZLXu6MFAAAA0fjWDEBObAoGEH2dmTY2AKIzOQByWmtWmxwAkfnRcQDWd/3940xTjVTA83MAYlhr7pWp1kgFAAAAgMLjDiYAeXgWdKuJCqyFz7cDAEAT+V5ZIjXGxiVatSP+1NNlacxmfz43bLnLoes8Dl2P7eGFasCSpcttfijF0N/6DwubbHegWaiS7cWX32jW+VVXVx/6D3rV+00jO+2y/v6OC7wV15cusQGgaZUlkndbh0hq6Z3Xa6DrZqmBDvzD5bGcd2f17J23e2bLltU6Vk3U+JqZ4dgzrjQ7pPXowG32CjXlFVLW+rZJOGe0RmWJzie5mwUAAADR+NYMQE5sCgYQfZ2ZNjYAojM5AHJaa1abHACR+dFxAPKxBt820yJjFfD8HIAY1poXGakAAAAAUHjcvQQgD8+B/iPTWFMV+A6fbwcAgKawUbtUZ5uWaNVat+8cJrw91WVpzFZsNpjtWFzUq68Xah3uemysDRClPHdqz35moUq6vdLdw/La2madX+MmzfB+08huvPfFsMUuh/lbLtQSyVpX2ADQ9Fq3T+1rLSKppXf21QNcN0sNdMBRF8Ry3l1xQ/+83S+bv2CxY9VEffTpvLD1HoebHdJ6dGDbPUNNeYWUtX+0qXTOaI3KKlN7u5sFAAAA0fjGDEBObAoGEH2dmTY2AKIzOQByWmtWmxwAkfnRcQDytQ4/xlgFPD8HIIZ15vczPWGsAgAAAEBhcfcSgDw9C/plps9MVmAVPt8OAACxS6d/UFaZesumJVq1E8662iVpzCZNnhZ+UdUl67F4eMhwL9Y6PDnibRsgSnlu/yP/YhbmUPkOB4VdUieFrsedH045/7rQ87p+4fYBg8O9Dz8Tqgc/Hx5/duTKRowZv7Inho5a+d6+4n9/y12PhhtuHxgu6tU3nHj2NSF19Lmhw37Hhk06dPXaxlz/gU826/xasnR5uHXgKO85jSx1fE9/xwVbss5FNgA0g913/7fMLP7EWkRSS5+KdY4AACAASURBVO6My+9yzSw10B7pP8dy3vXp/0je7pfN/uIrx6oJuuWBkeHNt6eaG9J6lm67Z6gpr5CydlubSueM1qisQ2pjN7MAAAAgGt+YAciJTcEAoq8z08YGQHQmB0BOa81qkwMgMj86DkA+1+I3Gq2A5+cAxLDO/O9Mk4xWAAAAACgc7lwCkMdnQbtkWma6Av/i8+0AABC3VonkUTYs0ar9oqpLmPzedJekMTv0pIsjHY8p78/wYq3D2InTbYIo5bHeA0aENjsfah420CbbdQ2djzkvXPjX20P14OfDO+9+EJbX1ub9va22ri58MntOGPP6pNB/4JPhnMv6hE5HnZM5Nt0chzy1zZ5HhnnzFzTrDBs6erL3nUZ2Xq8H/B0XcFVVJ/7QlTYANL2yRPJGaxFJLblTe/ZzzSw1UIcD/hDLeXffo0Pzdq9s+qy5jlUT9OAz48Nt9wwyN6T1rFvbPUNNeYWUtVu2qHTOaPUSqYUbbLDB99zJAgAAgGh8YwYgJzYFA4i+zkwbGwDRmRwAOa01q00OgMj86DgA+VyL/1umYcYr4Pk5ADGsNbfINNd4BQAAAIDC4K4lAHl+FnSa6Qr8i8+3AwBAnLbaKv3vrSpT79u0RKttPHnB9S5HYzZ0xNhIx6LNzt1CbV2dF2wd3p/xuU0QpTzW49qBZuF32riqczj8lJ7hsWdeCvPmL2jW97z6+vrwwYxZYfCzI0OPK28Je3Q9xTFaj3rdPKBZj+dHn37pfaeR9R4wImy52+H+jgu0Dbfd50eutgGg6bVq32lHaxFJLbmTLrzdNbPUQL/a7YhYzrunhr2ct3tlUz6Y7Vg1QS+Ne2/l/W5zQ1q/urXdM9SUV0hZu3mLSueMVqusMjneXSwAAACIzjdmAHJiUzCA6OvMtLEBEJ3JAZDTWrPa5ACIzI+OA5Dv9fhPMr1nxAKenwMQw1pz30y1RiwAAAAAND93LAGI4VlQXxMWCD7fDgAA8dqostOfbFiiVdtku67hgxmzXI7GaHltbdjzoO6RjkfXY3t4wbL48qvFNkGU8thBJ11lHn49Ezt0DWdefGP4cOYnBf0++OlnX4RHn3wxnH1Zn7BTxxMduxzactdDw5fzvmrW4zfgiXHeexpZlxMu9XdcoLXeKv2/rrYBoFl8ryyRnGo9IqmlduL5t7peltZS7wEjwsZVXWI578aMeytv98nenPKx49UETXr347DZTgebG9J6dmjbPUJNeYWUtZvbtHfOaPUSqfvdwgIAAIDofGMGICc2BQOIvs5MGxsA0ZkcADmtNatNDoDI/Og4AHGsydtlWmjMgufn3hEBiGGteaERCwAAAADNz91KAGJ4DvSfmV4xZaHF8/l2AACIy4bb7vOjskRqlg1LtGrnXn6zS9GY3TlwSOTjcXGvvl6wLOrrQ7iterSNEKU81X7fE8zDTF2POz9MeX9GUb4vvjFxSuh5Xb//n7078ZOiPBD/H5Lvfnf3t7k2+eZwBmNmNNxCDyCoCKLEBA+6B7RFUYzigWg8YvBAMXjFCzVGPCPeGOIoXgl4SySKeIAHHiMGLzTxVuRQjpn6lVndnbgKVTNV3T3d7/fr9fkDqJqq53mqin6CvkPHOJcRmnzhtUU9XwuefdW9p5VNOPs6f8Ml2kab7fB9K24AKI7quuxJ5iOSKrV9j5pivSx9TmdOvTO16y7JZ6iPLHzF+SpAd973iDFDSqBRPQYHjTW10no7v3Nv14z+qapM7nhPsAAAACA6/2MGIBabggFEn2fmDRsA0Rk5AGLNNRuMHACR+dFxANKal+8c1myoBe/PASDheWaHsOsMswAAAABQXJ5WApDSu6ANwl4z0kJF8307AACkpTozbILNStSy2v754G+vv20pmqJly1cGmR//LPI5mTFztoMWwfV3PG4jRCmhzVU79q6v+LHw8j/8KWhubv//H7qpqTmYt+Dp4NjTLg56DdnLXOcL6jJw9+D9pcuKdp6Wr1wVXDDd/ac1Tbl2TtBt69H+jkuw79eN2MiKGwCKY4M+O3UxH5FUqe39y3Otl6XP6Ve/vTG16y7J52pzHl3sfKXcZTfOC06bco0xQ0qgPbsPDhpraqX1NqVzH9eMPtvOnmABAABAdP63DEAsNgUDiD7PzBs2AKIzcgDEmms2GDkAIvOj4wCkOTc/w1AL3p8DQArzzK+GPWGoBQAAAIDi8aQSgBTfBQ0I+8hoCxXL9+0AAJCGH2y6439W1eXetVGJWjZp8lTL0JSdcu6Vsc7JoheWOGgR3PvQ8zZDlBLo4F9dWtHj4GZD9w0WPru4LO+Tq1evCW6+fU4wfJ9jzHk+p8kXXlvU83PjXU+4B7WyEQec7G+4BPt+JtvNqhsAiqc6k33UnERSJbbn4WdbK0uf0y9PvSaVa662fz5obm5O7BnZXXOfc75SbuZ9Twfb7/FLY4aUQKN7bB001tRK6+28zr1dM/rndyh19V09vQIAAIDo/G8ZgFhsCgYQfZ6ZN2wARGfkAIg112wwcgBE5kfHAUhzbv7lj3/ay3AL3p8DQApzzeqwVw23AAAAAFAcnlICkPK7oJFhzUZcqEi+bwcAgDRU1eVOtVGJWtZpwMjgrXfetwxN0cuvvv6PDQbjnJO1TU0OXASPN75mM0QpgXb42cSKHQd/vOthwetvvlMR98yFzy4Oxh51ZrBhn3pzoE/qMnD34IPlK4p2Tp587m/uQa3suLOv9zdcgm3Qa9gAq24AKOaz3+wR5iSSKrHdfn6mtbL0OR1w7MWpXHP9d9gv0Wdkt9y70PlKudkPNXouLCXU6B5bB401tdJ6O7dzH9eM/ruquuyqPn0O+BdPrwAAACA6/1sGIBabggFEn2fmDRsA0Rk5AGLNNRuMHACR+dFxANKen/972EOGXPD+HABSmGv2CVthyAUAAACAwvOEEoACvAs62YgLFcn37QAAkLQf9Bm+QXVdbrnNStSy08+/xhI0ZQcedWasczJizAQHLaIlr79nM0QpgboP3qsix8BBww8K3n53acXdOxe/9FpwyHHn2ET1ky655uainYsVH64KLph+v/tQK5py7ZyKvXeVdL2yO1p5A0DxVPXNbRiOyc3mJZIqrV3GnWatLH1Oexw6OZVrbtheRyX6jGz6rAXOV8pdef2dxgspoX7WfVDQWFMrrbfJXfq6ZvTfVdXlnvLkCgAAAOLxv2UAYrEpGED0eWbesAEQnZEDINZcs8HIARCZHx0HoBBz9A3CXjHsgvfnAJDCXHOXsCbDLgAAAAAUlqeTABTgPVCHsGuNulBxfN8OAABJq87kzrdRiVrWddCo4P2lyyxBUzT/ycagY+/6WOdl0uSpDlxEKz9abTNEqY2dcuEfK3IM7L/DfsFrr79V0ffQpxpfCEYddELFz4f6bb9fsGbt2qKdh5vuftK9qJXtPPYUc/qSa9ieVt4AUORnwHW5+81JJFVaw/c/yTpZ+pyy+6bz7G/fI05N9PnYZTfOc75S7ILp9we/PPF844WUUPt03zporKmV1tupXTZzzahl/nMMAAAAxOR/ywDEYlMwgOjzzLxhAyA6IwdArLlmg5EDIDLfVQJQqHl6XdhyQy94fw4AKcw1Jxp2AQAAAKCwPJkEoEDvgf4t7EEjL1QU37cDAECSvtdzWE1VXXaVTUrUst9O9XsMaWpubg7q9zkm9nmZMXO2gxfD5TZblNrU/hMurLjxr9eQvYLFL73mBvqJO/78UNB/h/0qek5006z7inb8FzyzxL2olU046zpz+hJrg7phP7f6BoDiqs5kDzUvkVRpZcdMsk6WPqchux2ZyjV3zK8vSuzZWFNzc3DBdOcqzf4wa0Gw+Y77Gy+khBrTfVDQWFMrrbcTuvZ3zahlJ3hqBQAAAPH4whsgFpuCAUSfZ+YNGwDRGTkAYs01/YgTQHR+dByAQs7Vdwxba/gF788BIOF5Zoewqw29AAAAAFA4nkwCUMB3Qd8Pe8noCxXD9+0AAJCkqrrcVTYoUct6DdkrWL7iQ8vPFN18+5xWnZtFLyxx8GK45d6FNkWU2tAOe02sqPFvwz71wZx5j7t5fsaKlR8GJ51z+T+OTyXOi4bufkTRjv07769wL2pl5107J9h4y5Hm9iVUVSZ3vNU3ABTXhnXZquq6bJO5iaRK6uPnW9bJ0v+u/04HpXLNnX3x9MSejS1fucq5Srnpf5prrJASbL/ug4LGmlppvR3XdXPXjP7n/Unv+l09tQIAAIB4fN0NEItNwQCizzPzhg2A6IwcALHmmg1GDoDI/Og4AIWer483/IL35wCQwjzzX8PuM/wCAAAAQGF4KglAgd8FbRq21AgMFcH37QAAkJQNew3rXp3JrrVJiVr2u2m3WHqmaPXqNcGWw8bGPi+dBowM1jY1OYAx/GX+CzZFlNpQzyH7VNT4d/r517hxrsODjz4V9N9hv4qcG338by+Wq2552P2olW23+9Hm9qW0KWQme54VOAAUX1Umd5+5iaRK6id7TLBGlj6n7oP3SuWamzbjjsSei73xzjLnKuVOv+A6Y4WUYPt3Hxg01tRK6+2orlu4ZvTfdew5vIcnVgAAABCPr7oBYrEpGED0eWbesAEQnZEDINZcs8HIARCZHx0HoBhz9nMNweD9OQCkMM/8RtgThmAAAAAASJ8nkgAU4V3Q4LCPjMJQ9nzfDgAASanK5G60QYla1nfomOCjVassPVN0wRUzWnVuRoyZ4ODF9Mzi122KKLWyM6feGXTsXV8x41/9PscEa9audeNcjw+WrQj2PeK0ipsfHTzhrKId89kPP++e1MrGHnuR+X0JFa49Z1iBA0AJPA/unT3Y3ERSJbXtyPHWyNLntNFmO6dyzd3x54cSey724qvvOFcpt9ehJxsrpAQ7oPvAoLGmVlpvv+i2pWtGn7w7ya7u1i3/fz2xAgAAgHh80Q0Qi03BAKLPM/OGDYDojBwAseaaDUYOgMj86DgAxZizfznsesMweH8OACnMNavDXjEMAwAAAEC6PI0EoEjvgnYLazISQ1nzfTsAACRhg971farrcs02KVHLrrnhdsvOFL397tKgy8DdW3VuJk2e6gDG9MY7y2yKKLWyQ0+6omLGvk222DV45bU33DQjam5uDn7zu+uCDfvUV8zfSE3/Xf4xhhfD4iVvuye1sjMuvT3o2LveHL9kNobMzbMKB4Di22izHb5fncmuNT+RVCltvfMvrJGlz3T2FXends09tnBRYs/Fnv7r685Xil3S8ECr31lK+vzGdhsYNNbUSuvt4G5buWb0X2Wyz3haBQAAAPH5mhsgFpuCAUSfZ+YNGwDRGTkAYs01G4wcAJH50XEAijVv/7ewOYZi8P4cAFKYa/YIe89QDAAAAADp8SQSgCK+CzrKSAxlzfftAACQhKq67CwblKhlWw4bG6xZs9ayM0UTTr2o1ednxszZDmBMa9Y2BRdMv9/miFIr2nnsKRUz/p176XVumK0w6565QU3/XSrm7+SCK28synH+8KM17kltqPfQ/c3zS6Rw/bnEKhwASuW5cO5e8xNJldKA+kOtj6XPdMKUW1K75l79+5uJPRd75KlXnK8UO/eK24wTUsKN675V0FhTK623A7oNdM3ov96dZLI3eFIFAAAA8fmKGyAWm4IBRJ9n5g0bANEZOQBizTUbjBwAkfnRcQCKOXf/RtiThmPw/hwAUphrDg77yHAMAAAAAOnwFBKAIr8LOtdoDGXL9+0AANBWG/QaNsDmJPpsN/xptiVnip5/cUmwUd8RrT4/i15Y4iC2wrQ/PmpzRKkVbT7s4IoY+7bY6YDgo1Wr3Cxb6f6Hnwg6D9itMjbhzh4YNDc3F+U4/37mfPelVpYfd6p5fqmUya35Uj7/FatxACi+qrrsgeYnkiqlj59xWR9L/9yRp1+byvXWsXd9sHr1msSeid33yF+drxQbf/Ilxgkp4Q7utlXQWFMrrbd9um/tmtEnZU/ypAoAAADi8wU3QCw2BQOIPs/MGzYAojNyAMSaazYYOQAi86PjABR7/t4x7BVDMnh/DgApzDV3C2syJAMAAABA8jyBBKDI74G+HHaDERnKku/bAQCgrarqcvfamEQt22bnnwdrm3xTm6bRh5zU6vPTacBI56eVZv3lGZsjSjE779o5QU3/XSpi/Lvjzw+5UbbR/Ccb/zFOVcLfy/0PP1GUY/xnGwi3uqPPnG6uX0JtWJetshoHgOL7Xs/h363O5NaYn0iqhDbf6SDrY+kzjZt4SSrXW4/Be3q/047acc8jjRNSwh3cbaugsaZWWm+juw92zegfVdVld/OkCgAAAOLz9TZALDYFA4g+z8wbNgCiM3IAxJprNhg5ACLzo+MAlMIcPhP2vmEZvD8HgBTmmkcakgEAAAAgeZ4+AlAC74H+PewvRmUoO75vBwCAtqiqyw2xMYk+28y751pupuj+h59o0/kZMWaCg9hKDz35ss0RpZhN+u1NFTH27bL/cW6SCZkz7/Ggpv8uZf83M/7EKUU5voteetO9qZWdN+2+oHbzvPl+qdQn29+KHABK5hnxveYnkiqh/juNsz6WPtPow89J5XrbZpdDEn0mdsOdTzhfKXXu1bODjTYbYZyQEu7n3bYKGmtqpfU2svs2rhl90rCenlIBAABAfL7cBojFpmAA0eeZecMGQHRGDoBYc80GIwdAZH50HIBSmcdvEbbc0AzenwNACnPN0w3LAAAAAJAsTx4BKJH3QF8Pm29khrLi+3YAAGiL6kx2rk1J1LKhux8RNDc3W26mpKmp+R/HuC3naNLkqQ5kK/31lbdskCjFbOyxF1XE+Hf/w0+4SSboj3feH3TsXV/WfzNdB40KPlq1quDHdtmKj9yb2tC2I8eb85dIHXtl97AiB4DSsEHdsJ+bn0iqhDbbYZy1sfSZRhxwcirX28ixxyf6TOyaWx9xvlLqxPOuN0ZIKXRo1wFBY02ttN5GbLqta0ZBdSa7dqOtt/43T6kAAAAgPl9tA8RiUzCA6PPMvGEDIDojB0CsuWaDkQMgMj86DkApzeW3C/vI8AzenwNAwvPMDmEXG5oBAAAAIDmePAJQQu+CvhP2rNEZyobv2wEAoLWqe2V3tDGJPtu998+31EzR72+8s83naMbM2Q5kK723dKUNEqWYZcecUPZjX27vo90gU3D6+deU/d/OrHvmFuXYXn7jQ+5PrWz/Yy405y+RqjLZX1mVA0Bp6Nhrx+pwfG42R5FU7vXd/kBrY+kzbbfHMalcbz8/7pxEn4ddfN0Dzldaz8uOPNsYIaXQ4d0GBI01tdJ6G7bpENeMwrLPeUIFAAAAreOLbYBYbAoGEH2emTdsAERn5ACINddsMHIAROZHxwEotfn8iLC1hmjw/hwAEp5nfjlsuuEZAAAAAJLhqSMAJfYuqGPYS0ZoKAu+bwcAgFbqUJ3JzbcpiVpWv88xlpkpWr7iw6Buu73bfJ4WvbDEwWyl5uZmGy9KMdtshwPLfvy79/75bpApWNvUFIw66ISy/tvZf/zpRTm2f5z9lPtTKxt/2jTz/hKpKpO92rIcAEpHVSb3oDmKpHKv79ADrI2lz7Rl7pBUrreTf3NFYs/CVq1e41yl+Q5g+/2MEVIKHd5ty6CxplZab0M3/bFrRmHZmzydAgAAgNbxxTZALDYFA4g+z8wbNgCiM3IAxJprNhg5ACLzo+MAlOKc/kBDNHh/DgApzDP/JWymIRoAAAAA2s4TRwBK8F3Qj8JeN0pDu+f7dgAAaI3qumEjbEiiz/bgo09ZZqbozAuubfM56jRgZLC2qcnBbIPrbnvMJolSxM6bdl+wUd+dy3rs+8luh7sxpuiNt94Nug/eo2z/fmr754MVKz8s+HGd98RL7lGtbPxp08z7S2eDyAeszAGgdFT1yh5pfiKp3Os9dH9rY+kz9RwyJpXr7eKrb07sWdh7S1c6Vyl18vm3Gh+klDqi24CgsaZWWm9Dem7nmlFQncmd7OkUAAAAtI6vtQFisSkYQPR5Zt6wARCdkQMg1lyzwcgBEJkfHQegVOf1xxqmwftzAEhhnvnvYXMM0wAAAADQNp42AlCi74J6hb1npIZ2zfftAAAQ36QvV2VyT9iURC3bfdwkS8wU/f2Nt4MfbTmyzedpxJgJDmYb3f3gczZKlCI26bc3lf34d80Nt7sxpuyGP80u67+h2+6dV/Bj+tdX3nKPamXjT5tm7l86vW5tDgCl43s9h9WYn0gq9+p+up+1sfSZavvlU7nebpp1X2LPwl57433nKqUOnnih8UFKqaO6bhE01tRK621gz5+6ZvRxO3s6BQAAAK3jS22AWGwKBhB9npk3bABEZ+QAiDXXbDByAETmR8cBKOW5/RmGavD+HABSmGd+M2y+oRoAAAAAWs+TRgBK+F3QoLAVRmtot3zfDgAAcXXM5EbZjEQt69i7Pnhs4SJLzBQdOvE3iZyrSZOnOpht9Nizr9ooUYrYuOMvLevxr/OA3YJly1e6MRbAqIMmle3f0fgTpxT8eC5d9qF7VCsbf9o08/8S6tuds1+zQgeA0lFVl33cHEVSOZfZbl9rY6lFZ195T2rX218eeiKxZ2GLXnrT+Uqp7fc40vggpdSxXTcPGmtqpfW2ea+hrhkFVT3rO3kyBQAAAK3jK22AWGwKBhB9npk3bABEZ+QAiDXXbDByAETmR8cBKPX5/RmGa/D+HABSmGd+M2y+4RoAAAAAWsdTRgBK/F3QkDAbZ0L75Pt2AACIJZ//SnVdrtGGJGrZmF+canmZooXPLg427FOfyLmaMXO2A9pGr/z9PRslShHbeeyvy3r8O/qUC90UC+TZ519KbCwstXoN2Stoamou+DG95Pq57lOtaPxp08z/S6iOPYf3sEgHgNJRlcn+yhxFUjnXa7t9rY2lFk367U2pXW+LXliS2HOwxxtfc75S6DdX3Rv8sN8uxgcppSZ16R801tRK6613r+1dM1r+pS9N+rInUwAAANA6vtIGiMWmYADR55l5wwZAdEYOgFhzzQYjB0BkfnQcgFKf33cIO9+QDd6fA0AKc83vhC00ZAMAAABAfJ4wAtAO3gVtF/ahURvaHd+3AwBAHFV12TE2I1HLNuxTHzz7/EuWlykaOfb4ktyEsFKtWLnKZolSxAbt/IuyHgOffPavbooFdNjx55bt39JjCxcV/Hhed9tj7lOt6KgzplsDlFAd64YNtUoHgNLRsefwHuYoksq5nkPGWBtLLfrFKVeldr299/6yxJ6DzX38RecrhQ496Qpjg5Rip3TpFzTW1ErrrWuvnVwzFV5VJvegp1IAAADQer7QBojFpmAA0eeZecMGQHRGDoBYc80GIwdAZH50HID2MMfvEHahYRu8PweAFOaa3w172rANAAAAAPF4ughAO3kXNDTsIyM3tCu+bwcAgKj69DngX6rrci/YkEQtO3jCWZaWKbrt3gcTO1edBowM1jY1OagJmHrDgzZMlCLUZdCeZTv+bT38YDfDAnvh5deCDfvUl+Xf02+nFv63q+54oNF9qhWdeP7N1gClVK/s/lbqAFBawjG60TxFUrnWc8g+1sZSi8YcdX4q11pN/12C5ubmxJ6D3T1vkfOVQjuPPcnYIKXYGZ03CxpraqX19sO6rGumwqvKZC/2RAoAAABazxfaALHYFAwg+jwzb9gAiM7IARBrrtlg5ACIzI+OA9Be5vkdwi4xdIP35wCQwlzze2HPGroBAAAAIDpPFgFoR++C6sNWG72h3fB9OwAARFWVyR1kMxK1bKO+I4LFL71maZmSNWvWBgPrxyV2vkaMmeCgJuSGO5+wYaK0ns667K6yHgN/87vr3AyLYM+fn1iWf0+7j5tU8GP50JMvu1e1orOvuNs6oLQ60UodAErtGXL2dHMUSeVaj232tjaWWrTLgaemcq3132G/RJ+D3Tr7KecrhXpu+zNjg5Ri53TuGzTW1Err7OmajV0vCj7+ns8TKQAAAGg9X2cDxGJTMIDo88y8YQMgOiMHQKy5ZoORAyAyPzoOQHua63857BrDN3h/DgApzDU7hi02fAMAAABANJ4qAtDO3gXtHLbGCA7tgu/bAQAgio6b5/+9KpN7zWYkatn4E6dYVqbo0mtvTfR8TZo81UFNyD3zFtkwUVpPR585vazHwMUvveZmWASzH5hfln9PnQaMDNasWVvQY7nopTfdq1rZRpvtbC1QKmVyl1mtA0BpqcrktjRPkVSudR+8l3Wx1KLt9jgmlWttxJgJiT4Hmz5rgfOVcJN+e5NxQUq5KZ37BI01tdI6e6S2k+tFwQZ96rfyRAoAAABaz9fZALHYFAwg+jwzb9gAiM7IARBrrtlg5ACIzI+OA9De5vtfCZtmCAfvzwEghbnmRmGLDeEAAAAAsH6eKALQDt8FjQxbYxSHkuf7dgAAiKIqk/uljUjUsh/22zl4+dXXLStT8v7SZUGPwXsmes5mzJztwCZkwbOv2jRRWk/7H3Nh2Y6B2486wo2wSJqamoO67fYuy7+rBQufK+ixfPPdZe5VrezjTdStB0ql7B1W6wBQaiZ9ORynXzdPkVSOdR882rpYalH/ncalcq0dctw5iT4Hu/zGec5Xwu15+NnGBSnlLupcFzTW1ErrbM7GnV0vav5Wv6Ff9zwKAAAAWs/X2QCx2BQMIPo8M2/YAIjOyAEQa67ZYOQAiMyPjgPQHuf8X/74v0UaxsH7cwBIYa75/bCnDeMAAAAAsG6eJgLQTt8F7RT2kZEcSprv2wEAYH2+0y3/1eq67Js2IlHLJp7xO0vKFE2aPDXxc7bohSUObEJefPUdmyZK62nE2FPKdgycctn1boRFdPQpF5bl39UFV95Y0OP44ao17lWt3jD6IOuB0ulpK3YAKD3Vmdzl5imSyrGug/a0LpZa9PE1kca1dup5Vyf2DKypqTm4YLpzlXQDhx9iXJBSbmqnTNBYUyuts9s36ep60QueRAEAAEDb+DIbIBabCLdlKgAAIABJREFUggFEn2fmDRsA0Rk5AGLNNRuMHACR+dFxANrrvL9D2PmGcvD+HABSmGt+L2yhoRwAAAAAvpgniQC043dBO4R9aDSHkuX7dgAAWJ/qTO5Ym5CoZZtssWvw5tvvWlKm5OVXXw9q+u+S6DnrNGBksLapycFNyPsffGjTRGk9Dd7liLIdB59Z9KIbYRH9ee5jZfl3deBRZxb8WF7SMNf9qhUN2e1Ia4JSKZN7y4odAErPBr1y9eYqksqxLoP2tC6WPum8afcFG/auT+Vau/K6WYk9/1q6zPucpDv7inuCH/QdblyQUu7qTr2CxppaaZ3dvEkP10vFl73JkygAAABoG19mA8RiUzCA6PPMvGEDIDojB0CsuWaDkQMgMj86DkB7nvt3CPut4Ry8PweAFOaa3w170nAOAAAAAJ/PU0QA2vm7oKFhK43oUJJ83w4AAOuyUa/cN6vqcu/ahEQt+/W5V1pOpmjfI05L/JyNGDPBgU1Qc3NzcNF1D9g8UVpHmw7ZuyzHwL5Dx/zjHkDxfPjRquCH/XYuu7+tgfXjCn4sp/3xUferVpTd9wRrgtLZLLLpS/n8V6zcAaC0fK/ndv9Rlcl9aK4iqdzqvNUo62Lpk065aGZq19pdcx5J7PnXq2+873wl3M8nXWZMkArQ73/UM2isqZXW2cd/J66Xiu8ET6IAAACgbXyZDRCLTcEAos8z84YNgOiMHACx5poNRg6AyPzoOADtff7fIewcQzp4fw4AKcw1/zPsEUM6AAAAAPxvniACUAbvgrYOW2ZUh5Lj+3YAAFiX6rrciTYgUcu6DNw9ePf9DywnU/LI488GHXvXJ37eJk2e6uAm7Pcz59s8UfqCzpt2X7Bhn+FlOQ4edfIFboAlYMfR48vub2vDPvXB8hUfFvQ43nTPk+5ZrWjUoZOtC0qo7/Uc/l0rdwAoPVV1uT+Zq0gqtzoP3MO6WPqko86Yntq19syiFxN7/tX44hvOV8LtsNdEY4JUgK7/0aZBY02ttM4u69TL9VLxDRvhKRQAAAC0ja+yAWKxKRhA9Hlm3rABEJ2RAyDWXLPByAEQmR8dB6Bc1gFnGNbB+3MASGGe+a2wRwzrAAAAAPDPPD0EoEzeBQ0OW2Zkh5Li+3YAAPgiG/XKfbMqk33fBiRq2dkXT7eUTElzc3Oww57jUzlvM2bOdoATdttfnrV5ovQFnXj+zWU7Dt4+e54bYAk44azLyvLv69EnGgt6HO+a+5x7VivaZ/x51gUl1Ia9hnW3egeA0lPdu/4AcxVJ5VbXQXtaF0ufNPa4i1O71pZ+sDyx51+PPPWK85VgU66dE3QZtIcxQSpAN2/SI2isqZXW2QWderteKv0dSZ/6jT2FAgAAgLbxVTZALDYFA4g+z8wbNgCiM3IAxJprNhg5ACLzo+MAlNNa4OiwZsM7eH8OAAnPM78adpehHQAAAAD+hyeHAJTRu6C+YW8Z3aFk+L4dAAC+SHVd7gQbkKhlm24zOvhg+QpLyZTc8KfZqZ27RS8scYATNu/Jl2ygKH1Bh550RVmOgxv1HWEcLBF/uOXusvwb+/2Ndxb0OD74+IvuWa3ogGMvsjYopXrlBlu9A0Dp2bAuWxWO1c3mK5LKqe6DR1sXS5+0+yFnpnKdddlq90Sff81++HnnK8Em/uYG44FUoGZu0j1orKmV1tlZXfq6Xiq5TO6DL33pSx08hQIAAIC28VU2QCw2BQOIPs/MGzYAojNyAMSaazYYOQAi86PjAJTbeuDAsCZDPHh/DgAJzzP/NWyG4R0AAAAA/ounhgCU2bugrmE2MobS4Pt2AAD4PBv1yn2zqi77nk1I1LILr7zRMjIlH360Kui3/X6pnLdOA0YGa5v8/7ekPffimzZQlL6gPQ8/pyzHwR1Hj3fzKxFzH1lYln9jp025pqDH8fHGV92zWtHPJ021NiipTSOz/nM5AJSoqrrcw+Yrksqp7tv8zLpY+qQd9z4+lets2/whiT7/unX2U85Xgo06dLLxQCpQd2zSLWisqZXW2Uld+rteKrrsA54+AQAAQNv5KhsgFt9tA0SfZ+YNGwDRGTkAYs01G4wcAJH50XEAynFNsFvYasM8eH8OAAnPM78SdrkhHgAAAAB83w5AWb4L+mHYIqM8FJ3v2wEA4PNUZbKTbD6ilmV+vHew8sOPLCNTcu6l16V27kaMmeAAp+DNd5bZQFH6gnbYa2JZjoW/PvdKN78S8erf3yzLv7GDjjmroMfx2RfecM9qRb845SrrgxKqqi57oBU8AJToM+a67ETzFUnl1KZD9rYulj5p4IjDUrnORh9yUqLPv34/c77zlWD9dxpnPJAK1OxNugSNNbXSOpvQdXPXS0WXvdDTJwAAAGg7X2UDxGJTMIDo88y8YQMgOiMHQKy5ZoORAyAyPzoOQLmuC3YIW2GoB+/PASDheWaHsHMM8wAAAABUOk8LASjTd0HfD3vcSA9F5ft2AAD4rNo++W9U1WXfs/mIWnbZ7/9oCZmSt955P+iy1e6pnbtJk6c6yClYvWatDRSlL9xY86CyHAvvvX++m1+JWNvUFHTsXV92f2M7jT6yoMfxxVffcc9qRUefOd36oITaoC53lFU8AJSmDfrs1Nt8RVI51evHY6yLpU/qOWRMKtfZMb++KNHnX7+7fq7zlVBnXnZnsGEZPpOVSrW/1HYOGmtqpXX2i25bul4quKq67IGePgEAAEDb+SobIBabggFEn2fmDRsA0Rk5AGLNNRuMHACR+dFxAMp5bTAw7H3DPXh/DgApzDWPNtQDAAAAUMk8JQSgjN8DfTPsAaM9FI3v2wEA4LOqMtlf2XxELes7dEzw0apVlpApGX/S+amevxkzZzvIKbnq5odtpCh9Tj/acreyGws36jsiWLZ8pRtfCdlki13L7u8s8+OfFfQY/v2tpe5ZrWjib26wRiilMrlTrOIBoGR1qMpk/2bOIqls1u3b7WtdLIVNuXZO8MN+u6RynZ039frEnn19tGqN85VgY4+9yFggFbB5tZ2CxppaaZ2N7TbQ9VLBVdXVb+HREwAAALSdL7IBYrEpGED0eWbesAEQnZEDINZcs8HIARCZHx0HoNzXB5mw1wz54P05AKQw1zwkrMmQDwAAAEAl8oQQgDJ/D/QfYTON+FAUvm8HAICWavvkv1FVl3vX5iNq2dXX32b5mJLnFr8SbNR3RKrnb9ELSxzolNxy70IbKUqfafLld5blWPiT3Q530ysxPbcdXXZ/Zx/PCZqbmwt2DN9dutJ9qxWdeP4t1giltGlkJnuelTwAlK7qTO5ycxZJ5VLvn+5vXSyFnTk1vWfAM2bOTuzZ19vvLXe+EmybXccbC6QCNr/2R0FjTa20zvbqsbXrpWLLNn2nW/6rnjwBAABA2/kiGyAWm4IBRJ9n5g0bANEZOQBizTUbjBwAkfnRcQAqYY1QHfaEYR+8PweAFOaa9WErDfsAAAAAVBpPBwGogPdAXwm72KgPBef7dgAAaKkqkzvexiNq2RY7HRCsXr3G8jElow6alOr56zRgZLC2qcmBTsmcRxfbSFH6TMdMvq4sx8OjT7nQTa/EbL7j/mX5t/bB8hUFO4YrP1ztvtWKTrvkNuuE0upKK3kAKF3VmWzefEVSudR36AHWxVLYxHOuT+06mzf/qcSefb346jvOV0Kde/XsoKbfLsYCqYA9Wbtx0FhTK62zXXts63qp3Bo9dQIAAIBk+CIbIBabggFEn2fmDRsA0Rk5AGLNNRuMHACR+dFxACplnfCfYfcZ+sH7cwBIYa65edhbhn4AAAAAKokngwBU0Lugo8Oajf5QML5vBwCAT32r39CvV9Vl37HxiFp23S33WDqm5J6/PJr6+RsxZoIDnaKFz//dZorSZxo38RLjIQWx2dB9y/Jvbcnf3izYMVzb1OS+1YpOu2SWdUIJVZXJ3Wg1DwClq7ZP/htVmexq8xZJ5dBmOxxoXSyFHXLC5e3i2djCRX9zvhLqsJOvNA5IBe6Zmo2DxppaaZ3ttOmPXS+V+m6kLjfNUycAAABIhi+yAWKxKRhA9Hlm3rABEJ2RAyDWXLPByAEQmR8dB6CS1gr/GvYHwz94fw4AKcw1Nwl73vAPAAAAQKXwVBCACnsXtHfYajMAKAjftwMAwKeqMrnjbTyilg2sHxesWbvW0jEFa5uagm3zh6R+DidNnupgp+jV19+3maL0mUYdOrksx8TnFr/ipldiem47uiz/1p5qfKGgx/GC6e5bcTvtktusFUpp48hM7h6reQAo+efO95m3SCqH+u80zrpYCtvriHNTucZ+0Gd4sGZNcu8l5z7+ovOVUDv8bKJxQCpgP6jLBo01tdJ6G9TzJ66ZSn03Upc9whMnAAAASIYvsgFisSkYQPR5Zt6wARCdkQMg1lyzwcgBEJkfHQeg0tYLHcLONAUA788BIIW55vfD5psCAAAAAFAJPBEEoALfBW0X9oFZAKTO9+0AAPCxb/Ub+vWquuw7Nh5Ry26adZ9lY0quaritIOdwxszZDnaKVny4ymaKUgVsrtlpwMigqanZTa/EfHxeynH+Nf/JxoIex4uve8C9K2anXjLLWqGUymTnWtEDQGkLx+yjzVsklUObDzvYulgKq9/vpFSusT4/HZPoc687Hmh0vhJoyrVzgk5bjTIOSAVs48ywoLGmVlpvdb12cM1UaB0z9Vt74gQAAADJ8EU2QCw2BQOIPs/MGzYAojNyAMSaazYYOQAi86PjAFTqumF8WJOpAHh/DgAJzzO/HnaHaQAAAAAA5c7TQAAq9F3QZmF/NxOAVPm+HQAAPlZVl51o0xG1bJtdDgmampotG1OwbPnKIPPjvQtyHhe9sMQBT9mlNzxoU0WpRQPqDy27MTH7s6Pc7ErM6tVrgo6968tyDvbI488W9FhONY7F7tcXz7ReKKUyuflW9ABQ2qrrhvU0b5FUDm2R+7l1sRS2za7j28Vz2Bl3PeF8JdAxk68zBkgFrktmx6CxplZab5vUDXPNVGTZpm/1G/p1T5wAAAAgGb7KBojFpmAA0eeZecMGQHRGDoBYc80GIwdAZH50HIBKXjtsH7bUdAC8PweAhOeZXwk7z1QAAAAAgHLmSSAAFfwuqDpsvtkApMb37QAA8PFGG1V12XdsOqKWzbx7riVjSn7926sKcg47DRgZrG1qcsBTdv2dj9tUUWpRj232Lrsx8ehTLnSzKzGvvPZG2c7BHn7smYIeyytuesi9K2anXPQn64USqqou95RVPQCUvA5Vddkl5i6S2nsD6g+xLpbC+gw9IJVrbNzRkxN97nXVzQ87Xwm089hfGwOkAtej145BY02ttM6ertnY9VK5NXrUBAAAAMnxVTZALDYFA4g+z8wbNgCiM3IAxJprNhg5ACLzo+MAVPr6oWfYy6YE4P05AKQw1zwgbI0pAQAAAADlyBNAACr8PdBXw24xI4BU+L4dAACq6rITbTiilg3JHxo0NTVbMqbgtdffCjbZYteCnMcRYyY44AVw97xFNlWUPmnKtXOCH2w2ouzGxSuvm+VmV2IefuyZsp2HPRT+2wrpmlsfcf+K2SkX/tGaoYSqyuSet6oHgPbwDDr3O3MXSe29rYYfZl0shdVunk/lGvv1uVcm9syrqbk5uHD6/c5XAvUcso8xQCpwvXttHzTW1Err7MHaTq6XSn0vUpeb5kkTAAAAJMdX2QCx2BQMIPo8M2/YAIjOyAEQa67ZYOQAiMyPjgNgDREEVWGPmBaA9+cAkMJc86dh75sWAAAAAFBuPP0DwHug4Cthp5sVQOJ83w4AQGX7dufs16oz2bdtOqKW3Xnfw5aLKTnomLMKdh4nTZ7qgBfA/GeW2FRR+qTTLplVluPiQ48942ZXYmbMnF2287BHn2gs6LH8/cz57l8xO/nCW60ZSqlM9hUrewAofdV1w0aYu0hq7w3a+RfWxar4zpx6Z2rX2OXT/5TYM68PVnzkfCXQieff4v4vFaF+vbYPGmtqpXV2xybdXC8VWlVd9ghPmgAAACA5vsoGiMWmYADR55l5wwZAdEYOgFhzzQYjB0BkfnQcAP5rHfEfYTeaGoD35wCQwlyzR9iLpgYAAAAAlBNP/gDgv98F7Re22uwAEuP7dgAAKlt1JnesDUfUsp1GH2mpmJIFC58LOvauL9i5nDFztoNeAC8sedvGitInHTP5D2U3Ln583/5g2Qo3uxJzyrlXlu1c7LnFrxT0WE6ftcD9K2YnnX+rdUNJlX3Dyh4ASt9GvXLfrM7k1pi7SGrPDd7lCOtiVXwTzroutWvs9tnzEnvm9dqbS52vBNrz8HPc/6UiNLDnT4PGmlppnc3YpIfrpULrmKnf2pMmAAAASI6vsgFisSkYQPR5Zt6wARCdkQMg1lyzwcgBEJkfHQeA/1lLfDnsdNMD8P4cAFKYa34v7EHTAwAAAADKhad+APBP74K2C3vXDAES4ft2AAAq17c7Z79Wncm+bcMRtWzOvMctFVMyfJ9jCnouF72wxEEvgPc+WGljRemTxk28pOzGxc133N+NrgSNOmhS2c7F/v7G2wU9ltNnLXD/itnxv5lh3VBCVdVl37O6B4D2oTqTnWv+Iqk9t82uv7QuVsV34HHpPQNe+OzixJ55Pffim85XAvXf6SD3f6kI/aTndkFjTa20zq7slHG9VGTZpm/1G/p1T5kAAAAgOb7KBojFpmAA0eeZecMGQHRGDoBYc80GIwdAZH50HAD+95piZNhy0wTw/hwAEp5n/mvYpaYIAAAAAJQDT/wA4H+9C9okbKFZArSZ79sBAKhc1ZlhE2w2opaNHHu8ZWJKbr3z/oKey04DRgZrm5oc+AJoam4OLvrD/TZXlMJGHTq57MbGfQ7/tRtdqd13m5qDHoP3LNv52PIVHxb0eE6ftcD9K2ZHnf57a4cSqiqTfd/qHgDayfPoutyJ5i+S2nM/3v1o62JVfCMPPj21a+y995cl9sxr/tNLnK82dsbUO4KOvevd/6UilN10SNBYUyuts/M693a9VGaNnjABAABAsnyZDRCLTcEAos8z84YNgOiMHACx5poNRg6AyPzoOAB8/rqiV9gLpgrg/TkApDDXPCBslakCAAAAAO2ZJ30A8Lnvgb4adoOZArSJ79sBAKhM3+6c/Vp1Jvu2zUb0aR9virZg4XOWiSlYvXpNMCB7YEHP54gxExz4Apr2x0dtsCiF7bj38WU3Pp55wbVuciVm4bOLy3Y+Vts/HzQ3Nxf0eE6ftcD9K2aHnXSF9UMplckttcIHgPZhg17DBpi/SGrPbT/6WOtiVXzb7XFMKtdX10GjEn3m9edH/up8tbH9J1zo3i8VqZHdtwkaa2qldfbrrv1cLxVYVV32Wk+YAAAAIFm+zAaIxaZgANHnmXnDBkB0Rg6AWHPNBiMHQGR+dBwAvnht8e2wu0wXwPtzAEhhrjkg7O+mCwAAAAC0V57yAcAXvgfqEHZ0WJMZA7SK79sBAKhM1ZnsMTYbUcv2PeJUS8SUXHjljQU/n5MmT3XgC+iPf37KBotS2FbDDyu78fHm2+e4yZWYS665uWznYwPrxxX8eE6ftcD9K2bjJl5i/VBKZXJLrfABoJ3Yeuv/8/HYbQ4jqb220z6TrItV8fXdYWwq19f2o45I9JnXn+572vlqY4Pzv3Tvl4rUz7oPChpraqV1NqHrFq6XCqyqLnuEB0wAAACQLF9mA8RiUzCA6PPMvGEDIDojB0CsuWaDkQMgMj86DgDrXl98Jex0Uwbw/hwAUphrVoc9ZMoAAAAAQHvkCR8ArPdd0A5h75k1QGy+bwcAoPJs0Gen/6+6LvumzUb0aRv2qQ+efu5FS8QUvPf+sqD74D0Kfk5nzJzt4BfQnEcX22BRCuux7d5lN0Y++exf3eRKzIh9jy3bOdmogyYV/HhOn7XA/Stm+xx5njVEKZXJLbXKB4D2Ixy/bzaHkdReG77/SdbFqvg23nJkKtfXQcec5ZlXCfWbq+4NfthvF/d+qUgd2G1g0FhTK62zg7tt5XqpwDbonRvo6RIAAAAky5fZALHYFAwg+jwzb9gAiM7IARBrrtlg5ACIzI+OA0C0dcbPwlaaOoD35wCQ8Dzz38OuNm0AAAAAoL3xdA8AIr0L6hrWaOYAsfi+HQCAylOdyR5qoxG17LDjz7U8TMnE039XlHP63OJXHPwCeuK512yyqIpvyrVzgo367lx2Y+Sy5f6fbyl54613gw371JftnOyoky8o+DH9/cz57mEx2+PQydYQpVQmt9QqHwDaj6re2YPNYSS11/LjTrUuVkV31uV3pXZ9nXH+tESfeV3SMNc5a0OHnni5+75UxA7vtmXQWFMrrbO9emzteqm4sk3f7pz9mqdLAAAAkCxfZwPEYlMwgOjzzLxhAyA6IwdArLlmg5EDIDI/Og4A0dcambDnTR/A+3MASGGuuVeYH3cGAAAAoN3wVA8AIr8H+lrYH8weIDLftwMAUFn69DngX6ozuZdtNKJP+2G/nYOXX33d8jAFi196LdhosxEFP6edBowM1jY1OQEF9NLf3rXJoiq+0y+9vezGyN4/2ccNrsT8btotZT0vu+DKGwt+TK+59RH3sJjtMu4064hSKpP7wEofANqP6syOPzKHkdRe2+2QM62LVdEdd/b1qV1ff7jl7sSedy1fucr5amPbjz7WfV8qYsd23SJorKmV1tnwHtu6XirvfcizniwBAABA8nydDRCLTcEAos8z84YNgOiMHACx5poNRg6AyPzoOADEW298Pex6Uwjw/hwAUphr9g5bbAoBAAAAQHvgiR4AxH4XdEDYKrMIWC/ftwMAUFmqeuX2ttGIWnbcaZdYGqZk3yNOLco5HTFmgoNfYO99sNImi6r4Jp5zfdmNkbvsf5wbXAlpbm4OBg0/qKznZX+e+1jBj+sVNz3kHhazYfv8yjqihKqqy75npQ8A7Us4hr9gHiOpPbbn4edYF6uiO2ji71K7vuYteDqx512vvbnU+WpD5027L/jRlru570tF7MQu/YLGmlppnf140+1cLxX3PiQ3zVMlAAAASJ4vtAFisSkYQPR5Zt6wARCdkQMg1lyzwcgBEJkfHQeA+GuODmGHha02lQDvzwEg4bnmN8JuNI0AAAAAoNR5mgcArXoX1DfsRTMJWCfftwMAUEkmfbk6k33GRiP6tE222DV44613LQ1T8OgTjUHH3vVFOa+TJk91Agqsqbk5uPAP99tsURXdoSddUXbj5FEnX+AGV0L+PHdB2c/N3n53acGP66U3POgeFrNtdh1vLVFSZd+w1geA9qUqk73EHEZSe2yf8edZF6ui2+3nZ6Z2fb3+5juJPe96ZvHrzlcbGn/ate75UpE7s/NmQWNNrbTO+vXa3vVSee9DfuGpEgAAACTPF9oAsdgUDCD6PDNv2ACIzsgBEGuu2WDkAIjMj44DQOvXHgPD/mY6Ad6fA0DC88wOYUeHrTWdAAAAAKBUeZIHAK1+F/T/wm43m4Av5Pt2AAAqR3XdsBE2GFHLTj3vasvCFDQ3Nwe5vY8u2nmdMXO2k1AE19z6iM0WVdHtc+SUshsnL776Zje3ErL7uEllPS/rO3RMUY7rRX94wD0sZn13GGstUUplsq9Y7QNA+1JVlxtpHiOpPbb/MRdaF6ui++meE1K5tjbZYtd/vFtLyrwnXnK+2tBO+0xyz5eK3HmdeweNNbXSOuuW2cn1UmF1rMsO8lQJAAAAkucLbYBYbAoGEH2emTdsAERn5ACINddsMHIAROZHxwGgbeuP74fda0oB3p8DQApzzSFhr5tSAAAAAFCKPMEDgDa9B/pK2Ilha80q4H/xfTsAAJWjKpN7xCYj+rSug0YF7y9dZlmYgptum1PUc7vohSVOQhHcOvspmy2qosuPO7Xsxso773vYza1EzJv/VPlvzD3+9IIf14/3Knb/il+XQXtaT5RQ4Tr3eat9AGhfvttj2PfCcbzZXEZSe2vcxEusi1XR9dtxXCrX1pD8oYk+87rj/medr1Z23rVzgk5bjXLPl4rcpZ3qgsaaWukLe6Zm4+AHrpUKK9v07c7Zr3mqBAAAAMnzlTZALDYFA4g+z8wbNgCiM3IAxJprNhg5ACLzo+MA0PY1SIeww8JWm1qA9+cAkPBc8zthM00rAAAAACg1nt4BQCLvggaHvWpmAf/E9+0AAFSGqkz2xzYYUct+O9VvJKRh9eo1wZbDxhbtvHYaMDJY29TkRBTBfY/81YaLquiGjj6u7MbKxudfdnMrESPGTCj7udkV1xX+//KsXrPW/SvuxsLT7gs27F1vPVFaPW3FDwDt8Hl1Xe4p8xhJ7a1DTrjc2lgV3Y8G7JbKtbXvEacm+0Xo7Y85X63sqDOmu99LJdC0Tr2Cxppa6Qt7sLaTa6XSymSf8TQJAAAA0uErbYBYbAoGEH2emTdsAERn5ACINdf0g1EAMf6LiZEDABJbi/QLW2x6Ad6fA0DC88wOYYeFrTK9AAAAAKBUeHIHAIm9C/p/YbeaXcB/8307AACVoaoud69NRvRpPbcdHSxbvtKSMAUXXXVTUc/tiDETnIQiebzxNRsuqqLbMndI2Y2XHyxf4eZWAm66bU5FzM+ef3FJwY/tBys+cv+K2WmX3GY9UXotsOIHgPanOpObYh4jqb31i1OusjZWxXb2Ffekdm2dcu6ViT7zuvSGB52zVpYdc4L7vVQC3bBJj6Cxplb6wm7bpJtrpdLK5C7zNAkAAADS4UttgFhsCgYQfZ6ZN2wARGfkAIg112wwcgBE5kfHASDZ9cjXw6abYoD35wCQwlyzb9jzphgAAAAAlAJP7AAg0fdAHcIOCLN5Nvi+HQCASlDdJ9vfBiNq2eXT/2Q5mIL3ly4Lug/eo6jndtLkqU5Ekbz46js2XFRF13PImLIaK7tstbsbWwlYtnxl0Psn+5T93Ozjf2Mx/O3Npe5fMTv27AbriRKrKpN70KpcXpRQAAAgAElEQVQfANqfjr2zw81lJLW3jjz9WmtjVWzH/eaG1K6ta264PbHnXR9+tMb5amVTrp0TdB64h/u9VALN3KR70FhTK31h1/6op2ul0updf4CnSQAAAJAOX2sDxGJTMIDo88y8YQMgOiMHQKy5ZoORAyAyPzoOAOmsS/YKW2GqgffnAEDC88yvhU0zzQAAAACg2DytA4BU3gV1D1topkGF8307AADlr7oud7MNRvRpm++4f7Bq1WrLwRSccNZlRT+/M2bOdiKK5N2lK2y6qIqutl++rMbLbXY5xI2tBBx9yoUVMT8bf9L5RTm+i15+y/0rZoeceJk1Rel1l1U/ALQ/Hbvlv1Vdl20yl5HUnjpm8nXWxqrYDv7VpaldW3PmPZ7Y867X3/7A+Wplx0z+g3u9VCLdu3GXoLGmVvrCLujU27VScQ3r6WkSAAAApMPX2gCx2BQMIPo8M2/YAIjOyAEQa67ZYOQAiMyPjgNAemuTHmGPm27g/TkAkMJc82dhS003AAAAACgWT+kAILX3QF8Nu9Rsgwrm+3YAAMrbhr2Gda+uyzXbXESfdt0t91gKpuDlV18PavrvUvTzu+iFJU5GkaxZ22TTRVVsZ195d9mNlyPHHu/GVmR33vdwxczP/jx3QVGO8YJnlriHxWzvX55rTVFiVWVyN1r5A0D7VJ3JzTefkdSemvibG6yNVbGNOnRyatfWK6+9kdjzrudeetP5amX1+53kXi+VSA9u3ClorKmVvrBTuvRzrVRSmdwHX8rnv+JJEgAAAKTDF9sAsdgUDCD6PDNv2ACIzsgBEGuu2WDkAIjMj44DQLrrk38JOyFsrWkH3p8DAAnPNTcKm23KAQAAAEAxeEIHAKm/Cxoa9jezDiqQ79sBAChvVZns1TYY0acNHnFwsLapyVIwBWOPOrPo57fTgJHOb5FdfuM8Gy+qIjthyi1lN2aOO3qym1oR/e31t4NeQ/aqiPlZ98F7BGvWFOf/hM95dLF7WMyyYyZZV5ReV1r5A0D7VF2XPctcRlJ76uNnYNbGqtS2H31sKtfVD/vtnOi7rYcXvux8taIp184Jug7a071eKpEW1GwSNNbUSl/YL7tu6VqpoKoyuXs8RQIAAID0+GobIBabggFEn2fmDRsA0Rk5AGLNNRuMHACR+dFxACjMOmWLsOdNPfD+HABIeJ7ZIeywsI9MPQAAAAAoJE/nAKAg74K+E3aTmQcVxvftAACUr+/1yv2wKpNdbYMRfdrMu+daBqZgwcLngo6964t+fkeMmeBkFNn1dz5u80VVZONPm1Z2Y+axp13splYkq1atDnYafWTFzM9+ecKUoh3rWX95xj0sZgPqD7GuKLUyuSlW/wDQPlX3yu5oPiOpPXXKRX+yNlbFtvlOB6VyXQ0aflCiz7vuevA556sVHXt2g/u8VCJ1DHumZuOgsaZW+sLGdB/keqmgqupyp3qKBAAAAOnx5TZALDYFA4g+z8wbNgCiM3IAxJprNhg5ACLzo+MAULi1ytfCLjH9wPtzACCFuWb3sMdMPwAAAAAoFE/lAKCg74L2CvvADIQK4ft2AADKV3Umd77NRfRp2+/xy6C5udkyMAXD9zmmJM7xpMlTnYwiu+OBRpsvqiIbe+xFZTdunnXR793UiuDjucovJv22ouZo8xY8XbTjPX3WAvewmHUZtKe1hc0kAYCEfKvf0K9XZ3JrzGkktZfOuPR2a2NVbJ22GpXKdTX6kJMSfd41464nnK9WNGLsKe7zUolUmxkWNNbUSutseI9tXS8V9R4km/UUCQAAANLj622AWGwKBhB9npk3bABEZ+QAiDXXbDByAETmR8cBoPBrluFhb5qG4P05AJDwPPNfwyaHNZmGAAAAAJA2T+QAoODvgmrD7jcLoQL4vh0AgPL03R7DvleVya60uYg+7c9zF1gCpmDm3XNL5hzPmDnbCSmyB5/4/9m7EzepqgPhw9FsM18mM5P5ZpLYgKZbBGWRatqNoKIRjRvVgDQiClFREuKuUdxxi+KCCwQURUUUlXaLGiXugor7ioZ2F1dUUBSRrbvPd0jM9yQjahVUdd+69b7P8/sDoO4959xzq+u84fBFlWWDDz4ndfPmpVffalBrBaeed3lZrc+23e3AVvu/bmxsChOufdAYlkdjJt8T2nbv69kiaWWyR9sBAIDSVVGdfdSaRlKpdN4V93o+VtnuiRTrvjrhrEsKuud12Y2P+MzybNzUmaHzNkON81JC6pLZJTRUVklf2zZdf+l+KaN+snG/H9tBAgAAgOLx7W2AvDgUDCD3dWadaQMgd2YOgLzWmvVmDoCc+dFxAGid55YfxSZaiuD9OQBQhLVmj9gcSxEAAAAAislOHAC0ynugtWLDY4usRkgx328HACCdKqprz3CwiP7ebvsd6/GvCFasaAxb1o5IzOf80mtv+VBa2QuvvOcARpVl2X1HpW7uvP5P9xnUWtjYSdeV3Rpt0tRbWu3/e978T41feXb8udd5tkhgFZm+I+wAAEDpalOdPceaRlIp1K6mn2djle+eyHnXF+3euvTqWwu237V8RaPPazU6roifr6T826TbTqGhskr62rp128X9UjbvQLKv2j0CAACA4vINboC8OBQMIPd1Zp1pAyB3Zg6AvNaa9WYOgJz50XEAaN3nl11jb1uS4P05AFDgdea/xEbHGi1JAAAAACgGu3AA0Krvgipj91iRkFK+3w4AQPpU1dT9R0Umu9DhIvp7jz8zx+NfEaw86C8pn3GHnruHxqYmH0ore/O9jx3AqLJs24FHpG7uvOP+Rw1qLWjytNvLbn3WvsfA8PHCRa32fz775feMX3k24viJni2SWCY7wC4AAJSuiups1ppGUim0/s9392wseyJF6J4HnijYfteHH33m81qNBvzmdOO8lKC23PiXoaGySvrK5sTWq866X8qkiursVLtHAAAAUFy+xQ2QF4eCAeS+zqwzbQDkzswBkNdas97MAZAzPzoOAK3/DPOfsYmWJXh/DgAUYa2ZiT1tWQIAAABAodl9A4BWfw+0Vmx47FMrE1LG99sBAEifNpk+xzhYRH/vVwef6tGvCD759LPQddshifmc++97jA8lARYuWuIARpVlm+48InXz56zHZxvUWmqH9pZ7QruavmW3Rjvx7Emt+v9+32MvG7/ybPffjvZ8kcS61W5jFwAASlfFpn3/b5zTm61rJCW9ztsM8Wyssq1uxOlFu7deef3tgu13vfLmhz6v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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+jz04EAAAAAAA8n9tBFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVPpCbxwAADYFJREFUVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVZX24EAAAAAAQJC/9QQbVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHACWH6cFeOLUKMAAAAASUVORK5CYII=" + }, + "paraswap": { + "color": "#0058D4", + "title": "Paraswap", + "icon": "data:image/svg+xml,%3csvg width='75' height='31' viewBox='0 0 75 31' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3cg clip-path='url(%23clip0)'%3e %3cpath d='M18.5198 20.2395L13.209 10.2522L7.89786 20.2395H18.5198ZM9.49768 14.7701L11.9002 10.2522H7.09521L9.49768 14.7701ZM57.8444 18.255C58.0989 18.255 58.3473 18.2456 58.5897 18.2267C58.8321 18.2081 59.0523 18.1836 59.2514 18.1538C59.4499 18.1236 59.6243 18.0956 59.7759 18.0693C59.9263 18.0431 60.0417 18.0186 60.1217 17.9961V14.3272C60.1217 14.0198 60.082 13.7349 60.002 13.4722C59.9226 13.2096 59.7951 12.9826 59.6213 12.7913C59.4457 12.5997 59.2171 12.4497 58.9356 12.341C58.6535 12.2323 58.3094 12.1777 57.9046 12.1777C57.507 12.1777 57.1672 12.2042 56.885 12.2565C56.6029 12.3091 56.3942 12.3652 56.2595 12.4252L56.3666 13.0667C56.47 13.0292 56.633 12.9808 56.855 12.9206C57.0781 12.8606 57.4156 12.8305 57.8685 12.8305C58.1861 12.8305 58.4423 12.8772 58.6372 12.9711C58.8321 13.0652 58.9831 13.189 59.0908 13.3428C59.1972 13.4964 59.267 13.6688 59.2989 13.8604C59.326 14.0239 59.3392 14.1925 59.3434 14.3645H59.3464V14.4433C59.3464 14.4461 59.347 14.4484 59.347 14.4512V14.8114H59.3464V15.4528H59.347V17.501C59.1876 17.5311 58.9951 17.5556 58.7684 17.5742C58.5422 17.593 58.2775 17.6022 57.9756 17.6022C57.7296 17.6022 57.5088 17.5815 57.3139 17.5402C57.1196 17.4992 56.9524 17.4336 56.8135 17.3436C56.6745 17.2535 56.5669 17.1336 56.4917 16.9831C56.4159 16.8331 56.3786 16.6497 56.3786 16.4318C56.3786 16.1841 56.4339 15.9857 56.5452 15.8354C56.6565 15.6854 56.7996 15.567 56.9747 15.4808C57.1491 15.3946 57.3398 15.3385 57.5467 15.3119C57.7536 15.2859 57.9521 15.2729 58.1428 15.2729C58.2926 15.2729 58.4261 15.2775 58.547 15.2859V14.6629C58.5368 14.6622 58.5278 14.6604 58.5181 14.6594C58.3948 14.6479 58.2775 14.6422 58.1663 14.6422C57.7933 14.6422 57.4475 14.6762 57.1293 14.7438C56.8117 14.8114 56.5374 14.9183 56.307 15.0644C56.0766 15.2109 55.8974 15.3963 55.7705 15.6216C55.6435 15.8466 55.5798 16.1165 55.5798 16.4318C55.5798 16.7621 55.6375 17.0415 55.7524 17.2701C55.8673 17.4992 56.0267 17.6867 56.2294 17.8331C56.4321 17.9793 56.6703 18.0862 56.9446 18.1538C57.2189 18.2211 57.519 18.255 57.8444 18.255ZM38.5987 18.255C38.8526 18.255 39.101 18.2456 39.3434 18.2267C39.5858 18.2081 39.8066 18.1836 40.0051 18.1538C40.2035 18.1236 40.3786 18.0956 40.5296 18.0693C40.6805 18.0431 40.796 18.0186 40.8754 17.9961V14.3272C40.8754 14.0198 40.8357 13.7349 40.7563 13.4722C40.6769 13.2096 40.5494 12.9826 40.375 12.7913C40.1999 12.5997 39.9714 12.4497 39.6893 12.341C39.4072 12.2323 39.0637 12.1777 38.6583 12.1777C38.2607 12.1777 37.9208 12.2042 37.6389 12.2565C37.3568 12.3091 37.1483 12.3652 37.0132 12.4252L37.1204 13.0667C37.2235 13.0292 37.3866 12.9808 37.6093 12.9206C37.8316 12.8606 38.1693 12.8305 38.6222 12.8305C38.9404 12.8305 39.196 12.8772 39.3915 12.9711C39.5858 13.0652 39.7368 13.189 39.8444 13.3428C39.9515 13.4964 40.0207 13.6688 40.0532 13.8604C40.0802 14.0239 40.0929 14.1925 40.0971 14.3645H40.1007V17.501C39.9413 17.5311 39.7494 17.5556 39.5226 17.5742C39.2959 17.593 39.0318 17.6022 38.7299 17.6022C38.4832 17.6022 38.2625 17.5815 38.0682 17.5402C37.8733 17.4992 37.7063 17.4336 37.5673 17.3436C37.4281 17.2535 37.321 17.1336 37.2456 16.9831C37.1702 16.8331 37.1326 16.6497 37.1326 16.4318C37.1326 16.1841 37.188 15.9857 37.2994 15.8354C37.4103 15.6854 37.5534 15.567 37.7284 15.4808C37.9034 15.3946 38.0941 15.3385 38.3004 15.3119C38.5073 15.2859 38.7058 15.2729 38.8965 15.2729C39.0463 15.2729 39.1792 15.2775 39.3007 15.2859V14.6629C39.2905 14.6622 39.282 14.6604 39.2718 14.6594C39.1485 14.6479 39.0318 14.6422 38.9205 14.6422C38.547 14.6422 38.2011 14.6762 37.8835 14.7438C37.5656 14.8114 37.2914 14.9183 37.0609 15.0644C36.8302 15.2109 36.6514 15.3963 36.5243 15.6216C36.3972 15.8466 36.3337 16.1165 36.3337 16.4318C36.3337 16.7621 36.3915 17.0415 36.5064 17.2701C36.6218 17.4992 36.7806 17.6867 36.9832 17.8331C37.1859 17.9793 37.4247 18.0862 37.6983 18.1538C37.9726 18.2211 38.2727 18.255 38.5987 18.255ZM29.279 18.255C29.5329 18.255 29.7813 18.2456 30.0238 18.2267C30.266 18.2081 30.4867 18.1836 30.6855 18.1538C30.8837 18.1236 31.0591 18.0956 31.2099 18.0693C31.3607 18.0431 31.4761 18.0186 31.5555 17.9961V14.3272C31.5555 14.0198 31.5158 13.7349 31.4366 13.4722C31.357 13.2096 31.2296 12.9826 31.055 12.7913C30.8802 12.5997 30.6516 12.4497 30.3694 12.341C30.0872 12.2323 29.7437 12.1777 29.3384 12.1777C28.9409 12.1777 28.6013 12.2042 28.3192 12.2565C28.0369 12.3091 27.8285 12.3652 27.6934 12.4252L27.8008 13.0667C27.9039 13.0292 28.0668 12.9808 28.2896 12.9206C28.5118 12.8606 28.8497 12.8305 29.3027 12.8305C29.6204 12.8305 29.8767 12.8772 30.0715 12.9711C30.266 13.0652 30.4174 13.189 30.5245 13.3428C30.6319 13.4964 30.7012 13.6688 30.7332 13.8604C30.7602 14.0239 30.7731 14.1925 30.7776 14.3645H30.7806L30.7807 14.4473L30.7809 14.4512V14.8114H30.7806V15.4528H30.7809V17.501C30.6218 17.5311 30.4293 17.5556 30.2026 17.5742C29.9764 17.593 29.712 17.6022 29.41 17.6022C29.1636 17.6022 28.943 17.5815 28.7484 17.5402C28.5536 17.4992 28.3866 17.4336 28.2477 17.3436C28.1086 17.2535 28.0013 17.1336 27.9261 16.9831C27.8504 16.8331 27.8128 16.6497 27.8128 16.4318C27.8128 16.1841 27.8683 15.9857 27.9796 15.8354C28.0905 15.6854 28.2336 15.567 28.4087 15.4808C28.5835 15.3946 28.774 15.3385 28.9808 15.3119C29.1873 15.2859 29.3863 15.2729 29.5769 15.2729C29.7263 15.2729 29.8595 15.2775 29.9808 15.2859V14.6629C29.9709 14.6622 29.9622 14.6604 29.9524 14.6594C29.829 14.6479 29.712 14.6422 29.6006 14.6422C29.227 14.6422 28.8814 14.6762 28.5637 14.7438C28.2458 14.8114 27.9716 14.9183 27.7411 15.0644C27.5104 15.2109 27.3316 15.3963 27.2044 15.6216C27.0776 15.8466 27.014 16.1165 27.014 16.4318C27.014 16.7621 27.0717 17.0415 27.1866 17.2701C27.302 17.4992 27.4608 17.6867 27.6633 17.8331C27.8663 17.9793 28.1048 18.0862 28.3791 18.1538C28.6532 18.2211 28.9528 18.255 29.279 18.255ZM62.1993 20.2129V17.7935C62.3347 17.8912 62.5512 17.9943 62.849 18.1033C63.1473 18.2117 63.4992 18.2663 63.904 18.2663C64.3491 18.2663 64.7443 18.1912 65.0902 18.0412C65.436 17.8912 65.7278 17.6831 65.9665 17.4165C66.2047 17.1502 66.3858 16.8316 66.5085 16.4599C66.6318 16.0884 66.6938 15.6816 66.6938 15.2389C66.6938 14.7663 66.6198 14.3426 66.473 13.9673C66.3257 13.5923 66.1193 13.2734 65.8535 13.0106C65.587 12.7482 65.2688 12.5476 64.8995 12.4086C64.5302 12.2698 64.1187 12.2002 63.6658 12.2002C63.1172 12.2002 62.6643 12.2341 62.307 12.3017C61.9491 12.3691 61.655 12.4405 61.4246 12.5155V20.2129H62.1993ZM33.6117 18.1313V13.0331C33.6754 13.0033 33.8085 12.9658 34.0111 12.9206C34.2136 12.8757 34.4817 12.853 34.8159 12.853C35.1335 12.853 35.3897 12.8701 35.5847 12.9037C35.7792 12.9377 35.9082 12.9693 35.9718 12.9991L36.1267 12.3691C36.0393 12.3316 35.8826 12.2943 35.6561 12.2565C35.4296 12.2191 35.1892 12.2002 34.9347 12.2002C34.4343 12.2002 34.009 12.2435 33.6591 12.3298C33.3095 12.416 33.0353 12.5007 32.837 12.5831V18.1313H33.6117ZM21.6589 20.2129V17.7935C21.7937 17.8912 22.0104 17.9943 22.3083 18.1033C22.6065 18.2117 22.958 18.2663 23.3633 18.2663C23.8084 18.2663 24.2038 18.1912 24.5494 18.0412C24.8953 17.8912 25.1873 17.6831 25.4256 17.4165C25.6641 17.1502 25.8447 16.8316 25.9679 16.4599C26.0912 16.0884 26.1528 15.6816 26.1528 15.2389C26.1528 14.7663 26.0792 14.3426 25.9324 13.9673C25.7851 13.5923 25.5785 13.2734 25.3125 13.0106C25.0461 12.7482 24.7284 12.5476 24.3589 12.4086C23.989 12.2698 23.578 12.2002 23.125 12.2002C22.5767 12.2002 22.1237 12.2341 21.766 12.3017C21.4084 12.3691 21.1145 12.4405 20.884 12.5155V20.2129H21.6589ZM43.8378 18.2663C44.5608 18.2663 45.1311 18.1313 45.5485 17.8612C45.9653 17.591 46.1741 17.1936 46.1741 16.668C46.1741 16.3908 46.1223 16.1602 46.0195 15.9759C45.9154 15.792 45.7807 15.6349 45.6141 15.5035C45.4469 15.3721 45.2538 15.2596 45.036 15.1663C44.8171 15.0731 44.5885 14.9816 44.3503 14.892C44.1199 14.8022 43.9154 14.7204 43.7362 14.6453C43.5575 14.5709 43.4066 14.4902 43.2832 14.404C43.1599 14.3173 43.0667 14.2178 43.0035 14.1048C42.9392 13.992 42.9079 13.8568 42.9079 13.6986C42.9079 13.6898 42.9088 12.6496 42.9094 12.3593L42.9097 12.2849H42.126C42.1243 12.3141 42.1217 13.486 42.1212 13.7236L42.1211 13.7647C42.1211 14.0122 42.1687 14.2224 42.2643 14.3948C42.3599 14.5675 42.4863 14.7157 42.6457 14.8395C42.8044 14.9632 42.9873 15.0719 43.1936 15.1657C43.4005 15.2596 43.6189 15.3515 43.8499 15.4415C44.1356 15.554 44.3762 15.6515 44.5711 15.7341C44.7654 15.8165 44.9223 15.903 45.0414 15.993C45.1611 16.0831 45.246 16.1841 45.2983 16.2968C45.3494 16.4094 45.3753 16.5445 45.3753 16.702C45.3753 17.0321 45.2303 17.2665 44.9404 17.4053C44.6505 17.5443 44.2829 17.6135 43.8378 17.6135C43.5912 17.6135 43.3747 17.5987 43.1882 17.5685C43.0011 17.5387 42.8405 17.5027 42.7052 17.4616C42.5699 17.4206 42.4628 17.3826 42.3834 17.3492C42.304 17.3152 42.2523 17.291 42.2282 17.276L42.0255 17.9397C42.1211 17.9851 42.3118 18.0507 42.5981 18.1366C42.8838 18.2232 43.2971 18.2663 43.8378 18.2663ZM49.1894 18.1313C49.3079 17.8701 49.433 17.5764 49.5648 17.2499C49.6959 16.9236 49.8318 16.5749 49.9708 16.2038C50.1103 15.8323 50.2457 15.442 50.3756 15.0323C50.5067 14.6232 50.6312 14.2042 50.7497 13.7757C50.8688 14.2033 50.9939 14.6211 51.125 15.0298C51.2562 15.4382 51.3915 15.828 51.5317 16.1989C51.6718 16.5701 51.8078 16.9186 51.9401 17.2446C52.0718 17.5706 52.1987 17.8663 52.319 18.1313H53.0372C53.4438 17.2841 53.8174 16.3885 54.156 15.4438C54.4953 14.4994 54.8081 13.4556 55.095 12.3127H54.3311C54.2438 12.7111 54.1344 13.1412 54.0026 13.6032C53.8715 14.0653 53.7296 14.5234 53.5786 14.9767C53.4264 15.4303 53.2754 15.8612 53.1238 16.2695C52.9723 16.6782 52.8285 17.0247 52.6932 17.3096C52.5332 16.9344 52.3756 16.5329 52.221 16.1048C52.0652 15.677 51.9184 15.2436 51.7801 14.8051C51.6417 14.366 51.5148 13.9348 51.3999 13.5111C51.285 13.0872 51.1924 12.688 51.1214 12.3127H50.4538C50.3593 12.6874 50.2529 13.0867 50.1344 13.5109C50.0153 13.9351 49.889 14.3647 49.7548 14.8C49.6207 15.2354 49.4769 15.6673 49.3242 16.0956C49.1714 16.5242 49.0186 16.925 48.8664 17.2981C48.7311 17.0132 48.5855 16.6678 48.4303 16.2622C48.2745 15.8568 48.1211 15.4272 47.9696 14.9734C47.818 14.5198 47.676 14.0625 47.5449 13.6009C47.4132 13.14 47.3031 12.7106 47.2153 12.3127H46.393C46.6781 13.4535 46.9891 14.4969 47.3272 15.4422C47.6646 16.3874 48.0369 17.2839 48.4448 18.1313H49.1894ZM63.8324 17.6022C63.6496 17.6022 63.4751 17.5851 63.3085 17.5517C63.1413 17.5181 62.9861 17.4747 62.8429 17.4221C62.6998 17.3698 62.5747 17.3137 62.4676 17.2535C62.3605 17.1936 62.2709 17.1372 62.1993 17.0846V13.0219C62.3184 12.9844 62.4959 12.9487 62.7299 12.9147C62.9644 12.8811 63.2724 12.8642 63.6538 12.8642C64.3214 12.8642 64.8574 13.0688 65.2628 13.4777C65.6688 13.8867 65.8709 14.4736 65.8709 15.2389C65.8709 15.5614 65.8354 15.8675 65.7638 16.156C65.6923 16.4451 65.5768 16.6961 65.418 16.9101C65.2592 17.1239 65.0505 17.2928 64.7924 17.4165C64.5338 17.5402 64.2144 17.6022 63.8324 17.6022ZM23.2919 17.6022C23.1089 17.6022 22.9343 17.5851 22.7675 17.5517C22.6004 17.5181 22.4455 17.4747 22.3024 17.4221C22.1593 17.3698 22.0341 17.3137 21.927 17.2535C21.8198 17.1936 21.7303 17.1372 21.6589 17.0846V13.0219C21.7778 12.9844 21.9549 12.9487 22.1892 12.9147C22.4237 12.8811 22.7317 12.8642 23.1128 12.8642C23.7806 12.8642 24.317 13.0688 24.7221 13.4777C25.1276 13.8867 25.3304 14.4736 25.3304 15.2389C25.3304 15.5614 25.2947 15.8675 25.223 16.156C25.1516 16.4451 25.0363 16.6961 24.8774 16.9101C24.7181 17.1239 24.5097 17.2928 24.2515 17.4165C23.993 17.5402 23.6732 17.6022 23.2919 17.6022ZM16.3509 18.9175H10.067L13.209 13.0089L16.3509 18.9175Z' fill='%23FDFDFD'/%3e %3c/g%3e %3cdefs%3e %3cclipPath id='clip0'%3e %3crect width='60' height='10.2857' fill='white' transform='translate(7.09521 10.2522)'/%3e %3c/clipPath%3e %3c/defs%3e %3c/svg%3e", + "iconPng": "data:image/png;base64,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" + }, + "uniswap": { + "color": "#FFE9F4", + "title": "Uniswap", + "icon": "data:image/svg+xml,%3csvg width='75' height='30' viewBox='0 0 75 30' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3cpath fill-rule='evenodd' clip-rule='evenodd' d='M43.8413 12.1956C42.7398 12.4731 42.2236 13.3368 42.5366 14.378C42.6707 14.8242 43.0833 15.2743 43.6667 15.6109C44.7182 16.2175 45.0278 16.4631 45.2076 16.8332C45.3576 17.142 45.3707 17.2452 45.295 17.5251C45.1175 18.1821 44.6539 18.5444 43.9907 18.5444C43.3138 18.5444 42.8384 18.1647 42.7323 17.5392C42.6898 17.2877 42.6372 17.2074 42.5157 17.2074C42.3706 17.2074 42.3554 17.2739 42.3554 17.911V18.6145L42.7957 18.7641C43.4832 18.9976 44.4611 18.9697 45.0446 18.6999C46.1813 18.1744 46.617 17.1313 46.1068 16.1565C45.916 15.7919 45.4371 15.385 44.6167 14.8901C43.7545 14.3699 43.3702 13.9915 43.3139 13.607C43.2273 13.016 43.7588 12.5269 44.4853 12.529C45.0543 12.5306 45.2985 12.6653 45.5002 13.0888C45.6265 13.3539 45.7169 13.4416 45.8664 13.4439C46.0318 13.4464 46.0565 13.4156 46.0143 13.2589C45.9865 13.1555 45.9632 12.8963 45.9627 12.6829C45.9618 12.4119 45.9226 12.28 45.8326 12.2457C45.5876 12.1519 44.1572 12.116 43.8413 12.1956ZM21.7253 12.4442C21.7253 12.5644 21.7813 12.6113 21.9248 12.6113C22.3297 12.6113 22.3514 12.7281 22.3962 15.1517C22.4354 17.269 22.4499 17.438 22.6191 17.7506C22.8616 18.1982 23.1904 18.4961 23.6961 18.7263C24.0425 18.884 24.2612 18.9174 24.954 18.9189C25.7056 18.9203 25.8425 18.896 26.2732 18.6853C26.5374 18.556 26.8666 18.3137 27.0046 18.1468C27.4832 17.5683 27.5339 17.2887 27.5881 14.9271C27.6404 12.6529 27.6475 12.616 28.036 12.6125C28.1264 12.6118 28.1827 12.5471 28.1827 12.4442C28.1827 12.2863 28.1268 12.277 27.1764 12.277C26.237 12.277 26.17 12.2878 26.17 12.4389C26.17 12.5601 26.238 12.6073 26.4407 12.6269C26.886 12.6699 26.9222 12.8411 26.9236 14.915C26.925 17.0176 26.8531 17.4221 26.4029 17.8479C25.9843 18.2439 25.6511 18.3773 25.0807 18.3773C24.2613 18.3773 23.6807 17.9959 23.4903 17.3327C23.4262 17.1097 23.4027 16.2895 23.4194 14.8675L23.4445 12.7366L23.738 12.6423C23.8995 12.5904 24.0437 12.487 24.0586 12.4125C24.0826 12.2927 23.949 12.277 22.9055 12.277C21.7813 12.277 21.7253 12.285 21.7253 12.4442ZM29.5245 12.4442C29.5245 12.5735 29.5804 12.6113 29.7721 12.6113C30.1992 12.6113 30.4397 12.7754 30.5362 13.1327C30.5912 13.3358 30.6148 14.306 30.5987 15.6926C30.5699 18.1684 30.536 18.3303 30.0239 18.4324C29.8551 18.4661 29.7761 18.5317 29.7761 18.6384C29.7761 18.7842 29.8581 18.7951 30.9502 18.7951C32.023 18.7951 32.1242 18.7822 32.1242 18.6453C32.1242 18.5386 32.0168 18.4669 31.7512 18.3961C31.4214 18.3082 31.368 18.2602 31.2904 17.9819C31.1909 17.6246 31.1673 13.8609 31.2646 13.8718C31.2992 13.8756 31.6245 14.2235 31.9875 14.6448C32.3505 15.066 33.3436 16.1722 34.1944 17.1029C35.526 18.5596 35.7751 18.7951 35.9843 18.7951H36.2274L36.2514 15.8326C36.2684 13.7292 36.3036 12.8422 36.3724 12.7736C36.4258 12.7204 36.5957 12.6512 36.7498 12.6198C36.9134 12.5865 37.0302 12.5118 37.0302 12.4407C37.0302 12.3409 36.8211 12.3146 35.877 12.2956C34.7668 12.2732 34.724 12.2786 34.724 12.4418C34.724 12.5658 34.7789 12.6113 34.9289 12.6113C35.0417 12.6113 35.2398 12.702 35.3692 12.8128L35.6045 13.0144L35.6309 15.0273C35.6459 16.1638 35.625 17.0403 35.5829 17.0403C35.542 17.0403 35.286 16.7865 35.0139 16.4762C34.742 16.1659 33.9674 15.3104 33.2927 14.5751C32.6181 13.8397 31.881 13.0248 31.6549 12.7644L31.2437 12.2907L30.3841 12.2839C29.5781 12.2774 29.5245 12.2875 29.5245 12.4442ZM38.33 12.4442C38.33 12.5716 38.386 12.6113 38.5656 12.6113C38.6952 12.6113 38.8744 12.6646 38.964 12.7298C39.1175 12.8417 39.1282 12.9859 39.1529 15.2994C39.1839 18.1883 39.1585 18.3502 38.6623 18.4293C38.4124 18.4691 38.33 18.521 38.33 18.6387C38.33 18.7846 38.4146 18.7951 39.5879 18.7951C40.7899 18.7951 40.8459 18.7877 40.8459 18.628C40.8459 18.5091 40.7899 18.4608 40.6522 18.4608C40.5458 18.4608 40.3854 18.4075 40.2958 18.3423C40.1416 18.2301 40.1318 18.0856 40.1087 15.5881C40.0851 13.0296 40.0893 12.9473 40.2555 12.7818C40.3496 12.688 40.5209 12.6113 40.6362 12.6113C40.7899 12.6113 40.8459 12.5667 40.8459 12.4442C40.8459 12.2845 40.7899 12.277 39.5879 12.277C38.386 12.277 38.33 12.2845 38.33 12.4442ZM47.1112 12.4442C47.1384 12.5477 47.2256 12.6113 47.3403 12.6113C47.4422 12.6113 47.6081 12.6988 47.709 12.8058C47.8115 12.9145 48.3848 14.2882 49.0083 15.9186L50.1242 18.8369L50.4168 18.8619L50.7094 18.8869L51.4933 16.8145C51.9245 15.6748 52.3226 14.652 52.3779 14.5417C52.4728 14.3529 52.4939 14.3816 52.7459 15.0431C52.8929 15.4292 53.2844 16.4501 53.6157 17.3118L54.2181 18.8787H54.4835C54.6296 18.8787 54.7682 18.8287 54.7918 18.7676C54.8153 18.7066 55.2006 17.7195 55.648 16.574C56.0955 15.4287 56.5911 14.1597 56.7494 13.7543C57.1101 12.831 57.1823 12.717 57.4698 12.6171C57.5976 12.5728 57.7021 12.4781 57.7021 12.4067C57.7021 12.2967 57.5494 12.277 56.6958 12.277C55.7454 12.277 55.6894 12.2863 55.6894 12.4442C55.6894 12.5652 55.7454 12.6113 55.8922 12.6113C56.2182 12.6113 56.3603 12.6995 56.3603 12.902C56.3603 13.071 54.763 17.4063 54.6646 17.5043C54.6041 17.5646 53.1618 13.5374 53.1096 13.1627C53.0589 12.7986 53.2144 12.6113 53.567 12.6113C53.7047 12.6113 53.7606 12.5631 53.7606 12.4442C53.7606 12.2842 53.7047 12.277 52.4607 12.277C51.2168 12.277 51.1609 12.2842 51.1609 12.4442C51.1609 12.5394 51.2168 12.6113 51.2909 12.6113C51.5527 12.6113 51.8997 12.8633 51.9889 13.1184C52.117 13.4843 52.0191 13.8553 51.265 15.8617L50.6245 17.5662L50.4866 17.2405C50.4107 17.0615 50.0157 16.0047 49.6091 14.8923C48.8101 12.7069 48.7983 12.6113 49.3262 12.6113C49.5116 12.6113 49.5675 12.5726 49.5675 12.4442C49.5675 12.2845 49.5116 12.277 48.3175 12.277C47.1087 12.277 47.0689 12.2825 47.1112 12.4442ZM64.0946 12.5018C64.0946 12.5018 64.0945 12.6159 64.1086 12.6477C64.1226 12.6794 64.2128 12.6913 64.2128 12.6913C64.2688 12.7064 64.322 12.7195 64.3723 12.732C64.6258 12.7948 64.8038 12.8388 64.875 13.0052C64.923 13.1176 64.926 13.5085 64.9266 15.6037C64.9272 17.8131 64.9268 18.0839 64.8677 18.2299C64.7944 18.4109 64.6541 18.5071 64.3303 18.598C64.3303 18.598 64.1871 18.6378 64.1485 18.6734C64.11 18.709 64.1027 18.7886 64.1027 18.7886C64.1027 18.7886 64.0997 18.8625 64.1327 18.898C64.1657 18.9334 64.2538 18.9165 64.2538 18.9165L65.093 18.9187L66.485 18.93C66.485 18.93 66.5419 18.9375 66.5714 18.8999C66.6009 18.8622 66.5933 18.7884 66.5933 18.7884C66.5933 18.7884 66.5933 18.7095 66.5566 18.674C66.52 18.6384 66.3778 18.6051 66.3778 18.6051C66.0634 18.5278 65.9021 18.4269 65.8308 18.2632C65.7778 18.1415 65.7721 17.8131 65.7641 17.129V16.126C65.7993 16.1458 65.8314 16.1683 65.8653 16.1921C66.0258 16.3043 66.2267 16.4449 66.9772 16.4666C67.8865 16.493 68.4335 16.0884 68.7588 15.6184C69.0841 15.1485 69.2103 14.4102 68.9716 13.6238C68.733 12.8373 68.0326 12.3614 67.0481 12.3122C66.5349 12.2865 65.7883 12.3119 65.371 12.3308L65.2541 12.336C64.875 12.3526 64.4206 12.3888 64.1943 12.4104L64.1936 12.4104C64.132 12.4163 64.1259 12.4169 64.1086 12.4387C64.0914 12.4607 64.0946 12.5018 64.0946 12.5018ZM67.7897 15.5826C68.1554 15.2388 68.1615 14.7009 68.1615 14.3573C68.1256 13.8186 67.9085 12.7825 66.6788 12.7825C66.3913 12.7677 65.8031 12.8173 65.7868 13.2161C65.769 13.2866 65.761 13.7794 65.7656 14.5357L65.7729 15.7428L65.898 15.8087L65.9048 15.8123C65.9727 15.8482 66.0608 15.8947 66.2149 15.9249C66.7037 16.0206 67.4239 15.9265 67.7897 15.5826ZM60.0957 12.3824C60.1868 12.3479 60.2468 12.3249 60.2468 12.3249C60.2468 12.3249 60.3829 12.2689 60.4269 12.3249C60.4405 12.3421 60.4898 12.4695 60.6121 12.7852C60.6361 12.8472 60.6629 12.9163 60.6929 12.9934C60.8752 13.463 61.1371 14.1372 61.2749 14.4915C61.4127 14.8458 61.6853 15.547 61.8807 16.0496C62.076 16.5522 62.3268 17.1971 62.4378 17.4825C62.549 17.768 62.691 18.0648 62.7307 18.1189C62.7502 18.1455 62.7702 18.1786 62.792 18.2148C62.8778 18.357 62.9929 18.5477 63.2241 18.5851C63.2241 18.5851 63.4051 18.615 63.4319 18.6434C63.4587 18.6718 63.4648 18.7233 63.4648 18.7233V18.8202C63.4648 18.8202 63.4617 18.8449 63.4468 18.866C63.4319 18.887 63.3772 18.8811 63.3772 18.8811L61.9816 18.8812L60.9887 18.8884C60.9887 18.8884 60.954 18.8926 60.9336 18.8757C60.9131 18.8588 60.9025 18.816 60.9025 18.816V18.7431C60.9025 18.7431 60.894 18.6883 60.9336 18.6405C60.9733 18.5928 61.1327 18.5873 61.1327 18.5873C61.4333 18.5612 61.5526 18.3052 61.614 18.1734C61.6186 18.1635 61.6228 18.1544 61.6268 18.1461C61.6923 18.0098 61.6686 17.921 61.3729 17.1927C61.1778 16.7119 61.1113 16.5769 61.0639 16.5649C61.0306 16.5565 60.5112 16.5534 59.9096 16.558L58.8158 16.5663L58.7504 16.7461C58.5613 17.2662 58.3933 17.7828 58.368 17.9224C58.3164 18.2066 58.3883 18.5226 58.8063 18.5776C58.8063 18.5776 58.9612 18.5989 59.0026 18.6301C59.0439 18.6613 59.0584 18.7412 59.0584 18.7412V18.8148C59.0584 18.8148 59.0505 18.8499 59.022 18.8735C58.9936 18.8971 58.9198 18.8885 58.9198 18.8885H57.8759L56.8659 18.9C56.8659 18.9 56.8228 18.899 56.7909 18.8821C56.759 18.8652 56.754 18.8313 56.754 18.8313V18.7613C56.754 18.7613 56.7485 18.7159 56.8047 18.6603C56.861 18.6047 57.0128 18.5899 57.0128 18.5899C57.2889 18.5454 57.4452 18.2516 57.5352 18.0825C57.5419 18.07 57.5481 18.0582 57.5541 18.0472C57.5897 17.9814 57.7506 17.5971 57.9115 17.1934C58.0725 16.7896 58.2532 16.3379 58.313 16.1896C58.5164 15.6853 58.7097 15.2021 59.0024 14.4667C59.163 14.0629 59.4009 13.467 59.5309 13.1423L59.7674 12.552L60.0957 12.3824ZM60.0096 13.8173C60.0602 13.945 60.1378 14.1371 60.1818 14.2442C60.2259 14.3513 60.3494 14.6547 60.4561 14.9184C60.5628 15.182 60.6939 15.5029 60.7475 15.6314C60.801 15.76 60.8449 15.8712 60.8449 15.8786C60.8449 15.8861 60.4429 15.8922 59.9516 15.8922C59.3876 15.8922 59.0584 15.8814 59.0584 15.8628C59.0584 15.8467 59.0773 15.7826 59.1004 15.7205C59.1371 15.6217 59.3204 15.0971 59.7252 13.9322C59.7876 13.7523 59.8457 13.5936 59.854 13.5796C59.8825 13.5316 59.9175 13.5851 60.0096 13.8173Z' fill='%23FF006E'/%3e %3cpath d='M10.7128 12.6593C11.0026 13.1718 10.3544 13.3307 10.0501 13.36C9.5892 13.405 9.49377 13.1381 9.5838 12.8028C9.61338 12.6828 9.67894 12.5748 9.77165 12.4935C9.8644 12.4122 9.97976 12.3615 10.1021 12.3483C10.2227 12.3372 10.344 12.3605 10.452 12.4155C10.56 12.4705 10.6504 12.555 10.7128 12.6593Z' fill='%23FF006E'/%3e %3cpath d='M12.5223 11.7109C12.1854 14.2995 16.7271 13.7609 16.6406 15.8211C17.0886 15.236 17.2813 13.6465 15.9624 12.8284C14.7873 12.0989 13.2561 12.498 12.5223 11.7109Z' fill='%23FF006E'/%3e %3cpath d='M16.1937 12.6219L16.191 12.6179C16.15 12.5413 16.1033 12.4681 16.0512 12.3987C15.8981 12.1903 15.6785 12.041 15.429 11.9756C15.2629 11.9326 15.0931 11.9058 14.9219 11.8956C14.7485 11.8829 14.5715 11.8757 14.3928 11.8663C14.0344 11.8465 13.6675 11.8096 13.3091 11.707C13.2195 11.6813 13.1299 11.6534 13.0434 11.6197C12.9987 11.6035 12.957 11.5859 12.9127 11.567C12.8683 11.5481 12.8231 11.5265 12.7782 11.5036C12.6097 11.4109 12.4536 11.297 12.3137 11.1647C12.0377 10.9068 11.8209 10.6143 11.6036 10.3308C11.3988 10.0462 11.1789 9.77277 10.9451 9.51173C10.7143 9.256 10.4415 9.04198 10.1387 8.87899C9.82509 8.72031 9.48447 8.62259 9.13477 8.59096C9.49756 8.55139 9.86457 8.59636 10.2072 8.72237C10.553 8.85723 10.8691 9.0589 11.1377 9.31597C11.313 9.48115 11.4777 9.65747 11.6305 9.84385C12.7684 9.61884 13.6912 9.81865 14.4004 10.2066L14.4166 10.2147C14.6423 10.3377 14.8538 10.4853 15.0473 10.6548C15.0782 10.6818 15.1087 10.7088 15.1369 10.7363C15.2879 10.8757 15.4285 11.0261 15.5576 11.1863L15.5674 11.1993C15.9863 11.7322 16.1933 12.2862 16.1937 12.6219Z' fill='%23FF006E'/%3e %3cpath d='M9.19254 8.92444C9.48285 8.96674 9.77898 9.08285 9.9698 9.30427C10.1607 9.52568 10.231 9.8137 10.2861 10.0878C10.3309 10.3002 10.3663 10.5167 10.4496 10.7178C10.4899 10.8159 10.5491 10.9019 10.5983 10.9946C10.6391 11.0715 10.7135 11.1409 10.7421 11.2232C10.7473 11.235 10.7492 11.248 10.7477 11.2608C10.7462 11.2736 10.7414 11.2858 10.7336 11.2961C10.6324 11.4086 10.3591 11.2835 10.2561 11.2331C10.0779 11.1444 9.91842 11.0222 9.78615 10.8731C9.37265 10.4118 9.15895 9.748 9.17195 9.1436C9.17481 9.07023 9.18169 8.99706 9.19254 8.92444Z' fill='%23FF006E'/%3e %3cpath d='M14.0477 14.1259C13.4205 15.8841 16.2652 17.0637 15.1995 18.8512C16.293 18.3976 16.8122 17.0272 16.3584 15.9399C15.9615 14.9854 14.7878 14.6376 14.0477 14.1259Z' fill='%23FF006E'/%3e %3cpath d='M10.2852 16.4254C10.456 16.296 10.6429 16.1894 10.8411 16.1082C11.0416 16.0276 11.2496 15.9673 11.462 15.9282C11.8836 15.8476 12.3007 15.8278 12.651 15.686C12.8241 15.6181 12.9833 15.519 13.1209 15.3935C13.2541 15.2692 13.356 15.115 13.4184 14.9435C13.4822 14.7625 13.5082 14.5702 13.4945 14.3787C13.4787 14.173 13.4324 13.9708 13.357 13.7788C13.5132 13.942 13.6269 14.1413 13.6881 14.3591C13.7492 14.5769 13.756 14.8066 13.7078 15.0276C13.653 15.2617 13.5347 15.4759 13.366 15.6464C13.199 15.8117 12.9976 15.9377 12.7764 16.0155C12.5653 16.0898 12.3451 16.1353 12.1219 16.1505C11.9069 16.1685 11.699 16.1734 11.4947 16.1855C11.0817 16.203 10.6738 16.2838 10.2852 16.4254Z' fill='%23FF006E'/%3e %3cpath d='M14.2981 19.5159C14.2349 19.5663 14.1717 19.6198 14.1023 19.6666C14.0324 19.7129 13.9592 19.7538 13.8832 19.7891C13.7251 19.8666 13.5512 19.9061 13.3752 19.9047C12.8985 19.8957 12.5616 19.5393 12.3646 19.1365C12.2301 18.862 12.1374 18.5654 11.9779 18.3039C11.7499 17.93 11.3597 17.6289 10.9028 17.6847C10.7164 17.7081 10.5417 17.7922 10.4382 17.9547C10.1658 18.3791 10.5569 18.9736 11.0555 18.8894C11.0979 18.8829 11.1394 18.8715 11.1792 18.8552C11.2188 18.8383 11.2557 18.8157 11.2889 18.7882C11.3586 18.7299 11.4111 18.6537 11.4408 18.5677C11.4735 18.478 11.4808 18.3809 11.4618 18.2873C11.4414 18.1894 11.3839 18.1034 11.3015 18.0474C11.3973 18.0925 11.472 18.1732 11.5098 18.2725C11.549 18.3746 11.5591 18.4857 11.5389 18.5933C11.5193 18.7054 11.4701 18.8102 11.3965 18.8966C11.3573 18.9411 11.3121 18.9797 11.262 19.0114C11.2125 19.0427 11.1594 19.0679 11.1039 19.0865C10.9914 19.1252 10.8716 19.1376 10.7536 19.123C10.5879 19.0993 10.4316 19.0312 10.3011 18.9259C10.147 18.8035 10.0323 18.6433 9.89298 18.5056C9.73328 18.3372 9.54486 18.199 9.3366 18.0974C9.193 18.034 9.04271 17.9872 8.8886 17.9579C8.81109 17.9417 8.73272 17.93 8.6543 17.9201C8.61846 17.9165 8.44285 17.8773 8.41821 17.9002C8.66051 17.6762 8.92468 17.4772 9.20667 17.3062C9.49621 17.1336 9.80711 17 10.1313 16.9089C10.4675 16.8138 10.8191 16.7867 11.1657 16.8292C11.3442 16.8507 11.5189 16.8961 11.6854 16.9642C11.8598 17.0342 12.0208 17.1341 12.1611 17.2594C12.3001 17.3909 12.4124 17.5481 12.4918 17.7225C12.5635 17.8857 12.617 18.0564 12.6512 18.2315C12.7534 18.7549 12.7158 19.5663 13.3981 19.686C13.4336 19.6929 13.4695 19.698 13.5056 19.7013L13.6171 19.704C13.6938 19.6985 13.77 19.6875 13.8451 19.6711C14.0008 19.6344 14.1525 19.5823 14.2981 19.5159Z' fill='%23FF006E'/%3e %3cpath d='M9.7211 11.5589C9.69625 11.6548 9.65286 11.7448 9.59342 11.8239C9.48279 11.9682 9.33632 12.0807 9.16873 12.1502C9.01801 12.2154 8.85841 12.2576 8.69521 12.2753C8.6598 12.2798 8.62309 12.2825 8.5877 12.2852C8.48435 12.2891 8.38497 12.3262 8.30412 12.391C8.22326 12.4558 8.16518 12.5449 8.13837 12.6452C8.12609 12.6952 8.11696 12.7458 8.11104 12.7969C8.09491 12.9292 8.09223 13.0669 8.07789 13.2334C8.04279 13.5168 7.96119 13.7923 7.83642 14.0489C7.67425 14.3918 7.49237 14.6681 7.53448 15.0633C7.56225 15.3198 7.69307 15.4917 7.86689 15.669C8.18048 15.9912 8.88249 16.1352 8.7257 16.9291C8.63116 17.4029 7.84897 17.9003 6.7496 18.074C6.85891 18.0573 6.60938 17.6347 6.5937 17.6077C6.47588 17.4223 6.34686 17.2477 6.25323 17.0466C6.06956 16.6564 5.98444 16.205 6.0597 15.7774C6.13899 15.3274 6.47051 14.9827 6.74602 14.6389C7.07395 14.2298 7.418 13.6938 7.49416 13.1628C7.51208 13.0341 7.52462 12.8729 7.55329 12.7127C7.58063 12.5352 7.63598 12.3632 7.71726 12.2033C7.77274 12.0984 7.84578 12.0038 7.93319 11.9238C7.97876 11.8814 8.00883 11.8247 8.01858 11.763C8.02832 11.7014 8.01719 11.6382 7.98695 11.5836L6.23442 8.41718L8.75165 11.5377C8.78032 11.5739 8.81655 11.6032 8.85779 11.6237C8.89903 11.6442 8.94428 11.6554 8.99025 11.6564C9.03627 11.6574 9.08191 11.6482 9.12401 11.6295C9.16606 11.6107 9.20352 11.5829 9.23372 11.5481C9.2656 11.5107 9.28366 11.4634 9.2849 11.4142C9.2861 11.3651 9.27042 11.317 9.24041 11.2781C9.07603 11.067 8.90218 10.8519 8.73373 10.6403L8.10029 9.85278L6.8289 8.28037L5.09521 6.09509L6.99197 8.13952L8.34534 9.64262L9.02045 10.396C9.24443 10.6493 9.46845 10.8946 9.69243 11.161L9.72918 11.206L9.73726 11.2758C9.74815 11.3704 9.7427 11.4661 9.7211 11.5589Z' fill='%23FF006E'/%3e %3c/svg%3e", + "iconPng": "data:image/png;base64,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" + }, + "zeroEx": { + "color": "#000", + "title": "0x API", + "icon": "data:image/svg+xml,%3csvg width='75' height='31' viewBox='0 0 75 31' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3cpath d='M18.1075 11.6529C18.7415 10.8075 19.5823 10.3848 20.6299 10.3848C21.6774 10.3848 22.5136 10.8075 23.1385 11.6529C23.7725 12.4891 24.0896 13.7388 24.0896 15.402C24.0896 17.0653 23.7725 18.315 23.1385 19.1512C22.5136 19.9874 21.6774 20.4055 20.6299 20.4055C19.5823 20.4055 18.7415 19.9874 18.1075 19.1512C17.4826 18.315 17.1702 17.0653 17.1702 15.402C17.1702 13.7388 17.4826 12.4891 18.1075 11.6529ZM18.0661 15.402C18.0661 16.7436 18.2729 17.7728 18.6864 18.4896L21.9945 11.6391C21.6269 11.3358 21.172 11.1842 20.6299 11.1842C19.7937 11.1842 19.155 11.5472 18.7139 12.2731C18.282 12.9899 18.0661 14.0328 18.0661 15.402ZM20.6299 19.606C21.4661 19.606 22.1001 19.2477 22.532 18.5309C22.9731 17.8142 23.1936 16.7712 23.1936 15.402C23.1936 14.0604 22.9869 13.0358 22.5734 12.3283L19.2653 19.165C19.642 19.459 20.0969 19.606 20.6299 19.606ZM30.7317 20.2263L28.8847 17.1801H28.3885L26.4725 20.2263H25.5077L27.7406 16.6977L25.742 13.3345H26.6793L28.3885 16.2153H28.8847L30.6214 13.3345H31.5587L29.5325 16.6563L31.7517 20.2263H30.7317ZM41.5873 10.3848L45.1159 20.2263H44.1373L43.0208 17.0423H38.486L37.3695 20.2263H36.4184L39.9333 10.3848H41.5873ZM40.4846 11.3496L38.7754 16.2153H42.7314L41.0222 11.3496H40.4846ZM46.699 10.3848H50.7376C51.7759 10.3848 52.5754 10.6375 53.1359 11.1429C53.6965 11.6483 53.9767 12.3512 53.9767 13.2518C53.9767 14.1523 53.6965 14.8553 53.1359 15.3607C52.5754 15.8661 51.7759 16.1188 50.7376 16.1188H47.6088V20.2263H46.699V10.3848ZM47.6088 15.2918H50.5859C52.24 15.2918 53.067 14.6118 53.067 13.2518C53.067 11.8918 52.24 11.2118 50.5859 11.2118H47.6088V15.2918ZM56.1104 10.3848H57.0202V20.2263H56.1104V10.3848Z' fill='%23FDFDFD'/%3e %3c/svg%3e", + "iconPng": "data:image/png;base64,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" + } +} diff --git a/test/e2e/mock-response-data/token-blocklist.json b/test/e2e/mock-response-data/token-blocklist.json new file mode 100644 index 000000000000..e86383472d6f --- /dev/null +++ b/test/e2e/mock-response-data/token-blocklist.json @@ -0,0 +1,582 @@ +[ + "0x1a95b271b0535d15fa49932daba31ba612b52946", + "0xd4d1c6857d994f9af768b67a6a6e9c279dae1303", + "0x985dd3d42de1e256d09e1c10f112bccb8015ad41", + "0x7afebbb46fdb47ed17b22ed075cde2447694fb9e", + "0x07597255910a51509ca469568b048f2597e72504", + "0x84a854d5019edba68eaf8220856cb85a2c054586", + "0x995de3d961b40ec6cdee0009059d48768ccbdd48", + "0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0", + "0xae31b85bfe62747d0836b82608b4830361a3d37a", + "0x954b890704693af242613edef1b603825afcd708", + "0x9ea4c67c314db0ec8fa13eaba4dc7ed1b320fd35", + "0x03fb52d4ee633ab0d06c833e32efdd8d388f3e6a", + "0xea319e87cf06203dae107dd8e5672175e3ee976c", + "0x4f3afec4e5a3f2a6a1a411def7d7dfe50ee057bf", + "0x79ba92dda26fce15e1e9af47d5cfdfd2a093e000", + "0x1da01e84f3d4e6716f274c987ae4bee5dc3c8288", + "0xa866f0198208eb07c83081d5136be7f775c2399e", + "0xb48e0f69e6a3064f5498d495f77ad83e0874ab28", + "0xaa19673aa1b483a5c4f73b446b4f851629a7e7d6", + "0x892f5a0b08bb7b1eecccc63ef3916ff201c93664", + "0xd1afbccc9a2c2187ea544363b986ea0ab6ef08b5", + "0xe1f8cd01ab04b51d02c6fb2bca61b03fb5e33b99", + "0x1443e7c1cce72662545d94779120c59251447e91", + "0x62359ed7505efc61ff1d56fef82158ccaffa23d7", + "0x88ef27e69108b2633f8e1c184cc37940a075cc02", + "0x0e3c91ed7d966ff1f7b58ab739a55e3c4473cd27", + "0x0417912b3a7af768051765040a55bb0925d4ddcf", + "0x73f8406eaace2ce69ba49a67551464fda1d11f14", + "0x78571accaf24052795f98b11f093b488a2d9eaa4", + "0x2129ff6000b95a973236020bcd2b2006b0d8e019", + "0x73fa9181cd0752a18ddfa285033df0323a804457", + "0x1ad606adde97c0c28bd6ac85554176bc55783c01", + "0x6d6506e6f438ede269877a0a720026559110b7d5", + "0x610c67be018a5c5bdc70acd8dc19688a11421073", + "0x12b28e6fffa7ff813b15b597d894d5ef5b0b7428", + "0xa1afffe3f4d611d252010e3eaf6f4d77088b0cd7", + "0xac00797df10e825589d8b53e715393be4e617459", + "0xe5868468cb6dd5d6d7056bd93f084816c6ef075f", + "0x98cc695d0c6e40239ea9c2411b71a17b6a85d5ea", + "0xd04785c4d8195e4a54d9dec3a9043872875ae9e2", + "0xc32cc5b70bee4bd54aa62b9aefb91346d18821c4", + "0x320583dd12ea9ad31e751feab1efae7b7a95c6d7", + "0xe95e4440493e5b96e79d63e8dc43ab676dd44e4c", + "0xf0b47ee3d3bdbef94999b2b8f4b81a52fbe2e3ed", + "0xc14a00033080eca5bea2bcd3d0645fa7825142da", + "0xa7de087329bfcda5639247f96140f9dabe3deed1", + "0x69692d3345010a207b759a7d1af6fc7f38b35c5e", + "0xea3cb156745a8d281a5fc174186c976f2dd04c2e", + "0x12d102f06da35cc0111eb58017fd2cd28537d0e1", + "0x14d1c83df4decee9deb14ee851f109f0101a6631", + "0x53f64be99da00fec224eaf9f8ce2012149d2fc88", + "0xd0d3ebcad6a20ce69bc3bc0e1ec964075425e533", + "0x3863ea7577fc91bfbaeae6a6a3e403524afcf787", + "0x32c868f6318d6334b2250f323d914bc2239e4eee", + "0x7a3d5d49d64e57dbd6fbb21df7202bd3ee7a2253", + "0xe8b251822d003a2b2466ee0e38391c2db2048739", + "0x8d5db0c1f0681071cb38a382ae6704588d9da587", + "0x36c6b0e43e43717890197a1d49d05eb3e5bed329", + "0xbb0a009ba1eb20c5062c790432f080f6597662af", + "0x2e2364966267b5d7d2ce6cd9a9b5bd19d9c7c6a9", + "0x45804880de22913dafe09f4980848ece6ecbaf78", + "0xbae5f2d8a1299e5c4963eaff3312399253f27ccb", + "0x91383a15c391c142b80045d8b4730c1c37ac0378", + "0x4bae380b5d762d543d426331b8437926443ae9ec", + "0x88930072f583936f506ce1f1d5fe69290c2d6a2a", + "0xeeee2a622330e6d2036691e983dee87330588603", + "0x239119c43e3cac84c8a2d45bcba0e46f528e5f77", + "0x4ba6ddd7b89ed838fed25d208d4f644106e34279", + "0xbf494f02ee3fde1f20bee6242bce2d1ed0c15e47", + "0xb6ee603933e024d8d53dde3faa0bf98fe2a3d6f1", + "0xa0bb0027c28ade4ac628b7f81e7b93ec71b4e020", + "0xa5959e9412d27041194c3c3bcbe855face2864f7", + "0x9af15d7b8776fa296019979e70a5be53c714a7ec", + "0xde9d41a01bb11a9f41e709242824e54c3917084e", + "0xed36482c7f8e5850e91ac0cf6bf2130a1aa2df92", + "0x389999216860ab8e0175387a0c90e5c52522c945", + "0xc981ca09a4d42961b57f299d70bbdd7ee1caf14b", + "0xeb1c63cc494970981a6e3367e6b6c6f6f9879d7d", + "0x521fd6d4b9e0e98a8074302fc8d703971b7eb43a", + "0x9b370397604e165c681ae2c02d4619616fdc5403", + "0xf6de69ce2803b5adb762986ed3dcf39e5dbfddb2", + "0x426ca1ea2406c07d75db9585f22781c096e3d0e0", + "0x967da4048cd07ab37855c090aaf366e4ce1b9f48", + "0xdfac0158449296b7c6b2537a6c2fbbe7c5cef328", + "0x10bae51262490b4f4af41e12ed52a0e744c1137a", + "0xbbc455cb4f1b9e4bfc4b73970d360c8f032efee6", + "0x658bbe318260ab879af701043b18f7e8c4daf448", + "0xe95a203b1a91a908f9b9ce46459d101078c2c3cb", + "0x3a3a65aab0dd2a17e3f1947ba16138cd37d08c04", + "0x78b039921e84e726eb72e7b1212bb35504c645ca", + "0x5e74c9036fb86bd7ecdcb084a0673efc32ea31cb", + "0x6d45640f5d0b75280647f2f37ccd19c1167f833c", + "0x0d7dea5922535087078dd3d7c554ea9f2655d4cb", + "0x32d5730fb85763281d459b9022cb247d8e10e0ef", + "0xd82bb924a1707950903e2c0a619824024e254cd1", + "0x23b4db3a435517fd5f2661a9c5a16f78311201c1", + "0xf013406a0b1d544238083df0b93ad0d2cbe0f65f", + "0x76a034e76aa835363056dd418611e4f81870f16e", + "0x14be9bde94102e13971e8f98acecac823cb7fd30", + "0x704135ecbb0bea17fd3daad8e3583ccc6f6f7f0e", + "0x33c2da7fd5b125e629b3950f3c38d7f721d7b30d", + "0xd7b3669c7d3e38ab5a441383d41f25e003e02148", + "0x90c88ccd74e57e016acae8ad1eaa12ecf4c06f33", + "0xd6014ea05bde904448b743833ddf07c3c7837481", + "0x5963fd7ca9b17b85768476019f81cb43d9d1818e", + "0x40ce0a1d8f4999807b92ec266a025f071814b15d", + "0xe95ebf4f50d0084c1ea62fcfa8a2bdd707254d3f", + "0x8fd68af8c21d99c442a5d9d2a0dde6b441ea51ee", + "0x6c1af18a949c293ad4bfc0dc455b463498463705", + "0x846d152216146c77c81af3a1657790ed8ba69281", + "0x063f94a725d4bfa66746d665782a1b137195860d", + "0xe307bcaa460d83baa6452784461593d7a537a047", + "0xcfc56009ab5217f70b86220c315f9c0532f18cdf", + "0xf9e9e69a9a13450c098c6591e57372c7876e6cbc", + "0x0a472678b927640ee14cb5ec618fd29f1014fed1", + "0x5506861bbb104baa8d8575e88e22084627b192d8", + "0xf4fb54c667fe525cf4811df291b2a2892261c3d7", + "0x105bf3675d3b380687ecf80d8f7f451707de6739", + "0x819ab68104dcf01189bb87a2a9129a19556c77d0", + "0x8db6fcc2bae3e63bdd9db520a46bb39a379847c6", + "0x912b38134f395d1bfab4c6f9db632c31667acf98", + "0xdf5e0e81dff6faf3a7e52ba697820c5e32d806a8", + "0x096d4552fe0066dca557d932426071835928284b", + "0x2512bbe0b3ba612b3d861e1fc682b17fa0b54d74", + "0xa54c67bd320da4f9725a6f585b7635a0c09b122e", + "0xdc58b6eb1c945568e34b7cf2b806636715f1762d", + "0x694cc203ae4e8223c220a0f8d72c26bf2c437c69", + "0xa7ed29b253d8b4e3109ce07c80fc570f81b63696", + "0x0391d2021f89dc339f60fff84546ea23e337750f", + "0x3d4a076a01b303259046b548c8d759a1c77c32fa", + "0x5c9adb28f0c7b35157a0c6ab5c55729f301c9b70", + "0x9cd9a927013075b0d39b1fb5f307560af471cc70", + "0x692eb773e0b5b7a79efac5a015c8b36a2577f65c", + "0x584bc13c7d411c00c01a62e8019472de68768430", + "0x776ca7ded9474829ea20ad4a5ab7a6ffdb64c796", + "0x559cce70236df3876f63731211ede1de35323a0f", + "0xebd888168161d67b2e35051c063de0212d05436a", + "0x80fb784b7ed66730e8b1dbd9820afd29931aab03", + "0xe7bc894cbeefb1d60f0401903a8377cbf52803c4", + "0x72630b1e3b42874bf335020ba0249e3e9e47bafc", + "0xf979d80a1aa41530424b9862db13900fd49e86fb", + "0x1c95b093d6c236d3ef7c796fe33f9cc6b8606714", + "0xc84f7abe4904ee4f20a8c5dfa3cc4bf1829330ab", + "0xe0e4839e0c7b2773c58764f9ec3b9622d01a0428", + "0xbbb38be7c6d954320c0297c06ab3265a950cdf89", + "0x910524678c0b1b23ffb9285a81f99c29c11cbaed", + "0x8da25b8ed753a5910013167945a676921e864436", + "0x02e578a87851670839d351d9372b10e2a580aec3", + "0x5e989c649e9cbabc7abca847d8909d73fac20399", + "0x13be79c25290c639794d75b9890d17acff7c0d95", + "0x976f972191ef68506368d2d52c7bc8d0ced1619f", + "0x6e10aacb89a28d6fa0fe68790777fec7e7f01890", + "0xbbff862d906e348e9946bfb2132ecb157da3d4b4", + "0xbe3547a464d03b226cf4be2c48629694450e3773", + "0xc12d1c73ee7dc3615ba4e37e4abfdbddfa38907e", + "0x4c81d9341c527b695298e4f08df9750b5ee055d8", + "0x595643d83b35df38e29058976c04000acfa31570", + "0x27f938d01231832cb11a56300aaa724d9f3bc961", + "0x969c736577b7cfaad322abbbd6db9bd057f6afca", + "0x0000a5050a8036d29afa9bf36546efe225ed51e9", + "0xc634108996f8a3876cc34f83f6453ae19e4ecfb3", + "0xc6a74a98f6202b47752c35a992a73d4c2284ee43", + "0x97880c1dd3b7f12f9117d234fa1cebe48fcdbd04", + "0x6e90f510d389688132f50acfb812a6a1f4d3317b", + "0x7d85e23014f84e6e21d5663acd8751bef3562352", + "0x85e076361cc813a908ff672f9bad1541474402b2", + "0x0b94cd8499a950cfd31c04247c293f2f95093f9b", + "0x2b42dc7ad5dd7d28a8b8ecd2d2a3e365ad12478b", + "0x123ab195dd38b1b40510d467a6a359b201af056f", + "0xbeb9ef514a379b997e0798fdcc901ee474b6d9a1", + "0xc75f15ada581219c95485c578e124df3985e4ce0", + "0x5d8d9f5b96f4438195be9b99eee6118ed4304286", + "0x48be867b240d2ffaff69e0746130f2c027d8d3d2", + "0x9f86f40999522ca55df01b2f3bce93615846c47a", + "0xd29fabc16cb57511844ae9cbda3cddf601e1489b", + "0xbe434a1b376ee521dd4c318d5ae5726efd4a69a1", + "0x4b3a0c6d668b43f3f07904e124328659b90bb4ca", + "0x1b22c32cd936cb97c28c5690a0695a82abf688e6", + "0x9d9200af83ad0cc3c95ce553a135602ac1aa5919", + "0xe0b7927c4af23765cb51314a0e0521a9645f0e2a", + "0xb5a5f22694352c15b00323844ad545abb2b11028", + "0x45128cb743951121fb70cb570c0784492732778a", + "0x960b236a07cf122663c4303350609a66a7b288c0", + "0x4fe83213d56308330ec302a8bd641f1d0113a4cc", + "0xb8c77482e45f1f44de1745f52c74426c631bdd52", + "0xb5a73f5fc8bbdbce59bfd01ca8d35062e0dad801", + "0x419d0d8bdd9af5e606ae2232ed285aff190e711b", + "0x884a5b1438588239bc4ec652538b12d620f8f083", + "0xf4727665f750c2764f16180efdbe85b106d1f0ad", + "0x5f3d5f3cd36592abb51dbfbfdb3e7716eb30610d", + "0x39bb259f66e1c59d5abef88375979b4d20d98022", + "0xebbdf302c940c6bfd49c6b165f457fdb324649bc", + "0x915044526758533dfb918eceb6e44bc21632060d", + "0xa4e8c3ec456107ea67d3075bf9e3df3a75823db0", + "0x80a7e048f37a50500351c204cb407766fa3bae7f", + "0x41ab1b6fcbb2fa9dced81acbdec13ea6315f2bf2", + "0x56a980328aee33aabb540a02e002c8323326bf36", + "0x882d911c2fdce3cfa37c6ebbae7d8d3beeb6d17f", + "0x8bef82e549c29affcefdb73214ea436fcb98e9fa", + "0x27dce1ec4d3f72c3e457cc50354f1f975ddef488", + "0x4c218ac55d53e9de63214f7dde5b4db2a5d48ed3", + "0xbb8a43af111b59c7742f36e9cd245357d04059fd", + "0x0cd7ca934c174f43b2c69683ed302db0f5cf199e", + "0xf76da36fe74bb8b36d56cb96f4866ada345b65fa", + "0x8a1e3930fde1f151471c368fdbb39f3f63a65b55", + "0x6b963f7b38980f5fbbd129fe98059eb2144076a7", + "0xdf347911910b6c9a4286ba8e2ee5ea4a39eb2134", + "0xe83e098eedb43b33d340d4757529e5a2c4ee3230", + "0xf0f8b0b8dbb1124261fc8d778e2287e3fd2cf4f5", + "0x0a9c5b451dd8a467e80671380a875085fe053e30", + "0x1234567461d3f8db7496581774bd869c83d51c93", + "0x96a65609a7b84e8842732deb08f56c3e21ac6f8a", + "0xfdff4c1ad7712cc11725ac4aa1eed5fb687595f4", + "0x4672bad527107471cb5067a887f4656d585a8a31", + "0xf0ee6b27b759c9893ce4f094b49ad28fd15a23e4", + "0x92a5b04d0ed5d94d7a193d1d334d3d16996f4e13", + "0x17fd666fa0784885fa1afec8ac624d9b7e72b752", + "0x9dc1ce41ca15d5f500f50ea7da15da21e4f80a1a", + "0x71d01db8d6a2fbea7f8d434599c237980c234e4c", + "0x014b50466590340d41307cc54dcee990c8d58aa8", + "0x9c23d67aea7b95d80942e3836bcdf7e708a747c2", + "0x8844d0ccf85bc11d4d9b9c98c60a26762d43f216", + "0xfd0df7b58bd53d1dd4835ecd69a703b4b26f7816", + "0x8ef7c0cf8fe68076446803bb9035bd2a3a5e1581", + "0xb3203db25a01fa7950a860b42b899ad7da52ddd6", + "0x7728dfef5abd468669eb7f9b48a7f70a501ed29d", + "0x1844b21593262668b7248d0f57a220caaba46ab9", + "0xfc3f409be8d8325d419cb80d68b0f571c6da8f67", + "0xc029ba3dc12e1834571e821d94a07de0a01138ea", + "0x160383dfbe5b0c17068991daf8d4570711c354d1", + "0x4156d3342d5c385a87d264f90653733592000581", + "0xe25b0bba01dc5630312b6a21927e578061a13f55", + "0x6175f6f85339f1e56affac5a68cbf8297969004d", + "0xd5f788ca0de8f17cbde1d1e35aa8f005a87fa00b", + "0xa2b0fde6d710e201d0d608e924a484d1a5fed57c", + "0xee8bd1502c3e9f6c543781467c01592ac51cfbb8", + "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", + "0x08f5a9235b08173b7569f83645d2c7fb55e8ccd8", + "0x24692791bc444c5cd0b81e3cbcaba4b04acd1f3b", + "0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374", + "0x24dcc881e7dd730546834452f21872d5cb4b5293", + "0x26ce25148832c04f3d7f26f32478a9fe55197166", + "0xb5a4ac5b04e777230ba3381195eff6a60c3934f2", + "0x2baecdf43734f22fd5c152db08e3c27233f0c7d2", + "0x71fc860f7d3a592a4a98740e39db31d25db65ae8", + "0xcdcfc0f66c522fd086a1b725ea3c0eeb9f9e8814", + "0xed30dd7e50edf3581ad970efc5d9379ce2614adb", + "0xdd974d5c2e2928dea5f71b9825b8b646686bd200", + "0xfb62ae373aca027177d1c18ee0862817f9080d08", + "0xad4f86a25bbc20ffb751f2fac312a0b4d8f88c64", + "0x91dfbee3965baaee32784c2d546b7a0c62f268c9", + "0xf5d669627376ebd411e34b98f19c868c8aba5ada", + "0x82dfdb2ec1aa6003ed4acba663403d7c2127ff67", + "0x62a6738d887f47e297676fab05b902709b106c64", + "0x43f11c02439e2736800433b4594994bd43cd066d", + "0x7ff4169a6b5122b664c51c95727d87750ec07c84", + "0xc1bfccd4c29813ede019d00d2179eea838a67703", + "0x777e2ae845272a2f540ebf6a3d03734a5a8f618e", + "0x8b3192f5eebd8579568a2ed41e6feb402f93f73f", + "0x4688a8b1f292fdab17e9a90c8bc379dc1dbd8713", + "0x2aeccb42482cc64e087b6d2e5da39f5a7a7001f8", + "0x1412eca9dc7daef60451e3155bb8dbf9da349933", + "0x2de72ada48bdf7bac276256d3f016fe058490c34", + "0x4922a015c4407f87432b179bb209e125432e4a2a", + "0x93b2fff814fcaeffb01406e80b4ecd89ca6a021b", + "0xfa5e27893aee4805283d86e4283da64f8c72dd56", + "0xc6b11850241c5127eab73af4b6c68bc267cbbff4", + "0x452b421be5b30f0c6ad8c3f03c06bdaab4f5c56c", + "0x0578779e746d7186253a36cf651ea786acfcf087", + "0xf9aba2e43fb19184408ea3b572a0fd672946f87b", + "0xdb0991dfc7e828b5a2837dc82d68e16490562c8d", + "0xe951ebe6b4420ab3f4844cf36dedd263d095b416", + "0x9215bd49b59748419eac6bad9dbe247df06ebdb9", + "0xe3a2c34fa2f59ffa95c4acd1e5663633d45bc3ad", + "0x05977ebc26825c0cd6097e0ad7204721516711eb", + "0x31f88266301b08631f9f0e33fd5c43c2a5d1e5b2", + "0xd1cec2f67fdc4c60e0963515dfc3343f31e32e47", + "0x15844029b2c2bf24506e9937739a9a912f1e4354", + "0x5562c33c383f6386be4f6dcdbd35a3a99bbcfde6", + "0x3cbfc1397def0602c2d211c70a1c0c38cedb5448", + "0x98cc3bd6af1880fcfda17ac477b2f612980e5e33", + "0x8ed9f862363ffdfd3a07546e618214b6d59f03d4", + "0x176c674ee533c6139b0dc8b458d72a93dcb3e705", + "0x8a8079c7149b8a1611e5c5d978dca3be16545f83", + "0xafd870f32ce54efdbf677466b612bf8ad164454b", + "0x336213e1ddfc69f4701fc3f86f4ef4a160c1159d", + "0x6345728b1cce16e6f8c509950b5c84fff88530d9", + "0xcb98f42221b2c251a4e74a1609722ee09f0cc08e", + "0x14d10003807ac60d07bb0ba82caeac8d2087c157", + "0x46a97629c9c1f58de6ec18c7f536e7e6d6a6ecde", + "0xf4eebdd0704021ef2a6bbe993fdf93030cd784b4", + "0xd50c1746d835d2770dda3703b69187bffeb14126", + "0xa9859874e1743a32409f75bb11549892138bba1e", + "0x2d7ac061fc3db53c39fe1607fb8cec1b2c162b01", + "0x79da1431150c9b82d2e5dfc1c68b33216846851e", + "0xa5a5df41883cdc00c4ccc6e8097130535399d9a3", + "0x0fed38108bdb8e62ef7b5680e8e0726e2f29e0de", + "0xc5807183a9661a533cb08cbc297594a0b864dc12", + "0x36a00ff9072570ef4b9292117850b8fe08d96cce", + "0x4adf728e2df4945082cdd6053869f51278fae196", + "0x27269b3e45a4d3e79a3d6bfee0c8fb13d0d711a6", + "0x8deef89058090ac5655a99eeb451a4f9183d1678", + "0x592244301cea952d6dab2fdc1fe6bd9e53917306", + "0xcd39b5434a0a92cf47d1f567a7df84be356814f0", + "0x7537aae01f3b218dae75e10d952473823f961b87", + "0xd2df355c19471c8bd7d8a3aa27ff4e26a21b4076", + "0xe36e2d3c7c34281fa3bc737950a68571736880a1", + "0x9cf7e61853ea30a41b02169391b393b901eac457", + "0xf48e200eaf9906362bb1442fca31e0835773b8b4", + "0x617aecb6137b5108d1e7d4918e3725c8cebdb848", + "0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6", + "0xeabacd844a196d7faf3ce596edebf9900341b420", + "0x0f83287ff768d1c1e17a42f44d644d7f22e8ee1d", + "0x9eef4ca7ab9fa8bc0650127341c2d3f707a40f8a", + "0xeb029507d3e043dd6c87f2917c4e82b902c35618", + "0xd38aeb759891882e78e957c80656572503d8c1b1", + "0xfe33ae95a9f0da8a845af33516edc240dcd711d6", + "0xe1afe1fd76fd88f78cbf599ea1846231b8ba3b6b", + "0x1715ac0743102bf5cd58efbb6cf2dc2685d967b6", + "0x88c8cf3a212c0369698d13fe98fcb76620389841", + "0x22602469d704bffb0936c7a7cfcd18f7aa269375", + "0xd71ecff9342a5ced620049e616c5035f1db98620", + "0xf50b5e535f62a56a9bd2d8e2434204e726c027fa", + "0x23348160d7f5aca21195df2b70f28fce2b0be9fc", + "0x97fe22e7341a0cd8db6f6c021a24dc8f4dad855f", + "0xc63b8ecce56ab9c46184ec6ab85e4771fea4c8ad", + "0xf6b1c627e95bfc3c1b4c9b825a032ff0fbf3e07d", + "0x269895a3df4d73b077fc823dd6da1b95f72aaf9b", + "0xc14103c2141e842e228fbac594579e798616ce7a", + "0x745a824d6abbd236aa794b5530062778a6ad7523", + "0x5a7e3c07604eb515c16b36cd51906a65f021f609", + "0x757de3ac6b830a931ef178c6634c5c551773155c", + "0x6d16cf3ec5f763d4d99cb0b0b110eefd93b11b56", + "0xd31533e8d0f3df62060e94b3f1318137bb6e3525", + "0x0352557b007a4aae1511c114409b932f06f9e2f4", + "0xf2e08356588ec5cd9e437552da87c0076b4970b0", + "0x918da91ccbc32b7a6a0cc4ecd5987bbab6e31e6d", + "0x30635297e450b930f8693297eba160d9e6c8ebcf", + "0x6a22e5e94388464181578aa7a6b869e00fe27846", + "0x261efcdd24cea98652b9700800a13dfbca4103ff", + "0x5299d6f7472dcc137d7f3c4bcfbbb514babf341a", + "0x2e59005c5c0f0a4d77cca82653d48b46322ee5cd", + "0x992058b7db08f9734d84485bfbc243c4ee6954a7", + "0x81ab848898b5ffd3354dbbefb333d5d183eedcb5", + "0xb2fdd60ad80ca7ba89b9bab3b5336c2601c020b4", + "0x208d174775dc39fe18b1b374972f77ddec6c0f73", + "0xf06ddacf71e2992e2122a1a0168c6967afdf63ce", + "0xd16c79c8a39d44b2f3eb45d2019cd6a42b03e2a9", + "0x3d995510f8d82c2ea341845932b5ddde0bead9a3", + "0x90f802c7e8fb5d40b0de583e34c065a3bd2020d8", + "0x002f0b1a71c5730cf2f4da1970a889207bdb6d0d", + "0x1062ad0e59fa67fa0b27369113098cc941dd0d5f", + "0xf93340b1a3adf7eedcaec25fae8171d4b736e89f", + "0x84bd083b1c8bf929f39c98bc17cf518f40154f58", + "0x81fab276aec924fbde190cf379783526d413cf70", + "0x4e110603e70b0b5f1c403ee543b37e1f1244cf28", + "0xcf55a7f92d5e0c6683debbc1fc20c0a6e056df13", + "0x654eebac62240e6c56bab5f6adf7cfa74a894510", + "0xa48920cc1ad85d8ea13af5d7be180c0338c306dd", + "0x249a198d59b57fda5dda90630febc86fd8c7594c", + "0x5ed1406873c9eb91f6f9a67ac4e152387c1132e7", + "0x8104c9f13118320eefe5fbea8a44d600b85981ef", + "0x69746c719e59674b147df25f50e7cfa0673cb625", + "0x6b1257641d18791141f025eab36fb567c4b564ff", + "0x4e83b6287588a96321b2661c5e041845ff7814af", + "0x59fec83ec709c893aedd1a144cf1828eb04127cd", + "0x89337bfb7938804c3776c9fb921eccaf5ab76758", + "0xec58d3aefc9aaa2e0036fa65f70d569f49d9d1ed", + "0xa6b9d7e3d76cf23549293fb22c488e0ea591a44e", + "0xe813b65da6c38a04591aed3f082d32db7d53c382", + "0x4b606e9eb2228c70f44453afe5a73e1fea258ce1", + "0x5247c0db4044fb6f97f32c7e1b48758019a5a912", + "0x56fb1acaff95c0b6ebcd17c8361a63d98b1a5a11", + "0xd49fa405dce086c65d66ca1ca41f8e98583812b4", + "0x29dddacba3b231ee8d673dd0f0fa759ea145561b", + "0xcbe430927370e95b4b10cfc702c6017ec7abefc3", + "0x4b7fb448df91c8ed973494f8c8c4f12daf3a8521", + "0x3108c33b6fb38efedaefd8b5f7ca01d5f5c7372d", + "0x0cae9e4d663793c2a2a0b211c1cf4bbca2b9caa7", + "0x31c63146a635eb7465e5853020b39713ac356991", + "0x59a921db27dd6d4d974745b7ffc5c33932653442", + "0xf72fcd9dcf0190923fadd44811e240ef4533fc86", + "0x56aa298a19c93c6801fdde870fa63ef75cc0af72", + "0x0e99cc0535bb6251f6679fa6e65d6d3b430e840b", + "0x13b02c8de71680e71f0820c996e4be43c2f57d15", + "0x41bbedd7286daab5910a1f15d12cbda839852bd7", + "0x9d1555d8cb3c846bb4f7d5b1b1080872c3166676", + "0x21ca39943e91d704678f5d00b6616650f066fd63", + "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359", + "0xc76fb75950536d98fa62ea968e1d6b45ffea2a55", + "0x3c9d6c1c73b31c837832c72e04d3152f051fc1a9", + "0xed91879919b71bb6905f23af0a68d231ecf87b14", + "0xf0fac7104aac544e4a7ce1a55adf2b5a25c65bd1", + "0xd341d1680eeee3255b8c4c75bcce7eb57f144dae", + "0xa89ac6e529acf391cfbbd377f3ac9d93eae9664e", + "0x28cb7e841ee97947a86b06fa4090c8451f64c0be", + "0xf29e46887ffae92f1ff87dfe39713875da541373", + "0x39eae99e685906ff1c11a962a743440d0a1a6e09", + "0x7b123f53421b1bf8533339bfbdc7c98aa94163db", + "0xd2dda223b2617cb616c1580db421e4cfae6a8a85", + "0x4b4701f3f827e1331fb22ff8e2beac24b17eb055", + "0x34612903db071e888a4dadcaa416d3ee263a87b9", + "0x1f3f9d3068568f8040775be2e8c03c103c61f3af", + "0x8eef5a82e6aa222a60f009ac18c24ee12dbf4b41", + "0x4639cd8cd52ec1cf2e496a606ce28d8afb1c792f", + "0x0f51bb10119727a7e5ea3538074fb341f56b09ad", + "0x5ca9a71b1d01849c0a95490cc00559717fcf0d1d", + "0x0bf6261297198d91d4fa460242c69232146a5703", + "0x7ef1081ecc8b5b5b130656a41d4ce4f89dbbcc8c", + "0xe54f9e6ab80ebc28515af8b8233c1aee6506a15e", + "0x2f3e054d233c93c59140c0905227c7c607c70cbb", + "0x98e0438d3ee1404fea48e38e92853bb08cfa68bd", + "0xba745513acebcbb977497c569d4f7d340f2a936b", + "0xea004e8fa3701b8e58e41b78d50996e0f7176cbd", + "0x2dbd330bc9b7f3a822a9173ab52172bdddcace2a", + "0xbf4a9a37ecfc21825011285222c36ab35de51f14", + "0xb97d5cf2864fb0d08b34a484ff48d5492b2324a0", + "0xd8c82fbc4d8ed0644a7ec04cf973e84c6153c1d7", + "0x6f3009663470475f0749a6b76195375f95495fcb", + "0xe6410569602124506658ff992f258616ea2d4a3d", + "0x4b4f5286e0f93e965292b922b9cd1677512f1222", + "0x0501e7a02c285b9b520fdbf1badc74ae931ad75d", + "0x90d702f071d2af33032943137ad0ab4280705817", + "0xb944b46bbd4ccca90c962ef225e2804e46691ccf", + "0xc89b4a8a121dd3e726fe7515e703936cf83e3350", + "0x3c4030839708a20fd2fb379cf11810dde4888d93", + "0xd4ca5c2aff1eefb0bea9e9eab16f88db2990c183", + "0xc8ce75f643ecad864fc625902a6a07371f38320d", + "0xee9801669c6138e84bd50deb500827b776777d28", + "0x05462671c05adc39a6521fa60d5e9443e9e9d2b9", + "0x738865301a9b7dd80dc3666dd48cf034ec42bdda", + "0x4ff5253e2304e3f5ed6547ac5d9952a62b91e3e8", + "0xbd0793332e9fb844a52a205a233ef27a5b34b927", + "0x41933422dc4a1cb8c822e06f12f7b52fa5e7e094", + "0x122f96d596384885b54bccdddf2125018c421d83", + "0xd123575d94a7ad9bff3ad037ae9d4d52f41a7518", + "0x3fa729b4548becbad4eab6ef18413470e6d5324c", + "0x40897c872214303b6f479a37e549ee1516b264a2", + "0xcc665390b03c5d324d8faf81c15ecee29a73bcb4", + "0x171d750d42d661b62c277a6b486adb82348c3eca", + "0x17e347aad89b30b96557bcbfbff8a14e75cc88a1", + "0x375a08ce3a460f20bbafd282be1e3579a2c31f41", + "0x7a8ca2f815a260660158a38c34ca321a3605ecfe", + "0x8c9e4cf756b9d01d791b95bc2d0913ef2bf03784", + "0x78a52e12c7b63d05c12f9608307587cf654ec3d0", + "0x6944d3e38973c4831da24e954fbd790c7e688bdd", + "0x87f5e8c3425218837f3cb67db941af0c01323e56", + "0x5a7092cf86a6790113c4d3fa83f48fd6efa71b0d", + "0xc87e2b27f7477668cc7b97e929953802590049f7", + "0x5c743a35e903f6c584514ec617acee0611cf44f3", + "0x5c3a228510d246b78a3765c20221cbf3082b44a4", + "0x48c276e8d03813224bb1e55f953adb6d02fd3e02", + "0xab6e163cbeb3959b68b90bec722f5a9eef82ba72", + "0x714599f7604144a3fe1737c440a70fc0fd6503ea", + "0x8848812bd31aeee33313c10a840ffc3169078c5b", + "0x545290b71402e8ca677edf6296f1448edf95abe7", + "0xe0f2544d3483e454755d245f92d5bdef474ce16d", + "0xb264455716277d6d1445a4b875efab6de8931f4a", + "0x1644fa222aa3fddf9ee5c8a3876d59d2f1cab8ba", + "0x963fc20c82650d28402f703a84cde25a5b2c4a5f", + "0xd59623cfe3dbe4f63e02e6add0f25d3b532b21ce", + "0x42237ac5aed08d64feae4817fa1f0282087447f7", + "0x08f9862424e2a8f7d7bdcd2c8c33c12d6cfbd43e", + "0x7c947c432a8b47fed452dbe026cc6648ad6a2cc6", + "0x4115454c188acfb9cb67c6d795214055381b53b5", + "0x58f43dc7968012f4db78ec97a36c9998658ffccc", + "0xbdb5f6d15ce744dd4f86c26e134077debfb69d6b", + "0x0c048e6bee9570427b0617806eb6244cdcd30295", + "0xbbd7c868b6b9f53068e0abb5b05868d6dfbdf82e", + "0xb7fc05dc3bf10628b008e36c079d2a85621dab7a", + "0xcdca7042bc49ea2aa25c021bc970566b48ad594e", + "0x54655b64235ee8ff4509a95e80b2359dc94991b4", + "0x19e8e359c65e794578df4284c10cb943ab6b087c", + "0x7bde93c2480750654ad2291af7424b794cfa31c2", + "0x2d706c835281d330e7fd40187286f67bce06ff72", + "0x9a58e231de6a0349cf7262400819c21a2267d09c", + "0x353d991a87f935af6b8e6fef4e73372322d1fb9f", + "0x559cc0850361afe1973c0ba5d0a3446c8a5ad678", + "0xf71a2d1303d2798d2c134597bce1f95928b62fca", + "0xcecdd3fac0cbd4733d0fa2ca161885174d5dcbde", + "0x5870700f1272a1adbb87c3140bd770880a95e55d", + "0xc3cc3076cb304494775b3193ef1aa080ba6bf962", + "0xb62e45c3df611dce236a6ddc7a493d79f9dfadef", + "0xe2f12bf6fdb06d717c5d4ee6afe29c401250e663", + "0x3b010020bb3d901e0d2e1986213ea8057a728ebf", + "0xd32c6bace4f8313c9672ace2799c78d732d5c13b", + "0xce87a9d2f96b4e41ade825ba56dc24699c8cf26d", + "0xb697adf526a4899c48390087946d790572837819", + "0x37da9de38c4094e090c014325f6ef4baeb302626", + "0x3f73108cfd890b3495dde34f7c236352cf2d9969", + "0x3ef9181c9b96baaafb3717a553e808ccc72be37d", + "0xb0ad00f5fd367bb384c22b11f539aa4d3009767e", + "0x83306cfd5fc8cb4a9e1ea265dce59f9e016f49c1", + "0x18084fba666a33d37592fa2633fd49a74dd93a88", + "0x9b73a367d09cd83e94e81e615af10e9ed7930858", + "0x46b91d7e028ebdb17d3fbc245f5eba3da9003aec", + "0x077493a615f2e903c30b4da919c738de1fb815e5", + "0x593a3e0037c18237e153f9d00797926866ee923d", + "0x167b3658750dcb1d56690cf94d09410d5d980bda", + "0x8965349fb649a33a30cbfda057d8ec2c48abe2a2", + "0x35e049f9ef07b452570c227afa6640cf42a75d96", + "0x2df54842cd85c60f21b4871e09bcc6047b2dcc4d", + "0x3a880652f47bfaa771908c07dd8673a787daed3a", + "0xd291e7a03283640fdc51b121ac401383a46cc623", + "0x3af33bef05c2dcb3c7288b77fe1c8d2aeba4d789", + "0x418d75f65a02b3d53b2418fb8e1fe493759c7605", + "0x097242a5cad85f62b12830754f1062587e13c18a", + "0x7452e3fc2fe611c6b7761c6c393bece059881ac7", + "0x037a54aab062628c9bbae1fdb1583c195585fe41", + "0x55296f69f40ea6d20e478533c15a6b08b654e758", + "0xff20817765cb7f73d4bde2e66e067e58d11095c2", + "0xe7804d91dfcde7f776c90043e03eaa6df87e6395", + "0x7e43d25ead96b1058f671f6690ea705ba2c7e5b9", + "0xcf39b7793512f03f2893c16459fd72e65d2ed00c", + "0x595832f8fc6bf59c85c527fec3740a1b7a361269", + "0xf1f955016ecbcd7321c7266bccfb96c68ea5e49b", + "0xf5832512cfda8083e5b2dd0aa7c1b9265c03ba1f", + "0xa3d58c4e56fedcae3a7c43a725aee9a71f0ece4e", + "0x533ba8a236c6b7dd2cf8e49fe8cefa30cef0c4bd", + "0x2f9a8b57b29e12a226590ff36c4b9729d4f779bf", + "0x6b60ee11b73230045cf9095e6e43ae9ea638e172", + "0x7277a44d1325d81ac58893002a1b40a41bea43fe", + "0x76175599887730786bda1545d0d7ace8737febb1", + "0xa82aa729ae2f0d78e961d66db53949e27a9e866d", + "0x322a46e88fa3c78f9c9e3dbb0254b61664a06109", + "0x8290d7a64f25e6b5002d98367e8367c1b532b534", + "0x26de40bffafe73ff4e37089b2c71e35fd02eb1a7", + "0x3d1ba9be9f66b8ee101911bc36d3fb562eac2244", + "0x10b35b348fd49966f2baf81df35a511c18bd1f80", + "0x47bc01597798dcd7506dcca36ac4302fc93a8cfb", + "0xc96df921009b790dffca412375251ed1a2b75c60", + "0xd6bd97a26232ba02172ff86b055d5d7be789335b", + "0x0ec72cd6690db40b16be166858299f19d4f8e5b0", + "0x15d4c048f83bd7e37d49ea4c83a07267ec4203da", + "0xeb3c8fc829d6afef0c3710aa22860c28c50755fe", + "0x8e00615469d759a0df6855dfb0963948888827a1", + "0x6b432d4aca9268fbf282c32143e9328ceb9190b8", + "0x221abee39e205a597acd80abc9d026d57108f5bf", + "0x58be0185356ad7cc59950d13ad2cd43c69de2e04", + "0xe574c0c33a7a67d9b09f9f0addbb3dca71a8f3e0", + "0x2b591e99afe9f32eaa6214f7b7629768c40eeb39", + "0x40eb49c971bceda8ea9998256aa7375f6bf05e90", + "0x3434d708ee9802125a24277326eeeea824a53e11", + "0xaaaebe6fe48e54f431b0c390cfaf0b017d09d42d", + "0x3c4b6e6e1ea3d4863700d7f76b36b7f3d3f13e3d", + "0xf04f22b39bf419fdec8eae7c69c5e89872915f53", + "0x85f17cf997934a597031b2e18a9ab6ebd4b9f6a4", + "0x7a1b3b2bfb687a26328e623441edaea69df3def5", + "0xc6e64729931f60d2c8bc70a27d66d9e0c28d1bf9", + "0x3506424f91fd33084466f402d5d97f05f8e3b4af", + "0x4fabb145d64652a948d72533023f6e7a623c7c53", + "0x6ae5f164d006b2fcfae195436345f0aa833d4830", + "0x8d983cb9388eac77af0474fa441c4815500cb7bb", + "0xbb0e17ef65f82ab018d8edd776e8dd940327b28b", + "0xddb3422497e61e13543bea06989c0789117555c5", + "0x0f5d2fb29fb7d3cfee444a200298f468908cc942", + "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0", + "0xb62132e35a6c13ee1ee0f84dc5d40bad8d815206", + "0x3845badade8e6dff049820680d1f14bd3903a5d0", + "0x9bf1d7d63dd7a4ce167cf4866388226eeefa702e", + "0x107c4504cd79c5d2696ea0030a8dd4e92601b82e", + "0x827d53c8170af52625f414bde00326fc8a085e86", + "0xda605fd5e003e6de0f33f6474080623fa6483e3e", + "0x888888435fde8e7d4c54cab67f206e4199454c60", + "0xaf446174961cd544e51b89310581669e8fc00d16", + "0x419c4db4b9e25d6db2ad9691ccb832c8d9fda05e", + "0x15874d65e649880c2614e7a480cb7c9a55787ff6", + "0x50d1c9771902476076ecfc8b2a83ad6b9355a4c9", + "0x108caf59641fc5d27502a87e641872b62d606ae2", + "0xbae73d6dfa362f1774930100269dd98e755d05ea", + "0xeda8b016efa8b1161208cf041cd86972eee0f31e", + "0xb1979ec52cdf54f680dbddbbd619bb566ffed1f3", + "0xd2877702675e6ceb975b4a1dff9fb7baf4c91ea9", + "0x335e14d18d8a903b782a39059dc35d61b94e1c1b", + "0xd11c37cc93042acab222a881068211ee2254e465", + "0x72dd4b6bd852a3aa172be4d6c5a6dbec588cf131", + "0xd26114cd6ee289accf82350c8d8487fedb8a0c07", + "0x971d048e737619884f2df75e31c7eb6412392328", + "0xaaaf91d9b90df800df4f55c205fd6989c977e73a", + "0xa47c8bf37f92abed4a126bda807a7b7498661acd" +] From e0d6c42dbacaa5ffca4c1c8c5ca84983ad26b30c Mon Sep 17 00:00:00 2001 From: George Marshall <george.marshall@consensys.net> Date: Wed, 12 Jun 2024 09:54:53 -0700 Subject: [PATCH 19/61] chore: updating failing snapshot in develop (#25261) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Fixes failing snapshot in `develop` most likely due to conflicts with https://github.com/MetaMask/metamask-extension/pull/24605 and https://github.com/MetaMask/metamask-extension/pull/24953 [Slack thread ](https://consensys.slack.com/archives/CTQAGKY5V/p1718207993031359) [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25261?quickstart=1) ## **Related issues** Fixes: N/A ## **Manual testing steps** 1. Pull this branch 2. Run `yarn jest` 3. See no failing snapshot tests ## **Screenshots/Recordings** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../security-tab/__snapshots__/security-tab.test.js.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap index 84eec8af8167..a3fec98ac6f1 100644 --- a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap +++ b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap @@ -1777,7 +1777,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" > <div - style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(159, 166, 174);" + style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(132, 140, 150);" > <div style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;" From 696cf1ddc49b1fa7ad508710d0e5a22753606163 Mon Sep 17 00:00:00 2001 From: Jyoti Puri <jyotipuri@gmail.com> Date: Wed, 12 Jun 2024 22:25:33 +0530 Subject: [PATCH 20/61] fix: add metrics ui_customizations: permit for permit signature types (#25105) --- .../lib/createRPCMethodTrackingMiddleware.js | 14 ++++++++- .../createRPCMethodTrackingMiddleware.test.js | 30 +++++++++++++++++++ shared/constants/metametrics.ts | 1 + shared/constants/transaction.ts | 2 ++ shared/modules/transaction.utils.test.js | 14 +++++++++ shared/modules/transaction.utils.ts | 3 ++ .../permit-simulation/permit-simulation.tsx | 2 +- .../confirm/info/typed-sign/typed-sign.tsx | 6 ++-- ui/pages/confirmations/utils/confirm.test.ts | 13 -------- ui/pages/confirmations/utils/confirm.ts | 10 ++----- 10 files changed, 69 insertions(+), 26 deletions(-) diff --git a/app/scripts/lib/createRPCMethodTrackingMiddleware.js b/app/scripts/lib/createRPCMethodTrackingMiddleware.js index 8ca3af21fd1b..ed2dfe48f2d9 100644 --- a/app/scripts/lib/createRPCMethodTrackingMiddleware.js +++ b/app/scripts/lib/createRPCMethodTrackingMiddleware.js @@ -7,6 +7,7 @@ import { MetaMetricsEventName, MetaMetricsEventUiCustomization, } from '../../../shared/constants/metametrics'; +import { parseTypedDataMessage } from '../../../shared/modules/transaction.utils'; import { BlockaidResultType, @@ -16,7 +17,10 @@ import { } from '../../../shared/constants/security-provider'; ///: BEGIN:ONLY_INCLUDE_IF(blockaid) -import { SIGNING_METHODS } from '../../../shared/constants/transaction'; +import { + EIP712_PRIMARY_TYPE_PERMIT, + SIGNING_METHODS, +} from '../../../shared/constants/transaction'; import { getBlockaidMetricsProps } from '../../../ui/helpers/utils/metrics'; ///: END:ONLY_INCLUDE_IF import { REDESIGN_APPROVAL_TYPES } from '../../../ui/pages/confirmations/utils/confirm'; @@ -303,6 +307,14 @@ export default function createRPCMethodTrackingMiddleware({ MetaMetricsEventUiCustomization.Siwe, ]; } + } else if (method === MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4) { + const { primaryType } = parseTypedDataMessage(data); + if (primaryType === EIP712_PRIMARY_TYPE_PERMIT) { + eventProperties.ui_customizations = [ + ...(eventProperties.ui_customizations || []), + MetaMetricsEventUiCustomization.Permit, + ]; + } } } catch (e) { console.warn(`createRPCMethodTrackingMiddleware: Errored - ${e}`); diff --git a/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js b/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js index d02153079743..595ef9349a8b 100644 --- a/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js +++ b/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js @@ -1,5 +1,6 @@ import { errorCodes } from 'eth-rpc-errors'; import { detectSIWE } from '@metamask/controller-utils'; + import { MESSAGE_TYPE } from '../../../shared/constants/app'; import { MetaMetricsEventCategory, @@ -11,6 +12,7 @@ import { BlockaidReason, BlockaidResultType, } from '../../../shared/constants/security-provider'; +import { permitSignatureMsg } from '../../../test/data/confirmations/typed_sign'; import createRPCMethodTrackingMiddleware from './createRPCMethodTrackingMiddleware'; const trackEvent = jest.fn(); @@ -506,6 +508,34 @@ describe('createRPCMethodTrackingMiddleware', () => { }); }); + it('should track typed-sign permit message if detected', async () => { + const req = { + method: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4, + origin: 'some.dapp', + params: [undefined, permitSignatureMsg.msgParams.data], + }; + const res = { + error: null, + }; + const { next, executeMiddlewareStack } = getNext(); + const handler = createHandler(); + + await handler(req, res, next); + await executeMiddlewareStack(); + + expect(trackEvent).toHaveBeenCalledTimes(2); + + expect(trackEvent.mock.calls[1][0]).toMatchObject({ + category: MetaMetricsEventCategory.InpageProvider, + event: MetaMetricsEventName.SignatureApproved, + properties: { + signature_type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4, + ui_customizations: [MetaMetricsEventUiCustomization.Permit], + }, + referrer: { url: 'some.dapp' }, + }); + }); + describe(`when '${MESSAGE_TYPE.ETH_SIGN}' is disabled in advanced settings`, () => { it(`should track ${MetaMetricsEventName.SignatureFailed} and include error property`, async () => { const mockError = { code: errorCodes.rpc.methodNotFound }; diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts index 13b91135446d..6db66f796679 100644 --- a/shared/constants/metametrics.ts +++ b/shared/constants/metametrics.ts @@ -837,6 +837,7 @@ export enum MetaMetricsEventUiCustomization { RedesignedConfirmation = 'redesigned_confirmation', SecurityAlertError = 'security_alert_error', Siwe = 'sign_in_with_ethereum', + Permit = 'permit', } /** diff --git a/shared/constants/transaction.ts b/shared/constants/transaction.ts index c4b1d9f8b429..726148865512 100644 --- a/shared/constants/transaction.ts +++ b/shared/constants/transaction.ts @@ -195,3 +195,5 @@ export enum TokenStandard { /** Not a token, but rather the base asset of the selected chain. */ none = 'NONE', } + +export const EIP712_PRIMARY_TYPE_PERMIT = 'Permit'; diff --git a/shared/modules/transaction.utils.test.js b/shared/modules/transaction.utils.test.js index 778abc198079..ad43a8aa227b 100644 --- a/shared/modules/transaction.utils.test.js +++ b/shared/modules/transaction.utils.test.js @@ -1,11 +1,13 @@ import EthQuery from '@metamask/ethjs-query'; import { TransactionType } from '@metamask/transaction-controller'; + import { createTestProviderTools } from '../../test/stub/provider'; import { determineTransactionType, isEIP1559Transaction, isLegacyTransaction, parseStandardTokenTransactionData, + parseTypedDataMessage, } from './transaction.utils'; describe('Transaction.utils', function () { @@ -387,5 +389,17 @@ describe('Transaction.utils', function () { getCodeResponse: '0x0a', }); }); + + describe('parseTypedDataMessage', () => { + it('parses data passed correctly', () => { + const result = parseTypedDataMessage('{"test": "dummy"}'); + expect(result.test).toBe('dummy'); + }); + it('throw error for invalid typedDataMessage', () => { + expect(() => { + parseTypedDataMessage(''); + }).toThrow(new Error('Unexpected end of JSON input')); + }); + }); }); }); diff --git a/shared/modules/transaction.utils.ts b/shared/modules/transaction.utils.ts index e6a5f96a126d..edf24d20be18 100644 --- a/shared/modules/transaction.utils.ts +++ b/shared/modules/transaction.utils.ts @@ -281,3 +281,6 @@ export async function determineTransactionAssetType( } return { assetType: AssetType.native, tokenStandard: TokenStandard.none }; } + +export const parseTypedDataMessage = (dataToParse: string) => + JSON.parse(dataToParse); diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx index fe43dd17183a..6aa8ec159ec0 100644 --- a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx @@ -2,6 +2,7 @@ import React, { useMemo } from 'react'; import { useSelector } from 'react-redux'; import { NameType } from '@metamask/name-controller'; +import { parseTypedDataMessage } from '../../../../../../../../shared/modules/transaction.utils'; import { Numeric } from '../../../../../../../../shared/modules/Numeric'; import Name from '../../../../../../../components/app/name/name'; import { @@ -17,7 +18,6 @@ import { Display, TextAlign, } from '../../../../../../../helpers/constants/design-system'; -import { parseTypedDataMessage } from '../../../../../utils'; import { SignatureRequestType } from '../../../../../types/confirm'; import useTokenExchangeRate from '../../../../../../../components/app/currency-input/hooks/useTokenExchangeRate'; import { IndividualFiatDisplay } from '../../../../simulation-details/fiat-display'; diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx index 5ff582bde243..12faf4d3816a 100644 --- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { useSelector } from 'react-redux'; import { isValidAddress } from 'ethereumjs-util'; +import { parseTypedDataMessage } from '../../../../../../../shared/modules/transaction.utils'; import { ConfirmInfoRow, ConfirmInfoRowAddress, @@ -16,10 +17,7 @@ import { BorderRadius, } from '../../../../../../helpers/constants/design-system'; import { SignatureRequestType } from '../../../../types/confirm'; -import { - isPermitSignatureRequest, - parseTypedDataMessage, -} from '../../../../utils'; +import { isPermitSignatureRequest } from '../../../../utils'; import { ConfirmInfoRowTypedSignData } from '../../row/typed-sign-data/typedSignData'; import { PermitSimulation } from './permit-simulation'; diff --git a/ui/pages/confirmations/utils/confirm.test.ts b/ui/pages/confirmations/utils/confirm.test.ts index 4e2edbaad6e8..c8d283f921b4 100644 --- a/ui/pages/confirmations/utils/confirm.test.ts +++ b/ui/pages/confirmations/utils/confirm.test.ts @@ -12,7 +12,6 @@ import { isSignatureApprovalRequest, isSignatureTransactionType, parseSanitizeTypedDataMessage, - parseTypedDataMessage, } from './confirm'; const typedDataMsg = @@ -38,18 +37,6 @@ describe('confirm util', () => { }); }); - describe('parseTypedDataMessage', () => { - it('parses data passed correctly', () => { - const result = parseTypedDataMessage('{"test": "dummy"}'); - expect(result.test).toBe('dummy'); - }); - it('throw error for invalid typedDataMessage', () => { - expect(() => { - parseSanitizeTypedDataMessage(''); - }).toThrow(); - }); - }); - describe('parseSanitizeTypedDataMessage', () => { it('parses and sanitizes data passed correctly', () => { const result = parseSanitizeTypedDataMessage(typedDataMsg); diff --git a/ui/pages/confirmations/utils/confirm.ts b/ui/pages/confirmations/utils/confirm.ts index abc57fa02483..0ef735cf7832 100644 --- a/ui/pages/confirmations/utils/confirm.ts +++ b/ui/pages/confirmations/utils/confirm.ts @@ -3,12 +3,11 @@ import { ApprovalType } from '@metamask/controller-utils'; import { TransactionType } from '@metamask/transaction-controller'; import { Json } from '@metamask/utils'; +import { EIP712_PRIMARY_TYPE_PERMIT } from '../../../../shared/constants/transaction'; +import { parseTypedDataMessage } from '../../../../shared/modules/transaction.utils'; import { sanitizeMessage } from '../../../helpers/utils/util'; import { SignatureRequestType } from '../types/confirm'; -import { - EIP712_PRIMARY_TYPE_PERMIT, - TYPED_SIGNATURE_VERSIONS, -} from '../constants'; +import { TYPED_SIGNATURE_VERSIONS } from '../constants'; export const REDESIGN_APPROVAL_TYPES = [ ApprovalType.EthSignTypedData, @@ -40,9 +39,6 @@ export const isSignatureTransactionType = (request?: Record<string, unknown>) => request && SIGNATURE_TRANSACTION_TYPES.includes(request.type as TransactionType); -export const parseTypedDataMessage = (dataToParse: string) => - JSON.parse(dataToParse); - export const parseSanitizeTypedDataMessage = (dataToParse: string) => { const { message, primaryType, types } = parseTypedDataMessage(dataToParse); const sanitizedMessage = sanitizeMessage(message, primaryType, types); From dc5247ff4b2e1febc12678fc034807ffb6da1385 Mon Sep 17 00:00:00 2001 From: jiexi <jiexiluan@gmail.com> Date: Wed, 12 Jun 2024 10:28:19 -0700 Subject: [PATCH 21/61] fix: Retry requests from provider after connection is ready, on all builds (#24142) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Currently, requests from the dapp can hang if: 1. they are sent before the extension is fully initialized / before the extension is ready to process requests from that specific dapp connection 2. they get swallowed do to an issue in chromium with streams on prerendered pages breaking when they become visible to the user The inpage provider does have a retry mechanism, but currently that only works on MV3 builds. Additionally, is not a 100% reliable trigger as the underlying `metamask_chainChanged` message that it relies on is tied to MetaMaskController mem state changes, and is not fired off each time a dapp connection is established. This PR attempts to fix request retries by: * Making the retry message triggered by `metamask_chainChanged` work on all builds, not just MV3 builds * Firing `metamask_chainChanged` every time a new dapp connection is established **Open concern:** There may be an edge case when a request with a confirmation is sent by the dapp, then received and shown to the user in the wallet, but swallowed by prerender. I believe my proposed changes in this PR would cause the confirmation to get resent even though there may still be a confirmation being shown to the user. I haven't been able to test this properly as debugging the prerender issue in general is difficult. This would require a dapp to send a request requiring confirmation pretty much immediately after page load, implying without user interaction. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/24142?quickstart=1) ## **Related issues** See: https://github.com/MetaMask/metamask-extension/issues/11069 See: https://github.com/MetaMask/metamask-extension/issues/23329 See: https://github.com/MetaMask/metamask-extension/issues/24025 ## **Manual testing steps** ### Verify this fixes the `metamask_sendDomainMetadata` issue 1. Restart extension 2. Open any page 3. Quickly open the wallet popup 4. Notice that there is no favicon 5. After 5s have elapsed since the page was opened, the favicon should populate in the wallet popup ### Verify this fixes retrying messages before extension is ready 1. Open any page (restarting extension not required) 2. Quickly open console and type `await window.ethereum.request({method: 'eth_chainId'})` 3. Notice that the response doesn't come immediately 4. After 5s have elapsed since the page was opened, the response should be shown in console ### Verify this fixes retrying messages after broken prerender stream Not easy to verify this unfortunately, you would need to break the prerender stream while a request was being made ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Alex Donesky <adonesky@gmail.com> Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com> --- app/scripts/contentscript.js | 2 -- app/scripts/metamask-controller.js | 44 ++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index b4787914cd8c..ab2483c9f9a3 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -8,7 +8,6 @@ import { checkForLastError, getIsBrowserPrerenderBroken, } from '../../shared/modules/browser-runtime.utils'; -import { isManifestV3 } from '../../shared/modules/mv3.utils'; import shouldInjectProvider from '../../shared/modules/provider-injection'; // contexts @@ -456,7 +455,6 @@ function logStreamDisconnectWarning(remoteLabel, error) { function extensionStreamMessageListener(msg) { if ( METAMASK_EXTENSION_CONNECT_SENT && - isManifestV3 && msg.data.method === 'metamask_chainChanged' ) { METAMASK_EXTENSION_CONNECT_SENT = false; diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 12c209020403..917aacfe7058 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -5015,6 +5015,11 @@ export default class MetamaskController extends EventEmitter { } }, ); + + // Used to show wallet liveliness to the provider + if (subjectType !== SubjectType.Internal) { + this._notifyChainChangeForConnection({ engine }, origin); + } } ///: BEGIN:ONLY_INCLUDE_IF(snaps) @@ -5544,9 +5549,7 @@ export default class MetamaskController extends EventEmitter { Object.keys(this.connections).forEach((origin) => { Object.values(this.connections[origin]).forEach(async (conn) => { try { - if (conn.engine) { - conn.engine.emit('notification', await getPayload(origin)); - } + this.notifyConnection(conn, await getPayload(origin)); } catch (err) { console.error(err); } @@ -5554,6 +5557,27 @@ export default class MetamaskController extends EventEmitter { }); } + /** + * Causes the RPC engine for passed connection to emit a + * notification event with the given payload. + * + * The caller is responsible for ensuring that only permitted notifications + * are sent. + * + * @param {object} connection - Data associated with the connection + * @param {object} connection.engine - The connection's JSON Rpc Engine + * @param {unknown} payload - The event payload + */ + notifyConnection(connection, payload) { + try { + if (connection.engine) { + connection.engine.emit('notification', payload); + } + } catch (err) { + console.error(err); + } + } + // handlers /** @@ -6121,6 +6145,20 @@ export default class MetamaskController extends EventEmitter { } } + async _notifyChainChangeForConnection(connection, origin) { + if (this.preferencesController.getUseRequestQueue()) { + this.notifyConnection(connection, { + method: NOTIFICATION_NAMES.chainChanged, + params: await this.getProviderNetworkState(origin), + }); + } else { + this.notifyConnection(connection, { + method: NOTIFICATION_NAMES.chainChanged, + params: await this.getProviderNetworkState(), + }); + } + } + async _onFinishedTransaction(transactionMeta) { if ( ![TransactionStatus.confirmed, TransactionStatus.failed].includes( From 7e24e8ff2f24529d833e647dac7ca753a5afeb4b Mon Sep 17 00:00:00 2001 From: Jony Bursztyn <jony.bursztyn@consensys.net> Date: Wed, 12 Jun 2024 19:53:47 +0200 Subject: [PATCH 22/61] fix: hide privacy policy toast during onboarding, and for onboarded users (#25217) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Fixes two bugs: - Privacy policy toast should not be seen during onboarding - Users who onboarded after the privacy policy date should not see the new privacy policy toast. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25217?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** New user onbaording after the date: 1. Set the privacy policy date to a date in the future from today 2. Onboard (create a new user) 3. User should not see the privacy policy toast at any moment New user onboarding before the date: 1. Set the privacy policy date to a date in the past from today. 2. Onboard (create a new user) 3. User should not see the privacy policy toast at any moment 4. Set the privacy policy date to a date in the future from today 5. User should not see the privacy policy toast on the home screen Old user after the privacy policy date: 1. Have a user already onboarded 2. Make sure the `onboardingDate` is `null` in the redux state (this simulates a user who has registered before this PR has been in production) 3. Set the privacy policy date to a date in the future from today 4. User should not see the new privacy policy toast Old user before the privacy policy date: 1. Have a user onboarded 2. Make sure the `onboardingDate` is `null` in the redux state (this simulates a user who has registered before this PR has been in production) 3. Set the privacy policy date to a date in the past before today 4. User should see the new privacy policy toast TL;DR: If the privacy policy date is in the future, the user should never see it -BUT- if the privacy policy is in the past, the user should see it, as long as the user onboarded before the privacy policy date. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: Brian Bergeron <brian.e.bergeron@gmail.com> Co-authored-by: NidhiKJha <menidhikjha@gmail.com> Co-authored-by: Nidhi Kumari <nidhi.kumari@consensys.net> --- app/scripts/controllers/app-state.js | 7 +++ app/scripts/lib/setupSentry.js | 1 + app/scripts/metamask-controller.js | 2 + ...rs-after-init-opt-in-background-state.json | 1 + .../errors-after-init-opt-in-ui-state.json | 1 + ui/pages/onboarding-flow/onboarding-flow.js | 5 ++ .../onboarding-flow/onboarding-flow.test.js | 1 + ui/pages/routes/routes.component.js | 8 ++- ui/pages/routes/routes.component.test.js | 31 +++++++++++ ui/selectors/selectors.js | 14 ++++- ui/selectors/selectors.test.js | 55 +++++++++++++++++-- ui/store/actions.ts | 6 ++ 12 files changed, 122 insertions(+), 10 deletions(-) diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 731a9d0d25e4..256dfba38438 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -52,6 +52,7 @@ export default class AppStateController extends EventEmitter { showAccountBanner: true, trezorModel: null, currentPopupId: undefined, + onboardingDate: null, newPrivacyPolicyToastClickedOrClosed: null, newPrivacyPolicyToastShownDate: null, // This key is only used for checking if the user had set advancedGasFee @@ -186,6 +187,12 @@ export default class AppStateController extends EventEmitter { }); } + setOnboardingDate() { + this.store.updateState({ + onboardingDate: Date.now(), + }); + } + setNewPrivacyPolicyToastClickedOrClosed() { this.store.updateState({ newPrivacyPolicyToastClickedOrClosed: true, diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 94843c2e9a98..dfa04ab73236 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -90,6 +90,7 @@ export const SENTRY_BACKGROUND_STATE = { browserEnvironment: true, connectedStatusPopoverHasBeenShown: true, currentPopupId: false, + onboardingDate: false, currentExtensionPopupId: false, defaultHomeActiveTabName: true, fullScreenGasPollTokens: true, diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 917aacfe7058..c7abd76ec606 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -3260,6 +3260,8 @@ export default class MetamaskController extends EventEmitter { appStateController.setSurveyLinkLastClickedOrClosed.bind( appStateController, ), + setOnboardingDate: + appStateController.setOnboardingDate.bind(appStateController), setNewPrivacyPolicyToastClickedOrClosed: appStateController.setNewPrivacyPolicyToastClickedOrClosed.bind( appStateController, diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json index e6a62e19d994..8ab0a3b93cd0 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json @@ -38,6 +38,7 @@ "showNetworkBanner": true, "showAccountBanner": true, "trezorModel": null, + "onboardingDate": "object", "newPrivacyPolicyToastClickedOrClosed": "object", "newPrivacyPolicyToastShownDate": "object", "hadAdvancedGasFeesSetPriorToMigration92_3": false, diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json index 11d99c406b31..93650970b9a9 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json @@ -74,6 +74,7 @@ "showNetworkBanner": true, "showAccountBanner": true, "trezorModel": null, + "onboardingDate": "object", "newPrivacyPolicyToastClickedOrClosed": "object", "newPrivacyPolicyToastShownDate": "object", "hadAdvancedGasFeesSetPriorToMigration92_3": false, diff --git a/ui/pages/onboarding-flow/onboarding-flow.js b/ui/pages/onboarding-flow/onboarding-flow.js index 180d6cd68c70..01ea177eb851 100644 --- a/ui/pages/onboarding-flow/onboarding-flow.js +++ b/ui/pages/onboarding-flow/onboarding-flow.js @@ -28,6 +28,7 @@ import { createNewVaultAndGetSeedPhrase, unlockAndGetSeedPhrase, createNewVaultAndRestore, + setOnboardingDate, } from '../../store/actions'; import { getFirstTimeFlowTypeRouteAfterUnlock } from '../../selectors'; import { MetaMetricsContext } from '../../contexts/metametrics'; @@ -70,6 +71,10 @@ export default function OnboardingFlow() { const isFromReminder = new URLSearchParams(search).get('isFromReminder'); const trackEvent = useContext(MetaMetricsContext); + useEffect(() => { + dispatch(setOnboardingDate()); + }, [dispatch]); + useEffect(() => { if (completedOnboarding && !isFromReminder) { history.push(DEFAULT_ROUTE); diff --git a/ui/pages/onboarding-flow/onboarding-flow.test.js b/ui/pages/onboarding-flow/onboarding-flow.test.js index 460d4bf4c9ce..cc471f5febd5 100644 --- a/ui/pages/onboarding-flow/onboarding-flow.test.js +++ b/ui/pages/onboarding-flow/onboarding-flow.test.js @@ -30,6 +30,7 @@ jest.mock('../../store/actions', () => ({ createNewVaultAndGetSeedPhrase: jest.fn().mockResolvedValue(null), unlockAndGetSeedPhrase: jest.fn().mockResolvedValue(null), createNewVaultAndRestore: jest.fn(), + setOnboardingDate: jest.fn(() => ({ type: 'TEST_DISPATCH' })), })); describe('Onboarding Flow', () => { diff --git a/ui/pages/routes/routes.component.js b/ui/pages/routes/routes.component.js index f33aed54aa12..640cf27751b5 100644 --- a/ui/pages/routes/routes.component.js +++ b/ui/pages/routes/routes.component.js @@ -617,11 +617,13 @@ export default class Routes extends Component { const isPrivacyToastRecent = this.getIsPrivacyToastRecent(); const isPrivacyToastNotShown = !newPrivacyPolicyToastShownDate; + if (!this.onHomeScreen()) { + return null; + } + return ( <ToastContainer> - {showConnectAccountToast && - this.onHomeScreen() && - !this.state.hideConnectAccountToast ? ( + {showConnectAccountToast && !this.state.hideConnectAccountToast ? ( <Toast key="connect-account-toast" startAdornment={ diff --git a/ui/pages/routes/routes.component.test.js b/ui/pages/routes/routes.component.test.js index e6274bfc3223..749939c227c7 100644 --- a/ui/pages/routes/routes.component.test.js +++ b/ui/pages/routes/routes.component.test.js @@ -3,9 +3,14 @@ import configureMockStore from 'redux-mock-store'; import { act } from '@testing-library/react'; import { SEND_STAGES } from '../../ducks/send'; +import { + CONFIRMATION_V_NEXT_ROUTE, + DEFAULT_ROUTE, +} from '../../helpers/constants/routes'; import { CHAIN_IDS, NETWORK_TYPES } from '../../../shared/constants/network'; import { renderWithProvider } from '../../../test/jest'; import mockSendState from '../../../test/data/mock-send-state.json'; +import mockState from '../../../test/data/mock-state.json'; import { useIsOriginalNativeTokenSymbol } from '../../hooks/useIsOriginalNativeTokenSymbol'; import Routes from '.'; @@ -123,3 +128,29 @@ describe('Routes Component', () => { }); }); }); + +describe('toast display', () => { + const testState = { + ...mockState, + metamask: { + ...mockState.metamask, + announcements: {}, + approvalFlows: [], + completedOnboarding: true, + usedNetworks: [], + swapsState: { swapsFeatureIsLive: true }, + }, + }; + + it('renders toastContainer on default route', async () => { + await render([DEFAULT_ROUTE], testState); + const toastContainer = document.querySelector('.toasts-container'); + expect(toastContainer).toBeInTheDocument(); + }); + + it('does not render toastContainer on confirmation route', async () => { + await render([CONFIRMATION_V_NEXT_ROUTE], testState); + const toastContainer = document.querySelector('.toasts-container'); + expect(toastContainer).not.toBeInTheDocument(); + }); +}); diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index ab003341df92..e0fd002d17a1 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -1869,11 +1869,17 @@ export function getShowSurveyToast(state) { * @returns {boolean} True if the current date is on or after the new privacy policy date and the privacy policy toast was not clicked or closed. False otherwise. */ export function getShowPrivacyPolicyToast(state) { - const { newPrivacyPolicyToastClickedOrClosed } = state.metamask; + const { newPrivacyPolicyToastClickedOrClosed, onboardingDate } = + state.metamask; const newPrivacyPolicyDate = new Date(PRIVACY_POLICY_DATE); const currentDate = new Date(Date.now()); return ( - !newPrivacyPolicyToastClickedOrClosed && currentDate >= newPrivacyPolicyDate + !newPrivacyPolicyToastClickedOrClosed && + currentDate >= newPrivacyPolicyDate && + // users who onboarded before the privacy policy date should see the notice + // and + // old users who don't have onboardingDate set should see the notice + (onboardingDate < newPrivacyPolicyDate || !onboardingDate) ); } @@ -1890,6 +1896,10 @@ export function getNewPrivacyPolicyToastShownDate(state) { return state.metamask.newPrivacyPolicyToastShownDate; } +export function getOnboardingDate(state) { + return state.metamask.onboardingDate; +} + export function getShowBetaHeader(state) { return state.metamask.showBetaHeader; } diff --git a/ui/selectors/selectors.test.js b/ui/selectors/selectors.test.js index 23bc7fed2ed1..f40a8497a86b 100644 --- a/ui/selectors/selectors.test.js +++ b/ui/selectors/selectors.test.js @@ -1290,30 +1290,46 @@ describe('Selectors', () => { dateNowSpy = jest .spyOn(Date, 'now') - .mockReturnValue(dayAfterPolicyDate); + .mockReturnValue(dayAfterPolicyDate.getTime()); }); afterEach(() => { dateNowSpy.mockRestore(); }); - it('shows the privacy policy toast when not yet seen and on or after the policy date', () => { + it('shows the privacy policy toast when not yet seen, on or after the policy date, and onboardingDate is before the policy date', () => { const result = selectors.getShowPrivacyPolicyToast({ metamask: { newPrivacyPolicyToastClickedOrClosed: null, + onboardingDate: new Date(PRIVACY_POLICY_DATE).setDate( + new Date(PRIVACY_POLICY_DATE).getDate() - 2, + ), }, }); expect(result).toBe(true); }); - it('does not show the privacy policy toast when seen and on or after the policy date', () => { + it('does not show the privacy policy toast when seen, even if on or after the policy date and onboardingDate is before the policy date', () => { const result = selectors.getShowPrivacyPolicyToast({ metamask: { newPrivacyPolicyToastClickedOrClosed: true, + onboardingDate: new Date(PRIVACY_POLICY_DATE).setDate( + new Date(PRIVACY_POLICY_DATE).getDate() - 2, + ), }, }); expect(result).toBe(false); }); + + it('shows the privacy policy toast when not yet seen, on or after the policy date, and onboardingDate is not set', () => { + const result = selectors.getShowPrivacyPolicyToast({ + metamask: { + newPrivacyPolicyToastClickedOrClosed: null, + onboardingDate: null, + }, + }); + expect(result).toBe(true); + }); }); describe('mock same day', () => { @@ -1327,23 +1343,39 @@ describe('Selectors', () => { dateNowSpy.mockRestore(); }); - it('shows the privacy policy toast when not yet seen and on or after the policy date', () => { + it('shows the privacy policy toast when not yet seen, on or after the policy date, and onboardingDate is before the policy date', () => { const result = selectors.getShowPrivacyPolicyToast({ metamask: { newPrivacyPolicyToastClickedOrClosed: null, + onboardingDate: new Date(PRIVACY_POLICY_DATE).setDate( + new Date(PRIVACY_POLICY_DATE).getDate() - 2, + ), }, }); expect(result).toBe(true); }); - it('does not show the privacy policy toast when seen and on or after the policy date', () => { + it('does not show the privacy policy toast when seen, even if on or after the policy date and onboardingDate is before the policy date', () => { const result = selectors.getShowPrivacyPolicyToast({ metamask: { newPrivacyPolicyToastClickedOrClosed: true, + onboardingDate: new Date(PRIVACY_POLICY_DATE).setDate( + new Date(PRIVACY_POLICY_DATE).getDate() - 2, + ), }, }); expect(result).toBe(false); }); + + it('shows the privacy policy toast when not yet seen, on or after the policy date, and onboardingDate is not set', () => { + const result = selectors.getShowPrivacyPolicyToast({ + metamask: { + newPrivacyPolicyToastClickedOrClosed: null, + onboardingDate: null, + }, + }); + expect(result).toBe(true); + }); }); describe('mock day before', () => { @@ -1364,6 +1396,19 @@ describe('Selectors', () => { const result = selectors.getShowPrivacyPolicyToast({ metamask: { newPrivacyPolicyToastClickedOrClosed: null, + onboardingDate: new Date(PRIVACY_POLICY_DATE).setDate( + new Date(PRIVACY_POLICY_DATE).getDate() - 2, + ), + }, + }); + expect(result).toBe(false); + }); + + it('does not show the privacy policy toast before the policy date even if onboardingDate is not set', () => { + const result = selectors.getShowPrivacyPolicyToast({ + metamask: { + newPrivacyPolicyToastClickedOrClosed: null, + onboardingDate: null, }, }); expect(result).toBe(false); diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 4025ec0a4bb1..2a8d1a983159 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -4272,6 +4272,12 @@ export function setNewPrivacyPolicyToastClickedOrClosed() { }; } +export function setOnboardingDate() { + return async () => { + await submitRequestToBackground('setOnboardingDate'); + }; +} + export function setNewPrivacyPolicyToastShownDate(time: number) { return async () => { await submitRequestToBackground('setNewPrivacyPolicyToastShownDate', [ From e407384c1c2a2b6b20e011b9a2bbf52a4a850b49 Mon Sep 17 00:00:00 2001 From: Elliot Winkler <elliot.winkler@gmail.com> Date: Wed, 12 Jun 2024 12:18:57 -0600 Subject: [PATCH 23/61] chore(deps): Bump base-controller to ^5.0.1 (#24209) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> This version of `@metamask/base-controller` does not introduce any functional changes, but there are a few developer experience improvements: - The controller messenger is now more type-safe, in that a messenger with an empty action/event allowlist guarantees that no actions/events are allowed to be called/emitted, and conversely, that a non-empty allowlist only allows the given actions/events - The "selector" version of `subscribe` (three arguments instead of two) is now fixed so that the arguments to the selector function are correctly typed. - It is now impossible to mutate state directly; state must only be mutated inside of a controller using the `update` method. This ensures that state updates are always controlled and expected. View changelog: https://github.com/MetaMask/core/blob/%40metamask/base-controller%405.0.1/packages/base-controller/CHANGELOG.md [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/24209?quickstart=1) ## **Related issues** Progresses #24140. ## **Manual testing steps** (None needed as there should be no functional changes.) ## **Screenshots/Recordings** (None) ## **Pre-merge author checklist** - [x] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com> Co-authored-by: Michele Esposito <michele@esposito.codes> Co-authored-by: Michele Esposito <34438276+mikesposito@users.noreply.github.com> Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com> Co-authored-by: Mark Stacey <markjstacey@gmail.com> --- .../authentication-controller.test.ts | 1 + .../push-platform-notifications.test.ts | 1 + .../user-storage-controller.test.ts | 1 + .../snap-keyring/utils/isBlockedUrl.test.ts | 5 +- lavamoat/browserify/beta/policy.json | 168 +++------------- lavamoat/browserify/flask/policy.json | 188 +++--------------- lavamoat/browserify/main/policy.json | 188 +++--------------- lavamoat/browserify/mmi/policy.json | 188 +++--------------- package.json | 2 +- yarn.lock | 4 +- 10 files changed, 126 insertions(+), 620 deletions(-) diff --git a/app/scripts/controllers/authentication/authentication-controller.test.ts b/app/scripts/controllers/authentication/authentication-controller.test.ts index 1a86cee38c82..e13b999de517 100644 --- a/app/scripts/controllers/authentication/authentication-controller.test.ts +++ b/app/scripts/controllers/authentication/authentication-controller.test.ts @@ -253,6 +253,7 @@ function createAuthenticationMessenger() { return messenger.getRestricted({ name: 'AuthenticationController', allowedActions: [`SnapController:handleRequest`], + allowedEvents: [], }); } diff --git a/app/scripts/controllers/push-platform-notifications/push-platform-notifications.test.ts b/app/scripts/controllers/push-platform-notifications/push-platform-notifications.test.ts index f29318737cb9..0b596fdb4992 100644 --- a/app/scripts/controllers/push-platform-notifications/push-platform-notifications.test.ts +++ b/app/scripts/controllers/push-platform-notifications/push-platform-notifications.test.ts @@ -133,6 +133,7 @@ function buildPushPlatformNotificationsControllerMessenger( return messenger.getRestricted({ name: 'PushPlatformNotificationsController', allowedActions: ['AuthenticationController:getBearerToken'], + allowedEvents: [], }) as PushPlatformNotificationsControllerMessenger; } diff --git a/app/scripts/controllers/user-storage/user-storage-controller.test.ts b/app/scripts/controllers/user-storage/user-storage-controller.test.ts index 471f82cbbd58..b70141f6eaab 100644 --- a/app/scripts/controllers/user-storage/user-storage-controller.test.ts +++ b/app/scripts/controllers/user-storage/user-storage-controller.test.ts @@ -301,6 +301,7 @@ function mockUserStorageMessenger() { 'MetamaskNotificationsController:disableMetamaskNotifications', 'MetamaskNotificationsController:selectIsMetamaskNotificationsEnabled', ], + allowedEvents: [], }); const mockSnapGetPublicKey = jest.fn().mockResolvedValue('MOCK_PUBLIC_KEY'); diff --git a/app/scripts/lib/snap-keyring/utils/isBlockedUrl.test.ts b/app/scripts/lib/snap-keyring/utils/isBlockedUrl.test.ts index ba7ef745ffa5..b40e52afe170 100644 --- a/app/scripts/lib/snap-keyring/utils/isBlockedUrl.test.ts +++ b/app/scripts/lib/snap-keyring/utils/isBlockedUrl.test.ts @@ -6,11 +6,10 @@ describe('isBlockedUrl', () => { const messenger = new ControllerMessenger(); const phishingControllerMessenger = messenger.getRestricted({ name: 'PhishingController', + allowedActions: [], + allowedEvents: [], }); const phishingController = new PhishingController({ - // @ts-expect-error The PhishingController uses a newer verison of the package - // `@metamask/base-controller`, which has a different messenger type. This error will be - // resolved shortly when the `@metamask/base-controller` package is updated. messenger: phishingControllerMessenger, state: { phishingLists: [ diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index da393aaecbe1..9e7e7e655ff4 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -768,16 +768,8 @@ }, "@metamask/address-book-controller": { "packages": { - "@metamask/address-book-controller>@metamask/base-controller": true, - "@metamask/address-book-controller>@metamask/controller-utils": true - } - }, - "@metamask/address-book-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true + "@metamask/address-book-controller>@metamask/controller-utils": true, + "@metamask/base-controller": true } }, "@metamask/address-book-controller>@metamask/controller-utils": { @@ -800,7 +792,7 @@ }, "@metamask/announcement-controller": { "packages": { - "@metamask/announcement-controller>@metamask/base-controller": true + "@metamask/base-controller": true } }, "@metamask/announcement-controller>@metamask/base-controller": { @@ -816,19 +808,11 @@ "console.info": true }, "packages": { - "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true } }, - "@metamask/approval-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/approval-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -853,11 +837,11 @@ "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/abi-utils": true, - "@metamask/assets-controllers>@metamask/base-controller": true, "@metamask/assets-controllers>@metamask/polling-controller": true, "@metamask/assets-controllers>async-mutex": true, "@metamask/assets-controllers>cockatiel": true, "@metamask/assets-controllers>multiformats": true, + "@metamask/base-controller": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, @@ -871,14 +855,6 @@ "webpack>events": true } }, - "@metamask/assets-controllers>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/assets-controllers>@metamask/polling-controller": { "globals": { "clearTimeout": true, @@ -886,19 +862,11 @@ "setTimeout": true }, "packages": { - "@metamask/assets-controllers>@metamask/polling-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/snaps-utils>fast-json-stable-stringify": true, "uuid": true } }, - "@metamask/assets-controllers>@metamask/polling-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/assets-controllers>async-mutex": { "globals": { "setTimeout": true @@ -1007,20 +975,12 @@ "@metamask/ens-controller": { "packages": { "@ethersproject/providers": true, - "@metamask/ens-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/ens-controller>@metamask/controller-utils": true, "@metamask/utils": true, "punycode": true } }, - "@metamask/ens-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/ens-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1543,23 +1503,15 @@ "packages": { "@ethereumjs/tx>@ethereumjs/util": true, "@metamask/assets-controllers>async-mutex": true, + "@metamask/base-controller": true, "@metamask/browser-passworder": true, "@metamask/eth-sig-util": true, - "@metamask/keyring-controller>@metamask/base-controller": true, "@metamask/keyring-controller>@metamask/eth-hd-keyring": true, "@metamask/keyring-controller>@metamask/eth-simple-keyring": true, "@metamask/keyring-controller>ethereumjs-wallet": true, "@metamask/utils": true } }, - "@metamask/keyring-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/keyring-controller>@metamask/eth-hd-keyring": { "globals": { "TextEncoder": true @@ -1629,18 +1581,10 @@ }, "@metamask/logging-controller": { "packages": { - "@metamask/logging-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "uuid": true } }, - "@metamask/logging-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/logo": { "globals": { "addEventListener": true, @@ -1657,8 +1601,8 @@ }, "@metamask/message-manager": { "packages": { - "@metamask/base-controller": true, "@metamask/eth-sig-util": true, + "@metamask/message-manager>@metamask/base-controller": true, "@metamask/message-manager>@metamask/controller-utils": true, "@metamask/message-manager>jsonschema": true, "@metamask/utils": true, @@ -1667,6 +1611,14 @@ "webpack>events": true } }, + "@metamask/message-manager>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/message-manager>@metamask/controller-utils": { "globals": { "URL": true, @@ -1752,10 +1704,10 @@ "setTimeout": true }, "packages": { + "@metamask/base-controller": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/eth-query": true, "@metamask/eth-token-tracker>@metamask/eth-block-tracker": true, - "@metamask/network-controller>@metamask/base-controller": true, "@metamask/network-controller>@metamask/controller-utils": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, @@ -1767,14 +1719,6 @@ "uuid": true } }, - "@metamask/network-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/network-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1854,7 +1798,7 @@ "console.error": true }, "packages": { - "@metamask/permission-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/permission-controller>@metamask/controller-utils": true, "@metamask/permission-controller>nanoid": true, "@metamask/providers>@metamask/rpc-errors": true, @@ -1864,14 +1808,6 @@ "immer": true } }, - "@metamask/permission-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/permission-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1897,37 +1833,21 @@ }, "@metamask/permission-log-controller": { "packages": { - "@metamask/permission-log-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/utils": true } }, - "@metamask/permission-log-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/phishing-controller": { "globals": { "fetch": true }, "packages": { - "@metamask/phishing-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/phishing-controller>@metamask/controller-utils": true, "@metamask/phishing-warning>eth-phishing-detect": true, "punycode": true } }, - "@metamask/phishing-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/phishing-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2002,21 +1922,13 @@ }, "@metamask/queued-request-controller": { "packages": { + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/queued-request-controller>@metamask/base-controller": true, "@metamask/selected-network-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true } }, - "@metamask/queued-request-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/rpc-methods-flask>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2052,16 +1964,8 @@ }, "@metamask/selected-network-controller": { "packages": { - "@metamask/network-controller>@metamask/swappable-obj-proxy": true, - "@metamask/selected-network-controller>@metamask/base-controller": true - } - }, - "@metamask/selected-network-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true + "@metamask/base-controller": true, + "@metamask/network-controller>@metamask/swappable-obj-proxy": true } }, "@metamask/signature-controller": { @@ -2069,9 +1973,9 @@ "console.info": true }, "packages": { + "@metamask/base-controller": true, "@metamask/logging-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/signature-controller>@metamask/base-controller": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/signature-controller>@metamask/message-manager": true, "@metamask/utils": true, @@ -2080,14 +1984,6 @@ "webpack>events": true } }, - "@metamask/signature-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/signature-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2108,9 +2004,9 @@ }, "@metamask/signature-controller>@metamask/message-manager": { "packages": { + "@metamask/base-controller": true, "@metamask/eth-sig-util": true, "@metamask/message-manager>jsonschema": true, - "@metamask/signature-controller>@metamask/base-controller": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/utils": true, "browserify>buffer": true, @@ -2667,11 +2563,11 @@ }, "packages": { "@metamask/assets-controllers>@metamask/polling-controller": true, + "@metamask/base-controller": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/transaction-controller": true, - "@metamask/user-operation-controller>@metamask/base-controller": true, "@metamask/user-operation-controller>@metamask/controller-utils": true, "@metamask/utils": true, "bn.js": true, @@ -2681,14 +2577,6 @@ "webpack>events": true } }, - "@metamask/user-operation-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/user-operation-controller>@metamask/controller-utils": { "globals": { "URL": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 285a6ee94fbe..24241a5bdac8 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -768,16 +768,8 @@ }, "@metamask/address-book-controller": { "packages": { - "@metamask/address-book-controller>@metamask/base-controller": true, - "@metamask/address-book-controller>@metamask/controller-utils": true - } - }, - "@metamask/address-book-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true + "@metamask/address-book-controller>@metamask/controller-utils": true, + "@metamask/base-controller": true } }, "@metamask/address-book-controller>@metamask/controller-utils": { @@ -800,7 +792,7 @@ }, "@metamask/announcement-controller": { "packages": { - "@metamask/announcement-controller>@metamask/base-controller": true + "@metamask/base-controller": true } }, "@metamask/announcement-controller>@metamask/base-controller": { @@ -816,19 +808,11 @@ "console.info": true }, "packages": { - "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true } }, - "@metamask/approval-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/approval-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -853,11 +837,11 @@ "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/abi-utils": true, - "@metamask/assets-controllers>@metamask/base-controller": true, "@metamask/assets-controllers>@metamask/polling-controller": true, "@metamask/assets-controllers>async-mutex": true, "@metamask/assets-controllers>cockatiel": true, "@metamask/assets-controllers>multiformats": true, + "@metamask/base-controller": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, @@ -871,14 +855,6 @@ "webpack>events": true } }, - "@metamask/assets-controllers>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/assets-controllers>@metamask/polling-controller": { "globals": { "clearTimeout": true, @@ -886,19 +862,11 @@ "setTimeout": true }, "packages": { - "@metamask/assets-controllers>@metamask/polling-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/snaps-utils>fast-json-stable-stringify": true, "uuid": true } }, - "@metamask/assets-controllers>@metamask/polling-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/assets-controllers>async-mutex": { "globals": { "setTimeout": true @@ -1007,20 +975,12 @@ "@metamask/ens-controller": { "packages": { "@ethersproject/providers": true, - "@metamask/ens-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/ens-controller>@metamask/controller-utils": true, "@metamask/utils": true, "punycode": true } }, - "@metamask/ens-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/ens-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1543,23 +1503,15 @@ "packages": { "@ethereumjs/tx>@ethereumjs/util": true, "@metamask/assets-controllers>async-mutex": true, + "@metamask/base-controller": true, "@metamask/browser-passworder": true, "@metamask/eth-sig-util": true, - "@metamask/keyring-controller>@metamask/base-controller": true, "@metamask/keyring-controller>@metamask/eth-hd-keyring": true, "@metamask/keyring-controller>@metamask/eth-simple-keyring": true, "@metamask/keyring-controller>ethereumjs-wallet": true, "@metamask/utils": true } }, - "@metamask/keyring-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/keyring-controller>@metamask/eth-hd-keyring": { "globals": { "TextEncoder": true @@ -1629,18 +1581,10 @@ }, "@metamask/logging-controller": { "packages": { - "@metamask/logging-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "uuid": true } }, - "@metamask/logging-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/logo": { "globals": { "addEventListener": true, @@ -1657,8 +1601,8 @@ }, "@metamask/message-manager": { "packages": { - "@metamask/base-controller": true, "@metamask/eth-sig-util": true, + "@metamask/message-manager>@metamask/base-controller": true, "@metamask/message-manager>@metamask/controller-utils": true, "@metamask/message-manager>jsonschema": true, "@metamask/utils": true, @@ -1667,6 +1611,14 @@ "webpack>events": true } }, + "@metamask/message-manager>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/message-manager>@metamask/controller-utils": { "globals": { "URL": true, @@ -1752,10 +1704,10 @@ "setTimeout": true }, "packages": { + "@metamask/base-controller": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/eth-query": true, "@metamask/eth-token-tracker>@metamask/eth-block-tracker": true, - "@metamask/network-controller>@metamask/base-controller": true, "@metamask/network-controller>@metamask/controller-utils": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, @@ -1767,14 +1719,6 @@ "uuid": true } }, - "@metamask/network-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/network-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1881,7 +1825,7 @@ "console.error": true }, "packages": { - "@metamask/permission-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/permission-controller>@metamask/controller-utils": true, "@metamask/permission-controller>nanoid": true, "@metamask/providers>@metamask/rpc-errors": true, @@ -1891,14 +1835,6 @@ "immer": true } }, - "@metamask/permission-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/permission-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1924,37 +1860,21 @@ }, "@metamask/permission-log-controller": { "packages": { - "@metamask/permission-log-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/utils": true } }, - "@metamask/permission-log-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/phishing-controller": { "globals": { "fetch": true }, "packages": { - "@metamask/phishing-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/phishing-controller>@metamask/controller-utils": true, "@metamask/phishing-warning>eth-phishing-detect": true, "punycode": true } }, - "@metamask/phishing-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/phishing-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2081,39 +2001,23 @@ }, "@metamask/queued-request-controller": { "packages": { + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/queued-request-controller>@metamask/base-controller": true, "@metamask/selected-network-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true } }, - "@metamask/queued-request-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/rate-limit-controller": { "globals": { "setTimeout": true }, "packages": { + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/rate-limit-controller>@metamask/base-controller": true, "@metamask/utils": true } }, - "@metamask/rate-limit-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/rpc-methods-flask>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2149,16 +2053,8 @@ }, "@metamask/selected-network-controller": { "packages": { - "@metamask/network-controller>@metamask/swappable-obj-proxy": true, - "@metamask/selected-network-controller>@metamask/base-controller": true - } - }, - "@metamask/selected-network-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true + "@metamask/base-controller": true, + "@metamask/network-controller>@metamask/swappable-obj-proxy": true } }, "@metamask/signature-controller": { @@ -2166,9 +2062,9 @@ "console.info": true }, "packages": { + "@metamask/base-controller": true, "@metamask/logging-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/signature-controller>@metamask/base-controller": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/signature-controller>@metamask/message-manager": true, "@metamask/utils": true, @@ -2177,14 +2073,6 @@ "webpack>events": true } }, - "@metamask/signature-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/signature-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2205,9 +2093,9 @@ }, "@metamask/signature-controller>@metamask/message-manager": { "packages": { + "@metamask/base-controller": true, "@metamask/eth-sig-util": true, "@metamask/message-manager>jsonschema": true, - "@metamask/signature-controller>@metamask/base-controller": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/utils": true, "browserify>buffer": true, @@ -2542,11 +2430,11 @@ "setTimeout": true }, "packages": { + "@metamask/base-controller": true, "@metamask/object-multiplex": true, "@metamask/permission-controller": true, "@metamask/post-message-stream": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/base-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>@metamask/json-rpc-middleware-stream": true, "@metamask/snaps-controllers>@xstate/fsm": true, @@ -2570,14 +2458,6 @@ "crypto.getRandomValues": true } }, - "@metamask/snaps-controllers>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/snaps-controllers>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -2865,11 +2745,11 @@ }, "packages": { "@metamask/assets-controllers>@metamask/polling-controller": true, + "@metamask/base-controller": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/transaction-controller": true, - "@metamask/user-operation-controller>@metamask/base-controller": true, "@metamask/user-operation-controller>@metamask/controller-utils": true, "@metamask/utils": true, "bn.js": true, @@ -2879,14 +2759,6 @@ "webpack>events": true } }, - "@metamask/user-operation-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/user-operation-controller>@metamask/controller-utils": { "globals": { "URL": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 285a6ee94fbe..24241a5bdac8 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -768,16 +768,8 @@ }, "@metamask/address-book-controller": { "packages": { - "@metamask/address-book-controller>@metamask/base-controller": true, - "@metamask/address-book-controller>@metamask/controller-utils": true - } - }, - "@metamask/address-book-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true + "@metamask/address-book-controller>@metamask/controller-utils": true, + "@metamask/base-controller": true } }, "@metamask/address-book-controller>@metamask/controller-utils": { @@ -800,7 +792,7 @@ }, "@metamask/announcement-controller": { "packages": { - "@metamask/announcement-controller>@metamask/base-controller": true + "@metamask/base-controller": true } }, "@metamask/announcement-controller>@metamask/base-controller": { @@ -816,19 +808,11 @@ "console.info": true }, "packages": { - "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true } }, - "@metamask/approval-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/approval-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -853,11 +837,11 @@ "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/abi-utils": true, - "@metamask/assets-controllers>@metamask/base-controller": true, "@metamask/assets-controllers>@metamask/polling-controller": true, "@metamask/assets-controllers>async-mutex": true, "@metamask/assets-controllers>cockatiel": true, "@metamask/assets-controllers>multiformats": true, + "@metamask/base-controller": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, @@ -871,14 +855,6 @@ "webpack>events": true } }, - "@metamask/assets-controllers>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/assets-controllers>@metamask/polling-controller": { "globals": { "clearTimeout": true, @@ -886,19 +862,11 @@ "setTimeout": true }, "packages": { - "@metamask/assets-controllers>@metamask/polling-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/snaps-utils>fast-json-stable-stringify": true, "uuid": true } }, - "@metamask/assets-controllers>@metamask/polling-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/assets-controllers>async-mutex": { "globals": { "setTimeout": true @@ -1007,20 +975,12 @@ "@metamask/ens-controller": { "packages": { "@ethersproject/providers": true, - "@metamask/ens-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/ens-controller>@metamask/controller-utils": true, "@metamask/utils": true, "punycode": true } }, - "@metamask/ens-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/ens-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1543,23 +1503,15 @@ "packages": { "@ethereumjs/tx>@ethereumjs/util": true, "@metamask/assets-controllers>async-mutex": true, + "@metamask/base-controller": true, "@metamask/browser-passworder": true, "@metamask/eth-sig-util": true, - "@metamask/keyring-controller>@metamask/base-controller": true, "@metamask/keyring-controller>@metamask/eth-hd-keyring": true, "@metamask/keyring-controller>@metamask/eth-simple-keyring": true, "@metamask/keyring-controller>ethereumjs-wallet": true, "@metamask/utils": true } }, - "@metamask/keyring-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/keyring-controller>@metamask/eth-hd-keyring": { "globals": { "TextEncoder": true @@ -1629,18 +1581,10 @@ }, "@metamask/logging-controller": { "packages": { - "@metamask/logging-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "uuid": true } }, - "@metamask/logging-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/logo": { "globals": { "addEventListener": true, @@ -1657,8 +1601,8 @@ }, "@metamask/message-manager": { "packages": { - "@metamask/base-controller": true, "@metamask/eth-sig-util": true, + "@metamask/message-manager>@metamask/base-controller": true, "@metamask/message-manager>@metamask/controller-utils": true, "@metamask/message-manager>jsonschema": true, "@metamask/utils": true, @@ -1667,6 +1611,14 @@ "webpack>events": true } }, + "@metamask/message-manager>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/message-manager>@metamask/controller-utils": { "globals": { "URL": true, @@ -1752,10 +1704,10 @@ "setTimeout": true }, "packages": { + "@metamask/base-controller": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/eth-query": true, "@metamask/eth-token-tracker>@metamask/eth-block-tracker": true, - "@metamask/network-controller>@metamask/base-controller": true, "@metamask/network-controller>@metamask/controller-utils": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, @@ -1767,14 +1719,6 @@ "uuid": true } }, - "@metamask/network-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/network-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1881,7 +1825,7 @@ "console.error": true }, "packages": { - "@metamask/permission-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/permission-controller>@metamask/controller-utils": true, "@metamask/permission-controller>nanoid": true, "@metamask/providers>@metamask/rpc-errors": true, @@ -1891,14 +1835,6 @@ "immer": true } }, - "@metamask/permission-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/permission-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1924,37 +1860,21 @@ }, "@metamask/permission-log-controller": { "packages": { - "@metamask/permission-log-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/utils": true } }, - "@metamask/permission-log-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/phishing-controller": { "globals": { "fetch": true }, "packages": { - "@metamask/phishing-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/phishing-controller>@metamask/controller-utils": true, "@metamask/phishing-warning>eth-phishing-detect": true, "punycode": true } }, - "@metamask/phishing-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/phishing-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2081,39 +2001,23 @@ }, "@metamask/queued-request-controller": { "packages": { + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/queued-request-controller>@metamask/base-controller": true, "@metamask/selected-network-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true } }, - "@metamask/queued-request-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/rate-limit-controller": { "globals": { "setTimeout": true }, "packages": { + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/rate-limit-controller>@metamask/base-controller": true, "@metamask/utils": true } }, - "@metamask/rate-limit-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/rpc-methods-flask>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2149,16 +2053,8 @@ }, "@metamask/selected-network-controller": { "packages": { - "@metamask/network-controller>@metamask/swappable-obj-proxy": true, - "@metamask/selected-network-controller>@metamask/base-controller": true - } - }, - "@metamask/selected-network-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true + "@metamask/base-controller": true, + "@metamask/network-controller>@metamask/swappable-obj-proxy": true } }, "@metamask/signature-controller": { @@ -2166,9 +2062,9 @@ "console.info": true }, "packages": { + "@metamask/base-controller": true, "@metamask/logging-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/signature-controller>@metamask/base-controller": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/signature-controller>@metamask/message-manager": true, "@metamask/utils": true, @@ -2177,14 +2073,6 @@ "webpack>events": true } }, - "@metamask/signature-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/signature-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2205,9 +2093,9 @@ }, "@metamask/signature-controller>@metamask/message-manager": { "packages": { + "@metamask/base-controller": true, "@metamask/eth-sig-util": true, "@metamask/message-manager>jsonschema": true, - "@metamask/signature-controller>@metamask/base-controller": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/utils": true, "browserify>buffer": true, @@ -2542,11 +2430,11 @@ "setTimeout": true }, "packages": { + "@metamask/base-controller": true, "@metamask/object-multiplex": true, "@metamask/permission-controller": true, "@metamask/post-message-stream": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/base-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>@metamask/json-rpc-middleware-stream": true, "@metamask/snaps-controllers>@xstate/fsm": true, @@ -2570,14 +2458,6 @@ "crypto.getRandomValues": true } }, - "@metamask/snaps-controllers>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/snaps-controllers>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -2865,11 +2745,11 @@ }, "packages": { "@metamask/assets-controllers>@metamask/polling-controller": true, + "@metamask/base-controller": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/transaction-controller": true, - "@metamask/user-operation-controller>@metamask/base-controller": true, "@metamask/user-operation-controller>@metamask/controller-utils": true, "@metamask/utils": true, "bn.js": true, @@ -2879,14 +2759,6 @@ "webpack>events": true } }, - "@metamask/user-operation-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/user-operation-controller>@metamask/controller-utils": { "globals": { "URL": true, diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 04d1ac777d26..45cb4ea1aadc 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -1053,16 +1053,8 @@ }, "@metamask/address-book-controller": { "packages": { - "@metamask/address-book-controller>@metamask/base-controller": true, - "@metamask/address-book-controller>@metamask/controller-utils": true - } - }, - "@metamask/address-book-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true + "@metamask/address-book-controller>@metamask/controller-utils": true, + "@metamask/base-controller": true } }, "@metamask/address-book-controller>@metamask/controller-utils": { @@ -1085,7 +1077,7 @@ }, "@metamask/announcement-controller": { "packages": { - "@metamask/announcement-controller>@metamask/base-controller": true + "@metamask/base-controller": true } }, "@metamask/announcement-controller>@metamask/base-controller": { @@ -1101,19 +1093,11 @@ "console.info": true }, "packages": { - "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true } }, - "@metamask/approval-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/approval-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1138,11 +1122,11 @@ "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/abi-utils": true, - "@metamask/assets-controllers>@metamask/base-controller": true, "@metamask/assets-controllers>@metamask/polling-controller": true, "@metamask/assets-controllers>async-mutex": true, "@metamask/assets-controllers>cockatiel": true, "@metamask/assets-controllers>multiformats": true, + "@metamask/base-controller": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, @@ -1156,14 +1140,6 @@ "webpack>events": true } }, - "@metamask/assets-controllers>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/assets-controllers>@metamask/polling-controller": { "globals": { "clearTimeout": true, @@ -1171,19 +1147,11 @@ "setTimeout": true }, "packages": { - "@metamask/assets-controllers>@metamask/polling-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/snaps-utils>fast-json-stable-stringify": true, "uuid": true } }, - "@metamask/assets-controllers>@metamask/polling-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/assets-controllers>async-mutex": { "globals": { "setTimeout": true @@ -1292,20 +1260,12 @@ "@metamask/ens-controller": { "packages": { "@ethersproject/providers": true, - "@metamask/ens-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/ens-controller>@metamask/controller-utils": true, "@metamask/utils": true, "punycode": true } }, - "@metamask/ens-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/ens-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1828,23 +1788,15 @@ "packages": { "@ethereumjs/tx>@ethereumjs/util": true, "@metamask/assets-controllers>async-mutex": true, + "@metamask/base-controller": true, "@metamask/browser-passworder": true, "@metamask/eth-sig-util": true, - "@metamask/keyring-controller>@metamask/base-controller": true, "@metamask/keyring-controller>@metamask/eth-hd-keyring": true, "@metamask/keyring-controller>@metamask/eth-simple-keyring": true, "@metamask/keyring-controller>ethereumjs-wallet": true, "@metamask/utils": true } }, - "@metamask/keyring-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/keyring-controller>@metamask/eth-hd-keyring": { "globals": { "TextEncoder": true @@ -1914,18 +1866,10 @@ }, "@metamask/logging-controller": { "packages": { - "@metamask/logging-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "uuid": true } }, - "@metamask/logging-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/logo": { "globals": { "addEventListener": true, @@ -1942,8 +1886,8 @@ }, "@metamask/message-manager": { "packages": { - "@metamask/base-controller": true, "@metamask/eth-sig-util": true, + "@metamask/message-manager>@metamask/base-controller": true, "@metamask/message-manager>@metamask/controller-utils": true, "@metamask/message-manager>jsonschema": true, "@metamask/utils": true, @@ -1952,6 +1896,14 @@ "webpack>events": true } }, + "@metamask/message-manager>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/message-manager>@metamask/controller-utils": { "globals": { "URL": true, @@ -2037,10 +1989,10 @@ "setTimeout": true }, "packages": { + "@metamask/base-controller": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/eth-query": true, "@metamask/eth-token-tracker>@metamask/eth-block-tracker": true, - "@metamask/network-controller>@metamask/base-controller": true, "@metamask/network-controller>@metamask/controller-utils": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, @@ -2052,14 +2004,6 @@ "uuid": true } }, - "@metamask/network-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/network-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2166,7 +2110,7 @@ "console.error": true }, "packages": { - "@metamask/permission-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/permission-controller>@metamask/controller-utils": true, "@metamask/permission-controller>nanoid": true, "@metamask/providers>@metamask/rpc-errors": true, @@ -2176,14 +2120,6 @@ "immer": true } }, - "@metamask/permission-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/permission-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2209,37 +2145,21 @@ }, "@metamask/permission-log-controller": { "packages": { - "@metamask/permission-log-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/utils": true } }, - "@metamask/permission-log-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/phishing-controller": { "globals": { "fetch": true }, "packages": { - "@metamask/phishing-controller>@metamask/base-controller": true, + "@metamask/base-controller": true, "@metamask/phishing-controller>@metamask/controller-utils": true, "@metamask/phishing-warning>eth-phishing-detect": true, "punycode": true } }, - "@metamask/phishing-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/phishing-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2366,39 +2286,23 @@ }, "@metamask/queued-request-controller": { "packages": { + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/queued-request-controller>@metamask/base-controller": true, "@metamask/selected-network-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true } }, - "@metamask/queued-request-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/rate-limit-controller": { "globals": { "setTimeout": true }, "packages": { + "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/rate-limit-controller>@metamask/base-controller": true, "@metamask/utils": true } }, - "@metamask/rate-limit-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/rpc-methods-flask>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2434,16 +2338,8 @@ }, "@metamask/selected-network-controller": { "packages": { - "@metamask/network-controller>@metamask/swappable-obj-proxy": true, - "@metamask/selected-network-controller>@metamask/base-controller": true - } - }, - "@metamask/selected-network-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true + "@metamask/base-controller": true, + "@metamask/network-controller>@metamask/swappable-obj-proxy": true } }, "@metamask/signature-controller": { @@ -2451,9 +2347,9 @@ "console.info": true }, "packages": { + "@metamask/base-controller": true, "@metamask/logging-controller": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/signature-controller>@metamask/base-controller": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/signature-controller>@metamask/message-manager": true, "@metamask/utils": true, @@ -2462,14 +2358,6 @@ "webpack>events": true } }, - "@metamask/signature-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/signature-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2490,9 +2378,9 @@ }, "@metamask/signature-controller>@metamask/message-manager": { "packages": { + "@metamask/base-controller": true, "@metamask/eth-sig-util": true, "@metamask/message-manager>jsonschema": true, - "@metamask/signature-controller>@metamask/base-controller": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/utils": true, "browserify>buffer": true, @@ -2827,11 +2715,11 @@ "setTimeout": true }, "packages": { + "@metamask/base-controller": true, "@metamask/object-multiplex": true, "@metamask/permission-controller": true, "@metamask/post-message-stream": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/base-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>@metamask/json-rpc-middleware-stream": true, "@metamask/snaps-controllers>@xstate/fsm": true, @@ -2855,14 +2743,6 @@ "crypto.getRandomValues": true } }, - "@metamask/snaps-controllers>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/snaps-controllers>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -3150,11 +3030,11 @@ }, "packages": { "@metamask/assets-controllers>@metamask/polling-controller": true, + "@metamask/base-controller": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/transaction-controller": true, - "@metamask/user-operation-controller>@metamask/base-controller": true, "@metamask/user-operation-controller>@metamask/controller-utils": true, "@metamask/utils": true, "bn.js": true, @@ -3164,14 +3044,6 @@ "webpack>events": true } }, - "@metamask/user-operation-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/user-operation-controller>@metamask/controller-utils": { "globals": { "URL": true, diff --git a/package.json b/package.json index 2d9836b3c06e..82fa333fe8e7 100644 --- a/package.json +++ b/package.json @@ -286,7 +286,7 @@ "@metamask/announcement-controller": "^6.1.0", "@metamask/approval-controller": "^6.0.1", "@metamask/assets-controllers": "patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A30.0.0%23~/.yarn/patches/@metamask-assets-controllers-npm-30.0.0-8747c20871.patch%3A%3Aversion=30.0.0&hash=9269c8#~/.yarn/patches/@metamask-assets-controllers-patch-26d4328777.patch", - "@metamask/base-controller": "^4.1.0", + "@metamask/base-controller": "^5.0.1", "@metamask/browser-passworder": "^4.3.0", "@metamask/contract-metadata": "^2.5.0", "@metamask/controller-utils": "^10.0.0", diff --git a/yarn.lock b/yarn.lock index cf50e0a9db6d..f749aeee2391 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4846,7 +4846,7 @@ __metadata: languageName: node linkType: hard -"@metamask/base-controller@npm:^4.1.0, @metamask/base-controller@npm:^4.1.1": +"@metamask/base-controller@npm:^4.1.1": version: 4.1.1 resolution: "@metamask/base-controller@npm:4.1.1" dependencies: @@ -24872,7 +24872,7 @@ __metadata: "@metamask/approval-controller": "npm:^6.0.1" "@metamask/assets-controllers": "patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A30.0.0%23~/.yarn/patches/@metamask-assets-controllers-npm-30.0.0-8747c20871.patch%3A%3Aversion=30.0.0&hash=9269c8#~/.yarn/patches/@metamask-assets-controllers-patch-26d4328777.patch" "@metamask/auto-changelog": "npm:^2.1.0" - "@metamask/base-controller": "npm:^4.1.0" + "@metamask/base-controller": "npm:^5.0.1" "@metamask/browser-passworder": "npm:^4.3.0" "@metamask/build-utils": "npm:^1.0.0" "@metamask/contract-metadata": "npm:^2.5.0" From d8e0cd1f4e67a48200215dc91c9c7c78c62abd2e Mon Sep 17 00:00:00 2001 From: Alex Donesky <adonesky@gmail.com> Date: Wed, 12 Jun 2024 15:39:42 -0500 Subject: [PATCH 24/61] fix: issue where user rejected request errors are not correctly handled in either wallet_switchEthereumChain nor wallet_addEthereumChain calls (#25269) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** A bug was introduced in https://github.com/MetaMask/metamask-extension/pull/24415, where user rejected request errors are not correctly handled in either `wallet_switchEthereumChain` nor `wallet_addEthereumChain` calls. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25269?quickstart=1) ## **Related issues** Fixes: Regression in API error handling found on a local run of [the new API testing tool](https://github.com/MetaMask/metamask-extension/pull/24132), will link report when available. ## **Manual testing steps** **wallet_addEthereumChain** 1. Go to https://docs.metamask.io/wallet/reference/wallet_addethereumchain/ 2. Submit the prepopulated `wallet_addEthereumChain` request 3. Confirm the request to add Gnosis Chain 4. But click "Cancel" on the second request to switch to the newly added chain 5. You should see `null` as the response **wallet_switchEthereumChain** 1. Make sure the wallet is on a chain other than gnosis 2. Go to https://docs.metamask.io/wallet/reference/wallet_switchethereumchain/ 3. Submit the prepopulated switchEthereumChain request (for chainId: 0x64) 4. Click cancel on the request to switch to gnosis chain 5. you should see: ``` { "code": 4001, "message": "User rejected the request.", "stack": "{\n \"code\": 4001,\n \"message\": \"User rejected the request.\",\n \"stack\": \"Error: User rejected the request.\\n } ``` in the response ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../handlers/ethereum-chain-utils.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/app/scripts/lib/rpc-method-middleware/handlers/ethereum-chain-utils.js b/app/scripts/lib/rpc-method-middleware/handlers/ethereum-chain-utils.js index 38e35897d53f..8b10cbb9cd6f 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/ethereum-chain-utils.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/ethereum-chain-utils.js @@ -230,11 +230,19 @@ export async function switchChain( await setActiveNetwork(networkClientId); res.result = null; } catch (error) { - return end( - error.code === errorCodes.provider.userRejectedRequest - ? undefined - : error, - ); + // We don't want to return an error if user rejects the request + // and this is a chained switch request after wallet_addEthereumChain. + // approvalFlowId is only defined when this call is of a + // wallet_addEthereumChain request so we can use it to determine + // if we should return an error + if ( + error.code === errorCodes.provider.userRejectedRequest && + approvalFlowId + ) { + res.result = null; + return end(); + } + return end(error); } finally { if (approvalFlowId) { endApprovalFlow({ id: approvalFlowId }); From dda8d96059a8656f9bfd40460408b1164d45379a Mon Sep 17 00:00:00 2001 From: Derek Brans <dbrans@gmail.com> Date: Wed, 12 Jun 2024 18:04:22 -0400 Subject: [PATCH 25/61] fix: swap+send e2e tests (#25275) --- test/e2e/tests/swap-send/swap-send-erc20.spec.ts | 4 ++-- test/e2e/tests/swap-send/swap-send-eth.spec.ts | 6 +++--- test/e2e/tests/swap-send/swap-send-test-utils.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/e2e/tests/swap-send/swap-send-erc20.spec.ts b/test/e2e/tests/swap-send/swap-send-erc20.spec.ts index 3e2fdc1f7b41..eb20ea18f42d 100644 --- a/test/e2e/tests/swap-send/swap-send-erc20.spec.ts +++ b/test/e2e/tests/swap-send/swap-send-erc20.spec.ts @@ -74,8 +74,8 @@ describe('Swap-Send ERC20', function () { await swapSendPage.verifyQuoteDisplay( '1 TST = 0.000002634 ETH', - '879687 ETH', - '≈ $2,647,857,870.00', + '0.0075669 ETH', + '≈ $22.78', ); await swapSendPage.submitSwap(); diff --git a/test/e2e/tests/swap-send/swap-send-eth.spec.ts b/test/e2e/tests/swap-send/swap-send-eth.spec.ts index f7835af0c332..4622a2000e24 100644 --- a/test/e2e/tests/swap-send/swap-send-eth.spec.ts +++ b/test/e2e/tests/swap-send/swap-send-eth.spec.ts @@ -67,8 +67,8 @@ describe('Swap-Send ETH', function () { await swapSendPage.verifyQuoteDisplay( '1 ETH = 301075.4807 TST', - '1500000 ETH', // TODO this looks weird - '≈ $4,515,000,000.00', + '0.0129028 ETH', + '≈ $38.84', ); await swapSendPage.submitSwap(); @@ -114,7 +114,7 @@ describe('Swap-Send ETH', function () { await swapSendPage.verifyMaxButtonClick( ['ETH', 'ETH'], - ['24.995559472', '24.995559472'], + ['24.9970184730279925', '24.9970184730279925'], ); }, ); diff --git a/test/e2e/tests/swap-send/swap-send-test-utils.ts b/test/e2e/tests/swap-send/swap-send-test-utils.ts index 4140d6bb92be..94e4a8f0a0c9 100644 --- a/test/e2e/tests/swap-send/swap-send-test-utils.ts +++ b/test/e2e/tests/swap-send/swap-send-test-utils.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import { Mockttp } from 'mockttp'; import FixtureBuilder from '../../fixture-builder'; import { SWAPS_API_V2_BASE_URL } from '../../../../shared/constants/swaps'; -import { defaultGanacheOptions } from '../../helpers'; +import { generateGanacheOptions } from '../../helpers'; import { SMART_CONTRACTS } from '../../seeder/smart-contracts'; import { SWAP_SEND_QUOTES_RESPONSE_ETH_TST } from './mocks/eth-data'; @@ -297,7 +297,7 @@ export const getSwapSendFixtures = ( smartContract: SMART_CONTRACTS.HST, ethConversionInUsd: ETH_CONVERSION_RATE_USD, testSpecificMock: mockSwapsApi(swapsQuotes), - ganacheOptions: defaultGanacheOptions, + ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), title, }; }; From 92e6b945eb54fafba491d9a84ca95c2e5fbaf932 Mon Sep 17 00:00:00 2001 From: Alex Donesky <adonesky@gmail.com> Date: Wed, 12 Jun 2024 17:46:48 -0500 Subject: [PATCH 26/61] fix: bump `SelectedNetworkController` to fix issue where selected network domain is incorrectly set (#25106) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Pulls [this fix](https://github.com/MetaMask/core/pull/4388) which adds a guard to the `setNetworkClientIdForDomain` method on the `SelectedNetworkController` to no longer add domains to domains state (nor create a selected network proxy for them) unless the `useRequestQueuePreference` flag is true Bumping the `@metamask/selected-network-controller` version required [bumping peer dependencies](https://github.com/MetaMask/core/blob/main/packages/selected-network-controller/CHANGELOG.md#changed): - `@metamask/network-controller` to v19.0.0 - An existing patch was repointed to this version. - `@metamask/permission-controller` to v10.0.0 -[ This required bumping its own peerDep](https://github.com/MetaMask/core/blob/main/packages/selected-network-controller/CHANGELOG.md#changed) `@metamask/approval-controller` to v7.0.0 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25106?quickstart=1) ## **Related issues** See: https://consensys.slack.com/archives/C1L7H42BT/p1717512150509719 ## **Manual testing steps** 1. Open settings -> experimental and toggle of the `Select networks for each site` setting 2. Go to any site 3. Open the console and execute: ``` await window.ethereum.request({ "method": "eth_chainId", "params": [] }); ``` 4. See that it matches the globally selected network 5. Manually change the network with the network switcher 6. Go back to the site and execute the same `eth_chainId` script 7. See that the result has changed to the chainId you switched to 8. Now execute ``` await window.ethereum.request({ "method": "wallet_requestPermissions", "params": [ { "eth_accounts": {} } ] }); ``` and connect an account to the site 9. Repeat steps 1 - 7 10. The `eth_chainId` results should still match the globally selected network ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> https://github.com/MetaMask/metamask-extension/assets/34557516/ff2f68ff-6ec8-495f-96c1-e938973ce59b ### **After** <!-- [screenshots/recordings] --> https://github.com/MetaMask/metamask-extension/assets/34557516/6061f4e2-faab-48a5-8c55-3b2a4e3aa9f2 ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com> --- ...rk-controller-npm-19.0.0-a5e0d1fe14.patch} | 4 +- lavamoat/browserify/beta/policy.json | 127 ++++++++++++--- lavamoat/browserify/flask/policy.json | 144 +++++++++++++++--- lavamoat/browserify/main/policy.json | 144 +++++++++++++++--- lavamoat/browserify/mmi/policy.json | 144 +++++++++++++++--- package.json | 13 +- yarn.lock | 115 +++++++++----- 7 files changed, 575 insertions(+), 116 deletions(-) rename .yarn/patches/{@metamask-network-controller-npm-18.1.2-1bcb8d8610.patch => @metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch} (86%) diff --git a/.yarn/patches/@metamask-network-controller-npm-18.1.2-1bcb8d8610.patch b/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch similarity index 86% rename from .yarn/patches/@metamask-network-controller-npm-18.1.2-1bcb8d8610.patch rename to .yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch index f4c01d448364..91cbc903b5c6 100644 --- a/.yarn/patches/@metamask-network-controller-npm-18.1.2-1bcb8d8610.patch +++ b/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch @@ -1,5 +1,5 @@ diff --git a/dist/chunk-4ZD3DTQ7.js b/dist/chunk-4ZD3DTQ7.js -index e172d15715b3cb4f26c42e51f8c7ff7394075bfe..148c802bac1d79f784618d18fa61d9de3330cae7 100644 +index e172d15715b3cb4f26c42e51f8c7ff7394075bfe..2c32427d0e005c8db2e4aa524609972fd57cba60 100644 --- a/dist/chunk-4ZD3DTQ7.js +++ b/dist/chunk-4ZD3DTQ7.js @@ -341,7 +341,6 @@ var NetworkController = class extends _basecontroller.BaseController { @@ -11,7 +11,7 @@ index e172d15715b3cb4f26c42e51f8c7ff7394075bfe..148c802bac1d79f784618d18fa61d9de /** * Refreshes the network meta with EIP-1559 support and the network status diff --git a/dist/chunk-UG2NYGJD.mjs b/dist/chunk-UG2NYGJD.mjs -index c39eb49a4a1d2b4ddb78aadb4fb03446b1705528..cd7ce41f31434e66b56f584c177d4952e334e212 100644 +index c39eb49a4a1d2b4ddb78aadb4fb03446b1705528..73f4df206f489036ed52831ac685219074bb768b 100644 --- a/dist/chunk-UG2NYGJD.mjs +++ b/dist/chunk-UG2NYGJD.mjs @@ -341,7 +341,6 @@ var NetworkController = class extends BaseController { diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 9e7e7e655ff4..496eb485f48c 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -808,11 +808,19 @@ "console.info": true }, "packages": { + "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, - "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true } }, + "@metamask/approval-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/approval-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1040,6 +1048,19 @@ "sass-loader>klona": true } }, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": { + "packages": { + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": true, + "@metamask/safe-event-emitter": true + } + }, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/safe-event-emitter": true, + "@metamask/utils": true + } + }, "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -1704,21 +1725,29 @@ "setTimeout": true }, "packages": { - "@metamask/base-controller": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/eth-query": true, "@metamask/eth-token-tracker>@metamask/eth-block-tracker": true, + "@metamask/network-controller>@metamask/base-controller": true, "@metamask/network-controller>@metamask/controller-utils": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, + "@metamask/network-controller>@metamask/json-rpc-engine": true, "@metamask/network-controller>@metamask/swappable-obj-proxy": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true, "browserify>assert": true, "uuid": true } }, + "@metamask/network-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/network-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1742,19 +1771,13 @@ "setTimeout": true }, "packages": { - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": true, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/utils": true, "node-fetch": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": { - "packages": { - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, - "@metamask/safe-event-emitter": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -1764,8 +1787,15 @@ }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { + "@metamask/network-controller>@metamask/json-rpc-engine": true, + "@metamask/safe-event-emitter": true + } + }, + "@metamask/network-controller>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true + "@metamask/utils": true } }, "@metamask/notification-controller>nanoid": { @@ -1798,16 +1828,24 @@ "console.error": true }, "packages": { - "@metamask/base-controller": true, + "@metamask/permission-controller>@metamask/base-controller": true, "@metamask/permission-controller>@metamask/controller-utils": true, + "@metamask/permission-controller>@metamask/json-rpc-engine": true, "@metamask/permission-controller>nanoid": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true, "deep-freeze-strict": true, "immer": true } }, + "@metamask/permission-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/permission-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1826,6 +1864,13 @@ "eth-ens-namehash": true } }, + "@metamask/permission-controller>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/safe-event-emitter": true, + "@metamask/utils": true + } + }, "@metamask/permission-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1964,8 +2009,16 @@ }, "@metamask/selected-network-controller": { "packages": { - "@metamask/base-controller": true, - "@metamask/network-controller>@metamask/swappable-obj-proxy": true + "@metamask/network-controller>@metamask/swappable-obj-proxy": true, + "@metamask/selected-network-controller>@metamask/base-controller": true + } + }, + "@metamask/selected-network-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true } }, "@metamask/signature-controller": { @@ -2358,8 +2411,8 @@ }, "@metamask/snaps-rpc-methods": { "packages": { - "@metamask/permission-controller": true, "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-rpc-methods>@metamask/permission-controller": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, "@metamask/snaps-utils": true, @@ -2368,6 +2421,26 @@ "superstruct": true } }, + "@metamask/snaps-rpc-methods>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, + "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-sdk": { "globals": { "fetch": true @@ -2413,10 +2486,10 @@ "fetch": true }, "packages": { - "@metamask/permission-controller": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, + "@metamask/snaps-utils>@metamask/permission-controller": true, "@metamask/snaps-utils>@metamask/slip44": true, "@metamask/snaps-utils>cron-parser": true, "@metamask/snaps-utils>fast-json-stable-stringify": true, @@ -2431,6 +2504,26 @@ "superstruct": true } }, + "@metamask/snaps-utils>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-utils>@metamask/permission-controller>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, + "@metamask/snaps-utils>@metamask/permission-controller>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-utils>cron-parser": { "packages": { "browserify>browser-resolve": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 24241a5bdac8..87580fa1fabe 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -808,11 +808,19 @@ "console.info": true }, "packages": { + "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, - "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true } }, + "@metamask/approval-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/approval-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1040,6 +1048,19 @@ "sass-loader>klona": true } }, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": { + "packages": { + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": true, + "@metamask/safe-event-emitter": true + } + }, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/safe-event-emitter": true, + "@metamask/utils": true + } + }, "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -1704,21 +1725,29 @@ "setTimeout": true }, "packages": { - "@metamask/base-controller": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/eth-query": true, "@metamask/eth-token-tracker>@metamask/eth-block-tracker": true, + "@metamask/network-controller>@metamask/base-controller": true, "@metamask/network-controller>@metamask/controller-utils": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, + "@metamask/network-controller>@metamask/json-rpc-engine": true, "@metamask/network-controller>@metamask/swappable-obj-proxy": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true, "browserify>assert": true, "uuid": true } }, + "@metamask/network-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/network-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1742,19 +1771,13 @@ "setTimeout": true }, "packages": { - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": true, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/utils": true, "node-fetch": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": { - "packages": { - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, - "@metamask/safe-event-emitter": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -1764,8 +1787,15 @@ }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { + "@metamask/network-controller>@metamask/json-rpc-engine": true, + "@metamask/safe-event-emitter": true + } + }, + "@metamask/network-controller>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true + "@metamask/utils": true } }, "@metamask/notification-controller": { @@ -1825,16 +1855,24 @@ "console.error": true }, "packages": { - "@metamask/base-controller": true, + "@metamask/permission-controller>@metamask/base-controller": true, "@metamask/permission-controller>@metamask/controller-utils": true, + "@metamask/permission-controller>@metamask/json-rpc-engine": true, "@metamask/permission-controller>nanoid": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true, "deep-freeze-strict": true, "immer": true } }, + "@metamask/permission-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/permission-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1853,6 +1891,13 @@ "eth-ens-namehash": true } }, + "@metamask/permission-controller>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/safe-event-emitter": true, + "@metamask/utils": true + } + }, "@metamask/permission-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2053,8 +2098,16 @@ }, "@metamask/selected-network-controller": { "packages": { - "@metamask/base-controller": true, - "@metamask/network-controller>@metamask/swappable-obj-proxy": true + "@metamask/network-controller>@metamask/swappable-obj-proxy": true, + "@metamask/selected-network-controller>@metamask/base-controller": true + } + }, + "@metamask/selected-network-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true } }, "@metamask/signature-controller": { @@ -2432,11 +2485,11 @@ "packages": { "@metamask/base-controller": true, "@metamask/object-multiplex": true, - "@metamask/permission-controller": true, "@metamask/post-message-stream": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>@metamask/json-rpc-middleware-stream": true, + "@metamask/snaps-controllers>@metamask/permission-controller": true, "@metamask/snaps-controllers>@xstate/fsm": true, "@metamask/snaps-controllers>concat-stream": true, "@metamask/snaps-controllers>get-npm-tarball-url": true, @@ -2475,6 +2528,21 @@ "readable-stream": true } }, + "@metamask/snaps-controllers>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-controllers>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, "@metamask/snaps-controllers>concat-stream": { "packages": { "browserify>buffer": true, @@ -2532,8 +2600,8 @@ }, "@metamask/snaps-rpc-methods": { "packages": { - "@metamask/permission-controller": true, "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-rpc-methods>@metamask/permission-controller": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, "@metamask/snaps-utils": true, @@ -2542,6 +2610,26 @@ "superstruct": true } }, + "@metamask/snaps-rpc-methods>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, + "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-sdk": { "globals": { "fetch": true @@ -2587,10 +2675,10 @@ "fetch": true }, "packages": { - "@metamask/permission-controller": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, + "@metamask/snaps-utils>@metamask/permission-controller": true, "@metamask/snaps-utils>@metamask/slip44": true, "@metamask/snaps-utils>cron-parser": true, "@metamask/snaps-utils>fast-json-stable-stringify": true, @@ -2605,6 +2693,26 @@ "superstruct": true } }, + "@metamask/snaps-utils>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-utils>@metamask/permission-controller>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, + "@metamask/snaps-utils>@metamask/permission-controller>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-utils>@metamask/snaps-registry": { "packages": { "@metamask/message-signing-snap>@noble/curves": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 24241a5bdac8..87580fa1fabe 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -808,11 +808,19 @@ "console.info": true }, "packages": { + "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, - "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true } }, + "@metamask/approval-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/approval-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1040,6 +1048,19 @@ "sass-loader>klona": true } }, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": { + "packages": { + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": true, + "@metamask/safe-event-emitter": true + } + }, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/safe-event-emitter": true, + "@metamask/utils": true + } + }, "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -1704,21 +1725,29 @@ "setTimeout": true }, "packages": { - "@metamask/base-controller": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/eth-query": true, "@metamask/eth-token-tracker>@metamask/eth-block-tracker": true, + "@metamask/network-controller>@metamask/base-controller": true, "@metamask/network-controller>@metamask/controller-utils": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, + "@metamask/network-controller>@metamask/json-rpc-engine": true, "@metamask/network-controller>@metamask/swappable-obj-proxy": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true, "browserify>assert": true, "uuid": true } }, + "@metamask/network-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/network-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1742,19 +1771,13 @@ "setTimeout": true }, "packages": { - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": true, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/utils": true, "node-fetch": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": { - "packages": { - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, - "@metamask/safe-event-emitter": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -1764,8 +1787,15 @@ }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { + "@metamask/network-controller>@metamask/json-rpc-engine": true, + "@metamask/safe-event-emitter": true + } + }, + "@metamask/network-controller>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true + "@metamask/utils": true } }, "@metamask/notification-controller": { @@ -1825,16 +1855,24 @@ "console.error": true }, "packages": { - "@metamask/base-controller": true, + "@metamask/permission-controller>@metamask/base-controller": true, "@metamask/permission-controller>@metamask/controller-utils": true, + "@metamask/permission-controller>@metamask/json-rpc-engine": true, "@metamask/permission-controller>nanoid": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true, "deep-freeze-strict": true, "immer": true } }, + "@metamask/permission-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/permission-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -1853,6 +1891,13 @@ "eth-ens-namehash": true } }, + "@metamask/permission-controller>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/safe-event-emitter": true, + "@metamask/utils": true + } + }, "@metamask/permission-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2053,8 +2098,16 @@ }, "@metamask/selected-network-controller": { "packages": { - "@metamask/base-controller": true, - "@metamask/network-controller>@metamask/swappable-obj-proxy": true + "@metamask/network-controller>@metamask/swappable-obj-proxy": true, + "@metamask/selected-network-controller>@metamask/base-controller": true + } + }, + "@metamask/selected-network-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true } }, "@metamask/signature-controller": { @@ -2432,11 +2485,11 @@ "packages": { "@metamask/base-controller": true, "@metamask/object-multiplex": true, - "@metamask/permission-controller": true, "@metamask/post-message-stream": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>@metamask/json-rpc-middleware-stream": true, + "@metamask/snaps-controllers>@metamask/permission-controller": true, "@metamask/snaps-controllers>@xstate/fsm": true, "@metamask/snaps-controllers>concat-stream": true, "@metamask/snaps-controllers>get-npm-tarball-url": true, @@ -2475,6 +2528,21 @@ "readable-stream": true } }, + "@metamask/snaps-controllers>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-controllers>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, "@metamask/snaps-controllers>concat-stream": { "packages": { "browserify>buffer": true, @@ -2532,8 +2600,8 @@ }, "@metamask/snaps-rpc-methods": { "packages": { - "@metamask/permission-controller": true, "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-rpc-methods>@metamask/permission-controller": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, "@metamask/snaps-utils": true, @@ -2542,6 +2610,26 @@ "superstruct": true } }, + "@metamask/snaps-rpc-methods>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, + "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-sdk": { "globals": { "fetch": true @@ -2587,10 +2675,10 @@ "fetch": true }, "packages": { - "@metamask/permission-controller": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, + "@metamask/snaps-utils>@metamask/permission-controller": true, "@metamask/snaps-utils>@metamask/slip44": true, "@metamask/snaps-utils>cron-parser": true, "@metamask/snaps-utils>fast-json-stable-stringify": true, @@ -2605,6 +2693,26 @@ "superstruct": true } }, + "@metamask/snaps-utils>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-utils>@metamask/permission-controller>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, + "@metamask/snaps-utils>@metamask/permission-controller>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-utils>@metamask/snaps-registry": { "packages": { "@metamask/message-signing-snap>@noble/curves": true, diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 45cb4ea1aadc..875d9fced807 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -1093,11 +1093,19 @@ "console.info": true }, "packages": { + "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, - "@metamask/base-controller": true, "@metamask/providers>@metamask/rpc-errors": true } }, + "@metamask/approval-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/approval-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1325,6 +1333,19 @@ "sass-loader>klona": true } }, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": { + "packages": { + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": true, + "@metamask/safe-event-emitter": true + } + }, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/safe-event-emitter": true, + "@metamask/utils": true + } + }, "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -1989,21 +2010,29 @@ "setTimeout": true }, "packages": { - "@metamask/base-controller": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/eth-query": true, "@metamask/eth-token-tracker>@metamask/eth-block-tracker": true, + "@metamask/network-controller>@metamask/base-controller": true, "@metamask/network-controller>@metamask/controller-utils": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, + "@metamask/network-controller>@metamask/json-rpc-engine": true, "@metamask/network-controller>@metamask/swappable-obj-proxy": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true, "browserify>assert": true, "uuid": true } }, + "@metamask/network-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/network-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2027,19 +2056,13 @@ "setTimeout": true }, "packages": { - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": true, + "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/utils": true, "node-fetch": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": { - "packages": { - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, - "@metamask/safe-event-emitter": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": { "packages": { "@metamask/providers>@metamask/rpc-errors": true, @@ -2049,8 +2072,15 @@ }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { + "@metamask/network-controller>@metamask/json-rpc-engine": true, + "@metamask/safe-event-emitter": true + } + }, + "@metamask/network-controller>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true + "@metamask/utils": true } }, "@metamask/notification-controller": { @@ -2110,16 +2140,24 @@ "console.error": true }, "packages": { - "@metamask/base-controller": true, + "@metamask/permission-controller>@metamask/base-controller": true, "@metamask/permission-controller>@metamask/controller-utils": true, + "@metamask/permission-controller>@metamask/json-rpc-engine": true, "@metamask/permission-controller>nanoid": true, "@metamask/providers>@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true, "deep-freeze-strict": true, "immer": true } }, + "@metamask/permission-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true + } + }, "@metamask/permission-controller>@metamask/controller-utils": { "globals": { "URL": true, @@ -2138,6 +2176,13 @@ "eth-ens-namehash": true } }, + "@metamask/permission-controller>@metamask/json-rpc-engine": { + "packages": { + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/safe-event-emitter": true, + "@metamask/utils": true + } + }, "@metamask/permission-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2338,8 +2383,16 @@ }, "@metamask/selected-network-controller": { "packages": { - "@metamask/base-controller": true, - "@metamask/network-controller>@metamask/swappable-obj-proxy": true + "@metamask/network-controller>@metamask/swappable-obj-proxy": true, + "@metamask/selected-network-controller>@metamask/base-controller": true + } + }, + "@metamask/selected-network-controller>@metamask/base-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "immer": true } }, "@metamask/signature-controller": { @@ -2717,11 +2770,11 @@ "packages": { "@metamask/base-controller": true, "@metamask/object-multiplex": true, - "@metamask/permission-controller": true, "@metamask/post-message-stream": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>@metamask/json-rpc-middleware-stream": true, + "@metamask/snaps-controllers>@metamask/permission-controller": true, "@metamask/snaps-controllers>@xstate/fsm": true, "@metamask/snaps-controllers>concat-stream": true, "@metamask/snaps-controllers>get-npm-tarball-url": true, @@ -2760,6 +2813,21 @@ "readable-stream": true } }, + "@metamask/snaps-controllers>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-controllers>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, "@metamask/snaps-controllers>concat-stream": { "packages": { "browserify>buffer": true, @@ -2817,8 +2885,8 @@ }, "@metamask/snaps-rpc-methods": { "packages": { - "@metamask/permission-controller": true, "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-rpc-methods>@metamask/permission-controller": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, "@metamask/snaps-utils": true, @@ -2827,6 +2895,26 @@ "superstruct": true } }, + "@metamask/snaps-rpc-methods>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, + "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-sdk": { "globals": { "fetch": true @@ -2872,10 +2960,10 @@ "fetch": true }, "packages": { - "@metamask/permission-controller": true, "@metamask/providers>@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, + "@metamask/snaps-utils>@metamask/permission-controller": true, "@metamask/snaps-utils>@metamask/slip44": true, "@metamask/snaps-utils>cron-parser": true, "@metamask/snaps-utils>fast-json-stable-stringify": true, @@ -2890,6 +2978,26 @@ "superstruct": true } }, + "@metamask/snaps-utils>@metamask/permission-controller": { + "globals": { + "console.error": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/controller-utils": true, + "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, + "@metamask/snaps-utils>@metamask/permission-controller>nanoid": true, + "@metamask/utils": true, + "deep-freeze-strict": true, + "immer": true + } + }, + "@metamask/snaps-utils>@metamask/permission-controller>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-utils>@metamask/snaps-registry": { "packages": { "@metamask/message-signing-snap>@noble/curves": true, diff --git a/package.json b/package.json index 82fa333fe8e7..41e2dbc4cec4 100644 --- a/package.json +++ b/package.json @@ -252,8 +252,9 @@ "sucrase@npm:3.34.0": "^3.35.0", "@expo/config/glob": "^10.3.10", "@expo/config-plugins/glob": "^10.3.10", - "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A18.1.2#~/.yarn/patches/@metamask-network-controller-npm-18.1.2-1bcb8d8610.patch", - "@solana/web3.js/rpc-websockets": "^8.0.1" + "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch", + "@solana/web3.js/rpc-websockets": "^8.0.1", + "@metamask/network-controller@npm:^19.0.0": "patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch" }, "dependencies": { "@babel/runtime": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch", @@ -284,7 +285,7 @@ "@metamask/accounts-controller": "^16.0.0", "@metamask/address-book-controller": "^4.0.1", "@metamask/announcement-controller": "^6.1.0", - "@metamask/approval-controller": "^6.0.1", + "@metamask/approval-controller": "^7.0.0", "@metamask/assets-controllers": "patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A30.0.0%23~/.yarn/patches/@metamask-assets-controllers-npm-30.0.0-8747c20871.patch%3A%3Aversion=30.0.0&hash=9269c8#~/.yarn/patches/@metamask-assets-controllers-patch-26d4328777.patch", "@metamask/base-controller": "^5.0.1", "@metamask/browser-passworder": "^4.3.0", @@ -314,11 +315,11 @@ "@metamask/message-signing-snap": "^0.3.3", "@metamask/metamask-eth-abis": "^3.1.1", "@metamask/name-controller": "^8.0.0", - "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A18.1.2#~/.yarn/patches/@metamask-network-controller-npm-18.1.2-1bcb8d8610.patch", + "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch", "@metamask/notification-controller": "^3.0.0", "@metamask/object-multiplex": "^2.0.0", "@metamask/obs-store": "^9.0.0", - "@metamask/permission-controller": "^9.1.0", + "@metamask/permission-controller": "^10.0.0", "@metamask/permission-log-controller": "^2.0.1", "@metamask/phishing-controller": "^9.0.3", "@metamask/post-message-stream": "^8.0.0", @@ -328,7 +329,7 @@ "@metamask/rate-limit-controller": "^5.0.1", "@metamask/safe-event-emitter": "^3.1.1", "@metamask/scure-bip39": "^2.0.3", - "@metamask/selected-network-controller": "^13.0.0", + "@metamask/selected-network-controller": "^15.0.2", "@metamask/signature-controller": "^14.0.1", "@metamask/smart-transactions-controller": "^10.1.2", "@metamask/snaps-controllers": "^8.4.0", diff --git a/yarn.lock b/yarn.lock index f749aeee2391..5f7759c93188 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5155,6 +5155,17 @@ __metadata: languageName: node linkType: hard +"@metamask/eth-json-rpc-provider@npm:^4.0.0": + version: 4.0.0 + resolution: "@metamask/eth-json-rpc-provider@npm:4.0.0" + dependencies: + "@metamask/json-rpc-engine": "npm:^9.0.0" + "@metamask/safe-event-emitter": "npm:^3.0.0" + "@metamask/utils": "npm:^8.3.0" + checksum: 10/00e87f5d70e044d3dfe7a62ae8c3b530e92dea91de2ad921dee00cd3307fbb1444c5441a05f6178aaf81e3b11f6feeccaa4a8683edf058bf7769c00efeb8915a + languageName: node + linkType: hard + "@metamask/eth-ledger-bridge-keyring@npm:^2.0.1": version: 2.0.1 resolution: "@metamask/eth-ledger-bridge-keyring@npm:2.0.1" @@ -5471,6 +5482,17 @@ __metadata: languageName: node linkType: hard +"@metamask/json-rpc-engine@npm:^9.0.0": + version: 9.0.0 + resolution: "@metamask/json-rpc-engine@npm:9.0.0" + dependencies: + "@metamask/rpc-errors": "npm:^6.2.1" + "@metamask/safe-event-emitter": "npm:^3.0.0" + "@metamask/utils": "npm:^8.3.0" + checksum: 10/9ddde2ca81e3b3a70e0cc752b5e22e436723cafa1948cbb45d63a42796a1260ff0f9356ebda0d375d9aae81232e77e487a8d0e1273aed3aa83ca0fe3e2f2763f + languageName: node + linkType: hard + "@metamask/json-rpc-middleware-stream@npm:^7.0.1": version: 7.0.1 resolution: "@metamask/json-rpc-middleware-stream@npm:7.0.1" @@ -5675,47 +5697,47 @@ __metadata: languageName: node linkType: hard -"@metamask/network-controller@npm:18.1.2": - version: 18.1.2 - resolution: "@metamask/network-controller@npm:18.1.2" +"@metamask/network-controller@npm:19.0.0": + version: 19.0.0 + resolution: "@metamask/network-controller@npm:19.0.0" dependencies: - "@metamask/base-controller": "npm:^5.0.2" - "@metamask/controller-utils": "npm:^9.1.0" + "@metamask/base-controller": "npm:^6.0.0" + "@metamask/controller-utils": "npm:^11.0.0" "@metamask/eth-block-tracker": "npm:^9.0.2" "@metamask/eth-json-rpc-infura": "npm:^9.1.0" "@metamask/eth-json-rpc-middleware": "npm:^12.1.1" - "@metamask/eth-json-rpc-provider": "npm:^3.0.2" + "@metamask/eth-json-rpc-provider": "npm:^4.0.0" "@metamask/eth-query": "npm:^4.0.0" - "@metamask/json-rpc-engine": "npm:^8.0.2" + "@metamask/json-rpc-engine": "npm:^9.0.0" "@metamask/rpc-errors": "npm:^6.2.1" "@metamask/swappable-obj-proxy": "npm:^2.2.0" "@metamask/utils": "npm:^8.3.0" - async-mutex: "npm:^0.2.6" + async-mutex: "npm:^0.5.0" immer: "npm:^9.0.6" uuid: "npm:^8.3.2" - checksum: 10/546829c5d24fa64aa2cae2e7b5f29edf4acb12e1367d7ae92ca30e2b1f56b79d53c4d069bc671029d06b0105eec3581204bcedcdf88896aacb38f7cc0e014cf8 + checksum: 10/d23c1c18ad909876ca5e6080f97ed982688fefbe0bfe3878897d094b7b0cf81b49a8166a7352aa051619967fb1b29179c5dae69cd0666ecef02827a8ce78bb64 languageName: node linkType: hard -"@metamask/network-controller@patch:@metamask/network-controller@npm%3A18.1.2#~/.yarn/patches/@metamask-network-controller-npm-18.1.2-1bcb8d8610.patch": - version: 18.1.2 - resolution: "@metamask/network-controller@patch:@metamask/network-controller@npm%3A18.1.2#~/.yarn/patches/@metamask-network-controller-npm-18.1.2-1bcb8d8610.patch::version=18.1.2&hash=b6da0e" +"@metamask/network-controller@patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch": + version: 19.0.0 + resolution: "@metamask/network-controller@patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch::version=19.0.0&hash=50b9c4" dependencies: - "@metamask/base-controller": "npm:^5.0.2" - "@metamask/controller-utils": "npm:^9.1.0" + "@metamask/base-controller": "npm:^6.0.0" + "@metamask/controller-utils": "npm:^11.0.0" "@metamask/eth-block-tracker": "npm:^9.0.2" "@metamask/eth-json-rpc-infura": "npm:^9.1.0" "@metamask/eth-json-rpc-middleware": "npm:^12.1.1" - "@metamask/eth-json-rpc-provider": "npm:^3.0.2" + "@metamask/eth-json-rpc-provider": "npm:^4.0.0" "@metamask/eth-query": "npm:^4.0.0" - "@metamask/json-rpc-engine": "npm:^8.0.2" + "@metamask/json-rpc-engine": "npm:^9.0.0" "@metamask/rpc-errors": "npm:^6.2.1" "@metamask/swappable-obj-proxy": "npm:^2.2.0" "@metamask/utils": "npm:^8.3.0" - async-mutex: "npm:^0.2.6" + async-mutex: "npm:^0.5.0" immer: "npm:^9.0.6" uuid: "npm:^8.3.2" - checksum: 10/f34e01544573763be68b5e7833b98bc136366a2e8b192ac242e5ee965d3e6ada734c93a5abb32670c75de60c929ad4e922e539918fef9991663b6a13aa697b5b + checksum: 10/fba2ac9e828336a31c9d6b4d04258bd0e9d9a903a75172b2722e42d8d768a2d7fb635792e9cc93089a5d231002d5ded061299e135656ff32351de80292f1b42e languageName: node linkType: hard @@ -5793,12 +5815,31 @@ __metadata: languageName: node linkType: hard -"@metamask/permission-controller@npm:^9.0.2, @metamask/permission-controller@npm:^9.1.0": - version: 9.1.0 - resolution: "@metamask/permission-controller@npm:9.1.0" +"@metamask/permission-controller@npm:^10.0.0": + version: 10.0.0 + resolution: "@metamask/permission-controller@npm:10.0.0" + dependencies: + "@metamask/base-controller": "npm:^6.0.0" + "@metamask/controller-utils": "npm:^11.0.0" + "@metamask/json-rpc-engine": "npm:^9.0.0" + "@metamask/rpc-errors": "npm:^6.2.1" + "@metamask/utils": "npm:^8.3.0" + "@types/deep-freeze-strict": "npm:^1.1.0" + deep-freeze-strict: "npm:^1.1.1" + immer: "npm:^9.0.6" + nanoid: "npm:^3.1.31" + peerDependencies: + "@metamask/approval-controller": ^7.0.0 + checksum: 10/0c72e205be760fc471b2a6892a9ad52d5c6a40b4cf1757464e992a5ada2dec57efbb24b09351ce8c29990b59f1d731cd2b338caaef37ce7690ea2d1919afe061 + languageName: node + linkType: hard + +"@metamask/permission-controller@npm:^9.0.2": + version: 9.1.1 + resolution: "@metamask/permission-controller@npm:9.1.1" dependencies: "@metamask/base-controller": "npm:^5.0.2" - "@metamask/controller-utils": "npm:^9.1.0" + "@metamask/controller-utils": "npm:^10.0.0" "@metamask/json-rpc-engine": "npm:^8.0.2" "@metamask/rpc-errors": "npm:^6.2.1" "@metamask/utils": "npm:^8.3.0" @@ -5808,7 +5849,7 @@ __metadata: nanoid: "npm:^3.1.31" peerDependencies: "@metamask/approval-controller": ^6.0.0 - checksum: 10/bfae4c16cbe5b180b00ef029c3fa8d7f770247dfad4c0afc11822f4b0bd36373d6f749ac5507f23cf5dbd848096fa86ad2546be190c665c419cae58fcf0d7f00 + checksum: 10/15b276863c8917779e6fa3aaa7df1cdc4e2342eb0f9a1cf75c84688bdc6ac63772315f8a2dbed68a3fa882e1d23dc61990d7c2308972f40c8241700b21f11677 languageName: node linkType: hard @@ -6038,20 +6079,20 @@ __metadata: languageName: node linkType: hard -"@metamask/selected-network-controller@npm:^13.0.0": - version: 13.0.0 - resolution: "@metamask/selected-network-controller@npm:13.0.0" +"@metamask/selected-network-controller@npm:^15.0.2": + version: 15.0.2 + resolution: "@metamask/selected-network-controller@npm:15.0.2" dependencies: - "@metamask/base-controller": "npm:^5.0.2" - "@metamask/json-rpc-engine": "npm:^8.0.2" - "@metamask/network-controller": "npm:^18.1.0" - "@metamask/permission-controller": "npm:^9.0.2" + "@metamask/base-controller": "npm:^6.0.0" + "@metamask/json-rpc-engine": "npm:^9.0.0" + "@metamask/network-controller": "npm:^19.0.0" + "@metamask/permission-controller": "npm:^10.0.0" "@metamask/swappable-obj-proxy": "npm:^2.2.0" "@metamask/utils": "npm:^8.3.0" peerDependencies: - "@metamask/network-controller": ^18.0.0 - "@metamask/permission-controller": ^9.0.0 - checksum: 10/bebb6798ea9b7f12535f1997b69ef4aa7669c245566dfbb8c6729d9e497c8a0dc52ddd42db09defc6acba3ea82d2eaddead149f05ce4730bc4096eae0cb71750 + "@metamask/network-controller": ^19.0.0 + "@metamask/permission-controller": ^10.0.0 + checksum: 10/8acf158801cb7657f4a01f0f5cdad67fbafc627f07b1c4728b403e1bd805684e13e478ac6e70ce4f772b5e08b049d895354ab2fa78eb5f2ee6a5c27bdc151298 languageName: node linkType: hard @@ -24869,7 +24910,7 @@ __metadata: "@metamask/accounts-controller": "npm:^16.0.0" "@metamask/address-book-controller": "npm:^4.0.1" "@metamask/announcement-controller": "npm:^6.1.0" - "@metamask/approval-controller": "npm:^6.0.1" + "@metamask/approval-controller": "npm:^7.0.0" "@metamask/assets-controllers": "patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A30.0.0%23~/.yarn/patches/@metamask-assets-controllers-npm-30.0.0-8747c20871.patch%3A%3Aversion=30.0.0&hash=9269c8#~/.yarn/patches/@metamask-assets-controllers-patch-26d4328777.patch" "@metamask/auto-changelog": "npm:^2.1.0" "@metamask/base-controller": "npm:^5.0.1" @@ -24908,11 +24949,11 @@ __metadata: "@metamask/message-signing-snap": "npm:^0.3.3" "@metamask/metamask-eth-abis": "npm:^3.1.1" "@metamask/name-controller": "npm:^8.0.0" - "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A18.1.2#~/.yarn/patches/@metamask-network-controller-npm-18.1.2-1bcb8d8610.patch" + "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch" "@metamask/notification-controller": "npm:^3.0.0" "@metamask/object-multiplex": "npm:^2.0.0" "@metamask/obs-store": "npm:^9.0.0" - "@metamask/permission-controller": "npm:^9.1.0" + "@metamask/permission-controller": "npm:^10.0.0" "@metamask/permission-log-controller": "npm:^2.0.1" "@metamask/phishing-controller": "npm:^9.0.3" "@metamask/phishing-warning": "npm:^3.0.3" @@ -24923,7 +24964,7 @@ __metadata: "@metamask/rate-limit-controller": "npm:^5.0.1" "@metamask/safe-event-emitter": "npm:^3.1.1" "@metamask/scure-bip39": "npm:^2.0.3" - "@metamask/selected-network-controller": "npm:^13.0.0" + "@metamask/selected-network-controller": "npm:^15.0.2" "@metamask/signature-controller": "npm:^14.0.1" "@metamask/smart-transactions-controller": "npm:^10.1.2" "@metamask/snaps-controllers": "npm:^8.4.0" From bb71b24c78029889b8604ea2fe4bb06c3b755de9 Mon Sep 17 00:00:00 2001 From: Danica Shen <zhaodanica@gmail.com> Date: Thu, 13 Jun 2024 03:13:45 +0100 Subject: [PATCH 27/61] fix: fix typo in pre-build-mv2 and changed value of ENABLE_CONFIRMATION_REDESIGN (#25258) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Small fix for `pre-build-mv2` description and `ENABLE_CONFIRMATION_REDESIGN` value in circle ci <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25258?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2c583ad09cad..5c7c21d65b31 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -568,10 +568,10 @@ jobs: name: build:debug command: find dist/ -type f -exec md5sum {} \; | sort -k 2 - run: - name: Move mmi build to 'dist-mv2' to avoid conflict with production build + name: Move mm build to 'dist-mv2' to avoid conflict with production build command: mv ./dist ./dist-mv2 - run: - name: Move mmi zips to 'builds-mv2' to avoid conflict with production build + name: Move mm zips to 'builds-mv2' to avoid conflict with production build command: mv ./builds ./builds-mv2 - store_artifacts: path: builds-mv2 @@ -859,7 +859,7 @@ jobs: at: . - run: name: Build extension for testing - command: ENABLE_CONFIRMATION_REDESIGN=1 yarn build:test + command: ENABLE_CONFIRMATION_REDESIGN=true yarn build:test - run: name: Move test build to 'dist-test' to avoid conflict with production build command: mv ./dist ./dist-test-confirmations @@ -881,7 +881,7 @@ jobs: at: . - run: name: Build extension for testing - command: ENABLE_CONFIRMATION_REDESIGN=1 yarn build:test:mv2 + command: ENABLE_CONFIRMATION_REDESIGN=true yarn build:test:mv2 - run: name: Move test build to 'dist-test-confirmations-mv2' to avoid conflict with production build command: mv ./dist ./dist-test-confirmations-mv2 @@ -1086,7 +1086,7 @@ jobs: fi no_output_timeout: 5m environment: - ENABLE_CONFIRMATION_REDESIGN: 1 + ENABLE_CONFIRMATION_REDESIGN: true - store_artifacts: path: test-artifacts destination: test-artifacts @@ -1372,7 +1372,7 @@ jobs: fi no_output_timeout: 5m environment: - ENABLE_CONFIRMATION_REDESIGN: 1 + ENABLE_CONFIRMATION_REDESIGN: true - store_artifacts: path: test-artifacts destination: test-artifacts From 59a805a4e42ef3584809aea07f37fb485bc287e6 Mon Sep 17 00:00:00 2001 From: Jyoti Puri <jyotipuri@gmail.com> Date: Thu, 13 Jun 2024 11:29:03 +0530 Subject: [PATCH 28/61] fix: Simulations on signature pages should be displayed only if preference is enabled (#25186) --- .../info/personal-sign/personal-sign.test.tsx | 7 ++++++- .../info/personal-sign/personal-sign.tsx | 6 +++++- .../info/typed-sign/typed-sign.test.tsx | 6 +++++- .../confirm/info/typed-sign/typed-sign.tsx | 6 +++++- .../selectors/preferences.test.ts | 19 +++++++++++++++++++ .../confirmations/selectors/preferences.ts | 8 ++++++++ 6 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 ui/pages/confirmations/selectors/preferences.test.ts create mode 100644 ui/pages/confirmations/selectors/preferences.ts diff --git a/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.test.tsx b/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.test.tsx index 92c3393b3bc1..67cabe3f667f 100644 --- a/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.test.tsx +++ b/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.test.tsx @@ -24,6 +24,7 @@ describe('PersonalSignInfo', () => { it('does not render if required data is not present in the transaction', () => { const state = { + ...mockState, confirm: { currentConfirmation: { id: '0050d5b0-c023-11ee-a0cb-3390a510a0ab', @@ -74,9 +75,13 @@ describe('PersonalSignInfo', () => { expect(getByText('Signing in with')).toBeDefined(); }); - it('display simulation for SIWE request', () => { + it('display simulation for SIWE request if preference useTransactionSimulations is enabled', () => { const state = { ...mockState, + metamask: { + ...mockState.metamask, + useTransactionSimulations: true, + }, confirm: { currentConfirmation: signatureRequestSIWE, }, diff --git a/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.tsx b/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.tsx index e9decf94e752..2fc34a299182 100644 --- a/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.tsx +++ b/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.tsx @@ -19,6 +19,7 @@ import { sanitizeString, } from '../../../../../../helpers/utils/util'; import { SignatureRequestType } from '../../../../types/confirm'; +import { selectUseTransactionSimulations } from '../../../../selectors/preferences'; import { isSIWESignatureRequest } from '../../../../utils'; import { AlertRow } from '../../../../../../components/app/confirm/info/row/alert-row/alert-row'; @@ -27,6 +28,9 @@ const PersonalSignInfo: React.FC = () => { const currentConfirmation = useSelector( currentConfirmationSelector, ) as SignatureRequestType; + const useTransactionSimulations = useSelector( + selectUseTransactionSimulations, + ); if (!currentConfirmation?.msgParams) { return null; @@ -37,7 +41,7 @@ const PersonalSignInfo: React.FC = () => { return ( <> - {isSiweSigReq && ( + {isSiweSigReq && useTransactionSimulations && ( <Box backgroundColor={BackgroundColor.backgroundDefault} borderRadius={BorderRadius.MD} diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx index dd6782af6644..4d64d3a38f28 100644 --- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx @@ -64,9 +64,13 @@ describe('TypedSignInfo', () => { expect(container).toMatchSnapshot(); }); - it('display simulation details for permit signature', () => { + it('display simulation details for permit signature if flag useTransactionSimulations is set', () => { const state = { ...mockState, + metamask: { + ...mockState.metamask, + useTransactionSimulations: true, + }, confirm: { currentConfirmation: permitSignatureMsg, }, diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx index 12faf4d3816a..766ef740e952 100644 --- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx @@ -18,6 +18,7 @@ import { } from '../../../../../../helpers/constants/design-system'; import { SignatureRequestType } from '../../../../types/confirm'; import { isPermitSignatureRequest } from '../../../../utils'; +import { selectUseTransactionSimulations } from '../../../../selectors/preferences'; import { ConfirmInfoRowTypedSignData } from '../../row/typed-sign-data/typedSignData'; import { PermitSimulation } from './permit-simulation'; @@ -26,6 +27,9 @@ const TypedSignInfo: React.FC = () => { const currentConfirmation = useSelector( currentConfirmationSelector, ) as SignatureRequestType; + const useTransactionSimulations = useSelector( + selectUseTransactionSimulations, + ); if (!currentConfirmation?.msgParams) { return null; @@ -40,7 +44,7 @@ const TypedSignInfo: React.FC = () => { return ( <> - {isPermit && <PermitSimulation />} + {isPermit && useTransactionSimulations && <PermitSimulation />} <Box backgroundColor={BackgroundColor.backgroundDefault} borderRadius={BorderRadius.MD} diff --git a/ui/pages/confirmations/selectors/preferences.test.ts b/ui/pages/confirmations/selectors/preferences.test.ts new file mode 100644 index 000000000000..58b1e3e264c4 --- /dev/null +++ b/ui/pages/confirmations/selectors/preferences.test.ts @@ -0,0 +1,19 @@ +import { selectUseTransactionSimulations } from './preferences'; + +describe('preference selectors', () => { + describe('getUseTransactionSimulations', () => { + it('returns value of useTransactionSimulations from state', () => { + const result = selectUseTransactionSimulations({ + metamask: { + useTransactionSimulations: true, + }, + }); + expect(result).toStrictEqual(true); + }); + + it('returns undefined if useTransactionSimulations is not set', () => { + const result = selectUseTransactionSimulations({ metamask: {} }); + expect(result).toStrictEqual(undefined); + }); + }); +}); diff --git a/ui/pages/confirmations/selectors/preferences.ts b/ui/pages/confirmations/selectors/preferences.ts new file mode 100644 index 000000000000..f50b958d19b1 --- /dev/null +++ b/ui/pages/confirmations/selectors/preferences.ts @@ -0,0 +1,8 @@ +export type RootState = { + metamask: { + useTransactionSimulations?: boolean; + }; +}; + +export const selectUseTransactionSimulations = (state: RootState) => + state.metamask.useTransactionSimulations; From 453b2b545ba394fe2352e58b8da197ab763101f3 Mon Sep 17 00:00:00 2001 From: Prithpal Sooriya <prithpal.sooriya@gmail.com> Date: Thu, 13 Jun 2024 11:18:28 +0100 Subject: [PATCH 29/61] fix: notification dates edge case (#25148) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Due to manual date comparisons, there were some weirdness with the dates displayed (such as a notification yesterday, but not 24 hours ago). This fix (using date built-ins) ensures correct notification dates. NOTE - need to port this on other platforms. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25148?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- ui/helpers/utils/notification.util.ts | 48 ++++++++-- ui/helpers/utils/notification.utils.test.ts | 97 +++++++++++++++++---- 2 files changed, 123 insertions(+), 22 deletions(-) diff --git a/ui/helpers/utils/notification.util.ts b/ui/helpers/utils/notification.util.ts index 31be80d4d8de..598936820a01 100644 --- a/ui/helpers/utils/notification.util.ts +++ b/ui/helpers/utils/notification.util.ts @@ -27,6 +27,41 @@ import { decimalToHex, } from '../../../shared/modules/conversion.utils'; +/** + * Checks if 2 date objects are on the same day + * + * @param currentDate + * @param dateToCheck + * @returns boolean if dates are same day. + */ +const isSameDay = (currentDate: Date, dateToCheck: Date) => + currentDate.getFullYear() === dateToCheck.getFullYear() && + currentDate.getMonth() === dateToCheck.getMonth() && + currentDate.getDate() === dateToCheck.getDate(); + +/** + * Checks if a date is "yesterday" from the current date + * + * @param currentDate + * @param dateToCheck + * @returns boolean if dates were "yesterday" + */ +const isYesterday = (currentDate: Date, dateToCheck: Date) => { + const yesterday = new Date(currentDate); + yesterday.setDate(currentDate.getDate() - 1); + return isSameDay(yesterday, dateToCheck); +}; + +/** + * Checks if 2 date objects are in the same year. + * + * @param currentDate + * @param dateToCheck + * @returns boolean if dates were in same year + */ +const isSameYear = (currentDate: Date, dateToCheck: Date) => + currentDate.getFullYear() === dateToCheck.getFullYear(); + /** * Formats a given date into different formats based on how much time has elapsed since that date. * @@ -34,11 +69,10 @@ import { * @returns The formatted date. */ export function formatMenuItemDate(date: Date) { - const elapsed = Math.abs(Date.now() - date.getTime()); - const diffDays = elapsed / (1000 * 60 * 60 * 24); + const currentDate = new Date(); - // E.g. Yesterday - if (diffDays < 1) { + // E.g. 12:21 + if (isSameDay(currentDate, date)) { return new Intl.DateTimeFormat('en', { hour: 'numeric', minute: 'numeric', @@ -46,8 +80,8 @@ export function formatMenuItemDate(date: Date) { }).format(date); } - // E.g. 12:21 - if (Math.floor(diffDays) === 1) { + // E.g. Yesterday + if (isYesterday(currentDate, date)) { return new Intl.RelativeTimeFormat('en', { numeric: 'auto' }).format( -1, 'day', @@ -55,7 +89,7 @@ export function formatMenuItemDate(date: Date) { } // E.g. 21 Oct - if (diffDays > 1 && diffDays < 365) { + if (isSameYear(currentDate, date)) { return new Intl.DateTimeFormat('en', { month: 'short', day: 'numeric', diff --git a/ui/helpers/utils/notification.utils.test.ts b/ui/helpers/utils/notification.utils.test.ts index cb37ffcbaaa0..e018b4076d22 100644 --- a/ui/helpers/utils/notification.utils.test.ts +++ b/ui/helpers/utils/notification.utils.test.ts @@ -6,31 +6,98 @@ import { } from './notification.util'; describe('formatMenuItemDate', () => { + beforeAll(() => { + jest.useFakeTimers(); + jest.setSystemTime(new Date('2024-06-07T09:40:00Z')); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + it('should format date as time if the date is today', () => { - const date = new Date(); - const result = formatMenuItemDate(date); - expect(result).toMatch(/^\d{2}:\d{2}$/u); + const assertToday = (modifyDate?: (d: Date) => void) => { + const testDate = new Date(); + modifyDate?.(testDate); + expect(formatMenuItemDate(testDate)).toMatch(/^\d{2}:\d{2}$/u); + }; + + // assert current date + assertToday(); + + // assert 1 hour ago + assertToday((testDate) => { + testDate.setHours(testDate.getHours() - 1); + return testDate; + }); }); it('should format date as "yesterday" if the date was yesterday', () => { - const date = new Date(); - date.setDate(date.getDate() - 1); - const result = formatMenuItemDate(date); - expect(result).toBe('yesterday'); + const assertYesterday = (modifyDate: (d: Date) => void) => { + const testDate = new Date(); + modifyDate(testDate); + expect(formatMenuItemDate(testDate)).toBe('yesterday'); + }; + + // assert exactly 1 day ago + assertYesterday((testDate) => { + testDate.setDate(testDate.getDate() - 1); + }); + + // assert almost a day ago, but was still yesterday + // E.g. if Today way 09:40AM, but date to test was 23 hours ago (yesterday at 10:40AM), we still want to to show yesterday + assertYesterday((testDate) => { + testDate.setDate(testDate.getDate() - 1); + testDate.setHours(testDate.getHours() + 1); + }); }); it('should format date as "DD Mon" if the date is this year but not today or yesterday', () => { - const date = new Date(); - date.setMonth(date.getMonth() - 1); - const result = formatMenuItemDate(date); - expect(result).toMatch(/^\w{3} \d{1,2}$/u); + const assertMonthsAgo = (modifyDate: (d: Date) => Date | void) => { + let testDate = new Date(); + testDate = modifyDate(testDate) ?? testDate; + expect(formatMenuItemDate(testDate)).toMatch(/^\w{3} \d{1,2}$/u); + }; + + // assert exactly 1 month ago + assertMonthsAgo((testDate) => { + testDate.setMonth(testDate.getMonth() - 1); + }); + + // assert 2 months ago + assertMonthsAgo((testDate) => { + testDate.setMonth(testDate.getMonth() - 2); + }); + + // assert almost a month ago (where it is a new month, but not 30 days) + assertMonthsAgo(() => { + // jest mock date is set in july, so we will test with month may + return new Date('2024-05-20T09:40:00Z'); + }); }); it('should format date as "Mon DD, YYYY" if the date is not this year', () => { - const date = new Date(); - date.setFullYear(date.getFullYear() - 1); - const result = formatMenuItemDate(date); - expect(result).toMatch(/^\w{3} \d{1,2}, \d{4}$/u); + const assertYearsAgo = (modifyDate: (d: Date) => Date | void) => { + let testDate = new Date(); + testDate = modifyDate(testDate) ?? testDate; + expect(formatMenuItemDate(testDate)).toMatch(/^\w{3} \d{1,2}, \d{4}$/u); + }; + + // assert exactly 1 year ago + assertYearsAgo((testDate) => { + testDate.setFullYear(testDate.getFullYear() - 1); + }); + + // assert 2 years ago + assertYearsAgo((testDate) => { + testDate.setFullYear(testDate.getFullYear() - 2); + }); + + // assert almost a year ago (where it is a new year, but not 365 days ago) + assertYearsAgo(() => { + // jest mock date is set in 2024, so we will test with year 2023 + return new Date('2023-11-20T09:40:00Z'); + }); }); }); From 0dff71e7ad2934c68b55dbc63c3ed61843c40c63 Mon Sep 17 00:00:00 2001 From: seaona <54408225+seaona@users.noreply.github.com> Date: Thu, 13 Jun 2024 12:42:48 +0200 Subject: [PATCH 30/61] fix: flaky test `ENS domain resolves to a correct address` (#25248) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR fixes the flaky test `ENS domain resolves to a correct address` The error is: ``` [driver] Called 'clickElement' with arguments [".address-list-item"] [driver] Called 'findElement' with arguments [{"css":".ens-input__selected-input__title","text":"test.eth"}] Failure on testcase: 'ENS domain resolves to a correct address', for more information see the artifacts tab in CI TimeoutError: Waiting for element to be located By(xpath, .//*[contains(concat(' ', normalize-space(./@class), ' '), ' ens-input__selected-input__title ')][(contains(string(.), 'test.eth') or contains(string(.), 'test.eth'))])` ``` The problem is that we are clicking the address-list-item button, and nothing happens afterwards. Then we try to find the next element but is not there. If we look into the address-list-item button element we can see how it has nested elements inside, which will render the address and the ENS domain. Clicking on a "container" element with other elements inside might not work as we expect, since the inside elements might not be fully updated before clicking with unknown effects (in this case, the ENS and address resolution) . To fix this, we are doing 2 things: - waiting for both the ENS and the address to be fully rendered (before we were just waiting for the ENS domain to be loaded) - clicking on a more specific element inside the container -> we now click into the inner element for the domain ENS See Box as the container button, and nested elements with address and ENS domain. ![Screenshot from 2024-06-12 10-49-23](https://github.com/MetaMask/metamask-extension/assets/54408225/bef54bcf-9f67-46f3-9155-b877fb9c844f) - ci failure example: https://app.circleci.com/pipelines/github/MetaMask/metamask-extension/86997/workflows/200911a8-50a6-42f2-b56a-b6f7afc8fc1e/jobs/3178850/artifacts [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25248?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/metamask-extension/issues/24652 ## **Manual testing steps** 1. Check ci 2. Run test multiple times locally with different builds `yarn test:e2e:single test/e2e/tests/transaction/ens.spec.js --browser=chrome --leave-running --retryUntilFailure --retries=10` ## **Screenshots/Recordings** Ci failure screenshot: notice how, after clicking the ENS address button, we don't see the asset below, this means that the click didn't have any effect. ![image](https://github.com/MetaMask/metamask-extension/assets/54408225/c62f66e5-a194-4d70-917b-5677cdb13f87) Expected: after clicking the EN address button, we should see the asset below ![Screenshot from 2024-06-12 10-04-33](https://github.com/MetaMask/metamask-extension/assets/54408225/9478f881-edeb-4a32-9e95-ce715526e72b) ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. - [ ] --- test/e2e/tests/transaction/ens.spec.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/test/e2e/tests/transaction/ens.spec.js b/test/e2e/tests/transaction/ens.spec.js index 9497fe3ef60c..db399fef5a93 100644 --- a/test/e2e/tests/transaction/ens.spec.js +++ b/test/e2e/tests/transaction/ens.spec.js @@ -8,6 +8,11 @@ const FixtureBuilder = require('../../fixture-builder'); describe('ENS', function () { const sampleAddress = '1111111111111111111111111111111111111111'; + + // Having 2 versions of the address is a bug(#25286) + const shortSampleAddress = '0x1111...1111'; + const shortSampleAddresV2 = '0x11111...11111'; + const sampleEnsDomain = 'test.eth'; const infuraUrl = 'https://mainnet.infura.io/v3/00000000000000000000000000000000'; @@ -95,7 +100,15 @@ describe('ENS', function () { css: '[data-testid="multichain-send-page__recipient__item__title"]', }); - await driver.clickElement('.multichain-send-page__recipient__item'); + await driver.waitForSelector({ + text: shortSampleAddress, + css: '.multichain-send-page__recipient__item__subtitle', + }); + + await driver.clickElement({ + text: sampleEnsDomain, + css: '[data-testid="multichain-send-page__recipient__item__title"]', + }); await driver.findElement({ css: '.ens-input__selected-input__title', @@ -103,7 +116,7 @@ describe('ENS', function () { }); await driver.findElement({ - text: '0x11111...11111', + text: shortSampleAddresV2, }); }, ); From 933e09d9654ec33fac6a4f0ce7ad2c35a61b7822 Mon Sep 17 00:00:00 2001 From: seaona <54408225+seaona@users.noreply.github.com> Date: Thu, 13 Jun 2024 13:49:19 +0200 Subject: [PATCH 31/61] fix: flaky test `Send NFT should not be able to send ERC1155 NFT with invalid amount` (#25289) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR fixes the flaky test `Send NFT should not be able to send ERC1155 NFT with invalid amount`. The error is `ElementNotInteractableError: Element <button class="mm-box nft-item__container"> could not be scrolled into view`. After looking into the code, we see that there is actually no reason why we are trying to scroll to the button before clicking it. This PR removes this step as well as other unnecessary steps and waits alongside the spec. :racehorse: It now runs faster (notice we were adding up more than **15seconds** of unnecessary delays) and without flakiness. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25289?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/metamask-extension/issues/25288 ## **Manual testing steps** 1. Run test multiple times `ENABLE_MV3=false FIREFOX_SNAP=false yarn test:e2e:single test/e2e/tests/tokens/nft/send-nft.spec.js --browser=firefox --leave-running --retryUntilFailure --retries=10` 2. Check ci ## **Screenshots/Recordings** https://github.com/MetaMask/metamask-extension/assets/54408225/9cee8b81-7d1f-4f38-9656-4f33e62d37c2 ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- test/e2e/tests/tokens/nft/send-nft.spec.js | 29 ++++++---------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/test/e2e/tests/tokens/nft/send-nft.spec.js b/test/e2e/tests/tokens/nft/send-nft.spec.js index f7bb456e8036..7df8febcab56 100644 --- a/test/e2e/tests/tokens/nft/send-nft.spec.js +++ b/test/e2e/tests/tokens/nft/send-nft.spec.js @@ -1,8 +1,9 @@ const { strict: assert } = require('assert'); const { defaultGanacheOptions, - withFixtures, + logInWithBalanceValidation, unlockWallet, + withFixtures, } = require('../../../helpers'); const { SMART_CONTRACTS } = require('../../../seeder/smart-contracts'); const FixtureBuilder = require('../../../fixture-builder'); @@ -93,16 +94,13 @@ describe('Send NFT', function () { smartContract: erc1155SmartContract, title: this.test.fullTitle(), }, - async ({ driver }) => { - await unlockWallet(driver); + async ({ driver, ganacheServer }) => { + await logInWithBalanceValidation(driver, ganacheServer); // Fill the send NFT form and confirm the transaction await driver.clickElement('[data-testid="account-overview__nfts-tab"]'); - await driver.delay(1000); - const erc1155Token = await driver.findElement('.nft-item__container'); - await driver.scrollToElement(erc1155Token); - await driver.delay(1000); + await driver.clickElement('[data-testid="nft-network-badge"]'); await driver.clickElement( '.nft-item__container .mm-badge-wrapper__badge-container', ); @@ -112,7 +110,6 @@ describe('Send NFT', function () { 'input[placeholder="Enter public address (0x) or ENS name"]', '0xc427D562164062a23a5cFf596A4a3208e72Acd28', ); - await driver.delay(1000); await driver.fill('input[placeholder="0"]', '1'); @@ -148,11 +145,6 @@ describe('Send NFT', function () { // Go back to NFTs tab and check the imported NFT is shown as previously owned await driver.clickElement('[data-testid="account-overview__nfts-tab"]'); - const refreshList = await driver.findElement( - '[data-testid="refresh-list-button"]', - ); - await driver.scrollToElement(refreshList); - await driver.delay(1000); await driver.clickElement('[data-testid="refresh-list-button"]'); const previouslyOwnedNft = await driver.findElement({ @@ -173,21 +165,16 @@ describe('Send NFT', function () { smartContract: erc1155SmartContract, title: this.test.fullTitle(), }, - async ({ driver }) => { - await unlockWallet(driver); + async ({ driver, ganacheServer }) => { + await logInWithBalanceValidation(driver, ganacheServer); // Fill the send NFT form and confirm the transaction await driver.clickElement('[data-testid="account-overview__nfts-tab"]'); - const erc1155Token = await driver.findElement('.nft-item__container'); - await driver.scrollToElement(erc1155Token); - await driver.delay(1000); - await driver.clickElement('.nft-item__container'); + await driver.clickElement('[data-testid="nft-network-badge"]'); await driver.clickElement({ text: 'Send', tag: 'button' }); - await driver.delay(10000); - await driver.fill( 'input[placeholder="Enter public address (0x) or ENS name"]', '0xc427D562164062a23a5cFf596A4a3208e72Acd28', From 0fd5f5ef813cd30893547329247cdbf555713e88 Mon Sep 17 00:00:00 2001 From: Jyoti Puri <jyotipuri@gmail.com> Date: Thu, 13 Jun 2024 19:10:50 +0530 Subject: [PATCH 32/61] feat: SIWE sign message section (#24997) --- app/_locales/en/messages.json | 15 + package.json | 1 + test/data/confirmations/personal_sign.ts | 38 ++ .../info/personal-sign/personal-sign.tsx | 33 +- .../__snapshots__/siwe-sign.test.tsx.snap | 547 ++++++++++++++++++ .../info/personal-sign/siwe-sign/index.ts | 1 + .../siwe-sign/siwe-sign.stories.tsx | 31 + .../siwe-sign/siwe-sign.test.tsx | 36 ++ .../personal-sign/siwe-sign/siwe-sign.tsx | 85 +++ .../components/confirm/utils.test.ts | 6 +- ui/pages/confirmations/types/confirm.ts | 12 + ui/pages/confirmations/utils/date.test.ts | 15 + ui/pages/confirmations/utils/date.ts | 12 + yarn.lock | 8 + 14 files changed, 823 insertions(+), 17 deletions(-) create mode 100644 ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/__snapshots__/siwe-sign.test.tsx.snap create mode 100644 ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/index.ts create mode 100644 ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.stories.tsx create mode 100644 ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.test.tsx create mode 100644 ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.tsx create mode 100644 ui/pages/confirmations/utils/date.test.ts create mode 100644 ui/pages/confirmations/utils/date.ts diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 25ad96fce540..4d251becd20a 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -4679,9 +4679,24 @@ "simulationsSettingSubHeader": { "message": "Estimate balance changes" }, + "siweIssued": { + "message": "Issued" + }, + "siweNetwork": { + "message": "Network" + }, + "siweRequestId": { + "message": "Request ID" + }, + "siweResources": { + "message": "Resources" + }, "siweSignatureSimulationDetailInfo": { "message": "This type of signature is not able to move your assets and is used for signing in." }, + "siweURI": { + "message": "URL" + }, "skip": { "message": "Skip" }, diff --git a/package.json b/package.json index 41e2dbc4cec4..041520f59739 100644 --- a/package.json +++ b/package.json @@ -489,6 +489,7 @@ "@types/gulp-sourcemaps": "^0.0.35", "@types/he": "^1", "@types/jest": "^29.5.12", + "@types/luxon": "^3.4.2", "@types/mocha": "^10.0.3", "@types/node": "^20", "@types/pify": "^5.0.1", diff --git a/test/data/confirmations/personal_sign.ts b/test/data/confirmations/personal_sign.ts index e0c9d093d78c..c6f7907eccc4 100644 --- a/test/data/confirmations/personal_sign.ts +++ b/test/data/confirmations/personal_sign.ts @@ -46,3 +46,41 @@ export const signatureRequestSIWE = { }, }, }; + +export const SignatureRequestSIWEWithResources = { + id: '210ca3b0-1ccb-11ef-b096-89c4d726ebb5', + securityAlertResponse: { + reason: 'loading', + result_type: 'validation_in_progress', + securityAlertId: 'b826df20-2eda-41bf-becf-6a100141a8be', + }, + status: 'unapproved', + time: 1716884423019, + type: 'personal_sign', + msgParams: { + from: '0x935e73edb9ff52e23bac7f7e049a1ecd06d05477', + data: '0x6d6574616d61736b2e6769746875622e696f2077616e747320796f7520746f207369676e20696e207769746820796f757220457468657265756d206163636f756e743a0a3078393335653733656462396666353265323362616337663765303433613165636430366430353437370a0a492061636365707420746865204d6574614d61736b205465726d73206f6620536572766963653a2068747470733a2f2f636f6d6d756e6974792e6d6574616d61736b2e696f2f746f730a0a5552493a2068747470733a2f2f6d6574616d61736b2e6769746875622e696f0a56657273696f6e3a20310a436861696e2049443a20310a4e6f6e63653a2033323839313735370a4973737565642041743a20323032312d30392d33305431363a32353a32342e3030305a', + signatureMethod: 'personal_sign', + origin: 'https://metamask.github.io', + siwe: { + isSIWEMessage: true, + parsedMessage: { + domain: 'metamask.github.io', + address: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477', + statement: + 'I accept the MetaMask Terms of Service: https://community.metamask.io/tos', + uri: 'https://metamask.github.io', + version: '1', + chainId: 1, + nonce: '32891757', + issuedAt: '2021-09-30T16:25:24.000Z', + notBefore: '2022-03-17T12:45:13.610Z', + requestId: 'some_id', + resources: [ + 'ipfs://Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu', + 'https://example.com/my-web2-claim.json', + ], + }, + }, + }, +}; diff --git a/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.tsx b/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.tsx index 2fc34a299182..93e8aff2ef35 100644 --- a/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.tsx +++ b/ui/pages/confirmations/components/confirm/info/personal-sign/personal-sign.tsx @@ -22,6 +22,7 @@ import { SignatureRequestType } from '../../../../types/confirm'; import { selectUseTransactionSimulations } from '../../../../selectors/preferences'; import { isSIWESignatureRequest } from '../../../../utils'; import { AlertRow } from '../../../../../../components/app/confirm/info/row/alert-row/alert-row'; +import { SIWESignInfo } from './siwe-sign'; const PersonalSignInfo: React.FC = () => { const t = useI18nContext(); @@ -37,11 +38,11 @@ const PersonalSignInfo: React.FC = () => { } const { from } = currentConfirmation.msgParams; - const isSiweSigReq = isSIWESignatureRequest(currentConfirmation); + const isSIWE = isSIWESignatureRequest(currentConfirmation); return ( <> - {isSiweSigReq && useTransactionSimulations && ( + {isSIWE && useTransactionSimulations && ( <Box backgroundColor={BackgroundColor.backgroundDefault} borderRadius={BorderRadius.MD} @@ -70,7 +71,7 @@ const PersonalSignInfo: React.FC = () => { > <ConfirmInfoRowUrl url={currentConfirmation.msgParams.origin} /> </AlertRow> - {isSiweSigReq && ( + {isSIWE && ( <ConfirmInfoRow label={t('signingInWith')}> <ConfirmInfoRowAddress address={from} /> </ConfirmInfoRow> @@ -82,17 +83,21 @@ const PersonalSignInfo: React.FC = () => { padding={2} marginBottom={4} > - <AlertRow - alertKey="message" - ownerId={currentConfirmation.id} - label={t('message')} - > - <ConfirmInfoRowText - text={sanitizeString( - hexToText(currentConfirmation.msgParams?.data), - )} - /> - </AlertRow> + {isSIWE ? ( + <SIWESignInfo /> + ) : ( + <AlertRow + alertKey="message" + ownerId={currentConfirmation.id} + label={t('message')} + > + <ConfirmInfoRowText + text={sanitizeString( + hexToText(currentConfirmation.msgParams?.data), + )} + /> + </AlertRow> + )} </Box> </> ); diff --git a/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/__snapshots__/siwe-sign.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/__snapshots__/siwe-sign.test.tsx.snap new file mode 100644 index 000000000000..1e62756cf223 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/__snapshots__/siwe-sign.test.tsx.snap @@ -0,0 +1,547 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SIWESignInfo renders correctly for SIWE signature request 1`] = ` +<div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Message + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + I accept the MetaMask Terms of Service: https://community.metamask.io/tos + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + URL + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + metamask.github.io + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Network + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + Ethereum Mainnet + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Account + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--align-items-center" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--align-items-center" + > + <div + class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-account mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-transparent box--border-style-solid box--border-width-1" + > + <div + class="mm-avatar-account__jazzicon" + > + <div + style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 16px; height: 16px; display: inline-block; background: rgb(200, 20, 59);" + > + <svg + height="16" + width="16" + x="0" + y="0" + > + <rect + fill="#017B8E" + height="16" + transform="translate(0.39972303467835485 -0.4108005578484912) rotate(317.9 8 8)" + width="16" + x="0" + y="0" + /> + <rect + fill="#F2B602" + height="16" + transform="translate(-3.7466980184561267 5.704967714142398) rotate(134.1 8 8)" + width="16" + x="0" + y="0" + /> + <rect + fill="#FA8E00" + height="16" + transform="translate(-12.856136345377399 -5.7794405216344416) rotate(364.0 8 8)" + width="16" + x="0" + y="0" + /> + </svg> + </div> + </div> + </div> + <p + class="mm-box mm-text mm-text--body-md mm-box--margin-left-2 mm-box--color-inherit" + data-testid="confirm-info-row-display-name" + > + 0x935e7...05477 + </p> + </div> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Version + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + 1 + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Chain ID + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + 1 + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Nonce + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + 32891757 + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Issued + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + 30 September 2021, 16:25 + </p> + </div> + </div> +</div> +`; + +exports[`SIWESignInfo renders correctly for SIWE signature request with resources 1`] = ` +<div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Message + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + I accept the MetaMask Terms of Service: https://community.metamask.io/tos + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + URL + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + metamask.github.io + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Network + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + Ethereum Mainnet + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Account + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--align-items-center" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--align-items-center" + > + <div + class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-account mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-transparent box--border-style-solid box--border-width-1" + > + <div + class="mm-avatar-account__jazzicon" + > + <div + style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 16px; height: 16px; display: inline-block; background: rgb(200, 20, 59);" + > + <svg + height="16" + width="16" + x="0" + y="0" + > + <rect + fill="#017B8E" + height="16" + transform="translate(0.39972303467835485 -0.4108005578484912) rotate(317.9 8 8)" + width="16" + x="0" + y="0" + /> + <rect + fill="#F2B602" + height="16" + transform="translate(-3.7466980184561267 5.704967714142398) rotate(134.1 8 8)" + width="16" + x="0" + y="0" + /> + <rect + fill="#FA8E00" + height="16" + transform="translate(-12.856136345377399 -5.7794405216344416) rotate(364.0 8 8)" + width="16" + x="0" + y="0" + /> + </svg> + </div> + </div> + </div> + <p + class="mm-box mm-text mm-text--body-md mm-box--margin-left-2 mm-box--color-inherit" + data-testid="confirm-info-row-display-name" + > + 0x935E7...05477 + </p> + </div> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Version + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + 1 + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Chain ID + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + 1 + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Nonce + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + 32891757 + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Issued + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + 30 September 2021, 16:25 + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Request ID + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + some_id + </p> + </div> + </div> + <div + class="mm-box confirm-info-row mm-box--margin-top-2 mm-box--margin-bottom-2 mm-box--padding-right-2 mm-box--padding-left-2 mm-box--display-flex mm-box--flex-direction-row mm-box--flex-wrap-wrap mm-box--justify-content-space-between mm-box--color-text-default mm-box--rounded-lg" + style="overflow-wrap: anywhere; min-height: 24px;" + > + <div + class="mm-box mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md-medium mm-box--color-inherit" + > + Resources + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + ipfs://Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu + </p> + </div> + <div + class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--flex-wrap-wrap mm-box--align-items-center" + > + <p + class="mm-box mm-text mm-text--body-md mm-box--color-inherit" + style="white-space: pre-wrap;" + > + https://example.com/my-web2-claim.json + </p> + </div> + </div> +</div> +`; diff --git a/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/index.ts b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/index.ts new file mode 100644 index 000000000000..e62d38d2b793 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/index.ts @@ -0,0 +1 @@ +export { default as SIWESignInfo } from './siwe-sign'; diff --git a/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.stories.tsx b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.stories.tsx new file mode 100644 index 000000000000..8434f23752eb --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.stories.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { Provider } from 'react-redux'; + +import { SignatureRequestSIWEWithResources } from '../../../../../../../../test/data/confirmations/personal_sign'; +import mockState from '../../../../../../../../test/data/mock-state.json'; +import configureStore from '../../../../../../../store/store'; + +import SIWESignInfo from './siwe-sign'; + +const store = configureStore({ + metamask: { + ...mockState.metamask, + }, + confirm: { + currentConfirmation: SignatureRequestSIWEWithResources, + }, +}); + +const Story = { + title: 'Components/App/Confirm/info/SIWESignInfo', + component: SIWESignInfo, + decorators: [ + (story: () => any) => <Provider store={store}>{story()}</Provider>, + ], +}; + +export default Story; + +export const DefaultStory = () => <SIWESignInfo />; + +DefaultStory.storyName = 'Default'; diff --git a/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.test.tsx b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.test.tsx new file mode 100644 index 000000000000..abede6223caa --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.test.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; + +import mockState from '../../../../../../../../test/data/mock-state.json'; +import { renderWithProvider } from '../../../../../../../../test/lib/render-helpers'; +import { + SignatureRequestSIWEWithResources, + signatureRequestSIWE, +} from '../../../../../../../../test/data/confirmations/personal_sign'; +import SIWESignInfo from './siwe-sign'; + +describe('SIWESignInfo', () => { + it('renders correctly for SIWE signature request', () => { + const state = { + ...mockState, + confirm: { + currentConfirmation: signatureRequestSIWE, + }, + }; + const mockStore = configureMockStore([])(state); + const { container } = renderWithProvider(<SIWESignInfo />, mockStore); + expect(container).toMatchSnapshot(); + }); + + it('renders correctly for SIWE signature request with resources', () => { + const state = { + ...mockState, + confirm: { + currentConfirmation: SignatureRequestSIWEWithResources, + }, + }; + const mockStore = configureMockStore([])(state); + const { container } = renderWithProvider(<SIWESignInfo />, mockStore); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.tsx b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.tsx new file mode 100644 index 000000000000..8c1260c3ede5 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.tsx @@ -0,0 +1,85 @@ +import React from 'react'; +import { useSelector } from 'react-redux'; +import { toHex } from '@metamask/controller-utils'; + +import { NETWORK_TO_NAME_MAP } from '../../../../../../../../shared/constants/network'; +import { useI18nContext } from '../../../../../../../hooks/useI18nContext'; +import { currentConfirmationSelector } from '../../../../../../../selectors'; +import { SignatureRequestType } from '../../../../../types/confirm'; +import { + ConfirmInfoRow, + ConfirmInfoRowAddress, + ConfirmInfoRowText, +} from '../../../../../../../components/app/confirm/info/row'; +import { formatDate } from '../../../../../utils/date'; + +const SIWESignInfo: React.FC = () => { + const t = useI18nContext(); + const currentConfirmation = useSelector( + currentConfirmationSelector, + ) as SignatureRequestType; + + const siweMessage = currentConfirmation?.msgParams?.siwe?.parsedMessage; + + if (!siweMessage) { + return null; + } + + const { + address, + chainId, + domain, + issuedAt, + nonce, + requestId, + statement, + resources, + version, + } = siweMessage; + const hexChainId = toHex(chainId); + const network = + (NETWORK_TO_NAME_MAP as Record<string, string>)[hexChainId] ?? hexChainId; + + return ( + <> + <ConfirmInfoRow label={t('message')}> + <ConfirmInfoRowText text={statement} /> + </ConfirmInfoRow> + <ConfirmInfoRow label={t('siweURI')}> + <ConfirmInfoRowText text={domain} /> + </ConfirmInfoRow> + <ConfirmInfoRow label={t('siweNetwork')}> + <ConfirmInfoRowText text={network} /> + </ConfirmInfoRow> + <ConfirmInfoRow label={t('account')}> + <ConfirmInfoRowAddress address={address} /> + </ConfirmInfoRow> + <ConfirmInfoRow label={t('version')}> + <ConfirmInfoRowText text={version} /> + </ConfirmInfoRow> + <ConfirmInfoRow label={t('chainId')}> + <ConfirmInfoRowText text={`${chainId}`} /> + </ConfirmInfoRow> + <ConfirmInfoRow label={t('nonce')}> + <ConfirmInfoRowText text={nonce} /> + </ConfirmInfoRow> + <ConfirmInfoRow label={t('siweIssued')}> + <ConfirmInfoRowText text={formatDate(issuedAt)} /> + </ConfirmInfoRow> + {requestId && ( + <ConfirmInfoRow label={t('siweRequestId')}> + <ConfirmInfoRowText text={requestId} /> + </ConfirmInfoRow> + )} + {resources && ( + <ConfirmInfoRow label={t('siweResources')}> + {resources.map((resource, index) => ( + <ConfirmInfoRowText key={`resource-${index}`} text={resource} /> + ))} + </ConfirmInfoRow> + )} + </> + ); +}; + +export default SIWESignInfo; diff --git a/ui/pages/confirmations/components/confirm/utils.test.ts b/ui/pages/confirmations/components/confirm/utils.test.ts index 2250d62fa62c..87e6307de7be 100644 --- a/ui/pages/confirmations/components/confirm/utils.test.ts +++ b/ui/pages/confirmations/components/confirm/utils.test.ts @@ -20,9 +20,9 @@ describe('getConfirmationSender()', () => { }); test("returns the sender address from a transaction if it's passed", () => { - const testCurrentConfirmation = - unapprovedPersonalSignMsg as SignatureRequestType; - const { from } = getConfirmationSender(testCurrentConfirmation); + const { from } = getConfirmationSender( + unapprovedPersonalSignMsg as SignatureRequestType, + ); expect(from).toEqual(PERSONAL_SIGN_SENDER_ADDRESS); }); diff --git a/ui/pages/confirmations/types/confirm.ts b/ui/pages/confirmations/types/confirm.ts index 70e173b03deb..a48e1d4984ba 100644 --- a/ui/pages/confirmations/types/confirm.ts +++ b/ui/pages/confirmations/types/confirm.ts @@ -28,6 +28,18 @@ export type SignatureRequestType = { version?: string; siwe?: { isSIWEMessage: boolean; + parsedMessage: null | { + domain: string; + address: string; + statement: string; + uri: string; + version: string; + chainId: number; + nonce: string; + issuedAt: string; + requestId?: string; + resources?: string[]; + }; }; }; type: TransactionType; diff --git a/ui/pages/confirmations/utils/date.test.ts b/ui/pages/confirmations/utils/date.test.ts new file mode 100644 index 000000000000..dc1fdd40454a --- /dev/null +++ b/ui/pages/confirmations/utils/date.test.ts @@ -0,0 +1,15 @@ +import { formatDate } from './date'; + +describe('date util', () => { + describe('formatDate', () => { + it('formats passed date string', () => { + expect(formatDate('2021-09-30T16:25:24.000Z')).toEqual( + '30 September 2021, 16:25', + ); + }); + + it('returns empty string if empty string is passed', () => { + expect(formatDate('')).toEqual(''); + }); + }); +}); diff --git a/ui/pages/confirmations/utils/date.ts b/ui/pages/confirmations/utils/date.ts new file mode 100644 index 000000000000..19ffa5d027d4 --- /dev/null +++ b/ui/pages/confirmations/utils/date.ts @@ -0,0 +1,12 @@ +import { DateTime } from 'luxon'; + +export const formatDate = (dateString: string) => { + if (!dateString) { + return dateString; + } + + return DateTime.fromISO(dateString) + .setLocale('en') + .setZone('utc') + .toFormat('dd LLLL yyyy, HH:mm'); +}; diff --git a/yarn.lock b/yarn.lock index 5f7759c93188..f5cd2d65be86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9950,6 +9950,13 @@ __metadata: languageName: node linkType: hard +"@types/luxon@npm:^3.4.2": + version: 3.4.2 + resolution: "@types/luxon@npm:3.4.2" + checksum: 10/fd89566e3026559f2bc4ddcc1e70a2c16161905ed50be9473ec0cfbbbe919165041408c4f6e06c4bcf095445535052e2c099087c76b1b38e368127e618fc968d + languageName: node + linkType: hard + "@types/mdast@npm:^3.0.0": version: 3.0.10 resolution: "@types/mdast@npm:3.0.10" @@ -25023,6 +25030,7 @@ __metadata: "@types/gulp-sourcemaps": "npm:^0.0.35" "@types/he": "npm:^1" "@types/jest": "npm:^29.5.12" + "@types/luxon": "npm:^3.4.2" "@types/mocha": "npm:^10.0.3" "@types/node": "npm:^20" "@types/pify": "npm:^5.0.1" From 54823b9d96fbaf1a4c34c37d5dbc5d9cf8b29a05 Mon Sep 17 00:00:00 2001 From: Monte Lai <monte.lai@consensys.net> Date: Thu, 13 Jun 2024 23:41:30 +0800 Subject: [PATCH 33/61] chore: bump keyring-api and eth-snap-keyring (#25287) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR bumps `@metamask/keyring-api` to `^8.0.0` and `@metamask/eth-snap-keyring` to `^4.3.1` ## **Related issues** Fixes: ## **Manual testing steps** ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** ### **After** ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com> --- lavamoat/browserify/beta/policy.json | 18 ++++++++++++++- lavamoat/browserify/flask/policy.json | 18 ++++++++++++++- lavamoat/browserify/main/policy.json | 18 ++++++++++++++- lavamoat/browserify/mmi/policy.json | 18 ++++++++++++++- package.json | 4 ++-- yarn.lock | 32 ++++++++++++++++++++------- 6 files changed, 94 insertions(+), 14 deletions(-) diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 496eb485f48c..42b366d8270a 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -750,8 +750,8 @@ "@ethereumjs/tx>@ethereumjs/util": true, "@ethereumjs/tx>ethereum-cryptography": true, "@metamask/accounts-controller>@metamask/base-controller": true, + "@metamask/accounts-controller>@metamask/keyring-api": true, "@metamask/eth-snap-keyring": true, - "@metamask/keyring-api": true, "@metamask/keyring-controller": true, "@metamask/snaps-utils": true, "@metamask/utils": true, @@ -766,6 +766,22 @@ "immer": true } }, + "@metamask/accounts-controller>@metamask/keyring-api": { + "globals": { + "URL": true + }, + "packages": { + "@metamask/accounts-controller>@metamask/keyring-api>uuid": true, + "@metamask/keyring-api>bech32": true, + "@metamask/utils": true, + "superstruct": true + } + }, + "@metamask/accounts-controller>@metamask/keyring-api>uuid": { + "globals": { + "crypto": true + } + }, "@metamask/address-book-controller": { "packages": { "@metamask/address-book-controller>@metamask/controller-utils": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 87580fa1fabe..a79a242eb914 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -750,8 +750,8 @@ "@ethereumjs/tx>@ethereumjs/util": true, "@ethereumjs/tx>ethereum-cryptography": true, "@metamask/accounts-controller>@metamask/base-controller": true, + "@metamask/accounts-controller>@metamask/keyring-api": true, "@metamask/eth-snap-keyring": true, - "@metamask/keyring-api": true, "@metamask/keyring-controller": true, "@metamask/snaps-utils": true, "@metamask/utils": true, @@ -766,6 +766,22 @@ "immer": true } }, + "@metamask/accounts-controller>@metamask/keyring-api": { + "globals": { + "URL": true + }, + "packages": { + "@metamask/accounts-controller>@metamask/keyring-api>uuid": true, + "@metamask/keyring-api>bech32": true, + "@metamask/utils": true, + "superstruct": true + } + }, + "@metamask/accounts-controller>@metamask/keyring-api>uuid": { + "globals": { + "crypto": true + } + }, "@metamask/address-book-controller": { "packages": { "@metamask/address-book-controller>@metamask/controller-utils": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 87580fa1fabe..a79a242eb914 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -750,8 +750,8 @@ "@ethereumjs/tx>@ethereumjs/util": true, "@ethereumjs/tx>ethereum-cryptography": true, "@metamask/accounts-controller>@metamask/base-controller": true, + "@metamask/accounts-controller>@metamask/keyring-api": true, "@metamask/eth-snap-keyring": true, - "@metamask/keyring-api": true, "@metamask/keyring-controller": true, "@metamask/snaps-utils": true, "@metamask/utils": true, @@ -766,6 +766,22 @@ "immer": true } }, + "@metamask/accounts-controller>@metamask/keyring-api": { + "globals": { + "URL": true + }, + "packages": { + "@metamask/accounts-controller>@metamask/keyring-api>uuid": true, + "@metamask/keyring-api>bech32": true, + "@metamask/utils": true, + "superstruct": true + } + }, + "@metamask/accounts-controller>@metamask/keyring-api>uuid": { + "globals": { + "crypto": true + } + }, "@metamask/address-book-controller": { "packages": { "@metamask/address-book-controller>@metamask/controller-utils": true, diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 875d9fced807..f97f4a34f66f 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -1035,8 +1035,8 @@ "@ethereumjs/tx>@ethereumjs/util": true, "@ethereumjs/tx>ethereum-cryptography": true, "@metamask/accounts-controller>@metamask/base-controller": true, + "@metamask/accounts-controller>@metamask/keyring-api": true, "@metamask/eth-snap-keyring": true, - "@metamask/keyring-api": true, "@metamask/keyring-controller": true, "@metamask/snaps-utils": true, "@metamask/utils": true, @@ -1051,6 +1051,22 @@ "immer": true } }, + "@metamask/accounts-controller>@metamask/keyring-api": { + "globals": { + "URL": true + }, + "packages": { + "@metamask/accounts-controller>@metamask/keyring-api>uuid": true, + "@metamask/keyring-api>bech32": true, + "@metamask/utils": true, + "superstruct": true + } + }, + "@metamask/accounts-controller>@metamask/keyring-api>uuid": { + "globals": { + "crypto": true + } + }, "@metamask/address-book-controller": { "packages": { "@metamask/address-book-controller>@metamask/controller-utils": true, diff --git a/package.json b/package.json index 041520f59739..003e22c504d3 100644 --- a/package.json +++ b/package.json @@ -298,7 +298,7 @@ "@metamask/eth-ledger-bridge-keyring": "^2.0.1", "@metamask/eth-query": "^4.0.0", "@metamask/eth-sig-util": "^7.0.1", - "@metamask/eth-snap-keyring": "^4.2.1", + "@metamask/eth-snap-keyring": "^4.3.1", "@metamask/eth-token-tracker": "^8.0.0", "@metamask/eth-trezor-keyring": "^3.1.0", "@metamask/etherscan-link": "^3.0.0", @@ -307,7 +307,7 @@ "@metamask/ethjs-query": "^0.7.1", "@metamask/gas-fee-controller": "^15.1.2", "@metamask/jazzicon": "^2.0.0", - "@metamask/keyring-api": "^6.3.1", + "@metamask/keyring-api": "^8.0.0", "@metamask/keyring-controller": "patch:@metamask/keyring-controller@npm%3A15.0.0#~/.yarn/patches/@metamask-keyring-controller-npm-15.0.0-fa070ce311.patch", "@metamask/logging-controller": "^3.0.1", "@metamask/logo": "^3.1.2", diff --git a/yarn.lock b/yarn.lock index f5cd2d65be86..a3b1636e42c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5226,13 +5226,13 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-snap-keyring@npm:^4.0.0, @metamask/eth-snap-keyring@npm:^4.1.1, @metamask/eth-snap-keyring@npm:^4.2.1": - version: 4.2.1 - resolution: "@metamask/eth-snap-keyring@npm:4.2.1" +"@metamask/eth-snap-keyring@npm:^4.0.0, @metamask/eth-snap-keyring@npm:^4.1.1, @metamask/eth-snap-keyring@npm:^4.3.1": + version: 4.3.1 + resolution: "@metamask/eth-snap-keyring@npm:4.3.1" dependencies: "@ethereumjs/tx": "npm:^4.2.0" "@metamask/eth-sig-util": "npm:^7.0.1" - "@metamask/keyring-api": "npm:^6.3.1" + "@metamask/keyring-api": "npm:^8.0.0" "@metamask/snaps-controllers": "npm:^8.1.1" "@metamask/snaps-sdk": "npm:^4.2.0" "@metamask/snaps-utils": "npm:^7.4.0" @@ -5240,7 +5240,7 @@ __metadata: "@types/uuid": "npm:^9.0.1" superstruct: "npm:^1.0.3" uuid: "npm:^9.0.0" - checksum: 10/96bccfe67fc490ea7891a7ef54839dc5bab6d6ffd4107fa05342045fc25e9045338df058b07c2942248e437c98279ae9addd13f632530cdca4f7cdeabcae0497 + checksum: 10/6362a499e8e25413bf8039c06e66939104bdb69b9dc22df5a44dd55e32304cffb869d4969755e8b4f3234749c6f382d8bbcdfeafe5a75064e85fa43307dbefee languageName: node linkType: hard @@ -5533,7 +5533,7 @@ __metadata: languageName: node linkType: hard -"@metamask/keyring-api@npm:^6.0.0, @metamask/keyring-api@npm:^6.1.1, @metamask/keyring-api@npm:^6.3.1": +"@metamask/keyring-api@npm:^6.0.0, @metamask/keyring-api@npm:^6.1.1": version: 6.4.0 resolution: "@metamask/keyring-api@npm:6.4.0" dependencies: @@ -5549,6 +5549,22 @@ __metadata: languageName: node linkType: hard +"@metamask/keyring-api@npm:^8.0.0": + version: 8.0.0 + resolution: "@metamask/keyring-api@npm:8.0.0" + dependencies: + "@metamask/snaps-sdk": "npm:^4.2.0" + "@metamask/utils": "npm:^8.4.0" + "@types/uuid": "npm:^9.0.8" + bech32: "npm:^2.0.0" + superstruct: "npm:^1.0.3" + uuid: "npm:^9.0.1" + peerDependencies: + "@metamask/providers": ">=15 <18" + checksum: 10/0c8546a4e980c70a7d4a6dcc470fa4968ca36d3e05f8fa8974e980c2b02616ada8ed416aa49f2801f883c08455453b2386d393e3b41c853d2dd45c226f8c360f + languageName: node + linkType: hard + "@metamask/keyring-controller@npm:15.0.0": version: 15.0.0 resolution: "@metamask/keyring-controller@npm:15.0.0" @@ -24938,7 +24954,7 @@ __metadata: "@metamask/eth-ledger-bridge-keyring": "npm:^2.0.1" "@metamask/eth-query": "npm:^4.0.0" "@metamask/eth-sig-util": "npm:^7.0.1" - "@metamask/eth-snap-keyring": "npm:^4.2.1" + "@metamask/eth-snap-keyring": "npm:^4.3.1" "@metamask/eth-token-tracker": "npm:^8.0.0" "@metamask/eth-trezor-keyring": "npm:^3.1.0" "@metamask/etherscan-link": "npm:^3.0.0" @@ -24948,7 +24964,7 @@ __metadata: "@metamask/forwarder": "npm:^1.1.0" "@metamask/gas-fee-controller": "npm:^15.1.2" "@metamask/jazzicon": "npm:^2.0.0" - "@metamask/keyring-api": "npm:^6.3.1" + "@metamask/keyring-api": "npm:^8.0.0" "@metamask/keyring-controller": "patch:@metamask/keyring-controller@npm%3A15.0.0#~/.yarn/patches/@metamask-keyring-controller-npm-15.0.0-fa070ce311.patch" "@metamask/logging-controller": "npm:^3.0.1" "@metamask/logo": "npm:^3.1.2" From 1d926088456f905f9f4d4f085c787cc8a100e2e6 Mon Sep 17 00:00:00 2001 From: salimtb <salim.toubal@outlook.com> Date: Thu, 13 Jun 2024 18:00:25 +0200 Subject: [PATCH 34/61] feat: add search feature (#25170) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Add filter search for popular network list <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25170?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** 1. Click on the network logo 2. you should be able to filter on network add using search input ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** https://github.com/MetaMask/metamask-extension/assets/26223211/1a47f1c0-77f1-4b9a-94b3-b3b6bd71112c https://github.com/MetaMask/metamask-extension/assets/26223211/1a47f1c0-77f1-4b9a-94b3-b3b6bd71112c ### **After** https://github.com/MetaMask/metamask-extension/assets/26223211/5b970fba-e309-4abb-8961-8fbf625b0baf https://github.com/MetaMask/metamask-extension/assets/26223211/1a3d8474-33ee-40c3-b4bd-d85dc3d985d6 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../network-list-menu.test.js.snap | 3 + .../network-list-menu/network-list-menu.js | 85 +++++++++++-------- .../network-list-menu.test.js | 52 ++++++++++++ .../network-list-search.test.tsx.snap | 28 ++++++ .../network-list-search.test.tsx | 61 +++++++++++++ .../network-list-search.tsx | 44 ++++++++++ 6 files changed, 238 insertions(+), 35 deletions(-) create mode 100644 ui/components/multichain/network-list-menu/__snapshots__/network-list-menu.test.js.snap create mode 100644 ui/components/multichain/network-list-menu/network-list-search/__snapshots__/network-list-search.test.tsx.snap create mode 100644 ui/components/multichain/network-list-menu/network-list-search/network-list-search.test.tsx create mode 100644 ui/components/multichain/network-list-menu/network-list-search/network-list-search.tsx diff --git a/ui/components/multichain/network-list-menu/__snapshots__/network-list-menu.test.js.snap b/ui/components/multichain/network-list-menu/__snapshots__/network-list-menu.test.js.snap new file mode 100644 index 000000000000..1b2a8d056105 --- /dev/null +++ b/ui/components/multichain/network-list-menu/__snapshots__/network-list-menu.test.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NetworkListMenu renders properly 1`] = `<div />`; diff --git a/ui/components/multichain/network-list-menu/network-list-menu.js b/ui/components/multichain/network-list-menu/network-list-menu.js index da7f145e7389..022ad7f055b0 100644 --- a/ui/components/multichain/network-list-menu/network-list-menu.js +++ b/ui/components/multichain/network-list-menu/network-list-menu.js @@ -37,11 +37,9 @@ import ToggleButton from '../../ui/toggle-button'; import { AlignItems, BackgroundColor, - BlockSize, Display, FlexDirection, JustifyContent, - Size, TextColor, } from '../../../helpers/constants/design-system'; import { @@ -56,7 +54,6 @@ import { ModalContent, ModalHeader, } from '../../component-library'; -import { TextFieldSearch } from '../../component-library/text-field-search/deprecated'; import { ADD_POPULAR_CUSTOM_NETWORK } from '../../../helpers/constants/routes'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app'; @@ -71,6 +68,7 @@ import { } from '../../../ducks/metamask/metamask'; import { getLocalNetworkMenuRedesignFeatureFlag } from '../../../helpers/utils/feature-flags'; import PopularNetworkList from './popular-network-list/popular-network-list'; +import NetworkListSearch from './network-list-search/network-list-search'; export const NetworkListMenu = ({ onClose }) => { const t = useI18nContext(); @@ -101,8 +99,6 @@ export const NetworkListMenu = ({ onClose }) => { const isUnlocked = useSelector(getIsUnlocked); - const showSearch = nonTestNetworks.length > 3; - const orderedNetworksList = useSelector(getOrderedNetworksList); const networkConfigurationChainIds = Object.values(networkConfigurations).map( @@ -116,6 +112,7 @@ export const NetworkListMenu = ({ onClose }) => { const notExistingNetworkConfigurations = sortedFeaturedNetworks.filter( ({ chainId }) => !networkConfigurationChainIds.includes(chainId), ); + const newOrderNetworks = () => { if (!orderedNetworksList || orderedNetworksList.length === 0) { return nonTestNetworks; @@ -147,6 +144,7 @@ export const NetworkListMenu = ({ onClose }) => { }, [dispatch, currentlyOnTestNetwork]); const [searchQuery, setSearchQuery] = useState(''); + const [focusSearch, setFocusSearch] = useState(false); const onboardedInThisUISession = useSelector(getOnboardedInThisUISession); const showNetworkBanner = useSelector(getShowNetworkBanner); const showBanner = @@ -175,14 +173,14 @@ export const NetworkListMenu = ({ onClose }) => { let searchResults = [...networksList].length === items.length ? items : [...networksList]; - const searchAddNetworkResults = + let searchAddNetworkResults = [...notExistingNetworkConfigurations].length === items.length ? items : [...notExistingNetworkConfigurations]; - const isSearching = searchQuery !== ''; + let searchTestNetworkResults = [...testNetworks]; - if (isSearching) { + if (focusSearch && searchQuery !== '') { const fuse = new Fuse(searchResults, { threshold: 0.2, location: 0, @@ -192,12 +190,45 @@ export const NetworkListMenu = ({ onClose }) => { shouldSort: true, keys: ['nickname', 'chainId', 'ticker'], }); + const fuseForPopularNetworks = new Fuse(searchAddNetworkResults, { + threshold: 0.2, + location: 0, + distance: 100, + maxPatternLength: 32, + minMatchCharLength: 1, + shouldSort: true, + keys: ['nickname', 'chainId', 'ticker'], + }); + + const fuseForTestsNetworks = new Fuse(searchTestNetworkResults, { + threshold: 0.2, + location: 0, + distance: 100, + maxPatternLength: 32, + minMatchCharLength: 1, + shouldSort: true, + keys: ['nickname', 'chainId', 'ticker'], + }); + fuse.setCollection(searchResults); + fuseForPopularNetworks.setCollection(searchAddNetworkResults); + fuseForTestsNetworks.setCollection(searchTestNetworkResults); + const fuseResults = fuse.search(searchQuery); - // Ensure order integrity with original list + const fuseForPopularNetworksResults = + fuseForPopularNetworks.search(searchQuery); + const fuseForTestsNetworksResults = + fuseForTestsNetworks.search(searchQuery); + searchResults = searchResults.filter((network) => fuseResults.includes(network), ); + searchAddNetworkResults = searchAddNetworkResults.filter((network) => + fuseForPopularNetworksResults.includes(network), + ); + searchTestNetworkResults = searchTestNetworkResults.filter((network) => + fuseForTestsNetworksResults.includes(network), + ); } const generateNetworkListItem = ({ @@ -210,8 +241,8 @@ export const NetworkListMenu = ({ onClose }) => { name={network.nickname} iconSrc={network?.rpcPrefs?.imageUrl} key={network.id} - selected={isCurrentNetwork} - focus={isCurrentNetwork && !showSearch} + selected={isCurrentNetwork && !focusSearch} + focus={isCurrentNetwork && !focusSearch} onClick={() => { dispatch(toggleNetworkMenu()); if (network.providerType) { @@ -305,27 +336,11 @@ export const NetworkListMenu = ({ onClose }) => { {t('networkMenuHeading')} </ModalHeader> <> - {showSearch ? ( - <Box - paddingLeft={4} - paddingRight={4} - paddingBottom={4} - paddingTop={0} - > - <TextFieldSearch - size={Size.SM} - width={BlockSize.Full} - placeholder={t('search')} - value={searchQuery} - onChange={(e) => setSearchQuery(e.target.value)} - clearButtonOnClick={() => setSearchQuery('')} - clearButtonProps={{ - size: Size.SM, - }} - inputProps={{ autoFocus: true }} - /> - </Box> - ) : null} + <NetworkListSearch + searchQuery={searchQuery} + setSearchQuery={setSearchQuery} + setFocusSearch={setFocusSearch} + /> {showBanner ? ( <BannerBase className="network-list-menu__banner" @@ -350,7 +365,7 @@ export const NetworkListMenu = ({ onClose }) => { /> ) : null} <Box className="multichain-network-list-menu"> - {searchResults.length === 0 && isSearching ? ( + {searchResults.length === 0 && focusSearch ? ( <Text paddingLeft={4} paddingRight={4} @@ -424,11 +439,11 @@ export const NetworkListMenu = ({ onClose }) => { </Box> {showTestNetworks || currentlyOnTestNetwork ? ( <Box className="multichain-network-list-menu"> - {generateMenuItems(testNetworks)} + {generateMenuItems(searchTestNetworkResults)} </Box> ) : null} </Box> - <Box padding={4}> + <Box paddingLeft={4} paddingRight={4} paddingTop={4}> <ButtonSecondary size={ButtonSecondarySize.Lg} startIconName={IconName.Add} diff --git a/ui/components/multichain/network-list-menu/network-list-menu.test.js b/ui/components/multichain/network-list-menu/network-list-menu.test.js index 031ad257317c..ffd96256e336 100644 --- a/ui/components/multichain/network-list-menu/network-list-menu.test.js +++ b/ui/components/multichain/network-list-menu/network-list-menu.test.js @@ -61,6 +61,10 @@ describe('NetworkListMenu', () => { mockNetworkMenuRedesignToggle.mockReturnValue(false); }); + it('renders properly', () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); it('displays important controls', () => { const { getByText, getByPlaceholderText } = render(); @@ -129,6 +133,7 @@ describe('NetworkListMenu', () => { expect(queryByText('Chain 5')).toBeInTheDocument(); const searchBox = getByPlaceholderText('Search'); + fireEvent.focus(searchBox); fireEvent.change(searchBox, { target: { value: 'Main' } }); expect(queryByText('Chain 5')).not.toBeInTheDocument(); @@ -150,4 +155,51 @@ describe('NetworkListMenu', () => { document.querySelectorAll('multichain-network-list-item__delete'), ).toHaveLength(0); }); + + describe('NetworkListMenu with ENABLE_NETWORK_UI_REDESIGN', () => { + // Set the environment variable before tests run + beforeEach(() => { + process.env.ENABLE_NETWORK_UI_REDESIGN = 'true'; + }); + + // Reset the environment variable after tests complete + afterEach(() => { + delete process.env.ENABLE_NETWORK_UI_REDESIGN; + }); + + it('should display "Arbitrum" when ENABLE_NETWORK_UI_REDESIGN is true', async () => { + const { queryByText, getByPlaceholderText } = render(); + + // Now "Arbitrum" should be in the document if PopularNetworkList is rendered + expect(queryByText('Arbitrum One')).toBeInTheDocument(); + + // Simulate typing "Optimism" into the search box + const searchBox = getByPlaceholderText('Search'); + fireEvent.focus(searchBox); + fireEvent.change(searchBox, { target: { value: 'OP Mainnet' } }); + + // "Optimism" should be visible, but "Arbitrum" should not + expect(queryByText('OP Mainnet')).toBeInTheDocument(); + expect(queryByText('Arbitrum One')).not.toBeInTheDocument(); + }); + + it('should filter testNets when ENABLE_NETWORK_UI_REDESIGN is true', async () => { + const { queryByText, getByPlaceholderText } = render({ + showTestNetworks: true, + }); + + // Check if all testNets are available + expect(queryByText('Linea Sepolia')).toBeInTheDocument(); + expect(queryByText('Sepolia')).toBeInTheDocument(); + + // Simulate typing "Linea Sepolia" into the search box + const searchBox = getByPlaceholderText('Search'); + fireEvent.focus(searchBox); + fireEvent.change(searchBox, { target: { value: 'Linea Sepolia' } }); + + // "Linea Sepolia" should be visible, but "Sepolia" should not + expect(queryByText('Linea Sepolia')).toBeInTheDocument(); + expect(queryByText('Sepolia')).not.toBeInTheDocument(); + }); + }); }); diff --git a/ui/components/multichain/network-list-menu/network-list-search/__snapshots__/network-list-search.test.tsx.snap b/ui/components/multichain/network-list-menu/network-list-search/__snapshots__/network-list-search.test.tsx.snap new file mode 100644 index 000000000000..6b2597430661 --- /dev/null +++ b/ui/components/multichain/network-list-menu/network-list-search/__snapshots__/network-list-search.test.tsx.snap @@ -0,0 +1,28 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NetworkListSearch renders search list component 1`] = ` +<div> + <div + class="mm-box mm-box--padding-top-0 mm-box--padding-right-4 mm-box--padding-bottom-4 mm-box--padding-left-4" + > + <div + class="mm-box mm-text-field mm-text-field--size-lg mm-text-field--focused mm-text-field--truncate mm-text-field-search mm-box--padding-right-0 mm-box--padding-left-4 mm-box--display-inline-flex mm-box--align-items-center mm-box--width-full mm-box--background-color-background-default mm-box--rounded-sm mm-box--border-width-1 box--border-style-solid" + data-testid="search-list" + > + <span + class="mm-box mm-icon mm-icon--size-sm mm-box--display-inline-block mm-box--color-inherit" + style="mask-image: url('./images/icons/search.svg');" + /> + <input + autocomplete="off" + class="mm-box mm-text mm-input mm-input--disable-state-styles mm-text-field__input mm-text--body-md mm-box--margin-0 mm-box--margin-right-6 mm-box--padding-0 mm-box--padding-right-4 mm-box--padding-left-2 mm-box--color-text-default mm-box--background-color-transparent mm-box--border-style-none" + data-testid="network-redesign-modal-search-input" + focused="true" + placeholder="search" + type="search" + value="" + /> + </div> + </div> +</div> +`; diff --git a/ui/components/multichain/network-list-menu/network-list-search/network-list-search.test.tsx b/ui/components/multichain/network-list-menu/network-list-search/network-list-search.test.tsx new file mode 100644 index 000000000000..c6b164976563 --- /dev/null +++ b/ui/components/multichain/network-list-menu/network-list-search/network-list-search.test.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { render, fireEvent } from '@testing-library/react'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; +import NetworkListSearch from './network-list-search'; + +jest.mock('../../../../hooks/useI18nContext', () => ({ + useI18nContext: jest.fn(), +})); + +describe('NetworkListSearch', () => { + const mockSetSearchQuery = jest.fn(); + const mockSetFocusSearch = jest.fn(); + const useI18nContextMock = useI18nContext as jest.Mock; + + beforeEach(() => { + jest.clearAllMocks(); + useI18nContextMock.mockReturnValue((key: string) => key); + }); + + it('renders search list component', () => { + const { container } = render( + <NetworkListSearch + searchQuery="" + setSearchQuery={mockSetSearchQuery} + setFocusSearch={mockSetFocusSearch} + />, + ); + + expect(container).toMatchSnapshot(); + }); + + it('should update search query on user input', () => { + const { getByPlaceholderText } = render( + <NetworkListSearch + searchQuery="" + setSearchQuery={mockSetSearchQuery} + setFocusSearch={mockSetFocusSearch} + />, + ); + + const searchInput = getByPlaceholderText('search'); + fireEvent.change(searchInput, { target: { value: 'Ethereum' } }); + + expect(mockSetSearchQuery).toHaveBeenCalledWith('Ethereum'); + }); + + it('should clear search query when clear button is clicked', () => { + const { getByRole } = render( + <NetworkListSearch + searchQuery="Ethereum" + setSearchQuery={mockSetSearchQuery} + setFocusSearch={mockSetFocusSearch} + />, + ); + + const clearButton = getByRole('button', { name: /clear/u }); + fireEvent.click(clearButton); + + expect(mockSetSearchQuery).toHaveBeenCalledWith(''); + }); +}); diff --git a/ui/components/multichain/network-list-menu/network-list-search/network-list-search.tsx b/ui/components/multichain/network-list-menu/network-list-search/network-list-search.tsx new file mode 100644 index 000000000000..fdd74ec8a444 --- /dev/null +++ b/ui/components/multichain/network-list-menu/network-list-search/network-list-search.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; +import { + Box, + ButtonIconSize, + TextFieldSearch, + TextFieldSearchSize, +} from '../../../component-library'; +import { BlockSize } from '../../../../helpers/constants/design-system'; + +const NetworkListSearch = ({ + searchQuery, + setSearchQuery, + setFocusSearch, +}: { + searchQuery: string; + setSearchQuery: (query: string) => void; + setFocusSearch: (val: boolean) => void; +}) => { + const t = useI18nContext(); + + return ( + <Box paddingLeft={4} paddingRight={4} paddingBottom={4} paddingTop={0}> + <TextFieldSearch + size={TextFieldSearchSize.Lg} + width={BlockSize.Full} + placeholder={t('search')} + autoFocus + value={searchQuery} + onFocus={() => setFocusSearch(true)} + onBlur={() => setFocusSearch(false)} + onChange={(e) => setSearchQuery(e.target.value)} + clearButtonOnClick={() => setSearchQuery('')} + clearButtonProps={{ + size: ButtonIconSize.Sm, + }} + inputProps={{ 'data-testid': 'network-redesign-modal-search-input' }} + data-testid="search-list" + /> + </Box> + ); +}; + +export default NetworkListSearch; From 64c249771fbcf2440c94d897e74a8328f23e4788 Mon Sep 17 00:00:00 2001 From: sahar-fehri <sahar.fehri@consensys.net> Date: Thu, 13 Jun 2024 18:06:07 +0200 Subject: [PATCH 35/61] fix: fix token detection modal stuck on firefox (#25279) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Token detection modal seems to stay stuck on firefox [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25279?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/metamask-extension/issues/25256 ## **Manual testing steps** To run locally use: `rm -rf dist && ENABLE_MV3=false yarn && ENABLE_MV3=false yarn build:dev dev --build-type main --lockdown false --snow false --apply-lavamoat false` 1. Import wallet on firefox 2. Got to settings => security and privacy and disable token auto detection 3. Go back to home page and you should see the token detection modal 4. Clicking on allow should dismiss the modal and enable the token detection ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> https://github.com/MetaMask/metamask-extension/assets/10994169/e23f59d6-7bc9-4707-872d-436c1a56e7cf ### **After** https://github.com/MetaMask/metamask-extension/assets/10994169/cf47e04c-e5bc-4898-92f1-c80c87988fdb ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com> --- .../app/auto-detect-token/auto-detect-token-modal.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/components/app/auto-detect-token/auto-detect-token-modal.tsx b/ui/components/app/auto-detect-token/auto-detect-token-modal.tsx index 27ea2bfcaf70..cf03216ec3ca 100644 --- a/ui/components/app/auto-detect-token/auto-detect-token-modal.tsx +++ b/ui/components/app/auto-detect-token/auto-detect-token-modal.tsx @@ -45,6 +45,7 @@ function AutoDetectTokenModal({ const dispatch = useDispatch(); const trackEvent = useContext(MetaMetricsContext); const { chainId } = useSelector(getProviderConfig); + const locale = useSelector(getCurrentLocale); const handleTokenAutoDetection = useCallback( (val) => { @@ -55,7 +56,7 @@ function AutoDetectTokenModal({ category: MetaMetricsEventCategory.Navigation, properties: { chain_id: chainId, - locale: getCurrentLocale, + locale, referrer: ORIGIN_METAMASK, }, }); From e3071f20ccff8e1a3b76084c05ee5203f9f4de26 Mon Sep 17 00:00:00 2001 From: Frederik Bolding <frederik.bolding@gmail.com> Date: Thu, 13 Jun 2024 18:25:43 +0200 Subject: [PATCH 36/61] feat: Use sandboxed pages for Snaps execution in MV3 (#25171) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Moves the execution of Snaps to a [sandboxed page](https://developer.chrome.com/docs/extensions/how-to/security/sandboxing-eval) referencing a local HTML file inside the offscreen document when using the MV3 build. This effectively gives us access to `eval` without hitting the network and should reduce the overhead when booting a Snap (+ allow for Snaps to execute when the user is offline). To support this, this PR introduces some new changes to the manifest as well as the build process. For the build process we simply copy the same iframe bundle currently used in the hosted version to `/dist/chrome/snaps`. For the manifest, we add a reference to the sandboxed page and tweak the CSP of the sandbox to be as restrictive as possible (the default is not very strict). Then we can simply point the existing offscreen executor to use the local iframe instead of the remote one. Closes https://github.com/MetaMask/metamask-extension/issues/25250 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25171?quickstart=1) --- app/manifest/v3/_base.json | 3 +++ app/manifest/v3/chrome.json | 3 ++- development/build/static.js | 21 +++++++++++++++++++++ offscreen/scripts/offscreen.ts | 2 +- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/app/manifest/v3/_base.json b/app/manifest/v3/_base.json index 39e96825add8..f3ffbf07c173 100644 --- a/app/manifest/v3/_base.json +++ b/app/manifest/v3/_base.json @@ -75,5 +75,8 @@ "webRequest", "offscreen" ], + "sandbox": { + "pages": ["snaps/index.html"] + }, "short_name": "__MSG_appName__" } diff --git a/app/manifest/v3/chrome.json b/app/manifest/v3/chrome.json index 79656e26f0f9..2308cc912b55 100644 --- a/app/manifest/v3/chrome.json +++ b/app/manifest/v3/chrome.json @@ -1,6 +1,7 @@ { "content_security_policy": { - "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'none'; frame-ancestors 'none';" + "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'none'; frame-ancestors 'none';", + "sandbox": "sandbox allow-scripts; script-src 'self' 'unsafe-inline' 'unsafe-eval'; object-src 'none'; default-src 'none'; connect-src *;" }, "externally_connectable": { "matches": ["https://metamask.io/*"], diff --git a/development/build/static.js b/development/build/static.js index 5729828568d6..ecff5d2501c0 100644 --- a/development/build/static.js +++ b/development/build/static.js @@ -202,6 +202,27 @@ function getCopyTargets( pattern: `*.html`, dest: '', }, + ...(process.env.ENABLE_MV3 === 'true' || + process.env.ENABLE_MV3 === undefined + ? [ + { + src: getPathInsideNodeModules( + '@metamask/snaps-execution-environments', + 'dist/browserify/iframe/index.html', + ), + dest: `snaps/index.html`, + pattern: '', + }, + { + src: getPathInsideNodeModules( + '@metamask/snaps-execution-environments', + 'dist/browserify/iframe/bundle.js', + ), + dest: `snaps/bundle.js`, + pattern: '', + }, + ] + : []), ]; if (activeFeatures.includes('blockaid')) { diff --git a/offscreen/scripts/offscreen.ts b/offscreen/scripts/offscreen.ts index 8c0598b4bd3f..7eddac9cb840 100644 --- a/offscreen/scripts/offscreen.ts +++ b/offscreen/scripts/offscreen.ts @@ -19,4 +19,4 @@ const parentStream = new BrowserRuntimePostMessageStream({ target: 'parent', }); -ProxySnapExecutor.initialize(parentStream); +ProxySnapExecutor.initialize(parentStream, './snaps/index.html'); From 82efbdfe91ee40aa9747c7f9eebb0906e0a350e4 Mon Sep 17 00:00:00 2001 From: Devin <168687171+Devin-Apps@users.noreply.github.com> Date: Thu, 13 Jun 2024 22:36:00 +0530 Subject: [PATCH 37/61] refactor: Part of #17670- Replace Typography with Text component in confirm-recovery-phrase.js (#25019) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Migrated the `Typography` component to the `Text` component in the `confirm-recovery-phrase.js` file, ensuring that specific variants and props are updated accordingly. ### Devin Preview Link https://preview.devin.ai/devin/fb1ad1cf9af64c40b1eb876b52b7b79c ## **Related issues** Partially Fixes: https://github.com/MetaMask/metamask-extension/issues/17670 ## **Manual testing steps** 1. Go to the latest build of storybook in this PR 2. Manually check if the page `ConfirmRecoveryPhrase` renders correctly ## **Screenshots** ### Before ![](https://api.devin.ai/attachments/32458e32-bc11-47fc-996b-a8c97c5ed3ec/before_changes_confirm-recovery-phrase.png) ### After <img width="1646" alt="con" src="https://github.com/MetaMask/metamask-extension/assets/168687171/b2f3b614-db29-4045-a03b-f0d3b0829564"> ## **Pre-merge author checklist** - [X] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I’ve included tests if applicable - [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [X] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [X] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Shreyasi Mandal <shreyasi18sia@gmail.com> --- .../confirm-recovery-phrase.js | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/ui/pages/onboarding-flow/recovery-phrase/confirm-recovery-phrase.js b/ui/pages/onboarding-flow/recovery-phrase/confirm-recovery-phrase.js index c933bd561af1..fe788e211318 100644 --- a/ui/pages/onboarding-flow/recovery-phrase/confirm-recovery-phrase.js +++ b/ui/pages/onboarding-flow/recovery-phrase/confirm-recovery-phrase.js @@ -5,12 +5,12 @@ import { debounce } from 'lodash'; import PropTypes from 'prop-types'; import Box from '../../../components/ui/box'; import Button from '../../../components/ui/button'; -import Typography from '../../../components/ui/typography'; +import { Text } from '../../../components/component-library'; import { - TEXT_ALIGN, - TypographyVariant, + TextAlign, + TextVariant, JustifyContent, - FONT_WEIGHT, + FontWeight, } from '../../../helpers/constants/design-system'; import { ThreeStepProgressBar, @@ -73,24 +73,21 @@ export default function ConfirmRecoveryPhrase({ secretRecoveryPhrase = '' }) { /> <Box justifyContent={JustifyContent.center} - textAlign={TEXT_ALIGN.CENTER} + textAlign={TextAlign.Center} marginBottom={4} > - <Typography - variant={TypographyVariant.H2} - fontWeight={FONT_WEIGHT.BOLD} - > + <Text variant={TextVariant.headingLg} fontWeight={FontWeight.Bold}> {t('seedPhraseConfirm')} - </Typography> + </Text> </Box> <Box justifyContent={JustifyContent.center} - textAlign={TEXT_ALIGN.CENTER} + textAlign={TextAlign.Center} marginBottom={4} > - <Typography variant={TypographyVariant.H4}> + <Text variant={TextVariant.headingSm} fontWeight={FontWeight.Normal}> {t('seedPhraseEnterMissingWords')} - </Typography> + </Text> </Box> <RecoveryPhraseChips secretRecoveryPhrase={splitSecretRecoveryPhrase} From 69837108d5b3bb4d9d94584ec3e5b5fad86b0993 Mon Sep 17 00:00:00 2001 From: Devin <168687171+Devin-Apps@users.noreply.github.com> Date: Thu, 13 Jun 2024 22:43:09 +0530 Subject: [PATCH 38/61] refactor: Replace Typography with Text component in skip-srp-backup-popover.js (#25149) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Migrate Typography to Text in `skip-srp-backup-popover.js` Devin Run Link: https://preview.devin.ai/devin/c985a865ba6044c9bf43ecceea4433ac [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25149?quickstart=1) ## **Related issues** Partially Fixes: https://github.com/MetaMask/metamask-extension/issues/17670 ## **Manual testing steps** 1. Go to the latest build of storybook in this PR 2. Manually check if `SkipSRPBackupPopover` is rendered properly. ## **Screenshots/Recordings** ### **Before** <img width="1653" alt="Screenshot 2024-06-13 at 10 11 31" src="https://github.com/MetaMask/metamask-extension/assets/168687171/fe1fb5f6-0fa2-4732-87dc-d746cd6a4606"> ### **After** <img width="1653" alt="Screenshot 2024-06-13 at 09 42 19" src="https://github.com/MetaMask/metamask-extension/assets/168687171/eee08b46-4c7b-45bb-9cd8-873388de98f7"> ## **Pre-merge author checklist** - [X] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I’ve included tests if applicable - [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../skip-srp-backup-popover.js | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/ui/pages/onboarding-flow/secure-your-wallet/skip-srp-backup-popover.js b/ui/pages/onboarding-flow/secure-your-wallet/skip-srp-backup-popover.js index e3017cc86be9..22af8be7e7ea 100644 --- a/ui/pages/onboarding-flow/secure-your-wallet/skip-srp-backup-popover.js +++ b/ui/pages/onboarding-flow/secure-your-wallet/skip-srp-backup-popover.js @@ -6,14 +6,18 @@ import { useI18nContext } from '../../../hooks/useI18nContext'; import Button from '../../../components/ui/button'; import Popover from '../../../components/ui/popover'; import Box from '../../../components/ui/box'; -import Typography from '../../../components/ui/typography'; +import { + Text, + Icon, + IconName, + IconSize, +} from '../../../components/component-library'; import { AlignItems, IconColor, FLEX_DIRECTION, - FONT_WEIGHT, JustifyContent, - TypographyVariant, + TextVariant, } from '../../../helpers/constants/design-system'; import { setSeedPhraseBackedUp } from '../../../store/actions'; import Checkbox from '../../../components/ui/check-box'; @@ -23,11 +27,6 @@ import { MetaMetricsEventName, } from '../../../../shared/constants/metametrics'; import { MetaMetricsContext } from '../../../contexts/metametrics'; -import { - Icon, - IconName, - IconSize, -} from '../../../components/component-library'; export default function SkipSRPBackup({ handleClose }) { const [checked, setChecked] = useState(false); @@ -91,12 +90,7 @@ export default function SkipSRPBackup({ handleClose }) { className="skip-srp-backup-popover__icon" color={IconColor.errorDefault} /> - <Typography - variant={TypographyVariant.H3} - fontWeight={FONT_WEIGHT.BOLD} - > - {t('skipAccountSecurity')} - </Typography> + <Text variant={TextVariant.headingMd}>{t('skipAccountSecurity')}</Text> <Box justifyContent={JustifyContent.center} margin={3}> <label className="skip-srp-backup-popover__label"> <Checkbox @@ -105,12 +99,9 @@ export default function SkipSRPBackup({ handleClose }) { checked={checked} dataTestId="skip-srp-backup-popover-checkbox" /> - <Typography - className="skip-srp-backup-popover__details" - variant={TypographyVariant.H7} - > + <Text className="skip-srp-backup-popover__details"> {t('skipAccountSecurityDetails')} - </Typography> + </Text> </label> </Box> </Box> From 04642d21f9feeccd09b16fa318c6c7876fd34ab1 Mon Sep 17 00:00:00 2001 From: Derek Brans <dbrans@gmail.com> Date: Thu, 13 Jun 2024 13:48:38 -0400 Subject: [PATCH 39/61] chore: revert recent gas api endpoint changes (#25230) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > [!NOTE] > Once this PR is merged into develop, it will be cherry-picked into the next 11.16 hotfix as well as v12.0.0. ## **Description** We need to move quickly on a hotfix for the Extension due to a caching issue with the [infura.io](http://infura.io/) endpoint. The [API team has asked](https://consensys.slack.com/archives/C05B78N1T9B/p1717783170599949) us to revert a recent gas API endpoint change until the issue is resolved, which could take months. Here is what is in this PR: - apply patch using core patch branch MetaMask/core/pull/4403 - revert #23717 ### Re: Large gas-fee-controller patch file The renaming of `chunk` files in the `dist` folder of the gas-fee-controller are the cause of the large .patch file. For more context, see this [slack thread](https://consensys.slack.com/archives/CTQAGKY5V/p1718123930090259?thread_ts=1718123750.012709&cid=CTQAGKY5V). ### Re: Transitive dependencies on `gas-fee-controller@17.0.0` Although `transaction-controller` and `user-operation-controller` depend on v17, they can be safely ignored. The only runtime dependency those packages have is on the [enum-like GAS_ESTIMATE_TYPES](https://github.com/MetaMask/core/blob/dcc1d9291297ca2106cd2a461c51ce2f4667d84d/packages/gas-fee-controller/src/GasFeeController.ts#L61-L66), ([example1](https://github.com/MetaMask/core/blob/dcc1d9291297ca2106cd2a461c51ce2f4667d84d/packages/user-operation-controller/src/utils/gas-fees.ts#L224), [example2](https://github.com/MetaMask/core/blob/dcc1d9291297ca2106cd2a461c51ce2f4667d84d/packages/transaction-controller/src/gas-flows/DefaultGasFeeFlow.ts#L41-L62)) which hasn't be touched in [3 years](https://github.com/MetaMask/core/pull/494/files#diff-ac8f6d6d8ff039810f56d99da8735d4eb8c2978eed2685b1741c9124c7b8bb6fR47-R52). ### After the hotfix we need to: 1. Revert MetaMask/core/pulls/4068 in core on top of the latest gas-fee-controller (v17) 2. Upgrade gas-fee-controller in Extension and Mobile [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25230?quickstart=1) ## **Related issues** - Related: https://github.com/MetaMask/metamask-extension/issues/25194 ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com> --- ...fee-controller-npm-15.1.2-db4d2976aa.patch | 2630 +++++++++++++++++ app/scripts/metamask-controller.js | 13 +- lavamoat/browserify/beta/policy.json | 1 - lavamoat/browserify/flask/policy.json | 1 - lavamoat/browserify/main/policy.json | 1 - lavamoat/browserify/mmi/policy.json | 1 - package.json | 5 +- privacy-snapshot.json | 2 +- shared/constants/swaps.ts | 2 +- shared/lib/swaps-utils.js | 3 +- test/e2e/mock-e2e.js | 97 +- test/jest/constants.js | 2 +- ui/pages/swaps/swaps.util.ts | 13 +- yarn.lock | 25 +- 14 files changed, 2718 insertions(+), 78 deletions(-) create mode 100644 .yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch diff --git a/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch b/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch new file mode 100644 index 000000000000..e4e69c39609c --- /dev/null +++ b/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch @@ -0,0 +1,2630 @@ +diff --git a/dist/GasFeeController.js b/dist/GasFeeController.js +index 089bba219bac937eeccb423f3e69ad5407ef9be0..b6bdda12ceeb0c38b344b20f80c3afc5120ce3f9 100644 +--- a/dist/GasFeeController.js ++++ b/dist/GasFeeController.js +@@ -3,12 +3,12 @@ + + + +-var _chunkH5WHAYLIjs = require('./chunk-H5WHAYLI.js'); +-require('./chunk-Q2YPK5SL.js'); ++var _chunkX74LQX2Yjs = require('./chunk-X74LQX2Y.js'); ++require('./chunk-2MFVV2BX.js'); + + + + + +-exports.GAS_API_BASE_URL = _chunkH5WHAYLIjs.GAS_API_BASE_URL; exports.GAS_ESTIMATE_TYPES = _chunkH5WHAYLIjs.GAS_ESTIMATE_TYPES; exports.GasFeeController = _chunkH5WHAYLIjs.GasFeeController; exports.default = _chunkH5WHAYLIjs.GasFeeController_default; ++exports.GAS_ESTIMATE_TYPES = _chunkX74LQX2Yjs.GAS_ESTIMATE_TYPES; exports.GasFeeController = _chunkX74LQX2Yjs.GasFeeController; exports.LEGACY_GAS_PRICES_API_URL = _chunkX74LQX2Yjs.LEGACY_GAS_PRICES_API_URL; exports.default = _chunkX74LQX2Yjs.GasFeeController_default; + //# sourceMappingURL=GasFeeController.js.map +\ No newline at end of file +diff --git a/dist/GasFeeController.mjs b/dist/GasFeeController.mjs +index 14ab557e85665a30cbd8b4cec41448d5b88fed91..9b9b90786ac35a4cf320d00a933ef151cdf03821 100644 +--- a/dist/GasFeeController.mjs ++++ b/dist/GasFeeController.mjs +@@ -1,14 +1,14 @@ + import { +- GAS_API_BASE_URL, + GAS_ESTIMATE_TYPES, + GasFeeController, +- GasFeeController_default +-} from "./chunk-BEVZS3YV.mjs"; +-import "./chunk-KORLXV32.mjs"; ++ GasFeeController_default, ++ LEGACY_GAS_PRICES_API_URL ++} from "./chunk-A7NHJBXX.mjs"; ++import "./chunk-R3IOI7AK.mjs"; + export { +- GAS_API_BASE_URL, + GAS_ESTIMATE_TYPES, + GasFeeController, ++ LEGACY_GAS_PRICES_API_URL, + GasFeeController_default as default + }; + //# sourceMappingURL=GasFeeController.mjs.map +\ No newline at end of file +diff --git a/dist/chunk-2MFVV2BX.js b/dist/chunk-2MFVV2BX.js +new file mode 100644 +index 0000000000000000000000000000000000000000..4f83a713baa28f3d687c50ed7ad3c79715a2b588 +--- /dev/null ++++ b/dist/chunk-2MFVV2BX.js +@@ -0,0 +1,156 @@ ++"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var __accessCheck = (obj, member, msg) => { ++ if (!member.has(obj)) ++ throw TypeError("Cannot " + msg); ++}; ++var __privateGet = (obj, member, getter) => { ++ __accessCheck(obj, member, "read from private field"); ++ return getter ? getter.call(obj) : member.get(obj); ++}; ++var __privateAdd = (obj, member, value) => { ++ if (member.has(obj)) ++ throw TypeError("Cannot add the same private member more than once"); ++ member instanceof WeakSet ? member.add(obj) : member.set(obj, value); ++}; ++var __privateSet = (obj, member, value, setter) => { ++ __accessCheck(obj, member, "write to private field"); ++ setter ? setter.call(obj, value) : member.set(obj, value); ++ return value; ++}; ++var __privateMethod = (obj, member, method) => { ++ __accessCheck(obj, member, "access private method"); ++ return method; ++}; ++ ++// src/gas-util.ts ++ ++ ++ ++ ++ ++var _controllerutils = require('@metamask/controller-utils'); ++var _bnjs = require('bn.js'); var _bnjs2 = _interopRequireDefault(_bnjs); ++var makeClientIdHeader = (clientId) => ({ "X-Client-Id": clientId }); ++function normalizeGWEIDecimalNumbers(n) { ++ const numberAsWEIHex = _controllerutils.gweiDecToWEIBN.call(void 0, n).toString(16); ++ const numberAsGWEI = _controllerutils.weiHexToGweiDec.call(void 0, numberAsWEIHex); ++ return numberAsGWEI; ++} ++async function fetchGasEstimates(url, clientId) { ++ const estimates = await _controllerutils.handleFetch.call(void 0, ++ url, ++ clientId ? { headers: makeClientIdHeader(clientId) } : void 0 ++ ); ++ return { ++ low: { ++ ...estimates.low, ++ suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.low.suggestedMaxPriorityFeePerGas ++ ), ++ suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.low.suggestedMaxFeePerGas ++ ) ++ }, ++ medium: { ++ ...estimates.medium, ++ suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.medium.suggestedMaxPriorityFeePerGas ++ ), ++ suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.medium.suggestedMaxFeePerGas ++ ) ++ }, ++ high: { ++ ...estimates.high, ++ suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.high.suggestedMaxPriorityFeePerGas ++ ), ++ suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.high.suggestedMaxFeePerGas ++ ) ++ }, ++ estimatedBaseFee: normalizeGWEIDecimalNumbers(estimates.estimatedBaseFee), ++ historicalBaseFeeRange: estimates.historicalBaseFeeRange, ++ baseFeeTrend: estimates.baseFeeTrend, ++ latestPriorityFeeRange: estimates.latestPriorityFeeRange, ++ historicalPriorityFeeRange: estimates.historicalPriorityFeeRange, ++ priorityFeeTrend: estimates.priorityFeeTrend, ++ networkCongestion: estimates.networkCongestion ++ }; ++} ++async function fetchLegacyGasPriceEstimates(url, clientId) { ++ const result = await _controllerutils.handleFetch.call(void 0, url, { ++ referrer: url, ++ referrerPolicy: "no-referrer-when-downgrade", ++ method: "GET", ++ mode: "cors", ++ headers: { ++ "Content-Type": "application/json", ++ ...clientId && makeClientIdHeader(clientId) ++ } ++ }); ++ return { ++ low: result.SafeGasPrice, ++ medium: result.ProposeGasPrice, ++ high: result.FastGasPrice ++ }; ++} ++async function fetchEthGasPriceEstimate(ethQuery) { ++ const gasPrice = await _controllerutils.query.call(void 0, ethQuery, "gasPrice"); ++ return { ++ gasPrice: _controllerutils.weiHexToGweiDec.call(void 0, gasPrice).toString() ++ }; ++} ++function calculateTimeEstimate(maxPriorityFeePerGas, maxFeePerGas, gasFeeEstimates) { ++ const { low, medium, high, estimatedBaseFee } = gasFeeEstimates; ++ const maxPriorityFeePerGasInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, maxPriorityFeePerGas); ++ const maxFeePerGasInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, maxFeePerGas); ++ const estimatedBaseFeeInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, estimatedBaseFee); ++ const effectiveMaxPriorityFee = _bnjs2.default.min( ++ maxPriorityFeePerGasInWEI, ++ maxFeePerGasInWEI.sub(estimatedBaseFeeInWEI) ++ ); ++ const lowMaxPriorityFeeInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, ++ low.suggestedMaxPriorityFeePerGas ++ ); ++ const mediumMaxPriorityFeeInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, ++ medium.suggestedMaxPriorityFeePerGas ++ ); ++ const highMaxPriorityFeeInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, ++ high.suggestedMaxPriorityFeePerGas ++ ); ++ let lowerTimeBound; ++ let upperTimeBound; ++ if (effectiveMaxPriorityFee.lt(lowMaxPriorityFeeInWEI)) { ++ lowerTimeBound = null; ++ upperTimeBound = "unknown"; ++ } else if (effectiveMaxPriorityFee.gte(lowMaxPriorityFeeInWEI) && effectiveMaxPriorityFee.lt(mediumMaxPriorityFeeInWEI)) { ++ lowerTimeBound = low.minWaitTimeEstimate; ++ upperTimeBound = low.maxWaitTimeEstimate; ++ } else if (effectiveMaxPriorityFee.gte(mediumMaxPriorityFeeInWEI) && effectiveMaxPriorityFee.lt(highMaxPriorityFeeInWEI)) { ++ lowerTimeBound = medium.minWaitTimeEstimate; ++ upperTimeBound = medium.maxWaitTimeEstimate; ++ } else if (effectiveMaxPriorityFee.eq(highMaxPriorityFeeInWEI)) { ++ lowerTimeBound = high.minWaitTimeEstimate; ++ upperTimeBound = high.maxWaitTimeEstimate; ++ } else { ++ lowerTimeBound = 0; ++ upperTimeBound = high.maxWaitTimeEstimate; ++ } ++ return { ++ lowerTimeBound, ++ upperTimeBound ++ }; ++} ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++exports.__privateGet = __privateGet; exports.__privateAdd = __privateAdd; exports.__privateSet = __privateSet; exports.__privateMethod = __privateMethod; exports.normalizeGWEIDecimalNumbers = normalizeGWEIDecimalNumbers; exports.fetchGasEstimates = fetchGasEstimates; exports.fetchLegacyGasPriceEstimates = fetchLegacyGasPriceEstimates; exports.fetchEthGasPriceEstimate = fetchEthGasPriceEstimate; exports.calculateTimeEstimate = calculateTimeEstimate; ++//# sourceMappingURL=chunk-2MFVV2BX.js.map +\ No newline at end of file +diff --git a/dist/chunk-2MFVV2BX.js.map b/dist/chunk-2MFVV2BX.js.map +new file mode 100644 +index 0000000000000000000000000000000000000000..c6d83c1c168ee0b053be10a74334ac712bb6a6a1 +--- /dev/null ++++ b/dist/chunk-2MFVV2BX.js.map +@@ -0,0 +1 @@ ++{"version":3,"sources":["../src/gas-util.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n query,\n handleFetch,\n gweiDecToWEIBN,\n weiHexToGweiDec,\n} from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport BN from 'bn.js';\n\nimport type {\n GasFeeEstimates,\n EthGasPriceEstimate,\n EstimatedGasFeeTimeBounds,\n unknownString,\n LegacyGasPriceEstimate,\n} from './GasFeeController';\n\nconst makeClientIdHeader = (clientId: string) => ({ 'X-Client-Id': clientId });\n\n/**\n * Convert a decimal GWEI value to a decimal string rounded to the nearest WEI.\n *\n * @param n - The input GWEI amount, as a decimal string or a number.\n * @returns The decimal string GWEI amount.\n */\nexport function normalizeGWEIDecimalNumbers(n: string | number) {\n const numberAsWEIHex = gweiDecToWEIBN(n).toString(16);\n const numberAsGWEI = weiHexToGweiDec(numberAsWEIHex);\n return numberAsGWEI;\n}\n\n/**\n * Fetch gas estimates from the given URL.\n *\n * @param url - The gas estimate URL.\n * @param clientId - The client ID used to identify to the API who is asking for estimates.\n * @returns The gas estimates.\n */\nexport async function fetchGasEstimates(\n url: string,\n clientId?: string,\n): Promise<GasFeeEstimates> {\n const estimates = await handleFetch(\n url,\n clientId ? { headers: makeClientIdHeader(clientId) } : undefined,\n );\n return {\n low: {\n ...estimates.low,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.low.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.low.suggestedMaxFeePerGas,\n ),\n },\n medium: {\n ...estimates.medium,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.medium.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.medium.suggestedMaxFeePerGas,\n ),\n },\n high: {\n ...estimates.high,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.high.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.high.suggestedMaxFeePerGas,\n ),\n },\n estimatedBaseFee: normalizeGWEIDecimalNumbers(estimates.estimatedBaseFee),\n historicalBaseFeeRange: estimates.historicalBaseFeeRange,\n baseFeeTrend: estimates.baseFeeTrend,\n latestPriorityFeeRange: estimates.latestPriorityFeeRange,\n historicalPriorityFeeRange: estimates.historicalPriorityFeeRange,\n priorityFeeTrend: estimates.priorityFeeTrend,\n networkCongestion: estimates.networkCongestion,\n };\n}\n\n/**\n * Hit the legacy MetaSwaps gasPrices estimate api and return the low, medium\n * high values from that API.\n *\n * @param url - The URL to fetch gas price estimates from.\n * @param clientId - The client ID used to identify to the API who is asking for estimates.\n * @returns The gas price estimates.\n */\nexport async function fetchLegacyGasPriceEstimates(\n url: string,\n clientId?: string,\n): Promise<LegacyGasPriceEstimate> {\n const result = await handleFetch(url, {\n referrer: url,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n headers: {\n 'Content-Type': 'application/json',\n ...(clientId && makeClientIdHeader(clientId)),\n },\n });\n return {\n low: result.SafeGasPrice,\n medium: result.ProposeGasPrice,\n high: result.FastGasPrice,\n };\n}\n\n/**\n * Get a gas price estimate from the network using the `eth_gasPrice` method.\n *\n * @param ethQuery - The EthQuery instance to call the network with.\n * @returns A gas price estimate.\n */\nexport async function fetchEthGasPriceEstimate(\n ethQuery: EthQuery,\n): Promise<EthGasPriceEstimate> {\n const gasPrice = await query(ethQuery, 'gasPrice');\n return {\n gasPrice: weiHexToGweiDec(gasPrice).toString(),\n };\n}\n\n/**\n * Estimate the time it will take for a transaction to be confirmed.\n *\n * @param maxPriorityFeePerGas - The max priority fee per gas.\n * @param maxFeePerGas - The max fee per gas.\n * @param gasFeeEstimates - The gas fee estimates.\n * @returns The estimated lower and upper bounds for when this transaction will be confirmed.\n */\nexport function calculateTimeEstimate(\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n gasFeeEstimates: GasFeeEstimates,\n): EstimatedGasFeeTimeBounds {\n const { low, medium, high, estimatedBaseFee } = gasFeeEstimates;\n\n const maxPriorityFeePerGasInWEI = gweiDecToWEIBN(maxPriorityFeePerGas);\n const maxFeePerGasInWEI = gweiDecToWEIBN(maxFeePerGas);\n const estimatedBaseFeeInWEI = gweiDecToWEIBN(estimatedBaseFee);\n\n const effectiveMaxPriorityFee = BN.min(\n maxPriorityFeePerGasInWEI,\n maxFeePerGasInWEI.sub(estimatedBaseFeeInWEI),\n );\n\n const lowMaxPriorityFeeInWEI = gweiDecToWEIBN(\n low.suggestedMaxPriorityFeePerGas,\n );\n const mediumMaxPriorityFeeInWEI = gweiDecToWEIBN(\n medium.suggestedMaxPriorityFeePerGas,\n );\n const highMaxPriorityFeeInWEI = gweiDecToWEIBN(\n high.suggestedMaxPriorityFeePerGas,\n );\n\n let lowerTimeBound;\n let upperTimeBound;\n\n if (effectiveMaxPriorityFee.lt(lowMaxPriorityFeeInWEI)) {\n lowerTimeBound = null;\n upperTimeBound = 'unknown' as unknownString;\n } else if (\n effectiveMaxPriorityFee.gte(lowMaxPriorityFeeInWEI) &&\n effectiveMaxPriorityFee.lt(mediumMaxPriorityFeeInWEI)\n ) {\n lowerTimeBound = low.minWaitTimeEstimate;\n upperTimeBound = low.maxWaitTimeEstimate;\n } else if (\n effectiveMaxPriorityFee.gte(mediumMaxPriorityFeeInWEI) &&\n effectiveMaxPriorityFee.lt(highMaxPriorityFeeInWEI)\n ) {\n lowerTimeBound = medium.minWaitTimeEstimate;\n upperTimeBound = medium.maxWaitTimeEstimate;\n } else if (effectiveMaxPriorityFee.eq(highMaxPriorityFeeInWEI)) {\n lowerTimeBound = high.minWaitTimeEstimate;\n upperTimeBound = high.maxWaitTimeEstimate;\n } else {\n lowerTimeBound = 0;\n upperTimeBound = high.maxWaitTimeEstimate;\n }\n\n return {\n lowerTimeBound,\n upperTimeBound,\n };\n}\n"]} +\ No newline at end of file +diff --git a/dist/chunk-A7NHJBXX.mjs b/dist/chunk-A7NHJBXX.mjs +new file mode 100644 +index 0000000000000000000000000000000000000000..1dd920c4a314888548db98885976b336d2fec79d +--- /dev/null ++++ b/dist/chunk-A7NHJBXX.mjs +@@ -0,0 +1,390 @@ ++import { ++ __privateAdd, ++ __privateGet, ++ __privateMethod, ++ __privateSet, ++ calculateTimeEstimate, ++ fetchEthGasPriceEstimate, ++ fetchGasEstimates, ++ fetchLegacyGasPriceEstimates ++} from "./chunk-R3IOI7AK.mjs"; ++ ++// src/GasFeeController.ts ++import { ++ convertHexToDecimal, ++ safelyExecute, ++ toHex ++} from "@metamask/controller-utils"; ++import EthQuery from "@metamask/eth-query"; ++import { StaticIntervalPollingController } from "@metamask/polling-controller"; ++import { v1 as random } from "uuid"; ++var LEGACY_GAS_PRICES_API_URL = `https://api.metaswap.codefi.network/gasPrices`; ++var GAS_ESTIMATE_TYPES = { ++ FEE_MARKET: "fee-market", ++ LEGACY: "legacy", ++ ETH_GASPRICE: "eth_gasPrice", ++ NONE: "none" ++}; ++var metadata = { ++ gasFeeEstimatesByChainId: { ++ persist: true, ++ anonymous: false ++ }, ++ gasFeeEstimates: { persist: true, anonymous: false }, ++ estimatedGasFeeTimeBounds: { persist: true, anonymous: false }, ++ gasEstimateType: { persist: true, anonymous: false }, ++ nonRPCGasFeeApisDisabled: { persist: true, anonymous: false } ++}; ++var name = "GasFeeController"; ++var defaultState = { ++ gasFeeEstimatesByChainId: {}, ++ gasFeeEstimates: {}, ++ estimatedGasFeeTimeBounds: {}, ++ gasEstimateType: GAS_ESTIMATE_TYPES.NONE, ++ nonRPCGasFeeApisDisabled: false ++}; ++var _getProvider, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn; ++var GasFeeController = class extends StaticIntervalPollingController { ++ /** ++ * Creates a GasFeeController instance. ++ * ++ * @param options - The controller options. ++ * @param options.interval - The time in milliseconds to wait between polls. ++ * @param options.messenger - The controller messenger. ++ * @param options.state - The initial state. ++ * @param options.getCurrentNetworkEIP1559Compatibility - Determines whether or not the current ++ * network is EIP-1559 compatible. ++ * @param options.getCurrentNetworkLegacyGasAPICompatibility - Determines whether or not the ++ * current network is compatible with the legacy gas price API. ++ * @param options.getCurrentAccountEIP1559Compatibility - Determines whether or not the current ++ * account is EIP-1559 compatible. ++ * @param options.getChainId - Returns the current chain ID. ++ * @param options.getProvider - Returns a network provider for the current network. ++ * @param options.onNetworkDidChange - A function for registering an event handler for the ++ * network state change event. ++ * @param options.legacyAPIEndpoint - The legacy gas price API URL. This option is primarily for ++ * testing purposes. ++ * @param options.EIP1559APIEndpoint - The EIP-1559 gas price API URL. ++ * @param options.clientId - The client ID used to identify to the gas estimation API who is ++ * asking for estimates. ++ */ ++ constructor({ ++ interval = 15e3, ++ messenger, ++ state, ++ getCurrentNetworkEIP1559Compatibility, ++ getCurrentAccountEIP1559Compatibility, ++ getChainId, ++ getCurrentNetworkLegacyGasAPICompatibility, ++ getProvider, ++ onNetworkDidChange, ++ legacyAPIEndpoint = LEGACY_GAS_PRICES_API_URL, ++ EIP1559APIEndpoint, ++ clientId ++ }) { ++ super({ ++ name, ++ metadata, ++ messenger, ++ state: { ...defaultState, ...state } ++ }); ++ __privateAdd(this, _onNetworkControllerDidChange); ++ __privateAdd(this, _getProvider, void 0); ++ this.intervalDelay = interval; ++ this.setIntervalLength(interval); ++ this.pollTokens = /* @__PURE__ */ new Set(); ++ this.getCurrentNetworkEIP1559Compatibility = getCurrentNetworkEIP1559Compatibility; ++ this.getCurrentNetworkLegacyGasAPICompatibility = getCurrentNetworkLegacyGasAPICompatibility; ++ this.getCurrentAccountEIP1559Compatibility = getCurrentAccountEIP1559Compatibility; ++ __privateSet(this, _getProvider, getProvider); ++ this.EIP1559APIEndpoint = EIP1559APIEndpoint; ++ this.legacyAPIEndpoint = legacyAPIEndpoint; ++ this.clientId = clientId; ++ this.ethQuery = new EthQuery(__privateGet(this, _getProvider).call(this)); ++ if (onNetworkDidChange && getChainId) { ++ this.currentChainId = getChainId(); ++ onNetworkDidChange(async (networkControllerState) => { ++ await __privateMethod(this, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn).call(this, networkControllerState); ++ }); ++ } else { ++ this.currentChainId = this.messagingSystem.call( ++ "NetworkController:getState" ++ ).providerConfig.chainId; ++ this.messagingSystem.subscribe( ++ "NetworkController:networkDidChange", ++ async (networkControllerState) => { ++ await __privateMethod(this, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn).call(this, networkControllerState); ++ } ++ ); ++ } ++ } ++ async resetPolling() { ++ if (this.pollTokens.size !== 0) { ++ const tokens = Array.from(this.pollTokens); ++ this.stopPolling(); ++ await this.getGasFeeEstimatesAndStartPolling(tokens[0]); ++ tokens.slice(1).forEach((token) => { ++ this.pollTokens.add(token); ++ }); ++ } ++ } ++ async fetchGasFeeEstimates(options) { ++ return await this._fetchGasFeeEstimateData(options); ++ } ++ async getGasFeeEstimatesAndStartPolling(pollToken) { ++ const _pollToken = pollToken || random(); ++ this.pollTokens.add(_pollToken); ++ if (this.pollTokens.size === 1) { ++ await this._fetchGasFeeEstimateData(); ++ this._poll(); ++ } ++ return _pollToken; ++ } ++ /** ++ * Gets and sets gasFeeEstimates in state. ++ * ++ * @param options - The gas fee estimate options. ++ * @param options.shouldUpdateState - Determines whether the state should be updated with the ++ * updated gas estimates. ++ * @returns The gas fee estimates. ++ */ ++ async _fetchGasFeeEstimateData(options = {}) { ++ const { shouldUpdateState = true, networkClientId } = options; ++ let ethQuery, isEIP1559Compatible, isLegacyGasAPICompatible, decimalChainId; ++ if (networkClientId !== void 0) { ++ const networkClient = this.messagingSystem.call( ++ "NetworkController:getNetworkClientById", ++ networkClientId ++ ); ++ isLegacyGasAPICompatible = networkClient.configuration.chainId === "0x38"; ++ decimalChainId = convertHexToDecimal(networkClient.configuration.chainId); ++ try { ++ const result = await this.messagingSystem.call( ++ "NetworkController:getEIP1559Compatibility", ++ networkClientId ++ ); ++ isEIP1559Compatible = result || false; ++ } catch { ++ isEIP1559Compatible = false; ++ } ++ ethQuery = new EthQuery(networkClient.provider); ++ } ++ ethQuery ?? (ethQuery = this.ethQuery); ++ isLegacyGasAPICompatible ?? (isLegacyGasAPICompatible = this.getCurrentNetworkLegacyGasAPICompatibility()); ++ decimalChainId ?? (decimalChainId = convertHexToDecimal(this.currentChainId)); ++ try { ++ isEIP1559Compatible ?? (isEIP1559Compatible = await this.getEIP1559Compatibility()); ++ } catch (e) { ++ console.error(e); ++ isEIP1559Compatible ?? (isEIP1559Compatible = false); ++ } ++ const gasFeeCalculations = await determineGasFeeCalculations({ ++ isEIP1559Compatible, ++ isLegacyGasAPICompatible, ++ fetchGasEstimates, ++ fetchGasEstimatesUrl: this.EIP1559APIEndpoint.replace( ++ "<chain_id>", ++ `${decimalChainId}` ++ ), ++ fetchLegacyGasPriceEstimates, ++ fetchLegacyGasPriceEstimatesUrl: this.legacyAPIEndpoint.replace( ++ "<chain_id>", ++ `${decimalChainId}` ++ ), ++ fetchEthGasPriceEstimate, ++ calculateTimeEstimate, ++ clientId: this.clientId, ++ ethQuery, ++ nonRPCGasFeeApisDisabled: this.state.nonRPCGasFeeApisDisabled ++ }); ++ if (shouldUpdateState) { ++ const chainId = toHex(decimalChainId); ++ this.update((state) => { ++ if (this.currentChainId === chainId) { ++ state.gasFeeEstimates = gasFeeCalculations.gasFeeEstimates; ++ state.estimatedGasFeeTimeBounds = gasFeeCalculations.estimatedGasFeeTimeBounds; ++ state.gasEstimateType = gasFeeCalculations.gasEstimateType; ++ } ++ state.gasFeeEstimatesByChainId ?? (state.gasFeeEstimatesByChainId = {}); ++ state.gasFeeEstimatesByChainId[chainId] = { ++ gasFeeEstimates: gasFeeCalculations.gasFeeEstimates, ++ estimatedGasFeeTimeBounds: gasFeeCalculations.estimatedGasFeeTimeBounds, ++ gasEstimateType: gasFeeCalculations.gasEstimateType ++ }; ++ }); ++ } ++ return gasFeeCalculations; ++ } ++ /** ++ * Remove the poll token, and stop polling if the set of poll tokens is empty. ++ * ++ * @param pollToken - The poll token to disconnect. ++ */ ++ disconnectPoller(pollToken) { ++ this.pollTokens.delete(pollToken); ++ if (this.pollTokens.size === 0) { ++ this.stopPolling(); ++ } ++ } ++ stopPolling() { ++ if (this.intervalId) { ++ clearInterval(this.intervalId); ++ } ++ this.pollTokens.clear(); ++ this.resetState(); ++ } ++ /** ++ * Prepare to discard this controller. ++ * ++ * This stops any active polling. ++ */ ++ destroy() { ++ super.destroy(); ++ this.stopPolling(); ++ } ++ _poll() { ++ if (this.intervalId) { ++ clearInterval(this.intervalId); ++ } ++ this.intervalId = setInterval(async () => { ++ await safelyExecute(() => this._fetchGasFeeEstimateData()); ++ }, this.intervalDelay); ++ } ++ /** ++ * Fetching token list from the Token Service API. ++ * ++ * @private ++ * @param networkClientId - The ID of the network client triggering the fetch. ++ * @returns A promise that resolves when this operation completes. ++ */ ++ async _executePoll(networkClientId) { ++ await this._fetchGasFeeEstimateData({ networkClientId }); ++ } ++ resetState() { ++ this.update(() => { ++ return defaultState; ++ }); ++ } ++ async getEIP1559Compatibility() { ++ const currentNetworkIsEIP1559Compatible = await this.getCurrentNetworkEIP1559Compatibility(); ++ const currentAccountIsEIP1559Compatible = this.getCurrentAccountEIP1559Compatibility?.() ?? true; ++ return currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible; ++ } ++ getTimeEstimate(maxPriorityFeePerGas, maxFeePerGas) { ++ if (!this.state.gasFeeEstimates || this.state.gasEstimateType !== GAS_ESTIMATE_TYPES.FEE_MARKET) { ++ return {}; ++ } ++ return calculateTimeEstimate( ++ maxPriorityFeePerGas, ++ maxFeePerGas, ++ this.state.gasFeeEstimates ++ ); ++ } ++ enableNonRPCGasFeeApis() { ++ this.update((state) => { ++ state.nonRPCGasFeeApisDisabled = false; ++ }); ++ } ++ disableNonRPCGasFeeApis() { ++ this.update((state) => { ++ state.nonRPCGasFeeApisDisabled = true; ++ }); ++ } ++}; ++_getProvider = new WeakMap(); ++_onNetworkControllerDidChange = new WeakSet(); ++onNetworkControllerDidChange_fn = async function(networkControllerState) { ++ const newChainId = networkControllerState.providerConfig.chainId; ++ if (newChainId !== this.currentChainId) { ++ this.ethQuery = new EthQuery(__privateGet(this, _getProvider).call(this)); ++ await this.resetPolling(); ++ this.currentChainId = newChainId; ++ } ++}; ++var GasFeeController_default = GasFeeController; ++ ++// src/determineGasFeeCalculations.ts ++async function determineGasFeeCalculations(args) { ++ try { ++ return await getEstimatesUsingFallbacks(args); ++ } catch (error) { ++ if (error instanceof Error) { ++ throw new Error( ++ `Gas fee/price estimation failed. Message: ${error.message}` ++ ); ++ } ++ throw error; ++ } ++} ++async function getEstimatesUsingFallbacks(request) { ++ const { ++ isEIP1559Compatible, ++ isLegacyGasAPICompatible, ++ nonRPCGasFeeApisDisabled ++ } = request; ++ try { ++ if (isEIP1559Compatible && !nonRPCGasFeeApisDisabled) { ++ return await getEstimatesUsingFeeMarketEndpoint(request); ++ } ++ if (isLegacyGasAPICompatible && !nonRPCGasFeeApisDisabled) { ++ return await getEstimatesUsingLegacyEndpoint(request); ++ } ++ throw new Error("Main gas fee/price estimation failed. Use fallback"); ++ } catch { ++ return await getEstimatesUsingProvider(request); ++ } ++} ++async function getEstimatesUsingFeeMarketEndpoint(request) { ++ const { ++ fetchGasEstimates: fetchGasEstimates2, ++ fetchGasEstimatesUrl, ++ clientId, ++ calculateTimeEstimate: calculateTimeEstimate2 ++ } = request; ++ const estimates = await fetchGasEstimates2(fetchGasEstimatesUrl, clientId); ++ const { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas } = estimates.medium; ++ const estimatedGasFeeTimeBounds = calculateTimeEstimate2( ++ suggestedMaxPriorityFeePerGas, ++ suggestedMaxFeePerGas, ++ estimates ++ ); ++ return { ++ gasFeeEstimates: estimates, ++ estimatedGasFeeTimeBounds, ++ gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET ++ }; ++} ++async function getEstimatesUsingLegacyEndpoint(request) { ++ const { ++ fetchLegacyGasPriceEstimates: fetchLegacyGasPriceEstimates2, ++ fetchLegacyGasPriceEstimatesUrl, ++ clientId ++ } = request; ++ const estimates = await fetchLegacyGasPriceEstimates2( ++ fetchLegacyGasPriceEstimatesUrl, ++ clientId ++ ); ++ return { ++ gasFeeEstimates: estimates, ++ estimatedGasFeeTimeBounds: {}, ++ gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY ++ }; ++} ++async function getEstimatesUsingProvider(request) { ++ const { ethQuery, fetchEthGasPriceEstimate: fetchEthGasPriceEstimate2 } = request; ++ const estimates = await fetchEthGasPriceEstimate2(ethQuery); ++ return { ++ gasFeeEstimates: estimates, ++ estimatedGasFeeTimeBounds: {}, ++ gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE ++ }; ++} ++ ++export { ++ determineGasFeeCalculations, ++ LEGACY_GAS_PRICES_API_URL, ++ GAS_ESTIMATE_TYPES, ++ GasFeeController, ++ GasFeeController_default ++}; ++//# sourceMappingURL=chunk-A7NHJBXX.mjs.map +\ No newline at end of file +diff --git a/dist/chunk-A7NHJBXX.mjs.map b/dist/chunk-A7NHJBXX.mjs.map +new file mode 100644 +index 0000000000000000000000000000000000000000..d40e21b8870bb3ef2d3a092e9abdbb83527764f3 +--- /dev/null ++++ b/dist/chunk-A7NHJBXX.mjs.map +@@ -0,0 +1 @@ ++{"version":3,"sources":["../src/GasFeeController.ts","../src/determineGasFeeCalculations.ts"],"sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport {\n convertHexToDecimal,\n safelyExecute,\n toHex,\n} from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkControllerGetEIP1559CompatibilityAction,\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n NetworkControllerNetworkDidChangeEvent,\n NetworkState,\n ProviderProxy,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { v1 as random } from 'uuid';\n\nimport determineGasFeeCalculations from './determineGasFeeCalculations';\nimport {\n fetchGasEstimates,\n fetchLegacyGasPriceEstimates,\n fetchEthGasPriceEstimate,\n calculateTimeEstimate,\n} from './gas-util';\n\nexport const LEGACY_GAS_PRICES_API_URL = `https://api.metaswap.codefi.network/gasPrices`;\n\nexport type unknownString = 'unknown';\n\n// Fee Market describes the way gas is set after the london hardfork, and was\n// defined by EIP-1559.\nexport type FeeMarketEstimateType = 'fee-market';\n// Legacy describes gasPrice estimates from before london hardfork, when the\n// user is connected to mainnet and are presented with fast/average/slow\n// estimate levels to choose from.\nexport type LegacyEstimateType = 'legacy';\n// EthGasPrice describes a gasPrice estimate received from eth_gasPrice. Post\n// london this value should only be used for legacy type transactions when on\n// networks that support EIP-1559. This type of estimate is the most accurate\n// to display on custom networks that don't support EIP-1559.\nexport type EthGasPriceEstimateType = 'eth_gasPrice';\n// NoEstimate describes the state of the controller before receiving its first\n// estimate.\nexport type NoEstimateType = 'none';\n\n/**\n * Indicates which type of gasEstimate the controller is currently returning.\n * This is useful as a way of asserting that the shape of gasEstimates matches\n * expectations. NONE is a special case indicating that no previous gasEstimate\n * has been fetched.\n */\nexport const GAS_ESTIMATE_TYPES = {\n FEE_MARKET: 'fee-market' as FeeMarketEstimateType,\n LEGACY: 'legacy' as LegacyEstimateType,\n ETH_GASPRICE: 'eth_gasPrice' as EthGasPriceEstimateType,\n NONE: 'none' as NoEstimateType,\n};\n\nexport type GasEstimateType =\n | FeeMarketEstimateType\n | EthGasPriceEstimateType\n | LegacyEstimateType\n | NoEstimateType;\n\nexport type EstimatedGasFeeTimeBounds = {\n lowerTimeBound: number | null;\n upperTimeBound: number | unknownString;\n};\n\n/**\n * @type EthGasPriceEstimate\n *\n * A single gas price estimate for networks and accounts that don't support EIP-1559\n * This estimate comes from eth_gasPrice but is converted to dec gwei to match other\n * return values\n * @property gasPrice - A GWEI dec string\n */\n\nexport type EthGasPriceEstimate = {\n gasPrice: string;\n};\n\n/**\n * @type LegacyGasPriceEstimate\n *\n * A set of gas price estimates for networks and accounts that don't support EIP-1559\n * These estimates include low, medium and high all as strings representing gwei in\n * decimal format.\n * @property high - gasPrice, in decimal gwei string format, suggested for fast inclusion\n * @property medium - gasPrice, in decimal gwei string format, suggested for avg inclusion\n * @property low - gasPrice, in decimal gwei string format, suggested for slow inclusion\n */\nexport type LegacyGasPriceEstimate = {\n high: string;\n medium: string;\n low: string;\n};\n\n/**\n * @type Eip1559GasFee\n *\n * Data necessary to provide an estimate of a gas fee with a specific tip\n * @property minWaitTimeEstimate - The fastest the transaction will take, in milliseconds\n * @property maxWaitTimeEstimate - The slowest the transaction will take, in milliseconds\n * @property suggestedMaxPriorityFeePerGas - A suggested \"tip\", a GWEI hex number\n * @property suggestedMaxFeePerGas - A suggested max fee, the most a user will pay. a GWEI hex number\n */\nexport type Eip1559GasFee = {\n minWaitTimeEstimate: number; // a time duration in milliseconds\n maxWaitTimeEstimate: number; // a time duration in milliseconds\n suggestedMaxPriorityFeePerGas: string; // a GWEI decimal number\n suggestedMaxFeePerGas: string; // a GWEI decimal number\n};\n\n/**\n * @type GasFeeEstimates\n *\n * Data necessary to provide multiple GasFee estimates, and supporting information, to the user\n * @property low - A GasFee for a minimum necessary combination of tip and maxFee\n * @property medium - A GasFee for a recommended combination of tip and maxFee\n * @property high - A GasFee for a high combination of tip and maxFee\n * @property estimatedBaseFee - An estimate of what the base fee will be for the pending/next block. A GWEI dec number\n * @property networkCongestion - A normalized number that can be used to gauge the congestion\n * level of the network, with 0 meaning not congested and 1 meaning extremely congested\n */\nexport type GasFeeEstimates = SourcedGasFeeEstimates | FallbackGasFeeEstimates;\n\ntype SourcedGasFeeEstimates = {\n low: Eip1559GasFee;\n medium: Eip1559GasFee;\n high: Eip1559GasFee;\n estimatedBaseFee: string;\n historicalBaseFeeRange: [string, string];\n baseFeeTrend: 'up' | 'down' | 'level';\n latestPriorityFeeRange: [string, string];\n historicalPriorityFeeRange: [string, string];\n priorityFeeTrend: 'up' | 'down' | 'level';\n networkCongestion: number;\n};\n\ntype FallbackGasFeeEstimates = {\n low: Eip1559GasFee;\n medium: Eip1559GasFee;\n high: Eip1559GasFee;\n estimatedBaseFee: string;\n historicalBaseFeeRange: null;\n baseFeeTrend: null;\n latestPriorityFeeRange: null;\n historicalPriorityFeeRange: null;\n priorityFeeTrend: null;\n networkCongestion: null;\n};\n\nconst metadata = {\n gasFeeEstimatesByChainId: {\n persist: true,\n anonymous: false,\n },\n gasFeeEstimates: { persist: true, anonymous: false },\n estimatedGasFeeTimeBounds: { persist: true, anonymous: false },\n gasEstimateType: { persist: true, anonymous: false },\n nonRPCGasFeeApisDisabled: { persist: true, anonymous: false },\n};\n\nexport type GasFeeStateEthGasPrice = {\n gasFeeEstimates: EthGasPriceEstimate;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: EthGasPriceEstimateType;\n};\n\nexport type GasFeeStateFeeMarket = {\n gasFeeEstimates: GasFeeEstimates;\n estimatedGasFeeTimeBounds: EstimatedGasFeeTimeBounds | Record<string, never>;\n gasEstimateType: FeeMarketEstimateType;\n};\n\nexport type GasFeeStateLegacy = {\n gasFeeEstimates: LegacyGasPriceEstimate;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: LegacyEstimateType;\n};\n\nexport type GasFeeStateNoEstimates = {\n gasFeeEstimates: Record<string, never>;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: NoEstimateType;\n};\n\nexport type FetchGasFeeEstimateOptions = {\n shouldUpdateState?: boolean;\n networkClientId?: NetworkClientId;\n};\n\n/**\n * @type GasFeeState\n *\n * Gas Fee controller state\n * @property gasFeeEstimates - Gas fee estimate data based on new EIP-1559 properties\n * @property estimatedGasFeeTimeBounds - Estimates representing the minimum and maximum\n */\nexport type SingleChainGasFeeState =\n | GasFeeStateEthGasPrice\n | GasFeeStateFeeMarket\n | GasFeeStateLegacy\n | GasFeeStateNoEstimates;\n\nexport type GasFeeEstimatesByChainId = {\n gasFeeEstimatesByChainId?: Record<string, SingleChainGasFeeState>;\n};\n\nexport type GasFeeState = GasFeeEstimatesByChainId &\n SingleChainGasFeeState & {\n nonRPCGasFeeApisDisabled?: boolean;\n };\n\nconst name = 'GasFeeController';\n\nexport type GasFeeStateChange = ControllerStateChangeEvent<\n typeof name,\n GasFeeState\n>;\n\nexport type GetGasFeeState = ControllerGetStateAction<typeof name, GasFeeState>;\n\nexport type GasFeeControllerActions = GetGasFeeState;\n\nexport type GasFeeControllerEvents = GasFeeStateChange;\n\ntype AllowedActions =\n | NetworkControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetEIP1559CompatibilityAction;\n\ntype GasFeeMessenger = RestrictedControllerMessenger<\n typeof name,\n GasFeeControllerActions | AllowedActions,\n GasFeeControllerEvents | NetworkControllerNetworkDidChangeEvent,\n AllowedActions['type'],\n NetworkControllerNetworkDidChangeEvent['type']\n>;\n\nconst defaultState: GasFeeState = {\n gasFeeEstimatesByChainId: {},\n gasFeeEstimates: {},\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.NONE,\n nonRPCGasFeeApisDisabled: false,\n};\n\n/**\n * Controller that retrieves gas fee estimate data and polls for updated data on a set interval\n */\nexport class GasFeeController extends StaticIntervalPollingController<\n typeof name,\n GasFeeState,\n GasFeeMessenger\n> {\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay;\n\n private readonly pollTokens: Set<string>;\n\n private readonly legacyAPIEndpoint: string;\n\n private readonly EIP1559APIEndpoint: string;\n\n private readonly getCurrentNetworkEIP1559Compatibility;\n\n private readonly getCurrentNetworkLegacyGasAPICompatibility;\n\n private readonly getCurrentAccountEIP1559Compatibility;\n\n private currentChainId;\n\n private ethQuery?: EthQuery;\n\n private readonly clientId?: string;\n\n #getProvider: () => ProviderProxy;\n\n /**\n * Creates a GasFeeController instance.\n *\n * @param options - The controller options.\n * @param options.interval - The time in milliseconds to wait between polls.\n * @param options.messenger - The controller messenger.\n * @param options.state - The initial state.\n * @param options.getCurrentNetworkEIP1559Compatibility - Determines whether or not the current\n * network is EIP-1559 compatible.\n * @param options.getCurrentNetworkLegacyGasAPICompatibility - Determines whether or not the\n * current network is compatible with the legacy gas price API.\n * @param options.getCurrentAccountEIP1559Compatibility - Determines whether or not the current\n * account is EIP-1559 compatible.\n * @param options.getChainId - Returns the current chain ID.\n * @param options.getProvider - Returns a network provider for the current network.\n * @param options.onNetworkDidChange - A function for registering an event handler for the\n * network state change event.\n * @param options.legacyAPIEndpoint - The legacy gas price API URL. This option is primarily for\n * testing purposes.\n * @param options.EIP1559APIEndpoint - The EIP-1559 gas price API URL.\n * @param options.clientId - The client ID used to identify to the gas estimation API who is\n * asking for estimates.\n */\n constructor({\n interval = 15000,\n messenger,\n state,\n getCurrentNetworkEIP1559Compatibility,\n getCurrentAccountEIP1559Compatibility,\n getChainId,\n getCurrentNetworkLegacyGasAPICompatibility,\n getProvider,\n onNetworkDidChange,\n legacyAPIEndpoint = LEGACY_GAS_PRICES_API_URL,\n EIP1559APIEndpoint,\n clientId,\n }: {\n interval?: number;\n messenger: GasFeeMessenger;\n state?: GasFeeState;\n getCurrentNetworkEIP1559Compatibility: () => Promise<boolean>;\n getCurrentNetworkLegacyGasAPICompatibility: () => boolean;\n getCurrentAccountEIP1559Compatibility?: () => boolean;\n getChainId?: () => Hex;\n getProvider: () => ProviderProxy;\n onNetworkDidChange?: (listener: (state: NetworkState) => void) => void;\n legacyAPIEndpoint?: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n EIP1559APIEndpoint: string;\n clientId?: string;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.intervalDelay = interval;\n this.setIntervalLength(interval);\n this.pollTokens = new Set();\n this.getCurrentNetworkEIP1559Compatibility =\n getCurrentNetworkEIP1559Compatibility;\n this.getCurrentNetworkLegacyGasAPICompatibility =\n getCurrentNetworkLegacyGasAPICompatibility;\n this.getCurrentAccountEIP1559Compatibility =\n getCurrentAccountEIP1559Compatibility;\n this.#getProvider = getProvider;\n this.EIP1559APIEndpoint = EIP1559APIEndpoint;\n this.legacyAPIEndpoint = legacyAPIEndpoint;\n this.clientId = clientId;\n\n this.ethQuery = new EthQuery(this.#getProvider());\n\n if (onNetworkDidChange && getChainId) {\n this.currentChainId = getChainId();\n onNetworkDidChange(async (networkControllerState) => {\n await this.#onNetworkControllerDidChange(networkControllerState);\n });\n } else {\n this.currentChainId = this.messagingSystem.call(\n 'NetworkController:getState',\n ).providerConfig.chainId;\n this.messagingSystem.subscribe(\n 'NetworkController:networkDidChange',\n async (networkControllerState) => {\n await this.#onNetworkControllerDidChange(networkControllerState);\n },\n );\n }\n }\n\n async resetPolling() {\n if (this.pollTokens.size !== 0) {\n const tokens = Array.from(this.pollTokens);\n this.stopPolling();\n await this.getGasFeeEstimatesAndStartPolling(tokens[0]);\n tokens.slice(1).forEach((token) => {\n this.pollTokens.add(token);\n });\n }\n }\n\n async fetchGasFeeEstimates(options?: FetchGasFeeEstimateOptions) {\n return await this._fetchGasFeeEstimateData(options);\n }\n\n async getGasFeeEstimatesAndStartPolling(\n pollToken: string | undefined,\n ): Promise<string> {\n const _pollToken = pollToken || random();\n\n this.pollTokens.add(_pollToken);\n\n if (this.pollTokens.size === 1) {\n await this._fetchGasFeeEstimateData();\n this._poll();\n }\n\n return _pollToken;\n }\n\n /**\n * Gets and sets gasFeeEstimates in state.\n *\n * @param options - The gas fee estimate options.\n * @param options.shouldUpdateState - Determines whether the state should be updated with the\n * updated gas estimates.\n * @returns The gas fee estimates.\n */\n async _fetchGasFeeEstimateData(\n options: FetchGasFeeEstimateOptions = {},\n ): Promise<GasFeeState> {\n const { shouldUpdateState = true, networkClientId } = options;\n\n let ethQuery,\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n decimalChainId: number;\n\n if (networkClientId !== undefined) {\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n isLegacyGasAPICompatible = networkClient.configuration.chainId === '0x38';\n\n decimalChainId = convertHexToDecimal(networkClient.configuration.chainId);\n\n try {\n const result = await this.messagingSystem.call(\n 'NetworkController:getEIP1559Compatibility',\n networkClientId,\n );\n isEIP1559Compatible = result || false;\n } catch {\n isEIP1559Compatible = false;\n }\n ethQuery = new EthQuery(networkClient.provider);\n }\n\n ethQuery ??= this.ethQuery;\n\n isLegacyGasAPICompatible ??=\n this.getCurrentNetworkLegacyGasAPICompatibility();\n\n decimalChainId ??= convertHexToDecimal(this.currentChainId);\n\n try {\n isEIP1559Compatible ??= await this.getEIP1559Compatibility();\n } catch (e) {\n console.error(e);\n isEIP1559Compatible ??= false;\n }\n\n const gasFeeCalculations = await determineGasFeeCalculations({\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n fetchGasEstimates,\n fetchGasEstimatesUrl: this.EIP1559APIEndpoint.replace(\n '<chain_id>',\n `${decimalChainId}`,\n ),\n fetchLegacyGasPriceEstimates,\n fetchLegacyGasPriceEstimatesUrl: this.legacyAPIEndpoint.replace(\n '<chain_id>',\n `${decimalChainId}`,\n ),\n fetchEthGasPriceEstimate,\n calculateTimeEstimate,\n clientId: this.clientId,\n ethQuery,\n nonRPCGasFeeApisDisabled: this.state.nonRPCGasFeeApisDisabled,\n });\n\n if (shouldUpdateState) {\n const chainId = toHex(decimalChainId);\n this.update((state) => {\n if (this.currentChainId === chainId) {\n state.gasFeeEstimates = gasFeeCalculations.gasFeeEstimates;\n state.estimatedGasFeeTimeBounds =\n gasFeeCalculations.estimatedGasFeeTimeBounds;\n state.gasEstimateType = gasFeeCalculations.gasEstimateType;\n }\n state.gasFeeEstimatesByChainId ??= {};\n state.gasFeeEstimatesByChainId[chainId] = {\n gasFeeEstimates: gasFeeCalculations.gasFeeEstimates,\n estimatedGasFeeTimeBounds:\n gasFeeCalculations.estimatedGasFeeTimeBounds,\n gasEstimateType: gasFeeCalculations.gasEstimateType,\n } as SingleChainGasFeeState;\n });\n }\n\n return gasFeeCalculations;\n }\n\n /**\n * Remove the poll token, and stop polling if the set of poll tokens is empty.\n *\n * @param pollToken - The poll token to disconnect.\n */\n disconnectPoller(pollToken: string) {\n this.pollTokens.delete(pollToken);\n if (this.pollTokens.size === 0) {\n this.stopPolling();\n }\n }\n\n stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n this.pollTokens.clear();\n this.resetState();\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n private _poll() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this._fetchGasFeeEstimateData());\n }, this.intervalDelay);\n }\n\n /**\n * Fetching token list from the Token Service API.\n *\n * @private\n * @param networkClientId - The ID of the network client triggering the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll(networkClientId: string): Promise<void> {\n await this._fetchGasFeeEstimateData({ networkClientId });\n }\n\n private resetState() {\n this.update(() => {\n return defaultState;\n });\n }\n\n private async getEIP1559Compatibility() {\n const currentNetworkIsEIP1559Compatible =\n await this.getCurrentNetworkEIP1559Compatibility();\n const currentAccountIsEIP1559Compatible =\n this.getCurrentAccountEIP1559Compatibility?.() ?? true;\n\n return (\n currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible\n );\n }\n\n getTimeEstimate(\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n ): EstimatedGasFeeTimeBounds | Record<string, never> {\n if (\n !this.state.gasFeeEstimates ||\n this.state.gasEstimateType !== GAS_ESTIMATE_TYPES.FEE_MARKET\n ) {\n return {};\n }\n return calculateTimeEstimate(\n maxPriorityFeePerGas,\n maxFeePerGas,\n this.state.gasFeeEstimates,\n );\n }\n\n async #onNetworkControllerDidChange(networkControllerState: NetworkState) {\n const newChainId = networkControllerState.providerConfig.chainId;\n\n if (newChainId !== this.currentChainId) {\n this.ethQuery = new EthQuery(this.#getProvider());\n await this.resetPolling();\n\n this.currentChainId = newChainId;\n }\n }\n\n enableNonRPCGasFeeApis() {\n this.update((state) => {\n state.nonRPCGasFeeApisDisabled = false;\n });\n }\n\n disableNonRPCGasFeeApis() {\n this.update((state) => {\n state.nonRPCGasFeeApisDisabled = true;\n });\n }\n}\n\nexport default GasFeeController;\n","import type {\n EstimatedGasFeeTimeBounds,\n EthGasPriceEstimate,\n GasFeeEstimates,\n GasFeeState as GasFeeCalculations,\n LegacyGasPriceEstimate,\n} from './GasFeeController';\nimport { GAS_ESTIMATE_TYPES } from './GasFeeController';\n\ntype DetermineGasFeeCalculationsRequest = {\n isEIP1559Compatible: boolean;\n isLegacyGasAPICompatible: boolean;\n fetchGasEstimates: (\n url: string,\n clientId?: string,\n ) => Promise<GasFeeEstimates>;\n fetchGasEstimatesUrl: string;\n fetchLegacyGasPriceEstimates: (\n url: string,\n clientId?: string,\n ) => Promise<LegacyGasPriceEstimate>;\n fetchLegacyGasPriceEstimatesUrl: string;\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fetchEthGasPriceEstimate: (ethQuery: any) => Promise<EthGasPriceEstimate>;\n calculateTimeEstimate: (\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n gasFeeEstimates: GasFeeEstimates,\n ) => EstimatedGasFeeTimeBounds;\n clientId: string | undefined;\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ethQuery: any;\n nonRPCGasFeeApisDisabled?: boolean;\n};\n\n/**\n * Obtains a set of max base and priority fee estimates along with time estimates so that we\n * can present them to users when they are sending transactions or making swaps.\n *\n * @param args - The arguments.\n * @param args.isEIP1559Compatible - Governs whether or not we can use an EIP-1559-only method to\n * produce estimates.\n * @param args.isLegacyGasAPICompatible - Governs whether or not we can use a non-EIP-1559 method to\n * produce estimates (for instance, testnets do not support estimates altogether).\n * @param args.fetchGasEstimates - A function that fetches gas estimates using an EIP-1559-specific\n * API.\n * @param args.fetchGasEstimatesUrl - The URL for the API we can use to obtain EIP-1559-specific\n * estimates.\n * @param args.fetchLegacyGasPriceEstimates - A function that fetches gas estimates using an\n * non-EIP-1559-specific API.\n * @param args.fetchLegacyGasPriceEstimatesUrl - The URL for the API we can use to obtain\n * non-EIP-1559-specific estimates.\n * @param args.fetchEthGasPriceEstimate - A function that fetches gas estimates using\n * `eth_gasPrice`.\n * @param args.calculateTimeEstimate - A function that determine time estimate bounds.\n * @param args.clientId - An identifier that an API can use to know who is asking for estimates.\n * @param args.ethQuery - An EthQuery instance we can use to talk to Ethereum directly.\n * @param args.nonRPCGasFeeApisDisabled - Whether to disable requests to the legacyAPIEndpoint and the EIP1559APIEndpoint\n * @returns The gas fee calculations.\n */\nexport default async function determineGasFeeCalculations(\n args: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n try {\n return await getEstimatesUsingFallbacks(args);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Gas fee/price estimation failed. Message: ${error.message}`,\n );\n }\n\n throw error;\n }\n}\n\n/**\n * Retrieve the gas fee estimates using a series of fallback mechanisms.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingFallbacks(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n nonRPCGasFeeApisDisabled,\n } = request;\n\n try {\n if (isEIP1559Compatible && !nonRPCGasFeeApisDisabled) {\n return await getEstimatesUsingFeeMarketEndpoint(request);\n }\n\n if (isLegacyGasAPICompatible && !nonRPCGasFeeApisDisabled) {\n return await getEstimatesUsingLegacyEndpoint(request);\n }\n\n throw new Error('Main gas fee/price estimation failed. Use fallback');\n } catch {\n return await getEstimatesUsingProvider(request);\n }\n}\n\n/**\n * Retrieve gas fee estimates using the EIP-1559 endpoint of the gas API.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingFeeMarketEndpoint(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n fetchGasEstimates,\n fetchGasEstimatesUrl,\n clientId,\n calculateTimeEstimate,\n } = request;\n\n const estimates = await fetchGasEstimates(fetchGasEstimatesUrl, clientId);\n\n const { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas } =\n estimates.medium;\n\n const estimatedGasFeeTimeBounds = calculateTimeEstimate(\n suggestedMaxPriorityFeePerGas,\n suggestedMaxFeePerGas,\n estimates,\n );\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds,\n gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,\n };\n}\n\n/**\n * Retrieve gas fee estimates using the legacy endpoint of the gas API.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingLegacyEndpoint(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n fetchLegacyGasPriceEstimates,\n fetchLegacyGasPriceEstimatesUrl,\n clientId,\n } = request;\n\n const estimates = await fetchLegacyGasPriceEstimates(\n fetchLegacyGasPriceEstimatesUrl,\n clientId,\n );\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,\n };\n}\n\n/**\n * Retrieve gas fee estimates using an `eth_gasPrice` call to the RPC provider.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingProvider(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const { ethQuery, fetchEthGasPriceEstimate } = request;\n\n const estimates = await fetchEthGasPriceEstimate(ethQuery);\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE,\n };\n}\n"],"mappings":"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","names":["fetchGasEstimates","calculateTimeEstimate","fetchLegacyGasPriceEstimates","fetchEthGasPriceEstimate"]} +\ No newline at end of file +diff --git a/dist/chunk-BEVZS3YV.mjs b/dist/chunk-BEVZS3YV.mjs +deleted file mode 100644 +index 3be5db0695ee6a2c71e64ed76c43a1f30cc9e5ac..0000000000000000000000000000000000000000 +--- a/dist/chunk-BEVZS3YV.mjs ++++ /dev/null +@@ -1,396 +0,0 @@ +-import { +- __privateAdd, +- __privateGet, +- __privateMethod, +- __privateSet, +- calculateTimeEstimate, +- fetchEthGasPriceEstimate, +- fetchGasEstimates, +- fetchLegacyGasPriceEstimates +-} from "./chunk-KORLXV32.mjs"; +- +-// src/GasFeeController.ts +-import { +- convertHexToDecimal, +- safelyExecute, +- toHex +-} from "@metamask/controller-utils"; +-import EthQuery from "@metamask/eth-query"; +-import { StaticIntervalPollingController } from "@metamask/polling-controller"; +-import { v1 as random } from "uuid"; +-var GAS_API_BASE_URL = "https://gas.api.infura.io"; +-var GAS_ESTIMATE_TYPES = { +- FEE_MARKET: "fee-market", +- LEGACY: "legacy", +- ETH_GASPRICE: "eth_gasPrice", +- NONE: "none" +-}; +-var metadata = { +- gasFeeEstimatesByChainId: { +- persist: true, +- anonymous: false +- }, +- gasFeeEstimates: { persist: true, anonymous: false }, +- estimatedGasFeeTimeBounds: { persist: true, anonymous: false }, +- gasEstimateType: { persist: true, anonymous: false }, +- nonRPCGasFeeApisDisabled: { persist: true, anonymous: false } +-}; +-var name = "GasFeeController"; +-var defaultState = { +- gasFeeEstimatesByChainId: {}, +- gasFeeEstimates: {}, +- estimatedGasFeeTimeBounds: {}, +- gasEstimateType: GAS_ESTIMATE_TYPES.NONE, +- nonRPCGasFeeApisDisabled: false +-}; +-var _getProvider, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn; +-var GasFeeController = class extends StaticIntervalPollingController { +- /** +- * Creates a GasFeeController instance. +- * +- * @param options - The controller options. +- * @param options.interval - The time in milliseconds to wait between polls. +- * @param options.messenger - The controller messenger. +- * @param options.state - The initial state. +- * @param options.getCurrentNetworkEIP1559Compatibility - Determines whether or not the current +- * network is EIP-1559 compatible. +- * @param options.getCurrentNetworkLegacyGasAPICompatibility - Determines whether or not the +- * current network is compatible with the legacy gas price API. +- * @param options.getCurrentAccountEIP1559Compatibility - Determines whether or not the current +- * account is EIP-1559 compatible. +- * @param options.getChainId - Returns the current chain ID. +- * @param options.getProvider - Returns a network provider for the current network. +- * @param options.onNetworkDidChange - A function for registering an event handler for the +- * network state change event. +- * @param options.clientId - The client ID used to identify to the gas estimation API who is +- * asking for estimates. +- * @param options.infuraAPIKey - The Infura API key used for infura API requests. +- */ +- constructor({ +- interval = 15e3, +- messenger, +- state, +- getCurrentNetworkEIP1559Compatibility, +- getCurrentAccountEIP1559Compatibility, +- getChainId, +- getCurrentNetworkLegacyGasAPICompatibility, +- getProvider, +- onNetworkDidChange, +- clientId, +- infuraAPIKey +- }) { +- super({ +- name, +- metadata, +- messenger, +- state: { ...defaultState, ...state } +- }); +- __privateAdd(this, _onNetworkControllerDidChange); +- __privateAdd(this, _getProvider, void 0); +- this.intervalDelay = interval; +- this.setIntervalLength(interval); +- this.pollTokens = /* @__PURE__ */ new Set(); +- this.getCurrentNetworkEIP1559Compatibility = getCurrentNetworkEIP1559Compatibility; +- this.getCurrentNetworkLegacyGasAPICompatibility = getCurrentNetworkLegacyGasAPICompatibility; +- this.getCurrentAccountEIP1559Compatibility = getCurrentAccountEIP1559Compatibility; +- __privateSet(this, _getProvider, getProvider); +- this.EIP1559APIEndpoint = `${GAS_API_BASE_URL}/networks/<chain_id>/suggestedGasFees`; +- this.legacyAPIEndpoint = `${GAS_API_BASE_URL}/networks/<chain_id>/gasPrices`; +- this.clientId = clientId; +- this.infuraAPIKey = infuraAPIKey; +- this.ethQuery = new EthQuery(__privateGet(this, _getProvider).call(this)); +- if (onNetworkDidChange && getChainId) { +- this.currentChainId = getChainId(); +- onNetworkDidChange(async (networkControllerState) => { +- await __privateMethod(this, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn).call(this, networkControllerState); +- }); +- } else { +- this.currentChainId = this.messagingSystem.call( +- "NetworkController:getState" +- ).providerConfig.chainId; +- this.messagingSystem.subscribe( +- "NetworkController:networkDidChange", +- async (networkControllerState) => { +- await __privateMethod(this, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn).call(this, networkControllerState); +- } +- ); +- } +- } +- async resetPolling() { +- if (this.pollTokens.size !== 0) { +- const tokens = Array.from(this.pollTokens); +- this.stopPolling(); +- await this.getGasFeeEstimatesAndStartPolling(tokens[0]); +- tokens.slice(1).forEach((token) => { +- this.pollTokens.add(token); +- }); +- } +- } +- async fetchGasFeeEstimates(options) { +- return await this._fetchGasFeeEstimateData(options); +- } +- async getGasFeeEstimatesAndStartPolling(pollToken) { +- const _pollToken = pollToken || random(); +- this.pollTokens.add(_pollToken); +- if (this.pollTokens.size === 1) { +- await this._fetchGasFeeEstimateData(); +- this._poll(); +- } +- return _pollToken; +- } +- /** +- * Gets and sets gasFeeEstimates in state. +- * +- * @param options - The gas fee estimate options. +- * @param options.shouldUpdateState - Determines whether the state should be updated with the +- * updated gas estimates. +- * @returns The gas fee estimates. +- */ +- async _fetchGasFeeEstimateData(options = {}) { +- const { shouldUpdateState = true, networkClientId } = options; +- let ethQuery, isEIP1559Compatible, isLegacyGasAPICompatible, decimalChainId; +- if (networkClientId !== void 0) { +- const networkClient = this.messagingSystem.call( +- "NetworkController:getNetworkClientById", +- networkClientId +- ); +- isLegacyGasAPICompatible = networkClient.configuration.chainId === "0x38"; +- decimalChainId = convertHexToDecimal(networkClient.configuration.chainId); +- try { +- const result = await this.messagingSystem.call( +- "NetworkController:getEIP1559Compatibility", +- networkClientId +- ); +- isEIP1559Compatible = result || false; +- } catch { +- isEIP1559Compatible = false; +- } +- ethQuery = new EthQuery(networkClient.provider); +- } +- ethQuery ?? (ethQuery = this.ethQuery); +- isLegacyGasAPICompatible ?? (isLegacyGasAPICompatible = this.getCurrentNetworkLegacyGasAPICompatibility()); +- decimalChainId ?? (decimalChainId = convertHexToDecimal(this.currentChainId)); +- try { +- isEIP1559Compatible ?? (isEIP1559Compatible = await this.getEIP1559Compatibility()); +- } catch (e) { +- console.error(e); +- isEIP1559Compatible ?? (isEIP1559Compatible = false); +- } +- const gasFeeCalculations = await determineGasFeeCalculations({ +- isEIP1559Compatible, +- isLegacyGasAPICompatible, +- fetchGasEstimates, +- fetchGasEstimatesUrl: this.EIP1559APIEndpoint.replace( +- "<chain_id>", +- `${decimalChainId}` +- ), +- fetchLegacyGasPriceEstimates, +- fetchLegacyGasPriceEstimatesUrl: this.legacyAPIEndpoint.replace( +- "<chain_id>", +- `${decimalChainId}` +- ), +- fetchEthGasPriceEstimate, +- calculateTimeEstimate, +- clientId: this.clientId, +- ethQuery, +- infuraAPIKey: this.infuraAPIKey, +- nonRPCGasFeeApisDisabled: this.state.nonRPCGasFeeApisDisabled +- }); +- if (shouldUpdateState) { +- const chainId = toHex(decimalChainId); +- this.update((state) => { +- if (this.currentChainId === chainId) { +- state.gasFeeEstimates = gasFeeCalculations.gasFeeEstimates; +- state.estimatedGasFeeTimeBounds = gasFeeCalculations.estimatedGasFeeTimeBounds; +- state.gasEstimateType = gasFeeCalculations.gasEstimateType; +- } +- state.gasFeeEstimatesByChainId ?? (state.gasFeeEstimatesByChainId = {}); +- state.gasFeeEstimatesByChainId[chainId] = { +- gasFeeEstimates: gasFeeCalculations.gasFeeEstimates, +- estimatedGasFeeTimeBounds: gasFeeCalculations.estimatedGasFeeTimeBounds, +- gasEstimateType: gasFeeCalculations.gasEstimateType +- }; +- }); +- } +- return gasFeeCalculations; +- } +- /** +- * Remove the poll token, and stop polling if the set of poll tokens is empty. +- * +- * @param pollToken - The poll token to disconnect. +- */ +- disconnectPoller(pollToken) { +- this.pollTokens.delete(pollToken); +- if (this.pollTokens.size === 0) { +- this.stopPolling(); +- } +- } +- stopPolling() { +- if (this.intervalId) { +- clearInterval(this.intervalId); +- } +- this.pollTokens.clear(); +- this.resetState(); +- } +- /** +- * Prepare to discard this controller. +- * +- * This stops any active polling. +- */ +- destroy() { +- super.destroy(); +- this.stopPolling(); +- } +- _poll() { +- if (this.intervalId) { +- clearInterval(this.intervalId); +- } +- this.intervalId = setInterval(async () => { +- await safelyExecute(() => this._fetchGasFeeEstimateData()); +- }, this.intervalDelay); +- } +- /** +- * Fetching token list from the Token Service API. +- * +- * @private +- * @param networkClientId - The ID of the network client triggering the fetch. +- * @returns A promise that resolves when this operation completes. +- */ +- async _executePoll(networkClientId) { +- await this._fetchGasFeeEstimateData({ networkClientId }); +- } +- resetState() { +- this.update(() => { +- return defaultState; +- }); +- } +- async getEIP1559Compatibility() { +- const currentNetworkIsEIP1559Compatible = await this.getCurrentNetworkEIP1559Compatibility(); +- const currentAccountIsEIP1559Compatible = this.getCurrentAccountEIP1559Compatibility?.() ?? true; +- return currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible; +- } +- getTimeEstimate(maxPriorityFeePerGas, maxFeePerGas) { +- if (!this.state.gasFeeEstimates || this.state.gasEstimateType !== GAS_ESTIMATE_TYPES.FEE_MARKET) { +- return {}; +- } +- return calculateTimeEstimate( +- maxPriorityFeePerGas, +- maxFeePerGas, +- this.state.gasFeeEstimates +- ); +- } +- enableNonRPCGasFeeApis() { +- this.update((state) => { +- state.nonRPCGasFeeApisDisabled = false; +- }); +- } +- disableNonRPCGasFeeApis() { +- this.update((state) => { +- state.nonRPCGasFeeApisDisabled = true; +- }); +- } +-}; +-_getProvider = new WeakMap(); +-_onNetworkControllerDidChange = new WeakSet(); +-onNetworkControllerDidChange_fn = async function(networkControllerState) { +- const newChainId = networkControllerState.providerConfig.chainId; +- if (newChainId !== this.currentChainId) { +- this.ethQuery = new EthQuery(__privateGet(this, _getProvider).call(this)); +- await this.resetPolling(); +- this.currentChainId = newChainId; +- } +-}; +-var GasFeeController_default = GasFeeController; +- +-// src/determineGasFeeCalculations.ts +-async function determineGasFeeCalculations(args) { +- try { +- return await getEstimatesUsingFallbacks(args); +- } catch (error) { +- if (error instanceof Error) { +- throw new Error( +- `Gas fee/price estimation failed. Message: ${error.message}` +- ); +- } +- throw error; +- } +-} +-async function getEstimatesUsingFallbacks(request) { +- const { +- isEIP1559Compatible, +- isLegacyGasAPICompatible, +- nonRPCGasFeeApisDisabled +- } = request; +- try { +- if (isEIP1559Compatible && !nonRPCGasFeeApisDisabled) { +- return await getEstimatesUsingFeeMarketEndpoint(request); +- } +- if (isLegacyGasAPICompatible && !nonRPCGasFeeApisDisabled) { +- return await getEstimatesUsingLegacyEndpoint(request); +- } +- throw new Error("Main gas fee/price estimation failed. Use fallback"); +- } catch { +- return await getEstimatesUsingProvider(request); +- } +-} +-async function getEstimatesUsingFeeMarketEndpoint(request) { +- const { +- fetchGasEstimates: fetchGasEstimates2, +- fetchGasEstimatesUrl, +- infuraAPIKey, +- clientId, +- calculateTimeEstimate: calculateTimeEstimate2 +- } = request; +- const estimates = await fetchGasEstimates2( +- fetchGasEstimatesUrl, +- infuraAPIKey, +- clientId +- ); +- const { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas } = estimates.medium; +- const estimatedGasFeeTimeBounds = calculateTimeEstimate2( +- suggestedMaxPriorityFeePerGas, +- suggestedMaxFeePerGas, +- estimates +- ); +- return { +- gasFeeEstimates: estimates, +- estimatedGasFeeTimeBounds, +- gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET +- }; +-} +-async function getEstimatesUsingLegacyEndpoint(request) { +- const { +- fetchLegacyGasPriceEstimates: fetchLegacyGasPriceEstimates2, +- fetchLegacyGasPriceEstimatesUrl, +- infuraAPIKey, +- clientId +- } = request; +- const estimates = await fetchLegacyGasPriceEstimates2( +- fetchLegacyGasPriceEstimatesUrl, +- infuraAPIKey, +- clientId +- ); +- return { +- gasFeeEstimates: estimates, +- estimatedGasFeeTimeBounds: {}, +- gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY +- }; +-} +-async function getEstimatesUsingProvider(request) { +- const { ethQuery, fetchEthGasPriceEstimate: fetchEthGasPriceEstimate2 } = request; +- const estimates = await fetchEthGasPriceEstimate2(ethQuery); +- return { +- gasFeeEstimates: estimates, +- estimatedGasFeeTimeBounds: {}, +- gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE +- }; +-} +- +-export { +- determineGasFeeCalculations, +- GAS_API_BASE_URL, +- GAS_ESTIMATE_TYPES, +- GasFeeController, +- GasFeeController_default +-}; +-//# sourceMappingURL=chunk-BEVZS3YV.mjs.map +\ No newline at end of file +diff --git a/dist/chunk-BEVZS3YV.mjs.map b/dist/chunk-BEVZS3YV.mjs.map +deleted file mode 100644 +index fc90025f10e73e5cdafc8964cd84365e51ad0c42..0000000000000000000000000000000000000000 +--- a/dist/chunk-BEVZS3YV.mjs.map ++++ /dev/null +@@ -1 +0,0 @@ +-{"version":3,"sources":["../src/GasFeeController.ts","../src/determineGasFeeCalculations.ts"],"sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport {\n convertHexToDecimal,\n safelyExecute,\n toHex,\n} from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkControllerGetEIP1559CompatibilityAction,\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n NetworkControllerNetworkDidChangeEvent,\n NetworkState,\n ProviderProxy,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { v1 as random } from 'uuid';\n\nimport determineGasFeeCalculations from './determineGasFeeCalculations';\nimport {\n calculateTimeEstimate,\n fetchGasEstimates,\n fetchLegacyGasPriceEstimates,\n fetchEthGasPriceEstimate,\n} from './gas-util';\n\nexport const GAS_API_BASE_URL = 'https://gas.api.infura.io';\n\nexport type unknownString = 'unknown';\n\n// Fee Market describes the way gas is set after the london hardfork, and was\n// defined by EIP-1559.\nexport type FeeMarketEstimateType = 'fee-market';\n// Legacy describes gasPrice estimates from before london hardfork, when the\n// user is connected to mainnet and are presented with fast/average/slow\n// estimate levels to choose from.\nexport type LegacyEstimateType = 'legacy';\n// EthGasPrice describes a gasPrice estimate received from eth_gasPrice. Post\n// london this value should only be used for legacy type transactions when on\n// networks that support EIP-1559. This type of estimate is the most accurate\n// to display on custom networks that don't support EIP-1559.\nexport type EthGasPriceEstimateType = 'eth_gasPrice';\n// NoEstimate describes the state of the controller before receiving its first\n// estimate.\nexport type NoEstimateType = 'none';\n\n/**\n * Indicates which type of gasEstimate the controller is currently returning.\n * This is useful as a way of asserting that the shape of gasEstimates matches\n * expectations. NONE is a special case indicating that no previous gasEstimate\n * has been fetched.\n */\nexport const GAS_ESTIMATE_TYPES = {\n FEE_MARKET: 'fee-market' as FeeMarketEstimateType,\n LEGACY: 'legacy' as LegacyEstimateType,\n ETH_GASPRICE: 'eth_gasPrice' as EthGasPriceEstimateType,\n NONE: 'none' as NoEstimateType,\n};\n\nexport type GasEstimateType =\n | FeeMarketEstimateType\n | EthGasPriceEstimateType\n | LegacyEstimateType\n | NoEstimateType;\n\nexport type EstimatedGasFeeTimeBounds = {\n lowerTimeBound: number | null;\n upperTimeBound: number | unknownString;\n};\n\n/**\n * @type EthGasPriceEstimate\n *\n * A single gas price estimate for networks and accounts that don't support EIP-1559\n * This estimate comes from eth_gasPrice but is converted to dec gwei to match other\n * return values\n * @property gasPrice - A GWEI dec string\n */\n\nexport type EthGasPriceEstimate = {\n gasPrice: string;\n};\n\n/**\n * @type LegacyGasPriceEstimate\n *\n * A set of gas price estimates for networks and accounts that don't support EIP-1559\n * These estimates include low, medium and high all as strings representing gwei in\n * decimal format.\n * @property high - gasPrice, in decimal gwei string format, suggested for fast inclusion\n * @property medium - gasPrice, in decimal gwei string format, suggested for avg inclusion\n * @property low - gasPrice, in decimal gwei string format, suggested for slow inclusion\n */\nexport type LegacyGasPriceEstimate = {\n high: string;\n medium: string;\n low: string;\n};\n\n/**\n * @type Eip1559GasFee\n *\n * Data necessary to provide an estimate of a gas fee with a specific tip\n * @property minWaitTimeEstimate - The fastest the transaction will take, in milliseconds\n * @property maxWaitTimeEstimate - The slowest the transaction will take, in milliseconds\n * @property suggestedMaxPriorityFeePerGas - A suggested \"tip\", a GWEI hex number\n * @property suggestedMaxFeePerGas - A suggested max fee, the most a user will pay. a GWEI hex number\n */\nexport type Eip1559GasFee = {\n minWaitTimeEstimate: number; // a time duration in milliseconds\n maxWaitTimeEstimate: number; // a time duration in milliseconds\n suggestedMaxPriorityFeePerGas: string; // a GWEI decimal number\n suggestedMaxFeePerGas: string; // a GWEI decimal number\n};\n\n/**\n * @type GasFeeEstimates\n *\n * Data necessary to provide multiple GasFee estimates, and supporting information, to the user\n * @property low - A GasFee for a minimum necessary combination of tip and maxFee\n * @property medium - A GasFee for a recommended combination of tip and maxFee\n * @property high - A GasFee for a high combination of tip and maxFee\n * @property estimatedBaseFee - An estimate of what the base fee will be for the pending/next block. A GWEI dec number\n * @property networkCongestion - A normalized number that can be used to gauge the congestion\n * level of the network, with 0 meaning not congested and 1 meaning extremely congested\n */\nexport type GasFeeEstimates = SourcedGasFeeEstimates | FallbackGasFeeEstimates;\n\ntype SourcedGasFeeEstimates = {\n low: Eip1559GasFee;\n medium: Eip1559GasFee;\n high: Eip1559GasFee;\n estimatedBaseFee: string;\n historicalBaseFeeRange: [string, string];\n baseFeeTrend: 'up' | 'down' | 'level';\n latestPriorityFeeRange: [string, string];\n historicalPriorityFeeRange: [string, string];\n priorityFeeTrend: 'up' | 'down' | 'level';\n networkCongestion: number;\n};\n\ntype FallbackGasFeeEstimates = {\n low: Eip1559GasFee;\n medium: Eip1559GasFee;\n high: Eip1559GasFee;\n estimatedBaseFee: string;\n historicalBaseFeeRange: null;\n baseFeeTrend: null;\n latestPriorityFeeRange: null;\n historicalPriorityFeeRange: null;\n priorityFeeTrend: null;\n networkCongestion: null;\n};\n\nconst metadata = {\n gasFeeEstimatesByChainId: {\n persist: true,\n anonymous: false,\n },\n gasFeeEstimates: { persist: true, anonymous: false },\n estimatedGasFeeTimeBounds: { persist: true, anonymous: false },\n gasEstimateType: { persist: true, anonymous: false },\n nonRPCGasFeeApisDisabled: { persist: true, anonymous: false },\n};\n\nexport type GasFeeStateEthGasPrice = {\n gasFeeEstimates: EthGasPriceEstimate;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: EthGasPriceEstimateType;\n};\n\nexport type GasFeeStateFeeMarket = {\n gasFeeEstimates: GasFeeEstimates;\n estimatedGasFeeTimeBounds: EstimatedGasFeeTimeBounds | Record<string, never>;\n gasEstimateType: FeeMarketEstimateType;\n};\n\nexport type GasFeeStateLegacy = {\n gasFeeEstimates: LegacyGasPriceEstimate;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: LegacyEstimateType;\n};\n\nexport type GasFeeStateNoEstimates = {\n gasFeeEstimates: Record<string, never>;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: NoEstimateType;\n};\n\nexport type FetchGasFeeEstimateOptions = {\n shouldUpdateState?: boolean;\n networkClientId?: NetworkClientId;\n};\n\n/**\n * @type GasFeeState\n *\n * Gas Fee controller state\n * @property gasFeeEstimates - Gas fee estimate data based on new EIP-1559 properties\n * @property estimatedGasFeeTimeBounds - Estimates representing the minimum and maximum\n */\nexport type SingleChainGasFeeState =\n | GasFeeStateEthGasPrice\n | GasFeeStateFeeMarket\n | GasFeeStateLegacy\n | GasFeeStateNoEstimates;\n\nexport type GasFeeEstimatesByChainId = {\n gasFeeEstimatesByChainId?: Record<string, SingleChainGasFeeState>;\n};\n\nexport type GasFeeState = GasFeeEstimatesByChainId &\n SingleChainGasFeeState & {\n nonRPCGasFeeApisDisabled?: boolean;\n };\n\nconst name = 'GasFeeController';\n\nexport type GasFeeStateChange = ControllerStateChangeEvent<\n typeof name,\n GasFeeState\n>;\n\nexport type GetGasFeeState = ControllerGetStateAction<typeof name, GasFeeState>;\n\nexport type GasFeeControllerActions = GetGasFeeState;\n\nexport type GasFeeControllerEvents = GasFeeStateChange;\n\ntype AllowedActions =\n | NetworkControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetEIP1559CompatibilityAction;\n\ntype GasFeeMessenger = RestrictedControllerMessenger<\n typeof name,\n GasFeeControllerActions | AllowedActions,\n GasFeeControllerEvents | NetworkControllerNetworkDidChangeEvent,\n AllowedActions['type'],\n NetworkControllerNetworkDidChangeEvent['type']\n>;\n\nconst defaultState: GasFeeState = {\n gasFeeEstimatesByChainId: {},\n gasFeeEstimates: {},\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.NONE,\n nonRPCGasFeeApisDisabled: false,\n};\n\n/**\n * Controller that retrieves gas fee estimate data and polls for updated data on a set interval\n */\nexport class GasFeeController extends StaticIntervalPollingController<\n typeof name,\n GasFeeState,\n GasFeeMessenger\n> {\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay;\n\n private readonly pollTokens: Set<string>;\n\n private readonly legacyAPIEndpoint: string;\n\n private readonly EIP1559APIEndpoint: string;\n\n private readonly getCurrentNetworkEIP1559Compatibility;\n\n private readonly getCurrentNetworkLegacyGasAPICompatibility;\n\n private readonly getCurrentAccountEIP1559Compatibility;\n\n private readonly infuraAPIKey: string;\n\n private currentChainId;\n\n private ethQuery?: EthQuery;\n\n private readonly clientId?: string;\n\n #getProvider: () => ProviderProxy;\n\n /**\n * Creates a GasFeeController instance.\n *\n * @param options - The controller options.\n * @param options.interval - The time in milliseconds to wait between polls.\n * @param options.messenger - The controller messenger.\n * @param options.state - The initial state.\n * @param options.getCurrentNetworkEIP1559Compatibility - Determines whether or not the current\n * network is EIP-1559 compatible.\n * @param options.getCurrentNetworkLegacyGasAPICompatibility - Determines whether or not the\n * current network is compatible with the legacy gas price API.\n * @param options.getCurrentAccountEIP1559Compatibility - Determines whether or not the current\n * account is EIP-1559 compatible.\n * @param options.getChainId - Returns the current chain ID.\n * @param options.getProvider - Returns a network provider for the current network.\n * @param options.onNetworkDidChange - A function for registering an event handler for the\n * network state change event.\n * @param options.clientId - The client ID used to identify to the gas estimation API who is\n * asking for estimates.\n * @param options.infuraAPIKey - The Infura API key used for infura API requests.\n */\n constructor({\n interval = 15000,\n messenger,\n state,\n getCurrentNetworkEIP1559Compatibility,\n getCurrentAccountEIP1559Compatibility,\n getChainId,\n getCurrentNetworkLegacyGasAPICompatibility,\n getProvider,\n onNetworkDidChange,\n clientId,\n infuraAPIKey,\n }: {\n interval?: number;\n messenger: GasFeeMessenger;\n state?: GasFeeState;\n getCurrentNetworkEIP1559Compatibility: () => Promise<boolean>;\n getCurrentNetworkLegacyGasAPICompatibility: () => boolean;\n getCurrentAccountEIP1559Compatibility?: () => boolean;\n getChainId?: () => Hex;\n getProvider: () => ProviderProxy;\n onNetworkDidChange?: (listener: (state: NetworkState) => void) => void;\n clientId?: string;\n infuraAPIKey: string;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.intervalDelay = interval;\n this.setIntervalLength(interval);\n this.pollTokens = new Set();\n this.getCurrentNetworkEIP1559Compatibility =\n getCurrentNetworkEIP1559Compatibility;\n this.getCurrentNetworkLegacyGasAPICompatibility =\n getCurrentNetworkLegacyGasAPICompatibility;\n this.getCurrentAccountEIP1559Compatibility =\n getCurrentAccountEIP1559Compatibility;\n this.#getProvider = getProvider;\n this.EIP1559APIEndpoint = `${GAS_API_BASE_URL}/networks/<chain_id>/suggestedGasFees`;\n this.legacyAPIEndpoint = `${GAS_API_BASE_URL}/networks/<chain_id>/gasPrices`;\n this.clientId = clientId;\n this.infuraAPIKey = infuraAPIKey;\n\n this.ethQuery = new EthQuery(this.#getProvider());\n\n if (onNetworkDidChange && getChainId) {\n this.currentChainId = getChainId();\n onNetworkDidChange(async (networkControllerState) => {\n await this.#onNetworkControllerDidChange(networkControllerState);\n });\n } else {\n this.currentChainId = this.messagingSystem.call(\n 'NetworkController:getState',\n ).providerConfig.chainId;\n this.messagingSystem.subscribe(\n 'NetworkController:networkDidChange',\n async (networkControllerState) => {\n await this.#onNetworkControllerDidChange(networkControllerState);\n },\n );\n }\n }\n\n async resetPolling() {\n if (this.pollTokens.size !== 0) {\n const tokens = Array.from(this.pollTokens);\n this.stopPolling();\n await this.getGasFeeEstimatesAndStartPolling(tokens[0]);\n tokens.slice(1).forEach((token) => {\n this.pollTokens.add(token);\n });\n }\n }\n\n async fetchGasFeeEstimates(options?: FetchGasFeeEstimateOptions) {\n return await this._fetchGasFeeEstimateData(options);\n }\n\n async getGasFeeEstimatesAndStartPolling(\n pollToken: string | undefined,\n ): Promise<string> {\n const _pollToken = pollToken || random();\n\n this.pollTokens.add(_pollToken);\n\n if (this.pollTokens.size === 1) {\n await this._fetchGasFeeEstimateData();\n this._poll();\n }\n\n return _pollToken;\n }\n\n /**\n * Gets and sets gasFeeEstimates in state.\n *\n * @param options - The gas fee estimate options.\n * @param options.shouldUpdateState - Determines whether the state should be updated with the\n * updated gas estimates.\n * @returns The gas fee estimates.\n */\n async _fetchGasFeeEstimateData(\n options: FetchGasFeeEstimateOptions = {},\n ): Promise<GasFeeState> {\n const { shouldUpdateState = true, networkClientId } = options;\n\n let ethQuery,\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n decimalChainId: number;\n\n if (networkClientId !== undefined) {\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n isLegacyGasAPICompatible = networkClient.configuration.chainId === '0x38';\n\n decimalChainId = convertHexToDecimal(networkClient.configuration.chainId);\n\n try {\n const result = await this.messagingSystem.call(\n 'NetworkController:getEIP1559Compatibility',\n networkClientId,\n );\n isEIP1559Compatible = result || false;\n } catch {\n isEIP1559Compatible = false;\n }\n ethQuery = new EthQuery(networkClient.provider);\n }\n\n ethQuery ??= this.ethQuery;\n\n isLegacyGasAPICompatible ??=\n this.getCurrentNetworkLegacyGasAPICompatibility();\n\n decimalChainId ??= convertHexToDecimal(this.currentChainId);\n\n try {\n isEIP1559Compatible ??= await this.getEIP1559Compatibility();\n } catch (e) {\n console.error(e);\n isEIP1559Compatible ??= false;\n }\n\n const gasFeeCalculations = await determineGasFeeCalculations({\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n fetchGasEstimates,\n fetchGasEstimatesUrl: this.EIP1559APIEndpoint.replace(\n '<chain_id>',\n `${decimalChainId}`,\n ),\n fetchLegacyGasPriceEstimates,\n fetchLegacyGasPriceEstimatesUrl: this.legacyAPIEndpoint.replace(\n '<chain_id>',\n `${decimalChainId}`,\n ),\n fetchEthGasPriceEstimate,\n calculateTimeEstimate,\n clientId: this.clientId,\n ethQuery,\n infuraAPIKey: this.infuraAPIKey,\n nonRPCGasFeeApisDisabled: this.state.nonRPCGasFeeApisDisabled,\n });\n\n if (shouldUpdateState) {\n const chainId = toHex(decimalChainId);\n this.update((state) => {\n if (this.currentChainId === chainId) {\n state.gasFeeEstimates = gasFeeCalculations.gasFeeEstimates;\n state.estimatedGasFeeTimeBounds =\n gasFeeCalculations.estimatedGasFeeTimeBounds;\n state.gasEstimateType = gasFeeCalculations.gasEstimateType;\n }\n state.gasFeeEstimatesByChainId ??= {};\n state.gasFeeEstimatesByChainId[chainId] = {\n gasFeeEstimates: gasFeeCalculations.gasFeeEstimates,\n estimatedGasFeeTimeBounds:\n gasFeeCalculations.estimatedGasFeeTimeBounds,\n gasEstimateType: gasFeeCalculations.gasEstimateType,\n } as SingleChainGasFeeState;\n });\n }\n\n return gasFeeCalculations;\n }\n\n /**\n * Remove the poll token, and stop polling if the set of poll tokens is empty.\n *\n * @param pollToken - The poll token to disconnect.\n */\n disconnectPoller(pollToken: string) {\n this.pollTokens.delete(pollToken);\n if (this.pollTokens.size === 0) {\n this.stopPolling();\n }\n }\n\n stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n this.pollTokens.clear();\n this.resetState();\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n private _poll() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this._fetchGasFeeEstimateData());\n }, this.intervalDelay);\n }\n\n /**\n * Fetching token list from the Token Service API.\n *\n * @private\n * @param networkClientId - The ID of the network client triggering the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll(networkClientId: string): Promise<void> {\n await this._fetchGasFeeEstimateData({ networkClientId });\n }\n\n private resetState() {\n this.update(() => {\n return defaultState;\n });\n }\n\n private async getEIP1559Compatibility() {\n const currentNetworkIsEIP1559Compatible =\n await this.getCurrentNetworkEIP1559Compatibility();\n const currentAccountIsEIP1559Compatible =\n this.getCurrentAccountEIP1559Compatibility?.() ?? true;\n\n return (\n currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible\n );\n }\n\n getTimeEstimate(\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n ): EstimatedGasFeeTimeBounds | Record<string, never> {\n if (\n !this.state.gasFeeEstimates ||\n this.state.gasEstimateType !== GAS_ESTIMATE_TYPES.FEE_MARKET\n ) {\n return {};\n }\n return calculateTimeEstimate(\n maxPriorityFeePerGas,\n maxFeePerGas,\n this.state.gasFeeEstimates,\n );\n }\n\n async #onNetworkControllerDidChange(networkControllerState: NetworkState) {\n const newChainId = networkControllerState.providerConfig.chainId;\n\n if (newChainId !== this.currentChainId) {\n this.ethQuery = new EthQuery(this.#getProvider());\n await this.resetPolling();\n\n this.currentChainId = newChainId;\n }\n }\n\n enableNonRPCGasFeeApis() {\n this.update((state) => {\n state.nonRPCGasFeeApisDisabled = false;\n });\n }\n\n disableNonRPCGasFeeApis() {\n this.update((state) => {\n state.nonRPCGasFeeApisDisabled = true;\n });\n }\n}\n\nexport default GasFeeController;\n","import type {\n EstimatedGasFeeTimeBounds,\n EthGasPriceEstimate,\n GasFeeEstimates,\n GasFeeState as GasFeeCalculations,\n LegacyGasPriceEstimate,\n} from './GasFeeController';\nimport { GAS_ESTIMATE_TYPES } from './GasFeeController';\n\ntype DetermineGasFeeCalculationsRequest = {\n isEIP1559Compatible: boolean;\n isLegacyGasAPICompatible: boolean;\n fetchGasEstimates: (\n url: string,\n infuraAPIKey: string,\n clientId?: string,\n ) => Promise<GasFeeEstimates>;\n fetchGasEstimatesUrl: string;\n fetchLegacyGasPriceEstimates: (\n url: string,\n infuraAPIKey: string,\n clientId?: string,\n ) => Promise<LegacyGasPriceEstimate>;\n fetchLegacyGasPriceEstimatesUrl: string;\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fetchEthGasPriceEstimate: (ethQuery: any) => Promise<EthGasPriceEstimate>;\n calculateTimeEstimate: (\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n gasFeeEstimates: GasFeeEstimates,\n ) => EstimatedGasFeeTimeBounds;\n clientId: string | undefined;\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ethQuery: any;\n infuraAPIKey: string;\n nonRPCGasFeeApisDisabled?: boolean;\n};\n\n/**\n * Obtains a set of max base and priority fee estimates along with time estimates so that we\n * can present them to users when they are sending transactions or making swaps.\n *\n * @param args - The arguments.\n * @param args.isEIP1559Compatible - Governs whether or not we can use an EIP-1559-only method to\n * produce estimates.\n * @param args.isLegacyGasAPICompatible - Governs whether or not we can use a non-EIP-1559 method to\n * produce estimates (for instance, testnets do not support estimates altogether).\n * @param args.fetchGasEstimates - A function that fetches gas estimates using an EIP-1559-specific\n * API.\n * @param args.fetchGasEstimatesUrl - The URL for the API we can use to obtain EIP-1559-specific\n * estimates.\n * @param args.fetchLegacyGasPriceEstimates - A function that fetches gas estimates using an\n * non-EIP-1559-specific API.\n * @param args.fetchLegacyGasPriceEstimatesUrl - The URL for the API we can use to obtain\n * non-EIP-1559-specific estimates.\n * @param args.fetchEthGasPriceEstimate - A function that fetches gas estimates using\n * `eth_gasPrice`.\n * @param args.calculateTimeEstimate - A function that determine time estimate bounds.\n * @param args.clientId - An identifier that an API can use to know who is asking for estimates.\n * @param args.ethQuery - An EthQuery instance we can use to talk to Ethereum directly.\n * @param args.infuraAPIKey - Infura API key to use for requests to Infura.\n * @param args.nonRPCGasFeeApisDisabled - Whether to disable requests to the legacyAPIEndpoint and the EIP1559APIEndpoint\n * @returns The gas fee calculations.\n */\nexport default async function determineGasFeeCalculations(\n args: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n try {\n return await getEstimatesUsingFallbacks(args);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Gas fee/price estimation failed. Message: ${error.message}`,\n );\n }\n\n throw error;\n }\n}\n\n/**\n * Retrieve the gas fee estimates using a series of fallback mechanisms.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingFallbacks(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n nonRPCGasFeeApisDisabled,\n } = request;\n\n try {\n if (isEIP1559Compatible && !nonRPCGasFeeApisDisabled) {\n return await getEstimatesUsingFeeMarketEndpoint(request);\n }\n\n if (isLegacyGasAPICompatible && !nonRPCGasFeeApisDisabled) {\n return await getEstimatesUsingLegacyEndpoint(request);\n }\n\n throw new Error('Main gas fee/price estimation failed. Use fallback');\n } catch {\n return await getEstimatesUsingProvider(request);\n }\n}\n\n/**\n * Retrieve gas fee estimates using the EIP-1559 endpoint of the gas API.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingFeeMarketEndpoint(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n fetchGasEstimates,\n fetchGasEstimatesUrl,\n infuraAPIKey,\n clientId,\n calculateTimeEstimate,\n } = request;\n\n const estimates = await fetchGasEstimates(\n fetchGasEstimatesUrl,\n infuraAPIKey,\n clientId,\n );\n\n const { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas } =\n estimates.medium;\n\n const estimatedGasFeeTimeBounds = calculateTimeEstimate(\n suggestedMaxPriorityFeePerGas,\n suggestedMaxFeePerGas,\n estimates,\n );\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds,\n gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,\n };\n}\n\n/**\n * Retrieve gas fee estimates using the legacy endpoint of the gas API.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingLegacyEndpoint(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n fetchLegacyGasPriceEstimates,\n fetchLegacyGasPriceEstimatesUrl,\n infuraAPIKey,\n clientId,\n } = request;\n\n const estimates = await fetchLegacyGasPriceEstimates(\n fetchLegacyGasPriceEstimatesUrl,\n infuraAPIKey,\n clientId,\n );\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,\n };\n}\n\n/**\n * Retrieve gas fee estimates using an `eth_gasPrice` call to the RPC provider.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingProvider(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const { ethQuery, fetchEthGasPriceEstimate } = request;\n\n const estimates = await fetchEthGasPriceEstimate(ethQuery);\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE,\n };\n}\n"],"mappings":"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","names":["fetchGasEstimates","calculateTimeEstimate","fetchLegacyGasPriceEstimates","fetchEthGasPriceEstimate"]} +\ No newline at end of file +diff --git a/dist/chunk-H5WHAYLI.js b/dist/chunk-H5WHAYLI.js +deleted file mode 100644 +index 3d6f8458707153d0b3cdd19da2bce7cb32da8eef..0000000000000000000000000000000000000000 +--- a/dist/chunk-H5WHAYLI.js ++++ /dev/null +@@ -1,396 +0,0 @@ +-"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +- +- +- +- +- +- +- +- +-var _chunkQ2YPK5SLjs = require('./chunk-Q2YPK5SL.js'); +- +-// src/GasFeeController.ts +- +- +- +- +-var _controllerutils = require('@metamask/controller-utils'); +-var _ethquery = require('@metamask/eth-query'); var _ethquery2 = _interopRequireDefault(_ethquery); +-var _pollingcontroller = require('@metamask/polling-controller'); +-var _uuid = require('uuid'); +-var GAS_API_BASE_URL = "https://gas.api.infura.io"; +-var GAS_ESTIMATE_TYPES = { +- FEE_MARKET: "fee-market", +- LEGACY: "legacy", +- ETH_GASPRICE: "eth_gasPrice", +- NONE: "none" +-}; +-var metadata = { +- gasFeeEstimatesByChainId: { +- persist: true, +- anonymous: false +- }, +- gasFeeEstimates: { persist: true, anonymous: false }, +- estimatedGasFeeTimeBounds: { persist: true, anonymous: false }, +- gasEstimateType: { persist: true, anonymous: false }, +- nonRPCGasFeeApisDisabled: { persist: true, anonymous: false } +-}; +-var name = "GasFeeController"; +-var defaultState = { +- gasFeeEstimatesByChainId: {}, +- gasFeeEstimates: {}, +- estimatedGasFeeTimeBounds: {}, +- gasEstimateType: GAS_ESTIMATE_TYPES.NONE, +- nonRPCGasFeeApisDisabled: false +-}; +-var _getProvider, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn; +-var GasFeeController = class extends _pollingcontroller.StaticIntervalPollingController { +- /** +- * Creates a GasFeeController instance. +- * +- * @param options - The controller options. +- * @param options.interval - The time in milliseconds to wait between polls. +- * @param options.messenger - The controller messenger. +- * @param options.state - The initial state. +- * @param options.getCurrentNetworkEIP1559Compatibility - Determines whether or not the current +- * network is EIP-1559 compatible. +- * @param options.getCurrentNetworkLegacyGasAPICompatibility - Determines whether or not the +- * current network is compatible with the legacy gas price API. +- * @param options.getCurrentAccountEIP1559Compatibility - Determines whether or not the current +- * account is EIP-1559 compatible. +- * @param options.getChainId - Returns the current chain ID. +- * @param options.getProvider - Returns a network provider for the current network. +- * @param options.onNetworkDidChange - A function for registering an event handler for the +- * network state change event. +- * @param options.clientId - The client ID used to identify to the gas estimation API who is +- * asking for estimates. +- * @param options.infuraAPIKey - The Infura API key used for infura API requests. +- */ +- constructor({ +- interval = 15e3, +- messenger, +- state, +- getCurrentNetworkEIP1559Compatibility, +- getCurrentAccountEIP1559Compatibility, +- getChainId, +- getCurrentNetworkLegacyGasAPICompatibility, +- getProvider, +- onNetworkDidChange, +- clientId, +- infuraAPIKey +- }) { +- super({ +- name, +- metadata, +- messenger, +- state: { ...defaultState, ...state } +- }); +- _chunkQ2YPK5SLjs.__privateAdd.call(void 0, this, _onNetworkControllerDidChange); +- _chunkQ2YPK5SLjs.__privateAdd.call(void 0, this, _getProvider, void 0); +- this.intervalDelay = interval; +- this.setIntervalLength(interval); +- this.pollTokens = /* @__PURE__ */ new Set(); +- this.getCurrentNetworkEIP1559Compatibility = getCurrentNetworkEIP1559Compatibility; +- this.getCurrentNetworkLegacyGasAPICompatibility = getCurrentNetworkLegacyGasAPICompatibility; +- this.getCurrentAccountEIP1559Compatibility = getCurrentAccountEIP1559Compatibility; +- _chunkQ2YPK5SLjs.__privateSet.call(void 0, this, _getProvider, getProvider); +- this.EIP1559APIEndpoint = `${GAS_API_BASE_URL}/networks/<chain_id>/suggestedGasFees`; +- this.legacyAPIEndpoint = `${GAS_API_BASE_URL}/networks/<chain_id>/gasPrices`; +- this.clientId = clientId; +- this.infuraAPIKey = infuraAPIKey; +- this.ethQuery = new (0, _ethquery2.default)(_chunkQ2YPK5SLjs.__privateGet.call(void 0, this, _getProvider).call(this)); +- if (onNetworkDidChange && getChainId) { +- this.currentChainId = getChainId(); +- onNetworkDidChange(async (networkControllerState) => { +- await _chunkQ2YPK5SLjs.__privateMethod.call(void 0, this, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn).call(this, networkControllerState); +- }); +- } else { +- this.currentChainId = this.messagingSystem.call( +- "NetworkController:getState" +- ).providerConfig.chainId; +- this.messagingSystem.subscribe( +- "NetworkController:networkDidChange", +- async (networkControllerState) => { +- await _chunkQ2YPK5SLjs.__privateMethod.call(void 0, this, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn).call(this, networkControllerState); +- } +- ); +- } +- } +- async resetPolling() { +- if (this.pollTokens.size !== 0) { +- const tokens = Array.from(this.pollTokens); +- this.stopPolling(); +- await this.getGasFeeEstimatesAndStartPolling(tokens[0]); +- tokens.slice(1).forEach((token) => { +- this.pollTokens.add(token); +- }); +- } +- } +- async fetchGasFeeEstimates(options) { +- return await this._fetchGasFeeEstimateData(options); +- } +- async getGasFeeEstimatesAndStartPolling(pollToken) { +- const _pollToken = pollToken || _uuid.v1.call(void 0, ); +- this.pollTokens.add(_pollToken); +- if (this.pollTokens.size === 1) { +- await this._fetchGasFeeEstimateData(); +- this._poll(); +- } +- return _pollToken; +- } +- /** +- * Gets and sets gasFeeEstimates in state. +- * +- * @param options - The gas fee estimate options. +- * @param options.shouldUpdateState - Determines whether the state should be updated with the +- * updated gas estimates. +- * @returns The gas fee estimates. +- */ +- async _fetchGasFeeEstimateData(options = {}) { +- const { shouldUpdateState = true, networkClientId } = options; +- let ethQuery, isEIP1559Compatible, isLegacyGasAPICompatible, decimalChainId; +- if (networkClientId !== void 0) { +- const networkClient = this.messagingSystem.call( +- "NetworkController:getNetworkClientById", +- networkClientId +- ); +- isLegacyGasAPICompatible = networkClient.configuration.chainId === "0x38"; +- decimalChainId = _controllerutils.convertHexToDecimal.call(void 0, networkClient.configuration.chainId); +- try { +- const result = await this.messagingSystem.call( +- "NetworkController:getEIP1559Compatibility", +- networkClientId +- ); +- isEIP1559Compatible = result || false; +- } catch { +- isEIP1559Compatible = false; +- } +- ethQuery = new (0, _ethquery2.default)(networkClient.provider); +- } +- ethQuery ?? (ethQuery = this.ethQuery); +- isLegacyGasAPICompatible ?? (isLegacyGasAPICompatible = this.getCurrentNetworkLegacyGasAPICompatibility()); +- decimalChainId ?? (decimalChainId = _controllerutils.convertHexToDecimal.call(void 0, this.currentChainId)); +- try { +- isEIP1559Compatible ?? (isEIP1559Compatible = await this.getEIP1559Compatibility()); +- } catch (e) { +- console.error(e); +- isEIP1559Compatible ?? (isEIP1559Compatible = false); +- } +- const gasFeeCalculations = await determineGasFeeCalculations({ +- isEIP1559Compatible, +- isLegacyGasAPICompatible, +- fetchGasEstimates: _chunkQ2YPK5SLjs.fetchGasEstimates, +- fetchGasEstimatesUrl: this.EIP1559APIEndpoint.replace( +- "<chain_id>", +- `${decimalChainId}` +- ), +- fetchLegacyGasPriceEstimates: _chunkQ2YPK5SLjs.fetchLegacyGasPriceEstimates, +- fetchLegacyGasPriceEstimatesUrl: this.legacyAPIEndpoint.replace( +- "<chain_id>", +- `${decimalChainId}` +- ), +- fetchEthGasPriceEstimate: _chunkQ2YPK5SLjs.fetchEthGasPriceEstimate, +- calculateTimeEstimate: _chunkQ2YPK5SLjs.calculateTimeEstimate, +- clientId: this.clientId, +- ethQuery, +- infuraAPIKey: this.infuraAPIKey, +- nonRPCGasFeeApisDisabled: this.state.nonRPCGasFeeApisDisabled +- }); +- if (shouldUpdateState) { +- const chainId = _controllerutils.toHex.call(void 0, decimalChainId); +- this.update((state) => { +- if (this.currentChainId === chainId) { +- state.gasFeeEstimates = gasFeeCalculations.gasFeeEstimates; +- state.estimatedGasFeeTimeBounds = gasFeeCalculations.estimatedGasFeeTimeBounds; +- state.gasEstimateType = gasFeeCalculations.gasEstimateType; +- } +- state.gasFeeEstimatesByChainId ?? (state.gasFeeEstimatesByChainId = {}); +- state.gasFeeEstimatesByChainId[chainId] = { +- gasFeeEstimates: gasFeeCalculations.gasFeeEstimates, +- estimatedGasFeeTimeBounds: gasFeeCalculations.estimatedGasFeeTimeBounds, +- gasEstimateType: gasFeeCalculations.gasEstimateType +- }; +- }); +- } +- return gasFeeCalculations; +- } +- /** +- * Remove the poll token, and stop polling if the set of poll tokens is empty. +- * +- * @param pollToken - The poll token to disconnect. +- */ +- disconnectPoller(pollToken) { +- this.pollTokens.delete(pollToken); +- if (this.pollTokens.size === 0) { +- this.stopPolling(); +- } +- } +- stopPolling() { +- if (this.intervalId) { +- clearInterval(this.intervalId); +- } +- this.pollTokens.clear(); +- this.resetState(); +- } +- /** +- * Prepare to discard this controller. +- * +- * This stops any active polling. +- */ +- destroy() { +- super.destroy(); +- this.stopPolling(); +- } +- _poll() { +- if (this.intervalId) { +- clearInterval(this.intervalId); +- } +- this.intervalId = setInterval(async () => { +- await _controllerutils.safelyExecute.call(void 0, () => this._fetchGasFeeEstimateData()); +- }, this.intervalDelay); +- } +- /** +- * Fetching token list from the Token Service API. +- * +- * @private +- * @param networkClientId - The ID of the network client triggering the fetch. +- * @returns A promise that resolves when this operation completes. +- */ +- async _executePoll(networkClientId) { +- await this._fetchGasFeeEstimateData({ networkClientId }); +- } +- resetState() { +- this.update(() => { +- return defaultState; +- }); +- } +- async getEIP1559Compatibility() { +- const currentNetworkIsEIP1559Compatible = await this.getCurrentNetworkEIP1559Compatibility(); +- const currentAccountIsEIP1559Compatible = this.getCurrentAccountEIP1559Compatibility?.() ?? true; +- return currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible; +- } +- getTimeEstimate(maxPriorityFeePerGas, maxFeePerGas) { +- if (!this.state.gasFeeEstimates || this.state.gasEstimateType !== GAS_ESTIMATE_TYPES.FEE_MARKET) { +- return {}; +- } +- return _chunkQ2YPK5SLjs.calculateTimeEstimate.call(void 0, +- maxPriorityFeePerGas, +- maxFeePerGas, +- this.state.gasFeeEstimates +- ); +- } +- enableNonRPCGasFeeApis() { +- this.update((state) => { +- state.nonRPCGasFeeApisDisabled = false; +- }); +- } +- disableNonRPCGasFeeApis() { +- this.update((state) => { +- state.nonRPCGasFeeApisDisabled = true; +- }); +- } +-}; +-_getProvider = new WeakMap(); +-_onNetworkControllerDidChange = new WeakSet(); +-onNetworkControllerDidChange_fn = async function(networkControllerState) { +- const newChainId = networkControllerState.providerConfig.chainId; +- if (newChainId !== this.currentChainId) { +- this.ethQuery = new (0, _ethquery2.default)(_chunkQ2YPK5SLjs.__privateGet.call(void 0, this, _getProvider).call(this)); +- await this.resetPolling(); +- this.currentChainId = newChainId; +- } +-}; +-var GasFeeController_default = GasFeeController; +- +-// src/determineGasFeeCalculations.ts +-async function determineGasFeeCalculations(args) { +- try { +- return await getEstimatesUsingFallbacks(args); +- } catch (error) { +- if (error instanceof Error) { +- throw new Error( +- `Gas fee/price estimation failed. Message: ${error.message}` +- ); +- } +- throw error; +- } +-} +-async function getEstimatesUsingFallbacks(request) { +- const { +- isEIP1559Compatible, +- isLegacyGasAPICompatible, +- nonRPCGasFeeApisDisabled +- } = request; +- try { +- if (isEIP1559Compatible && !nonRPCGasFeeApisDisabled) { +- return await getEstimatesUsingFeeMarketEndpoint(request); +- } +- if (isLegacyGasAPICompatible && !nonRPCGasFeeApisDisabled) { +- return await getEstimatesUsingLegacyEndpoint(request); +- } +- throw new Error("Main gas fee/price estimation failed. Use fallback"); +- } catch { +- return await getEstimatesUsingProvider(request); +- } +-} +-async function getEstimatesUsingFeeMarketEndpoint(request) { +- const { +- fetchGasEstimates: fetchGasEstimates2, +- fetchGasEstimatesUrl, +- infuraAPIKey, +- clientId, +- calculateTimeEstimate: calculateTimeEstimate2 +- } = request; +- const estimates = await fetchGasEstimates2( +- fetchGasEstimatesUrl, +- infuraAPIKey, +- clientId +- ); +- const { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas } = estimates.medium; +- const estimatedGasFeeTimeBounds = calculateTimeEstimate2( +- suggestedMaxPriorityFeePerGas, +- suggestedMaxFeePerGas, +- estimates +- ); +- return { +- gasFeeEstimates: estimates, +- estimatedGasFeeTimeBounds, +- gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET +- }; +-} +-async function getEstimatesUsingLegacyEndpoint(request) { +- const { +- fetchLegacyGasPriceEstimates: fetchLegacyGasPriceEstimates2, +- fetchLegacyGasPriceEstimatesUrl, +- infuraAPIKey, +- clientId +- } = request; +- const estimates = await fetchLegacyGasPriceEstimates2( +- fetchLegacyGasPriceEstimatesUrl, +- infuraAPIKey, +- clientId +- ); +- return { +- gasFeeEstimates: estimates, +- estimatedGasFeeTimeBounds: {}, +- gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY +- }; +-} +-async function getEstimatesUsingProvider(request) { +- const { ethQuery, fetchEthGasPriceEstimate: fetchEthGasPriceEstimate2 } = request; +- const estimates = await fetchEthGasPriceEstimate2(ethQuery); +- return { +- gasFeeEstimates: estimates, +- estimatedGasFeeTimeBounds: {}, +- gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE +- }; +-} +- +- +- +- +- +- +- +-exports.determineGasFeeCalculations = determineGasFeeCalculations; exports.GAS_API_BASE_URL = GAS_API_BASE_URL; exports.GAS_ESTIMATE_TYPES = GAS_ESTIMATE_TYPES; exports.GasFeeController = GasFeeController; exports.GasFeeController_default = GasFeeController_default; +-//# sourceMappingURL=chunk-H5WHAYLI.js.map +\ No newline at end of file +diff --git a/dist/chunk-H5WHAYLI.js.map b/dist/chunk-H5WHAYLI.js.map +deleted file mode 100644 +index ed761f584584470a8176f029d9d860dc017428fc..0000000000000000000000000000000000000000 +--- a/dist/chunk-H5WHAYLI.js.map ++++ /dev/null +@@ -1 +0,0 @@ +-{"version":3,"sources":["../src/GasFeeController.ts","../src/determineGasFeeCalculations.ts"],"names":["fetchGasEstimates","calculateTimeEstimate","fetchLegacyGasPriceEstimates","fetchEthGasPriceEstimate"],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport {\n convertHexToDecimal,\n safelyExecute,\n toHex,\n} from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkControllerGetEIP1559CompatibilityAction,\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n NetworkControllerNetworkDidChangeEvent,\n NetworkState,\n ProviderProxy,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { v1 as random } from 'uuid';\n\nimport determineGasFeeCalculations from './determineGasFeeCalculations';\nimport {\n calculateTimeEstimate,\n fetchGasEstimates,\n fetchLegacyGasPriceEstimates,\n fetchEthGasPriceEstimate,\n} from './gas-util';\n\nexport const GAS_API_BASE_URL = 'https://gas.api.infura.io';\n\nexport type unknownString = 'unknown';\n\n// Fee Market describes the way gas is set after the london hardfork, and was\n// defined by EIP-1559.\nexport type FeeMarketEstimateType = 'fee-market';\n// Legacy describes gasPrice estimates from before london hardfork, when the\n// user is connected to mainnet and are presented with fast/average/slow\n// estimate levels to choose from.\nexport type LegacyEstimateType = 'legacy';\n// EthGasPrice describes a gasPrice estimate received from eth_gasPrice. Post\n// london this value should only be used for legacy type transactions when on\n// networks that support EIP-1559. This type of estimate is the most accurate\n// to display on custom networks that don't support EIP-1559.\nexport type EthGasPriceEstimateType = 'eth_gasPrice';\n// NoEstimate describes the state of the controller before receiving its first\n// estimate.\nexport type NoEstimateType = 'none';\n\n/**\n * Indicates which type of gasEstimate the controller is currently returning.\n * This is useful as a way of asserting that the shape of gasEstimates matches\n * expectations. NONE is a special case indicating that no previous gasEstimate\n * has been fetched.\n */\nexport const GAS_ESTIMATE_TYPES = {\n FEE_MARKET: 'fee-market' as FeeMarketEstimateType,\n LEGACY: 'legacy' as LegacyEstimateType,\n ETH_GASPRICE: 'eth_gasPrice' as EthGasPriceEstimateType,\n NONE: 'none' as NoEstimateType,\n};\n\nexport type GasEstimateType =\n | FeeMarketEstimateType\n | EthGasPriceEstimateType\n | LegacyEstimateType\n | NoEstimateType;\n\nexport type EstimatedGasFeeTimeBounds = {\n lowerTimeBound: number | null;\n upperTimeBound: number | unknownString;\n};\n\n/**\n * @type EthGasPriceEstimate\n *\n * A single gas price estimate for networks and accounts that don't support EIP-1559\n * This estimate comes from eth_gasPrice but is converted to dec gwei to match other\n * return values\n * @property gasPrice - A GWEI dec string\n */\n\nexport type EthGasPriceEstimate = {\n gasPrice: string;\n};\n\n/**\n * @type LegacyGasPriceEstimate\n *\n * A set of gas price estimates for networks and accounts that don't support EIP-1559\n * These estimates include low, medium and high all as strings representing gwei in\n * decimal format.\n * @property high - gasPrice, in decimal gwei string format, suggested for fast inclusion\n * @property medium - gasPrice, in decimal gwei string format, suggested for avg inclusion\n * @property low - gasPrice, in decimal gwei string format, suggested for slow inclusion\n */\nexport type LegacyGasPriceEstimate = {\n high: string;\n medium: string;\n low: string;\n};\n\n/**\n * @type Eip1559GasFee\n *\n * Data necessary to provide an estimate of a gas fee with a specific tip\n * @property minWaitTimeEstimate - The fastest the transaction will take, in milliseconds\n * @property maxWaitTimeEstimate - The slowest the transaction will take, in milliseconds\n * @property suggestedMaxPriorityFeePerGas - A suggested \"tip\", a GWEI hex number\n * @property suggestedMaxFeePerGas - A suggested max fee, the most a user will pay. a GWEI hex number\n */\nexport type Eip1559GasFee = {\n minWaitTimeEstimate: number; // a time duration in milliseconds\n maxWaitTimeEstimate: number; // a time duration in milliseconds\n suggestedMaxPriorityFeePerGas: string; // a GWEI decimal number\n suggestedMaxFeePerGas: string; // a GWEI decimal number\n};\n\n/**\n * @type GasFeeEstimates\n *\n * Data necessary to provide multiple GasFee estimates, and supporting information, to the user\n * @property low - A GasFee for a minimum necessary combination of tip and maxFee\n * @property medium - A GasFee for a recommended combination of tip and maxFee\n * @property high - A GasFee for a high combination of tip and maxFee\n * @property estimatedBaseFee - An estimate of what the base fee will be for the pending/next block. A GWEI dec number\n * @property networkCongestion - A normalized number that can be used to gauge the congestion\n * level of the network, with 0 meaning not congested and 1 meaning extremely congested\n */\nexport type GasFeeEstimates = SourcedGasFeeEstimates | FallbackGasFeeEstimates;\n\ntype SourcedGasFeeEstimates = {\n low: Eip1559GasFee;\n medium: Eip1559GasFee;\n high: Eip1559GasFee;\n estimatedBaseFee: string;\n historicalBaseFeeRange: [string, string];\n baseFeeTrend: 'up' | 'down' | 'level';\n latestPriorityFeeRange: [string, string];\n historicalPriorityFeeRange: [string, string];\n priorityFeeTrend: 'up' | 'down' | 'level';\n networkCongestion: number;\n};\n\ntype FallbackGasFeeEstimates = {\n low: Eip1559GasFee;\n medium: Eip1559GasFee;\n high: Eip1559GasFee;\n estimatedBaseFee: string;\n historicalBaseFeeRange: null;\n baseFeeTrend: null;\n latestPriorityFeeRange: null;\n historicalPriorityFeeRange: null;\n priorityFeeTrend: null;\n networkCongestion: null;\n};\n\nconst metadata = {\n gasFeeEstimatesByChainId: {\n persist: true,\n anonymous: false,\n },\n gasFeeEstimates: { persist: true, anonymous: false },\n estimatedGasFeeTimeBounds: { persist: true, anonymous: false },\n gasEstimateType: { persist: true, anonymous: false },\n nonRPCGasFeeApisDisabled: { persist: true, anonymous: false },\n};\n\nexport type GasFeeStateEthGasPrice = {\n gasFeeEstimates: EthGasPriceEstimate;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: EthGasPriceEstimateType;\n};\n\nexport type GasFeeStateFeeMarket = {\n gasFeeEstimates: GasFeeEstimates;\n estimatedGasFeeTimeBounds: EstimatedGasFeeTimeBounds | Record<string, never>;\n gasEstimateType: FeeMarketEstimateType;\n};\n\nexport type GasFeeStateLegacy = {\n gasFeeEstimates: LegacyGasPriceEstimate;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: LegacyEstimateType;\n};\n\nexport type GasFeeStateNoEstimates = {\n gasFeeEstimates: Record<string, never>;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: NoEstimateType;\n};\n\nexport type FetchGasFeeEstimateOptions = {\n shouldUpdateState?: boolean;\n networkClientId?: NetworkClientId;\n};\n\n/**\n * @type GasFeeState\n *\n * Gas Fee controller state\n * @property gasFeeEstimates - Gas fee estimate data based on new EIP-1559 properties\n * @property estimatedGasFeeTimeBounds - Estimates representing the minimum and maximum\n */\nexport type SingleChainGasFeeState =\n | GasFeeStateEthGasPrice\n | GasFeeStateFeeMarket\n | GasFeeStateLegacy\n | GasFeeStateNoEstimates;\n\nexport type GasFeeEstimatesByChainId = {\n gasFeeEstimatesByChainId?: Record<string, SingleChainGasFeeState>;\n};\n\nexport type GasFeeState = GasFeeEstimatesByChainId &\n SingleChainGasFeeState & {\n nonRPCGasFeeApisDisabled?: boolean;\n };\n\nconst name = 'GasFeeController';\n\nexport type GasFeeStateChange = ControllerStateChangeEvent<\n typeof name,\n GasFeeState\n>;\n\nexport type GetGasFeeState = ControllerGetStateAction<typeof name, GasFeeState>;\n\nexport type GasFeeControllerActions = GetGasFeeState;\n\nexport type GasFeeControllerEvents = GasFeeStateChange;\n\ntype AllowedActions =\n | NetworkControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetEIP1559CompatibilityAction;\n\ntype GasFeeMessenger = RestrictedControllerMessenger<\n typeof name,\n GasFeeControllerActions | AllowedActions,\n GasFeeControllerEvents | NetworkControllerNetworkDidChangeEvent,\n AllowedActions['type'],\n NetworkControllerNetworkDidChangeEvent['type']\n>;\n\nconst defaultState: GasFeeState = {\n gasFeeEstimatesByChainId: {},\n gasFeeEstimates: {},\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.NONE,\n nonRPCGasFeeApisDisabled: false,\n};\n\n/**\n * Controller that retrieves gas fee estimate data and polls for updated data on a set interval\n */\nexport class GasFeeController extends StaticIntervalPollingController<\n typeof name,\n GasFeeState,\n GasFeeMessenger\n> {\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay;\n\n private readonly pollTokens: Set<string>;\n\n private readonly legacyAPIEndpoint: string;\n\n private readonly EIP1559APIEndpoint: string;\n\n private readonly getCurrentNetworkEIP1559Compatibility;\n\n private readonly getCurrentNetworkLegacyGasAPICompatibility;\n\n private readonly getCurrentAccountEIP1559Compatibility;\n\n private readonly infuraAPIKey: string;\n\n private currentChainId;\n\n private ethQuery?: EthQuery;\n\n private readonly clientId?: string;\n\n #getProvider: () => ProviderProxy;\n\n /**\n * Creates a GasFeeController instance.\n *\n * @param options - The controller options.\n * @param options.interval - The time in milliseconds to wait between polls.\n * @param options.messenger - The controller messenger.\n * @param options.state - The initial state.\n * @param options.getCurrentNetworkEIP1559Compatibility - Determines whether or not the current\n * network is EIP-1559 compatible.\n * @param options.getCurrentNetworkLegacyGasAPICompatibility - Determines whether or not the\n * current network is compatible with the legacy gas price API.\n * @param options.getCurrentAccountEIP1559Compatibility - Determines whether or not the current\n * account is EIP-1559 compatible.\n * @param options.getChainId - Returns the current chain ID.\n * @param options.getProvider - Returns a network provider for the current network.\n * @param options.onNetworkDidChange - A function for registering an event handler for the\n * network state change event.\n * @param options.clientId - The client ID used to identify to the gas estimation API who is\n * asking for estimates.\n * @param options.infuraAPIKey - The Infura API key used for infura API requests.\n */\n constructor({\n interval = 15000,\n messenger,\n state,\n getCurrentNetworkEIP1559Compatibility,\n getCurrentAccountEIP1559Compatibility,\n getChainId,\n getCurrentNetworkLegacyGasAPICompatibility,\n getProvider,\n onNetworkDidChange,\n clientId,\n infuraAPIKey,\n }: {\n interval?: number;\n messenger: GasFeeMessenger;\n state?: GasFeeState;\n getCurrentNetworkEIP1559Compatibility: () => Promise<boolean>;\n getCurrentNetworkLegacyGasAPICompatibility: () => boolean;\n getCurrentAccountEIP1559Compatibility?: () => boolean;\n getChainId?: () => Hex;\n getProvider: () => ProviderProxy;\n onNetworkDidChange?: (listener: (state: NetworkState) => void) => void;\n clientId?: string;\n infuraAPIKey: string;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.intervalDelay = interval;\n this.setIntervalLength(interval);\n this.pollTokens = new Set();\n this.getCurrentNetworkEIP1559Compatibility =\n getCurrentNetworkEIP1559Compatibility;\n this.getCurrentNetworkLegacyGasAPICompatibility =\n getCurrentNetworkLegacyGasAPICompatibility;\n this.getCurrentAccountEIP1559Compatibility =\n getCurrentAccountEIP1559Compatibility;\n this.#getProvider = getProvider;\n this.EIP1559APIEndpoint = `${GAS_API_BASE_URL}/networks/<chain_id>/suggestedGasFees`;\n this.legacyAPIEndpoint = `${GAS_API_BASE_URL}/networks/<chain_id>/gasPrices`;\n this.clientId = clientId;\n this.infuraAPIKey = infuraAPIKey;\n\n this.ethQuery = new EthQuery(this.#getProvider());\n\n if (onNetworkDidChange && getChainId) {\n this.currentChainId = getChainId();\n onNetworkDidChange(async (networkControllerState) => {\n await this.#onNetworkControllerDidChange(networkControllerState);\n });\n } else {\n this.currentChainId = this.messagingSystem.call(\n 'NetworkController:getState',\n ).providerConfig.chainId;\n this.messagingSystem.subscribe(\n 'NetworkController:networkDidChange',\n async (networkControllerState) => {\n await this.#onNetworkControllerDidChange(networkControllerState);\n },\n );\n }\n }\n\n async resetPolling() {\n if (this.pollTokens.size !== 0) {\n const tokens = Array.from(this.pollTokens);\n this.stopPolling();\n await this.getGasFeeEstimatesAndStartPolling(tokens[0]);\n tokens.slice(1).forEach((token) => {\n this.pollTokens.add(token);\n });\n }\n }\n\n async fetchGasFeeEstimates(options?: FetchGasFeeEstimateOptions) {\n return await this._fetchGasFeeEstimateData(options);\n }\n\n async getGasFeeEstimatesAndStartPolling(\n pollToken: string | undefined,\n ): Promise<string> {\n const _pollToken = pollToken || random();\n\n this.pollTokens.add(_pollToken);\n\n if (this.pollTokens.size === 1) {\n await this._fetchGasFeeEstimateData();\n this._poll();\n }\n\n return _pollToken;\n }\n\n /**\n * Gets and sets gasFeeEstimates in state.\n *\n * @param options - The gas fee estimate options.\n * @param options.shouldUpdateState - Determines whether the state should be updated with the\n * updated gas estimates.\n * @returns The gas fee estimates.\n */\n async _fetchGasFeeEstimateData(\n options: FetchGasFeeEstimateOptions = {},\n ): Promise<GasFeeState> {\n const { shouldUpdateState = true, networkClientId } = options;\n\n let ethQuery,\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n decimalChainId: number;\n\n if (networkClientId !== undefined) {\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n isLegacyGasAPICompatible = networkClient.configuration.chainId === '0x38';\n\n decimalChainId = convertHexToDecimal(networkClient.configuration.chainId);\n\n try {\n const result = await this.messagingSystem.call(\n 'NetworkController:getEIP1559Compatibility',\n networkClientId,\n );\n isEIP1559Compatible = result || false;\n } catch {\n isEIP1559Compatible = false;\n }\n ethQuery = new EthQuery(networkClient.provider);\n }\n\n ethQuery ??= this.ethQuery;\n\n isLegacyGasAPICompatible ??=\n this.getCurrentNetworkLegacyGasAPICompatibility();\n\n decimalChainId ??= convertHexToDecimal(this.currentChainId);\n\n try {\n isEIP1559Compatible ??= await this.getEIP1559Compatibility();\n } catch (e) {\n console.error(e);\n isEIP1559Compatible ??= false;\n }\n\n const gasFeeCalculations = await determineGasFeeCalculations({\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n fetchGasEstimates,\n fetchGasEstimatesUrl: this.EIP1559APIEndpoint.replace(\n '<chain_id>',\n `${decimalChainId}`,\n ),\n fetchLegacyGasPriceEstimates,\n fetchLegacyGasPriceEstimatesUrl: this.legacyAPIEndpoint.replace(\n '<chain_id>',\n `${decimalChainId}`,\n ),\n fetchEthGasPriceEstimate,\n calculateTimeEstimate,\n clientId: this.clientId,\n ethQuery,\n infuraAPIKey: this.infuraAPIKey,\n nonRPCGasFeeApisDisabled: this.state.nonRPCGasFeeApisDisabled,\n });\n\n if (shouldUpdateState) {\n const chainId = toHex(decimalChainId);\n this.update((state) => {\n if (this.currentChainId === chainId) {\n state.gasFeeEstimates = gasFeeCalculations.gasFeeEstimates;\n state.estimatedGasFeeTimeBounds =\n gasFeeCalculations.estimatedGasFeeTimeBounds;\n state.gasEstimateType = gasFeeCalculations.gasEstimateType;\n }\n state.gasFeeEstimatesByChainId ??= {};\n state.gasFeeEstimatesByChainId[chainId] = {\n gasFeeEstimates: gasFeeCalculations.gasFeeEstimates,\n estimatedGasFeeTimeBounds:\n gasFeeCalculations.estimatedGasFeeTimeBounds,\n gasEstimateType: gasFeeCalculations.gasEstimateType,\n } as SingleChainGasFeeState;\n });\n }\n\n return gasFeeCalculations;\n }\n\n /**\n * Remove the poll token, and stop polling if the set of poll tokens is empty.\n *\n * @param pollToken - The poll token to disconnect.\n */\n disconnectPoller(pollToken: string) {\n this.pollTokens.delete(pollToken);\n if (this.pollTokens.size === 0) {\n this.stopPolling();\n }\n }\n\n stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n this.pollTokens.clear();\n this.resetState();\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n private _poll() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this._fetchGasFeeEstimateData());\n }, this.intervalDelay);\n }\n\n /**\n * Fetching token list from the Token Service API.\n *\n * @private\n * @param networkClientId - The ID of the network client triggering the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll(networkClientId: string): Promise<void> {\n await this._fetchGasFeeEstimateData({ networkClientId });\n }\n\n private resetState() {\n this.update(() => {\n return defaultState;\n });\n }\n\n private async getEIP1559Compatibility() {\n const currentNetworkIsEIP1559Compatible =\n await this.getCurrentNetworkEIP1559Compatibility();\n const currentAccountIsEIP1559Compatible =\n this.getCurrentAccountEIP1559Compatibility?.() ?? true;\n\n return (\n currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible\n );\n }\n\n getTimeEstimate(\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n ): EstimatedGasFeeTimeBounds | Record<string, never> {\n if (\n !this.state.gasFeeEstimates ||\n this.state.gasEstimateType !== GAS_ESTIMATE_TYPES.FEE_MARKET\n ) {\n return {};\n }\n return calculateTimeEstimate(\n maxPriorityFeePerGas,\n maxFeePerGas,\n this.state.gasFeeEstimates,\n );\n }\n\n async #onNetworkControllerDidChange(networkControllerState: NetworkState) {\n const newChainId = networkControllerState.providerConfig.chainId;\n\n if (newChainId !== this.currentChainId) {\n this.ethQuery = new EthQuery(this.#getProvider());\n await this.resetPolling();\n\n this.currentChainId = newChainId;\n }\n }\n\n enableNonRPCGasFeeApis() {\n this.update((state) => {\n state.nonRPCGasFeeApisDisabled = false;\n });\n }\n\n disableNonRPCGasFeeApis() {\n this.update((state) => {\n state.nonRPCGasFeeApisDisabled = true;\n });\n }\n}\n\nexport default GasFeeController;\n","import type {\n EstimatedGasFeeTimeBounds,\n EthGasPriceEstimate,\n GasFeeEstimates,\n GasFeeState as GasFeeCalculations,\n LegacyGasPriceEstimate,\n} from './GasFeeController';\nimport { GAS_ESTIMATE_TYPES } from './GasFeeController';\n\ntype DetermineGasFeeCalculationsRequest = {\n isEIP1559Compatible: boolean;\n isLegacyGasAPICompatible: boolean;\n fetchGasEstimates: (\n url: string,\n infuraAPIKey: string,\n clientId?: string,\n ) => Promise<GasFeeEstimates>;\n fetchGasEstimatesUrl: string;\n fetchLegacyGasPriceEstimates: (\n url: string,\n infuraAPIKey: string,\n clientId?: string,\n ) => Promise<LegacyGasPriceEstimate>;\n fetchLegacyGasPriceEstimatesUrl: string;\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fetchEthGasPriceEstimate: (ethQuery: any) => Promise<EthGasPriceEstimate>;\n calculateTimeEstimate: (\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n gasFeeEstimates: GasFeeEstimates,\n ) => EstimatedGasFeeTimeBounds;\n clientId: string | undefined;\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ethQuery: any;\n infuraAPIKey: string;\n nonRPCGasFeeApisDisabled?: boolean;\n};\n\n/**\n * Obtains a set of max base and priority fee estimates along with time estimates so that we\n * can present them to users when they are sending transactions or making swaps.\n *\n * @param args - The arguments.\n * @param args.isEIP1559Compatible - Governs whether or not we can use an EIP-1559-only method to\n * produce estimates.\n * @param args.isLegacyGasAPICompatible - Governs whether or not we can use a non-EIP-1559 method to\n * produce estimates (for instance, testnets do not support estimates altogether).\n * @param args.fetchGasEstimates - A function that fetches gas estimates using an EIP-1559-specific\n * API.\n * @param args.fetchGasEstimatesUrl - The URL for the API we can use to obtain EIP-1559-specific\n * estimates.\n * @param args.fetchLegacyGasPriceEstimates - A function that fetches gas estimates using an\n * non-EIP-1559-specific API.\n * @param args.fetchLegacyGasPriceEstimatesUrl - The URL for the API we can use to obtain\n * non-EIP-1559-specific estimates.\n * @param args.fetchEthGasPriceEstimate - A function that fetches gas estimates using\n * `eth_gasPrice`.\n * @param args.calculateTimeEstimate - A function that determine time estimate bounds.\n * @param args.clientId - An identifier that an API can use to know who is asking for estimates.\n * @param args.ethQuery - An EthQuery instance we can use to talk to Ethereum directly.\n * @param args.infuraAPIKey - Infura API key to use for requests to Infura.\n * @param args.nonRPCGasFeeApisDisabled - Whether to disable requests to the legacyAPIEndpoint and the EIP1559APIEndpoint\n * @returns The gas fee calculations.\n */\nexport default async function determineGasFeeCalculations(\n args: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n try {\n return await getEstimatesUsingFallbacks(args);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Gas fee/price estimation failed. Message: ${error.message}`,\n );\n }\n\n throw error;\n }\n}\n\n/**\n * Retrieve the gas fee estimates using a series of fallback mechanisms.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingFallbacks(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n nonRPCGasFeeApisDisabled,\n } = request;\n\n try {\n if (isEIP1559Compatible && !nonRPCGasFeeApisDisabled) {\n return await getEstimatesUsingFeeMarketEndpoint(request);\n }\n\n if (isLegacyGasAPICompatible && !nonRPCGasFeeApisDisabled) {\n return await getEstimatesUsingLegacyEndpoint(request);\n }\n\n throw new Error('Main gas fee/price estimation failed. Use fallback');\n } catch {\n return await getEstimatesUsingProvider(request);\n }\n}\n\n/**\n * Retrieve gas fee estimates using the EIP-1559 endpoint of the gas API.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingFeeMarketEndpoint(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n fetchGasEstimates,\n fetchGasEstimatesUrl,\n infuraAPIKey,\n clientId,\n calculateTimeEstimate,\n } = request;\n\n const estimates = await fetchGasEstimates(\n fetchGasEstimatesUrl,\n infuraAPIKey,\n clientId,\n );\n\n const { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas } =\n estimates.medium;\n\n const estimatedGasFeeTimeBounds = calculateTimeEstimate(\n suggestedMaxPriorityFeePerGas,\n suggestedMaxFeePerGas,\n estimates,\n );\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds,\n gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,\n };\n}\n\n/**\n * Retrieve gas fee estimates using the legacy endpoint of the gas API.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingLegacyEndpoint(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n fetchLegacyGasPriceEstimates,\n fetchLegacyGasPriceEstimatesUrl,\n infuraAPIKey,\n clientId,\n } = request;\n\n const estimates = await fetchLegacyGasPriceEstimates(\n fetchLegacyGasPriceEstimatesUrl,\n infuraAPIKey,\n clientId,\n );\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,\n };\n}\n\n/**\n * Retrieve gas fee estimates using an `eth_gasPrice` call to the RPC provider.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingProvider(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const { ethQuery, fetchEthGasPriceEstimate } = request;\n\n const estimates = await fetchEthGasPriceEstimate(ethQuery);\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE,\n };\n}\n"]} +\ No newline at end of file +diff --git a/dist/chunk-KORLXV32.mjs b/dist/chunk-KORLXV32.mjs +deleted file mode 100644 +index a964582d5c161e6b650fe9447442ca9540f9fdb9..0000000000000000000000000000000000000000 +--- a/dist/chunk-KORLXV32.mjs ++++ /dev/null +@@ -1,165 +0,0 @@ +-var __accessCheck = (obj, member, msg) => { +- if (!member.has(obj)) +- throw TypeError("Cannot " + msg); +-}; +-var __privateGet = (obj, member, getter) => { +- __accessCheck(obj, member, "read from private field"); +- return getter ? getter.call(obj) : member.get(obj); +-}; +-var __privateAdd = (obj, member, value) => { +- if (member.has(obj)) +- throw TypeError("Cannot add the same private member more than once"); +- member instanceof WeakSet ? member.add(obj) : member.set(obj, value); +-}; +-var __privateSet = (obj, member, value, setter) => { +- __accessCheck(obj, member, "write to private field"); +- setter ? setter.call(obj, value) : member.set(obj, value); +- return value; +-}; +-var __privateMethod = (obj, member, method) => { +- __accessCheck(obj, member, "access private method"); +- return method; +-}; +- +-// src/gas-util.ts +-import { +- query, +- handleFetch, +- gweiDecToWEIBN, +- weiHexToGweiDec +-} from "@metamask/controller-utils"; +-import BN from "bn.js"; +-var makeClientIdHeader = (clientId) => ({ "X-Client-Id": clientId }); +-function normalizeGWEIDecimalNumbers(n) { +- const numberAsWEIHex = gweiDecToWEIBN(n).toString(16); +- const numberAsGWEI = weiHexToGweiDec(numberAsWEIHex); +- return numberAsGWEI; +-} +-async function fetchGasEstimates(url, infuraAPIKey, clientId) { +- const infuraAuthToken = buildInfuraAuthToken(infuraAPIKey); +- const estimates = await handleFetch(url, { +- headers: getHeaders(infuraAuthToken, clientId) +- }); +- return { +- low: { +- ...estimates.low, +- suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.low.suggestedMaxPriorityFeePerGas +- ), +- suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.low.suggestedMaxFeePerGas +- ) +- }, +- medium: { +- ...estimates.medium, +- suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.medium.suggestedMaxPriorityFeePerGas +- ), +- suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.medium.suggestedMaxFeePerGas +- ) +- }, +- high: { +- ...estimates.high, +- suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.high.suggestedMaxPriorityFeePerGas +- ), +- suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.high.suggestedMaxFeePerGas +- ) +- }, +- estimatedBaseFee: normalizeGWEIDecimalNumbers(estimates.estimatedBaseFee), +- historicalBaseFeeRange: estimates.historicalBaseFeeRange, +- baseFeeTrend: estimates.baseFeeTrend, +- latestPriorityFeeRange: estimates.latestPriorityFeeRange, +- historicalPriorityFeeRange: estimates.historicalPriorityFeeRange, +- priorityFeeTrend: estimates.priorityFeeTrend, +- networkCongestion: estimates.networkCongestion +- }; +-} +-async function fetchLegacyGasPriceEstimates(url, infuraAPIKey, clientId) { +- const infuraAuthToken = buildInfuraAuthToken(infuraAPIKey); +- const result = await handleFetch(url, { +- referrer: url, +- referrerPolicy: "no-referrer-when-downgrade", +- method: "GET", +- mode: "cors", +- headers: getHeaders(infuraAuthToken, clientId) +- }); +- return { +- low: result.SafeGasPrice, +- medium: result.ProposeGasPrice, +- high: result.FastGasPrice +- }; +-} +-async function fetchEthGasPriceEstimate(ethQuery) { +- const gasPrice = await query(ethQuery, "gasPrice"); +- return { +- gasPrice: weiHexToGweiDec(gasPrice).toString() +- }; +-} +-function calculateTimeEstimate(maxPriorityFeePerGas, maxFeePerGas, gasFeeEstimates) { +- const { low, medium, high, estimatedBaseFee } = gasFeeEstimates; +- const maxPriorityFeePerGasInWEI = gweiDecToWEIBN(maxPriorityFeePerGas); +- const maxFeePerGasInWEI = gweiDecToWEIBN(maxFeePerGas); +- const estimatedBaseFeeInWEI = gweiDecToWEIBN(estimatedBaseFee); +- const effectiveMaxPriorityFee = BN.min( +- maxPriorityFeePerGasInWEI, +- maxFeePerGasInWEI.sub(estimatedBaseFeeInWEI) +- ); +- const lowMaxPriorityFeeInWEI = gweiDecToWEIBN( +- low.suggestedMaxPriorityFeePerGas +- ); +- const mediumMaxPriorityFeeInWEI = gweiDecToWEIBN( +- medium.suggestedMaxPriorityFeePerGas +- ); +- const highMaxPriorityFeeInWEI = gweiDecToWEIBN( +- high.suggestedMaxPriorityFeePerGas +- ); +- let lowerTimeBound; +- let upperTimeBound; +- if (effectiveMaxPriorityFee.lt(lowMaxPriorityFeeInWEI)) { +- lowerTimeBound = null; +- upperTimeBound = "unknown"; +- } else if (effectiveMaxPriorityFee.gte(lowMaxPriorityFeeInWEI) && effectiveMaxPriorityFee.lt(mediumMaxPriorityFeeInWEI)) { +- lowerTimeBound = low.minWaitTimeEstimate; +- upperTimeBound = low.maxWaitTimeEstimate; +- } else if (effectiveMaxPriorityFee.gte(mediumMaxPriorityFeeInWEI) && effectiveMaxPriorityFee.lt(highMaxPriorityFeeInWEI)) { +- lowerTimeBound = medium.minWaitTimeEstimate; +- upperTimeBound = medium.maxWaitTimeEstimate; +- } else if (effectiveMaxPriorityFee.eq(highMaxPriorityFeeInWEI)) { +- lowerTimeBound = high.minWaitTimeEstimate; +- upperTimeBound = high.maxWaitTimeEstimate; +- } else { +- lowerTimeBound = 0; +- upperTimeBound = high.maxWaitTimeEstimate; +- } +- return { +- lowerTimeBound, +- upperTimeBound +- }; +-} +-function buildInfuraAuthToken(infuraAPIKey) { +- return Buffer.from(`${infuraAPIKey}:`).toString("base64"); +-} +-function getHeaders(infuraAuthToken, clientId) { +- return { +- "Content-Type": "application/json", +- Authorization: `Basic ${infuraAuthToken}`, +- // Only add the clientId header if clientId is a non-empty string +- ...clientId?.trim() ? makeClientIdHeader(clientId) : {} +- }; +-} +- +-export { +- __privateGet, +- __privateAdd, +- __privateSet, +- __privateMethod, +- normalizeGWEIDecimalNumbers, +- fetchGasEstimates, +- fetchLegacyGasPriceEstimates, +- fetchEthGasPriceEstimate, +- calculateTimeEstimate +-}; +-//# sourceMappingURL=chunk-KORLXV32.mjs.map +\ No newline at end of file +diff --git a/dist/chunk-KORLXV32.mjs.map b/dist/chunk-KORLXV32.mjs.map +deleted file mode 100644 +index b95130543a5b39392214c5fe873ad367e6fa8af7..0000000000000000000000000000000000000000 +--- a/dist/chunk-KORLXV32.mjs.map ++++ /dev/null +@@ -1 +0,0 @@ +-{"version":3,"sources":["../src/gas-util.ts"],"sourcesContent":["import {\n query,\n handleFetch,\n gweiDecToWEIBN,\n weiHexToGweiDec,\n} from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport BN from 'bn.js';\n\nimport type {\n GasFeeEstimates,\n EthGasPriceEstimate,\n EstimatedGasFeeTimeBounds,\n unknownString,\n LegacyGasPriceEstimate,\n} from './GasFeeController';\n\nconst makeClientIdHeader = (clientId: string) => ({ 'X-Client-Id': clientId });\n\n/**\n * Convert a decimal GWEI value to a decimal string rounded to the nearest WEI.\n *\n * @param n - The input GWEI amount, as a decimal string or a number.\n * @returns The decimal string GWEI amount.\n */\nexport function normalizeGWEIDecimalNumbers(n: string | number) {\n const numberAsWEIHex = gweiDecToWEIBN(n).toString(16);\n const numberAsGWEI = weiHexToGweiDec(numberAsWEIHex);\n return numberAsGWEI;\n}\n\n/**\n * Fetch gas estimates from the given URL.\n *\n * @param url - The gas estimate URL.\n * @param infuraAPIKey - The Infura API key used for infura API requests.\n * @param clientId - The client ID used to identify to the API who is asking for estimates.\n * @returns The gas estimates.\n */\nexport async function fetchGasEstimates(\n url: string,\n infuraAPIKey: string,\n clientId?: string,\n): Promise<GasFeeEstimates> {\n const infuraAuthToken = buildInfuraAuthToken(infuraAPIKey);\n const estimates = await handleFetch(url, {\n headers: getHeaders(infuraAuthToken, clientId),\n });\n return {\n low: {\n ...estimates.low,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.low.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.low.suggestedMaxFeePerGas,\n ),\n },\n medium: {\n ...estimates.medium,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.medium.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.medium.suggestedMaxFeePerGas,\n ),\n },\n high: {\n ...estimates.high,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.high.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.high.suggestedMaxFeePerGas,\n ),\n },\n estimatedBaseFee: normalizeGWEIDecimalNumbers(estimates.estimatedBaseFee),\n historicalBaseFeeRange: estimates.historicalBaseFeeRange,\n baseFeeTrend: estimates.baseFeeTrend,\n latestPriorityFeeRange: estimates.latestPriorityFeeRange,\n historicalPriorityFeeRange: estimates.historicalPriorityFeeRange,\n priorityFeeTrend: estimates.priorityFeeTrend,\n networkCongestion: estimates.networkCongestion,\n };\n}\n\n/**\n * Hit the legacy MetaSwaps gasPrices estimate api and return the low, medium\n * high values from that API.\n *\n * @param url - The URL to fetch gas price estimates from.\n * @param infuraAPIKey - The Infura API key used for infura API requests.\n * @param clientId - The client ID used to identify to the API who is asking for estimates.\n * @returns The gas price estimates.\n */\nexport async function fetchLegacyGasPriceEstimates(\n url: string,\n infuraAPIKey: string,\n clientId?: string,\n): Promise<LegacyGasPriceEstimate> {\n const infuraAuthToken = buildInfuraAuthToken(infuraAPIKey);\n const result = await handleFetch(url, {\n referrer: url,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n headers: getHeaders(infuraAuthToken, clientId),\n });\n return {\n low: result.SafeGasPrice,\n medium: result.ProposeGasPrice,\n high: result.FastGasPrice,\n };\n}\n\n/**\n * Get a gas price estimate from the network using the `eth_gasPrice` method.\n *\n * @param ethQuery - The EthQuery instance to call the network with.\n * @returns A gas price estimate.\n */\nexport async function fetchEthGasPriceEstimate(\n ethQuery: EthQuery,\n): Promise<EthGasPriceEstimate> {\n const gasPrice = await query(ethQuery, 'gasPrice');\n return {\n gasPrice: weiHexToGweiDec(gasPrice).toString(),\n };\n}\n\n/**\n * Estimate the time it will take for a transaction to be confirmed.\n *\n * @param maxPriorityFeePerGas - The max priority fee per gas.\n * @param maxFeePerGas - The max fee per gas.\n * @param gasFeeEstimates - The gas fee estimates.\n * @returns The estimated lower and upper bounds for when this transaction will be confirmed.\n */\nexport function calculateTimeEstimate(\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n gasFeeEstimates: GasFeeEstimates,\n): EstimatedGasFeeTimeBounds {\n const { low, medium, high, estimatedBaseFee } = gasFeeEstimates;\n\n const maxPriorityFeePerGasInWEI = gweiDecToWEIBN(maxPriorityFeePerGas);\n const maxFeePerGasInWEI = gweiDecToWEIBN(maxFeePerGas);\n const estimatedBaseFeeInWEI = gweiDecToWEIBN(estimatedBaseFee);\n\n const effectiveMaxPriorityFee = BN.min(\n maxPriorityFeePerGasInWEI,\n maxFeePerGasInWEI.sub(estimatedBaseFeeInWEI),\n );\n\n const lowMaxPriorityFeeInWEI = gweiDecToWEIBN(\n low.suggestedMaxPriorityFeePerGas,\n );\n const mediumMaxPriorityFeeInWEI = gweiDecToWEIBN(\n medium.suggestedMaxPriorityFeePerGas,\n );\n const highMaxPriorityFeeInWEI = gweiDecToWEIBN(\n high.suggestedMaxPriorityFeePerGas,\n );\n\n let lowerTimeBound;\n let upperTimeBound;\n\n if (effectiveMaxPriorityFee.lt(lowMaxPriorityFeeInWEI)) {\n lowerTimeBound = null;\n upperTimeBound = 'unknown' as unknownString;\n } else if (\n effectiveMaxPriorityFee.gte(lowMaxPriorityFeeInWEI) &&\n effectiveMaxPriorityFee.lt(mediumMaxPriorityFeeInWEI)\n ) {\n lowerTimeBound = low.minWaitTimeEstimate;\n upperTimeBound = low.maxWaitTimeEstimate;\n } else if (\n effectiveMaxPriorityFee.gte(mediumMaxPriorityFeeInWEI) &&\n effectiveMaxPriorityFee.lt(highMaxPriorityFeeInWEI)\n ) {\n lowerTimeBound = medium.minWaitTimeEstimate;\n upperTimeBound = medium.maxWaitTimeEstimate;\n } else if (effectiveMaxPriorityFee.eq(highMaxPriorityFeeInWEI)) {\n lowerTimeBound = high.minWaitTimeEstimate;\n upperTimeBound = high.maxWaitTimeEstimate;\n } else {\n lowerTimeBound = 0;\n upperTimeBound = high.maxWaitTimeEstimate;\n }\n\n return {\n lowerTimeBound,\n upperTimeBound,\n };\n}\n\n/**\n * Build an infura auth token from the given API key and secret.\n *\n * @param infuraAPIKey - The Infura API key.\n * @returns The base64 encoded auth token.\n */\nfunction buildInfuraAuthToken(infuraAPIKey: string) {\n // We intentionally leave the password empty, as Infura does not require one\n return Buffer.from(`${infuraAPIKey}:`).toString('base64');\n}\n\n/**\n * Get the headers for a request to the gas fee API.\n *\n * @param infuraAuthToken - The Infura auth token to use for the request.\n * @param clientId - The client ID used to identify to the API who is asking for estimates.\n * @returns The headers for the request.\n */\nfunction getHeaders(infuraAuthToken: string, clientId?: string) {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Basic ${infuraAuthToken}`,\n // Only add the clientId header if clientId is a non-empty string\n ...(clientId?.trim() ? makeClientIdHeader(clientId) : {}),\n };\n}\n"],"mappings":"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","names":[]} +\ No newline at end of file +diff --git a/dist/chunk-Q2YPK5SL.js b/dist/chunk-Q2YPK5SL.js +deleted file mode 100644 +index 154d3eafb98cdb84cda1a2ea60f6be8a75f4e7a6..0000000000000000000000000000000000000000 +--- a/dist/chunk-Q2YPK5SL.js ++++ /dev/null +@@ -1,165 +0,0 @@ +-"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var __accessCheck = (obj, member, msg) => { +- if (!member.has(obj)) +- throw TypeError("Cannot " + msg); +-}; +-var __privateGet = (obj, member, getter) => { +- __accessCheck(obj, member, "read from private field"); +- return getter ? getter.call(obj) : member.get(obj); +-}; +-var __privateAdd = (obj, member, value) => { +- if (member.has(obj)) +- throw TypeError("Cannot add the same private member more than once"); +- member instanceof WeakSet ? member.add(obj) : member.set(obj, value); +-}; +-var __privateSet = (obj, member, value, setter) => { +- __accessCheck(obj, member, "write to private field"); +- setter ? setter.call(obj, value) : member.set(obj, value); +- return value; +-}; +-var __privateMethod = (obj, member, method) => { +- __accessCheck(obj, member, "access private method"); +- return method; +-}; +- +-// src/gas-util.ts +- +- +- +- +- +-var _controllerutils = require('@metamask/controller-utils'); +-var _bnjs = require('bn.js'); var _bnjs2 = _interopRequireDefault(_bnjs); +-var makeClientIdHeader = (clientId) => ({ "X-Client-Id": clientId }); +-function normalizeGWEIDecimalNumbers(n) { +- const numberAsWEIHex = _controllerutils.gweiDecToWEIBN.call(void 0, n).toString(16); +- const numberAsGWEI = _controllerutils.weiHexToGweiDec.call(void 0, numberAsWEIHex); +- return numberAsGWEI; +-} +-async function fetchGasEstimates(url, infuraAPIKey, clientId) { +- const infuraAuthToken = buildInfuraAuthToken(infuraAPIKey); +- const estimates = await _controllerutils.handleFetch.call(void 0, url, { +- headers: getHeaders(infuraAuthToken, clientId) +- }); +- return { +- low: { +- ...estimates.low, +- suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.low.suggestedMaxPriorityFeePerGas +- ), +- suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.low.suggestedMaxFeePerGas +- ) +- }, +- medium: { +- ...estimates.medium, +- suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.medium.suggestedMaxPriorityFeePerGas +- ), +- suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.medium.suggestedMaxFeePerGas +- ) +- }, +- high: { +- ...estimates.high, +- suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.high.suggestedMaxPriorityFeePerGas +- ), +- suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( +- estimates.high.suggestedMaxFeePerGas +- ) +- }, +- estimatedBaseFee: normalizeGWEIDecimalNumbers(estimates.estimatedBaseFee), +- historicalBaseFeeRange: estimates.historicalBaseFeeRange, +- baseFeeTrend: estimates.baseFeeTrend, +- latestPriorityFeeRange: estimates.latestPriorityFeeRange, +- historicalPriorityFeeRange: estimates.historicalPriorityFeeRange, +- priorityFeeTrend: estimates.priorityFeeTrend, +- networkCongestion: estimates.networkCongestion +- }; +-} +-async function fetchLegacyGasPriceEstimates(url, infuraAPIKey, clientId) { +- const infuraAuthToken = buildInfuraAuthToken(infuraAPIKey); +- const result = await _controllerutils.handleFetch.call(void 0, url, { +- referrer: url, +- referrerPolicy: "no-referrer-when-downgrade", +- method: "GET", +- mode: "cors", +- headers: getHeaders(infuraAuthToken, clientId) +- }); +- return { +- low: result.SafeGasPrice, +- medium: result.ProposeGasPrice, +- high: result.FastGasPrice +- }; +-} +-async function fetchEthGasPriceEstimate(ethQuery) { +- const gasPrice = await _controllerutils.query.call(void 0, ethQuery, "gasPrice"); +- return { +- gasPrice: _controllerutils.weiHexToGweiDec.call(void 0, gasPrice).toString() +- }; +-} +-function calculateTimeEstimate(maxPriorityFeePerGas, maxFeePerGas, gasFeeEstimates) { +- const { low, medium, high, estimatedBaseFee } = gasFeeEstimates; +- const maxPriorityFeePerGasInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, maxPriorityFeePerGas); +- const maxFeePerGasInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, maxFeePerGas); +- const estimatedBaseFeeInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, estimatedBaseFee); +- const effectiveMaxPriorityFee = _bnjs2.default.min( +- maxPriorityFeePerGasInWEI, +- maxFeePerGasInWEI.sub(estimatedBaseFeeInWEI) +- ); +- const lowMaxPriorityFeeInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, +- low.suggestedMaxPriorityFeePerGas +- ); +- const mediumMaxPriorityFeeInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, +- medium.suggestedMaxPriorityFeePerGas +- ); +- const highMaxPriorityFeeInWEI = _controllerutils.gweiDecToWEIBN.call(void 0, +- high.suggestedMaxPriorityFeePerGas +- ); +- let lowerTimeBound; +- let upperTimeBound; +- if (effectiveMaxPriorityFee.lt(lowMaxPriorityFeeInWEI)) { +- lowerTimeBound = null; +- upperTimeBound = "unknown"; +- } else if (effectiveMaxPriorityFee.gte(lowMaxPriorityFeeInWEI) && effectiveMaxPriorityFee.lt(mediumMaxPriorityFeeInWEI)) { +- lowerTimeBound = low.minWaitTimeEstimate; +- upperTimeBound = low.maxWaitTimeEstimate; +- } else if (effectiveMaxPriorityFee.gte(mediumMaxPriorityFeeInWEI) && effectiveMaxPriorityFee.lt(highMaxPriorityFeeInWEI)) { +- lowerTimeBound = medium.minWaitTimeEstimate; +- upperTimeBound = medium.maxWaitTimeEstimate; +- } else if (effectiveMaxPriorityFee.eq(highMaxPriorityFeeInWEI)) { +- lowerTimeBound = high.minWaitTimeEstimate; +- upperTimeBound = high.maxWaitTimeEstimate; +- } else { +- lowerTimeBound = 0; +- upperTimeBound = high.maxWaitTimeEstimate; +- } +- return { +- lowerTimeBound, +- upperTimeBound +- }; +-} +-function buildInfuraAuthToken(infuraAPIKey) { +- return Buffer.from(`${infuraAPIKey}:`).toString("base64"); +-} +-function getHeaders(infuraAuthToken, clientId) { +- return { +- "Content-Type": "application/json", +- Authorization: `Basic ${infuraAuthToken}`, +- // Only add the clientId header if clientId is a non-empty string +- ...clientId?.trim() ? makeClientIdHeader(clientId) : {} +- }; +-} +- +- +- +- +- +- +- +- +- +- +- +-exports.__privateGet = __privateGet; exports.__privateAdd = __privateAdd; exports.__privateSet = __privateSet; exports.__privateMethod = __privateMethod; exports.normalizeGWEIDecimalNumbers = normalizeGWEIDecimalNumbers; exports.fetchGasEstimates = fetchGasEstimates; exports.fetchLegacyGasPriceEstimates = fetchLegacyGasPriceEstimates; exports.fetchEthGasPriceEstimate = fetchEthGasPriceEstimate; exports.calculateTimeEstimate = calculateTimeEstimate; +-//# sourceMappingURL=chunk-Q2YPK5SL.js.map +\ No newline at end of file +diff --git a/dist/chunk-Q2YPK5SL.js.map b/dist/chunk-Q2YPK5SL.js.map +deleted file mode 100644 +index dc1a17f2cd5fdd749b46fbb546375ea3a1925081..0000000000000000000000000000000000000000 +--- a/dist/chunk-Q2YPK5SL.js.map ++++ /dev/null +@@ -1 +0,0 @@ +-{"version":3,"sources":["../src/gas-util.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n query,\n handleFetch,\n gweiDecToWEIBN,\n weiHexToGweiDec,\n} from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport BN from 'bn.js';\n\nimport type {\n GasFeeEstimates,\n EthGasPriceEstimate,\n EstimatedGasFeeTimeBounds,\n unknownString,\n LegacyGasPriceEstimate,\n} from './GasFeeController';\n\nconst makeClientIdHeader = (clientId: string) => ({ 'X-Client-Id': clientId });\n\n/**\n * Convert a decimal GWEI value to a decimal string rounded to the nearest WEI.\n *\n * @param n - The input GWEI amount, as a decimal string or a number.\n * @returns The decimal string GWEI amount.\n */\nexport function normalizeGWEIDecimalNumbers(n: string | number) {\n const numberAsWEIHex = gweiDecToWEIBN(n).toString(16);\n const numberAsGWEI = weiHexToGweiDec(numberAsWEIHex);\n return numberAsGWEI;\n}\n\n/**\n * Fetch gas estimates from the given URL.\n *\n * @param url - The gas estimate URL.\n * @param infuraAPIKey - The Infura API key used for infura API requests.\n * @param clientId - The client ID used to identify to the API who is asking for estimates.\n * @returns The gas estimates.\n */\nexport async function fetchGasEstimates(\n url: string,\n infuraAPIKey: string,\n clientId?: string,\n): Promise<GasFeeEstimates> {\n const infuraAuthToken = buildInfuraAuthToken(infuraAPIKey);\n const estimates = await handleFetch(url, {\n headers: getHeaders(infuraAuthToken, clientId),\n });\n return {\n low: {\n ...estimates.low,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.low.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.low.suggestedMaxFeePerGas,\n ),\n },\n medium: {\n ...estimates.medium,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.medium.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.medium.suggestedMaxFeePerGas,\n ),\n },\n high: {\n ...estimates.high,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.high.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.high.suggestedMaxFeePerGas,\n ),\n },\n estimatedBaseFee: normalizeGWEIDecimalNumbers(estimates.estimatedBaseFee),\n historicalBaseFeeRange: estimates.historicalBaseFeeRange,\n baseFeeTrend: estimates.baseFeeTrend,\n latestPriorityFeeRange: estimates.latestPriorityFeeRange,\n historicalPriorityFeeRange: estimates.historicalPriorityFeeRange,\n priorityFeeTrend: estimates.priorityFeeTrend,\n networkCongestion: estimates.networkCongestion,\n };\n}\n\n/**\n * Hit the legacy MetaSwaps gasPrices estimate api and return the low, medium\n * high values from that API.\n *\n * @param url - The URL to fetch gas price estimates from.\n * @param infuraAPIKey - The Infura API key used for infura API requests.\n * @param clientId - The client ID used to identify to the API who is asking for estimates.\n * @returns The gas price estimates.\n */\nexport async function fetchLegacyGasPriceEstimates(\n url: string,\n infuraAPIKey: string,\n clientId?: string,\n): Promise<LegacyGasPriceEstimate> {\n const infuraAuthToken = buildInfuraAuthToken(infuraAPIKey);\n const result = await handleFetch(url, {\n referrer: url,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n headers: getHeaders(infuraAuthToken, clientId),\n });\n return {\n low: result.SafeGasPrice,\n medium: result.ProposeGasPrice,\n high: result.FastGasPrice,\n };\n}\n\n/**\n * Get a gas price estimate from the network using the `eth_gasPrice` method.\n *\n * @param ethQuery - The EthQuery instance to call the network with.\n * @returns A gas price estimate.\n */\nexport async function fetchEthGasPriceEstimate(\n ethQuery: EthQuery,\n): Promise<EthGasPriceEstimate> {\n const gasPrice = await query(ethQuery, 'gasPrice');\n return {\n gasPrice: weiHexToGweiDec(gasPrice).toString(),\n };\n}\n\n/**\n * Estimate the time it will take for a transaction to be confirmed.\n *\n * @param maxPriorityFeePerGas - The max priority fee per gas.\n * @param maxFeePerGas - The max fee per gas.\n * @param gasFeeEstimates - The gas fee estimates.\n * @returns The estimated lower and upper bounds for when this transaction will be confirmed.\n */\nexport function calculateTimeEstimate(\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n gasFeeEstimates: GasFeeEstimates,\n): EstimatedGasFeeTimeBounds {\n const { low, medium, high, estimatedBaseFee } = gasFeeEstimates;\n\n const maxPriorityFeePerGasInWEI = gweiDecToWEIBN(maxPriorityFeePerGas);\n const maxFeePerGasInWEI = gweiDecToWEIBN(maxFeePerGas);\n const estimatedBaseFeeInWEI = gweiDecToWEIBN(estimatedBaseFee);\n\n const effectiveMaxPriorityFee = BN.min(\n maxPriorityFeePerGasInWEI,\n maxFeePerGasInWEI.sub(estimatedBaseFeeInWEI),\n );\n\n const lowMaxPriorityFeeInWEI = gweiDecToWEIBN(\n low.suggestedMaxPriorityFeePerGas,\n );\n const mediumMaxPriorityFeeInWEI = gweiDecToWEIBN(\n medium.suggestedMaxPriorityFeePerGas,\n );\n const highMaxPriorityFeeInWEI = gweiDecToWEIBN(\n high.suggestedMaxPriorityFeePerGas,\n );\n\n let lowerTimeBound;\n let upperTimeBound;\n\n if (effectiveMaxPriorityFee.lt(lowMaxPriorityFeeInWEI)) {\n lowerTimeBound = null;\n upperTimeBound = 'unknown' as unknownString;\n } else if (\n effectiveMaxPriorityFee.gte(lowMaxPriorityFeeInWEI) &&\n effectiveMaxPriorityFee.lt(mediumMaxPriorityFeeInWEI)\n ) {\n lowerTimeBound = low.minWaitTimeEstimate;\n upperTimeBound = low.maxWaitTimeEstimate;\n } else if (\n effectiveMaxPriorityFee.gte(mediumMaxPriorityFeeInWEI) &&\n effectiveMaxPriorityFee.lt(highMaxPriorityFeeInWEI)\n ) {\n lowerTimeBound = medium.minWaitTimeEstimate;\n upperTimeBound = medium.maxWaitTimeEstimate;\n } else if (effectiveMaxPriorityFee.eq(highMaxPriorityFeeInWEI)) {\n lowerTimeBound = high.minWaitTimeEstimate;\n upperTimeBound = high.maxWaitTimeEstimate;\n } else {\n lowerTimeBound = 0;\n upperTimeBound = high.maxWaitTimeEstimate;\n }\n\n return {\n lowerTimeBound,\n upperTimeBound,\n };\n}\n\n/**\n * Build an infura auth token from the given API key and secret.\n *\n * @param infuraAPIKey - The Infura API key.\n * @returns The base64 encoded auth token.\n */\nfunction buildInfuraAuthToken(infuraAPIKey: string) {\n // We intentionally leave the password empty, as Infura does not require one\n return Buffer.from(`${infuraAPIKey}:`).toString('base64');\n}\n\n/**\n * Get the headers for a request to the gas fee API.\n *\n * @param infuraAuthToken - The Infura auth token to use for the request.\n * @param clientId - The client ID used to identify to the API who is asking for estimates.\n * @returns The headers for the request.\n */\nfunction getHeaders(infuraAuthToken: string, clientId?: string) {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Basic ${infuraAuthToken}`,\n // Only add the clientId header if clientId is a non-empty string\n ...(clientId?.trim() ? makeClientIdHeader(clientId) : {}),\n };\n}\n"]} +\ No newline at end of file +diff --git a/dist/chunk-R3IOI7AK.mjs b/dist/chunk-R3IOI7AK.mjs +new file mode 100644 +index 0000000000000000000000000000000000000000..005f6ca08cfdc55aabcf1849e2a3b651ee7d9303 +--- /dev/null ++++ b/dist/chunk-R3IOI7AK.mjs +@@ -0,0 +1,156 @@ ++var __accessCheck = (obj, member, msg) => { ++ if (!member.has(obj)) ++ throw TypeError("Cannot " + msg); ++}; ++var __privateGet = (obj, member, getter) => { ++ __accessCheck(obj, member, "read from private field"); ++ return getter ? getter.call(obj) : member.get(obj); ++}; ++var __privateAdd = (obj, member, value) => { ++ if (member.has(obj)) ++ throw TypeError("Cannot add the same private member more than once"); ++ member instanceof WeakSet ? member.add(obj) : member.set(obj, value); ++}; ++var __privateSet = (obj, member, value, setter) => { ++ __accessCheck(obj, member, "write to private field"); ++ setter ? setter.call(obj, value) : member.set(obj, value); ++ return value; ++}; ++var __privateMethod = (obj, member, method) => { ++ __accessCheck(obj, member, "access private method"); ++ return method; ++}; ++ ++// src/gas-util.ts ++import { ++ query, ++ handleFetch, ++ gweiDecToWEIBN, ++ weiHexToGweiDec ++} from "@metamask/controller-utils"; ++import BN from "bn.js"; ++var makeClientIdHeader = (clientId) => ({ "X-Client-Id": clientId }); ++function normalizeGWEIDecimalNumbers(n) { ++ const numberAsWEIHex = gweiDecToWEIBN(n).toString(16); ++ const numberAsGWEI = weiHexToGweiDec(numberAsWEIHex); ++ return numberAsGWEI; ++} ++async function fetchGasEstimates(url, clientId) { ++ const estimates = await handleFetch( ++ url, ++ clientId ? { headers: makeClientIdHeader(clientId) } : void 0 ++ ); ++ return { ++ low: { ++ ...estimates.low, ++ suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.low.suggestedMaxPriorityFeePerGas ++ ), ++ suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.low.suggestedMaxFeePerGas ++ ) ++ }, ++ medium: { ++ ...estimates.medium, ++ suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.medium.suggestedMaxPriorityFeePerGas ++ ), ++ suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.medium.suggestedMaxFeePerGas ++ ) ++ }, ++ high: { ++ ...estimates.high, ++ suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.high.suggestedMaxPriorityFeePerGas ++ ), ++ suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers( ++ estimates.high.suggestedMaxFeePerGas ++ ) ++ }, ++ estimatedBaseFee: normalizeGWEIDecimalNumbers(estimates.estimatedBaseFee), ++ historicalBaseFeeRange: estimates.historicalBaseFeeRange, ++ baseFeeTrend: estimates.baseFeeTrend, ++ latestPriorityFeeRange: estimates.latestPriorityFeeRange, ++ historicalPriorityFeeRange: estimates.historicalPriorityFeeRange, ++ priorityFeeTrend: estimates.priorityFeeTrend, ++ networkCongestion: estimates.networkCongestion ++ }; ++} ++async function fetchLegacyGasPriceEstimates(url, clientId) { ++ const result = await handleFetch(url, { ++ referrer: url, ++ referrerPolicy: "no-referrer-when-downgrade", ++ method: "GET", ++ mode: "cors", ++ headers: { ++ "Content-Type": "application/json", ++ ...clientId && makeClientIdHeader(clientId) ++ } ++ }); ++ return { ++ low: result.SafeGasPrice, ++ medium: result.ProposeGasPrice, ++ high: result.FastGasPrice ++ }; ++} ++async function fetchEthGasPriceEstimate(ethQuery) { ++ const gasPrice = await query(ethQuery, "gasPrice"); ++ return { ++ gasPrice: weiHexToGweiDec(gasPrice).toString() ++ }; ++} ++function calculateTimeEstimate(maxPriorityFeePerGas, maxFeePerGas, gasFeeEstimates) { ++ const { low, medium, high, estimatedBaseFee } = gasFeeEstimates; ++ const maxPriorityFeePerGasInWEI = gweiDecToWEIBN(maxPriorityFeePerGas); ++ const maxFeePerGasInWEI = gweiDecToWEIBN(maxFeePerGas); ++ const estimatedBaseFeeInWEI = gweiDecToWEIBN(estimatedBaseFee); ++ const effectiveMaxPriorityFee = BN.min( ++ maxPriorityFeePerGasInWEI, ++ maxFeePerGasInWEI.sub(estimatedBaseFeeInWEI) ++ ); ++ const lowMaxPriorityFeeInWEI = gweiDecToWEIBN( ++ low.suggestedMaxPriorityFeePerGas ++ ); ++ const mediumMaxPriorityFeeInWEI = gweiDecToWEIBN( ++ medium.suggestedMaxPriorityFeePerGas ++ ); ++ const highMaxPriorityFeeInWEI = gweiDecToWEIBN( ++ high.suggestedMaxPriorityFeePerGas ++ ); ++ let lowerTimeBound; ++ let upperTimeBound; ++ if (effectiveMaxPriorityFee.lt(lowMaxPriorityFeeInWEI)) { ++ lowerTimeBound = null; ++ upperTimeBound = "unknown"; ++ } else if (effectiveMaxPriorityFee.gte(lowMaxPriorityFeeInWEI) && effectiveMaxPriorityFee.lt(mediumMaxPriorityFeeInWEI)) { ++ lowerTimeBound = low.minWaitTimeEstimate; ++ upperTimeBound = low.maxWaitTimeEstimate; ++ } else if (effectiveMaxPriorityFee.gte(mediumMaxPriorityFeeInWEI) && effectiveMaxPriorityFee.lt(highMaxPriorityFeeInWEI)) { ++ lowerTimeBound = medium.minWaitTimeEstimate; ++ upperTimeBound = medium.maxWaitTimeEstimate; ++ } else if (effectiveMaxPriorityFee.eq(highMaxPriorityFeeInWEI)) { ++ lowerTimeBound = high.minWaitTimeEstimate; ++ upperTimeBound = high.maxWaitTimeEstimate; ++ } else { ++ lowerTimeBound = 0; ++ upperTimeBound = high.maxWaitTimeEstimate; ++ } ++ return { ++ lowerTimeBound, ++ upperTimeBound ++ }; ++} ++ ++export { ++ __privateGet, ++ __privateAdd, ++ __privateSet, ++ __privateMethod, ++ normalizeGWEIDecimalNumbers, ++ fetchGasEstimates, ++ fetchLegacyGasPriceEstimates, ++ fetchEthGasPriceEstimate, ++ calculateTimeEstimate ++}; ++//# sourceMappingURL=chunk-R3IOI7AK.mjs.map +\ No newline at end of file +diff --git a/dist/chunk-R3IOI7AK.mjs.map b/dist/chunk-R3IOI7AK.mjs.map +new file mode 100644 +index 0000000000000000000000000000000000000000..151a4aa1146e106a273c2e7cbfe8e97c7e6ae6b6 +--- /dev/null ++++ b/dist/chunk-R3IOI7AK.mjs.map +@@ -0,0 +1 @@ ++{"version":3,"sources":["../src/gas-util.ts"],"sourcesContent":["import {\n query,\n handleFetch,\n gweiDecToWEIBN,\n weiHexToGweiDec,\n} from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport BN from 'bn.js';\n\nimport type {\n GasFeeEstimates,\n EthGasPriceEstimate,\n EstimatedGasFeeTimeBounds,\n unknownString,\n LegacyGasPriceEstimate,\n} from './GasFeeController';\n\nconst makeClientIdHeader = (clientId: string) => ({ 'X-Client-Id': clientId });\n\n/**\n * Convert a decimal GWEI value to a decimal string rounded to the nearest WEI.\n *\n * @param n - The input GWEI amount, as a decimal string or a number.\n * @returns The decimal string GWEI amount.\n */\nexport function normalizeGWEIDecimalNumbers(n: string | number) {\n const numberAsWEIHex = gweiDecToWEIBN(n).toString(16);\n const numberAsGWEI = weiHexToGweiDec(numberAsWEIHex);\n return numberAsGWEI;\n}\n\n/**\n * Fetch gas estimates from the given URL.\n *\n * @param url - The gas estimate URL.\n * @param clientId - The client ID used to identify to the API who is asking for estimates.\n * @returns The gas estimates.\n */\nexport async function fetchGasEstimates(\n url: string,\n clientId?: string,\n): Promise<GasFeeEstimates> {\n const estimates = await handleFetch(\n url,\n clientId ? { headers: makeClientIdHeader(clientId) } : undefined,\n );\n return {\n low: {\n ...estimates.low,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.low.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.low.suggestedMaxFeePerGas,\n ),\n },\n medium: {\n ...estimates.medium,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.medium.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.medium.suggestedMaxFeePerGas,\n ),\n },\n high: {\n ...estimates.high,\n suggestedMaxPriorityFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.high.suggestedMaxPriorityFeePerGas,\n ),\n suggestedMaxFeePerGas: normalizeGWEIDecimalNumbers(\n estimates.high.suggestedMaxFeePerGas,\n ),\n },\n estimatedBaseFee: normalizeGWEIDecimalNumbers(estimates.estimatedBaseFee),\n historicalBaseFeeRange: estimates.historicalBaseFeeRange,\n baseFeeTrend: estimates.baseFeeTrend,\n latestPriorityFeeRange: estimates.latestPriorityFeeRange,\n historicalPriorityFeeRange: estimates.historicalPriorityFeeRange,\n priorityFeeTrend: estimates.priorityFeeTrend,\n networkCongestion: estimates.networkCongestion,\n };\n}\n\n/**\n * Hit the legacy MetaSwaps gasPrices estimate api and return the low, medium\n * high values from that API.\n *\n * @param url - The URL to fetch gas price estimates from.\n * @param clientId - The client ID used to identify to the API who is asking for estimates.\n * @returns The gas price estimates.\n */\nexport async function fetchLegacyGasPriceEstimates(\n url: string,\n clientId?: string,\n): Promise<LegacyGasPriceEstimate> {\n const result = await handleFetch(url, {\n referrer: url,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n headers: {\n 'Content-Type': 'application/json',\n ...(clientId && makeClientIdHeader(clientId)),\n },\n });\n return {\n low: result.SafeGasPrice,\n medium: result.ProposeGasPrice,\n high: result.FastGasPrice,\n };\n}\n\n/**\n * Get a gas price estimate from the network using the `eth_gasPrice` method.\n *\n * @param ethQuery - The EthQuery instance to call the network with.\n * @returns A gas price estimate.\n */\nexport async function fetchEthGasPriceEstimate(\n ethQuery: EthQuery,\n): Promise<EthGasPriceEstimate> {\n const gasPrice = await query(ethQuery, 'gasPrice');\n return {\n gasPrice: weiHexToGweiDec(gasPrice).toString(),\n };\n}\n\n/**\n * Estimate the time it will take for a transaction to be confirmed.\n *\n * @param maxPriorityFeePerGas - The max priority fee per gas.\n * @param maxFeePerGas - The max fee per gas.\n * @param gasFeeEstimates - The gas fee estimates.\n * @returns The estimated lower and upper bounds for when this transaction will be confirmed.\n */\nexport function calculateTimeEstimate(\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n gasFeeEstimates: GasFeeEstimates,\n): EstimatedGasFeeTimeBounds {\n const { low, medium, high, estimatedBaseFee } = gasFeeEstimates;\n\n const maxPriorityFeePerGasInWEI = gweiDecToWEIBN(maxPriorityFeePerGas);\n const maxFeePerGasInWEI = gweiDecToWEIBN(maxFeePerGas);\n const estimatedBaseFeeInWEI = gweiDecToWEIBN(estimatedBaseFee);\n\n const effectiveMaxPriorityFee = BN.min(\n maxPriorityFeePerGasInWEI,\n maxFeePerGasInWEI.sub(estimatedBaseFeeInWEI),\n );\n\n const lowMaxPriorityFeeInWEI = gweiDecToWEIBN(\n low.suggestedMaxPriorityFeePerGas,\n );\n const mediumMaxPriorityFeeInWEI = gweiDecToWEIBN(\n medium.suggestedMaxPriorityFeePerGas,\n );\n const highMaxPriorityFeeInWEI = gweiDecToWEIBN(\n high.suggestedMaxPriorityFeePerGas,\n );\n\n let lowerTimeBound;\n let upperTimeBound;\n\n if (effectiveMaxPriorityFee.lt(lowMaxPriorityFeeInWEI)) {\n lowerTimeBound = null;\n upperTimeBound = 'unknown' as unknownString;\n } else if (\n effectiveMaxPriorityFee.gte(lowMaxPriorityFeeInWEI) &&\n effectiveMaxPriorityFee.lt(mediumMaxPriorityFeeInWEI)\n ) {\n lowerTimeBound = low.minWaitTimeEstimate;\n upperTimeBound = low.maxWaitTimeEstimate;\n } else if (\n effectiveMaxPriorityFee.gte(mediumMaxPriorityFeeInWEI) &&\n effectiveMaxPriorityFee.lt(highMaxPriorityFeeInWEI)\n ) {\n lowerTimeBound = medium.minWaitTimeEstimate;\n upperTimeBound = medium.maxWaitTimeEstimate;\n } else if (effectiveMaxPriorityFee.eq(highMaxPriorityFeeInWEI)) {\n lowerTimeBound = high.minWaitTimeEstimate;\n upperTimeBound = high.maxWaitTimeEstimate;\n } else {\n lowerTimeBound = 0;\n upperTimeBound = high.maxWaitTimeEstimate;\n }\n\n return {\n lowerTimeBound,\n upperTimeBound,\n };\n}\n"],"mappings":"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","names":[]} +\ No newline at end of file +diff --git a/dist/chunk-X74LQX2Y.js b/dist/chunk-X74LQX2Y.js +new file mode 100644 +index 0000000000000000000000000000000000000000..11d4e4b36c51872b5b529eb4e7d4f7eea91e87c7 +--- /dev/null ++++ b/dist/chunk-X74LQX2Y.js +@@ -0,0 +1,390 @@ ++"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } ++ ++ ++ ++ ++ ++ ++ ++ ++var _chunk2MFVV2BXjs = require('./chunk-2MFVV2BX.js'); ++ ++// src/GasFeeController.ts ++ ++ ++ ++ ++var _controllerutils = require('@metamask/controller-utils'); ++var _ethquery = require('@metamask/eth-query'); var _ethquery2 = _interopRequireDefault(_ethquery); ++var _pollingcontroller = require('@metamask/polling-controller'); ++var _uuid = require('uuid'); ++var LEGACY_GAS_PRICES_API_URL = `https://api.metaswap.codefi.network/gasPrices`; ++var GAS_ESTIMATE_TYPES = { ++ FEE_MARKET: "fee-market", ++ LEGACY: "legacy", ++ ETH_GASPRICE: "eth_gasPrice", ++ NONE: "none" ++}; ++var metadata = { ++ gasFeeEstimatesByChainId: { ++ persist: true, ++ anonymous: false ++ }, ++ gasFeeEstimates: { persist: true, anonymous: false }, ++ estimatedGasFeeTimeBounds: { persist: true, anonymous: false }, ++ gasEstimateType: { persist: true, anonymous: false }, ++ nonRPCGasFeeApisDisabled: { persist: true, anonymous: false } ++}; ++var name = "GasFeeController"; ++var defaultState = { ++ gasFeeEstimatesByChainId: {}, ++ gasFeeEstimates: {}, ++ estimatedGasFeeTimeBounds: {}, ++ gasEstimateType: GAS_ESTIMATE_TYPES.NONE, ++ nonRPCGasFeeApisDisabled: false ++}; ++var _getProvider, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn; ++var GasFeeController = class extends _pollingcontroller.StaticIntervalPollingController { ++ /** ++ * Creates a GasFeeController instance. ++ * ++ * @param options - The controller options. ++ * @param options.interval - The time in milliseconds to wait between polls. ++ * @param options.messenger - The controller messenger. ++ * @param options.state - The initial state. ++ * @param options.getCurrentNetworkEIP1559Compatibility - Determines whether or not the current ++ * network is EIP-1559 compatible. ++ * @param options.getCurrentNetworkLegacyGasAPICompatibility - Determines whether or not the ++ * current network is compatible with the legacy gas price API. ++ * @param options.getCurrentAccountEIP1559Compatibility - Determines whether or not the current ++ * account is EIP-1559 compatible. ++ * @param options.getChainId - Returns the current chain ID. ++ * @param options.getProvider - Returns a network provider for the current network. ++ * @param options.onNetworkDidChange - A function for registering an event handler for the ++ * network state change event. ++ * @param options.legacyAPIEndpoint - The legacy gas price API URL. This option is primarily for ++ * testing purposes. ++ * @param options.EIP1559APIEndpoint - The EIP-1559 gas price API URL. ++ * @param options.clientId - The client ID used to identify to the gas estimation API who is ++ * asking for estimates. ++ */ ++ constructor({ ++ interval = 15e3, ++ messenger, ++ state, ++ getCurrentNetworkEIP1559Compatibility, ++ getCurrentAccountEIP1559Compatibility, ++ getChainId, ++ getCurrentNetworkLegacyGasAPICompatibility, ++ getProvider, ++ onNetworkDidChange, ++ legacyAPIEndpoint = LEGACY_GAS_PRICES_API_URL, ++ EIP1559APIEndpoint, ++ clientId ++ }) { ++ super({ ++ name, ++ metadata, ++ messenger, ++ state: { ...defaultState, ...state } ++ }); ++ _chunk2MFVV2BXjs.__privateAdd.call(void 0, this, _onNetworkControllerDidChange); ++ _chunk2MFVV2BXjs.__privateAdd.call(void 0, this, _getProvider, void 0); ++ this.intervalDelay = interval; ++ this.setIntervalLength(interval); ++ this.pollTokens = /* @__PURE__ */ new Set(); ++ this.getCurrentNetworkEIP1559Compatibility = getCurrentNetworkEIP1559Compatibility; ++ this.getCurrentNetworkLegacyGasAPICompatibility = getCurrentNetworkLegacyGasAPICompatibility; ++ this.getCurrentAccountEIP1559Compatibility = getCurrentAccountEIP1559Compatibility; ++ _chunk2MFVV2BXjs.__privateSet.call(void 0, this, _getProvider, getProvider); ++ this.EIP1559APIEndpoint = EIP1559APIEndpoint; ++ this.legacyAPIEndpoint = legacyAPIEndpoint; ++ this.clientId = clientId; ++ this.ethQuery = new (0, _ethquery2.default)(_chunk2MFVV2BXjs.__privateGet.call(void 0, this, _getProvider).call(this)); ++ if (onNetworkDidChange && getChainId) { ++ this.currentChainId = getChainId(); ++ onNetworkDidChange(async (networkControllerState) => { ++ await _chunk2MFVV2BXjs.__privateMethod.call(void 0, this, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn).call(this, networkControllerState); ++ }); ++ } else { ++ this.currentChainId = this.messagingSystem.call( ++ "NetworkController:getState" ++ ).providerConfig.chainId; ++ this.messagingSystem.subscribe( ++ "NetworkController:networkDidChange", ++ async (networkControllerState) => { ++ await _chunk2MFVV2BXjs.__privateMethod.call(void 0, this, _onNetworkControllerDidChange, onNetworkControllerDidChange_fn).call(this, networkControllerState); ++ } ++ ); ++ } ++ } ++ async resetPolling() { ++ if (this.pollTokens.size !== 0) { ++ const tokens = Array.from(this.pollTokens); ++ this.stopPolling(); ++ await this.getGasFeeEstimatesAndStartPolling(tokens[0]); ++ tokens.slice(1).forEach((token) => { ++ this.pollTokens.add(token); ++ }); ++ } ++ } ++ async fetchGasFeeEstimates(options) { ++ return await this._fetchGasFeeEstimateData(options); ++ } ++ async getGasFeeEstimatesAndStartPolling(pollToken) { ++ const _pollToken = pollToken || _uuid.v1.call(void 0, ); ++ this.pollTokens.add(_pollToken); ++ if (this.pollTokens.size === 1) { ++ await this._fetchGasFeeEstimateData(); ++ this._poll(); ++ } ++ return _pollToken; ++ } ++ /** ++ * Gets and sets gasFeeEstimates in state. ++ * ++ * @param options - The gas fee estimate options. ++ * @param options.shouldUpdateState - Determines whether the state should be updated with the ++ * updated gas estimates. ++ * @returns The gas fee estimates. ++ */ ++ async _fetchGasFeeEstimateData(options = {}) { ++ const { shouldUpdateState = true, networkClientId } = options; ++ let ethQuery, isEIP1559Compatible, isLegacyGasAPICompatible, decimalChainId; ++ if (networkClientId !== void 0) { ++ const networkClient = this.messagingSystem.call( ++ "NetworkController:getNetworkClientById", ++ networkClientId ++ ); ++ isLegacyGasAPICompatible = networkClient.configuration.chainId === "0x38"; ++ decimalChainId = _controllerutils.convertHexToDecimal.call(void 0, networkClient.configuration.chainId); ++ try { ++ const result = await this.messagingSystem.call( ++ "NetworkController:getEIP1559Compatibility", ++ networkClientId ++ ); ++ isEIP1559Compatible = result || false; ++ } catch { ++ isEIP1559Compatible = false; ++ } ++ ethQuery = new (0, _ethquery2.default)(networkClient.provider); ++ } ++ ethQuery ?? (ethQuery = this.ethQuery); ++ isLegacyGasAPICompatible ?? (isLegacyGasAPICompatible = this.getCurrentNetworkLegacyGasAPICompatibility()); ++ decimalChainId ?? (decimalChainId = _controllerutils.convertHexToDecimal.call(void 0, this.currentChainId)); ++ try { ++ isEIP1559Compatible ?? (isEIP1559Compatible = await this.getEIP1559Compatibility()); ++ } catch (e) { ++ console.error(e); ++ isEIP1559Compatible ?? (isEIP1559Compatible = false); ++ } ++ const gasFeeCalculations = await determineGasFeeCalculations({ ++ isEIP1559Compatible, ++ isLegacyGasAPICompatible, ++ fetchGasEstimates: _chunk2MFVV2BXjs.fetchGasEstimates, ++ fetchGasEstimatesUrl: this.EIP1559APIEndpoint.replace( ++ "<chain_id>", ++ `${decimalChainId}` ++ ), ++ fetchLegacyGasPriceEstimates: _chunk2MFVV2BXjs.fetchLegacyGasPriceEstimates, ++ fetchLegacyGasPriceEstimatesUrl: this.legacyAPIEndpoint.replace( ++ "<chain_id>", ++ `${decimalChainId}` ++ ), ++ fetchEthGasPriceEstimate: _chunk2MFVV2BXjs.fetchEthGasPriceEstimate, ++ calculateTimeEstimate: _chunk2MFVV2BXjs.calculateTimeEstimate, ++ clientId: this.clientId, ++ ethQuery, ++ nonRPCGasFeeApisDisabled: this.state.nonRPCGasFeeApisDisabled ++ }); ++ if (shouldUpdateState) { ++ const chainId = _controllerutils.toHex.call(void 0, decimalChainId); ++ this.update((state) => { ++ if (this.currentChainId === chainId) { ++ state.gasFeeEstimates = gasFeeCalculations.gasFeeEstimates; ++ state.estimatedGasFeeTimeBounds = gasFeeCalculations.estimatedGasFeeTimeBounds; ++ state.gasEstimateType = gasFeeCalculations.gasEstimateType; ++ } ++ state.gasFeeEstimatesByChainId ?? (state.gasFeeEstimatesByChainId = {}); ++ state.gasFeeEstimatesByChainId[chainId] = { ++ gasFeeEstimates: gasFeeCalculations.gasFeeEstimates, ++ estimatedGasFeeTimeBounds: gasFeeCalculations.estimatedGasFeeTimeBounds, ++ gasEstimateType: gasFeeCalculations.gasEstimateType ++ }; ++ }); ++ } ++ return gasFeeCalculations; ++ } ++ /** ++ * Remove the poll token, and stop polling if the set of poll tokens is empty. ++ * ++ * @param pollToken - The poll token to disconnect. ++ */ ++ disconnectPoller(pollToken) { ++ this.pollTokens.delete(pollToken); ++ if (this.pollTokens.size === 0) { ++ this.stopPolling(); ++ } ++ } ++ stopPolling() { ++ if (this.intervalId) { ++ clearInterval(this.intervalId); ++ } ++ this.pollTokens.clear(); ++ this.resetState(); ++ } ++ /** ++ * Prepare to discard this controller. ++ * ++ * This stops any active polling. ++ */ ++ destroy() { ++ super.destroy(); ++ this.stopPolling(); ++ } ++ _poll() { ++ if (this.intervalId) { ++ clearInterval(this.intervalId); ++ } ++ this.intervalId = setInterval(async () => { ++ await _controllerutils.safelyExecute.call(void 0, () => this._fetchGasFeeEstimateData()); ++ }, this.intervalDelay); ++ } ++ /** ++ * Fetching token list from the Token Service API. ++ * ++ * @private ++ * @param networkClientId - The ID of the network client triggering the fetch. ++ * @returns A promise that resolves when this operation completes. ++ */ ++ async _executePoll(networkClientId) { ++ await this._fetchGasFeeEstimateData({ networkClientId }); ++ } ++ resetState() { ++ this.update(() => { ++ return defaultState; ++ }); ++ } ++ async getEIP1559Compatibility() { ++ const currentNetworkIsEIP1559Compatible = await this.getCurrentNetworkEIP1559Compatibility(); ++ const currentAccountIsEIP1559Compatible = this.getCurrentAccountEIP1559Compatibility?.() ?? true; ++ return currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible; ++ } ++ getTimeEstimate(maxPriorityFeePerGas, maxFeePerGas) { ++ if (!this.state.gasFeeEstimates || this.state.gasEstimateType !== GAS_ESTIMATE_TYPES.FEE_MARKET) { ++ return {}; ++ } ++ return _chunk2MFVV2BXjs.calculateTimeEstimate.call(void 0, ++ maxPriorityFeePerGas, ++ maxFeePerGas, ++ this.state.gasFeeEstimates ++ ); ++ } ++ enableNonRPCGasFeeApis() { ++ this.update((state) => { ++ state.nonRPCGasFeeApisDisabled = false; ++ }); ++ } ++ disableNonRPCGasFeeApis() { ++ this.update((state) => { ++ state.nonRPCGasFeeApisDisabled = true; ++ }); ++ } ++}; ++_getProvider = new WeakMap(); ++_onNetworkControllerDidChange = new WeakSet(); ++onNetworkControllerDidChange_fn = async function(networkControllerState) { ++ const newChainId = networkControllerState.providerConfig.chainId; ++ if (newChainId !== this.currentChainId) { ++ this.ethQuery = new (0, _ethquery2.default)(_chunk2MFVV2BXjs.__privateGet.call(void 0, this, _getProvider).call(this)); ++ await this.resetPolling(); ++ this.currentChainId = newChainId; ++ } ++}; ++var GasFeeController_default = GasFeeController; ++ ++// src/determineGasFeeCalculations.ts ++async function determineGasFeeCalculations(args) { ++ try { ++ return await getEstimatesUsingFallbacks(args); ++ } catch (error) { ++ if (error instanceof Error) { ++ throw new Error( ++ `Gas fee/price estimation failed. Message: ${error.message}` ++ ); ++ } ++ throw error; ++ } ++} ++async function getEstimatesUsingFallbacks(request) { ++ const { ++ isEIP1559Compatible, ++ isLegacyGasAPICompatible, ++ nonRPCGasFeeApisDisabled ++ } = request; ++ try { ++ if (isEIP1559Compatible && !nonRPCGasFeeApisDisabled) { ++ return await getEstimatesUsingFeeMarketEndpoint(request); ++ } ++ if (isLegacyGasAPICompatible && !nonRPCGasFeeApisDisabled) { ++ return await getEstimatesUsingLegacyEndpoint(request); ++ } ++ throw new Error("Main gas fee/price estimation failed. Use fallback"); ++ } catch { ++ return await getEstimatesUsingProvider(request); ++ } ++} ++async function getEstimatesUsingFeeMarketEndpoint(request) { ++ const { ++ fetchGasEstimates: fetchGasEstimates2, ++ fetchGasEstimatesUrl, ++ clientId, ++ calculateTimeEstimate: calculateTimeEstimate2 ++ } = request; ++ const estimates = await fetchGasEstimates2(fetchGasEstimatesUrl, clientId); ++ const { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas } = estimates.medium; ++ const estimatedGasFeeTimeBounds = calculateTimeEstimate2( ++ suggestedMaxPriorityFeePerGas, ++ suggestedMaxFeePerGas, ++ estimates ++ ); ++ return { ++ gasFeeEstimates: estimates, ++ estimatedGasFeeTimeBounds, ++ gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET ++ }; ++} ++async function getEstimatesUsingLegacyEndpoint(request) { ++ const { ++ fetchLegacyGasPriceEstimates: fetchLegacyGasPriceEstimates2, ++ fetchLegacyGasPriceEstimatesUrl, ++ clientId ++ } = request; ++ const estimates = await fetchLegacyGasPriceEstimates2( ++ fetchLegacyGasPriceEstimatesUrl, ++ clientId ++ ); ++ return { ++ gasFeeEstimates: estimates, ++ estimatedGasFeeTimeBounds: {}, ++ gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY ++ }; ++} ++async function getEstimatesUsingProvider(request) { ++ const { ethQuery, fetchEthGasPriceEstimate: fetchEthGasPriceEstimate2 } = request; ++ const estimates = await fetchEthGasPriceEstimate2(ethQuery); ++ return { ++ gasFeeEstimates: estimates, ++ estimatedGasFeeTimeBounds: {}, ++ gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE ++ }; ++} ++ ++ ++ ++ ++ ++ ++ ++exports.determineGasFeeCalculations = determineGasFeeCalculations; exports.LEGACY_GAS_PRICES_API_URL = LEGACY_GAS_PRICES_API_URL; exports.GAS_ESTIMATE_TYPES = GAS_ESTIMATE_TYPES; exports.GasFeeController = GasFeeController; exports.GasFeeController_default = GasFeeController_default; ++//# sourceMappingURL=chunk-X74LQX2Y.js.map +\ No newline at end of file +diff --git a/dist/chunk-X74LQX2Y.js.map b/dist/chunk-X74LQX2Y.js.map +new file mode 100644 +index 0000000000000000000000000000000000000000..c330267c1f74907a70d669611fb5d8eff71305aa +--- /dev/null ++++ b/dist/chunk-X74LQX2Y.js.map +@@ -0,0 +1 @@ ++{"version":3,"sources":["../src/GasFeeController.ts","../src/determineGasFeeCalculations.ts"],"names":["fetchGasEstimates","calculateTimeEstimate","fetchLegacyGasPriceEstimates","fetchEthGasPriceEstimate"],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport {\n convertHexToDecimal,\n safelyExecute,\n toHex,\n} from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkControllerGetEIP1559CompatibilityAction,\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n NetworkControllerNetworkDidChangeEvent,\n NetworkState,\n ProviderProxy,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { v1 as random } from 'uuid';\n\nimport determineGasFeeCalculations from './determineGasFeeCalculations';\nimport {\n fetchGasEstimates,\n fetchLegacyGasPriceEstimates,\n fetchEthGasPriceEstimate,\n calculateTimeEstimate,\n} from './gas-util';\n\nexport const LEGACY_GAS_PRICES_API_URL = `https://api.metaswap.codefi.network/gasPrices`;\n\nexport type unknownString = 'unknown';\n\n// Fee Market describes the way gas is set after the london hardfork, and was\n// defined by EIP-1559.\nexport type FeeMarketEstimateType = 'fee-market';\n// Legacy describes gasPrice estimates from before london hardfork, when the\n// user is connected to mainnet and are presented with fast/average/slow\n// estimate levels to choose from.\nexport type LegacyEstimateType = 'legacy';\n// EthGasPrice describes a gasPrice estimate received from eth_gasPrice. Post\n// london this value should only be used for legacy type transactions when on\n// networks that support EIP-1559. This type of estimate is the most accurate\n// to display on custom networks that don't support EIP-1559.\nexport type EthGasPriceEstimateType = 'eth_gasPrice';\n// NoEstimate describes the state of the controller before receiving its first\n// estimate.\nexport type NoEstimateType = 'none';\n\n/**\n * Indicates which type of gasEstimate the controller is currently returning.\n * This is useful as a way of asserting that the shape of gasEstimates matches\n * expectations. NONE is a special case indicating that no previous gasEstimate\n * has been fetched.\n */\nexport const GAS_ESTIMATE_TYPES = {\n FEE_MARKET: 'fee-market' as FeeMarketEstimateType,\n LEGACY: 'legacy' as LegacyEstimateType,\n ETH_GASPRICE: 'eth_gasPrice' as EthGasPriceEstimateType,\n NONE: 'none' as NoEstimateType,\n};\n\nexport type GasEstimateType =\n | FeeMarketEstimateType\n | EthGasPriceEstimateType\n | LegacyEstimateType\n | NoEstimateType;\n\nexport type EstimatedGasFeeTimeBounds = {\n lowerTimeBound: number | null;\n upperTimeBound: number | unknownString;\n};\n\n/**\n * @type EthGasPriceEstimate\n *\n * A single gas price estimate for networks and accounts that don't support EIP-1559\n * This estimate comes from eth_gasPrice but is converted to dec gwei to match other\n * return values\n * @property gasPrice - A GWEI dec string\n */\n\nexport type EthGasPriceEstimate = {\n gasPrice: string;\n};\n\n/**\n * @type LegacyGasPriceEstimate\n *\n * A set of gas price estimates for networks and accounts that don't support EIP-1559\n * These estimates include low, medium and high all as strings representing gwei in\n * decimal format.\n * @property high - gasPrice, in decimal gwei string format, suggested for fast inclusion\n * @property medium - gasPrice, in decimal gwei string format, suggested for avg inclusion\n * @property low - gasPrice, in decimal gwei string format, suggested for slow inclusion\n */\nexport type LegacyGasPriceEstimate = {\n high: string;\n medium: string;\n low: string;\n};\n\n/**\n * @type Eip1559GasFee\n *\n * Data necessary to provide an estimate of a gas fee with a specific tip\n * @property minWaitTimeEstimate - The fastest the transaction will take, in milliseconds\n * @property maxWaitTimeEstimate - The slowest the transaction will take, in milliseconds\n * @property suggestedMaxPriorityFeePerGas - A suggested \"tip\", a GWEI hex number\n * @property suggestedMaxFeePerGas - A suggested max fee, the most a user will pay. a GWEI hex number\n */\nexport type Eip1559GasFee = {\n minWaitTimeEstimate: number; // a time duration in milliseconds\n maxWaitTimeEstimate: number; // a time duration in milliseconds\n suggestedMaxPriorityFeePerGas: string; // a GWEI decimal number\n suggestedMaxFeePerGas: string; // a GWEI decimal number\n};\n\n/**\n * @type GasFeeEstimates\n *\n * Data necessary to provide multiple GasFee estimates, and supporting information, to the user\n * @property low - A GasFee for a minimum necessary combination of tip and maxFee\n * @property medium - A GasFee for a recommended combination of tip and maxFee\n * @property high - A GasFee for a high combination of tip and maxFee\n * @property estimatedBaseFee - An estimate of what the base fee will be for the pending/next block. A GWEI dec number\n * @property networkCongestion - A normalized number that can be used to gauge the congestion\n * level of the network, with 0 meaning not congested and 1 meaning extremely congested\n */\nexport type GasFeeEstimates = SourcedGasFeeEstimates | FallbackGasFeeEstimates;\n\ntype SourcedGasFeeEstimates = {\n low: Eip1559GasFee;\n medium: Eip1559GasFee;\n high: Eip1559GasFee;\n estimatedBaseFee: string;\n historicalBaseFeeRange: [string, string];\n baseFeeTrend: 'up' | 'down' | 'level';\n latestPriorityFeeRange: [string, string];\n historicalPriorityFeeRange: [string, string];\n priorityFeeTrend: 'up' | 'down' | 'level';\n networkCongestion: number;\n};\n\ntype FallbackGasFeeEstimates = {\n low: Eip1559GasFee;\n medium: Eip1559GasFee;\n high: Eip1559GasFee;\n estimatedBaseFee: string;\n historicalBaseFeeRange: null;\n baseFeeTrend: null;\n latestPriorityFeeRange: null;\n historicalPriorityFeeRange: null;\n priorityFeeTrend: null;\n networkCongestion: null;\n};\n\nconst metadata = {\n gasFeeEstimatesByChainId: {\n persist: true,\n anonymous: false,\n },\n gasFeeEstimates: { persist: true, anonymous: false },\n estimatedGasFeeTimeBounds: { persist: true, anonymous: false },\n gasEstimateType: { persist: true, anonymous: false },\n nonRPCGasFeeApisDisabled: { persist: true, anonymous: false },\n};\n\nexport type GasFeeStateEthGasPrice = {\n gasFeeEstimates: EthGasPriceEstimate;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: EthGasPriceEstimateType;\n};\n\nexport type GasFeeStateFeeMarket = {\n gasFeeEstimates: GasFeeEstimates;\n estimatedGasFeeTimeBounds: EstimatedGasFeeTimeBounds | Record<string, never>;\n gasEstimateType: FeeMarketEstimateType;\n};\n\nexport type GasFeeStateLegacy = {\n gasFeeEstimates: LegacyGasPriceEstimate;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: LegacyEstimateType;\n};\n\nexport type GasFeeStateNoEstimates = {\n gasFeeEstimates: Record<string, never>;\n estimatedGasFeeTimeBounds: Record<string, never>;\n gasEstimateType: NoEstimateType;\n};\n\nexport type FetchGasFeeEstimateOptions = {\n shouldUpdateState?: boolean;\n networkClientId?: NetworkClientId;\n};\n\n/**\n * @type GasFeeState\n *\n * Gas Fee controller state\n * @property gasFeeEstimates - Gas fee estimate data based on new EIP-1559 properties\n * @property estimatedGasFeeTimeBounds - Estimates representing the minimum and maximum\n */\nexport type SingleChainGasFeeState =\n | GasFeeStateEthGasPrice\n | GasFeeStateFeeMarket\n | GasFeeStateLegacy\n | GasFeeStateNoEstimates;\n\nexport type GasFeeEstimatesByChainId = {\n gasFeeEstimatesByChainId?: Record<string, SingleChainGasFeeState>;\n};\n\nexport type GasFeeState = GasFeeEstimatesByChainId &\n SingleChainGasFeeState & {\n nonRPCGasFeeApisDisabled?: boolean;\n };\n\nconst name = 'GasFeeController';\n\nexport type GasFeeStateChange = ControllerStateChangeEvent<\n typeof name,\n GasFeeState\n>;\n\nexport type GetGasFeeState = ControllerGetStateAction<typeof name, GasFeeState>;\n\nexport type GasFeeControllerActions = GetGasFeeState;\n\nexport type GasFeeControllerEvents = GasFeeStateChange;\n\ntype AllowedActions =\n | NetworkControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetEIP1559CompatibilityAction;\n\ntype GasFeeMessenger = RestrictedControllerMessenger<\n typeof name,\n GasFeeControllerActions | AllowedActions,\n GasFeeControllerEvents | NetworkControllerNetworkDidChangeEvent,\n AllowedActions['type'],\n NetworkControllerNetworkDidChangeEvent['type']\n>;\n\nconst defaultState: GasFeeState = {\n gasFeeEstimatesByChainId: {},\n gasFeeEstimates: {},\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.NONE,\n nonRPCGasFeeApisDisabled: false,\n};\n\n/**\n * Controller that retrieves gas fee estimate data and polls for updated data on a set interval\n */\nexport class GasFeeController extends StaticIntervalPollingController<\n typeof name,\n GasFeeState,\n GasFeeMessenger\n> {\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay;\n\n private readonly pollTokens: Set<string>;\n\n private readonly legacyAPIEndpoint: string;\n\n private readonly EIP1559APIEndpoint: string;\n\n private readonly getCurrentNetworkEIP1559Compatibility;\n\n private readonly getCurrentNetworkLegacyGasAPICompatibility;\n\n private readonly getCurrentAccountEIP1559Compatibility;\n\n private currentChainId;\n\n private ethQuery?: EthQuery;\n\n private readonly clientId?: string;\n\n #getProvider: () => ProviderProxy;\n\n /**\n * Creates a GasFeeController instance.\n *\n * @param options - The controller options.\n * @param options.interval - The time in milliseconds to wait between polls.\n * @param options.messenger - The controller messenger.\n * @param options.state - The initial state.\n * @param options.getCurrentNetworkEIP1559Compatibility - Determines whether or not the current\n * network is EIP-1559 compatible.\n * @param options.getCurrentNetworkLegacyGasAPICompatibility - Determines whether or not the\n * current network is compatible with the legacy gas price API.\n * @param options.getCurrentAccountEIP1559Compatibility - Determines whether or not the current\n * account is EIP-1559 compatible.\n * @param options.getChainId - Returns the current chain ID.\n * @param options.getProvider - Returns a network provider for the current network.\n * @param options.onNetworkDidChange - A function for registering an event handler for the\n * network state change event.\n * @param options.legacyAPIEndpoint - The legacy gas price API URL. This option is primarily for\n * testing purposes.\n * @param options.EIP1559APIEndpoint - The EIP-1559 gas price API URL.\n * @param options.clientId - The client ID used to identify to the gas estimation API who is\n * asking for estimates.\n */\n constructor({\n interval = 15000,\n messenger,\n state,\n getCurrentNetworkEIP1559Compatibility,\n getCurrentAccountEIP1559Compatibility,\n getChainId,\n getCurrentNetworkLegacyGasAPICompatibility,\n getProvider,\n onNetworkDidChange,\n legacyAPIEndpoint = LEGACY_GAS_PRICES_API_URL,\n EIP1559APIEndpoint,\n clientId,\n }: {\n interval?: number;\n messenger: GasFeeMessenger;\n state?: GasFeeState;\n getCurrentNetworkEIP1559Compatibility: () => Promise<boolean>;\n getCurrentNetworkLegacyGasAPICompatibility: () => boolean;\n getCurrentAccountEIP1559Compatibility?: () => boolean;\n getChainId?: () => Hex;\n getProvider: () => ProviderProxy;\n onNetworkDidChange?: (listener: (state: NetworkState) => void) => void;\n legacyAPIEndpoint?: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n EIP1559APIEndpoint: string;\n clientId?: string;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.intervalDelay = interval;\n this.setIntervalLength(interval);\n this.pollTokens = new Set();\n this.getCurrentNetworkEIP1559Compatibility =\n getCurrentNetworkEIP1559Compatibility;\n this.getCurrentNetworkLegacyGasAPICompatibility =\n getCurrentNetworkLegacyGasAPICompatibility;\n this.getCurrentAccountEIP1559Compatibility =\n getCurrentAccountEIP1559Compatibility;\n this.#getProvider = getProvider;\n this.EIP1559APIEndpoint = EIP1559APIEndpoint;\n this.legacyAPIEndpoint = legacyAPIEndpoint;\n this.clientId = clientId;\n\n this.ethQuery = new EthQuery(this.#getProvider());\n\n if (onNetworkDidChange && getChainId) {\n this.currentChainId = getChainId();\n onNetworkDidChange(async (networkControllerState) => {\n await this.#onNetworkControllerDidChange(networkControllerState);\n });\n } else {\n this.currentChainId = this.messagingSystem.call(\n 'NetworkController:getState',\n ).providerConfig.chainId;\n this.messagingSystem.subscribe(\n 'NetworkController:networkDidChange',\n async (networkControllerState) => {\n await this.#onNetworkControllerDidChange(networkControllerState);\n },\n );\n }\n }\n\n async resetPolling() {\n if (this.pollTokens.size !== 0) {\n const tokens = Array.from(this.pollTokens);\n this.stopPolling();\n await this.getGasFeeEstimatesAndStartPolling(tokens[0]);\n tokens.slice(1).forEach((token) => {\n this.pollTokens.add(token);\n });\n }\n }\n\n async fetchGasFeeEstimates(options?: FetchGasFeeEstimateOptions) {\n return await this._fetchGasFeeEstimateData(options);\n }\n\n async getGasFeeEstimatesAndStartPolling(\n pollToken: string | undefined,\n ): Promise<string> {\n const _pollToken = pollToken || random();\n\n this.pollTokens.add(_pollToken);\n\n if (this.pollTokens.size === 1) {\n await this._fetchGasFeeEstimateData();\n this._poll();\n }\n\n return _pollToken;\n }\n\n /**\n * Gets and sets gasFeeEstimates in state.\n *\n * @param options - The gas fee estimate options.\n * @param options.shouldUpdateState - Determines whether the state should be updated with the\n * updated gas estimates.\n * @returns The gas fee estimates.\n */\n async _fetchGasFeeEstimateData(\n options: FetchGasFeeEstimateOptions = {},\n ): Promise<GasFeeState> {\n const { shouldUpdateState = true, networkClientId } = options;\n\n let ethQuery,\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n decimalChainId: number;\n\n if (networkClientId !== undefined) {\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n isLegacyGasAPICompatible = networkClient.configuration.chainId === '0x38';\n\n decimalChainId = convertHexToDecimal(networkClient.configuration.chainId);\n\n try {\n const result = await this.messagingSystem.call(\n 'NetworkController:getEIP1559Compatibility',\n networkClientId,\n );\n isEIP1559Compatible = result || false;\n } catch {\n isEIP1559Compatible = false;\n }\n ethQuery = new EthQuery(networkClient.provider);\n }\n\n ethQuery ??= this.ethQuery;\n\n isLegacyGasAPICompatible ??=\n this.getCurrentNetworkLegacyGasAPICompatibility();\n\n decimalChainId ??= convertHexToDecimal(this.currentChainId);\n\n try {\n isEIP1559Compatible ??= await this.getEIP1559Compatibility();\n } catch (e) {\n console.error(e);\n isEIP1559Compatible ??= false;\n }\n\n const gasFeeCalculations = await determineGasFeeCalculations({\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n fetchGasEstimates,\n fetchGasEstimatesUrl: this.EIP1559APIEndpoint.replace(\n '<chain_id>',\n `${decimalChainId}`,\n ),\n fetchLegacyGasPriceEstimates,\n fetchLegacyGasPriceEstimatesUrl: this.legacyAPIEndpoint.replace(\n '<chain_id>',\n `${decimalChainId}`,\n ),\n fetchEthGasPriceEstimate,\n calculateTimeEstimate,\n clientId: this.clientId,\n ethQuery,\n nonRPCGasFeeApisDisabled: this.state.nonRPCGasFeeApisDisabled,\n });\n\n if (shouldUpdateState) {\n const chainId = toHex(decimalChainId);\n this.update((state) => {\n if (this.currentChainId === chainId) {\n state.gasFeeEstimates = gasFeeCalculations.gasFeeEstimates;\n state.estimatedGasFeeTimeBounds =\n gasFeeCalculations.estimatedGasFeeTimeBounds;\n state.gasEstimateType = gasFeeCalculations.gasEstimateType;\n }\n state.gasFeeEstimatesByChainId ??= {};\n state.gasFeeEstimatesByChainId[chainId] = {\n gasFeeEstimates: gasFeeCalculations.gasFeeEstimates,\n estimatedGasFeeTimeBounds:\n gasFeeCalculations.estimatedGasFeeTimeBounds,\n gasEstimateType: gasFeeCalculations.gasEstimateType,\n } as SingleChainGasFeeState;\n });\n }\n\n return gasFeeCalculations;\n }\n\n /**\n * Remove the poll token, and stop polling if the set of poll tokens is empty.\n *\n * @param pollToken - The poll token to disconnect.\n */\n disconnectPoller(pollToken: string) {\n this.pollTokens.delete(pollToken);\n if (this.pollTokens.size === 0) {\n this.stopPolling();\n }\n }\n\n stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n this.pollTokens.clear();\n this.resetState();\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n private _poll() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this._fetchGasFeeEstimateData());\n }, this.intervalDelay);\n }\n\n /**\n * Fetching token list from the Token Service API.\n *\n * @private\n * @param networkClientId - The ID of the network client triggering the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll(networkClientId: string): Promise<void> {\n await this._fetchGasFeeEstimateData({ networkClientId });\n }\n\n private resetState() {\n this.update(() => {\n return defaultState;\n });\n }\n\n private async getEIP1559Compatibility() {\n const currentNetworkIsEIP1559Compatible =\n await this.getCurrentNetworkEIP1559Compatibility();\n const currentAccountIsEIP1559Compatible =\n this.getCurrentAccountEIP1559Compatibility?.() ?? true;\n\n return (\n currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible\n );\n }\n\n getTimeEstimate(\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n ): EstimatedGasFeeTimeBounds | Record<string, never> {\n if (\n !this.state.gasFeeEstimates ||\n this.state.gasEstimateType !== GAS_ESTIMATE_TYPES.FEE_MARKET\n ) {\n return {};\n }\n return calculateTimeEstimate(\n maxPriorityFeePerGas,\n maxFeePerGas,\n this.state.gasFeeEstimates,\n );\n }\n\n async #onNetworkControllerDidChange(networkControllerState: NetworkState) {\n const newChainId = networkControllerState.providerConfig.chainId;\n\n if (newChainId !== this.currentChainId) {\n this.ethQuery = new EthQuery(this.#getProvider());\n await this.resetPolling();\n\n this.currentChainId = newChainId;\n }\n }\n\n enableNonRPCGasFeeApis() {\n this.update((state) => {\n state.nonRPCGasFeeApisDisabled = false;\n });\n }\n\n disableNonRPCGasFeeApis() {\n this.update((state) => {\n state.nonRPCGasFeeApisDisabled = true;\n });\n }\n}\n\nexport default GasFeeController;\n","import type {\n EstimatedGasFeeTimeBounds,\n EthGasPriceEstimate,\n GasFeeEstimates,\n GasFeeState as GasFeeCalculations,\n LegacyGasPriceEstimate,\n} from './GasFeeController';\nimport { GAS_ESTIMATE_TYPES } from './GasFeeController';\n\ntype DetermineGasFeeCalculationsRequest = {\n isEIP1559Compatible: boolean;\n isLegacyGasAPICompatible: boolean;\n fetchGasEstimates: (\n url: string,\n clientId?: string,\n ) => Promise<GasFeeEstimates>;\n fetchGasEstimatesUrl: string;\n fetchLegacyGasPriceEstimates: (\n url: string,\n clientId?: string,\n ) => Promise<LegacyGasPriceEstimate>;\n fetchLegacyGasPriceEstimatesUrl: string;\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fetchEthGasPriceEstimate: (ethQuery: any) => Promise<EthGasPriceEstimate>;\n calculateTimeEstimate: (\n maxPriorityFeePerGas: string,\n maxFeePerGas: string,\n gasFeeEstimates: GasFeeEstimates,\n ) => EstimatedGasFeeTimeBounds;\n clientId: string | undefined;\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ethQuery: any;\n nonRPCGasFeeApisDisabled?: boolean;\n};\n\n/**\n * Obtains a set of max base and priority fee estimates along with time estimates so that we\n * can present them to users when they are sending transactions or making swaps.\n *\n * @param args - The arguments.\n * @param args.isEIP1559Compatible - Governs whether or not we can use an EIP-1559-only method to\n * produce estimates.\n * @param args.isLegacyGasAPICompatible - Governs whether or not we can use a non-EIP-1559 method to\n * produce estimates (for instance, testnets do not support estimates altogether).\n * @param args.fetchGasEstimates - A function that fetches gas estimates using an EIP-1559-specific\n * API.\n * @param args.fetchGasEstimatesUrl - The URL for the API we can use to obtain EIP-1559-specific\n * estimates.\n * @param args.fetchLegacyGasPriceEstimates - A function that fetches gas estimates using an\n * non-EIP-1559-specific API.\n * @param args.fetchLegacyGasPriceEstimatesUrl - The URL for the API we can use to obtain\n * non-EIP-1559-specific estimates.\n * @param args.fetchEthGasPriceEstimate - A function that fetches gas estimates using\n * `eth_gasPrice`.\n * @param args.calculateTimeEstimate - A function that determine time estimate bounds.\n * @param args.clientId - An identifier that an API can use to know who is asking for estimates.\n * @param args.ethQuery - An EthQuery instance we can use to talk to Ethereum directly.\n * @param args.nonRPCGasFeeApisDisabled - Whether to disable requests to the legacyAPIEndpoint and the EIP1559APIEndpoint\n * @returns The gas fee calculations.\n */\nexport default async function determineGasFeeCalculations(\n args: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n try {\n return await getEstimatesUsingFallbacks(args);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Gas fee/price estimation failed. Message: ${error.message}`,\n );\n }\n\n throw error;\n }\n}\n\n/**\n * Retrieve the gas fee estimates using a series of fallback mechanisms.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingFallbacks(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n isEIP1559Compatible,\n isLegacyGasAPICompatible,\n nonRPCGasFeeApisDisabled,\n } = request;\n\n try {\n if (isEIP1559Compatible && !nonRPCGasFeeApisDisabled) {\n return await getEstimatesUsingFeeMarketEndpoint(request);\n }\n\n if (isLegacyGasAPICompatible && !nonRPCGasFeeApisDisabled) {\n return await getEstimatesUsingLegacyEndpoint(request);\n }\n\n throw new Error('Main gas fee/price estimation failed. Use fallback');\n } catch {\n return await getEstimatesUsingProvider(request);\n }\n}\n\n/**\n * Retrieve gas fee estimates using the EIP-1559 endpoint of the gas API.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingFeeMarketEndpoint(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n fetchGasEstimates,\n fetchGasEstimatesUrl,\n clientId,\n calculateTimeEstimate,\n } = request;\n\n const estimates = await fetchGasEstimates(fetchGasEstimatesUrl, clientId);\n\n const { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas } =\n estimates.medium;\n\n const estimatedGasFeeTimeBounds = calculateTimeEstimate(\n suggestedMaxPriorityFeePerGas,\n suggestedMaxFeePerGas,\n estimates,\n );\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds,\n gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,\n };\n}\n\n/**\n * Retrieve gas fee estimates using the legacy endpoint of the gas API.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingLegacyEndpoint(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const {\n fetchLegacyGasPriceEstimates,\n fetchLegacyGasPriceEstimatesUrl,\n clientId,\n } = request;\n\n const estimates = await fetchLegacyGasPriceEstimates(\n fetchLegacyGasPriceEstimatesUrl,\n clientId,\n );\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,\n };\n}\n\n/**\n * Retrieve gas fee estimates using an `eth_gasPrice` call to the RPC provider.\n * @param request - The request object.\n * @returns The gas fee estimates.\n */\nasync function getEstimatesUsingProvider(\n request: DetermineGasFeeCalculationsRequest,\n): Promise<GasFeeCalculations> {\n const { ethQuery, fetchEthGasPriceEstimate } = request;\n\n const estimates = await fetchEthGasPriceEstimate(ethQuery);\n\n return {\n gasFeeEstimates: estimates,\n estimatedGasFeeTimeBounds: {},\n gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE,\n };\n}\n"]} +\ No newline at end of file +diff --git a/dist/determineGasFeeCalculations.js b/dist/determineGasFeeCalculations.js +index 87f583d091e574fc81b84ce35ee4b9979dbabdf6..ccfd460054f0affdec3857d8ec0015fe5c0814cb 100644 +--- a/dist/determineGasFeeCalculations.js ++++ b/dist/determineGasFeeCalculations.js +@@ -1,8 +1,8 @@ + "use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +-var _chunkH5WHAYLIjs = require('./chunk-H5WHAYLI.js'); +-require('./chunk-Q2YPK5SL.js'); ++var _chunkX74LQX2Yjs = require('./chunk-X74LQX2Y.js'); ++require('./chunk-2MFVV2BX.js'); + + +-exports.default = _chunkH5WHAYLIjs.determineGasFeeCalculations; ++exports.default = _chunkX74LQX2Yjs.determineGasFeeCalculations; + //# sourceMappingURL=determineGasFeeCalculations.js.map +\ No newline at end of file +diff --git a/dist/determineGasFeeCalculations.mjs b/dist/determineGasFeeCalculations.mjs +index b372041262f1d8372632922919f52aa2c6c5ee89..e5b349a8f349076b85481dceec5795b07aeb19ca 100644 +--- a/dist/determineGasFeeCalculations.mjs ++++ b/dist/determineGasFeeCalculations.mjs +@@ -1,7 +1,7 @@ + import { + determineGasFeeCalculations +-} from "./chunk-BEVZS3YV.mjs"; +-import "./chunk-KORLXV32.mjs"; ++} from "./chunk-A7NHJBXX.mjs"; ++import "./chunk-R3IOI7AK.mjs"; + export { + determineGasFeeCalculations as default + }; +diff --git a/dist/gas-util.js b/dist/gas-util.js +index 74c93749878df29b40eea3d998d26d734112d75c..aad155e1a969ac01a09f8e18becac39a79860199 100644 +--- a/dist/gas-util.js ++++ b/dist/gas-util.js +@@ -4,12 +4,12 @@ + + + +-var _chunkQ2YPK5SLjs = require('./chunk-Q2YPK5SL.js'); ++var _chunk2MFVV2BXjs = require('./chunk-2MFVV2BX.js'); + + + + + + +-exports.calculateTimeEstimate = _chunkQ2YPK5SLjs.calculateTimeEstimate; exports.fetchEthGasPriceEstimate = _chunkQ2YPK5SLjs.fetchEthGasPriceEstimate; exports.fetchGasEstimates = _chunkQ2YPK5SLjs.fetchGasEstimates; exports.fetchLegacyGasPriceEstimates = _chunkQ2YPK5SLjs.fetchLegacyGasPriceEstimates; exports.normalizeGWEIDecimalNumbers = _chunkQ2YPK5SLjs.normalizeGWEIDecimalNumbers; ++exports.calculateTimeEstimate = _chunk2MFVV2BXjs.calculateTimeEstimate; exports.fetchEthGasPriceEstimate = _chunk2MFVV2BXjs.fetchEthGasPriceEstimate; exports.fetchGasEstimates = _chunk2MFVV2BXjs.fetchGasEstimates; exports.fetchLegacyGasPriceEstimates = _chunk2MFVV2BXjs.fetchLegacyGasPriceEstimates; exports.normalizeGWEIDecimalNumbers = _chunk2MFVV2BXjs.normalizeGWEIDecimalNumbers; + //# sourceMappingURL=gas-util.js.map +\ No newline at end of file +diff --git a/dist/gas-util.mjs b/dist/gas-util.mjs +index c0846d32a7fe2598691c5c0bcc19ce2b8af67bc3..60f38a1b3899f0223fa7651988e57fa659e713e8 100644 +--- a/dist/gas-util.mjs ++++ b/dist/gas-util.mjs +@@ -4,7 +4,7 @@ import { + fetchGasEstimates, + fetchLegacyGasPriceEstimates, + normalizeGWEIDecimalNumbers +-} from "./chunk-KORLXV32.mjs"; ++} from "./chunk-R3IOI7AK.mjs"; + export { + calculateTimeEstimate, + fetchEthGasPriceEstimate, +diff --git a/dist/index.js b/dist/index.js +index 499a7d57b68212db4402be72ab8d3384a841dba0..f172d463bef0093dd477dfad74ff50d30e42a7f0 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -2,11 +2,11 @@ + + + +-var _chunkH5WHAYLIjs = require('./chunk-H5WHAYLI.js'); +-require('./chunk-Q2YPK5SL.js'); ++var _chunkX74LQX2Yjs = require('./chunk-X74LQX2Y.js'); ++require('./chunk-2MFVV2BX.js'); + + + + +-exports.GAS_API_BASE_URL = _chunkH5WHAYLIjs.GAS_API_BASE_URL; exports.GAS_ESTIMATE_TYPES = _chunkH5WHAYLIjs.GAS_ESTIMATE_TYPES; exports.GasFeeController = _chunkH5WHAYLIjs.GasFeeController; ++exports.GAS_ESTIMATE_TYPES = _chunkX74LQX2Yjs.GAS_ESTIMATE_TYPES; exports.GasFeeController = _chunkX74LQX2Yjs.GasFeeController; exports.LEGACY_GAS_PRICES_API_URL = _chunkX74LQX2Yjs.LEGACY_GAS_PRICES_API_URL; + //# sourceMappingURL=index.js.map +\ No newline at end of file +diff --git a/dist/index.mjs b/dist/index.mjs +index 47fbe488932996ec192dd04a6b92d72c038681cc..71847186d44947ec3b2d75d142afbeede0aa64fc 100644 +--- a/dist/index.mjs ++++ b/dist/index.mjs +@@ -1,12 +1,12 @@ + import { +- GAS_API_BASE_URL, + GAS_ESTIMATE_TYPES, +- GasFeeController +-} from "./chunk-BEVZS3YV.mjs"; +-import "./chunk-KORLXV32.mjs"; ++ GasFeeController, ++ LEGACY_GAS_PRICES_API_URL ++} from "./chunk-A7NHJBXX.mjs"; ++import "./chunk-R3IOI7AK.mjs"; + export { +- GAS_API_BASE_URL, + GAS_ESTIMATE_TYPES, +- GasFeeController ++ GasFeeController, ++ LEGACY_GAS_PRICES_API_URL + }; + //# sourceMappingURL=index.mjs.map +\ No newline at end of file +diff --git a/dist/tsconfig.build.tsbuildinfo b/dist/tsconfig.build.tsbuildinfo +index c226cf271a32a00bf6054fba381ed5f846ed9752..008d925dcefc659662cbfa15bd507ce773b8fc56 100644 +--- a/dist/tsconfig.build.tsbuildinfo ++++ b/dist/tsconfig.build.tsbuildinfo +@@ -1 +1 @@ +-{"program":{"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../../types/eth-ens-namehash.d.ts","../../../types/ethereum-ens-network-map.d.ts","../../../types/global.d.ts","../../../types/single-call-balance-checker-abi.d.ts","../../../types/@metamask/contract-metadata.d.ts","../../../types/@metamask/eth-hd-keyring.d.ts","../../../types/@metamask/eth-simple-keyring.d.ts","../../../types/@metamask/ethjs-provider-http.d.ts","../../../types/@metamask/ethjs-unit.d.ts","../../../types/@metamask/metamask-eth-abis.d.ts","../../../types/eth-json-rpc-infura/src/createProvider.d.ts","../../../types/eth-phishing-detect/src/config.json.d.ts","../../../types/eth-phishing-detect/src/detector.d.ts","../../base-controller/dist/types/BaseControllerV1.d.ts","../../../node_modules/superstruct/dist/error.d.ts","../../../node_modules/superstruct/dist/utils.d.ts","../../../node_modules/superstruct/dist/struct.d.ts","../../../node_modules/superstruct/dist/structs/coercions.d.ts","../../../node_modules/superstruct/dist/structs/refinements.d.ts","../../../node_modules/superstruct/dist/structs/types.d.ts","../../../node_modules/superstruct/dist/structs/utilities.d.ts","../../../node_modules/superstruct/dist/index.d.ts","../../../node_modules/@metamask/utils/dist/types/assert.d.ts","../../../node_modules/@metamask/utils/dist/types/base64.d.ts","../../../node_modules/@metamask/utils/dist/types/hex.d.ts","../../../node_modules/@metamask/utils/dist/types/bytes.d.ts","../../../node_modules/@metamask/utils/dist/types/caip-types.d.ts","../../../node_modules/@metamask/utils/dist/types/checksum.d.ts","../../../node_modules/@metamask/utils/dist/types/coercers.d.ts","../../../node_modules/@metamask/utils/dist/types/collections.d.ts","../../../node_modules/@metamask/utils/dist/types/encryption-types.d.ts","../../../node_modules/@metamask/utils/dist/types/errors.d.ts","../../../node_modules/@metamask/utils/dist/types/json.d.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/dom-events.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/globals.global.d.ts","../../../node_modules/@types/node/index.d.ts","../../../node_modules/@ethereumjs/common/dist/enums.d.ts","../../../node_modules/@ethereumjs/common/dist/types.d.ts","../../../node_modules/buffer/index.d.ts","../../../node_modules/@ethereumjs/util/dist/constants.d.ts","../../../node_modules/@ethereumjs/util/dist/units.d.ts","../../../node_modules/@ethereumjs/util/dist/address.d.ts","../../../node_modules/@ethereumjs/util/dist/bytes.d.ts","../../../node_modules/@ethereumjs/util/dist/types.d.ts","../../../node_modules/@ethereumjs/util/dist/account.d.ts","../../../node_modules/@ethereumjs/util/dist/withdrawal.d.ts","../../../node_modules/@ethereumjs/util/dist/signature.d.ts","../../../node_modules/@ethereumjs/util/dist/encoding.d.ts","../../../node_modules/@ethereumjs/util/dist/asyncEventEmitter.d.ts","../../../node_modules/@ethereumjs/util/dist/internal.d.ts","../../../node_modules/@ethereumjs/util/dist/lock.d.ts","../../../node_modules/@ethereumjs/util/dist/provider.d.ts","../../../node_modules/@ethereumjs/util/dist/index.d.ts","../../../node_modules/@ethereumjs/common/dist/common.d.ts","../../../node_modules/@ethereumjs/common/dist/utils.d.ts","../../../node_modules/@ethereumjs/common/dist/index.d.ts","../../../node_modules/@ethereumjs/tx/dist/eip2930Transaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/legacyTransaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/types.d.ts","../../../node_modules/@ethereumjs/tx/dist/baseTransaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/eip1559Transaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/transactionFactory.d.ts","../../../node_modules/@ethereumjs/tx/dist/index.d.ts","../../../node_modules/@metamask/utils/dist/types/keyring.d.ts","../../../node_modules/@types/ms/index.d.ts","../../../node_modules/@types/debug/index.d.ts","../../../node_modules/@metamask/utils/dist/types/logging.d.ts","../../../node_modules/@metamask/utils/dist/types/misc.d.ts","../../../node_modules/@metamask/utils/dist/types/number.d.ts","../../../node_modules/@metamask/utils/dist/types/opaque.d.ts","../../../node_modules/@metamask/utils/dist/types/promise.d.ts","../../../node_modules/@metamask/utils/dist/types/time.d.ts","../../../node_modules/@metamask/utils/dist/types/transaction-types.d.ts","../../../node_modules/@metamask/utils/dist/types/versions.d.ts","../../../node_modules/@metamask/utils/dist/types/index.d.ts","../../../node_modules/immer/dist/utils/env.d.ts","../../../node_modules/immer/dist/utils/errors.d.ts","../../../node_modules/immer/dist/types/types-external.d.ts","../../../node_modules/immer/dist/types/types-internal.d.ts","../../../node_modules/immer/dist/utils/common.d.ts","../../../node_modules/immer/dist/utils/plugins.d.ts","../../../node_modules/immer/dist/core/scope.d.ts","../../../node_modules/immer/dist/core/finalize.d.ts","../../../node_modules/immer/dist/core/proxy.d.ts","../../../node_modules/immer/dist/core/immerClass.d.ts","../../../node_modules/immer/dist/core/current.d.ts","../../../node_modules/immer/dist/internal.d.ts","../../../node_modules/immer/dist/plugins/es5.d.ts","../../../node_modules/immer/dist/plugins/patches.d.ts","../../../node_modules/immer/dist/plugins/mapset.d.ts","../../../node_modules/immer/dist/plugins/all.d.ts","../../../node_modules/immer/dist/immer.d.ts","../../base-controller/dist/types/RestrictedControllerMessenger.d.ts","../../base-controller/dist/types/ControllerMessenger.d.ts","../../base-controller/dist/types/BaseControllerV2.d.ts","../../base-controller/dist/types/index.d.ts","../../controller-utils/dist/types/types.d.ts","../../controller-utils/dist/types/constants.d.ts","../../../node_modules/@metamask/eth-query/index.d.ts","../../../node_modules/@types/bn.js/index.d.ts","../../controller-utils/dist/types/util.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/abnf.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/utils.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/parsers.d.ts","../../controller-utils/dist/types/siwe.d.ts","../../controller-utils/dist/types/index.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/types.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/createEventEmitterProxy.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/createSwappableProxy.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/index.d.ts","../../network-controller/dist/types/constants.d.ts","../../../node_modules/@metamask/safe-event-emitter/dist/cjs/index.d.ts","../../json-rpc-engine/dist/types/JsonRpcEngine.d.ts","../../json-rpc-engine/dist/types/createAsyncMiddleware.d.ts","../../json-rpc-engine/dist/types/createScaffoldMiddleware.d.ts","../../json-rpc-engine/dist/types/getUniqueId.d.ts","../../json-rpc-engine/dist/types/idRemapMiddleware.d.ts","../../json-rpc-engine/dist/types/mergeMiddleware.d.ts","../../json-rpc-engine/dist/types/index.d.ts","../../eth-json-rpc-provider/dist/types/safe-event-emitter-provider.d.ts","../../eth-json-rpc-provider/dist/types/provider-from-engine.d.ts","../../eth-json-rpc-provider/dist/types/provider-from-middleware.d.ts","../../eth-json-rpc-provider/dist/types/index.d.ts","../../../node_modules/eth-block-tracker/dist/BlockTracker.d.ts","../../../node_modules/eth-block-tracker/dist/PollingBlockTracker.d.ts","../../../node_modules/eth-block-tracker/dist/SubscribeBlockTracker.d.ts","../../../node_modules/eth-block-tracker/dist/index.d.ts","../../network-controller/dist/types/types.d.ts","../../network-controller/dist/types/create-auto-managed-network-client.d.ts","../../network-controller/dist/types/NetworkController.d.ts","../../network-controller/dist/types/create-network-client.d.ts","../../network-controller/dist/types/index.d.ts","../../polling-controller/dist/types/types.d.ts","../../polling-controller/dist/types/BlockTrackerPollingController.d.ts","../../polling-controller/dist/types/StaticIntervalPollingController.d.ts","../../polling-controller/dist/types/index.d.ts","../../../node_modules/@types/uuid/index.d.ts","../src/determineGasFeeCalculations.ts","../src/gas-util.ts","../src/GasFeeController.ts","../src/index.ts","../../../node_modules/@babel/types/lib/index.d.ts","../../../node_modules/@types/babel__generator/index.d.ts","../../../node_modules/@babel/parser/typings/babel-parser.d.ts","../../../node_modules/@types/babel__template/index.d.ts","../../../node_modules/@types/babel__traverse/index.d.ts","../../../node_modules/@types/babel__core/index.d.ts","../../../node_modules/@types/deep-freeze-strict/index.d.ts","../../../node_modules/@types/eslint/helpers.d.ts","../../../node_modules/@types/estree/index.d.ts","../../../node_modules/@types/json-schema/index.d.ts","../../../node_modules/@types/eslint/index.d.ts","../../../node_modules/@types/graceful-fs/index.d.ts","../../../node_modules/@types/istanbul-lib-coverage/index.d.ts","../../../node_modules/@types/istanbul-lib-report/index.d.ts","../../../node_modules/@types/istanbul-reports/index.d.ts","../../../node_modules/chalk/index.d.ts","../../../node_modules/jest-diff/build/cleanupSemantic.d.ts","../../../node_modules/pretty-format/build/types.d.ts","../../../node_modules/pretty-format/build/index.d.ts","../../../node_modules/jest-diff/build/types.d.ts","../../../node_modules/jest-diff/build/diffLines.d.ts","../../../node_modules/jest-diff/build/printDiffs.d.ts","../../../node_modules/jest-diff/build/index.d.ts","../../../node_modules/jest-matcher-utils/build/index.d.ts","../../../node_modules/@types/jest/index.d.ts","../../../node_modules/@types/jest-when/index.d.ts","../../../node_modules/@types/json5/index.d.ts","../../../node_modules/@types/lodash/common/common.d.ts","../../../node_modules/@types/lodash/common/array.d.ts","../../../node_modules/@types/lodash/common/collection.d.ts","../../../node_modules/@types/lodash/common/date.d.ts","../../../node_modules/@types/lodash/common/function.d.ts","../../../node_modules/@types/lodash/common/lang.d.ts","../../../node_modules/@types/lodash/common/math.d.ts","../../../node_modules/@types/lodash/common/number.d.ts","../../../node_modules/@types/lodash/common/object.d.ts","../../../node_modules/@types/lodash/common/seq.d.ts","../../../node_modules/@types/lodash/common/string.d.ts","../../../node_modules/@types/lodash/common/util.d.ts","../../../node_modules/@types/lodash/index.d.ts","../../../node_modules/@types/minimatch/index.d.ts","../../../node_modules/@types/parse-json/index.d.ts","../../../node_modules/@types/pbkdf2/index.d.ts","../../../node_modules/@types/prettier/index.d.ts","../../../node_modules/@types/punycode/index.d.ts","../../../node_modules/@types/readable-stream/node_modules/safe-buffer/index.d.ts","../../../node_modules/@types/readable-stream/index.d.ts","../../../node_modules/@types/secp256k1/index.d.ts","../../../node_modules/@types/semver/classes/semver.d.ts","../../../node_modules/@types/semver/functions/parse.d.ts","../../../node_modules/@types/semver/functions/valid.d.ts","../../../node_modules/@types/semver/functions/clean.d.ts","../../../node_modules/@types/semver/functions/inc.d.ts","../../../node_modules/@types/semver/functions/diff.d.ts","../../../node_modules/@types/semver/functions/major.d.ts","../../../node_modules/@types/semver/functions/minor.d.ts","../../../node_modules/@types/semver/functions/patch.d.ts","../../../node_modules/@types/semver/functions/prerelease.d.ts","../../../node_modules/@types/semver/functions/compare.d.ts","../../../node_modules/@types/semver/functions/rcompare.d.ts","../../../node_modules/@types/semver/functions/compare-loose.d.ts","../../../node_modules/@types/semver/functions/compare-build.d.ts","../../../node_modules/@types/semver/functions/sort.d.ts","../../../node_modules/@types/semver/functions/rsort.d.ts","../../../node_modules/@types/semver/functions/gt.d.ts","../../../node_modules/@types/semver/functions/lt.d.ts","../../../node_modules/@types/semver/functions/eq.d.ts","../../../node_modules/@types/semver/functions/neq.d.ts","../../../node_modules/@types/semver/functions/gte.d.ts","../../../node_modules/@types/semver/functions/lte.d.ts","../../../node_modules/@types/semver/functions/cmp.d.ts","../../../node_modules/@types/semver/functions/coerce.d.ts","../../../node_modules/@types/semver/classes/comparator.d.ts","../../../node_modules/@types/semver/classes/range.d.ts","../../../node_modules/@types/semver/functions/satisfies.d.ts","../../../node_modules/@types/semver/ranges/max-satisfying.d.ts","../../../node_modules/@types/semver/ranges/min-satisfying.d.ts","../../../node_modules/@types/semver/ranges/to-comparators.d.ts","../../../node_modules/@types/semver/ranges/min-version.d.ts","../../../node_modules/@types/semver/ranges/valid.d.ts","../../../node_modules/@types/semver/ranges/outside.d.ts","../../../node_modules/@types/semver/ranges/gtr.d.ts","../../../node_modules/@types/semver/ranges/ltr.d.ts","../../../node_modules/@types/semver/ranges/intersects.d.ts","../../../node_modules/@types/semver/ranges/simplify.d.ts","../../../node_modules/@types/semver/ranges/subset.d.ts","../../../node_modules/@types/semver/internals/identifiers.d.ts","../../../node_modules/@types/semver/index.d.ts","../../../node_modules/@types/sinonjs__fake-timers/index.d.ts","../../../node_modules/@types/sinon/index.d.ts","../../../node_modules/@types/stack-utils/index.d.ts","../../../node_modules/@types/yargs-parser/index.d.ts","../../../node_modules/@types/yargs/index.d.ts"],"fileInfos":[{"version":"8730f4bf322026ff5229336391a18bcaa1f94d4f82416c8b2f3954e2ccaae2ba","affectsGlobalScope":true},"dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6","7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467","8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9","5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06","4b421cbfb3a38a27c279dec1e9112c3d1da296f77a1a85ddadf7e7a425d45d18","1fc5ab7a764205c68fa10d381b08417795fc73111d6dd16b5b1ed36badb743d9",{"version":"3aafcb693fe5b5c3bd277bd4c3a617b53db474fe498fc5df067c5603b1eebde7","affectsGlobalScope":true},{"version":"adb996790133eb33b33aadb9c09f15c2c575e71fb57a62de8bf74dbf59ec7dfb","affectsGlobalScope":true},{"version":"8cc8c5a3bac513368b0157f3d8b31cfdcfe78b56d3724f30f80ed9715e404af8","affectsGlobalScope":true},{"version":"cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a","affectsGlobalScope":true},{"version":"c5c05907c02476e4bde6b7e76a79ffcd948aedd14b6a8f56e4674221b0417398","affectsGlobalScope":true},{"version":"5f406584aef28a331c36523df688ca3650288d14f39c5d2e555c95f0d2ff8f6f","affectsGlobalScope":true},{"version":"22f230e544b35349cfb3bd9110b6ef37b41c6d6c43c3314a31bd0d9652fcec72","affectsGlobalScope":true},{"version":"7ea0b55f6b315cf9ac2ad622b0a7813315bb6e97bf4bb3fbf8f8affbca7dc695","affectsGlobalScope":true},{"version":"3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93","affectsGlobalScope":true},{"version":"eb26de841c52236d8222f87e9e6a235332e0788af8c87a71e9e210314300410a","affectsGlobalScope":true},{"version":"3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006","affectsGlobalScope":true},{"version":"17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a","affectsGlobalScope":true},{"version":"7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98","affectsGlobalScope":true},{"version":"6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577","affectsGlobalScope":true},{"version":"81cac4cbc92c0c839c70f8ffb94eb61e2d32dc1c3cf6d95844ca099463cf37ea","affectsGlobalScope":true},{"version":"b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e","affectsGlobalScope":true},{"version":"0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a","affectsGlobalScope":true},{"version":"da233fc1c8a377ba9e0bed690a73c290d843c2c3d23a7bd7ec5cd3d7d73ba1e0","affectsGlobalScope":true},{"version":"d154ea5bb7f7f9001ed9153e876b2d5b8f5c2bb9ec02b3ae0d239ec769f1f2ae","affectsGlobalScope":true},{"version":"bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c","affectsGlobalScope":true},{"version":"c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8","affectsGlobalScope":true},{"version":"9d57b2b5d15838ed094aa9ff1299eecef40b190722eb619bac4616657a05f951","affectsGlobalScope":true},{"version":"6c51b5dd26a2c31dbf37f00cfc32b2aa6a92e19c995aefb5b97a3a64f1ac99de","affectsGlobalScope":true},{"version":"6e7997ef61de3132e4d4b2250e75343f487903ddf5370e7ce33cf1b9db9a63ed","affectsGlobalScope":true},{"version":"2ad234885a4240522efccd77de6c7d99eecf9b4de0914adb9a35c0c22433f993","affectsGlobalScope":true},{"version":"5e5e095c4470c8bab227dbbc61374878ecead104c74ab9960d3adcccfee23205","affectsGlobalScope":true},{"version":"09aa50414b80c023553090e2f53827f007a301bc34b0495bfb2c3c08ab9ad1eb","affectsGlobalScope":true},{"version":"d7f680a43f8cd12a6b6122c07c54ba40952b0c8aa140dcfcf32eb9e6cb028596","affectsGlobalScope":true},{"version":"3787b83e297de7c315d55d4a7c546ae28e5f6c0a361b7a1dcec1f1f50a54ef11","affectsGlobalScope":true},{"version":"e7e8e1d368290e9295ef18ca23f405cf40d5456fa9f20db6373a61ca45f75f40","affectsGlobalScope":true},{"version":"faf0221ae0465363c842ce6aa8a0cbda5d9296940a8e26c86e04cc4081eea21e","affectsGlobalScope":true},{"version":"06393d13ea207a1bfe08ec8d7be562549c5e2da8983f2ee074e00002629d1871","affectsGlobalScope":true},{"version":"2768ef564cfc0689a1b76106c421a2909bdff0acbe87da010785adab80efdd5c","affectsGlobalScope":true},{"version":"b248e32ca52e8f5571390a4142558ae4f203ae2f94d5bac38a3084d529ef4e58","affectsGlobalScope":true},{"version":"52d1bb7ab7a3306fd0375c8bff560feed26ed676a5b0457fa8027b563aecb9a4","affectsGlobalScope":true},"70bbfaec021ac4a0c805374225b55d70887f987df8b8dd7711d79464bb7b4385","869089d60b67219f63e6aca810284c89bae1b384b5cbc7ce64e53d82ad223ed5",{"version":"18338b6a4b920ec7d49b4ffafcbf0fa8a86b4bfd432966efd722dab611157cf4","affectsGlobalScope":true},"62a0875a0397b35a2364f1d401c0ce17975dfa4d47bf6844de858ae04da349f9","ee7491d0318d1fafcba97d5b72b450eb52671570f7a4ecd9e8898d40eaae9472","e3e7d217d89b380c1f34395eadc9289542851b0f0a64007dfe1fb7cf7423d24e","fd79909e93b4d50fd0ed9f3d39ddf8ba0653290bac25c295aac49f6befbd081b","345a9cc2945406f53051cd0e9b51f82e1e53929848eab046fdda91ee8aa7da31","9debe2de883da37a914e5e784a7be54c201b8f1d783822ad6f443ff409a5ea21","dee5d5c5440cda1f3668f11809a5503c30db0476ad117dd450f7ba5a45300e8f","f5e396c1424c391078c866d6f84afe0b4d2f7f85a160b9c756cd63b5b1775d93","5caa6f4fff16066d377d4e254f6c34c16540da3809cd66cd626a303bc33c419f","730d055528bdf12c8524870bb33d237991be9084c57634e56e5d8075f6605e02","75b22c74010ba649de1a1676a4c4b8b5bb4294fecd05089e2094429b16d7840c","5615ccf831db2ffc82145243081ebdb60ea8e1005ee8f975d1c0c1401a9c894e","38682ed3630bb6ecdace80d5a9adc811fc20a419f1940446e306c3a020d083b9","cc182e6e4f691cd6f7bf7cb491247a4c7818f9f1cb2db1d45c65ff906e3f741b","a50599c08934a62f11657bdbe0dc929ab66da1b1f09974408fd9a33ec1bb8060","5a20e7d6c630b91be15e9b837853173829d00273197481dc8d3e94df61105a71","8d478048d71cc16f806d4b71b252ecb67c7444ccf4f4b09b29a312712184f859","e0eda929c6b9b628cdeb0e54cd3582cb97e64f28aab34612fc1431c545899584","9df4662ca3dbc2522bc115833ee04faa1afbb4e249a85ef4a0a09c621346bd08","b25d9065cf1c1f537a140bbc508e953ed2262f77134574c432d206ff36f4bdbf","1b103313097041aa9cd705a682c652f08613cb5cf8663321061c0902f845e81c","68ccec8662818911d8a12b8ed028bc5729fb4f1d34793c4701265ba60bc73cf4","5f85b8b79dc4d36af672c035b2beb71545de63a5d60bccbeee64c260941672ab","b3d48529ae61dc27d0bfbfa2cb3e0dff8189644bd155bdf5df1e8e14669f7043","40fe4b689225816b31fe5794c0fbf3534568819709e40295ead998a2bc1ab237","f65b5e33b9ad545a1eebbd6afe857314725ad42aaf069913e33f928ab3e4990a","fb6f2a87beb7fb1f4c2b762d0c76a9459fc91f557231569b0ee21399e22aa13d","31c858dc85996fac4b7fa944e1016d5c72f514930a72357ab5001097bf6511c7","3de30a871b3340be8b679c52aa12f90dd1c8c60874517be58968fdbcc4d79445","6fd985bd31eaf77542625306fb0404d32bff978990f0a06428e5f0b9a3b58109","5b3cd03ae354ea96eff1f74d7c410fe4852e6382227e8b0ecf87ab5e3a5bbcd4","7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419",{"version":"056097110efd16869ec118cedb44ecbac9a019576eee808d61304ca6d5cb2cbe","affectsGlobalScope":true},"f51b4042a3ac86f1f707500a9768f88d0b0c1fc3f3e45a73333283dea720cdc6",{"version":"6fb8358e10ed92a7f515b7d79da3904c955a3ffd4e14aa9df6f0ea113041f1cf","affectsGlobalScope":true},"45c831238c6dac21c72da5f335747736a56a3847192bf03c84b958a7e9ec93e2","661a11d16ad2e3543a77c53bcd4017ee9a450f47ab7def3ab493a86eae4d550c",{"version":"8cdc646cec7819581ef343b83855b1bfe4fe674f2c84f4fb8dc90d82fb56bd3a","affectsGlobalScope":true},"a40826e8476694e90da94aa008283a7de50d1dafd37beada623863f1901cb7fb","9dd56225cc2d8cb8fe5ceb0043ff386987637e12fecc6078896058a99deae284","2375ed4b439215aa3b6d0c6fd175c78a4384b30cb43cbadaecbf0a18954c98cb","7693b90b3075deaccafd5efb467bf9f2b747a3075be888652ef73e64396d8628","41231da15bb5e3e806a8395bd15c7befd2ec90f9f4e3c9d0ae1356bccb76dbb0","fccfef201d057cb407fa515311bd608549bab6c7b8adcf8f2df31f5d3b796478",{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true},"5f20d20b7607174caf1a6da9141aeb9f2142159ae2410ca30c7a0fccd1d19c99",{"version":"464762c6213566d072f1ced5e8e9a954785ec5e53883b7397198abb5ef5b8f71","affectsGlobalScope":true},"6387920dc3e18927335b086deec75bf8e50f879a5e273d32ee7bb7a55ba50572","9bba37424094688c4663c177a1379b229f919b8912889a472f32fdc5f08ddb4d","29a4be13b3a30d3e66667b75c58ec61fb2df8fa0422534fdee3cfb30c5dbf450","83366d901beda79d6eb37aaaf6ca248dcd88946302b2a7d975590783be51e88e","bf268a0aea37ad4ae3b7a9b58559190b6fc01ea16a31e35cd05817a0a60f895a","43ec77c369473e92e2ecebf0554a0fdaa9c256644a6070f28228dfcceec77351",{"version":"d7dad6db394a3d9f7b49755e4b610fbf8ed6eb0c9810ae5f1a119f6b5d76de45","affectsGlobalScope":true},"95ed02bacb4502c985b69742ec82a4576d4ff4a6620ecc91593f611d502ae546","bf755525c4e6f85a970b98c4755d98e8aa1b6dbd83a5d8fcc57d3d497351b936","dd67d2b5e4e8a182a38de8e69fb736945eaa4588e0909c14e01a14bd3cc1fd1e",{"version":"28084e15b63e6211769db2fe646d8bc5c4c6776321e0deffe2d12eefd52cb6b9","affectsGlobalScope":true},{"version":"aed37dabf86c99d6c8508700576ecede86688397bc12523541858705a0c737c2","affectsGlobalScope":true},"cc6ef5733d4ea6d2e06310a32dffd2c16418b467c5033d49cecc4f3a25de7497","94768454c3348b6ebe48e45fbad8c92e2bb7af4a35243edbe2b90823d0bd7f9a","0be79b3ff0f16b6c2f9bc8c4cc7097ea417d8d67f8267f7e1eec8e32b548c2ff","1c61ffa3a71b77363b30d19832c269ef62fba787f5610cac7254728d3b69ab2e","84da3c28344e621fd1d591f2c09e9595292d2b70018da28a553268ac122597d4","269929a24b2816343a178008ac9ae9248304d92a8ba8e233055e0ed6dbe6ef71","6e191fea1db6e9e4fa828259cf489e820ec9170effff57fb081a2f3295db4722","aed943465fbce1efe49ee16b5ea409050f15cd8eaf116f6fadb64ef0772e7d95","70d08483a67bf7050dbedace398ef3fee9f436fcd60517c97c4c1e22e3c6f3e8","c40fdf7b2e18df49ce0568e37f0292c12807a0748be79e272745e7216bed2606",{"version":"e933de8143e1d12dd51d89b398760fd5a9081896be366dad88a922d0b29f3c69","affectsGlobalScope":true},"4e228e78c1e9b0a75c70588d59288f63a6258e8b1fe4a67b0c53fe03461421d9","b38d55d08708c2410a3039687db70b4a5bfa69fc4845617c313b5a10d9c5c637","205d50c24359ead003dc537b9b65d2a64208dfdffe368f403cf9e0357831db9e","1265fddcd0c68be9d2a3b29805d0280484c961264dd95e0b675f7bd91f777e78",{"version":"a05e2d784c9be7051c4ac87a407c66d2106e23490c18c038bbd0712bde7602fd","affectsGlobalScope":true},{"version":"df90b9d0e9980762da8daf8adf6ffa0c853e76bfd269c377be0d07a9ad87acd2","affectsGlobalScope":true},"cf434b5c04792f62d6f4bdd5e2c8673f36e638e910333c172614d5def9b17f98","1d65d4798df9c2df008884035c41d3e67731f29db5ecb64cd7378797c7c53a2f","0faee6b555890a1cb106e2adc5d3ffd89545b1da894d474e9d436596d654998f","c6c01ea1c42508edf11a36d13b70f6e35774f74355ba5d358354d4a77cc67ea1","867f95abf1df444aab146b19847391fc2f922a55f6a970a27ed8226766cee29f",{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true},"b0297b09e607bec9698cac7cf55463d6731406efb1161ee4d448293b47397c84","175323e2a79a6076e0bada8a390d535a3ea817158bf1b1f46e31efca9028a0a2","7a10053aadc19335532a4d02756db4865974fd69bea5439ddcc5bfdf062d9476","4967529644e391115ca5592184d4b63980569adf60ee685f968fd59ab1557188","aed9e712a9b168345362e8f3a949f16c99ca1e05d21328f05735dfdbb24414ef","b04fe6922ed3db93afdbd49cdda8576aa75f744592fceea96fb0d5f32158c4f5","ed8d6c8de90fc2a4faaebc28e91f2469928738efd5208fb75ade0fa607e892b7","d7c52b198d680fe65b1a8d1b001f0173ffa2536ca2e7082431d726ce1f6714cd","c07f251e1c4e415a838e5498380b55cfea94f3513229de292d2aa85ae52fc3e9","0ed401424892d6bf294a5374efe512d6951b54a71e5dd0290c55b6d0d915f6f7","b945be6da6a3616ef3a250bfe223362b1c7c6872e775b0c4d82a1bf7a28ff902","beea49237dd7c7110fabf3c7509919c9cb9da841d847c53cac162dc3479e2f87","0f45f8a529c450d8f394106cc622bff79e44a1716e1ac9c3cc68b43f7ecf65ee","c624ce90b04c27ce4f318ba6330d39bde3d4e306f0f497ce78d4bda5ab8e22ca","9b8253aa5cb2c82d505f72afdbf96e83b15cc6b9a6f4fadbbbab46210d5f1977","86a8f52e4b1ac49155e889376bcfa8528a634c90c27fec65aa0e949f77b740c5","aab5dd41c1e2316cc0b42a7dd15684f8582d5a1d16c0516276a2a8a7d0fecd9c","59948226626ee210045296ba1fc6cb0fe748d1ff613204e08e7157ab6862dee7","ec3e54d8b713c170fdc8110a7e4a6a97513a7ab6b05ac9e1100cb064d2bb7349","43beb30ecb39a603fde4376554887310b0699f25f7f39c5c91e3147b51bb3a26","666b77d7f06f49da114b090a399abbfa66d5b6c01a3fd9dc4f063a52ace28507","31997714a93fbc570f52d47d6a8ebfb021a34a68ea9ba58bbb69cdec9565657e","6032e4262822160128e644de3fc4410bcd7517c2f137525fd2623d2bb23cb0d3","8bd5c9b1016629c144fd228983395b9dbf0676a576716bc3d316cab612c33cd5","2ed90bd3925b23aed8f859ffd0e885250be0424ca2b57e9866dabef152e1d6b7","93f6bd17d92dab9db7897e1430a5aeaa03bcf51623156213d8397710367a76ce","3f62b770a42e8c47c7008726f95aa383e69d97e85e680d237b99fcb0ee601dd8","5b84cfe78028c35c3bb89c042f18bf08d09da11e82d275c378ae4d07d8477e6c","980d21b0081cbf81774083b1e3a46f4bbdcd2b68858df0f66d7fad9c82bc34bc","68cc8d6fcc2f270d7108f02f3ebc59480a54615be3e09a47e14527f349e9d53e","3eb11dbf3489064a47a2e1cf9d261b1f100ef0b3b50ffca6c44dd99d6dd81ac1","b17f3bb7d8333479c7e45e5f3d876761b9bca58f97594eca3f6a944fd825e632","3c1f1236cce6d6e0c4e2c1b4371e6f72d7c14842ecd76a98ed0748ee5730c8f3","6d7f58d5ea72d7834946fd7104a734dc7d40661be8b2e1eaced1ddce3268ebaf","4c26222991e6c97d5a8f541d4f2c67585eda9e8b33cf9f52931b098045236e88","277983d414aa99d78655186c3ee1e1c38c302e336aff1d77b47fcdc39d8273fe","47383b45796d525a4039cd22d2840ac55a1ff03a43d027f7f867ba7314a9cf53","6548773b3abbc18de29176c2141f766d4e437e40596ee480447abf83575445ad","6ddd27af0436ce59dd4c1896e2bfdb2bdb2529847d078b83ce67a144dff05491","816264799aef3fd5a09a3b6c25217d5ec26a9dfc7465eac7d6073bcdc7d88f3f","4df0891b133884cd9ed752d31c7d0ec0a09234e9ed5394abffd3c660761598db","b603b62d3dcd31ef757dc7339b4fa8acdbca318b0fb9ac485f9a1351955615f9","e642bd47b75ad6b53cbf0dfd7ddfa0f120bd10193f0c58ec37d87b59bf604aca","be90b24d2ee6f875ce3aaa482e7c41a54278856b03d04212681c4032df62baf9","78f5ff400b3cb37e7b90eef1ff311253ed31c8cb66505e9828fad099bffde021","372c47090e1131305d163469a895ff2938f33fa73aad988df31cd31743f9efb6","71c67dc6987bdbd5599353f90009ff825dd7db0450ef9a0aee5bb0c574d18512","6f12403b5eca6ae7ca8e3efe3eeb9c683b06ce3e3844ccfd04098d83cd7e4957","282c535df88175d64d9df4550d2fd1176fd940c1c6822f1e7584003237f179d3","c3a4752cf103e4c6034d5bd449c8f9d5e7b352d22a5f8f9a41a8efb11646f9c2","11a9e38611ac3c77c74240c58b6bd64a0032128b29354e999650f1de1e034b1c","4ed103ca6fff9cb244f7c4b86d1eb28ce8069c32db720784329946731badb5bb","d738f282842970e058672663311c6875482ee36607c88b98ffb6604fba99cb2a","ec859cd8226aa623e41bbb47c249a55ee16dc1b8647359585244d57d3a5ed0c7","8891c6e959d253a66434ff5dc9ae46058fb3493e84b4ca39f710ef2d350656b1","c4463cf02535444dcbc3e67ecd29f1972490f74e49957d6fd4282a1013796ba6","0cb0a957ff02de0b25fd0f3f37130ca7f22d1e0dea256569c714c1f73c6791f8","2f5075dc512d51786b1ba3b1696565641dfaae3ac854f5f13d61fa12ef81a47e","ca3353cc82b1981f0d25d71d7432d583a6ef882ccdea82d65fbe49af37be51cb","50679a8e27aacf72f8c40bcab15d7ef5e83494089b4726b83eec4554344d5cdc","45351e0d51780b6f4088277a4457b9879506ee2720a887de232df0f1efcb33d8","5d697a4b315cc5bb3042ae869abffd10c3b0d7b182cda0e4c45d8819937e5796","563fa27fdaec8f195b84f71a7af0ef48d30d5cc830575db86da86a63a470c8e6","6ee58aa536dabb19b09bc036f1abe83feb51e13d63b23d30b2d0631a2de99b8f","8aceb205dcc6f814ad99635baf1e40b6e01d06d3fe27b72fd766c6d0b8c0c600","299567f84bfedd1468dca2755a829cb19e607a6811673788807dc8921e211bc9","795d9fb85aad92221504db74dd179b506bd189bba0c104426f7e7bb8a66ffee5","1311bc194e0a69fe61031e852c1c0b439e2a2a3d1d5e2d8ff795499b9f283459","4b7ce19369d7e7fae76720c2c6c7f671bf3fa0f7093edb864f1ac358ca7c456c","c972ef44deca1fa8fab465915ffa00f82e126aacf3dfc8979c03b1b066ce5bb6","30285a1011c6d6b52f3ba3abb0a984be8148c05cdefb8eb6eb562335a3991f35","8e7adb22c0adecf7464861fc58ae3fc617b41ffbd70c97aa8493dc0966a82273","755f3cd1d9c1b564cff090e3b0e29200ae55690a91b87cb9e7a64c2dbeb314d3","d6bb7e0a6877b7856c183bff13d09dd9ae599ea43c6f6b33d3d5f72a830ed460","f1b51ae93c762d7c43f559933cd4842dd870367e8d92e90704ffa685dd5b29a3","3f450762fd7c34ed545e738abccb0af6a703572a10521643cf8fc88e3724c99c","fcc8beef29f39f09b1d9c9f99c42f9fed605ab1c28d2a630185f732b9ba53763","d6e6620a30d582182acc3f0a992a0c311adc589f111096aea11ab83fc09a5ccc","6213b8f686f56beab22b59a0f468590fd3a4c5fa931236a017efeca91d7c9584","c451cec9a588b1f105a5ea2c6063d4fca112b9d70105cacdadda0e1ef67e9379","cb047832dc68f5a2c41c62c5e95ddcacbae3a8b034d40cd15319a8cb7f25104a","980336ccdfc3c08f3c3b201aa6662e6016e20f15847f8465b68f3e8e67b4665c","5a3493939995f46ff3d9073cd534fb8961c3bf4e08c71db27066ff03d906dea8","bb5a2ac327605ebebf831c469b05bd34a33a6a46ee8c1edd9f3310aad32cf6a1","bf5d041f2440b4a9391e2b5eb3b8d94cbf1e3b8ff4703b6539d4e65e758c8f37","8516469eb90e723b0eb03df1be098f7e6a4709f6f48fd4532868d20a0a934f6e","d60e9ab369a72d234aac49adbe2900d8ef1408a6ea4db552cf2a48c9d8d6a1bc","0ebb4698803f01e2e7df6acce572fff068f4a20c47221721dafd70a27e372831","03460a54d0e0481d1e11097f66ad43f054bc95efdafe5f81bbc7a82be181af75","4070c2f1c3434fcf84886e04d30d82cd650ee443e53b82b404b144175cf8741e","2cea9689efa8591732096235abe7f084fc29c92badd5b0897a5e876b77e71887","4ed4e504126014fee13aaef5e3fc140f2ff7031ff3a8b5386717905820ea2d09","8129a34006218a6f3cdc81bbd438d5429eb18b08b4338a26977ac3b4df129d75","30d2170e1a718b5035611af55e3618b4ba8f42f0749bb52ee593da6082c4e2ce","98ef38666d88ec9699a722053e07ede65d3042f693fe7ff8c786e53dbb6fd43b","a3b8b6be7620897d1e481e8650c980a210a138fceb6e710eaf95fd9dd0dfe94a","12c89d0e32758c120a569045f21cf5b77244f86792611ced8de7f86b37e77781","14bd47270e654c8eb3b1489fa8c095912ee62a0a29bb92743393203722347c53","3d9297165e67fd59d9821cc93a9808213e33c56a8ac1c4273171f6afaaa2d4d5","e7af7d288b89287ad031b19583c597fcd9f5edc0b0d579b7b492f06cf57e058c","92cb686a9ca5eb5dd7d5d8d43a3707194c1e91ea07a027b3bcb60b6011b24632","fab58e600970e66547644a44bc9918e3223aa2cbd9e8763cec004b2cfb48827e",{"version":"f3e418819a6765dc6715ab2a51771c798543815d8499e29a857229bbf74ff419","signature":"b146c2211fb74ff8f672aa026d3992562e1c9c0d282cc712708b740c8f4cfb1a"},{"version":"d320adcc9e016b24e5873a7efb081d684a7990fbe23fe49c1c5354ba89bd129b","signature":"56c727d4c937865b6e7b114f58aa30f7678d5a9d924c0adb42368c403efb337d"},{"version":"fd1051fabcbc5740a5b3db8582c0bfee17883217121619fd765fbdd171f5d068","signature":"e4a433dbb39db571df95fa9677c8dede9cc6e21eb91a5a23e89ce2725cbd97da"},"d021f18758b28bda32bdaf0a987e0804cec074a9a4cfab8232ed81d96e75dfae","4489c6a9fde8934733aa7df6f7911461ee6e9e4ad092736bd416f6b2cc20b2c6","2c8e55457aaf4902941dfdba4061935922e8ee6e120539c9801cd7b400fae050","8041cfce439ff29d339742389de04c136e3029d6b1817f07b2d7fcbfb7534990","670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","9d38964b57191567a14b396422c87488cecd48f405c642daa734159875ee81d9","069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","8c95f96ccd4be0674944077aec1e4f2cccd515ca06d4327562dd017250e7d3fc",{"version":"64d4b35c5456adf258d2cf56c341e203a073253f229ef3208fc0d5020253b241","affectsGlobalScope":true},"ee7d8894904b465b072be0d2e4b45cf6b887cdba16a467645c4e200982ece7ea","f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","bc3cba7b0af2d52e7425299aee518db479d44004eff6fbbd206d1ee7e5ec3fb5","afe73051ff6a03a9565cbd8ebb0e956ee3df5e913ad5c1ded64218aabfa3dcb5","035a5df183489c2e22f3cf59fc1ed2b043d27f357eecc0eb8d8e840059d44245","a4809f4d92317535e6b22b01019437030077a76fec1d93b9881c9ed4738fcc54","5f53fa0bd22096d2a78533f94e02c899143b8f0f9891a46965294ee8b91a9434","0d14fa22c41fdc7277e6f71473b20ebc07f40f00e38875142335d5b63cdfc9d2","d8aab31ba8e618cc3eea10b0945de81cb93b7e8150a013a482332263b9305322","462bccdf75fcafc1ae8c30400c9425e1a4681db5d605d1a0edb4f990a54d8094","5923d8facbac6ecf7c84739a5c701a57af94a6f6648d6229a6c768cf28f0f8cb","7adecb2c3238794c378d336a8182d4c3dd2c4fa6fa1785e2797a3db550edea62","dc12dc0e5aa06f4e1a7692149b78f89116af823b9e1f1e4eae140cd3e0e674e6","1bfc6565b90c8771615cd8cfcf9b36efc0275e5e83ac7d9181307e96eb495161","8a8a96898906f065f296665e411f51010b51372fa260d5373bf9f64356703190","7f82ef88bdb67d9a850dd1c7cd2d690f33e0f0acd208e3c9eba086f3670d4f73",{"version":"ccfd8774cd9b929f63ff7dcf657977eb0652e3547f1fcac1b3a1dc5db22d4d58","affectsGlobalScope":true},"d92dc90fecd2552db74d8dc3c6fb4db9145b2aa0efe2c127236ba035969068d4","96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","b8442e9db28157344d1bc5d8a5a256f1692de213f0c0ddeb84359834015a008c","458111fc89d11d2151277c822dfdc1a28fa5b6b2493cf942e37d4cd0a6ee5f22","da2b6356b84a40111aaecb18304ea4e4fcb43d70efb1c13ca7d7a906445ee0d3","187119ff4f9553676a884e296089e131e8cc01691c546273b1d0089c3533ce42","febf0b2de54781102b00f61653b21377390a048fbf5262718c91860d11ff34a6","6f294731b495c65ecf46a5694f0082954b961cf05463bea823f8014098eaffa0","0aaef8cded245bf5036a7a40b65622dd6c4da71f7a35343112edbe112b348a1e","00baffbe8a2f2e4875367479489b5d43b5fc1429ecb4a4cc98cfc3009095f52a","68a0d0c508e1b6d8d23a519a8a0a3303dc5baa4849ca049f21e5bad41945e3fc","3c92b6dfd43cc1c2485d9eba5ff0b74a19bb8725b692773ef1d66dac48cda4bd","b03afe4bec768ae333582915146f48b161e567a81b5ebc31c4d78af089770ac9","df996e25faa505f85aeb294d15ebe61b399cf1d1e49959cdfaf2cc0815c203f9","4f6a12044ee6f458db11964153830abbc499e73d065c51c329ec97407f4b13dd","8841e2aa774b89bd23302dede20663306dc1b9902431ac64b24be8b8d0e3f649","916be7d770b0ae0406be9486ac12eb9825f21514961dd050594c4b250617d5a8","254d9fb8c872d73d34594be8a200fd7311dbfa10a4116bfc465fba408052f2b3","d88a5e779faf033be3d52142a04fbe1cb96009868e3bbdd296b2bc6c59e06c0e","2ccea88888048bbfcacbc9531a5596ea48a3e7dcd0a25f531a81bb717903ba4f","5e379df3d61561c2ed7789b5995b9ba2143bbba21a905e2381e16efe7d1fa424","f07a137bbe2de7a122c37bfea00e761975fb264c49f18003d398d71b3fb35a5f","d8f7109e14f20eb735225a62fd3f8366da1a8349e90331cdad57f4b04caf6c5a","cf3d384d082b933d987c4e2fe7bfb8710adfd9dc8155190056ed6695a25a559e","9871b7ee672bc16c78833bdab3052615834b08375cb144e4d2cba74473f4a589","c863198dae89420f3c552b5a03da6ed6d0acfa3807a64772b895db624b0de707","8b03a5e327d7db67112ebbc93b4f744133eda2c1743dbb0a990c61a8007823ef","86c73f2ee1752bac8eeeece234fd05dfcf0637a4fbd8032e4f5f43102faa8eec","42fad1f540271e35ca37cecda12c4ce2eef27f0f5cf0f8dd761d723c744d3159","ff3743a5de32bee10906aff63d1de726f6a7fd6ee2da4b8229054dfa69de2c34","83acd370f7f84f203e71ebba33ba61b7f1291ca027d7f9a662c6307d74e4ac22","1445cec898f90bdd18b2949b9590b3c012f5b7e1804e6e329fb0fe053946d5ec","0e5318ec2275d8da858b541920d9306650ae6ac8012f0e872fe66eb50321a669","cf530297c3fb3a92ec9591dd4fa229d58b5981e45fe6702a0bd2bea53a5e59be","c1f6f7d08d42148ddfe164d36d7aba91f467dbcb3caa715966ff95f55048b3a4","f4e9bf9103191ef3b3612d3ec0044ca4044ca5be27711fe648ada06fad4bcc85","0c1ee27b8f6a00097c2d6d91a21ee4d096ab52c1e28350f6362542b55380059a","7677d5b0db9e020d3017720f853ba18f415219fb3a9597343b1b1012cfd699f7","bc1c6bc119c1784b1a2be6d9c47addec0d83ef0d52c8fbe1f14a51b4dfffc675","52cf2ce99c2a23de70225e252e9822a22b4e0adb82643ab0b710858810e00bf1","770625067bb27a20b9826255a8d47b6b5b0a2d3dfcbd21f89904c731f671ba77","d1ed6765f4d7906a05968fb5cd6d1db8afa14dbe512a4884e8ea5c0f5e142c80","799c0f1b07c092626cf1efd71d459997635911bb5f7fc1196efe449bba87e965","2a184e4462b9914a30b1b5c41cf80c6d3428f17b20d3afb711fff3f0644001fd","9eabde32a3aa5d80de34af2c2206cdc3ee094c6504a8d0c2d6d20c7c179503cc","397c8051b6cfcb48aa22656f0faca2553c5f56187262135162ee79d2b2f6c966","a8ead142e0c87dcd5dc130eba1f8eeed506b08952d905c47621dc2f583b1bff9","a02f10ea5f73130efca046429254a4e3c06b5475baecc8f7b99a0014731be8b3","c2576a4083232b0e2d9bd06875dd43d371dee2e090325a9eac0133fd5650c1cb","4c9a0564bb317349de6a24eb4efea8bb79898fa72ad63a1809165f5bd42970dd","f40ac11d8859092d20f953aae14ba967282c3bb056431a37fced1866ec7a2681","cc11e9e79d4746cc59e0e17473a59d6f104692fd0eeea1bdb2e206eabed83b03","b444a410d34fb5e98aa5ee2b381362044f4884652e8bc8a11c8fe14bbd85518e","c35808c1f5e16d2c571aa65067e3cb95afeff843b259ecfa2fc107a9519b5392","14d5dc055143e941c8743c6a21fa459f961cbc3deedf1bfe47b11587ca4b3ef5","a3ad4e1fc542751005267d50a6298e6765928c0c3a8dce1572f2ba6ca518661c","f237e7c97a3a89f4591afd49ecb3bd8d14f51a1c4adc8fcae3430febedff5eb6","3ffdfbec93b7aed71082af62b8c3e0cc71261cc68d796665faa1e91604fbae8f","662201f943ed45b1ad600d03a90dffe20841e725203ced8b708c91fcd7f9379a","c9ef74c64ed051ea5b958621e7fb853fe3b56e8787c1587aefc6ea988b3c7e79","2462ccfac5f3375794b861abaa81da380f1bbd9401de59ffa43119a0b644253d","34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","7d8ddf0f021c53099e34ee831a06c394d50371816caa98684812f089b4c6b3d4","7d2a0ba1297be385a89b5515b88cd31b4a1eeef5236f710166dc1b36b1741e1b","9d92b037978bb9525bc4b673ebddd443277542e010c0aef019c03a170ccdaa73","ab82804a14454734010dcdcd43f564ff7b0389bee4c5692eec76ff5b30d4cf66","bae8d023ef6b23df7da26f51cea44321f95817c190342a36882e93b80d07a960","ae271d475b632ce7b03fea6d9cf6da72439e57a109672671cbc79f54e1386938"],"options":{"composite":true,"declaration":true,"declarationMap":true,"emitDeclarationOnly":true,"esModuleInterop":true,"inlineSources":true,"module":1,"outDir":"./types","rootDir":"../src","sourceMap":true,"strict":true,"target":7},"fileIdsList":[[234],[92,128,129,130,145],[129,130,146,147],[128,129],[128,145,148,151],[128,148,151,152],[149,150,151,153,154],[128,151],[128,145,148,149,150,153],[128,136],[128],[92,128],[80,128],[132,133,134,135,136,137,138,139,140,141,142,143,144],[128,134,135],[128,134,136],[199],[199,200,201],[64],[67],[64,67],[65,66,67,68,69,70,71,72,73,74,75,156,159,160,161,162,163,164,165,166],[58,64,65],[67,73,75,155],[158],[67,68],[64,162],[194,195],[234,235,236,237,238],[234,236],[157],[241,242,243],[93,128],[246],[247],[258],[252,257],[261,263,264,265,266,267,268,269,270,271,272,273],[261,262,264,265,266,267,268,269,270,271,272,273],[262,263,264,265,266,267,268,269,270,271,272,273],[261,262,263,265,266,267,268,269,270,271,272,273],[261,262,263,264,266,267,268,269,270,271,272,273],[261,262,263,264,265,267,268,269,270,271,272,273],[261,262,263,264,265,266,268,269,270,271,272,273],[261,262,263,264,265,266,267,269,270,271,272,273],[261,262,263,264,265,266,267,268,270,271,272,273],[261,262,263,264,265,266,267,268,269,271,272,273],[261,262,263,264,265,266,267,268,269,270,272,273],[261,262,263,264,265,266,267,268,269,270,271,273],[261,262,263,264,265,266,267,268,269,270,271,272],[76],[79],[80,85,112],[81,92,93,100,109,120],[81,82,92,100],[83,121],[84,85,93,101],[85,109,117],[86,88,92,100],[87],[88,89],[92],[91,92],[79,92],[92,93,94,109,120],[92,93,94,109],[92,95,100,109,120],[92,93,95,96,100,109,117,120],[95,97,109,117,120],[76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127],[92,98],[99,120,125],[88,92,100,109],[101],[102],[79,103],[104,119,125],[105],[106],[92,107],[107,108,121,123],[80,92,109,110,111],[80,109,111],[109,110],[112],[113],[92,115,116],[115,116],[85,100,109,117],[118],[100,119],[80,95,106,120],[85,121],[109,122],[123],[124],[80,85,92,94,103,109,120,123,125],[109,126],[128,279],[282,321],[282,306,321],[321],[282],[282,307,321],[282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320],[307,321],[322],[325],[204],[204,215,216],[216,217,218],[179],[179,180,181,182,183],[168,169,170,171,172,173,174,175,176,177,178],[250,253],[250,253,254,255],[252],[249,256],[251],[57,59,60,61,62,63],[57,58],[59],[58,59],[57,59],[167,184,185,186],[185],[186],[56,185,186,187],[189],[189,190,193,197],[196],[167,191,192],[212,213,214],[211,212],[167,211,212],[167,204,211],[167,188,191,198,224,228,229,230,231],[232],[191,192,198,232],[167,204],[167,205],[205,206,207,208,209,210],[167,188,191,198,202,203,220,221],[220],[203,220,222,223],[167,198,215,219],[167,188,224,225],[128,167,188,224,225],[225,226,227],[167,224],[167,188,224,228],[191,232]],"referencedMap":[[236,1],[146,2],[148,3],[130,4],[152,5],[153,6],[149,6],[155,7],[150,6],[154,8],[151,9],[137,10],[134,11],[141,12],[135,10],[132,13],[145,14],[139,11],[136,15],[138,16],[204,12],[200,17],[201,17],[202,18],[65,19],[66,19],[68,20],[69,19],[70,19],[71,21],[67,19],[167,22],[75,23],[156,24],[159,25],[165,26],[166,27],[196,28],[239,29],[235,1],[237,30],[238,1],[192,11],[158,31],[244,32],[245,33],[247,34],[248,35],[259,36],[258,37],[262,38],[263,39],[261,40],[264,41],[265,42],[266,43],[267,44],[268,45],[269,46],[270,47],[271,48],[272,49],[273,50],[76,51],[77,51],[79,52],[80,53],[81,54],[82,55],[83,56],[84,57],[85,58],[86,59],[87,60],[88,61],[89,61],[90,62],[91,63],[92,64],[93,65],[94,66],[95,67],[96,68],[97,69],[128,70],[98,71],[99,72],[100,73],[101,74],[102,75],[103,76],[104,77],[105,78],[106,79],[107,80],[108,81],[109,82],[111,83],[110,84],[112,85],[113,86],[115,87],[116,88],[117,89],[118,90],[119,91],[120,92],[121,93],[122,94],[123,95],[124,96],[125,97],[126,98],[276,11],[280,99],[281,11],[306,100],[307,101],[282,102],[285,102],[304,100],[305,100],[295,100],[294,103],[292,100],[287,100],[300,100],[298,100],[302,100],[286,100],[299,100],[303,100],[288,100],[289,100],[301,100],[283,100],[290,100],[291,100],[293,100],[297,100],[308,104],[296,100],[284,100],[321,105],[315,104],[317,106],[316,104],[309,104],[310,104],[312,104],[314,104],[318,106],[319,106],[311,106],[313,106],[323,107],[326,108],[216,109],[217,110],[218,110],[219,111],[175,112],[177,112],[176,112],[174,112],[184,113],[179,114],[170,112],[171,112],[172,112],[173,112],[254,115],[256,116],[255,115],[253,117],[257,118],[252,119],[64,120],[59,121],[60,122],[61,122],[62,123],[63,123],[58,124],[187,125],[186,126],[185,127],[188,128],[190,129],[198,130],[197,131],[193,132],[215,133],[213,134],[214,135],[212,136],[232,137],[230,138],[231,139],[233,138],[205,140],[206,141],[207,141],[209,141],[211,142],[210,141],[222,143],[221,144],[223,144],[224,145],[220,146],[226,147],[227,148],[228,149],[225,150]],"exportedModulesMap":[[236,1],[146,2],[148,3],[130,4],[152,5],[153,6],[149,6],[155,7],[150,6],[154,8],[151,9],[137,10],[134,11],[141,12],[135,10],[132,13],[145,14],[139,11],[136,15],[138,16],[204,12],[200,17],[201,17],[202,18],[65,19],[66,19],[68,20],[69,19],[70,19],[71,21],[67,19],[167,22],[75,23],[156,24],[159,25],[165,26],[166,27],[196,28],[239,29],[235,1],[237,30],[238,1],[192,11],[158,31],[244,32],[245,33],[247,34],[248,35],[259,36],[258,37],[262,38],[263,39],[261,40],[264,41],[265,42],[266,43],[267,44],[268,45],[269,46],[270,47],[271,48],[272,49],[273,50],[76,51],[77,51],[79,52],[80,53],[81,54],[82,55],[83,56],[84,57],[85,58],[86,59],[87,60],[88,61],[89,61],[90,62],[91,63],[92,64],[93,65],[94,66],[95,67],[96,68],[97,69],[128,70],[98,71],[99,72],[100,73],[101,74],[102,75],[103,76],[104,77],[105,78],[106,79],[107,80],[108,81],[109,82],[111,83],[110,84],[112,85],[113,86],[115,87],[116,88],[117,89],[118,90],[119,91],[120,92],[121,93],[122,94],[123,95],[124,96],[125,97],[126,98],[276,11],[280,99],[281,11],[306,100],[307,101],[282,102],[285,102],[304,100],[305,100],[295,100],[294,103],[292,100],[287,100],[300,100],[298,100],[302,100],[286,100],[299,100],[303,100],[288,100],[289,100],[301,100],[283,100],[290,100],[291,100],[293,100],[297,100],[308,104],[296,100],[284,100],[321,105],[315,104],[317,106],[316,104],[309,104],[310,104],[312,104],[314,104],[318,106],[319,106],[311,106],[313,106],[323,107],[326,108],[216,109],[217,110],[218,110],[219,111],[175,112],[177,112],[176,112],[174,112],[184,113],[179,114],[170,112],[171,112],[172,112],[173,112],[254,115],[256,116],[255,115],[253,117],[257,118],[252,119],[64,120],[59,121],[60,122],[61,122],[62,123],[63,123],[58,124],[187,125],[186,126],[185,127],[188,128],[190,129],[198,130],[197,131],[193,132],[215,133],[213,134],[214,135],[212,136],[232,151],[230,138],[231,152],[233,138],[205,140],[206,141],[207,141],[209,141],[211,142],[210,141],[222,143],[221,144],[223,144],[224,145],[220,146],[226,147],[227,148],[228,149],[225,150]],"semanticDiagnosticsPerFile":[236,234,146,129,148,130,147,152,153,149,155,150,154,151,137,134,141,135,132,140,145,142,143,144,139,136,133,138,191,204,200,201,202,199,65,66,68,69,70,71,72,73,74,67,167,75,156,159,160,161,162,163,164,165,166,194,196,195,239,235,237,238,192,158,240,241,244,242,245,246,247,248,259,258,243,260,262,263,261,264,265,266,267,268,269,270,271,272,273,274,157,76,77,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,78,127,95,96,97,128,98,99,100,101,102,103,104,105,106,107,108,109,111,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,275,276,277,278,280,279,281,306,307,282,285,304,305,295,294,292,287,300,298,302,286,299,303,288,289,301,283,290,291,293,297,308,296,284,321,320,315,317,316,309,310,312,314,318,319,311,313,323,322,324,229,325,326,131,249,216,217,218,219,178,175,177,176,174,184,179,183,180,182,181,170,171,172,168,169,173,250,254,256,255,253,257,252,251,57,64,59,60,61,62,63,58,8,10,9,2,11,12,13,14,15,16,17,18,3,4,22,19,20,21,23,24,25,5,26,27,28,29,6,33,30,31,32,34,7,35,40,41,36,37,38,39,1,42,56,187,186,185,188,190,198,197,189,193,215,213,214,212,232,230,231,233,205,206,207,208,209,211,210,222,203,221,223,224,220,226,227,228,225,47,48,49,50,51,52,43,53,54,55,44,45,46],"latestChangedDtsFile":"./types/index.d.ts"},"version":"4.9.5"} +\ No newline at end of file ++{"program":{"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../../types/eth-ens-namehash.d.ts","../../../types/ethereum-ens-network-map.d.ts","../../../types/global.d.ts","../../../types/single-call-balance-checker-abi.d.ts","../../../types/@metamask/contract-metadata.d.ts","../../../types/@metamask/eth-hd-keyring.d.ts","../../../types/@metamask/eth-simple-keyring.d.ts","../../../types/@metamask/ethjs-provider-http.d.ts","../../../types/@metamask/ethjs-unit.d.ts","../../../types/@metamask/metamask-eth-abis.d.ts","../../../types/eth-json-rpc-infura/src/createprovider.d.ts","../../../types/eth-phishing-detect/src/config.json.d.ts","../../../types/eth-phishing-detect/src/detector.d.ts","../../base-controller/dist/types/basecontrollerv1.d.ts","../../../node_modules/superstruct/dist/error.d.ts","../../../node_modules/superstruct/dist/utils.d.ts","../../../node_modules/superstruct/dist/struct.d.ts","../../../node_modules/superstruct/dist/structs/coercions.d.ts","../../../node_modules/superstruct/dist/structs/refinements.d.ts","../../../node_modules/superstruct/dist/structs/types.d.ts","../../../node_modules/superstruct/dist/structs/utilities.d.ts","../../../node_modules/superstruct/dist/index.d.ts","../../../node_modules/@metamask/utils/dist/types/assert.d.ts","../../../node_modules/@metamask/utils/dist/types/base64.d.ts","../../../node_modules/@metamask/utils/dist/types/hex.d.ts","../../../node_modules/@metamask/utils/dist/types/bytes.d.ts","../../../node_modules/@metamask/utils/dist/types/caip-types.d.ts","../../../node_modules/@metamask/utils/dist/types/checksum.d.ts","../../../node_modules/@metamask/utils/dist/types/coercers.d.ts","../../../node_modules/@metamask/utils/dist/types/collections.d.ts","../../../node_modules/@metamask/utils/dist/types/encryption-types.d.ts","../../../node_modules/@metamask/utils/dist/types/errors.d.ts","../../../node_modules/@metamask/utils/dist/types/json.d.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/dom-events.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/globals.global.d.ts","../../../node_modules/@types/node/index.d.ts","../../../node_modules/@ethereumjs/common/dist/enums.d.ts","../../../node_modules/@ethereumjs/common/dist/types.d.ts","../../../node_modules/buffer/index.d.ts","../../../node_modules/@ethereumjs/util/dist/constants.d.ts","../../../node_modules/@ethereumjs/util/dist/units.d.ts","../../../node_modules/@ethereumjs/util/dist/address.d.ts","../../../node_modules/@ethereumjs/util/dist/bytes.d.ts","../../../node_modules/@ethereumjs/util/dist/types.d.ts","../../../node_modules/@ethereumjs/util/dist/account.d.ts","../../../node_modules/@ethereumjs/util/dist/withdrawal.d.ts","../../../node_modules/@ethereumjs/util/dist/signature.d.ts","../../../node_modules/@ethereumjs/util/dist/encoding.d.ts","../../../node_modules/@ethereumjs/util/dist/asynceventemitter.d.ts","../../../node_modules/@ethereumjs/util/dist/internal.d.ts","../../../node_modules/@ethereumjs/util/dist/lock.d.ts","../../../node_modules/@ethereumjs/util/dist/provider.d.ts","../../../node_modules/@ethereumjs/util/dist/index.d.ts","../../../node_modules/@ethereumjs/common/dist/common.d.ts","../../../node_modules/@ethereumjs/common/dist/utils.d.ts","../../../node_modules/@ethereumjs/common/dist/index.d.ts","../../../node_modules/@ethereumjs/tx/dist/eip2930transaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/legacytransaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/types.d.ts","../../../node_modules/@ethereumjs/tx/dist/basetransaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/eip1559transaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/transactionfactory.d.ts","../../../node_modules/@ethereumjs/tx/dist/index.d.ts","../../../node_modules/@metamask/utils/dist/types/keyring.d.ts","../../../node_modules/@types/ms/index.d.ts","../../../node_modules/@types/debug/index.d.ts","../../../node_modules/@metamask/utils/dist/types/logging.d.ts","../../../node_modules/@metamask/utils/dist/types/misc.d.ts","../../../node_modules/@metamask/utils/dist/types/number.d.ts","../../../node_modules/@metamask/utils/dist/types/opaque.d.ts","../../../node_modules/@metamask/utils/dist/types/promise.d.ts","../../../node_modules/@metamask/utils/dist/types/time.d.ts","../../../node_modules/@metamask/utils/dist/types/transaction-types.d.ts","../../../node_modules/@metamask/utils/dist/types/versions.d.ts","../../../node_modules/@metamask/utils/dist/types/index.d.ts","../../../node_modules/immer/dist/utils/env.d.ts","../../../node_modules/immer/dist/utils/errors.d.ts","../../../node_modules/immer/dist/types/types-external.d.ts","../../../node_modules/immer/dist/types/types-internal.d.ts","../../../node_modules/immer/dist/utils/common.d.ts","../../../node_modules/immer/dist/utils/plugins.d.ts","../../../node_modules/immer/dist/core/scope.d.ts","../../../node_modules/immer/dist/core/finalize.d.ts","../../../node_modules/immer/dist/core/proxy.d.ts","../../../node_modules/immer/dist/core/immerclass.d.ts","../../../node_modules/immer/dist/core/current.d.ts","../../../node_modules/immer/dist/internal.d.ts","../../../node_modules/immer/dist/plugins/es5.d.ts","../../../node_modules/immer/dist/plugins/patches.d.ts","../../../node_modules/immer/dist/plugins/mapset.d.ts","../../../node_modules/immer/dist/plugins/all.d.ts","../../../node_modules/immer/dist/immer.d.ts","../../base-controller/dist/types/restrictedcontrollermessenger.d.ts","../../base-controller/dist/types/controllermessenger.d.ts","../../base-controller/dist/types/basecontrollerv2.d.ts","../../base-controller/dist/types/index.d.ts","../../controller-utils/dist/types/types.d.ts","../../controller-utils/dist/types/constants.d.ts","../../../node_modules/@metamask/eth-query/index.d.ts","../../../node_modules/@types/bn.js/index.d.ts","../../controller-utils/dist/types/util.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/abnf.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/utils.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/parsers.d.ts","../../controller-utils/dist/types/siwe.d.ts","../../controller-utils/dist/types/index.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/types.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/createeventemitterproxy.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/createswappableproxy.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/index.d.ts","../../network-controller/dist/types/constants.d.ts","../../../node_modules/@metamask/safe-event-emitter/dist/cjs/index.d.ts","../../json-rpc-engine/dist/types/jsonrpcengine.d.ts","../../json-rpc-engine/dist/types/createasyncmiddleware.d.ts","../../json-rpc-engine/dist/types/createscaffoldmiddleware.d.ts","../../json-rpc-engine/dist/types/getuniqueid.d.ts","../../json-rpc-engine/dist/types/idremapmiddleware.d.ts","../../json-rpc-engine/dist/types/mergemiddleware.d.ts","../../json-rpc-engine/dist/types/index.d.ts","../../eth-json-rpc-provider/dist/types/safe-event-emitter-provider.d.ts","../../eth-json-rpc-provider/dist/types/provider-from-engine.d.ts","../../eth-json-rpc-provider/dist/types/provider-from-middleware.d.ts","../../eth-json-rpc-provider/dist/types/index.d.ts","../../../node_modules/eth-block-tracker/dist/blocktracker.d.ts","../../../node_modules/eth-block-tracker/dist/pollingblocktracker.d.ts","../../../node_modules/eth-block-tracker/dist/subscribeblocktracker.d.ts","../../../node_modules/eth-block-tracker/dist/index.d.ts","../../network-controller/dist/types/types.d.ts","../../network-controller/dist/types/create-auto-managed-network-client.d.ts","../../network-controller/dist/types/networkcontroller.d.ts","../../network-controller/dist/types/create-network-client.d.ts","../../network-controller/dist/types/index.d.ts","../../polling-controller/dist/types/types.d.ts","../../polling-controller/dist/types/blocktrackerpollingcontroller.d.ts","../../polling-controller/dist/types/staticintervalpollingcontroller.d.ts","../../polling-controller/dist/types/index.d.ts","../../../node_modules/@types/uuid/index.d.ts","../src/determinegasfeecalculations.ts","../src/gas-util.ts","../src/gasfeecontroller.ts","../src/index.ts","../../../node_modules/@babel/types/lib/index.d.ts","../../../node_modules/@types/babel__generator/index.d.ts","../../../node_modules/@babel/parser/typings/babel-parser.d.ts","../../../node_modules/@types/babel__template/index.d.ts","../../../node_modules/@types/babel__traverse/index.d.ts","../../../node_modules/@types/babel__core/index.d.ts","../../../node_modules/@types/deep-freeze-strict/index.d.ts","../../../node_modules/@types/eslint/helpers.d.ts","../../../node_modules/@types/estree/index.d.ts","../../../node_modules/@types/json-schema/index.d.ts","../../../node_modules/@types/eslint/index.d.ts","../../../node_modules/@types/graceful-fs/index.d.ts","../../../node_modules/@types/istanbul-lib-coverage/index.d.ts","../../../node_modules/@types/istanbul-lib-report/index.d.ts","../../../node_modules/@types/istanbul-reports/index.d.ts","../../../node_modules/chalk/index.d.ts","../../../node_modules/jest-diff/build/cleanupsemantic.d.ts","../../../node_modules/pretty-format/build/types.d.ts","../../../node_modules/pretty-format/build/index.d.ts","../../../node_modules/jest-diff/build/types.d.ts","../../../node_modules/jest-diff/build/difflines.d.ts","../../../node_modules/jest-diff/build/printdiffs.d.ts","../../../node_modules/jest-diff/build/index.d.ts","../../../node_modules/jest-matcher-utils/build/index.d.ts","../../../node_modules/@types/jest/index.d.ts","../../../node_modules/@types/jest-when/index.d.ts","../../../node_modules/@types/json5/index.d.ts","../../../node_modules/@types/lodash/common/common.d.ts","../../../node_modules/@types/lodash/common/array.d.ts","../../../node_modules/@types/lodash/common/collection.d.ts","../../../node_modules/@types/lodash/common/date.d.ts","../../../node_modules/@types/lodash/common/function.d.ts","../../../node_modules/@types/lodash/common/lang.d.ts","../../../node_modules/@types/lodash/common/math.d.ts","../../../node_modules/@types/lodash/common/number.d.ts","../../../node_modules/@types/lodash/common/object.d.ts","../../../node_modules/@types/lodash/common/seq.d.ts","../../../node_modules/@types/lodash/common/string.d.ts","../../../node_modules/@types/lodash/common/util.d.ts","../../../node_modules/@types/lodash/index.d.ts","../../../node_modules/@types/minimatch/index.d.ts","../../../node_modules/@types/parse-json/index.d.ts","../../../node_modules/@types/pbkdf2/index.d.ts","../../../node_modules/@types/prettier/index.d.ts","../../../node_modules/@types/punycode/index.d.ts","../../../node_modules/@types/readable-stream/node_modules/safe-buffer/index.d.ts","../../../node_modules/@types/readable-stream/index.d.ts","../../../node_modules/@types/secp256k1/index.d.ts","../../../node_modules/@types/semver/classes/semver.d.ts","../../../node_modules/@types/semver/functions/parse.d.ts","../../../node_modules/@types/semver/functions/valid.d.ts","../../../node_modules/@types/semver/functions/clean.d.ts","../../../node_modules/@types/semver/functions/inc.d.ts","../../../node_modules/@types/semver/functions/diff.d.ts","../../../node_modules/@types/semver/functions/major.d.ts","../../../node_modules/@types/semver/functions/minor.d.ts","../../../node_modules/@types/semver/functions/patch.d.ts","../../../node_modules/@types/semver/functions/prerelease.d.ts","../../../node_modules/@types/semver/functions/compare.d.ts","../../../node_modules/@types/semver/functions/rcompare.d.ts","../../../node_modules/@types/semver/functions/compare-loose.d.ts","../../../node_modules/@types/semver/functions/compare-build.d.ts","../../../node_modules/@types/semver/functions/sort.d.ts","../../../node_modules/@types/semver/functions/rsort.d.ts","../../../node_modules/@types/semver/functions/gt.d.ts","../../../node_modules/@types/semver/functions/lt.d.ts","../../../node_modules/@types/semver/functions/eq.d.ts","../../../node_modules/@types/semver/functions/neq.d.ts","../../../node_modules/@types/semver/functions/gte.d.ts","../../../node_modules/@types/semver/functions/lte.d.ts","../../../node_modules/@types/semver/functions/cmp.d.ts","../../../node_modules/@types/semver/functions/coerce.d.ts","../../../node_modules/@types/semver/classes/comparator.d.ts","../../../node_modules/@types/semver/classes/range.d.ts","../../../node_modules/@types/semver/functions/satisfies.d.ts","../../../node_modules/@types/semver/ranges/max-satisfying.d.ts","../../../node_modules/@types/semver/ranges/min-satisfying.d.ts","../../../node_modules/@types/semver/ranges/to-comparators.d.ts","../../../node_modules/@types/semver/ranges/min-version.d.ts","../../../node_modules/@types/semver/ranges/valid.d.ts","../../../node_modules/@types/semver/ranges/outside.d.ts","../../../node_modules/@types/semver/ranges/gtr.d.ts","../../../node_modules/@types/semver/ranges/ltr.d.ts","../../../node_modules/@types/semver/ranges/intersects.d.ts","../../../node_modules/@types/semver/ranges/simplify.d.ts","../../../node_modules/@types/semver/ranges/subset.d.ts","../../../node_modules/@types/semver/internals/identifiers.d.ts","../../../node_modules/@types/semver/index.d.ts","../../../node_modules/@types/sinonjs__fake-timers/index.d.ts","../../../node_modules/@types/sinon/index.d.ts","../../../node_modules/@types/stack-utils/index.d.ts","../../../node_modules/@types/yargs-parser/index.d.ts","../../../node_modules/@types/yargs/index.d.ts"],"fileInfos":[{"version":"8730f4bf322026ff5229336391a18bcaa1f94d4f82416c8b2f3954e2ccaae2ba","affectsGlobalScope":true},"dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6","7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467","8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9","5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06","4b421cbfb3a38a27c279dec1e9112c3d1da296f77a1a85ddadf7e7a425d45d18","1fc5ab7a764205c68fa10d381b08417795fc73111d6dd16b5b1ed36badb743d9",{"version":"3aafcb693fe5b5c3bd277bd4c3a617b53db474fe498fc5df067c5603b1eebde7","affectsGlobalScope":true},{"version":"adb996790133eb33b33aadb9c09f15c2c575e71fb57a62de8bf74dbf59ec7dfb","affectsGlobalScope":true},{"version":"8cc8c5a3bac513368b0157f3d8b31cfdcfe78b56d3724f30f80ed9715e404af8","affectsGlobalScope":true},{"version":"cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a","affectsGlobalScope":true},{"version":"c5c05907c02476e4bde6b7e76a79ffcd948aedd14b6a8f56e4674221b0417398","affectsGlobalScope":true},{"version":"5f406584aef28a331c36523df688ca3650288d14f39c5d2e555c95f0d2ff8f6f","affectsGlobalScope":true},{"version":"22f230e544b35349cfb3bd9110b6ef37b41c6d6c43c3314a31bd0d9652fcec72","affectsGlobalScope":true},{"version":"7ea0b55f6b315cf9ac2ad622b0a7813315bb6e97bf4bb3fbf8f8affbca7dc695","affectsGlobalScope":true},{"version":"3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93","affectsGlobalScope":true},{"version":"eb26de841c52236d8222f87e9e6a235332e0788af8c87a71e9e210314300410a","affectsGlobalScope":true},{"version":"3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006","affectsGlobalScope":true},{"version":"17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a","affectsGlobalScope":true},{"version":"7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98","affectsGlobalScope":true},{"version":"6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577","affectsGlobalScope":true},{"version":"81cac4cbc92c0c839c70f8ffb94eb61e2d32dc1c3cf6d95844ca099463cf37ea","affectsGlobalScope":true},{"version":"b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e","affectsGlobalScope":true},{"version":"0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a","affectsGlobalScope":true},{"version":"da233fc1c8a377ba9e0bed690a73c290d843c2c3d23a7bd7ec5cd3d7d73ba1e0","affectsGlobalScope":true},{"version":"d154ea5bb7f7f9001ed9153e876b2d5b8f5c2bb9ec02b3ae0d239ec769f1f2ae","affectsGlobalScope":true},{"version":"bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c","affectsGlobalScope":true},{"version":"c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8","affectsGlobalScope":true},{"version":"9d57b2b5d15838ed094aa9ff1299eecef40b190722eb619bac4616657a05f951","affectsGlobalScope":true},{"version":"6c51b5dd26a2c31dbf37f00cfc32b2aa6a92e19c995aefb5b97a3a64f1ac99de","affectsGlobalScope":true},{"version":"6e7997ef61de3132e4d4b2250e75343f487903ddf5370e7ce33cf1b9db9a63ed","affectsGlobalScope":true},{"version":"2ad234885a4240522efccd77de6c7d99eecf9b4de0914adb9a35c0c22433f993","affectsGlobalScope":true},{"version":"5e5e095c4470c8bab227dbbc61374878ecead104c74ab9960d3adcccfee23205","affectsGlobalScope":true},{"version":"09aa50414b80c023553090e2f53827f007a301bc34b0495bfb2c3c08ab9ad1eb","affectsGlobalScope":true},{"version":"d7f680a43f8cd12a6b6122c07c54ba40952b0c8aa140dcfcf32eb9e6cb028596","affectsGlobalScope":true},{"version":"3787b83e297de7c315d55d4a7c546ae28e5f6c0a361b7a1dcec1f1f50a54ef11","affectsGlobalScope":true},{"version":"e7e8e1d368290e9295ef18ca23f405cf40d5456fa9f20db6373a61ca45f75f40","affectsGlobalScope":true},{"version":"faf0221ae0465363c842ce6aa8a0cbda5d9296940a8e26c86e04cc4081eea21e","affectsGlobalScope":true},{"version":"06393d13ea207a1bfe08ec8d7be562549c5e2da8983f2ee074e00002629d1871","affectsGlobalScope":true},{"version":"2768ef564cfc0689a1b76106c421a2909bdff0acbe87da010785adab80efdd5c","affectsGlobalScope":true},{"version":"b248e32ca52e8f5571390a4142558ae4f203ae2f94d5bac38a3084d529ef4e58","affectsGlobalScope":true},{"version":"52d1bb7ab7a3306fd0375c8bff560feed26ed676a5b0457fa8027b563aecb9a4","affectsGlobalScope":true},"70bbfaec021ac4a0c805374225b55d70887f987df8b8dd7711d79464bb7b4385","869089d60b67219f63e6aca810284c89bae1b384b5cbc7ce64e53d82ad223ed5",{"version":"18338b6a4b920ec7d49b4ffafcbf0fa8a86b4bfd432966efd722dab611157cf4","affectsGlobalScope":true},"62a0875a0397b35a2364f1d401c0ce17975dfa4d47bf6844de858ae04da349f9","ee7491d0318d1fafcba97d5b72b450eb52671570f7a4ecd9e8898d40eaae9472","e3e7d217d89b380c1f34395eadc9289542851b0f0a64007dfe1fb7cf7423d24e","fd79909e93b4d50fd0ed9f3d39ddf8ba0653290bac25c295aac49f6befbd081b","345a9cc2945406f53051cd0e9b51f82e1e53929848eab046fdda91ee8aa7da31","9debe2de883da37a914e5e784a7be54c201b8f1d783822ad6f443ff409a5ea21","dee5d5c5440cda1f3668f11809a5503c30db0476ad117dd450f7ba5a45300e8f","f5e396c1424c391078c866d6f84afe0b4d2f7f85a160b9c756cd63b5b1775d93","5caa6f4fff16066d377d4e254f6c34c16540da3809cd66cd626a303bc33c419f","730d055528bdf12c8524870bb33d237991be9084c57634e56e5d8075f6605e02","75b22c74010ba649de1a1676a4c4b8b5bb4294fecd05089e2094429b16d7840c","5615ccf831db2ffc82145243081ebdb60ea8e1005ee8f975d1c0c1401a9c894e","38682ed3630bb6ecdace80d5a9adc811fc20a419f1940446e306c3a020d083b9","cc182e6e4f691cd6f7bf7cb491247a4c7818f9f1cb2db1d45c65ff906e3f741b","a50599c08934a62f11657bdbe0dc929ab66da1b1f09974408fd9a33ec1bb8060","5a20e7d6c630b91be15e9b837853173829d00273197481dc8d3e94df61105a71","8d478048d71cc16f806d4b71b252ecb67c7444ccf4f4b09b29a312712184f859","e0eda929c6b9b628cdeb0e54cd3582cb97e64f28aab34612fc1431c545899584","9df4662ca3dbc2522bc115833ee04faa1afbb4e249a85ef4a0a09c621346bd08","b25d9065cf1c1f537a140bbc508e953ed2262f77134574c432d206ff36f4bdbf","1b103313097041aa9cd705a682c652f08613cb5cf8663321061c0902f845e81c","68ccec8662818911d8a12b8ed028bc5729fb4f1d34793c4701265ba60bc73cf4","5f85b8b79dc4d36af672c035b2beb71545de63a5d60bccbeee64c260941672ab","b3d48529ae61dc27d0bfbfa2cb3e0dff8189644bd155bdf5df1e8e14669f7043","40fe4b689225816b31fe5794c0fbf3534568819709e40295ead998a2bc1ab237","f65b5e33b9ad545a1eebbd6afe857314725ad42aaf069913e33f928ab3e4990a","fb6f2a87beb7fb1f4c2b762d0c76a9459fc91f557231569b0ee21399e22aa13d","31c858dc85996fac4b7fa944e1016d5c72f514930a72357ab5001097bf6511c7","3de30a871b3340be8b679c52aa12f90dd1c8c60874517be58968fdbcc4d79445","6fd985bd31eaf77542625306fb0404d32bff978990f0a06428e5f0b9a3b58109","5b3cd03ae354ea96eff1f74d7c410fe4852e6382227e8b0ecf87ab5e3a5bbcd4","7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419",{"version":"056097110efd16869ec118cedb44ecbac9a019576eee808d61304ca6d5cb2cbe","affectsGlobalScope":true},"f51b4042a3ac86f1f707500a9768f88d0b0c1fc3f3e45a73333283dea720cdc6",{"version":"6fb8358e10ed92a7f515b7d79da3904c955a3ffd4e14aa9df6f0ea113041f1cf","affectsGlobalScope":true},"45c831238c6dac21c72da5f335747736a56a3847192bf03c84b958a7e9ec93e2","661a11d16ad2e3543a77c53bcd4017ee9a450f47ab7def3ab493a86eae4d550c",{"version":"8cdc646cec7819581ef343b83855b1bfe4fe674f2c84f4fb8dc90d82fb56bd3a","affectsGlobalScope":true},"a40826e8476694e90da94aa008283a7de50d1dafd37beada623863f1901cb7fb","9dd56225cc2d8cb8fe5ceb0043ff386987637e12fecc6078896058a99deae284","2375ed4b439215aa3b6d0c6fd175c78a4384b30cb43cbadaecbf0a18954c98cb","7693b90b3075deaccafd5efb467bf9f2b747a3075be888652ef73e64396d8628","41231da15bb5e3e806a8395bd15c7befd2ec90f9f4e3c9d0ae1356bccb76dbb0","fccfef201d057cb407fa515311bd608549bab6c7b8adcf8f2df31f5d3b796478",{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true},"5f20d20b7607174caf1a6da9141aeb9f2142159ae2410ca30c7a0fccd1d19c99",{"version":"464762c6213566d072f1ced5e8e9a954785ec5e53883b7397198abb5ef5b8f71","affectsGlobalScope":true},"6387920dc3e18927335b086deec75bf8e50f879a5e273d32ee7bb7a55ba50572","9bba37424094688c4663c177a1379b229f919b8912889a472f32fdc5f08ddb4d","29a4be13b3a30d3e66667b75c58ec61fb2df8fa0422534fdee3cfb30c5dbf450","83366d901beda79d6eb37aaaf6ca248dcd88946302b2a7d975590783be51e88e","bf268a0aea37ad4ae3b7a9b58559190b6fc01ea16a31e35cd05817a0a60f895a","43ec77c369473e92e2ecebf0554a0fdaa9c256644a6070f28228dfcceec77351",{"version":"d7dad6db394a3d9f7b49755e4b610fbf8ed6eb0c9810ae5f1a119f6b5d76de45","affectsGlobalScope":true},"95ed02bacb4502c985b69742ec82a4576d4ff4a6620ecc91593f611d502ae546","bf755525c4e6f85a970b98c4755d98e8aa1b6dbd83a5d8fcc57d3d497351b936","dd67d2b5e4e8a182a38de8e69fb736945eaa4588e0909c14e01a14bd3cc1fd1e",{"version":"28084e15b63e6211769db2fe646d8bc5c4c6776321e0deffe2d12eefd52cb6b9","affectsGlobalScope":true},{"version":"aed37dabf86c99d6c8508700576ecede86688397bc12523541858705a0c737c2","affectsGlobalScope":true},"cc6ef5733d4ea6d2e06310a32dffd2c16418b467c5033d49cecc4f3a25de7497","94768454c3348b6ebe48e45fbad8c92e2bb7af4a35243edbe2b90823d0bd7f9a","0be79b3ff0f16b6c2f9bc8c4cc7097ea417d8d67f8267f7e1eec8e32b548c2ff","1c61ffa3a71b77363b30d19832c269ef62fba787f5610cac7254728d3b69ab2e","84da3c28344e621fd1d591f2c09e9595292d2b70018da28a553268ac122597d4","269929a24b2816343a178008ac9ae9248304d92a8ba8e233055e0ed6dbe6ef71","6e191fea1db6e9e4fa828259cf489e820ec9170effff57fb081a2f3295db4722","aed943465fbce1efe49ee16b5ea409050f15cd8eaf116f6fadb64ef0772e7d95","70d08483a67bf7050dbedace398ef3fee9f436fcd60517c97c4c1e22e3c6f3e8","c40fdf7b2e18df49ce0568e37f0292c12807a0748be79e272745e7216bed2606",{"version":"e933de8143e1d12dd51d89b398760fd5a9081896be366dad88a922d0b29f3c69","affectsGlobalScope":true},"4e228e78c1e9b0a75c70588d59288f63a6258e8b1fe4a67b0c53fe03461421d9","b38d55d08708c2410a3039687db70b4a5bfa69fc4845617c313b5a10d9c5c637","205d50c24359ead003dc537b9b65d2a64208dfdffe368f403cf9e0357831db9e","1265fddcd0c68be9d2a3b29805d0280484c961264dd95e0b675f7bd91f777e78",{"version":"a05e2d784c9be7051c4ac87a407c66d2106e23490c18c038bbd0712bde7602fd","affectsGlobalScope":true},{"version":"df90b9d0e9980762da8daf8adf6ffa0c853e76bfd269c377be0d07a9ad87acd2","affectsGlobalScope":true},"cf434b5c04792f62d6f4bdd5e2c8673f36e638e910333c172614d5def9b17f98","1d65d4798df9c2df008884035c41d3e67731f29db5ecb64cd7378797c7c53a2f","0faee6b555890a1cb106e2adc5d3ffd89545b1da894d474e9d436596d654998f","c6c01ea1c42508edf11a36d13b70f6e35774f74355ba5d358354d4a77cc67ea1","867f95abf1df444aab146b19847391fc2f922a55f6a970a27ed8226766cee29f",{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true},"b0297b09e607bec9698cac7cf55463d6731406efb1161ee4d448293b47397c84","175323e2a79a6076e0bada8a390d535a3ea817158bf1b1f46e31efca9028a0a2","7a10053aadc19335532a4d02756db4865974fd69bea5439ddcc5bfdf062d9476","4967529644e391115ca5592184d4b63980569adf60ee685f968fd59ab1557188","aed9e712a9b168345362e8f3a949f16c99ca1e05d21328f05735dfdbb24414ef","b04fe6922ed3db93afdbd49cdda8576aa75f744592fceea96fb0d5f32158c4f5","ed8d6c8de90fc2a4faaebc28e91f2469928738efd5208fb75ade0fa607e892b7","d7c52b198d680fe65b1a8d1b001f0173ffa2536ca2e7082431d726ce1f6714cd","c07f251e1c4e415a838e5498380b55cfea94f3513229de292d2aa85ae52fc3e9","0ed401424892d6bf294a5374efe512d6951b54a71e5dd0290c55b6d0d915f6f7","b945be6da6a3616ef3a250bfe223362b1c7c6872e775b0c4d82a1bf7a28ff902","beea49237dd7c7110fabf3c7509919c9cb9da841d847c53cac162dc3479e2f87","0f45f8a529c450d8f394106cc622bff79e44a1716e1ac9c3cc68b43f7ecf65ee","c624ce90b04c27ce4f318ba6330d39bde3d4e306f0f497ce78d4bda5ab8e22ca","9b8253aa5cb2c82d505f72afdbf96e83b15cc6b9a6f4fadbbbab46210d5f1977","86a8f52e4b1ac49155e889376bcfa8528a634c90c27fec65aa0e949f77b740c5","aab5dd41c1e2316cc0b42a7dd15684f8582d5a1d16c0516276a2a8a7d0fecd9c","59948226626ee210045296ba1fc6cb0fe748d1ff613204e08e7157ab6862dee7","ec3e54d8b713c170fdc8110a7e4a6a97513a7ab6b05ac9e1100cb064d2bb7349","43beb30ecb39a603fde4376554887310b0699f25f7f39c5c91e3147b51bb3a26","666b77d7f06f49da114b090a399abbfa66d5b6c01a3fd9dc4f063a52ace28507","31997714a93fbc570f52d47d6a8ebfb021a34a68ea9ba58bbb69cdec9565657e","6032e4262822160128e644de3fc4410bcd7517c2f137525fd2623d2bb23cb0d3","8bd5c9b1016629c144fd228983395b9dbf0676a576716bc3d316cab612c33cd5","2ed90bd3925b23aed8f859ffd0e885250be0424ca2b57e9866dabef152e1d6b7","93f6bd17d92dab9db7897e1430a5aeaa03bcf51623156213d8397710367a76ce","3f62b770a42e8c47c7008726f95aa383e69d97e85e680d237b99fcb0ee601dd8","5b84cfe78028c35c3bb89c042f18bf08d09da11e82d275c378ae4d07d8477e6c","980d21b0081cbf81774083b1e3a46f4bbdcd2b68858df0f66d7fad9c82bc34bc","68cc8d6fcc2f270d7108f02f3ebc59480a54615be3e09a47e14527f349e9d53e","3eb11dbf3489064a47a2e1cf9d261b1f100ef0b3b50ffca6c44dd99d6dd81ac1","b17f3bb7d8333479c7e45e5f3d876761b9bca58f97594eca3f6a944fd825e632","3c1f1236cce6d6e0c4e2c1b4371e6f72d7c14842ecd76a98ed0748ee5730c8f3","6d7f58d5ea72d7834946fd7104a734dc7d40661be8b2e1eaced1ddce3268ebaf","4c26222991e6c97d5a8f541d4f2c67585eda9e8b33cf9f52931b098045236e88","277983d414aa99d78655186c3ee1e1c38c302e336aff1d77b47fcdc39d8273fe","47383b45796d525a4039cd22d2840ac55a1ff03a43d027f7f867ba7314a9cf53","6548773b3abbc18de29176c2141f766d4e437e40596ee480447abf83575445ad","6ddd27af0436ce59dd4c1896e2bfdb2bdb2529847d078b83ce67a144dff05491","816264799aef3fd5a09a3b6c25217d5ec26a9dfc7465eac7d6073bcdc7d88f3f","4df0891b133884cd9ed752d31c7d0ec0a09234e9ed5394abffd3c660761598db","b603b62d3dcd31ef757dc7339b4fa8acdbca318b0fb9ac485f9a1351955615f9","e642bd47b75ad6b53cbf0dfd7ddfa0f120bd10193f0c58ec37d87b59bf604aca","be90b24d2ee6f875ce3aaa482e7c41a54278856b03d04212681c4032df62baf9","78f5ff400b3cb37e7b90eef1ff311253ed31c8cb66505e9828fad099bffde021","372c47090e1131305d163469a895ff2938f33fa73aad988df31cd31743f9efb6","71c67dc6987bdbd5599353f90009ff825dd7db0450ef9a0aee5bb0c574d18512","6f12403b5eca6ae7ca8e3efe3eeb9c683b06ce3e3844ccfd04098d83cd7e4957","282c535df88175d64d9df4550d2fd1176fd940c1c6822f1e7584003237f179d3","c3a4752cf103e4c6034d5bd449c8f9d5e7b352d22a5f8f9a41a8efb11646f9c2","11a9e38611ac3c77c74240c58b6bd64a0032128b29354e999650f1de1e034b1c","4ed103ca6fff9cb244f7c4b86d1eb28ce8069c32db720784329946731badb5bb","d738f282842970e058672663311c6875482ee36607c88b98ffb6604fba99cb2a","ec859cd8226aa623e41bbb47c249a55ee16dc1b8647359585244d57d3a5ed0c7","8891c6e959d253a66434ff5dc9ae46058fb3493e84b4ca39f710ef2d350656b1","c4463cf02535444dcbc3e67ecd29f1972490f74e49957d6fd4282a1013796ba6","0cb0a957ff02de0b25fd0f3f37130ca7f22d1e0dea256569c714c1f73c6791f8","2f5075dc512d51786b1ba3b1696565641dfaae3ac854f5f13d61fa12ef81a47e","ca3353cc82b1981f0d25d71d7432d583a6ef882ccdea82d65fbe49af37be51cb","50679a8e27aacf72f8c40bcab15d7ef5e83494089b4726b83eec4554344d5cdc","45351e0d51780b6f4088277a4457b9879506ee2720a887de232df0f1efcb33d8","5d697a4b315cc5bb3042ae869abffd10c3b0d7b182cda0e4c45d8819937e5796","563fa27fdaec8f195b84f71a7af0ef48d30d5cc830575db86da86a63a470c8e6","6ee58aa536dabb19b09bc036f1abe83feb51e13d63b23d30b2d0631a2de99b8f","8aceb205dcc6f814ad99635baf1e40b6e01d06d3fe27b72fd766c6d0b8c0c600","299567f84bfedd1468dca2755a829cb19e607a6811673788807dc8921e211bc9","795d9fb85aad92221504db74dd179b506bd189bba0c104426f7e7bb8a66ffee5","1311bc194e0a69fe61031e852c1c0b439e2a2a3d1d5e2d8ff795499b9f283459","4b7ce19369d7e7fae76720c2c6c7f671bf3fa0f7093edb864f1ac358ca7c456c","c972ef44deca1fa8fab465915ffa00f82e126aacf3dfc8979c03b1b066ce5bb6","30285a1011c6d6b52f3ba3abb0a984be8148c05cdefb8eb6eb562335a3991f35","8e7adb22c0adecf7464861fc58ae3fc617b41ffbd70c97aa8493dc0966a82273","755f3cd1d9c1b564cff090e3b0e29200ae55690a91b87cb9e7a64c2dbeb314d3","d6bb7e0a6877b7856c183bff13d09dd9ae599ea43c6f6b33d3d5f72a830ed460","f1b51ae93c762d7c43f559933cd4842dd870367e8d92e90704ffa685dd5b29a3","3f450762fd7c34ed545e738abccb0af6a703572a10521643cf8fc88e3724c99c","fcc8beef29f39f09b1d9c9f99c42f9fed605ab1c28d2a630185f732b9ba53763","d6e6620a30d582182acc3f0a992a0c311adc589f111096aea11ab83fc09a5ccc","6213b8f686f56beab22b59a0f468590fd3a4c5fa931236a017efeca91d7c9584","c451cec9a588b1f105a5ea2c6063d4fca112b9d70105cacdadda0e1ef67e9379","cb047832dc68f5a2c41c62c5e95ddcacbae3a8b034d40cd15319a8cb7f25104a","980336ccdfc3c08f3c3b201aa6662e6016e20f15847f8465b68f3e8e67b4665c","5a3493939995f46ff3d9073cd534fb8961c3bf4e08c71db27066ff03d906dea8","bb5a2ac327605ebebf831c469b05bd34a33a6a46ee8c1edd9f3310aad32cf6a1","bf5d041f2440b4a9391e2b5eb3b8d94cbf1e3b8ff4703b6539d4e65e758c8f37","8516469eb90e723b0eb03df1be098f7e6a4709f6f48fd4532868d20a0a934f6e","d60e9ab369a72d234aac49adbe2900d8ef1408a6ea4db552cf2a48c9d8d6a1bc","0ebb4698803f01e2e7df6acce572fff068f4a20c47221721dafd70a27e372831","03460a54d0e0481d1e11097f66ad43f054bc95efdafe5f81bbc7a82be181af75","4070c2f1c3434fcf84886e04d30d82cd650ee443e53b82b404b144175cf8741e","2cea9689efa8591732096235abe7f084fc29c92badd5b0897a5e876b77e71887","4ed4e504126014fee13aaef5e3fc140f2ff7031ff3a8b5386717905820ea2d09","8129a34006218a6f3cdc81bbd438d5429eb18b08b4338a26977ac3b4df129d75","30d2170e1a718b5035611af55e3618b4ba8f42f0749bb52ee593da6082c4e2ce","98ef38666d88ec9699a722053e07ede65d3042f693fe7ff8c786e53dbb6fd43b","a3b8b6be7620897d1e481e8650c980a210a138fceb6e710eaf95fd9dd0dfe94a","12c89d0e32758c120a569045f21cf5b77244f86792611ced8de7f86b37e77781","14bd47270e654c8eb3b1489fa8c095912ee62a0a29bb92743393203722347c53","3d9297165e67fd59d9821cc93a9808213e33c56a8ac1c4273171f6afaaa2d4d5","e7af7d288b89287ad031b19583c597fcd9f5edc0b0d579b7b492f06cf57e058c","92cb686a9ca5eb5dd7d5d8d43a3707194c1e91ea07a027b3bcb60b6011b24632","fab58e600970e66547644a44bc9918e3223aa2cbd9e8763cec004b2cfb48827e",{"version":"d1a5f486914e3ead50534f48742c4e5e885d28909bec274017189d3284bcb833","signature":"b943b90c649678cec7987a6d56f4917db1712079294cffdf650699235ff9f37d"},{"version":"15433a2e97dcee760d97f8e56afe908fe932611ef00711aed9b246ba058ce0be","signature":"c5fc52cba80e6ba6fde33b0f9370b8ba6866831070cbc84b20a7c6e9e1163160"},{"version":"674d97345e4d79afd1248bdf3a032c9280f2ef163b1a074d14a1a927d93397a4","signature":"6991b558e53d59bb2160b64ee154678e069bd9bfe5131c628dcb6ac0363ca00d"},"d021f18758b28bda32bdaf0a987e0804cec074a9a4cfab8232ed81d96e75dfae","4489c6a9fde8934733aa7df6f7911461ee6e9e4ad092736bd416f6b2cc20b2c6","2c8e55457aaf4902941dfdba4061935922e8ee6e120539c9801cd7b400fae050","8041cfce439ff29d339742389de04c136e3029d6b1817f07b2d7fcbfb7534990","670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","9d38964b57191567a14b396422c87488cecd48f405c642daa734159875ee81d9","069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","8c95f96ccd4be0674944077aec1e4f2cccd515ca06d4327562dd017250e7d3fc",{"version":"64d4b35c5456adf258d2cf56c341e203a073253f229ef3208fc0d5020253b241","affectsGlobalScope":true},"ee7d8894904b465b072be0d2e4b45cf6b887cdba16a467645c4e200982ece7ea","f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","bc3cba7b0af2d52e7425299aee518db479d44004eff6fbbd206d1ee7e5ec3fb5","afe73051ff6a03a9565cbd8ebb0e956ee3df5e913ad5c1ded64218aabfa3dcb5","035a5df183489c2e22f3cf59fc1ed2b043d27f357eecc0eb8d8e840059d44245","a4809f4d92317535e6b22b01019437030077a76fec1d93b9881c9ed4738fcc54","5f53fa0bd22096d2a78533f94e02c899143b8f0f9891a46965294ee8b91a9434","0d14fa22c41fdc7277e6f71473b20ebc07f40f00e38875142335d5b63cdfc9d2","d8aab31ba8e618cc3eea10b0945de81cb93b7e8150a013a482332263b9305322","462bccdf75fcafc1ae8c30400c9425e1a4681db5d605d1a0edb4f990a54d8094","5923d8facbac6ecf7c84739a5c701a57af94a6f6648d6229a6c768cf28f0f8cb","7adecb2c3238794c378d336a8182d4c3dd2c4fa6fa1785e2797a3db550edea62","dc12dc0e5aa06f4e1a7692149b78f89116af823b9e1f1e4eae140cd3e0e674e6","1bfc6565b90c8771615cd8cfcf9b36efc0275e5e83ac7d9181307e96eb495161","8a8a96898906f065f296665e411f51010b51372fa260d5373bf9f64356703190","7f82ef88bdb67d9a850dd1c7cd2d690f33e0f0acd208e3c9eba086f3670d4f73",{"version":"ccfd8774cd9b929f63ff7dcf657977eb0652e3547f1fcac1b3a1dc5db22d4d58","affectsGlobalScope":true},"d92dc90fecd2552db74d8dc3c6fb4db9145b2aa0efe2c127236ba035969068d4","96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","b8442e9db28157344d1bc5d8a5a256f1692de213f0c0ddeb84359834015a008c","458111fc89d11d2151277c822dfdc1a28fa5b6b2493cf942e37d4cd0a6ee5f22","da2b6356b84a40111aaecb18304ea4e4fcb43d70efb1c13ca7d7a906445ee0d3","187119ff4f9553676a884e296089e131e8cc01691c546273b1d0089c3533ce42","febf0b2de54781102b00f61653b21377390a048fbf5262718c91860d11ff34a6","6f294731b495c65ecf46a5694f0082954b961cf05463bea823f8014098eaffa0","0aaef8cded245bf5036a7a40b65622dd6c4da71f7a35343112edbe112b348a1e","00baffbe8a2f2e4875367479489b5d43b5fc1429ecb4a4cc98cfc3009095f52a","68a0d0c508e1b6d8d23a519a8a0a3303dc5baa4849ca049f21e5bad41945e3fc","3c92b6dfd43cc1c2485d9eba5ff0b74a19bb8725b692773ef1d66dac48cda4bd","b03afe4bec768ae333582915146f48b161e567a81b5ebc31c4d78af089770ac9","df996e25faa505f85aeb294d15ebe61b399cf1d1e49959cdfaf2cc0815c203f9","4f6a12044ee6f458db11964153830abbc499e73d065c51c329ec97407f4b13dd","8841e2aa774b89bd23302dede20663306dc1b9902431ac64b24be8b8d0e3f649","916be7d770b0ae0406be9486ac12eb9825f21514961dd050594c4b250617d5a8","254d9fb8c872d73d34594be8a200fd7311dbfa10a4116bfc465fba408052f2b3","d88a5e779faf033be3d52142a04fbe1cb96009868e3bbdd296b2bc6c59e06c0e","2ccea88888048bbfcacbc9531a5596ea48a3e7dcd0a25f531a81bb717903ba4f","5e379df3d61561c2ed7789b5995b9ba2143bbba21a905e2381e16efe7d1fa424","f07a137bbe2de7a122c37bfea00e761975fb264c49f18003d398d71b3fb35a5f","d8f7109e14f20eb735225a62fd3f8366da1a8349e90331cdad57f4b04caf6c5a","cf3d384d082b933d987c4e2fe7bfb8710adfd9dc8155190056ed6695a25a559e","9871b7ee672bc16c78833bdab3052615834b08375cb144e4d2cba74473f4a589","c863198dae89420f3c552b5a03da6ed6d0acfa3807a64772b895db624b0de707","8b03a5e327d7db67112ebbc93b4f744133eda2c1743dbb0a990c61a8007823ef","86c73f2ee1752bac8eeeece234fd05dfcf0637a4fbd8032e4f5f43102faa8eec","42fad1f540271e35ca37cecda12c4ce2eef27f0f5cf0f8dd761d723c744d3159","ff3743a5de32bee10906aff63d1de726f6a7fd6ee2da4b8229054dfa69de2c34","83acd370f7f84f203e71ebba33ba61b7f1291ca027d7f9a662c6307d74e4ac22","1445cec898f90bdd18b2949b9590b3c012f5b7e1804e6e329fb0fe053946d5ec","0e5318ec2275d8da858b541920d9306650ae6ac8012f0e872fe66eb50321a669","cf530297c3fb3a92ec9591dd4fa229d58b5981e45fe6702a0bd2bea53a5e59be","c1f6f7d08d42148ddfe164d36d7aba91f467dbcb3caa715966ff95f55048b3a4","f4e9bf9103191ef3b3612d3ec0044ca4044ca5be27711fe648ada06fad4bcc85","0c1ee27b8f6a00097c2d6d91a21ee4d096ab52c1e28350f6362542b55380059a","7677d5b0db9e020d3017720f853ba18f415219fb3a9597343b1b1012cfd699f7","bc1c6bc119c1784b1a2be6d9c47addec0d83ef0d52c8fbe1f14a51b4dfffc675","52cf2ce99c2a23de70225e252e9822a22b4e0adb82643ab0b710858810e00bf1","770625067bb27a20b9826255a8d47b6b5b0a2d3dfcbd21f89904c731f671ba77","d1ed6765f4d7906a05968fb5cd6d1db8afa14dbe512a4884e8ea5c0f5e142c80","799c0f1b07c092626cf1efd71d459997635911bb5f7fc1196efe449bba87e965","2a184e4462b9914a30b1b5c41cf80c6d3428f17b20d3afb711fff3f0644001fd","9eabde32a3aa5d80de34af2c2206cdc3ee094c6504a8d0c2d6d20c7c179503cc","397c8051b6cfcb48aa22656f0faca2553c5f56187262135162ee79d2b2f6c966","a8ead142e0c87dcd5dc130eba1f8eeed506b08952d905c47621dc2f583b1bff9","a02f10ea5f73130efca046429254a4e3c06b5475baecc8f7b99a0014731be8b3","c2576a4083232b0e2d9bd06875dd43d371dee2e090325a9eac0133fd5650c1cb","4c9a0564bb317349de6a24eb4efea8bb79898fa72ad63a1809165f5bd42970dd","f40ac11d8859092d20f953aae14ba967282c3bb056431a37fced1866ec7a2681","cc11e9e79d4746cc59e0e17473a59d6f104692fd0eeea1bdb2e206eabed83b03","b444a410d34fb5e98aa5ee2b381362044f4884652e8bc8a11c8fe14bbd85518e","c35808c1f5e16d2c571aa65067e3cb95afeff843b259ecfa2fc107a9519b5392","14d5dc055143e941c8743c6a21fa459f961cbc3deedf1bfe47b11587ca4b3ef5","a3ad4e1fc542751005267d50a6298e6765928c0c3a8dce1572f2ba6ca518661c","f237e7c97a3a89f4591afd49ecb3bd8d14f51a1c4adc8fcae3430febedff5eb6","3ffdfbec93b7aed71082af62b8c3e0cc71261cc68d796665faa1e91604fbae8f","662201f943ed45b1ad600d03a90dffe20841e725203ced8b708c91fcd7f9379a","c9ef74c64ed051ea5b958621e7fb853fe3b56e8787c1587aefc6ea988b3c7e79","2462ccfac5f3375794b861abaa81da380f1bbd9401de59ffa43119a0b644253d","34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","7d8ddf0f021c53099e34ee831a06c394d50371816caa98684812f089b4c6b3d4","7d2a0ba1297be385a89b5515b88cd31b4a1eeef5236f710166dc1b36b1741e1b","9d92b037978bb9525bc4b673ebddd443277542e010c0aef019c03a170ccdaa73","ab82804a14454734010dcdcd43f564ff7b0389bee4c5692eec76ff5b30d4cf66","bae8d023ef6b23df7da26f51cea44321f95817c190342a36882e93b80d07a960","ae271d475b632ce7b03fea6d9cf6da72439e57a109672671cbc79f54e1386938"],"options":{"composite":true,"declaration":true,"declarationMap":true,"emitDeclarationOnly":true,"esModuleInterop":true,"inlineSources":true,"module":1,"outDir":"./types","rootDir":"../src","sourceMap":true,"strict":true,"target":7},"fileIdsList":[[234],[92,128,129,130,145],[129,130,146,147],[128,129],[128,145,148,151],[128,148,151,152],[149,150,151,153,154],[128,151],[128,145,148,149,150,153],[128,136],[128],[92,128],[80,128],[132,133,134,135,136,137,138,139,140,141,142,143,144],[128,134,135],[128,134,136],[199],[199,200,201],[64],[67],[64,67],[65,66,67,68,69,70,71,72,73,74,75,156,159,160,161,162,163,164,165,166],[58,64,65],[67,73,75,155],[158],[67,68],[64,162],[194,195],[234,235,236,237,238],[234,236],[157],[241,242,243],[93,128],[246],[247],[258],[252,257],[261,263,264,265,266,267,268,269,270,271,272,273],[261,262,264,265,266,267,268,269,270,271,272,273],[262,263,264,265,266,267,268,269,270,271,272,273],[261,262,263,265,266,267,268,269,270,271,272,273],[261,262,263,264,266,267,268,269,270,271,272,273],[261,262,263,264,265,267,268,269,270,271,272,273],[261,262,263,264,265,266,268,269,270,271,272,273],[261,262,263,264,265,266,267,269,270,271,272,273],[261,262,263,264,265,266,267,268,270,271,272,273],[261,262,263,264,265,266,267,268,269,271,272,273],[261,262,263,264,265,266,267,268,269,270,272,273],[261,262,263,264,265,266,267,268,269,270,271,273],[261,262,263,264,265,266,267,268,269,270,271,272],[76],[79],[80,85,112],[81,92,93,100,109,120],[81,82,92,100],[83,121],[84,85,93,101],[85,109,117],[86,88,92,100],[87],[88,89],[92],[91,92],[79,92],[92,93,94,109,120],[92,93,94,109],[92,95,100,109,120],[92,93,95,96,100,109,117,120],[95,97,109,117,120],[76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127],[92,98],[99,120,125],[88,92,100,109],[101],[102],[79,103],[104,119,125],[105],[106],[92,107],[107,108,121,123],[80,92,109,110,111],[80,109,111],[109,110],[112],[113],[92,115,116],[115,116],[85,100,109,117],[118],[100,119],[80,95,106,120],[85,121],[109,122],[123],[124],[80,85,92,94,103,109,120,123,125],[109,126],[128,279],[282,321],[282,306,321],[321],[282],[282,307,321],[282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320],[307,321],[322],[325],[204],[216,217,218],[204,215,216],[179],[179,180,181,182,183],[168,169,170,171,172,173,174,175,176,177,178],[250,253],[250,253,254,255],[252],[249,256],[251],[57,59,60,61,62,63],[57,58],[59],[58,59],[57,59],[167,184,185,186],[185],[56,185,186,187],[186],[189],[189,190,193,197],[196],[167,191,192],[212,213,214],[211,212],[167,211,212],[167,204,211],[232],[191,192,198,232],[167,188,191,198,224,228,229,230,231],[167,205],[205,206,207,208,209,210],[167,204],[220],[203,220,222,223],[167,188,191,198,202,203,220,221],[167,198,215,219],[167,188,224,225],[225,226,227],[128,167,188,224,225],[167,224],[191,232],[167,188,224,228]],"referencedMap":[[236,1],[146,2],[148,3],[130,4],[152,5],[153,6],[149,6],[155,7],[150,6],[154,8],[151,9],[137,10],[134,11],[141,12],[135,10],[132,13],[145,14],[139,11],[136,15],[138,16],[204,12],[200,17],[201,17],[202,18],[65,19],[66,19],[68,20],[69,19],[70,19],[71,21],[67,19],[167,22],[75,23],[156,24],[159,25],[165,26],[166,27],[196,28],[239,29],[235,1],[237,30],[238,1],[192,11],[158,31],[244,32],[245,33],[247,34],[248,35],[259,36],[258,37],[262,38],[263,39],[261,40],[264,41],[265,42],[266,43],[267,44],[268,45],[269,46],[270,47],[271,48],[272,49],[273,50],[76,51],[77,51],[79,52],[80,53],[81,54],[82,55],[83,56],[84,57],[85,58],[86,59],[87,60],[88,61],[89,61],[90,62],[91,63],[92,64],[93,65],[94,66],[95,67],[96,68],[97,69],[128,70],[98,71],[99,72],[100,73],[101,74],[102,75],[103,76],[104,77],[105,78],[106,79],[107,80],[108,81],[109,82],[111,83],[110,84],[112,85],[113,86],[115,87],[116,88],[117,89],[118,90],[119,91],[120,92],[121,93],[122,94],[123,95],[124,96],[125,97],[126,98],[276,11],[280,99],[281,11],[306,100],[307,101],[282,102],[285,102],[304,100],[305,100],[295,100],[294,103],[292,100],[287,100],[300,100],[298,100],[302,100],[286,100],[299,100],[303,100],[288,100],[289,100],[301,100],[283,100],[290,100],[291,100],[293,100],[297,100],[308,104],[296,100],[284,100],[321,105],[315,104],[317,106],[316,104],[309,104],[310,104],[312,104],[314,104],[318,106],[319,106],[311,106],[313,106],[323,107],[326,108],[216,109],[219,110],[217,111],[218,111],[175,112],[177,112],[176,112],[174,112],[184,113],[179,114],[170,112],[171,112],[172,112],[173,112],[254,115],[256,116],[255,115],[253,117],[257,118],[252,119],[64,120],[59,121],[60,122],[61,122],[62,123],[63,123],[58,124],[187,125],[186,126],[188,127],[185,128],[190,129],[198,130],[197,131],[193,132],[215,133],[213,134],[214,135],[212,136],[230,137],[231,138],[232,139],[233,137],[206,140],[207,140],[209,140],[211,141],[205,142],[210,140],[221,143],[223,143],[224,144],[222,145],[220,146],[226,147],[228,148],[227,149],[225,150]],"exportedModulesMap":[[236,1],[146,2],[148,3],[130,4],[152,5],[153,6],[149,6],[155,7],[150,6],[154,8],[151,9],[137,10],[134,11],[141,12],[135,10],[132,13],[145,14],[139,11],[136,15],[138,16],[204,12],[200,17],[201,17],[202,18],[65,19],[66,19],[68,20],[69,19],[70,19],[71,21],[67,19],[167,22],[75,23],[156,24],[159,25],[165,26],[166,27],[196,28],[239,29],[235,1],[237,30],[238,1],[192,11],[158,31],[244,32],[245,33],[247,34],[248,35],[259,36],[258,37],[262,38],[263,39],[261,40],[264,41],[265,42],[266,43],[267,44],[268,45],[269,46],[270,47],[271,48],[272,49],[273,50],[76,51],[77,51],[79,52],[80,53],[81,54],[82,55],[83,56],[84,57],[85,58],[86,59],[87,60],[88,61],[89,61],[90,62],[91,63],[92,64],[93,65],[94,66],[95,67],[96,68],[97,69],[128,70],[98,71],[99,72],[100,73],[101,74],[102,75],[103,76],[104,77],[105,78],[106,79],[107,80],[108,81],[109,82],[111,83],[110,84],[112,85],[113,86],[115,87],[116,88],[117,89],[118,90],[119,91],[120,92],[121,93],[122,94],[123,95],[124,96],[125,97],[126,98],[276,11],[280,99],[281,11],[306,100],[307,101],[282,102],[285,102],[304,100],[305,100],[295,100],[294,103],[292,100],[287,100],[300,100],[298,100],[302,100],[286,100],[299,100],[303,100],[288,100],[289,100],[301,100],[283,100],[290,100],[291,100],[293,100],[297,100],[308,104],[296,100],[284,100],[321,105],[315,104],[317,106],[316,104],[309,104],[310,104],[312,104],[314,104],[318,106],[319,106],[311,106],[313,106],[323,107],[326,108],[216,109],[219,110],[217,111],[218,111],[175,112],[177,112],[176,112],[174,112],[184,113],[179,114],[170,112],[171,112],[172,112],[173,112],[254,115],[256,116],[255,115],[253,117],[257,118],[252,119],[64,120],[59,121],[60,122],[61,122],[62,123],[63,123],[58,124],[187,125],[186,126],[188,127],[185,128],[190,129],[198,130],[197,131],[193,132],[215,133],[213,134],[214,135],[212,136],[230,137],[231,151],[232,152],[233,137],[206,140],[207,140],[209,140],[211,141],[205,142],[210,140],[221,143],[223,143],[224,144],[222,145],[220,146],[226,147],[228,148],[227,149],[225,150]],"semanticDiagnosticsPerFile":[236,234,146,129,148,130,147,152,153,149,155,150,154,151,137,134,141,135,132,140,145,142,143,144,139,136,133,138,191,204,200,201,202,199,65,66,68,69,70,71,72,73,74,67,167,75,156,159,160,161,162,163,164,165,166,194,196,195,239,235,237,238,192,158,240,241,244,242,245,246,247,248,259,258,243,260,262,263,261,264,265,266,267,268,269,270,271,272,273,274,157,76,77,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,78,127,95,96,97,128,98,99,100,101,102,103,104,105,106,107,108,109,111,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,275,276,277,278,280,279,281,306,307,282,285,304,305,295,294,292,287,300,298,302,286,299,303,288,289,301,283,290,291,293,297,308,296,284,321,320,315,317,316,309,310,312,314,318,319,311,313,323,322,324,229,325,326,131,249,216,219,217,218,178,175,177,176,174,184,179,183,180,182,181,170,171,172,168,169,173,250,254,256,255,253,257,252,251,57,64,59,60,61,62,63,58,8,10,9,2,11,12,13,14,15,16,17,18,3,4,22,19,20,21,23,24,25,5,26,27,28,29,6,33,30,31,32,34,7,35,40,41,36,37,38,39,1,42,56,187,186,188,185,190,198,197,189,193,215,213,214,212,230,231,232,233,206,207,208,209,211,205,210,203,221,223,224,222,220,226,228,227,225,47,48,49,50,51,52,43,53,54,55,44,45,46],"latestChangedDtsFile":"./types/index.d.ts"},"version":"4.9.5"} +\ No newline at end of file +diff --git a/dist/types/GasFeeController.d.ts b/dist/types/GasFeeController.d.ts +index b6ffa7cd5b356ef6c5df6a79876308d21749bd06..56d9420b539cc8d98b8aeb0a84ba541fc3beae1b 100644 +--- a/dist/types/GasFeeController.d.ts ++++ b/dist/types/GasFeeController.d.ts +@@ -2,7 +2,7 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedCo + import type { NetworkClientId, NetworkControllerGetEIP1559CompatibilityAction, NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction, NetworkControllerNetworkDidChangeEvent, NetworkState, ProviderProxy } from '@metamask/network-controller'; + import { StaticIntervalPollingController } from '@metamask/polling-controller'; + import type { Hex } from '@metamask/utils'; +-export declare const GAS_API_BASE_URL = "https://gas.api.infura.io"; ++export declare const LEGACY_GAS_PRICES_API_URL = "https://api.metaswap.codefi.network/gasPrices"; + export type unknownString = 'unknown'; + export type FeeMarketEstimateType = 'fee-market'; + export type LegacyEstimateType = 'legacy'; +@@ -160,7 +160,6 @@ export declare class GasFeeController extends StaticIntervalPollingController<ty + private readonly getCurrentNetworkEIP1559Compatibility; + private readonly getCurrentNetworkLegacyGasAPICompatibility; + private readonly getCurrentAccountEIP1559Compatibility; +- private readonly infuraAPIKey; + private currentChainId; + private ethQuery?; + private readonly clientId?; +@@ -181,11 +180,13 @@ export declare class GasFeeController extends StaticIntervalPollingController<ty + * @param options.getProvider - Returns a network provider for the current network. + * @param options.onNetworkDidChange - A function for registering an event handler for the + * network state change event. ++ * @param options.legacyAPIEndpoint - The legacy gas price API URL. This option is primarily for ++ * testing purposes. ++ * @param options.EIP1559APIEndpoint - The EIP-1559 gas price API URL. + * @param options.clientId - The client ID used to identify to the gas estimation API who is + * asking for estimates. +- * @param options.infuraAPIKey - The Infura API key used for infura API requests. + */ +- constructor({ interval, messenger, state, getCurrentNetworkEIP1559Compatibility, getCurrentAccountEIP1559Compatibility, getChainId, getCurrentNetworkLegacyGasAPICompatibility, getProvider, onNetworkDidChange, clientId, infuraAPIKey, }: { ++ constructor({ interval, messenger, state, getCurrentNetworkEIP1559Compatibility, getCurrentAccountEIP1559Compatibility, getChainId, getCurrentNetworkLegacyGasAPICompatibility, getProvider, onNetworkDidChange, legacyAPIEndpoint, EIP1559APIEndpoint, clientId, }: { + interval?: number; + messenger: GasFeeMessenger; + state?: GasFeeState; +@@ -195,8 +196,9 @@ export declare class GasFeeController extends StaticIntervalPollingController<ty + getChainId?: () => Hex; + getProvider: () => ProviderProxy; + onNetworkDidChange?: (listener: (state: NetworkState) => void) => void; ++ legacyAPIEndpoint?: string; ++ EIP1559APIEndpoint: string; + clientId?: string; +- infuraAPIKey: string; + }); + resetPolling(): Promise<void>; + fetchGasFeeEstimates(options?: FetchGasFeeEstimateOptions): Promise<GasFeeState>; +diff --git a/dist/types/GasFeeController.d.ts.map b/dist/types/GasFeeController.d.ts.map +index 0dd80816d0083029fcc5ef3a85a47f188a5b4c02..127cdbe0c0fbfb37938403190c49d2a5687cf9c4 100644 +--- a/dist/types/GasFeeController.d.ts.map ++++ b/dist/types/GasFeeController.d.ts.map +@@ -1 +1 @@ +-{"version":3,"file":"GasFeeController.d.ts","sourceRoot":"","sources":["../../src/GasFeeController.ts"],"names":[],"mappings":"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"} +\ No newline at end of file ++{"version":3,"file":"GasFeeController.d.ts","sourceRoot":"","sources":["../../src/GasFeeController.ts"],"names":[],"mappings":"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"} +\ No newline at end of file +diff --git a/dist/types/determineGasFeeCalculations.d.ts b/dist/types/determineGasFeeCalculations.d.ts +index 8091a4d4290d6a3ca9ecbecc9ab8c6764a58cac9..6f4b2758a99e4d0d3fd2c8dce4064a2a2fc69c0a 100644 +--- a/dist/types/determineGasFeeCalculations.d.ts ++++ b/dist/types/determineGasFeeCalculations.d.ts +@@ -2,15 +2,14 @@ import type { EstimatedGasFeeTimeBounds, EthGasPriceEstimate, GasFeeEstimates, G + type DetermineGasFeeCalculationsRequest = { + isEIP1559Compatible: boolean; + isLegacyGasAPICompatible: boolean; +- fetchGasEstimates: (url: string, infuraAPIKey: string, clientId?: string) => Promise<GasFeeEstimates>; ++ fetchGasEstimates: (url: string, clientId?: string) => Promise<GasFeeEstimates>; + fetchGasEstimatesUrl: string; +- fetchLegacyGasPriceEstimates: (url: string, infuraAPIKey: string, clientId?: string) => Promise<LegacyGasPriceEstimate>; ++ fetchLegacyGasPriceEstimates: (url: string, clientId?: string) => Promise<LegacyGasPriceEstimate>; + fetchLegacyGasPriceEstimatesUrl: string; + fetchEthGasPriceEstimate: (ethQuery: any) => Promise<EthGasPriceEstimate>; + calculateTimeEstimate: (maxPriorityFeePerGas: string, maxFeePerGas: string, gasFeeEstimates: GasFeeEstimates) => EstimatedGasFeeTimeBounds; + clientId: string | undefined; + ethQuery: any; +- infuraAPIKey: string; + nonRPCGasFeeApisDisabled?: boolean; + }; + /** +@@ -35,7 +34,6 @@ type DetermineGasFeeCalculationsRequest = { + * @param args.calculateTimeEstimate - A function that determine time estimate bounds. + * @param args.clientId - An identifier that an API can use to know who is asking for estimates. + * @param args.ethQuery - An EthQuery instance we can use to talk to Ethereum directly. +- * @param args.infuraAPIKey - Infura API key to use for requests to Infura. + * @param args.nonRPCGasFeeApisDisabled - Whether to disable requests to the legacyAPIEndpoint and the EIP1559APIEndpoint + * @returns The gas fee calculations. + */ +diff --git a/dist/types/determineGasFeeCalculations.d.ts.map b/dist/types/determineGasFeeCalculations.d.ts.map +index 44ce4dc7b691ea0316163952f99d426d417afd1a..17cec260fc0836f59929a053270164e5c10e4b89 100644 +--- a/dist/types/determineGasFeeCalculations.d.ts.map ++++ b/dist/types/determineGasFeeCalculations.d.ts.map +@@ -1 +1 @@ +-{"version":3,"file":"determineGasFeeCalculations.d.ts","sourceRoot":"","sources":["../../src/determineGasFeeCalculations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,WAAW,IAAI,kBAAkB,EACjC,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAG5B,KAAK,kCAAkC,GAAG;IACxC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,wBAAwB,EAAE,OAAO,CAAC;IAClC,iBAAiB,EAAE,CACjB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC,eAAe,CAAC,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,4BAA4B,EAAE,CAC5B,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACrC,+BAA+B,EAAE,MAAM,CAAC;IAGxC,wBAAwB,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC1E,qBAAqB,EAAE,CACrB,oBAAoB,EAAE,MAAM,EAC5B,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,eAAe,KAC7B,yBAAyB,CAAC;IAC/B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAG7B,QAAQ,EAAE,GAAG,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAA8B,2BAA2B,CACvD,IAAI,EAAE,kCAAkC,GACvC,OAAO,CAAC,kBAAkB,CAAC,CAY7B"} +\ No newline at end of file ++{"version":3,"file":"determineGasFeeCalculations.d.ts","sourceRoot":"","sources":["../../src/determineGasFeeCalculations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,WAAW,IAAI,kBAAkB,EACjC,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAG5B,KAAK,kCAAkC,GAAG;IACxC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,wBAAwB,EAAE,OAAO,CAAC;IAClC,iBAAiB,EAAE,CACjB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC,eAAe,CAAC,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,4BAA4B,EAAE,CAC5B,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACrC,+BAA+B,EAAE,MAAM,CAAC;IAGxC,wBAAwB,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC1E,qBAAqB,EAAE,CACrB,oBAAoB,EAAE,MAAM,EAC5B,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,eAAe,KAC7B,yBAAyB,CAAC;IAC/B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAG7B,QAAQ,EAAE,GAAG,CAAC;IACd,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAA8B,2BAA2B,CACvD,IAAI,EAAE,kCAAkC,GACvC,OAAO,CAAC,kBAAkB,CAAC,CAY7B"} +\ No newline at end of file +diff --git a/dist/types/gas-util.d.ts b/dist/types/gas-util.d.ts +index 3739e0ffc0f895d20b5ab1e706b893e8606ef62b..661c3a87fbb2160075801e676d216809b01ecf6e 100644 +--- a/dist/types/gas-util.d.ts ++++ b/dist/types/gas-util.d.ts +@@ -11,21 +11,19 @@ export declare function normalizeGWEIDecimalNumbers(n: string | number): any; + * Fetch gas estimates from the given URL. + * + * @param url - The gas estimate URL. +- * @param infuraAPIKey - The Infura API key used for infura API requests. + * @param clientId - The client ID used to identify to the API who is asking for estimates. + * @returns The gas estimates. + */ +-export declare function fetchGasEstimates(url: string, infuraAPIKey: string, clientId?: string): Promise<GasFeeEstimates>; ++export declare function fetchGasEstimates(url: string, clientId?: string): Promise<GasFeeEstimates>; + /** + * Hit the legacy MetaSwaps gasPrices estimate api and return the low, medium + * high values from that API. + * + * @param url - The URL to fetch gas price estimates from. +- * @param infuraAPIKey - The Infura API key used for infura API requests. + * @param clientId - The client ID used to identify to the API who is asking for estimates. + * @returns The gas price estimates. + */ +-export declare function fetchLegacyGasPriceEstimates(url: string, infuraAPIKey: string, clientId?: string): Promise<LegacyGasPriceEstimate>; ++export declare function fetchLegacyGasPriceEstimates(url: string, clientId?: string): Promise<LegacyGasPriceEstimate>; + /** + * Get a gas price estimate from the network using the `eth_gasPrice` method. + * +diff --git a/dist/types/gas-util.d.ts.map b/dist/types/gas-util.d.ts.map +index 8a24af1980fc16f7ecbe97222cab534b3c0f6c2c..ab417991781db0ad097218682c264d7aa738bf12 100644 +--- a/dist/types/gas-util.d.ts.map ++++ b/dist/types/gas-util.d.ts.map +@@ -1 +1 @@ +-{"version":3,"file":"gas-util.d.ts","sourceRoot":"","sources":["../../src/gas-util.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAGhD,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EAEzB,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAI5B;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,OAI7D;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAyC1B;AAED;;;;;;;;GAQG;AACH,wBAAsB,4BAA4B,CAChD,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,sBAAsB,CAAC,CAcjC;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,mBAAmB,CAAC,CAK9B;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,oBAAoB,EAAE,MAAM,EAC5B,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,eAAe,GAC/B,yBAAyB,CAoD3B"} +\ No newline at end of file ++{"version":3,"file":"gas-util.d.ts","sourceRoot":"","sources":["../../src/gas-util.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAGhD,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EAEzB,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAI5B;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,OAI7D;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAyC1B;AAED;;;;;;;GAOG;AACH,wBAAsB,4BAA4B,CAChD,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,sBAAsB,CAAC,CAgBjC;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,mBAAmB,CAAC,CAK9B;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,oBAAoB,EAAE,MAAM,EAC5B,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,eAAe,GAC/B,yBAAyB,CAoD3B"} +\ No newline at end of file diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index c7abd76ec606..4d5145e876f6 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -159,7 +159,11 @@ import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; ///: END:ONLY_INCLUDE_IF import { AssetType, TokenStandard } from '../../shared/constants/transaction'; -import { SWAPS_CLIENT_ID } from '../../shared/constants/swaps'; +import { + GAS_API_BASE_URL, + GAS_DEV_API_BASE_URL, + SWAPS_CLIENT_ID, +} from '../../shared/constants/swaps'; import { CHAIN_IDS, NETWORK_TYPES, @@ -776,6 +780,10 @@ export default class MetamaskController extends EventEmitter { allowedEvents: ['NetworkController:stateChange'], }); + const gasApiBaseUrl = process.env.SWAPS_USE_DEV_APIS + ? GAS_DEV_API_BASE_URL + : GAS_API_BASE_URL; + this.gasFeeController = new GasFeeController({ state: initState.GasFeeController, interval: 10000, @@ -795,12 +803,13 @@ export default class MetamaskController extends EventEmitter { ), getCurrentAccountEIP1559Compatibility: this.getCurrentAccountEIP1559Compatibility.bind(this), + legacyAPIEndpoint: `${gasApiBaseUrl}/networks/<chain_id>/gasPrices`, + EIP1559APIEndpoint: `${gasApiBaseUrl}/networks/<chain_id>/suggestedGasFees`, getCurrentNetworkLegacyGasAPICompatibility: () => { const { chainId } = this.networkController.state.providerConfig; return chainId === CHAIN_IDS.BSC; }, getChainId: () => this.networkController.state.providerConfig.chainId, - infuraAPIKey: opts.infuraProjectId, }); this.appStateController = new AppStateController({ diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 42b366d8270a..2fe1806d1e1c 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -1466,7 +1466,6 @@ "@metamask/eth-query": true, "@metamask/gas-fee-controller>@metamask/controller-utils": true, "bn.js": true, - "browserify>buffer": true, "uuid": true } }, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index a79a242eb914..853f45039ae3 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -1466,7 +1466,6 @@ "@metamask/eth-query": true, "@metamask/gas-fee-controller>@metamask/controller-utils": true, "bn.js": true, - "browserify>buffer": true, "uuid": true } }, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index a79a242eb914..853f45039ae3 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -1466,7 +1466,6 @@ "@metamask/eth-query": true, "@metamask/gas-fee-controller>@metamask/controller-utils": true, "bn.js": true, - "browserify>buffer": true, "uuid": true } }, diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index f97f4a34f66f..7e1c1320bc3d 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -1751,7 +1751,6 @@ "@metamask/eth-query": true, "@metamask/gas-fee-controller>@metamask/controller-utils": true, "bn.js": true, - "browserify>buffer": true, "uuid": true } }, diff --git a/package.json b/package.json index 003e22c504d3..889deb2d6bf4 100644 --- a/package.json +++ b/package.json @@ -254,7 +254,8 @@ "@expo/config-plugins/glob": "^10.3.10", "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch", "@solana/web3.js/rpc-websockets": "^8.0.1", - "@metamask/network-controller@npm:^19.0.0": "patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch" + "@metamask/network-controller@npm:^19.0.0": "patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch", + "@metamask/gas-fee-controller@npm:^15.1.1": "patch:@metamask/gas-fee-controller@npm%3A15.1.2#~/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch" }, "dependencies": { "@babel/runtime": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch", @@ -305,7 +306,7 @@ "@metamask/ethjs": "^0.6.0", "@metamask/ethjs-contract": "^0.4.1", "@metamask/ethjs-query": "^0.7.1", - "@metamask/gas-fee-controller": "^15.1.2", + "@metamask/gas-fee-controller": "patch:@metamask/gas-fee-controller@npm%3A15.1.2#~/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch", "@metamask/jazzicon": "^2.0.0", "@metamask/keyring-api": "^8.0.0", "@metamask/keyring-controller": "patch:@metamask/keyring-controller@npm%3A15.0.0#~/.yarn/patches/@metamask-keyring-controller-npm-15.0.0-fa070ce311.patch", diff --git a/privacy-snapshot.json b/privacy-snapshot.json index 499582424bd4..b45cf79a6e8f 100644 --- a/privacy-snapshot.json +++ b/privacy-snapshot.json @@ -18,7 +18,7 @@ "etherscan.io", "execution.metamask.io", "fonts.gstatic.com", - "gas.api.infura.io", + "gas.api.cx.metamask.io", "github.com", "goerli.infura.io", "localhost:8000", diff --git a/shared/constants/swaps.ts b/shared/constants/swaps.ts index 61f9b58b3ed5..bd3db9d94a2f 100644 --- a/shared/constants/swaps.ts +++ b/shared/constants/swaps.ts @@ -171,7 +171,7 @@ const SWAPS_TESTNET_CHAIN_ID = '0x539'; export const SWAPS_API_V2_BASE_URL = 'https://swap.api.cx.metamask.io'; export const SWAPS_DEV_API_V2_BASE_URL = 'https://swap.dev-api.cx.metamask.io'; export const TOKEN_API_BASE_URL = 'https://tokens.api.cx.metamask.io'; -export const GAS_API_BASE_URL = 'https://gas.api.infura.io'; +export const GAS_API_BASE_URL = 'https://gas.api.cx.metamask.io'; export const GAS_DEV_API_BASE_URL = 'https://gas.uat-api.cx.metamask.io'; const BSC_DEFAULT_BLOCK_EXPLORER_URL = 'https://bscscan.com/'; diff --git a/shared/lib/swaps-utils.js b/shared/lib/swaps-utils.js index 303e0f12f0e1..f27f4c9e8a8f 100644 --- a/shared/lib/swaps-utils.js +++ b/shared/lib/swaps-utils.js @@ -3,6 +3,7 @@ import log from 'loglevel'; import { CHAIN_IDS } from '../constants/network'; import { GAS_API_BASE_URL, + GAS_DEV_API_BASE_URL, SWAPS_API_V2_BASE_URL, SWAPS_CHAINID_DEFAULT_TOKEN_MAP, SWAPS_CLIENT_ID, @@ -130,7 +131,7 @@ const getBaseUrlForNewSwapsApi = (type, chainId) => { const v2ApiBaseUrl = useDevApis ? SWAPS_DEV_API_V2_BASE_URL : SWAPS_API_V2_BASE_URL; - const gasApiBaseUrl = GAS_API_BASE_URL; + const gasApiBaseUrl = useDevApis ? GAS_DEV_API_BASE_URL : GAS_API_BASE_URL; const tokenApiBaseUrl = TOKEN_API_BASE_URL; const noNetworkSpecificTypes = ['refreshTime']; // These types don't need network info in the URL. if (noNetworkSpecificTypes.includes(type)) { diff --git a/test/e2e/mock-e2e.js b/test/e2e/mock-e2e.js index aa4572d842e3..f3279377114d 100644 --- a/test/e2e/mock-e2e.js +++ b/test/e2e/mock-e2e.js @@ -191,60 +191,18 @@ async function setupMocking( }; }); - const gasPricesCallbackMock = () => ({ - statusCode: 200, - json: { - SafeGasPrice: '1', - ProposeGasPrice: '2', - FastGasPrice: '3', - }, - }); - const suggestedGasFeesCallbackMock = () => ({ - statusCode: 200, - json: { - low: { - suggestedMaxPriorityFeePerGas: '1', - suggestedMaxFeePerGas: '20.44436136', - minWaitTimeEstimate: 15000, - maxWaitTimeEstimate: 30000, - }, - medium: { - suggestedMaxPriorityFeePerGas: '1.5', - suggestedMaxFeePerGas: '25.80554517', - minWaitTimeEstimate: 15000, - maxWaitTimeEstimate: 45000, - }, - high: { - suggestedMaxPriorityFeePerGas: '2', - suggestedMaxFeePerGas: '27.277766977', - minWaitTimeEstimate: 15000, - maxWaitTimeEstimate: 60000, - }, - estimatedBaseFee: '19.444436136', - networkCongestion: 0.14685, - latestPriorityFeeRange: ['0.378818859', '6.555563864'], - historicalPriorityFeeRange: ['0.1', '248.262969261'], - historicalBaseFeeRange: ['14.146999781', '28.825256275'], - priorityFeeTrend: 'down', - baseFeeTrend: 'up', - }, - }); - await server .forGet(`${GAS_API_BASE_URL}/networks/${chainId}/gasPrices`) - .thenCallback(gasPricesCallbackMock); - - await server - .forGet(`${GAS_API_BASE_URL}/networks/1/gasPrices`) - .thenCallback(gasPricesCallbackMock); - - await server - .forGet(`${GAS_API_BASE_URL}/networks/1/suggestedGasFees`) - .thenCallback(suggestedGasFeesCallbackMock); - - await server - .forGet(`${GAS_API_BASE_URL}/networks/${chainId}/suggestedGasFees`) - .thenCallback(suggestedGasFeesCallbackMock); + .thenCallback(() => { + return { + statusCode: 200, + json: { + SafeGasPrice: '1', + ProposeGasPrice: '2', + FastGasPrice: '3', + }, + }; + }); await server .forGet(`${SWAPS_API_V2_BASE_URL}/networks/1/token`) @@ -263,6 +221,41 @@ async function setupMocking( }; }); + await server + .forGet(`${GAS_API_BASE_URL}/networks/${chainId}/suggestedGasFees`) + .thenCallback(() => { + return { + statusCode: 200, + json: { + low: { + suggestedMaxPriorityFeePerGas: '1', + suggestedMaxFeePerGas: '20.44436136', + minWaitTimeEstimate: 15000, + maxWaitTimeEstimate: 30000, + }, + medium: { + suggestedMaxPriorityFeePerGas: '1.5', + suggestedMaxFeePerGas: '25.80554517', + minWaitTimeEstimate: 15000, + maxWaitTimeEstimate: 45000, + }, + high: { + suggestedMaxPriorityFeePerGas: '2', + suggestedMaxFeePerGas: '27.277766977', + minWaitTimeEstimate: 15000, + maxWaitTimeEstimate: 60000, + }, + estimatedBaseFee: '19.444436136', + networkCongestion: 0.14685, + latestPriorityFeeRange: ['0.378818859', '6.555563864'], + historicalPriorityFeeRange: ['0.1', '248.262969261'], + historicalBaseFeeRange: ['14.146999781', '28.825256275'], + priorityFeeTrend: 'down', + baseFeeTrend: 'up', + }, + }; + }); + await server .forGet(`${SWAPS_API_V2_BASE_URL}/featureFlags`) .thenCallback(() => { diff --git a/test/jest/constants.js b/test/jest/constants.js index 37253f494720..5f63bda3eb9d 100644 --- a/test/jest/constants.js +++ b/test/jest/constants.js @@ -1,2 +1,2 @@ export const METASWAP_BASE_URL = 'https://swap.api.cx.metamask.io'; -export const GAS_API_URL = 'https://gas.api.infura.io'; +export const GAS_API_URL = 'https://gas.api.cx.metamask.io'; diff --git a/ui/pages/swaps/swaps.util.ts b/ui/pages/swaps/swaps.util.ts index 8d258cbf5a14..ce06d4ef37f8 100644 --- a/ui/pages/swaps/swaps.util.ts +++ b/ui/pages/swaps/swaps.util.ts @@ -49,11 +49,6 @@ const CACHE_REFRESH_FIVE_MINUTES = 300000; const USD_CURRENCY_CODE = 'usd'; const clientIdHeader = { 'X-Client-Id': SWAPS_CLIENT_ID }; -const infuraAuthHeader = { - Authorization: `Basic ${Buffer.from( - `${process.env.INFURA_PROJECT_ID}:`, - ).toString('base64')}`, -}; type Validator = { property: string; @@ -276,13 +271,7 @@ export async function fetchSwapsGasPrices(chainId: any): Promise< const gasPricesUrl = getBaseApi('gasPrices', chainId); const response = await fetchWithCache({ url: gasPricesUrl, - fetchOptions: { - method: 'GET', - headers: { - ...clientIdHeader, - ...infuraAuthHeader, - }, - }, + fetchOptions: { method: 'GET', headers: clientIdHeader }, cacheOptions: { cacheRefreshTime: 30000 }, functionName: 'fetchSwapsGasPrices', }); diff --git a/yarn.lock b/yarn.lock index a3b1636e42c4..53e38866f75d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5408,7 +5408,7 @@ __metadata: languageName: node linkType: hard -"@metamask/gas-fee-controller@npm:^15.1.1, @metamask/gas-fee-controller@npm:^15.1.2": +"@metamask/gas-fee-controller@npm:15.1.2": version: 15.1.2 resolution: "@metamask/gas-fee-controller@npm:15.1.2" dependencies: @@ -5450,6 +5450,27 @@ __metadata: languageName: node linkType: hard +"@metamask/gas-fee-controller@patch:@metamask/gas-fee-controller@npm%3A15.1.2#~/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch": + version: 15.1.2 + resolution: "@metamask/gas-fee-controller@patch:@metamask/gas-fee-controller@npm%3A15.1.2#~/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch::version=15.1.2&hash=c5be0a" + dependencies: + "@metamask/base-controller": "npm:^5.0.2" + "@metamask/controller-utils": "npm:^9.1.0" + "@metamask/eth-query": "npm:^4.0.0" + "@metamask/ethjs-unit": "npm:^0.3.0" + "@metamask/network-controller": "npm:^18.1.0" + "@metamask/polling-controller": "npm:^6.0.2" + "@metamask/utils": "npm:^8.3.0" + "@types/bn.js": "npm:^5.1.5" + "@types/uuid": "npm:^8.3.0" + bn.js: "npm:^5.2.1" + uuid: "npm:^8.3.2" + peerDependencies: + "@metamask/network-controller": ^18.0.0 + checksum: 10/4785ff26e541911ffc5a280a9e1a9a648fb3d89e672afeedcd4951a8f176d8e6ae91192afe56fa943f6b4eeff3ce0dba7ec05228a62a8fee1664bb82642fcc15 + languageName: node + linkType: hard + "@metamask/jazzicon@npm:^2.0.0": version: 2.0.0 resolution: "@metamask/jazzicon@npm:2.0.0" @@ -24962,7 +24983,7 @@ __metadata: "@metamask/ethjs-contract": "npm:^0.4.1" "@metamask/ethjs-query": "npm:^0.7.1" "@metamask/forwarder": "npm:^1.1.0" - "@metamask/gas-fee-controller": "npm:^15.1.2" + "@metamask/gas-fee-controller": "patch:@metamask/gas-fee-controller@npm%3A15.1.2#~/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch" "@metamask/jazzicon": "npm:^2.0.0" "@metamask/keyring-api": "npm:^8.0.0" "@metamask/keyring-controller": "patch:@metamask/keyring-controller@npm%3A15.0.0#~/.yarn/patches/@metamask-keyring-controller-npm-15.0.0-fa070ce311.patch" From 8141ff2b29637ce5817c6595f6ec7b1bbaa41302 Mon Sep 17 00:00:00 2001 From: seaona <54408225+seaona@users.noreply.github.com> Date: Thu, 13 Jun 2024 20:53:11 +0200 Subject: [PATCH 40/61] fix: flaky test `Full-size View Setting @no-mmi opens the extension in popup view when opened from a dapp after enabling it in Advanced Settings` (#25295) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR fixes the flaky test `Full-size View Setting @no-mmi opens the extension in popup view when opened from a dapp after enabling it in Advanced Settings`. The problem is that it can take some time to load the window title, making the test fail. Now, we've added some retry logic, to prevent such cases. See video below This is a follow-up on @hjetpoluru 's work and investigation, so all credit to her :raised_hands: https://github.com/MetaMask/metamask-extension/pull/25150 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25295?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/metamask-extension/issues/24642 ## **Manual testing steps** 1. Check ci 2. Run test locally multiple times ## **Screenshots/Recordings** See how now we enter in the retry loop and the test passes https://github.com/MetaMask/metamask-extension/assets/54408225/d65d3419-0c95-4601-a5f2-5e6ab3ba4037 ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- test/e2e/webdriver/driver.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 6815460f3091..98e55ee28111 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -861,11 +861,21 @@ class Driver { * Retrieves the title of the window tab with the given handle ID. * * @param {int} handlerId - unique ID for the tab whose title is needed. - * @returns {Promise<string>} promise resolving to the tab title after command completion + * @param {number} retries - Number of times to retry fetching the title if not immediately available. + * @param {number} interval - Time in milliseconds to wait between retries. + * @returns {Promise<string>} Promise resolving to the tab title after command completion. + * @throws {Error} Throws an error if the window title does not load within the specified retries. */ - async getWindowTitleByHandlerId(handlerId) { + async getWindowTitleByHandlerId(handlerId, retries = 5, interval = 1000) { await this.driver.switchTo().window(handlerId); - return await this.driver.getTitle(); + for (let attempt = 1; attempt <= retries; attempt++) { + const title = await this.driver.getTitle(); + if (title) { + return title; + } + await new Promise((resolve) => setTimeout(resolve, interval)); + } + throw new Error('Window title did not load within the specified retries'); } /** From 42a0bac6add37efebc16c1bf23cb6f6f36ef28fb Mon Sep 17 00:00:00 2001 From: seaona <54408225+seaona@users.noreply.github.com> Date: Thu, 13 Jun 2024 20:57:20 +0200 Subject: [PATCH 41/61] fix: flaky test `Custom network JSON-RPC API should show warning when adding chainId ` (#25294) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR fixes the flaky test `Custom network JSON-RPC API should show warning when adding chainId`. The race condition is that whenever we are in the process of adding a network, if we click `Approve` before the 3 callout warnings have appeared, nothing happens and we remain in the same popup view. (See video below for visually spotting the race condition). This causes that we don't find the next element which is in the new popup window, which doesn't appear. `TimeoutError: Waiting for element to be located By(xpath, //h4[contains(text(), "You are adding a new RPC provider for Ethereum Mainnet")])` - Circle ci failure: https://app.circleci.com/pipelines/github/MetaMask/metamask-extension/87355/workflows/2a67b631-9bc0-4172-b5bd-4005857200f0/jobs/3197142/parallel-runs/4?filterBy=ALL - Circle ci artifacts: notice how we remained in the first window, instead of displaying the confirmation modal for adding the network ![image](https://github.com/MetaMask/metamask-extension/assets/54408225/c91720d0-e977-4c0c-86a7-949b1b5e463c) [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25294?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/metamask-extension/issues/24632 ## **Manual testing steps** 1. Check ci 2. Run test locally multiple times ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> See how the button can appear slightly before the warnings https://github.com/MetaMask/metamask-extension/assets/54408225/f4c54517-8c70-48a7-ae95-a955fd062905 ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../e2e/tests/network/add-custom-network.spec.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/e2e/tests/network/add-custom-network.spec.js b/test/e2e/tests/network/add-custom-network.spec.js index 5dc761710a33..0cd18c13a9bf 100644 --- a/test/e2e/tests/network/add-custom-network.spec.js +++ b/test/e2e/tests/network/add-custom-network.spec.js @@ -165,6 +165,22 @@ describe('Custom network', function () { windowHandles, ); + // To mitigate a race condition, we wait until the 3 callout warnings appear + await driver.waitForSelector({ + tag: 'span', + text: 'According to our record the network name may not correctly match this chain ID.', + }); + + await driver.waitForSelector({ + tag: 'span', + text: 'According to our records the submitted RPC URL value does not match a known provider for this chain ID.', + }); + + await driver.waitForSelector({ + tag: 'a', + text: 'verify the network details', + }); + await driver.clickElement({ tag: 'button', text: 'Approve', From 5f7830073cb6de43f8682b67cdd02a3a164dbd58 Mon Sep 17 00:00:00 2001 From: Devin <168687171+Devin-Apps@users.noreply.github.com> Date: Fri, 14 Jun 2024 02:41:21 +0530 Subject: [PATCH 42/61] refactor: Migrate Typography to Text component in definition-list.js and contract-token-values.js (#25050) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR migrates the Typography component to the Text component in `definition-list.js` and `contract-token-values.js` files as part of the effort to standardize text rendering across the application. Before and after screenshots are provided to ensure no visual regressions have occurred. Link to Devin run: https://preview.devin.ai/devin/d7074c3ba8244524a09ad51e8e6cd91e [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25050?quickstart=1) ## **Related issues** Partially Fixes: https://github.com/MetaMask/metamask-extension/issues/17670 ## **Manual testing steps** 1. Go to the latest build of storybook in this PR 2. Manually check if the page `DefinitionList` renders correctly 3. Manually check if the page `ContractTokenValues` renders correctly ## **Screenshots/Recordings** ### **Before** - DefinitionList: ![](https://api.devin.ai/attachments/7d8b1de1-22f0-4de5-91f9-87328f0a4bb6/83561859-0c8d-454c-919f-7f110cc985ea.png) - ContractTokenValues: ![](https://api.devin.ai/attachments/fcd5b554-34a8-47ef-9055-23c9414087e4/a76dcc0f-019a-4767-b48c-54d542c2cc19.png) ### **After** - DefinitionList: ![](https://api.devin.ai/attachments/ef772efd-209f-403b-8573-eb4fc9f40a11/279b0fe6-f049-496d-8666-d28cffee1acd.png) - ContractTokenValues: ![](https://api.devin.ai/attachments/651d2da7-b5b6-483d-8f3d-7ea1ae68cfd1/after_changes_contract-token-values.png) ## **Pre-merge author checklist** - [X] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I’ve included tests if applicable - [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Shreyasi Mandal <shreyasi18sia@gmail.com> --- .../ui/definition-list/definition-list.js | 38 ++++++++----------- .../contract-token-values.js | 19 ++++++---- .../add-ethereum-chain.test.js.snap | 16 ++++---- .../token-allowance.test.js.snap | 2 +- 4 files changed, 35 insertions(+), 40 deletions(-) diff --git a/ui/components/ui/definition-list/definition-list.js b/ui/components/ui/definition-list/definition-list.js index a640aed5073e..84a23325b37a 100644 --- a/ui/components/ui/definition-list/definition-list.js +++ b/ui/components/ui/definition-list/definition-list.js @@ -1,15 +1,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import { omit } from 'lodash'; -import Typography from '../typography'; import { Size, - TypographyVariant, - FONT_WEIGHT, - OVERFLOW_WRAP, + TextVariant, + OverflowWrap, TextColor, IconColor, - TextVariant, } from '../../../helpers/constants/design-system'; import Tooltip from '../tooltip'; import { Icon, IconName, IconSize, Text } from '../../component-library'; @@ -34,14 +31,11 @@ export default function DefinitionList({ <dl className="definition-list"> {Object.entries(dictionary).map(([term, definition]) => ( <React.Fragment key={`definition-for-${term}`}> - <Typography - variant={TypographyVariant.H6} - fontWeight={FONT_WEIGHT.BOLD} + <Text + variant={TextVariant.bodySmBold} {...termTypography} - boxProps={{ - marginTop: 0, - marginBottom: 1, - }} + marginTop={0} + marginBottom={1} className="definition-list__term" as="dt" > @@ -60,21 +54,19 @@ export default function DefinitionList({ /> </Tooltip> )} - </Typography> - <Typography - variant={TypographyVariant.H6} + </Text> + <Text + variant={TextVariant.bodySm} color={TextColor.textAlternative} {...definitionTypography} - boxProps={{ - marginTop: 0, - marginBottom: MARGIN_MAP[gapSize], - }} + marginTop={0} + marginBottom={MARGIN_MAP[gapSize]} className="definition-list__definition" - overflowWrap={OVERFLOW_WRAP.BREAK_WORD} + overflowWrap={OverflowWrap.BreakWord} as="dd" > {definition} - </Typography> + </Text> {warnings[term] && ( <Text variant={TextVariant.bodySm} color={TextColor.warningDefault}> {warnings[term]} @@ -94,9 +86,9 @@ DefinitionList.propTypes = { tooltips: PropTypes.objectOf(PropTypes.string), warnings: PropTypes.objectOf(PropTypes.string), termTypography: PropTypes.shape({ - ...omit(TypographyVariant.propTypes, ['tag', 'className', 'boxProps']), + ...omit(TextVariant.propTypes, ['tag', 'className', 'boxProps']), }), definitionTypography: PropTypes.shape({ - ...omit(TypographyVariant.propTypes, ['tag', 'className', 'boxProps']), + ...omit(TextVariant.propTypes, ['tag', 'className', 'boxProps']), }), }; diff --git a/ui/pages/confirmations/components/contract-token-values/contract-token-values.js b/ui/pages/confirmations/components/contract-token-values/contract-token-values.js index 75d06d71c8b9..6858689f77d0 100644 --- a/ui/pages/confirmations/components/contract-token-values/contract-token-values.js +++ b/ui/pages/confirmations/components/contract-token-values/contract-token-values.js @@ -5,18 +5,21 @@ import Box from '../../../../components/ui/box/box'; import Tooltip from '../../../../components/ui/tooltip/tooltip'; import { useI18nContext } from '../../../../hooks/useI18nContext'; import Identicon from '../../../../components/ui/identicon'; -import Typography from '../../../../components/ui/typography/typography'; import { - FONT_WEIGHT, - TypographyVariant, + Text, + ButtonIcon, + IconName, +} from '../../../../components/component-library'; +import { + TextVariant, DISPLAY, AlignItems, JustifyContent, TextColor, Color, + FontWeight, } from '../../../../helpers/constants/design-system'; import { useCopyToClipboard } from '../../../../hooks/useCopyToClipboard'; -import { ButtonIcon, IconName } from '../../../../components/component-library'; export default function ContractTokenValues({ address, @@ -36,15 +39,15 @@ export default function ContractTokenValues({ gap={2} > <Identicon address={address} diameter={24} /> - <Typography - variant={TypographyVariant.H2} - fontWeight={FONT_WEIGHT.BOLD} + <Text + variant={TextVariant.headingLg} + fontWeight={FontWeight.Bold} color={TextColor.textAlternative} marginTop={0} marginBottom={0} > {tokenName} - </Typography> + </Text> <Tooltip position="top" title={copied ? t('copiedExclamation') : t('copyToClipboard')} diff --git a/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap b/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap index a07d4d8bc62a..c0d5c682f312 100644 --- a/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap +++ b/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap @@ -70,7 +70,7 @@ exports[`add-ethereum-chain confirmation should match snapshot 1`] = ` class="definition-list" > <dt - class="box box--margin-bottom-1 box--flex-direction-row typography definition-list__term typography--h6 typography--weight-bold typography--style-normal typography--color-text-default" + class="mm-box mm-text definition-list__term mm-text--body-sm-bold mm-box--margin-top-0 mm-box--margin-bottom-1 mm-box--color-text-default" > Network name <div> @@ -90,12 +90,12 @@ exports[`add-ethereum-chain confirmation should match snapshot 1`] = ` </div> </dt> <dd - class="box box--margin-bottom-2 box--flex-direction-row typography definition-list__definition typography--h6 typography--weight-normal typography--style-normal typography--color-text-alternative typography--overflowwrap-break-word" + class="mm-box mm-text definition-list__definition mm-text--body-sm mm-text--overflow-wrap-break-word mm-box--margin-top-0 mm-box--margin-bottom-2 mm-box--color-text-alternative" > Test chain </dd> <dt - class="box box--margin-bottom-1 box--flex-direction-row typography definition-list__term typography--h6 typography--weight-bold typography--style-normal typography--color-text-default" + class="mm-box mm-text definition-list__term mm-text--body-sm-bold mm-box--margin-top-0 mm-box--margin-bottom-1 mm-box--color-text-default" > Network URL <div> @@ -115,12 +115,12 @@ exports[`add-ethereum-chain confirmation should match snapshot 1`] = ` </div> </dt> <dd - class="box box--margin-bottom-2 box--flex-direction-row typography definition-list__definition typography--h6 typography--weight-normal typography--style-normal typography--color-text-alternative typography--overflowwrap-break-word" + class="mm-box mm-text definition-list__definition mm-text--body-sm mm-text--overflow-wrap-break-word mm-box--margin-top-0 mm-box--margin-bottom-2 mm-box--color-text-alternative" > https://rpcurl.test.chain </dd> <dt - class="box box--margin-bottom-1 box--flex-direction-row typography definition-list__term typography--h6 typography--weight-bold typography--style-normal typography--color-text-default" + class="mm-box mm-text definition-list__term mm-text--body-sm-bold mm-box--margin-top-0 mm-box--margin-bottom-1 mm-box--color-text-default" > Chain ID <div> @@ -140,12 +140,12 @@ exports[`add-ethereum-chain confirmation should match snapshot 1`] = ` </div> </dt> <dd - class="box box--margin-bottom-2 box--flex-direction-row typography definition-list__definition typography--h6 typography--weight-normal typography--style-normal typography--color-text-alternative typography--overflowwrap-break-word" + class="mm-box mm-text definition-list__definition mm-text--body-sm mm-text--overflow-wrap-break-word mm-box--margin-top-0 mm-box--margin-bottom-2 mm-box--color-text-alternative" > 39321 </dd> <dt - class="box box--margin-bottom-1 box--flex-direction-row typography definition-list__term typography--h6 typography--weight-bold typography--style-normal typography--color-text-default" + class="mm-box mm-text definition-list__term mm-text--body-sm-bold mm-box--margin-top-0 mm-box--margin-bottom-1 mm-box--color-text-default" > Currency symbol <div> @@ -165,7 +165,7 @@ exports[`add-ethereum-chain confirmation should match snapshot 1`] = ` </div> </dt> <dd - class="box box--margin-bottom-2 box--flex-direction-row typography definition-list__definition typography--h6 typography--weight-normal typography--style-normal typography--color-text-alternative typography--overflowwrap-break-word" + class="mm-box mm-text definition-list__definition mm-text--body-sm mm-text--overflow-wrap-break-word mm-box--margin-top-0 mm-box--margin-bottom-2 mm-box--color-text-alternative" > TST </dd> diff --git a/ui/pages/confirmations/token-allowance/__snapshots__/token-allowance.test.js.snap b/ui/pages/confirmations/token-allowance/__snapshots__/token-allowance.test.js.snap index ca5141f6f873..e23e18cc2568 100644 --- a/ui/pages/confirmations/token-allowance/__snapshots__/token-allowance.test.js.snap +++ b/ui/pages/confirmations/token-allowance/__snapshots__/token-allowance.test.js.snap @@ -275,7 +275,7 @@ exports[`TokenAllowancePage when mounted should match snapshot 1`] = ` </div> </div> <h2 - class="box box--flex-direction-row typography typography--h2 typography--weight-bold typography--style-normal typography--color-text-alternative" + class="mm-box mm-text mm-text--heading-lg mm-text--font-weight-bold mm-box--margin-top-0 mm-box--margin-bottom-0 mm-box--color-text-alternative" > TST </h2> From 95b10da98f6add83aefb958696206c685af77ad7 Mon Sep 17 00:00:00 2001 From: Devin <168687171+Devin-Apps@users.noreply.github.com> Date: Fri, 14 Jun 2024 02:42:08 +0530 Subject: [PATCH 43/61] refactor: Part of #17670 - Replace Typography with Text component in ui/components/ui/chip/chip.js (#25017) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Migrate Typography to Text component in Chip component. This change is part of the effort to standardize text rendering across the application and ensure consistency in the design system. Before and after screenshots have been provided to ensure no visual regressions. ### Devin Preview Link https://preview.devin.ai/devin/2c41e8916ed14a95ae831b29501815ff ## **Related issues** Partially fixes: https://github.com/MetaMask/metamask-extension/issues/17670 ## **Manual testing steps** 1. Go to the latest build of storybook in this PR 2. Manually check if the page `Chip` renders correctly ## **Screenshots/Recordings** ### Before ![](https://api.devin.ai/attachments/d39de035-52cf-4e56-971e-f6578ff74405/aec5d600-87af-4486-a493-3c2c5da4cbef.png) ### After ![](https://api.devin.ai/attachments/327f61ef-9cef-4307-bfba-149e3062fd75/44134084-057e-4d59-b98e-ed3cdd97ceee.png) ## **Pre-merge author checklist** - [X] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I’ve included tests if applicable - [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Shreyasi Mandal <shreyasi18sia@gmail.com> --- ui/components/ui/chip/chip.js | 12 ++++++------ .../confirm-add-suggested-nft.test.js.snap | 4 ++-- ...firm-page-container-header.component.test.js.snap | 2 +- .../signature-request-original.test.js.snap | 2 +- .../signature-request-siwe.test.js.snap | 2 +- .../signature-request-header.component.test.js.snap | 4 ++-- .../__snapshots__/confirm-send-ether.test.js.snap | 2 +- .../__snapshots__/add-ethereum-chain.test.js.snap | 2 +- .../__snapshots__/switch-ethereum-chain.test.js.snap | 4 ++-- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ui/components/ui/chip/chip.js b/ui/components/ui/chip/chip.js index cdd961dbb71e..8593dd055845 100644 --- a/ui/components/ui/chip/chip.js +++ b/ui/components/ui/chip/chip.js @@ -2,13 +2,13 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { omit } from 'lodash'; -import Typography from '../typography'; +import { Text } from '../../component-library'; import UrlIcon from '../url-icon'; import { BackgroundColor, BorderColor, TextColor, - TypographyVariant, + TextVariant, } from '../../../helpers/constants/design-system'; /** @@ -66,15 +66,15 @@ export default function Chip({ <UrlIcon className="chip__left-url-icon" url={leftIconUrl} /> ) : null} {children ?? ( - <Typography + <Text className="chip__label" - variant={TypographyVariant.H6} + variant={TextVariant.bodySm} as="span" color={TextColor.textAlternative} {...labelProps} > {label} - </Typography> + </Text> )} {rightIcon ? <div className="chip__right-icon">{rightIcon}</div> : null} </div> @@ -102,7 +102,7 @@ Chip.propTypes = { * The label props of the component. Most Typography props can be used */ labelProps: PropTypes.shape({ - ...omit(TypographyVariant.propTypes, ['children', 'className']), + ...omit(TextVariant.propTypes, ['children', 'className']), }), /** * Children will replace the label of the Chip component. diff --git a/ui/pages/confirm-add-suggested-nft/__snapshots__/confirm-add-suggested-nft.test.js.snap b/ui/pages/confirm-add-suggested-nft/__snapshots__/confirm-add-suggested-nft.test.js.snap index b740ec784d5c..eca476209a9c 100644 --- a/ui/pages/confirm-add-suggested-nft/__snapshots__/confirm-add-suggested-nft.test.js.snap +++ b/ui/pages/confirm-add-suggested-nft/__snapshots__/confirm-add-suggested-nft.test.js.snap @@ -135,7 +135,7 @@ exports[`ConfirmAddSuggestedNFT Component should match snapshot 1`] = ` </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h6 typography--weight-normal typography--style-normal typography--color-text-alternative" + class="mm-box mm-text chip__label mm-text--body-sm mm-box--color-text-alternative" > https://www.opensea.io </span> @@ -347,7 +347,7 @@ exports[`ConfirmAddSuggestedNFT Component should match snapshot 1`] = ` </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h6 typography--weight-normal typography--style-normal typography--color-text-alternative" + class="mm-box mm-text chip__label mm-text--body-sm mm-box--color-text-alternative" > https://www.opensea.io </span> diff --git a/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/__snapshots__/confirm-page-container-header.component.test.js.snap b/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/__snapshots__/confirm-page-container-header.component.test.js.snap index 6bcd678b78c5..e18103e853e5 100644 --- a/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/__snapshots__/confirm-page-container-header.component.test.js.snap +++ b/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/__snapshots__/confirm-page-container-header.component.test.js.snap @@ -41,7 +41,7 @@ exports[`Confirm Detail Row Component should match snapshot 1`] = ` </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h7 typography--weight-normal typography--style-normal typography--color-text-alternative" + class="mm-box mm-text chip__label mm-text--h7 mm-box--color-text-alternative" > Private network </span> diff --git a/ui/pages/confirmations/components/signature-request-original/__snapshots__/signature-request-original.test.js.snap b/ui/pages/confirmations/components/signature-request-original/__snapshots__/signature-request-original.test.js.snap index 397ee6f14ffd..9ed331fefe28 100644 --- a/ui/pages/confirmations/components/signature-request-original/__snapshots__/signature-request-original.test.js.snap +++ b/ui/pages/confirmations/components/signature-request-original/__snapshots__/signature-request-original.test.js.snap @@ -202,7 +202,7 @@ exports[`SignatureRequestOriginal should match snapshot 1`] = ` </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h6 typography--weight-normal typography--style-normal typography--color-text-alternative" + class="mm-box mm-text chip__label mm-text--body-sm mm-box--color-text-alternative" > https://happydapp.website/governance?futarchy=true </span> diff --git a/ui/pages/confirmations/components/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap b/ui/pages/confirmations/components/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap index b962fa7a9d6e..a1219a561ba7 100644 --- a/ui/pages/confirmations/components/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap +++ b/ui/pages/confirmations/components/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap @@ -203,7 +203,7 @@ exports[`SignatureRequestSIWE (Sign in with Ethereum) should match snapshot 1`] </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h6 typography--weight-normal typography--style-normal typography--color-text-alternative" + class="mm-box mm-text chip__label mm-text--body-sm mm-box--color-text-alternative" > https://example-dapp.website </span> diff --git a/ui/pages/confirmations/components/signature-request/signature-request-header/__snapshots__/signature-request-header.component.test.js.snap b/ui/pages/confirmations/components/signature-request/signature-request-header/__snapshots__/signature-request-header.component.test.js.snap index 332fa46e439b..b188b22166c8 100644 --- a/ui/pages/confirmations/components/signature-request/signature-request-header/__snapshots__/signature-request-header.component.test.js.snap +++ b/ui/pages/confirmations/components/signature-request/signature-request-header/__snapshots__/signature-request-header.component.test.js.snap @@ -87,7 +87,7 @@ exports[`SignatureRequestHeader renders correctly with fromAccount 1`] = ` </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h7 typography--weight-normal typography--style-normal typography--color-text-alternative" + class="mm-box mm-text chip__label mm-text--h7 mm-box--color-text-alternative" > goerli </span> @@ -125,7 +125,7 @@ exports[`SignatureRequestHeader renders correctly without fromAccount 1`] = ` </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h7 typography--weight-normal typography--style-normal typography--color-text-alternative" + class="mm-box mm-text chip__label mm-text--h7 mm-box--color-text-alternative" > goerli </span> diff --git a/ui/pages/confirmations/confirm-send-ether/__snapshots__/confirm-send-ether.test.js.snap b/ui/pages/confirmations/confirm-send-ether/__snapshots__/confirm-send-ether.test.js.snap index d577a079e735..7b2ea95038b8 100644 --- a/ui/pages/confirmations/confirm-send-ether/__snapshots__/confirm-send-ether.test.js.snap +++ b/ui/pages/confirmations/confirm-send-ether/__snapshots__/confirm-send-ether.test.js.snap @@ -96,7 +96,7 @@ exports[`ConfirmSendEther should render correct information for for confirm send </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h7 typography--weight-normal typography--style-normal typography--color-text-alternative" + class="mm-box mm-text chip__label mm-text--h7 mm-box--color-text-alternative" > goerli </span> diff --git a/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap b/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap index c0d5c682f312..b93ff5aa52b8 100644 --- a/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap +++ b/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap @@ -28,7 +28,7 @@ exports[`add-ethereum-chain confirmation should match snapshot 1`] = ` </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h7 typography--weight-normal typography--style-normal typography--color-text-default" + class="mm-box mm-text chip__label mm-text--h7 mm-box--color-text-default" > Test initial state </span> diff --git a/ui/pages/confirmations/confirmation/templates/__snapshots__/switch-ethereum-chain.test.js.snap b/ui/pages/confirmations/confirmation/templates/__snapshots__/switch-ethereum-chain.test.js.snap index bdd900cdc72f..8e0ba8ed7bfb 100644 --- a/ui/pages/confirmations/confirmation/templates/__snapshots__/switch-ethereum-chain.test.js.snap +++ b/ui/pages/confirmations/confirmation/templates/__snapshots__/switch-ethereum-chain.test.js.snap @@ -28,7 +28,7 @@ exports[`switch-ethereum-chain confirmation should match snapshot 1`] = ` </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h7 typography--weight-normal typography--style-normal typography--color-text-default" + class="mm-box mm-text chip__label mm-text--h7 mm-box--color-text-default" > Test initial state </span> @@ -147,7 +147,7 @@ exports[`switch-ethereum-chain confirmation should show alert if there are pendi </div> </div> <span - class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h7 typography--weight-normal typography--style-normal typography--color-text-default" + class="mm-box mm-text chip__label mm-text--h7 mm-box--color-text-default" > Test initial state </span> From 853947713f80c9a981a1fee47d150cc9eea91240 Mon Sep 17 00:00:00 2001 From: Monte Lai <monte.lai@consensys.net> Date: Fri, 14 Jun 2024 15:53:34 +0800 Subject: [PATCH 44/61] feat: filter eth requests for non-EVM accounts (#25038) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR adds a new middleware to filter EVM requests that goes to non-EVM accounts. ## **Related issues** Fixes https://github.com/MetaMask/accounts-planning/issues/462 ## **Manual testing steps** ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** ### **After** ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../controllers/mmi-controller.test.ts | 215 +++++++------ .../controllers/permissions/specifications.js | 17 +- .../permissions/specifications.test.js | 47 +-- ...ToNonEvmAccountReqFilterMiddleware.test.ts | 285 ++++++++++++++++++ ...thodsToNonEvmAccountReqFilterMiddleware.ts | 94 ++++++ app/scripts/metamask-controller.js | 12 + shared/constants/permissions.ts | 4 + 7 files changed, 556 insertions(+), 118 deletions(-) create mode 100644 app/scripts/lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware.test.ts create mode 100644 app/scripts/lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware.ts diff --git a/app/scripts/controllers/mmi-controller.test.ts b/app/scripts/controllers/mmi-controller.test.ts index 3616c7ae29fe..102cd63d52f3 100644 --- a/app/scripts/controllers/mmi-controller.test.ts +++ b/app/scripts/controllers/mmi-controller.test.ts @@ -29,6 +29,7 @@ jest.mock('@metamask-institutional/portfolio-dashboard', () => ({ })); jest.mock('./permissions', () => ({ + ...jest.requireActual('./permissions'), getPermissionBackgroundApiMethods: jest.fn().mockImplementation(() => { return { addPermittedAccount: jest.fn(), @@ -299,12 +300,12 @@ describe('MMIController', function () { const result = await mmiController.addKeyringIfNotExists(type); - expect(mmiController.keyringController.getKeyringsByType).toHaveBeenCalledWith( - type - ); - expect(mmiController.keyringController.addNewKeyring).toHaveBeenCalledWith( - type - ); + expect( + mmiController.keyringController.getKeyringsByType, + ).toHaveBeenCalledWith(type); + expect( + mmiController.keyringController.addNewKeyring, + ).toHaveBeenCalledWith(type); expect(result).toBe('new-keyring'); }); @@ -318,10 +319,12 @@ describe('MMIController', function () { const result = await mmiController.addKeyringIfNotExists(type); - expect(mmiController.keyringController.getKeyringsByType).toHaveBeenCalledWith( - type - ); - expect(mmiController.keyringController.addNewKeyring).not.toHaveBeenCalled(); + expect( + mmiController.keyringController.getKeyringsByType, + ).toHaveBeenCalledWith(type); + expect( + mmiController.keyringController.addNewKeyring, + ).not.toHaveBeenCalled(); expect(result).toBe(existingKeyring); }); }); @@ -331,27 +334,30 @@ describe('MMIController', function () { mmiController.custodyController.getAllCustodyTypes = jest .fn() .mockReturnValue(['mock-custody-type']); - mmiController.addKeyringIfNotExists = jest - .fn() - .mockResolvedValue({ - on: jest.fn(), - getAccounts: jest.fn().mockResolvedValue(['0x1']), - getSupportedChains: jest.fn().mockResolvedValue({}), - }); + mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue({ + on: jest.fn(), + getAccounts: jest.fn().mockResolvedValue(['0x1']), + getSupportedChains: jest.fn().mockResolvedValue({}), + }); mmiController.storeCustodianSupportedChains = jest.fn(); mmiController.txStateManager = { getTransactions: jest.fn().mockReturnValue([]), }; mmiController.transactionUpdateController.subscribeToEvents = jest.fn(); mmiController.mmiConfigurationController.storeConfiguration = jest.fn(); - mmiController.transactionUpdateController.getCustomerProofForAddresses = jest.fn(); + mmiController.transactionUpdateController.getCustomerProofForAddresses = + jest.fn(); await mmiController.onSubmitPassword(); expect(mmiController.addKeyringIfNotExists).toHaveBeenCalled(); expect(mmiController.storeCustodianSupportedChains).toHaveBeenCalled(); - expect(mmiController.transactionUpdateController.subscribeToEvents).toHaveBeenCalled(); - expect(mmiController.mmiConfigurationController.storeConfiguration).toHaveBeenCalled(); + expect( + mmiController.transactionUpdateController.subscribeToEvents, + ).toHaveBeenCalled(); + expect( + mmiController.mmiConfigurationController.storeConfiguration, + ).toHaveBeenCalled(); }); }); @@ -368,20 +374,20 @@ describe('MMIController', function () { chainId: 1, }, }; - CUSTODIAN_TYPES['MOCK-CUSTODIAN-TYPE'] = { keyringClass: { type: 'mock-keyring-class' } }; - mmiController.addKeyringIfNotExists = jest - .fn() - .mockResolvedValue({ - on: jest.fn(), - setSelectedAddresses: jest.fn(), - addAccounts: jest.fn(), - addNewAccountForKeyring: jest.fn(), - getStatusMap: jest.fn(), - }); + CUSTODIAN_TYPES['MOCK-CUSTODIAN-TYPE'] = { + keyringClass: { type: 'mock-keyring-class' }, + }; + mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue({ + on: jest.fn(), + setSelectedAddresses: jest.fn(), + addAccounts: jest.fn(), + addNewAccountForKeyring: jest.fn(), + getStatusMap: jest.fn(), + }); mmiController.keyringController.getAccounts = jest .fn() .mockResolvedValue(['0x2']); - mmiController.keyringController.addNewAccountForKeyring = jest.fn() + mmiController.keyringController.addNewAccountForKeyring = jest.fn(); mmiController.custodyController.setAccountDetails = jest.fn(); mmiController.accountTracker.syncWithAddresses = jest.fn(); @@ -391,51 +397,55 @@ describe('MMIController', function () { const result = await mmiController.connectCustodyAddresses( custodianType, custodianName, - accounts + accounts, ); expect(mmiController.addKeyringIfNotExists).toHaveBeenCalled(); expect(mmiController.keyringController.getAccounts).toHaveBeenCalled(); - expect(mmiController.custodyController.setAccountDetails).toHaveBeenCalled(); + expect( + mmiController.custodyController.setAccountDetails, + ).toHaveBeenCalled(); expect(mmiController.accountTracker.syncWithAddresses).toHaveBeenCalled(); expect(mmiController.storeCustodianSupportedChains).toHaveBeenCalled(); - expect(mmiController.custodyController.storeCustodyStatusMap).toHaveBeenCalled(); + expect( + mmiController.custodyController.storeCustodyStatusMap, + ).toHaveBeenCalled(); expect(result).toEqual(['0x1']); }); }); describe('getCustodianAccounts', () => { it('should return custodian accounts', async () => { - CUSTODIAN_TYPES['MOCK-CUSTODIAN-TYPE'] = { keyringClass: { type: 'mock-keyring-class' } }; - mmiController.addKeyringIfNotExists = jest - .fn() - .mockResolvedValue({ - getCustodianAccounts: jest.fn().mockResolvedValue(['account1']), - }); + CUSTODIAN_TYPES['MOCK-CUSTODIAN-TYPE'] = { + keyringClass: { type: 'mock-keyring-class' }, + }; + mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue({ + getCustodianAccounts: jest.fn().mockResolvedValue(['account1']), + }); const result = await mmiController.getCustodianAccounts( 'token', 'neptune-custody', 'ECA3', - true + true, ); expect(result).toEqual(['account1']); }); it('should return custodian accounts when custodianType is not provided', async () => { - CUSTODIAN_TYPES['CUSTODIAN-TYPE'] = { keyringClass: { type: 'mock-keyring-class' } }; + CUSTODIAN_TYPES['CUSTODIAN-TYPE'] = { + keyringClass: { type: 'mock-keyring-class' }, + }; mmiController.messenger.call = jest .fn() .mockReturnValue({ address: '0x1' }); mmiController.custodyController.getCustodyTypeByAddress = jest .fn() .mockReturnValue('custodian-type'); - mmiController.addKeyringIfNotExists = jest - .fn() - .mockResolvedValue({ - getCustodianAccounts: jest.fn().mockResolvedValue(['account1']), - }); + mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue({ + getCustodianAccounts: jest.fn().mockResolvedValue(['account1']), + }); const result = await mmiController.getCustodianAccounts( 'token', @@ -448,18 +458,18 @@ describe('MMIController', function () { describe('getCustodianAccountsByAddress', () => { it('should return custodian accounts by address', async () => { - CUSTODIAN_TYPES['MOCK-CUSTODIAN-TYPE'] = { keyringClass: { type: 'mock-keyring-class' } }; - mmiController.addKeyringIfNotExists = jest - .fn() - .mockResolvedValue({ - getCustodianAccounts: jest.fn().mockResolvedValue(['account1']), - }); + CUSTODIAN_TYPES['MOCK-CUSTODIAN-TYPE'] = { + keyringClass: { type: 'mock-keyring-class' }, + }; + mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue({ + getCustodianAccounts: jest.fn().mockResolvedValue(['account1']), + }); const result = await mmiController.getCustodianAccountsByAddress( 'token', 'envName', 'address', - 'mock-custodian-type' + 'mock-custodian-type', ); expect(result).toEqual(['account1']); @@ -471,17 +481,15 @@ describe('MMIController', function () { mmiController.custodyController.getCustodyTypeByAddress = jest .fn() .mockReturnValue('custodyType'); - mmiController.addKeyringIfNotExists = jest - .fn() - .mockResolvedValue({ - getTransactionDeepLink: jest - .fn() - .mockResolvedValue('transactionDeepLink'), - }); + mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue({ + getTransactionDeepLink: jest + .fn() + .mockResolvedValue('transactionDeepLink'), + }); const result = await mmiController.getCustodianTransactionDeepLink( 'address', - 'txId' + 'txId', ); expect(result).toEqual('transactionDeepLink'); @@ -502,13 +510,11 @@ describe('MMIController', function () { mmiController.custodyController.getCustodyTypeByAddress = jest .fn() .mockReturnValue('custodyType'); - mmiController.addKeyringIfNotExists = jest - .fn() - .mockResolvedValue({ - getTransactionDeepLink: jest - .fn() - .mockResolvedValue('transactionDeepLink'), - }); + mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue({ + getTransactionDeepLink: jest + .fn() + .mockResolvedValue('transactionDeepLink'), + }); const result = await mmiController.getCustodianConfirmDeepLink('txId'); @@ -524,17 +530,15 @@ describe('MMIController', function () { mmiController.custodyController.getCustodyTypeByAddress = jest .fn() .mockReturnValue('custodyType'); - mmiController.addKeyringIfNotExists = jest - .fn() - .mockResolvedValue({ - getTransactionDeepLink: jest - .fn() - .mockResolvedValue('transactionDeepLink'), - }); + mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue({ + getTransactionDeepLink: jest + .fn() + .mockResolvedValue('transactionDeepLink'), + }); const result = await mmiController.getCustodianSignMessageDeepLink( 'address', - 'custodyTxId' + 'custodyTxId', ); expect(result).toEqual('transactionDeepLink'); @@ -595,7 +599,7 @@ describe('MMIController', function () { ]); const result = await mmiController.getCustodianJWTList( - 'custodianEnvName' + 'custodianEnvName', ); expect(result).toEqual([]); @@ -614,7 +618,7 @@ describe('MMIController', function () { const result = await mmiController.getAllCustodianAccountsWithToken( 'custodyType', - 'token' + 'token', ); expect(result).toEqual(['account1']); @@ -629,14 +633,19 @@ describe('MMIController', function () { const keyringMock = { replaceRefreshTokenAuthDetails: jest.fn(), }; - mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue(keyringMock); + mmiController.addKeyringIfNotExists = jest + .fn() + .mockResolvedValue(keyringMock); await mmiController.setCustodianNewRefreshToken({ address: 'address', refreshToken: 'refreshToken', }); - expect(keyringMock.replaceRefreshTokenAuthDetails).toHaveBeenCalledWith('address', 'refreshToken'); + expect(keyringMock.replaceRefreshTokenAuthDetails).toHaveBeenCalledWith( + 'address', + 'refreshToken', + ); }); }); @@ -652,7 +661,8 @@ describe('MMIController', function () { .fn() .mockResolvedValue('keyring'); mmiController.appStateController.getUnlockPromise = jest.fn(); - mmiController.custodyController.handleMmiCheckIfTokenIsPresent = jest.fn(); + mmiController.custodyController.handleMmiCheckIfTokenIsPresent = + jest.fn(); await mmiController.handleMmiCheckIfTokenIsPresent({ params: { @@ -662,8 +672,12 @@ describe('MMIController', function () { }, }); - expect(mmiController.appStateController.getUnlockPromise).toHaveBeenCalled(); - expect(mmiController.custodyController.handleMmiCheckIfTokenIsPresent).toHaveBeenCalled(); + expect( + mmiController.appStateController.getUnlockPromise, + ).toHaveBeenCalled(); + expect( + mmiController.custodyController.handleMmiCheckIfTokenIsPresent, + ).toHaveBeenCalled(); }); }); @@ -673,7 +687,7 @@ describe('MMIController', function () { await mmiController.handleMmiDashboardData(); expect(controllerMessengerSpy).toHaveBeenCalledWith( - 'AccountsController:listAccounts' + 'AccountsController:listAccounts', ); expect(controllerMessengerSpy).toHaveReturnedWith([ mockAccount, @@ -689,7 +703,7 @@ describe('MMIController', function () { networks: expect.anything(), getAccountDetails: expect.anything(), extensionId: expect.anything(), - }) + }), ); }); }); @@ -710,7 +724,7 @@ describe('MMIController', function () { const result = await mmiController.newUnsignedMessage( message, request, - 'v4' + 'v4', ); expect(result).toEqual('unsignedTypedMessage'); @@ -733,16 +747,15 @@ describe('MMIController', function () { await mmiController.handleSigningEvents( signature, messageId, - 'signOperation' + 'signOperation', ); expect( - mmiController.transactionUpdateController.addTransactionToWatchList + mmiController.transactionUpdateController.addTransactionToWatchList, ).toHaveBeenCalledWith('custodianTxId', '0x1', 'signOperation', true); - expect(mmiController.signatureController.setMessageMetadata).toHaveBeenCalledWith( - messageId, - signature - ); + expect( + mmiController.signatureController.setMessageMetadata, + ).toHaveBeenCalledWith(messageId, signature); }); }); @@ -752,12 +765,12 @@ describe('MMIController', function () { await mmiController.setAccountAndNetwork( 'mock-origin', mockAccount2.address, - '0x1' + '0x1', ); expect(selectedAccountSpy).toHaveBeenCalledWith( 'AccountsController:setSelectedAccount', - mockAccount2.id + mockAccount2.id, ); const selectedAccount = accountsController.getSelectedAccount(); @@ -770,7 +783,7 @@ describe('MMIController', function () { await mmiController.setAccountAndNetwork( 'mock-origin', mockAccount.address, - '0x1' + '0x1', ); expect(selectedAccountSpy).toHaveBeenCalledTimes(1); @@ -786,10 +799,12 @@ describe('MMIController', function () { await mmiController.handleMmiOpenAddHardwareWallet(); - expect(mmiController.appStateController.getUnlockPromise).toHaveBeenCalled(); - expect(mmiController.platform.openExtensionInBrowser).toHaveBeenCalledWith( - '/new-account/connect' - ); + expect( + mmiController.appStateController.getUnlockPromise, + ).toHaveBeenCalled(); + expect( + mmiController.platform.openExtensionInBrowser, + ).toHaveBeenCalledWith('/new-account/connect'); }); }); }); diff --git a/app/scripts/controllers/permissions/specifications.js b/app/scripts/controllers/permissions/specifications.js index 4f9d402dcc03..1caacf7d1cfd 100644 --- a/app/scripts/controllers/permissions/specifications.js +++ b/app/scripts/controllers/permissions/specifications.js @@ -9,6 +9,7 @@ import { endowmentCaveatSpecifications as snapsEndowmentCaveatSpecifications, } from '@metamask/snaps-rpc-methods'; ///: END:ONLY_INCLUDE_IF +import { isValidHexAddress } from '@metamask/utils'; import { CaveatTypes, RestrictedMethods, @@ -141,7 +142,8 @@ export const getPermissionSpecifications = ({ }); }, methodImplementation: async (_args) => { - const accounts = await getAllAccounts(); + // We only consider EVM addresses here, hence the filtering: + const accounts = (await getAllAccounts()).filter(isValidHexAddress); const internalAccounts = getInternalAccounts(); return accounts.sort((firstAddress, secondAddress) => { @@ -308,6 +310,19 @@ function validateCaveatNetworks( }); } +/** + * Unrestricted methods for Ethereum, see {@link unrestrictedMethods} for more details. + */ +export const unrestrictedEthSigningMethods = Object.freeze([ + 'eth_sendRawTransaction', + 'eth_sendTransaction', + 'eth_sign', + 'eth_signTypedData', + 'eth_signTypedData_v1', + 'eth_signTypedData_v3', + 'eth_signTypedData_v4', +]); + /** * All unrestricted methods recognized by the PermissionController. * Unrestricted methods are ignored by the permission system, but every diff --git a/app/scripts/controllers/permissions/specifications.test.js b/app/scripts/controllers/permissions/specifications.test.js index 2a343c5f1689..29f9f4f1b8ce 100644 --- a/app/scripts/controllers/permissions/specifications.test.js +++ b/app/scripts/controllers/permissions/specifications.test.js @@ -361,7 +361,7 @@ describe('PermissionController specifications', () => { const getInternalAccounts = jest.fn().mockImplementationOnce(() => { return [ { - address: '0x1', + address: '0x7A2Bd22810088523516737b4Dc238A4bC37c23F2', id: '21066553-d8c8-4cdc-af33-efc921cd3ca9', metadata: { name: 'Test Account', @@ -375,7 +375,7 @@ describe('PermissionController specifications', () => { type: EthAccountType.Eoa, }, { - address: '0x2', + address: '0x7152f909e5EB3EF198f17e5Cb087c5Ced88294e3', id: '0bd7348e-bdfe-4f67-875c-de831a583857', metadata: { name: 'Test Account', @@ -388,7 +388,7 @@ describe('PermissionController specifications', () => { type: EthAccountType.Eoa, }, { - address: '0x3', + address: '0xDe70d2FF1995DC03EF1a3b584e3ae14da020C616', id: 'ff8fda69-d416-4d25-80a2-efb77bc7d4ad', metadata: { name: 'Test Account', @@ -402,7 +402,7 @@ describe('PermissionController specifications', () => { type: EthAccountType.Eoa, }, { - address: '0x4', + address: '0x04eBa9B766477d8eCA77F5f0e67AE1863C95a7E3', id: '0bd7348e-bdfe-4f67-875c-de831a583857', metadata: { name: 'Test Account', @@ -419,7 +419,12 @@ describe('PermissionController specifications', () => { }); const getAllAccounts = jest .fn() - .mockImplementationOnce(() => ['0x1', '0x2', '0x3', '0x4']); + .mockImplementationOnce(() => [ + '0x7A2Bd22810088523516737b4Dc238A4bC37c23F2', + '0x7152f909e5EB3EF198f17e5Cb087c5Ced88294e3', + '0xDe70d2FF1995DC03EF1a3b584e3ae14da020C616', + '0x04eBa9B766477d8eCA77F5f0e67AE1863C95a7E3', + ]); const { methodImplementation } = getPermissionSpecifications({ getInternalAccounts, @@ -427,10 +432,10 @@ describe('PermissionController specifications', () => { })[RestrictedMethods.eth_accounts]; expect(await methodImplementation()).toStrictEqual([ - '0x3', - '0x4', - '0x1', - '0x2', + '0xDe70d2FF1995DC03EF1a3b584e3ae14da020C616', + '0x04eBa9B766477d8eCA77F5f0e67AE1863C95a7E3', + '0x7A2Bd22810088523516737b4Dc238A4bC37c23F2', + '0x7152f909e5EB3EF198f17e5Cb087c5Ced88294e3', ]); }); @@ -438,7 +443,7 @@ describe('PermissionController specifications', () => { const getInternalAccounts = jest.fn().mockImplementationOnce(() => { return [ { - address: '0x2', + address: '0x7152f909e5EB3EF198f17e5Cb087c5Ced88294e3', id: '0bd7348e-bdfe-4f67-875c-de831a583857', metadata: { name: 'Test Account', @@ -452,7 +457,7 @@ describe('PermissionController specifications', () => { type: EthAccountType.Eoa, }, { - address: '0x3', + address: '0xDe70d2FF1995DC03EF1a3b584e3ae14da020C616', id: 'ff8fda69-d416-4d25-80a2-efb77bc7d4ad', metadata: { name: 'Test Account', @@ -469,7 +474,11 @@ describe('PermissionController specifications', () => { }); const getAllAccounts = jest .fn() - .mockImplementationOnce(() => ['0x1', '0x2', '0x3']); + .mockImplementationOnce(() => [ + '0x7A2Bd22810088523516737b4Dc238A4bC37c23F2', + '0x7152f909e5EB3EF198f17e5Cb087c5Ced88294e3', + '0xDe70d2FF1995DC03EF1a3b584e3ae14da020C616', + ]); const { methodImplementation } = getPermissionSpecifications({ getInternalAccounts, @@ -478,7 +487,7 @@ describe('PermissionController specifications', () => { })[RestrictedMethods.eth_accounts]; await expect(() => methodImplementation()).rejects.toThrow( - 'Missing identity for address: "0x1".', + 'Missing identity for address: "0x7A2Bd22810088523516737b4Dc238A4bC37c23F2".', ); }); @@ -486,7 +495,7 @@ describe('PermissionController specifications', () => { const getInternalAccounts = jest.fn().mockImplementationOnce(() => { return [ { - address: '0x1', + address: '0x7A2Bd22810088523516737b4Dc238A4bC37c23F2', id: 'cf8dace4-9439-4bd4-b3a8-88c821c8fcb3', metadata: { name: 'Test Account', @@ -500,7 +509,7 @@ describe('PermissionController specifications', () => { type: EthAccountType.Eoa, }, { - address: '0x3', + address: '0xDe70d2FF1995DC03EF1a3b584e3ae14da020C616', id: 'ff8fda69-d416-4d25-80a2-efb77bc7d4ad', metadata: { name: 'Test Account', @@ -517,7 +526,11 @@ describe('PermissionController specifications', () => { }); const getAllAccounts = jest .fn() - .mockImplementationOnce(() => ['0x1', '0x2', '0x3']); + .mockImplementationOnce(() => [ + '0x7A2Bd22810088523516737b4Dc238A4bC37c23F2', + '0x7152f909e5EB3EF198f17e5Cb087c5Ced88294e3', + '0xDe70d2FF1995DC03EF1a3b584e3ae14da020C616', + ]); const { methodImplementation } = getPermissionSpecifications({ getInternalAccounts, @@ -526,7 +539,7 @@ describe('PermissionController specifications', () => { })[RestrictedMethods.eth_accounts]; await expect(() => methodImplementation()).rejects.toThrow( - 'Missing identity for address: "0x2".', + 'Missing identity for address: "0x7152f909e5EB3EF198f17e5Cb087c5Ced88294e3".', ); }); }); diff --git a/app/scripts/lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware.test.ts b/app/scripts/lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware.test.ts new file mode 100644 index 000000000000..3b677225a148 --- /dev/null +++ b/app/scripts/lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware.test.ts @@ -0,0 +1,285 @@ +import { jsonrpc2 } from '@metamask/utils'; +import { BtcAccountType, EthAccountType } from '@metamask/keyring-api'; +import { Json } from 'json-rpc-engine'; +import createEvmMethodsToNonEvmAccountReqFilterMiddleware, { + EvmMethodsToNonEvmAccountFilterMessenger, +} from './createEvmMethodsToNonEvmAccountReqFilterMiddleware'; + +describe('createEvmMethodsToNonEvmAccountReqFilterMiddleware', () => { + const getMockRequest = (method: string, params?: Json) => ({ + jsonrpc: jsonrpc2, + id: 1, + method, + params, + }); + const getMockResponse = () => ({ jsonrpc: jsonrpc2, id: 'foo' }); + + // @ts-expect-error This function is missing from the Mocha type definitions + it.each([ + // EVM requests + { + accountType: BtcAccountType.P2wpkh, + method: 'eth_accounts', + calledNext: false, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'eth_sendRawTransaction', + calledNext: false, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'eth_sendTransaction', + calledNext: false, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'eth_sign', + calledNext: false, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'eth_signTypedData', + calledNext: false, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'eth_signTypedData_v1', + calledNext: false, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'eth_signTypedData_v3', + calledNext: false, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'eth_signTypedData_v4', + calledNext: false, + }, + { + accountType: EthAccountType.Eoa, + method: 'eth_accounts', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'eth_sendRawTransaction', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'eth_sendTransaction', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'eth_sign', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'eth_signTypedData', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'eth_signTypedData_v1', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'eth_signTypedData_v3', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'eth_signTypedData_v4', + calledNext: true, + }, + + // EVM requests not associated with an account + { + accountType: BtcAccountType.P2wpkh, + method: 'eth_blockNumber', + calledNext: true, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'eth_chainId', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'eth_blockNumber', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'eth_chainId', + calledNext: true, + }, + + // other requests + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_getSnaps', + calledNext: true, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_invokeSnap', + calledNext: true, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_requestSnaps', + calledNext: true, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'snap_getClientStatus', + calledNext: true, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_addEthereumChain', + calledNext: true, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_getPermissions', + calledNext: true, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_requestPermissions', + calledNext: true, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_revokePermissions', + calledNext: true, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_switchEthereumChain', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'wallet_getSnaps', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'wallet_invokeSnap', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'wallet_requestSnaps', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'snap_getClientStatus', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'wallet_addEthereumChain', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'wallet_getPermissions', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'wallet_requestPermissions', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'wallet_revokePermissions', + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'wallet_switchEthereumChain', + calledNext: true, + }, + + // wallet_requestPermissions request + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_requestPermissions', + params: [{ eth_accounts: {} }], + calledNext: false, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_requestPermissions', + params: [{ snap_getClientStatus: {} }], + calledNext: true, + }, + { + accountType: BtcAccountType.P2wpkh, + method: 'wallet_requestPermissions', + params: [{ eth_accounts: {}, snap_getClientStatus: {} }], + calledNext: false, + }, + { + accountType: EthAccountType.Eoa, + method: 'wallet_requestPermissions', + params: [{ eth_accounts: {} }], + calledNext: true, + }, + + { + accountType: EthAccountType.Eoa, + method: 'wallet_requestPermissions', + params: [{ snap_getClientStatus: {} }], + calledNext: true, + }, + { + accountType: EthAccountType.Eoa, + method: 'wallet_requestPermissions', + params: [{ eth_accounts: {}, snap_getClientStatus: {} }], + calledNext: true, + }, + ])( + `accountType $accountType method $method with non-EVM account is passed to next called $calledNext times`, + ({ + accountType, + method, + params, + calledNext, + }: { + accountType: EthAccountType | BtcAccountType; + method: string; + params?: Json; + calledNext: number; + }) => { + const filterFn = createEvmMethodsToNonEvmAccountReqFilterMiddleware({ + messenger: { + call: jest.fn().mockReturnValue({ type: accountType }), + } as unknown as EvmMethodsToNonEvmAccountFilterMessenger, + }); + const mockNext = jest.fn(); + const mockEnd = jest.fn(); + + filterFn( + getMockRequest(method, params), + getMockResponse(), + mockNext, + mockEnd, + ); + + expect(mockNext).toHaveBeenCalledTimes(calledNext ? 1 : 0); + expect(mockEnd).toHaveBeenCalledTimes(calledNext ? 0 : 1); + }, + ); +}); diff --git a/app/scripts/lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware.ts b/app/scripts/lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware.ts new file mode 100644 index 000000000000..3e1eca86997e --- /dev/null +++ b/app/scripts/lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware.ts @@ -0,0 +1,94 @@ +import { isEvmAccountType } from '@metamask/keyring-api'; +import { RestrictedControllerMessenger } from '@metamask/base-controller'; +import { AccountsControllerGetSelectedAccountAction } from '@metamask/accounts-controller'; +import { JsonRpcMiddleware } from 'json-rpc-engine'; +import { RestrictedEthMethods } from '../../../shared/constants/permissions'; +import { unrestrictedEthSigningMethods } from '../controllers/permissions'; + +type AllowedActions = AccountsControllerGetSelectedAccountAction; + +export type EvmMethodsToNonEvmAccountFilterMessenger = + RestrictedControllerMessenger< + 'EvmMethodsToNonEvmAccountFilterMessenger', + AllowedActions, + never, + AllowedActions['type'], + never + >; + +const METHODS_TO_CHECK = [ + ...Object.values(RestrictedEthMethods), + ...unrestrictedEthSigningMethods, +]; + +/** + * Returns a middleware that filters out requests whose requests are restricted to EVM accounts. + * + * @param opt - The middleware options. + * @param opt.messenger - The messenger object. + * @returns The middleware function. + */ +export default function createEvmMethodsToNonEvmAccountReqFilterMiddleware({ + messenger, +}: { + messenger: EvmMethodsToNonEvmAccountFilterMessenger; +}): JsonRpcMiddleware<unknown, void> { + return function filterEvmRequestToNonEvmAccountsMiddleware( + req, + _res, + next, + end, + ) { + const selectedAccount = messenger.call( + 'AccountsController:getSelectedAccount', + ); + + // If it's an EVM account, there nothing to filter, so jump to the next + // middleware directly. + if (isEvmAccountType(selectedAccount.type)) { + return next(); + } + + const ethMethodsRequiringEthAccount = METHODS_TO_CHECK.includes(req.method); + if (ethMethodsRequiringEthAccount) { + return end( + new Error(`Non-EVM account cannot request this method: ${req.method}`), + ); + } + + // https://docs.metamask.io/wallet/reference/wallet_requestpermissions/ + // wallet_requestPermissions param is an array with one object. The object may contain + // multiple keys that represent the permissions being requested. + + // Example: + // { + // "method": "wallet_requestPermissions", + // "params": [ + // { + // "eth_accounts": {}, + // "anotherPermission": {} + // } + // ] + // } + + // TODO: Convert this to superstruct schema + const isWalletRequestPermission = + req.method === 'wallet_requestPermissions'; + if (isWalletRequestPermission && req?.params && Array.isArray(req.params)) { + const permissionsMethodRequest = Object.keys(req.params[0]); + + const isEvmPermissionRequest = METHODS_TO_CHECK.some((method) => + permissionsMethodRequest.includes(method), + ); + if (isEvmPermissionRequest) { + return end( + new Error( + `Non-EVM account cannot request this method: ${permissionsMethodRequest.toString()}`, + ), + ); + } + } + + return next(); + }; +} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 4d5145e876f6..75488f893ff7 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -329,6 +329,7 @@ import UserStorageController from './controllers/user-storage/user-storage-contr import { PushPlatformNotificationsController } from './controllers/push-platform-notifications/push-platform-notifications'; import { MetamaskNotificationsController } from './controllers/metamask-notifications/metamask-notifications'; import { updateSecurityAlertResponse } from './lib/ppom/ppom-util'; +import createEvmMethodsToNonEvmAccountReqFilterMiddleware from './lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware'; export const METAMASK_CONTROLLER_EVENTS = { // Fired after state changes that impact the extension badge (unapproved msg count) @@ -5172,6 +5173,17 @@ export default class MetamaskController extends EventEmitter { ); } + // EVM requests and eth permissions should not be passed to non-EVM accounts + // this middleware intercepts these requests and returns an error. + engine.push( + createEvmMethodsToNonEvmAccountReqFilterMiddleware({ + messenger: this.controllerMessenger.getRestricted({ + name: 'EvmMethodsToNonEvmAccountFilterMessenger', + allowedActions: ['AccountsController:getSelectedAccount'], + }), + }), + ); + // Unrestricted/permissionless RPC method implementations. // They must nevertheless be placed _behind_ the permission middleware. engine.push( diff --git a/shared/constants/permissions.ts b/shared/constants/permissions.ts index 0b3cebc377e5..8f1cf4ced063 100644 --- a/shared/constants/permissions.ts +++ b/shared/constants/permissions.ts @@ -3,6 +3,10 @@ export const CaveatTypes = Object.freeze({ restrictNetworkSwitching: 'restrictNetworkSwitching' as const, }); +export const RestrictedEthMethods = Object.freeze({ + eth_accounts: 'eth_accounts', +}); + export const RestrictedMethods = Object.freeze({ eth_accounts: 'eth_accounts', ///: BEGIN:ONLY_INCLUDE_IF(snaps) From b7d7a340cc5bce3bc05cfbdc78d43970ae7e49ee Mon Sep 17 00:00:00 2001 From: Charly Chevalier <charly.chevalier@consensys.net> Date: Fri, 14 Jun 2024 11:19:13 +0200 Subject: [PATCH 45/61] refactor: use new multichain selectors in accounts related components (#25290) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This is first work of migrating some components to use the new `multichain` selectors that have been introduced for non-EVM support within the extension. None regression is expected with the introduction of those selectors. Having a pre-PR would make future non-EVM related PRs much simpler to review too. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25290?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** > Mostly relying on unit and e2e tests here, since there is no new feature 1. `yarn start:flask` 2. Use the extension as usual ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> --- ui/components/app/asset-list/asset-list.js | 31 ++-- ...-preferenced-currency-display.component.js | 12 +- .../avatar-network/avatar-network.tsx | 2 +- .../multichain/ramps-card/ramps-card.js | 11 +- .../token-list-item/token-list-item.js | 4 +- ui/hooks/useCurrencyDisplay.js | 72 ++++---- ui/hooks/useCurrencyDisplay.test.js | 17 +- ui/hooks/useTransactionDisplayData.test.js | 25 ++- ui/hooks/useUserPreferencedCurrency.js | 17 +- ui/hooks/useUserPreferencedCurrency.test.js | 17 +- .../__snapshots__/asset-page.test.tsx.snap | 6 +- ui/pages/confirmations/hooks/test-utils.js | 24 ++- ui/selectors/multichain.test.ts | 160 ++++++++++++------ ui/selectors/multichain.ts | 99 ++++++++--- ui/selectors/selectors.js | 9 + 15 files changed, 349 insertions(+), 157 deletions(-) diff --git a/ui/components/app/asset-list/asset-list.js b/ui/components/app/asset-list/asset-list.js index a4e30cad81fc..2dff1f4f9715 100644 --- a/ui/components/app/asset-list/asset-list.js +++ b/ui/components/app/asset-list/asset-list.js @@ -6,23 +6,23 @@ import { PRIMARY, SECONDARY } from '../../../helpers/constants/common'; import { useUserPreferencedCurrency } from '../../../hooks/useUserPreferencedCurrency'; import { getSelectedAccountCachedBalance, - getShouldShowFiat, - getNativeCurrencyImage, getDetectedTokensInCurrentNetwork, getIstokenDetectionInactiveOnNonMainnetSupportedNetwork, getShouldHideZeroBalanceTokens, ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) getIsBuyableChain, ///: END:ONLY_INCLUDE_IF - getCurrentNetwork, getSelectedAccount, getPreferences, - getIsMainnet, } from '../../../selectors'; import { - getNativeCurrency, - getProviderConfig, -} from '../../../ducks/metamask/metamask'; + getMultichainCurrentNetwork, + getMultichainNativeCurrency, + getMultichainIsEvm, + getMultichainShouldShowFiat, + getMultichainCurrencyImage, + getMultichainIsMainnet, +} from '../../../selectors/multichain'; import { useCurrencyDisplay } from '../../../hooks/useCurrencyDisplay'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { @@ -53,12 +53,13 @@ import { const AssetList = ({ onClickAsset }) => { const [showDetectedTokens, setShowDetectedTokens] = useState(false); const selectedAccountBalance = useSelector(getSelectedAccountCachedBalance); - const nativeCurrency = useSelector(getNativeCurrency); - const showFiat = useSelector(getShouldShowFiat); - const { chainId } = useSelector(getCurrentNetwork); - const isMainnet = useSelector(getIsMainnet); + const nativeCurrency = useSelector(getMultichainNativeCurrency); + const showFiat = useSelector(getMultichainShouldShowFiat); + const isMainnet = useSelector(getMultichainIsMainnet); const { useNativeCurrencyAsPrimaryCurrency } = useSelector(getPreferences); - const { ticker, type, rpcUrl } = useSelector(getProviderConfig); + const { chainId, ticker, type, rpcUrl } = useSelector( + getMultichainCurrentNetwork, + ); const isOriginalNativeSymbol = useIsOriginalNativeTokenSymbol( chainId, ticker, @@ -94,7 +95,7 @@ const AssetList = ({ onClickAsset }) => { currency: secondaryCurrency, }); - const primaryTokenImage = useSelector(getNativeCurrencyImage); + const primaryTokenImage = useSelector(getMultichainCurrencyImage); const detectedTokens = useSelector(getDetectedTokensInCurrentNetwork) || []; const isTokenDetectionInactiveOnNonMainnetSupportedNetwork = useSelector( getIstokenDetectionInactiveOnNonMainnetSupportedNetwork, @@ -112,7 +113,9 @@ const AssetList = ({ onClickAsset }) => { const shouldShowBuy = isBuyableChain && balanceIsZero; ///: END:ONLY_INCLUDE_IF - let isStakeable = isMainnet; + const isEvm = useSelector(getMultichainIsEvm); + + let isStakeable = isMainnet && isEvm; ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) isStakeable = false; ///: END:ONLY_INCLUDE_IF diff --git a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js index bfe1e8e09033..6611fbcd68c1 100644 --- a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js +++ b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js @@ -1,13 +1,15 @@ import React, { useMemo } from 'react'; -import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; import { EtherDenomination } from '../../../../shared/constants/common'; import { PRIMARY, SECONDARY } from '../../../helpers/constants/common'; import CurrencyDisplay from '../../ui/currency-display'; import { useUserPreferencedCurrency } from '../../../hooks/useUserPreferencedCurrency'; import { AvatarNetwork, AvatarNetworkSize } from '../../component-library'; -import { getCurrentNetwork } from '../../../selectors'; -import { getNativeCurrency } from '../../../ducks/metamask/metamask'; +import { + getMultichainNativeCurrency, + getMultichainCurrentNetwork, +} from '../../../selectors/multichain'; /* eslint-disable jsdoc/require-param-name */ // eslint-disable-next-line jsdoc/require-param @@ -24,8 +26,8 @@ export default function UserPreferencedCurrencyDisplay({ showCurrencySuffix, ...restProps }) { - const currentNetwork = useSelector(getCurrentNetwork); - const nativeCurrency = useSelector(getNativeCurrency); + const currentNetwork = useSelector(getMultichainCurrentNetwork); + const nativeCurrency = useSelector(getMultichainNativeCurrency); const { currency, numberOfDecimals } = useUserPreferencedCurrency(type, { ethNumberOfDecimals, fiatNumberOfDecimals, diff --git a/ui/components/component-library/avatar-network/avatar-network.tsx b/ui/components/component-library/avatar-network/avatar-network.tsx index 676b674aaad7..487f2ad7ee05 100644 --- a/ui/components/component-library/avatar-network/avatar-network.tsx +++ b/ui/components/component-library/avatar-network/avatar-network.tsx @@ -80,7 +80,7 @@ export const AvatarNetwork: AvatarNetworkComponent = React.forwardRef( } onError={handleOnError} src={src} - alt={`${name} logo` || 'network logo'} + alt={(name && `${name} logo`) || 'network logo'} /> </> )} diff --git a/ui/components/multichain/ramps-card/ramps-card.js b/ui/components/multichain/ramps-card/ramps-card.js index 9b1956ac6b7d..e1c61f2a35c1 100644 --- a/ui/components/multichain/ramps-card/ramps-card.js +++ b/ui/components/multichain/ramps-card/ramps-card.js @@ -10,7 +10,10 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { getCurrentNetwork, getSwapsDefaultToken } from '../../../selectors'; +import { + getMultichainDefaultToken, + getMultichainCurrentNetwork, +} from '../../../selectors/multichain'; import { MetaMetricsEventCategory, MetaMetricsEventName, @@ -68,14 +71,15 @@ export const RampsCard = ({ variant }) => { const { openBuyCryptoInPdapp } = useRamps(metamaskEntryMap[variant]); const trackEvent = useContext(MetaMetricsContext); const currentLocale = useSelector(getCurrentLocale); - const { chainId, nickname } = useSelector(getCurrentNetwork); - const { symbol = 'ETH' } = useSelector(getSwapsDefaultToken); + const { chainId, nickname } = useSelector(getMultichainCurrentNetwork); + const { symbol } = useSelector(getMultichainDefaultToken); useEffect(() => { trackEvent({ event: MetaMetricsEventName.EmptyBuyBannerDisplayed, category: MetaMetricsEventCategory.Navigation, properties: { + // FIXME: This might not be a number for non-EVM networks chain_id: chainId, locale: currentLocale, network: nickname, @@ -92,6 +96,7 @@ export const RampsCard = ({ variant }) => { properties: { location: `${variant} tab`, text: `Buy ${symbol}`, + // FIXME: This might not be a number for non-EVM networks chain_id: chainId, token_symbol: symbol, }, diff --git a/ui/components/multichain/token-list-item/token-list-item.js b/ui/components/multichain/token-list-item/token-list-item.js index 7f01753dfa7f..08e3debea079 100644 --- a/ui/components/multichain/token-list-item/token-list-item.js +++ b/ui/components/multichain/token-list-item/token-list-item.js @@ -36,12 +36,12 @@ import { ModalContent } from '../../component-library/modal-content/deprecated'; import { ModalHeader } from '../../component-library/modal-header/deprecated'; import { getCurrentChainId, - getCurrentNetwork, getMetaMetricsId, getNativeCurrencyImage, getPreferences, getTestNetworkBackgroundColor, } from '../../../selectors'; +import { getMultichainCurrentNetwork } from '../../../selectors/multichain'; import Tooltip from '../../ui/tooltip'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { MetaMetricsContext } from '../../../contexts/metametrics'; @@ -132,7 +132,7 @@ export const TokenListItem = ({ </Box> ); // Used for badge icon - const currentNetwork = useSelector(getCurrentNetwork); + const currentNetwork = useSelector(getMultichainCurrentNetwork); const testNetworkBackgroundColor = useSelector(getTestNetworkBackgroundColor); return ( diff --git a/ui/hooks/useCurrencyDisplay.js b/ui/hooks/useCurrencyDisplay.js index 7ff8d48e17e1..bd60566bbf88 100644 --- a/ui/hooks/useCurrencyDisplay.js +++ b/ui/hooks/useCurrencyDisplay.js @@ -2,11 +2,12 @@ import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import BigNumber from 'bignumber.js'; import { formatCurrency } from '../helpers/utils/confirm-tx.util'; -import { getCurrentCurrency } from '../selectors'; import { - getConversionRate, - getNativeCurrency, -} from '../ducks/metamask/metamask'; + getMultichainCurrentCurrency, + getMultichainIsEvm, + getMultichainNativeCurrency, +} from '../selectors/multichain'; +import { getConversionRate } from '../ducks/metamask/metamask'; import { getValueFromWeiHex } from '../../shared/modules/conversion.utils'; import { TEST_NETWORK_TICKER_MAP } from '../../shared/constants/network'; @@ -60,8 +61,9 @@ export function useCurrencyDisplay( inputValue, { displayValue, prefix, numberOfDecimals, denomination, currency, ...opts }, ) { - const currentCurrency = useSelector(getCurrentCurrency); - const nativeCurrency = useSelector(getNativeCurrency); + const isEvm = useSelector(getMultichainIsEvm); + const currentCurrency = useSelector(getMultichainCurrentCurrency); + const nativeCurrency = useSelector(getMultichainNativeCurrency); const conversionRate = useSelector(getConversionRate); const isUserPreferredCurrency = currency === currentCurrency; @@ -69,31 +71,41 @@ export function useCurrencyDisplay( if (displayValue) { return displayValue; } - if ( - currency === nativeCurrency || - (!isUserPreferredCurrency && !nativeCurrency) - ) { - const ethDisplayValue = new Numeric(inputValue, 16, EtherDenomination.WEI) - .toDenomination(denomination || EtherDenomination.ETH) - .round(numberOfDecimals || DEFAULT_PRECISION) - .toBase(10) - .toString(); - return ethDisplayValue === '0' && inputValue && Number(inputValue) !== 0 - ? MIN_AMOUNT_DISPLAY - : ethDisplayValue; - } else if (isUserPreferredCurrency && conversionRate) { - return formatCurrency( - getValueFromWeiHex({ - value: inputValue, - fromCurrency: nativeCurrency, - toCurrency: currency, - conversionRate, - numberOfDecimals: numberOfDecimals || 2, - toDenomination: denomination, - }), - currency, - ); + if (isEvm) { + if ( + currency === nativeCurrency || + (!isUserPreferredCurrency && !nativeCurrency) + ) { + const ethDisplayValue = new Numeric( + inputValue, + 16, + EtherDenomination.WEI, + ) + .toDenomination(denomination || EtherDenomination.ETH) + .round(numberOfDecimals || DEFAULT_PRECISION) + .toBase(10) + .toString(); + + return ethDisplayValue === '0' && inputValue && Number(inputValue) !== 0 + ? MIN_AMOUNT_DISPLAY + : ethDisplayValue; + } else if (isUserPreferredCurrency && conversionRate) { + return formatCurrency( + getValueFromWeiHex({ + value: inputValue, + fromCurrency: nativeCurrency, + toCurrency: currency, + conversionRate, + numberOfDecimals: numberOfDecimals || 2, + toDenomination: denomination, + }), + currency, + ); + } + } else { + // For non-EVM we assume the input value can be formatted "as-is" + return formatCurrency(inputValue, currency); } return null; }, [ diff --git a/ui/hooks/useCurrencyDisplay.test.js b/ui/hooks/useCurrencyDisplay.test.js index d3863d0247aa..b97064121593 100644 --- a/ui/hooks/useCurrencyDisplay.test.js +++ b/ui/hooks/useCurrencyDisplay.test.js @@ -2,6 +2,11 @@ import { renderHook } from '@testing-library/react-hooks'; import * as reactRedux from 'react-redux'; import sinon from 'sinon'; import { getCurrentCurrency } from '../selectors'; +import { + getMultichainCurrentCurrency, + getMultichainIsEvm, + getMultichainNativeCurrency, +} from '../selectors/multichain'; import { getConversionRate, getNativeCurrency, @@ -128,9 +133,17 @@ describe('useCurrencyDisplay', () => { describe(`when input is { value: ${value}, decimals: ${restProps.numberOfDecimals}, denomation: ${restProps.denomination} }`, () => { const stub = sinon.stub(reactRedux, 'useSelector'); stub.callsFake((selector) => { - if (selector === getCurrentCurrency) { + if (selector === getMultichainIsEvm) { + return true; + } else if ( + selector === getCurrentCurrency || + selector === getMultichainCurrentCurrency + ) { return 'usd'; - } else if (selector === getNativeCurrency) { + } else if ( + selector === getNativeCurrency || + selector === getMultichainNativeCurrency + ) { return 'ETH'; } else if (selector === getConversionRate) { return 280.45; diff --git a/ui/hooks/useTransactionDisplayData.test.js b/ui/hooks/useTransactionDisplayData.test.js index 6a8838fdbd61..60de4dccd295 100644 --- a/ui/hooks/useTransactionDisplayData.test.js +++ b/ui/hooks/useTransactionDisplayData.test.js @@ -25,6 +25,12 @@ import { CHAIN_IDS } from '../../shared/constants/network'; import { TransactionGroupCategory } from '../../shared/constants/transaction'; import { formatDateWithYearContext } from '../helpers/utils/util'; import { getMessage } from '../helpers/utils/i18n-helper'; +import { + getMultichainCurrentCurrency, + getMultichainIsEvm, + getMultichainNativeCurrency, + getMultichainShouldShowFiat, +} from '../selectors/multichain'; import * as i18nhooks from './useI18nContext'; import * as useTokenFiatAmountHooks from './useTokenFiatAmount'; import { useTransactionDisplayData } from './useTransactionDisplayData'; @@ -201,7 +207,9 @@ describe('useTransactionDisplayData', () => { getMessage('en', messages, key, variables), ); useSelector.callsFake((selector) => { - if (selector === getTokens) { + if (selector === getMultichainIsEvm) { + return true; + } else if (selector === getTokens) { return [ { address: '0xabca64466f257793eaa52fcfff5066894b76a149', @@ -213,11 +221,20 @@ describe('useTransactionDisplayData', () => { return { useNativeCurrencyAsPrimaryCurrency: true, }; - } else if (selector === getShouldShowFiat) { + } else if ( + selector === getShouldShowFiat || + selector === getMultichainShouldShowFiat + ) { return false; - } else if (selector === getNativeCurrency) { + } else if ( + selector === getNativeCurrency || + selector === getMultichainNativeCurrency + ) { return 'ETH'; - } else if (selector === getCurrentCurrency) { + } else if ( + selector === getCurrentCurrency || + selector === getMultichainCurrentCurrency + ) { return 'ETH'; } else if (selector === getCurrentChainId) { return CHAIN_IDS.MAINNET; diff --git a/ui/hooks/useUserPreferencedCurrency.js b/ui/hooks/useUserPreferencedCurrency.js index 92b9f2e54e32..dbf5671f38c7 100644 --- a/ui/hooks/useUserPreferencedCurrency.js +++ b/ui/hooks/useUserPreferencedCurrency.js @@ -1,10 +1,10 @@ import { shallowEqual, useSelector } from 'react-redux'; +import { getPreferences } from '../selectors'; import { - getPreferences, - getShouldShowFiat, - getCurrentCurrency, -} from '../selectors'; -import { getNativeCurrency } from '../ducks/metamask/metamask'; + getMultichainNativeCurrency, + getMultichainCurrentCurrency, + getMultichainShouldShowFiat, +} from '../selectors/multichain'; import { PRIMARY, SECONDARY } from '../helpers/constants/common'; import { EtherDenomination } from '../../shared/constants/common'; @@ -41,13 +41,14 @@ import { ETH_DEFAULT_DECIMALS } from '../constants'; * @returns {UserPreferredCurrency} */ export function useUserPreferencedCurrency(type, opts = {}) { - const nativeCurrency = useSelector(getNativeCurrency); + const nativeCurrency = useSelector(getMultichainNativeCurrency); + const { useNativeCurrencyAsPrimaryCurrency } = useSelector( getPreferences, shallowEqual, ); - const showFiat = useSelector(getShouldShowFiat); - const currentCurrency = useSelector(getCurrentCurrency); + const showFiat = useSelector(getMultichainShouldShowFiat); + const currentCurrency = useSelector(getMultichainCurrentCurrency); const fiatReturn = { currency: currentCurrency, diff --git a/ui/hooks/useUserPreferencedCurrency.test.js b/ui/hooks/useUserPreferencedCurrency.test.js index 0b83fad77eba..814178068988 100644 --- a/ui/hooks/useUserPreferencedCurrency.test.js +++ b/ui/hooks/useUserPreferencedCurrency.test.js @@ -6,6 +6,11 @@ import { getPreferences, getShouldShowFiat, } from '../selectors'; +import { + getMultichainCurrentCurrency, + getMultichainIsEvm, + getMultichainShouldShowFiat, +} from '../selectors/multichain'; import { useUserPreferencedCurrency } from './useUserPreferencedCurrency'; const tests = [ @@ -120,9 +125,17 @@ function getFakeUseSelector(state) { return (selector) => { if (selector === getPreferences) { return state; - } else if (selector === getShouldShowFiat) { + } else if (selector === getMultichainIsEvm) { + return state.nativeCurrency === 'ETH'; + } else if ( + selector === getShouldShowFiat || + selector === getMultichainShouldShowFiat + ) { return state.showFiat; - } else if (selector === getCurrentCurrency) { + } else if ( + selector === getCurrentCurrency || + selector === getMultichainCurrentCurrency + ) { return state.currentCurrency; } return state.nativeCurrency; diff --git a/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap b/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap index 9b9b8d0a7fdd..dd027ab5608d 100644 --- a/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap +++ b/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap @@ -192,7 +192,7 @@ exports[`AssetPage should render a native asset 1`] = ` class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-border-muted box--border-style-solid box--border-width-1" > <img - alt="undefined logo" + alt="Ethereum Mainnet logo" class="mm-avatar-network__network-image" src="./images/eth_logo.svg" /> @@ -476,7 +476,7 @@ exports[`AssetPage should render an ERC20 asset without prices 1`] = ` class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-border-muted box--border-style-solid box--border-width-1" > <img - alt="undefined logo" + alt="Ethereum Mainnet logo" class="mm-avatar-network__network-image" src="./images/eth_logo.svg" /> @@ -951,7 +951,7 @@ exports[`AssetPage should render an ERC20 token with prices 1`] = ` class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-border-muted box--border-style-solid box--border-width-1" > <img - alt="undefined logo" + alt="Ethereum Mainnet logo" class="mm-avatar-network__network-image" src="./images/eth_logo.svg" /> diff --git a/ui/pages/confirmations/hooks/test-utils.js b/ui/pages/confirmations/hooks/test-utils.js index 5805c56c8f93..fea126d1e50c 100644 --- a/ui/pages/confirmations/hooks/test-utils.js +++ b/ui/pages/confirmations/hooks/test-utils.js @@ -21,6 +21,12 @@ import { import { Numeric } from '../../../../shared/modules/Numeric'; import { EtherDenomination } from '../../../../shared/constants/common'; import { useGasFeeEstimates } from '../../../hooks/useGasFeeEstimates'; +import { + getMultichainCurrentCurrency, + getMultichainIsEvm, + getMultichainNativeCurrency, + getMultichainShouldShowFiat, +} from '../../../selectors/multichain'; // Why this number? // 20 gwei * 21000 gasLimit = 420,000 gwei @@ -96,10 +102,16 @@ export const generateUseSelectorRouter = shouldShowFiat = true, } = {}) => (selector) => { + if (selector === getMultichainIsEvm) { + return true; + } if (selector === getConversionRate) { return MOCK_ETH_USD_CONVERSION_RATE; } - if (selector === getNativeCurrency) { + if ( + selector === getMultichainNativeCurrency || + selector === getNativeCurrency + ) { return EtherDenomination.ETH; } if (selector === getPreferences) { @@ -107,10 +119,16 @@ export const generateUseSelectorRouter = useNativeCurrencyAsPrimaryCurrency: true, }; } - if (selector === getCurrentCurrency) { + if ( + selector === getMultichainCurrentCurrency || + selector === getCurrentCurrency + ) { return 'USD'; } - if (selector === getShouldShowFiat) { + if ( + selector === getMultichainShouldShowFiat || + selector === getShouldShowFiat + ) { return shouldShowFiat; } if (selector === txDataSelector) { diff --git a/ui/selectors/multichain.test.ts b/ui/selectors/multichain.test.ts index 2b01bf105e82..d811f57798c3 100644 --- a/ui/selectors/multichain.test.ts +++ b/ui/selectors/multichain.test.ts @@ -1,7 +1,4 @@ -import { - getNativeCurrency, - getProviderConfig, -} from '../ducks/metamask/metamask'; +import { getNativeCurrency } from '../ducks/metamask/metamask'; import { MULTICHAIN_PROVIDER_CONFIGS, MultichainNetworks, @@ -12,61 +9,69 @@ import { MOCK_ACCOUNT_EOA, MOCK_ACCOUNT_BIP122_P2WPKH, } from '../../test/data/mock-accounts'; +import { CHAIN_IDS } from '../../shared/constants/network'; import { AccountsState } from './accounts'; import { + getMultichainCurrentChainId, getMultichainCurrentCurrency, getMultichainDefaultToken, getMultichainIsEvm, + getMultichainIsMainnet, getMultichainNativeCurrency, getMultichainNetwork, getMultichainNetworkProviders, getMultichainProviderConfig, getMultichainShouldShowFiat, } from './multichain'; -import { getCurrentCurrency, getShouldShowFiat } from '.'; +import { getCurrentCurrency, getCurrentNetwork, getShouldShowFiat } from '.'; type TestState = AccountsState & { metamask: { preferences: { showFiatInTestnets: boolean }; - providerConfig: { ticker: string; chainId: string }; + providerConfig: { type: string; ticker: string; chainId: string }; currentCurrency: string; currencyRates: Record<string, { conversionRate: string }>; completedOnboarding: boolean; }; }; -const MOCK_EVM_STATE: TestState = { - metamask: { - preferences: { - showFiatInTestnets: false, - }, - providerConfig: { - ticker: 'ETH', - chainId: '0x1', - }, - currentCurrency: 'ETH', - currencyRates: { - ETH: { - conversionRate: 'usd', +function getEvmState(): TestState { + return { + metamask: { + preferences: { + showFiatInTestnets: false, + }, + providerConfig: { + type: 'mainnet', + ticker: 'ETH', + chainId: '0x1', + }, + currentCurrency: 'ETH', + currencyRates: { + ETH: { + conversionRate: 'usd', + }, + }, + completedOnboarding: true, + internalAccounts: { + selectedAccount: MOCK_ACCOUNT_EOA.id, + accounts: MOCK_ACCOUNTS, }, }, - completedOnboarding: true, - internalAccounts: { - selectedAccount: MOCK_ACCOUNT_EOA.id, - accounts: MOCK_ACCOUNTS, - }, - }, -}; + }; +} -const MOCK_NON_EVM_STATE: AccountsState = { - metamask: { - ...MOCK_EVM_STATE.metamask, - internalAccounts: { - selectedAccount: MOCK_ACCOUNT_BIP122_P2WPKH.id, - accounts: MOCK_ACCOUNTS, +function getNonEvmState(): TestState { + return { + metamask: { + ...getEvmState().metamask, + internalAccounts: { + selectedAccount: MOCK_ACCOUNT_BIP122_P2WPKH.id, + accounts: MOCK_ACCOUNTS, + }, }, - }, -}; + }; +} function getBip122ProviderConfig(): MultichainProviderConfig { // For now, we only have Bitcoin non-EVM network, so we are expecting to have @@ -77,7 +82,7 @@ function getBip122ProviderConfig(): MultichainProviderConfig { describe('Multichain Selectors', () => { describe('getMultichainNetworkProviders', () => { it('has some providers', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); const networkProviders = getMultichainNetworkProviders(state); expect(Array.isArray(networkProviders)).toBe(true); @@ -87,21 +92,21 @@ describe('Multichain Selectors', () => { describe('getMultichainNetwork', () => { it('returns an EVM network provider if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); const network = getMultichainNetwork(state); expect(network.isEvmNetwork).toBe(true); }); it('returns an non-EVM network provider if account is non-EVM', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); const network = getMultichainNetwork(state); expect(network.isEvmNetwork).toBe(false); }); it('returns an EVM network provider if user is not onboarded', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); state.metamask.completedOnboarding = false; state.metamask.internalAccounts.selectedAccount = ''; @@ -112,13 +117,13 @@ describe('Multichain Selectors', () => { describe('getMultichainIsEvm', () => { it('returns true if selected account is EVM compatible', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainIsEvm(state)).toBe(true); }); it('returns false if selected account is not EVM compatible', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); expect(getMultichainIsEvm(state)).toBe(false); }); @@ -126,13 +131,16 @@ describe('Multichain Selectors', () => { describe('getMultichain{ProviderConfig,CurrentNetwork}', () => { it('returns a ProviderConfig if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); - expect(getMultichainProviderConfig(state)).toBe(getProviderConfig(state)); + // NOTE: We do fallback to `getCurrentNetwork` (using the "original" list + // of network) when using EVM context, so check against this value here + const evmMainnetNetwork = getCurrentNetwork(state); + expect(getMultichainProviderConfig(state)).toBe(evmMainnetNetwork); }); it('returns a MultichainProviderConfig if account is non-EVM (bip122:*)', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); const bip122ProviderConfig = getBip122ProviderConfig(); expect(getMultichainProviderConfig(state)).toBe(bip122ProviderConfig); @@ -141,13 +149,13 @@ describe('Multichain Selectors', () => { describe('getMultichainNativeCurrency', () => { it('returns same native currency if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainNativeCurrency(state)).toBe(getNativeCurrency(state)); }); it('returns MultichainProviderConfig.ticker if account is non-EVM (bip122:*)', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); const bip122ProviderConfig = getBip122ProviderConfig(); expect(getMultichainNativeCurrency(state)).toBe( @@ -158,7 +166,7 @@ describe('Multichain Selectors', () => { describe('getMultichainCurrentCurrency', () => { it('returns same currency currency if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainCurrentCurrency(state)).toBe( getCurrentCurrency(state), @@ -169,7 +177,7 @@ describe('Multichain Selectors', () => { it.each(['usd', 'ETH'])( "returns current currency '%s' if account is EVM", (currency: string) => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); state.metamask.currentCurrency = currency; expect(getCurrentCurrency(state)).toBe(currency); @@ -178,7 +186,7 @@ describe('Multichain Selectors', () => { ); it('fallbacks to ticker as currency if account is non-EVM (bip122:*)', () => { - const state = MOCK_NON_EVM_STATE; // .currentCurrency = 'ETH' + const state = getNonEvmState(); // .currentCurrency = 'ETH' const bip122ProviderConfig = getBip122ProviderConfig(); expect(getCurrentCurrency(state).toLowerCase()).not.toBe('usd'); @@ -190,13 +198,13 @@ describe('Multichain Selectors', () => { describe('getMultichainShouldShowFiat', () => { it('returns same value as getShouldShowFiat if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainShouldShowFiat(state)).toBe(getShouldShowFiat(state)); }); it('returns true if account is non-EVM', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); expect(getMultichainShouldShowFiat(state)).toBe(true); }); @@ -204,7 +212,7 @@ describe('Multichain Selectors', () => { describe('getMultichainDefaultToken', () => { it('returns ETH if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainDefaultToken(state)).toEqual({ symbol: 'ETH', @@ -212,7 +220,7 @@ describe('Multichain Selectors', () => { }); it('returns true if account is non-EVM (bip122:*)', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); const bip122ProviderConfig = getBip122ProviderConfig(); expect(getMultichainDefaultToken(state)).toEqual({ @@ -220,4 +228,52 @@ describe('Multichain Selectors', () => { }); }); }); + + describe('getMultichainCurrentChainId', () => { + it('returns current chain ID if account is EVM (mainnet)', () => { + const state = getEvmState(); + + expect(getMultichainCurrentChainId(state)).toEqual(CHAIN_IDS.MAINNET); + }); + + it('returns current chain ID if account is EVM (other)', () => { + const state = getEvmState(); + + state.metamask.providerConfig.chainId = CHAIN_IDS.SEPOLIA; + expect(getMultichainCurrentChainId(state)).toEqual(CHAIN_IDS.SEPOLIA); + }); + + it('returns current chain ID if account is non-EVM (bip122:<mainnet>)', () => { + const state = getNonEvmState(); + + expect(getMultichainCurrentChainId(state)).toEqual( + MultichainNetworks.BITCOIN, + ); + }); + + // No test for testnet with non-EVM for now, as we only support mainnet network providers! + }); + + describe('getMultichainIsMainnet', () => { + it('returns true if account is EVM (mainnet)', () => { + const state = getEvmState(); + + expect(getMultichainIsMainnet(state)).toBe(true); + }); + + it('returns false if account is EVM (testnet)', () => { + const state = getEvmState(); + + state.metamask.providerConfig.chainId = CHAIN_IDS.SEPOLIA; + expect(getMultichainIsMainnet(state)).toBe(false); + }); + + it('returns current chain ID if account is non-EVM (bip122:<mainnet>)', () => { + const state = getNonEvmState(); + + expect(getMultichainIsMainnet(state)).toBe(true); + }); + + // No test for testnet with non-EVM for now, as we only support mainnet network providers! + }); }); diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index 87598561c406..3e9070b1a3ab 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -5,9 +5,11 @@ import { KnownCaipNamespace, parseCaipChainId, } from '@metamask/utils'; +import { ChainId } from '@metamask/controller-utils'; import { MultichainProviderConfig, MULTICHAIN_PROVIDER_CONFIGS, + MultichainNetworks, } from '../../shared/constants/multichain/networks'; import { getCompletedOnboarding, @@ -17,7 +19,10 @@ import { import { AccountsState } from './accounts'; import { getAllNetworks, + getCurrentChainId, getCurrentCurrency, + getIsMainnet, + getMaybeSelectedInternalAccount, getNativeCurrencyImage, getSelectedInternalAccount, getShouldShowFiat, @@ -33,7 +38,7 @@ export type MultichainNetwork = { nickname: string; isEvmNetwork: boolean; chainId?: CaipChainId; - network?: ProviderConfig | MultichainProviderConfig; + network: ProviderConfig | MultichainProviderConfig; }; export function getMultichainNetworkProviders( @@ -46,41 +51,48 @@ export function getMultichainNetworkProviders( export function getMultichainNetwork( state: MultichainState, ): MultichainNetwork { - const isOnboarded = getCompletedOnboarding(state); - // Selected account is not available during onboarding - // This is used in the app header - const selectedAccount = getSelectedInternalAccount(state); - const isEvm = isEvmAccountType(selectedAccount?.type); + const isEvm = getMultichainIsEvm(state); // EVM networks const evmNetworks: ProviderConfig[] = getAllNetworks(state); - const evmProvider: ProviderConfig = getProviderConfig(state); + const evmChainId: ChainId = getCurrentChainId(state); - if (!isOnboarded || isEvm) { - const evmChainId = - `${KnownCaipNamespace.Eip155}:${evmProvider.chainId}` as CaipChainId; - const evmNetwork = evmNetworks.find( - (network) => network.chainId === evmProvider.chainId, - ); + if (isEvm) { + const evmNetwork: ProviderConfig = + evmNetworks.find((provider) => provider.chainId === evmChainId) ?? + getProviderConfig(state); // We fallback to the original selector otherwise return { nickname: 'Ethereum', isEvmNetwork: true, - chainId: evmChainId, + // We assume the chain ID is `string` or `number`, so we convert it to a + // `Number` to be compliant with EIP155 CAIP chain ID + chainId: `${KnownCaipNamespace.Eip155}:${Number( + evmChainId, + )}` as CaipChainId, network: evmNetwork, }; } - // Non-EVM networks + // Non-EVM networks: // (Hardcoded for testing) // HACK: For now, we rely on the account type being "sort-of" CAIP compliant, so use // this as a CAIP-2 namespace and apply our filter with it + // For non-EVM, we know we have a selected account, since the logic `isEvm` is based + // on having a non-EVM account being selected! + const selectedAccount = getSelectedInternalAccount(state); const nonEvmNetworks = getMultichainNetworkProviders(state); const nonEvmNetwork = nonEvmNetworks.find((provider) => { const { namespace } = parseCaipChainId(provider.chainId); return selectedAccount.type.startsWith(namespace); }); + if (!nonEvmNetwork) { + throw new Error( + 'Could not find non-EVM provider for the current configuration. This should never happen.', + ); + } + return { // TODO: Adapt this for other non-EVM networks // TODO: We need to have a way of setting nicknames of other non-EVM networks @@ -97,18 +109,29 @@ export function getMultichainNetwork( // currency will be BTC.. export function getMultichainIsEvm(state: MultichainState) { - const selectedAccount = getSelectedInternalAccount(state); - - // There are no selected account during onboarding. we default to the current EVM provider. - return !selectedAccount || isEvmAccountType(selectedAccount.type); + const isOnboarded = getCompletedOnboarding(state); + // Selected account is not available during onboarding (this is used in + // the AppHeader) + const selectedAccount = getMaybeSelectedInternalAccount(state); + + // There are no selected account during onboarding. we default to the original EVM behavior. + return ( + !isOnboarded || !selectedAccount || isEvmAccountType(selectedAccount.type) + ); } -export function getMultichainProviderConfig( - state: MultichainState, -): ProviderConfig | MultichainProviderConfig { - return getMultichainIsEvm(state) - ? getProviderConfig(state) - : getMultichainNetwork(state).network; +/** + * Retrieves the provider configuration for a multichain network. + * + * This function extracts the `network` field from the result of `getMultichainNetwork(state)`, + * which is expected to be a `MultichainProviderConfig` object. The naming might suggest that + * it returns a network, but it actually returns a provider configuration specific to a multichain setup. + * + * @param state - The redux state. + * @returns The current multichain provider configuration. + */ +export function getMultichainProviderConfig(state: MultichainState) { + return getMultichainNetwork(state).network; } export function getMultichainCurrentNetwork(state: MultichainState) { @@ -122,11 +145,16 @@ export function getMultichainNativeCurrency(state: MultichainState) { } export function getMultichainCurrentCurrency(state: MultichainState) { - const currentCurrency = getCurrentCurrency(state).toLowerCase(); + const currentCurrency = getCurrentCurrency(state); + + if (getMultichainIsEvm(state)) { + return currentCurrency; + } + // For non-EVM: // To mimic `getCurrentCurrency` we only consider fiat values, otherwise we // fallback to the current ticker symbol value - return currentCurrency === 'usd' + return currentCurrency && currentCurrency.toLowerCase() === 'usd' ? 'usd' : getMultichainProviderConfig(state).ticker; } @@ -151,8 +179,23 @@ export function getMultichainShouldShowFiat(state: MultichainState) { export function getMultichainDefaultToken(state: MultichainState) { const symbol = getMultichainIsEvm(state) - ? getProviderConfig(state).ticker + ? // We fallback to 'ETH' to keep original behavior of `getSwapsDefaultToken` + getProviderConfig(state).ticker ?? 'ETH' : getMultichainProviderConfig(state).ticker; return { symbol }; } + +export function getMultichainCurrentChainId(state: MultichainState) { + const { chainId } = getMultichainProviderConfig(state); + return chainId; +} + +export function getMultichainIsMainnet(state: MultichainState) { + const chainId = getMultichainCurrentChainId(state); + return getMultichainIsEvm(state) + ? getIsMainnet(state) + : // TODO: For now we only check for bitcoin mainnet, but we will need to + // update this for other non-EVM networks later! + chainId === MultichainNetworks.BITCOIN; +} diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index e0fd002d17a1..110a16f86f79 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -327,6 +327,15 @@ export function getInternalAccountByAddress(state, address) { ); } +export function getMaybeSelectedInternalAccount(state) { + // Same as `getSelectedInternalAccount`, but might potentially be `undefined`: + // - This might happen during the onboarding + const accountId = state.metamask.internalAccounts?.selectedAccount; + return accountId + ? state.metamask.internalAccounts?.accounts[accountId] + : undefined; +} + export function getSelectedInternalAccount(state) { const accountId = state.metamask.internalAccounts.selectedAccount; return state.metamask.internalAccounts.accounts[accountId]; From 0d32814de1c31f49d00088359c84a6d54a496c5a Mon Sep 17 00:00:00 2001 From: Prithpal Sooriya <prithpal.sooriya@gmail.com> Date: Fri, 14 Jun 2024 12:26:54 +0100 Subject: [PATCH 46/61] fix: notification detail network fee broke application (#25315) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Yeah, due to some type assertions (evil), we did not receive a correct value expected. Due to this we ended up performing a `.split` on an undefined... then crash. This adds some safer logic and also fixes the area that call the function with the wrong inputs. A separate PR will be ready that fixes these bad type assertions. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25315?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** 1. Create a MATIC send/receive notification 2. Open details 3. See crash ## **Screenshots/Recordings** ![image](https://github.com/MetaMask/metamask-extension/assets/17534261/4f4bb77d-dabd-4226-983a-b6d6ff2bb6b5) <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- ...ification-detail-block-explorer-button.tsx | 2 +- ui/helpers/utils/notification.util.ts | 33 +++++++++---------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx b/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx index 572762578d4b..23237a70a0c7 100644 --- a/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx +++ b/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx @@ -27,7 +27,7 @@ export const NotificationDetailBlockExplorerButton = ({ const chainIdHex = decimalToHex(chainId); const { nativeBlockExplorerUrl } = getNetworkDetailsByChainId( - `0x${chainId}` as keyof typeof CHAIN_IDS, + `0x${chainIdHex}` as keyof typeof CHAIN_IDS, ); const defaultNetworks: NetworkConfiguration[] = useSelector(getAllNetworks); diff --git a/ui/helpers/utils/notification.util.ts b/ui/helpers/utils/notification.util.ts index 598936820a01..b56cc9159263 100644 --- a/ui/helpers/utils/notification.util.ts +++ b/ui/helpers/utils/notification.util.ts @@ -301,8 +301,8 @@ export function getNetworkDetailsByChainId(chainId?: keyof typeof CHAIN_IDS): { nativeBlockExplorerUrl?: string; } { const fullNativeCurrencyName = - NETWORK_TO_NAME_MAP[chainId as keyof typeof NETWORK_TO_NAME_MAP]; - const nativeCurrencyName = fullNativeCurrencyName.split(' ')[0]; + NETWORK_TO_NAME_MAP[chainId as keyof typeof NETWORK_TO_NAME_MAP] ?? ''; + const nativeCurrencyName = fullNativeCurrencyName.split(' ')[0] ?? ''; const nativeCurrencySymbol = CHAIN_ID_TO_CURRENCY_SYMBOL_MAP[ chainId as keyof typeof CHAIN_ID_TO_CURRENCY_SYMBOL_MAP @@ -354,6 +354,8 @@ export function formatIsoDateString(isoDateString: string) { return formattedDate; } +export type HexChainId = (typeof CHAIN_IDS)[keyof typeof CHAIN_IDS]; + /** * Retrieves the RPC URL associated with a given chain ID. * @@ -363,10 +365,8 @@ export function formatIsoDateString(isoDateString: string) { * @param chainId - The chain ID for which the RPC URL is required. * @returns The RPC URL associated with the given chain ID, or undefined if no match is found. */ -export function getRpcUrlByChainId(chainId: keyof typeof CHAIN_IDS): string { - const rpc = FEATURED_RPCS.find( - (rpcItem) => rpcItem.chainId === CHAIN_IDS[chainId], - ); +export function getRpcUrlByChainId(chainId: HexChainId): string { + const rpc = FEATURED_RPCS.find((rpcItem) => rpcItem.chainId === chainId); // If rpc is found, return its URL. Otherwise, return a default URL based on the chainId. if (rpc) { @@ -374,19 +374,19 @@ export function getRpcUrlByChainId(chainId: keyof typeof CHAIN_IDS): string { } // Fallback RPC URLs based on the chainId switch (chainId) { - case 'MAINNET': + case CHAIN_IDS.MAINNET: return MAINNET_RPC_URL; - case 'GOERLI': + case CHAIN_IDS.GOERLI: return GOERLI_RPC_URL; - case 'SEPOLIA': + case CHAIN_IDS.SEPOLIA: return SEPOLIA_RPC_URL; - case 'LINEA_GOERLI': + case CHAIN_IDS.LINEA_GOERLI: return LINEA_GOERLI_RPC_URL; - case 'LINEA_SEPOLIA': + case CHAIN_IDS.LINEA_SEPOLIA: return LINEA_SEPOLIA_RPC_URL; - case 'LINEA_MAINNET': + case CHAIN_IDS.LINEA_MAINNET: return LINEA_MAINNET_RPC_URL; - case 'LOCALHOST': + case CHAIN_IDS.LOCALHOST: return LOCALHOST_RPC_URL; default: // Default to MAINNET if no match is found @@ -405,12 +405,9 @@ export const getNetworkFees = async (notification: OnChainRawNotification) => { throw new Error('Invalid notification type'); } - // eslint-disable-next-line camelcase - const { chain_id } = notification; - const chainId = decimalToHex(chain_id); - + const chainId = decimalToHex(notification.chain_id); const provider = new JsonRpcProvider( - getRpcUrlByChainId(`0x${chainId}` as keyof typeof CHAIN_IDS), + getRpcUrlByChainId(`0x${chainId}` as HexChainId), ); if (!provider) { From 191ab10d2569ca2bf0f75c63fe2f389b9a4371d5 Mon Sep 17 00:00:00 2001 From: seaona <54408225+seaona@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:09:59 +0200 Subject: [PATCH 47/61] fix: flaky test `should not prevent network requests to basic functionality endpoints when the basica functionality toggle is on` (#25316) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** The test fails because it expects a request to the autodetect token endpoint but this doesn't happen before the assertion is made. If we look at the artifacts we can see how after the network switch, MM is still loading. ci: https://app.circleci.com/pipelines/github/MetaMask/metamask-extension/87560/workflows/e7f9a8fd-c4e5-4f08-a8b2-9be559d3ad4c/jobs/3208109/tests#failed-test-0 ![Screenshot from 2024-06-14 13-08-27](https://github.com/MetaMask/metamask-extension/assets/54408225/394c8fe1-5110-4faa-8d35-425a3313b034) ![image](https://github.com/MetaMask/metamask-extension/assets/54408225/a38f1e94-db2f-4f98-9c2b-f2c59585fece) I see that there is a delay after switching networks. Possibly the flakiness was already found at the moment the test was written and this delay intended to mitigate it, but the result of this is not deterministic, since the delay is not enough sometimes and makes the test flaky `await driver.delay(tinyDelayMs);` The fix is to wait deterministically until the network switch has happened. As an addition, to add more certainty, we click on refresh tokens, and we make the assertion of the requests after that. With these 2 actions we increase the certainty that the request will be made before the assertion, however is not 100% deterministic, as we cannot know for sure when the API request is made in the background. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25316?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- test/e2e/tests/privacy/basic-functionality.spec.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/e2e/tests/privacy/basic-functionality.spec.js b/test/e2e/tests/privacy/basic-functionality.spec.js index d20aa0542285..b0f9b54e9928 100644 --- a/test/e2e/tests/privacy/basic-functionality.spec.js +++ b/test/e2e/tests/privacy/basic-functionality.spec.js @@ -66,6 +66,10 @@ describe('MetaMask onboarding @no-mmi', function () { await driver.clickElement({ text: 'Ethereum Mainnet', tag: 'p' }); await driver.delay(tinyDelayMs); + // Wait until network is fully switched and refresh tokens before asserting to mitigate flakiness + await driver.assertElementNotPresent('.loading-overlay'); + await driver.clickElement('[data-testid="refresh-list-button"]'); + for (let i = 0; i < mockedEndpoints.length; i += 1) { const requests = await mockedEndpoints[i].getSeenRequests(); @@ -104,9 +108,12 @@ describe('MetaMask onboarding @no-mmi', function () { await driver.clickElement({ text: 'Ethereum Mainnet', tag: 'p' }); await driver.delay(tinyDelayMs); + // Wait until network is fully switched and refresh tokens before asserting to mitigate flakiness + await driver.assertElementNotPresent('.loading-overlay'); + await driver.clickElement('[data-testid="refresh-list-button"]'); + for (let i = 0; i < mockedEndpoints.length; i += 1) { const requests = await mockedEndpoints[i].getSeenRequests(); - assert.equal( requests.length, 1, From 6163319253424fd56b07bbcc723b2e07c92bcee8 Mon Sep 17 00:00:00 2001 From: Nidhi Kumari <nidhi.kumari@consensys.net> Date: Fri, 14 Jun 2024 14:23:27 +0100 Subject: [PATCH 48/61] fix: Fix switch network popup (#25299) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR is to ensure the network switch modal doesn't show up in a flash when network is switched via the dapp ## **Related issues** Fixes: #25196 ## **Manual testing steps** 1. Go to Pancake swap Dapp 2. Connect MetaMask 3. Switch to Polygon or any network that is not already added to network list in metamask via Dapp 4. Network switch should happen and no modal should up in the flash ## **Screenshots/Recordings** ### **Before** https://github.com/MetaMask/metamask-extension/assets/39872794/ff30359f-2970-4e86-a68d-3bd6250c4d33 ### **After** https://github.com/MetaMask/metamask-extension/assets/39872794/a172ea2a-7db7-4b5f-b698-13e39a52b29a ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Jonathan Bursztyn <jonathan@bursztyn.io> --- ui/pages/routes/routes.component.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/pages/routes/routes.component.js b/ui/pages/routes/routes.component.js index 640cf27751b5..1e795f056eba 100644 --- a/ui/pages/routes/routes.component.js +++ b/ui/pages/routes/routes.component.js @@ -851,7 +851,9 @@ export default class Routes extends Component { } > {shouldShowNetworkDeprecationWarning ? <DeprecatedNetworks /> : null} - {shouldShowNetworkInfo && <NewNetworkInfo />} + {location.pathname === DEFAULT_ROUTE && shouldShowNetworkInfo ? ( + <NewNetworkInfo /> + ) : null} <QRHardwarePopover /> <Modal /> <Alert visible={this.props.alertOpen} msg={alertMessage} /> From 4aa2fd02999b7890b4e3bebc75e674250eb2346e Mon Sep 17 00:00:00 2001 From: seaona <54408225+seaona@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:25:13 +0200 Subject: [PATCH 49/61] fix: flaky test `Navigate transactions should reject and remove all unapproved transactions` (#25312) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR fixes the flaky test `Navigate transactions should reject and remove all unapproved transactions`. It fails with the error `TimeoutError: Waiting for element to be located By(xpath, //button[contains(text(), "Reject all")])`. The problem is that we click the Reject button, before the confirmation screen has fully loaded (specifically, the total amount for that tx is not there yet). This causes the click to don't have any effect and the subsequent popup with the Reject All never appears. The fix is simply await for the tx to be fully loaded (notice how the total amount box is not loaded at the moment of the failure below). Furthermore, it's been observed that the unapproved tx where trying to load simulations (see loading spinner). This shouldn't prevent to continue, but to further stabilize the test, the transactions have now disabled the simulations. - [ci artifacts](https://circleci-tasks-prod.s3.us-east-1.amazonaws.com/forks/storage/artifacts/fb281712-ea41-446f-b28f-c0bea18842cc/798839675/3b956a72-4bc3-4ab4-8711-9d8786b90aa8/9/test-artifacts/chrome/Navigate%20transactions%20should%20reject%20and%20remove%20all%20unapproved%20transactions/test-failure-screenshot.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAQVFQINEOCSPRCGLP%2F20240614%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240614T070310Z&X-Amz-Expires=60&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEAcaCXVzLWVhc3QtMSJGMEQCIHNThdyaubglBTAu8iEWtdQmyJDYsMnHS%2BZ8CmqpNjy1AiA5H6y8x2jtn0y%2FaqCSu1hD7orfORHWGN%2BlWiMbzXCVuiq0Agig%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAMaDDA0NTQ2NjgwNjU1NiIMdGPy5i2bqb9HiCvzKogCQMAcXnKXTqbbgJTWEmcA48k82rWrz3yFA3VtMSFHeb9VRIR9I9yfmm276VvqjjoOpXSa0I8LsuAaYBqZuGFCH7LNLSxpEEZVBjIsLjXMWetTaxbGcdRGyRth6K4B5GBTMxfqBKTGeE1qNWnh84MJpLgsNFVG3dqqGmFojTYrVCVdWVys%2FZfMPgC2WM8MgjtxlebGu9XW%2F9VQsq6A1mukjbox4%2F4ckwq65kPpXqJDvPd7jXLzcEByaU7kjlujipAobC4cOc6SLSQ%2BOVGjc3hXF9AHaKIl7BfS%2F3QmsNyXVrnnnExt3Uzqn1l%2Foen%2BXQHSz4sSmTeDf63fUeSfXZHi51pXSGwTBGnSMIbRr7MGOp4BPkSg3VCEXfzPxTABRXjbB2WTEBDMKXVF5HMgnYnfJ5snWqF6lXuztslav0q3zKbzUhEGg6OPF%2BsZHy%2FvdzPeaVGUoyAqHQjgmZynPsCbTCfv2GfNZkprts%2F9mfXGrGPqTtDzX%2B16Z1%2B13ev8ayTTDDHat8vdzlWkc8SzfX3h3NsZnmUnJA9EpfDTUGvg5rVtw%2BotbpmxJ%2BZJaLNP3Vc%3D&X-Amz-SignedHeaders=host&x-id=GetObject&X-Amz-Signature=5bcdd4ded909d42f11151e5336da7d0e903aaf99438b44c37116884354b55a5f) [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25312?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/metamask-extension/issues/24661 and https://github.com/MetaMask/metamask-extension/issues/24641 ## **Manual testing steps** 1. Check ci 2. Run test locally multiple times `yarn test:e2e:single test/e2e/tests/transaction/navigate-transactions.spec.js --browser=chrome --leave-running --retryUntilFailure --retries=10` ## **Screenshots/Recordings** ### **Before** Notice how when the test failed, the total tx amount was yet not loaded (3.000,..) and we only see the gas displayed. Furthermore: we see the tx simulation element loading (this is not the cause of this failure, but it has also disabled, to stabilize the screen). ![image](https://github.com/MetaMask/metamask-extension/assets/54408225/792d069c-2ab8-41aa-8180-37c84b817a72) ### **After** Notice that the tx simulations loading element is not there. Notice how the correct amount is await until proceeding (3.0000315) ![Screenshot from 2024-06-14 11-33-56](https://github.com/MetaMask/metamask-extension/assets/54408225/7e6e999f-707b-445c-a94b-51734579e767) ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- test/e2e/fixture-builder.js | 86 +++++++++++++++++++ .../transaction/navigate-transactions.spec.js | 35 ++++++++ 2 files changed, 121 insertions(+) diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index 283ed7678edf..f5873fb4cd6a 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -530,6 +530,12 @@ class FixtureBuilder { }); } + withPreferencesControllerTxSimulationsDisabled() { + return this.withPreferencesController({ + useTransactionSimulations: false, + }); + } + withAccountsController(data) { merge(this.fixture.data.AccountsController, data); return this; @@ -814,8 +820,28 @@ class FixtureBuilder { timestamp: 1631545992244, value: false, }, + { + op: 'add', + path: '/simulationData', + value: { + error: { + code: 'disabled', + message: 'Simulation disabled', + }, + tokenBalanceChanges: [], + }, + note: 'TransactionController#updateSimulationData - Update simulation data', + timestamp: 1631545992244, + }, ], ], + simulationData: { + error: { + code: 'disabled', + message: 'Simulation disabled', + }, + tokenBalanceChanges: [], + }, id: '7087d1d7-f0e8-4c0f-a903-6d9daa392baf', loadingDefaults: false, origin: 'https://metamask.github.io', @@ -869,8 +895,28 @@ class FixtureBuilder { timestamp: 1631545994695, value: false, }, + { + op: 'add', + path: '/simulationData', + value: { + error: { + code: 'disabled', + message: 'Simulation disabled', + }, + tokenBalanceChanges: [], + }, + note: 'TransactionController#updateSimulationData - Update simulation data', + timestamp: 1631545992244, + }, ], ], + simulationData: { + error: { + code: 'disabled', + message: 'Simulation disabled', + }, + tokenBalanceChanges: [], + }, id: '6eab4240-3762-4581-abc5-cd91eab6964e', loadingDefaults: false, origin: 'https://metamask.github.io', @@ -924,8 +970,28 @@ class FixtureBuilder { timestamp: 1631545996678, value: false, }, + { + op: 'add', + path: '/simulationData', + value: { + error: { + code: 'disabled', + message: 'Simulation disabled', + }, + tokenBalanceChanges: [], + }, + note: 'TransactionController#updateSimulationData - Update simulation data', + timestamp: 1631545992244, + }, ], ], + simulationData: { + error: { + code: 'disabled', + message: 'Simulation disabled', + }, + tokenBalanceChanges: [], + }, id: 'c15eee26-11d6-4914-a70e-36ef9a3bcacb', loadingDefaults: false, origin: 'https://metamask.github.io', @@ -979,8 +1045,28 @@ class FixtureBuilder { timestamp: 1631545998677, value: false, }, + { + op: 'add', + path: '/simulationData', + value: { + error: { + code: 'disabled', + message: 'Simulation disabled', + }, + tokenBalanceChanges: [], + }, + note: 'TransactionController#updateSimulationData - Update simulation data', + timestamp: 1631545992244, + }, ], ], + simulationData: { + error: { + code: 'disabled', + message: 'Simulation disabled', + }, + tokenBalanceChanges: [], + }, id: 'dfa9e5ad-d069-46b1-976e-a23734971d87', loadingDefaults: false, origin: 'https://metamask.github.io', diff --git a/test/e2e/tests/transaction/navigate-transactions.spec.js b/test/e2e/tests/transaction/navigate-transactions.spec.js index 99807d54f461..12c1144d5472 100644 --- a/test/e2e/tests/transaction/navigate-transactions.spec.js +++ b/test/e2e/tests/transaction/navigate-transactions.spec.js @@ -13,6 +13,7 @@ describe('Navigate transactions', function () { await withFixtures( { fixtures: new FixtureBuilder() + .withPreferencesControllerTxSimulationsDisabled() .withTransactionControllerMultipleTransactions() .build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), @@ -21,6 +22,12 @@ describe('Navigate transactions', function () { async ({ driver }) => { await unlockWallet(driver); + // Wait until total amount is loaded to mitigate flakiness on reject + await driver.findElement({ + tag: 'span', + text: '3.0000315', + }); + // navigate transactions await driver.clickElement('[data-testid="next-page"]'); let navigationElement = await driver.findElement( @@ -102,6 +109,7 @@ describe('Navigate transactions', function () { dapp: true, fixtures: new FixtureBuilder() .withPermissionControllerConnectedToTestDapp() + .withPreferencesControllerTxSimulationsDisabled() .withTransactionControllerMultipleTransactions() .build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), @@ -110,6 +118,12 @@ describe('Navigate transactions', function () { async ({ driver }) => { await unlockWallet(driver); + // Wait until total amount is loaded to mitigate flakiness on reject + await driver.findElement({ + tag: 'span', + text: '3.0000315', + }); + await driver.clickElement('[data-testid="next-page"]'); let navigationElement = await driver.findElement( '.confirm-page-container-navigation', @@ -146,6 +160,7 @@ describe('Navigate transactions', function () { await withFixtures( { fixtures: new FixtureBuilder() + .withPreferencesControllerTxSimulationsDisabled() .withTransactionControllerMultipleTransactions() .build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), @@ -154,6 +169,12 @@ describe('Navigate transactions', function () { async ({ driver }) => { await unlockWallet(driver); + // Wait until total amount is loaded to mitigate flakiness on reject + await driver.findElement({ + tag: 'span', + text: '3.0000315', + }); + // reject transaction await driver.clickElement({ text: 'Reject', tag: 'button' }); const navigationElement = await driver.waitForSelector({ @@ -174,6 +195,7 @@ describe('Navigate transactions', function () { await withFixtures( { fixtures: new FixtureBuilder() + .withPreferencesControllerTxSimulationsDisabled() .withTransactionControllerMultipleTransactions() .build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), @@ -182,6 +204,12 @@ describe('Navigate transactions', function () { async ({ driver }) => { await unlockWallet(driver); + // Wait until total amount is loaded to mitigate flakiness on reject + await driver.findElement({ + tag: 'span', + text: '3.0000315', + }); + // confirm transaction await driver.clickElement({ text: 'Confirm', tag: 'button' }); const navigationElement = await driver.waitForSelector({ @@ -202,6 +230,7 @@ describe('Navigate transactions', function () { await withFixtures( { fixtures: new FixtureBuilder() + .withPreferencesControllerTxSimulationsDisabled() .withTransactionControllerMultipleTransactions() .build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), @@ -210,6 +239,12 @@ describe('Navigate transactions', function () { async ({ driver, ganacheServer }) => { await unlockWallet(driver); + // Wait until total amount is loaded to mitigate flakiness on reject + await driver.findElement({ + tag: 'span', + text: '3.0000315', + }); + // reject transactions await driver.clickElement({ text: 'Reject 4', tag: 'a' }); await driver.clickElement({ text: 'Reject all', tag: 'button' }); From 901289c005e8aed3a28adff30dc91b10c4b7418d Mon Sep 17 00:00:00 2001 From: Monte Lai <monte.lai@consensys.net> Date: Fri, 14 Jun 2024 22:32:33 +0800 Subject: [PATCH 50/61] fix: filter only EVM address when calling syncWithAddresses (#25313) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR applies a removes all non EVM addresses prior to calling `syncWithAddresses` during `_onKeyringControllerUpdate`. This is because the `AccountTracker` does not support non EVM addresses. The `AccountTracker` now also subscribes to `onSelectedEvmAccountChange` instead of `onSelectedAccountChange` ## **Related issues** Fixes: ## **Manual testing steps** ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- app/scripts/lib/account-tracker.js | 2 +- app/scripts/metamask-controller.js | 14 ++++++---- app/scripts/metamask-controller.test.js | 37 ++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index 7de8632e2b74..3918f835f5d8 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -96,7 +96,7 @@ export default class AccountTracker { ); this.controllerMessenger.subscribe( - 'AccountsController:selectedAccountChange', + 'AccountsController:selectedEvmAccountChange', (newAccount) => { const { useMultiAccountBalanceChecker } = this.preferencesController.store.getState(); diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 75488f893ff7..b3783283474b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -330,6 +330,7 @@ import { PushPlatformNotificationsController } from './controllers/push-platform import { MetamaskNotificationsController } from './controllers/metamask-notifications/metamask-notifications'; import { updateSecurityAlertResponse } from './lib/ppom/ppom-util'; import createEvmMethodsToNonEvmAccountReqFilterMiddleware from './lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware'; +import { isEthAddress } from './lib/multichain/address'; export const METAMASK_CONTROLLER_EVENTS = { // Fired after state changes that impact the extension badge (unapproved msg count) @@ -1535,7 +1536,7 @@ export default class MetamaskController extends EventEmitter { onboardingController: this.onboardingController, controllerMessenger: this.controllerMessenger.getRestricted({ name: 'AccountTracker', - allowedEvents: ['AccountsController:selectedAccountChange'], + allowedEvents: ['AccountsController:selectedEvmAccountChange'], allowedActions: ['AccountsController:getSelectedAccount'], }), initState: { accounts: {} }, @@ -4261,6 +4262,7 @@ export default class MetamaskController extends EventEmitter { // Merge with existing accounts // and make sure addresses are not repeated const oldAccounts = await this.keyringController.getAccounts(); + const accountsToTrack = [ ...new Set( oldAccounts.concat(accounts.map((a) => a.address.toLowerCase())), @@ -5612,10 +5614,12 @@ export default class MetamaskController extends EventEmitter { */ async _onKeyringControllerUpdate(state) { const { keyrings } = state; - const addresses = keyrings.reduce( - (acc, { accounts }) => acc.concat(accounts), - [], - ); + + // The accounts tracker only supports EVM addresses and the keyring + // controller may pass non-EVM addresses, so we filter them out + const addresses = keyrings + .reduce((acc, { accounts }) => acc.concat(accounts), []) + .filter(isEthAddress); if (!addresses.length) { return; diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index 4c66e3bf8fac..7bfe1be8bc4a 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -1325,6 +1325,11 @@ describe('MetaMaskController', () => { }); describe('#_onKeyringControllerUpdate', () => { + const accounts = [ + '0x603E83442BA54A2d0E080c34D6908ec228bef59f', + '0xDe95cE6E727692286E02A931d074efD1E5E2f03c', + ]; + it('should do nothing if there are no keyrings in state', async () => { jest .spyOn(metamaskController.accountTracker, 'syncWithAddresses') @@ -1348,14 +1353,14 @@ describe('MetaMaskController', () => { await metamaskController._onKeyringControllerUpdate({ keyrings: [ { - accounts: ['0x1', '0x2'], + accounts, }, ], }); expect( metamaskController.accountTracker.syncWithAddresses, - ).toHaveBeenCalledWith(['0x1', '0x2']); + ).toHaveBeenCalledWith(accounts); expect(metamaskController.getState()).toStrictEqual(oldState); }); @@ -1369,14 +1374,38 @@ describe('MetaMaskController', () => { isUnlocked: true, keyrings: [ { - accounts: ['0x1', '0x2'], + accounts, + }, + ], + }); + + expect( + metamaskController.accountTracker.syncWithAddresses, + ).toHaveBeenCalledWith(accounts); + expect(metamaskController.getState()).toStrictEqual(oldState); + }); + + it('filter out non-EVM addresses prior to calling syncWithAddresses', async () => { + jest + .spyOn(metamaskController.accountTracker, 'syncWithAddresses') + .mockReturnValue(); + + const oldState = metamaskController.getState(); + await metamaskController._onKeyringControllerUpdate({ + keyrings: [ + { + accounts: [ + ...accounts, + // Non-EVM address which should not be used by syncWithAddresses + 'bc1ql49ydapnjafl5t2cp9zqpjwe6pdgmxy98859v2', + ], }, ], }); expect( metamaskController.accountTracker.syncWithAddresses, - ).toHaveBeenCalledWith(['0x1', '0x2']); + ).toHaveBeenCalledWith(accounts); expect(metamaskController.getState()).toStrictEqual(oldState); }); }); From 62ca8ad049cbb13fc04b883d63572d7e5fbda12d Mon Sep 17 00:00:00 2001 From: Matteo Scurati <matteo.scurati@gmail.com> Date: Fri, 14 Jun 2024 17:01:37 +0200 Subject: [PATCH 51/61] fix: use a min-width value in the notifications-tag-counter (#25322) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR introduces a fix for a bug related to the UI of the `notifications-tag-counter` component. The component now has a min-width to prevent the tag from appearing squished in the case of a single character. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25322?quickstart=1) ## **Related issues** ## **Manual testing steps** ## **Screenshots/Recordings** ### **Before** <img width="97" alt="Screenshot 2024-06-14 at 11 58 07" src="https://github.com/MetaMask/metamask-extension/assets/1284304/e9344e9b-ef7b-421b-8631-a19b27f90bc0"> ### **After** <img width="214" alt="Screenshot 2024-06-14 at 14 54 30" src="https://github.com/MetaMask/metamask-extension/assets/1284304/5704f5d7-a16f-4de9-812a-e4d6c59fb4f6"> <img width="279" alt="Screenshot 2024-06-14 at 14 54 35" src="https://github.com/MetaMask/metamask-extension/assets/1284304/4eb2de3b-ca53-428a-abc8-0b720cd2eb32"> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../app-header/__snapshots__/app-header.test.js.snap | 4 ++-- .../multichain/notifications-tag-counter/index.scss | 5 +++++ .../notifications-tag-counter.tsx | 8 ++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap b/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap index 290cdbe01773..d464e487dd57 100644 --- a/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap +++ b/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap @@ -383,11 +383,11 @@ exports[`App Header should match snapshot 1`] = ` style="position: relative;" > <div - class="mm-box notification-list-item__unread-dot__wrapper mm-box--padding-top-0 mm-box--padding-right-0 mm-box--padding-bottom-0 mm-box--padding-left-0 mm-box--display-block mm-box--background-color-error-default mm-box--rounded-md mm-box--border-style-none" + class="mm-box notification-list-item__unread-dot__wrapper mm-box--padding-top-0 mm-box--padding-right-0 mm-box--padding-bottom-0 mm-box--padding-left-0 mm-box--display-block mm-box--background-color-error-default mm-box--rounded-lg mm-box--border-style-none" style="position: absolute; cursor: pointer; top: -5px; left: 10px; z-index: 1;" > <p - class="mm-box mm-text notifications-tag-counter__unread-dot mm-text--body-xs mm-box--color-error-inverse" + class="mm-box mm-text notifications-tag-counter__unread-dot mm-text--body-xs mm-text--text-align-center mm-box--color-error-inverse" > 1 </p> diff --git a/ui/components/multichain/notifications-tag-counter/index.scss b/ui/components/multichain/notifications-tag-counter/index.scss index f5c8b1fe1e03..328c4cb9728d 100644 --- a/ui/components/multichain/notifications-tag-counter/index.scss +++ b/ui/components/multichain/notifications-tag-counter/index.scss @@ -2,7 +2,12 @@ padding-left: 6px; padding-right: 6px; + &__text { + min-width: 13px; + } + &__unread-dot { + min-width: 16.5px; padding-left: 3px; padding-right: 3px; line-height: 1.4; diff --git a/ui/components/multichain/notifications-tag-counter/notifications-tag-counter.tsx b/ui/components/multichain/notifications-tag-counter/notifications-tag-counter.tsx index 39b2b0175db1..4964eb8e7a23 100644 --- a/ui/components/multichain/notifications-tag-counter/notifications-tag-counter.tsx +++ b/ui/components/multichain/notifications-tag-counter/notifications-tag-counter.tsx @@ -8,6 +8,7 @@ import { Display, TextColor, TextVariant, + TextAlign, } from '../../../helpers/constants/design-system'; type NotificationsTagCounterProps = { @@ -37,7 +38,7 @@ export const NotificationsTagCounter = ({ }} backgroundColor={BackgroundColor.errorDefault} borderStyle={BorderStyle.none} - borderRadius={BorderRadius.MD} + borderRadius={BorderRadius.LG} paddingTop={0} paddingBottom={0} paddingLeft={0} @@ -47,6 +48,7 @@ export const NotificationsTagCounter = ({ color={TextColor.errorInverse} variant={TextVariant.bodyXs} className="notifications-tag-counter__unread-dot" + textAlign={TextAlign.Center} > {notificationsCount > 10 ? '9+' : notificationsCount} </Text> @@ -58,7 +60,7 @@ export const NotificationsTagCounter = ({ <Box backgroundColor={BackgroundColor.errorDefault} borderStyle={BorderStyle.none} - borderRadius={BorderRadius.MD} + borderRadius={BorderRadius.LG} paddingTop={0} paddingBottom={0} className="notifications-tag-counter" @@ -67,6 +69,8 @@ export const NotificationsTagCounter = ({ color={TextColor.errorInverse} variant={TextVariant.bodySm} data-testid="global-menu-notification-count" + className="notifications-tag-counter__text" + textAlign={TextAlign.Center} > {notificationsCount > 10 ? '9+' : notificationsCount} </Text> From 6eee01ace64ab1e424a1cb3c7ab578846eb43ddd Mon Sep 17 00:00:00 2001 From: Norbert Elter <72046715+itsyoboieltr@users.noreply.github.com> Date: Fri, 14 Jun 2024 17:11:11 +0200 Subject: [PATCH 52/61] feat: Add team label to pr (#25208) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25071?quickstart=1) This PR adds the `add-team-label` GitHub workflow and the accompanying `add-team-label-to-pr` script. Most of the implementation follows the `add-release-label` GitHub workflow and the `add-release-label-to-pr-and-linked-issues` script. To make the implementation easier, a new helper function, `addLabelByIdToLabelable` was also added, and the previously non-exported `retrieveLabel` function was exported. When a new PR is opened, it will automatically add the author's team to the labels. ## **Related issues** Fixes: https://github.com/MetaMask/MetaMask-planning/issues/2447 ## **Manual testing steps** 1. Still pending ## **Screenshots/Recordings** Not applicable ## **Pre-merge author checklist** - [x] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .github/scripts/add-team-label-to-pr.ts | 89 +++++++++++++++++++++++++ .github/scripts/shared/label.ts | 2 +- .github/scripts/shared/labelable.ts | 23 +++++-- .github/workflows/add-team-label.yml | 37 ++++++++++ package.json | 1 + 5 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 .github/scripts/add-team-label-to-pr.ts create mode 100644 .github/workflows/add-team-label.yml diff --git a/.github/scripts/add-team-label-to-pr.ts b/.github/scripts/add-team-label-to-pr.ts new file mode 100644 index 000000000000..fbbbe30cac37 --- /dev/null +++ b/.github/scripts/add-team-label-to-pr.ts @@ -0,0 +1,89 @@ +import * as core from '@actions/core'; +import { context, getOctokit } from '@actions/github'; +import { GitHub } from '@actions/github/lib/utils'; + +import { retrieveLabel } from './shared/label'; +import { Labelable, addLabelByIdToLabelable } from './shared/labelable'; +import { retrievePullRequest } from './shared/pull-request'; + +main().catch((error: Error): void => { + console.error(error); + process.exit(1); +}); + +async function main(): Promise<void> { + // "GITHUB_TOKEN" is an automatically generated, repository-specific access token provided by GitHub Actions. + // We can't use "GITHUB_TOKEN" here, as its permissions are scoped to the repository where the action is running. + // "GITHUB_TOKEN" does not have access to other repositories, even when they belong to the same organization. + // As we want to get files which are not necessarily located in the same repository, + // we need to create our own "RELEASE_LABEL_TOKEN" with "repo" permissions. + // Such a token allows to access other repositories of the MetaMask organisation. + const personalAccessToken = process.env.RELEASE_LABEL_TOKEN; + if (!personalAccessToken) { + core.setFailed('RELEASE_LABEL_TOKEN not found'); + process.exit(1); + } + + // Initialise octokit, required to call Github GraphQL API + const octokit: InstanceType<typeof GitHub> = getOctokit(personalAccessToken, { + previews: ['bane'], // The "bane" preview is required for adding, updating, creating and deleting labels. + }); + + // Retrieve pull request info from context + const pullRequestRepoOwner = context.repo.owner; + const pullRequestRepoName = context.repo.repo; + const pullRequestNumber = context.payload.pull_request?.number; + if (!pullRequestNumber) { + core.setFailed('Pull request number not found'); + process.exit(1); + } + + // Retrieve pull request + const pullRequest: Labelable = await retrievePullRequest( + octokit, + pullRequestRepoOwner, + pullRequestRepoName, + pullRequestNumber, + ); + + // Get the team label id based on the author of the pull request + const teamLabelId = await getTeamLabelIdByAuthor( + octokit, + pullRequestRepoOwner, + pullRequestRepoName, + pullRequest.author, + ); + + // Add the team label by id to the pull request + await addLabelByIdToLabelable(octokit, pullRequest, teamLabelId); +} + +// This helper function gets the team label id based on the author of the pull request +const getTeamLabelIdByAuthor = async ( + octokit: InstanceType<typeof GitHub>, + repoOwner: string, + repoName: string, + author: string, +): Promise<string> => { + // Retrieve the teams.json file from the repository + const { data } = (await octokit.request( + 'GET /repos/{owner}/{repo}/contents/{path}', + { owner: repoOwner, repo: 'MetaMask-planning', path: 'teams.json' }, + )) as { data: { content: string } }; + + // Parse the teams.json file content to json from base64 + const teamMembers: Record<string, string> = JSON.parse(atob(data.content)); + + // Get the label name based on the author + const labelName = teamMembers[author]; + + if (!labelName) { + core.setFailed(`Team label not found for author: ${author}`); + process.exit(1); + } + + // Retrieve the label id based on the label name + const labelId = await retrieveLabel(octokit, repoOwner, repoName, labelName); + + return labelId; +}; diff --git a/.github/scripts/shared/label.ts b/.github/scripts/shared/label.ts index 2a0632a263de..d218dcf42570 100644 --- a/.github/scripts/shared/label.ts +++ b/.github/scripts/shared/label.ts @@ -93,7 +93,7 @@ async function createLabel( } // This function retrieves the label on a specific repo -async function retrieveLabel( +export async function retrieveLabel( octokit: InstanceType<typeof GitHub>, repoOwner: string, repoName: string, diff --git a/.github/scripts/shared/labelable.ts b/.github/scripts/shared/labelable.ts index 9726297ea714..28d2307ecc11 100644 --- a/.github/scripts/shared/labelable.ts +++ b/.github/scripts/shared/labelable.ts @@ -27,14 +27,14 @@ export interface Labelable { export function findLabel( labelable: Labelable, labelToFind: Label, -): { - id: string; - name: string; -} | undefined { +): + | { + id: string; + name: string; + } + | undefined { // Check if label is present on labelable - return labelable.labels.find( - (label) => label.name === labelToFind.name, - ); + return labelable.labels.find((label) => label.name === labelToFind.name); } // This function adds label to a labelable object (i.e. a pull request or an issue) @@ -51,6 +51,15 @@ export async function addLabelToLabelable( label, ); + await addLabelByIdToLabelable(octokit, labelable, labelId); +} + +// This function adds label by id to a labelable object (i.e. a pull request or an issue) +export async function addLabelByIdToLabelable( + octokit: InstanceType<typeof GitHub>, + labelable: Labelable, + labelId: string, +): Promise<void> { const addLabelsToLabelableMutation = ` mutation AddLabelsToLabelable($labelableId: ID!, $labelIds: [ID!]!) { addLabelsToLabelable(input: {labelableId: $labelableId, labelIds: $labelIds}) { diff --git a/.github/workflows/add-team-label.yml b/.github/workflows/add-team-label.yml new file mode 100644 index 000000000000..eba9e48c1f15 --- /dev/null +++ b/.github/workflows/add-team-label.yml @@ -0,0 +1,37 @@ +name: Add team label to PR when it is opened + +on: + pull_request: + types: + - opened + +jobs: + add-team-label: + runs-on: ubuntu-latest + steps: + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + + - run: corepack enable + + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # This is needed to checkout all branches + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: yarn + + - name: Install dependencies + run: yarn --immutable + + - name: Add team label to PR + id: add-team-label-to-pr + env: + RELEASE_LABEL_TOKEN: ${{ secrets.RELEASE_LABEL_TOKEN }} + run: yarn run add-team-label-to-pr diff --git a/package.json b/package.json index 889deb2d6bf4..15793428c358 100644 --- a/package.json +++ b/package.json @@ -114,6 +114,7 @@ "generate-beta-commit": "node ./development/generate-beta-commit.js", "validate-branch-name": "validate-branch-name", "add-release-label-to-pr-and-linked-issues": "ts-node ./.github/scripts/add-release-label-to-pr-and-linked-issues.ts", + "add-team-label-to-pr": "ts-node ./.github/scripts/add-team-label-to-pr.ts", "check-pr-has-required-labels": "ts-node ./.github/scripts/check-pr-has-required-labels.ts", "close-release-bug-report-issue": "ts-node ./.github/scripts/close-release-bug-report-issue.ts", "check-template-and-add-labels": "ts-node ./.github/scripts/check-template-and-add-labels.ts", From b0a05f042b69e3569eebbcdafa66be14ce5b5267 Mon Sep 17 00:00:00 2001 From: seaona <54408225+seaona@users.noreply.github.com> Date: Fri, 14 Jun 2024 18:47:00 +0200 Subject: [PATCH 53/61] fix: flaky test `vault decrypt` due to SRP hold time (#25328) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This fixes another point of flakiness for the vault decrypt test. The logs show: ``` [driver] Called 'holdMouseDownOnElement' with arguments [{"text":"Hold to reveal SRP","tag":"span"},2000] [driver] Called 'findElement' with arguments ["[data-testid=\"srp_text\"]"] Failure on testcase: 'undefined', for more information see the artifacts tab in CI ``` The problem is that the holding time is not long enough so the srp element cannot be found. To repro, you can make a small time for the holding, and you'll see you hit the error. For fixing it we increase the holding time so we make sure that we'll always hold it until the required amount of time, within any variation of ci environment https://github.com/MetaMask/metamask-extension/assets/54408225/3251f205-4802-4f88-bcee-5a93203119a0 - ci : https://app.circleci.com/pipelines/github/MetaMask/metamask-extension/87595/workflows/a9d135e4-ecef-44b6-a564-e8e3ca6813b5/jobs/3210020/steps Fix: https://github.com/MetaMask/metamask-extension/assets/54408225/db882cfa-ca2e-4a18-9a15-c0b740def439 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25328?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/metamask-extension/issues/25329 ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- test/e2e/helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 3fb5f9f111ae..da554f59718c 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -638,7 +638,7 @@ const tapAndHoldToRevealSRP = async (driver) => { text: tEn('holdToRevealSRP'), tag: 'span', }, - 2000, + 3000, ); }; From 743f5ec3c05b6287dead68bff903f2a244fd816d Mon Sep 17 00:00:00 2001 From: Dan J Miller <danjm.com@gmail.com> Date: Fri, 14 Jun 2024 14:19:48 -0230 Subject: [PATCH 54/61] fix: Ensure phishing stale list network request is not sent before onboarding and if basic functionality is off (#25306) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This fix ensures that network requests for the phishing list are sent in two cases: 1. before onboarding is complete 2. after onboarding is complete if either the basic functionality toggle or the use phishing detection toggle is off To ensure the first, a call to `this.phishingController.maybeUpdateState()` in the metamask controller constructor was moved to the `postOnboardingInitialization` function. To ensure #2, two fixes were needed: - prevent the aforementioned call from occury of the `usePhishDetect` preference property is false - have the `setUsePhishDetect` call that is made in `handleSubmit` of `onboarding-flow/privacy-settings/privacy-settings.js` submit false if the basic functionality toggle is off and the user has not independently set the phishing detection toggle to on. This requires, in the advanced section of the onboarding flow, to default the phishing detection toggle setting to the basic functionality toggle value (`externalServicesOnboardingToggleState`), but then only using the phishing toggle value if the user sets that independently. the `basic-functionality.spec.js` e2e tests were updated to ensure that when the basic functionality toggle is off, no network request is sent to the phishing endpoint, and that a request is sent when the toggle is on. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25306?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/MetaMask-planning/issues/2625 ## **Manual testing steps** 1. Install and open the service worker (background) console, and open the network tab 2. There should be no request to the phishing endpoint 3. Go through onboarding and toggle off the basic functionality toggle in advanced settings, there should still be not network request to the phishing endpoint 4. Uninstall and re-install and go through the above steps, but do not toggle off the basic functionality toggle. There should now be a network request to the phishing endpoint after the user completes onboarding. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- app/scripts/metamask-controller.js | 8 ++++++-- test/e2e/tests/privacy/basic-functionality.spec.js | 7 +++++++ .../privacy-settings/privacy-settings.js | 13 ++++++++----- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b3783283474b..cc9e91e9e889 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -865,8 +865,6 @@ export default class MetamaskController extends EventEmitter { stalelistRefreshInterval: process.env.IN_TEST ? 30 * SECOND : undefined, }); - this.phishingController.maybeUpdateState(); - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) this.ppomController = new PPOMController({ messenger: this.controllerMessenger.getRestricted({ @@ -2339,7 +2337,13 @@ export default class MetamaskController extends EventEmitter { } postOnboardingInitialization() { + const { usePhishDetect } = this.preferencesController.store.getState(); + this.networkController.lookupNetwork(); + + if (usePhishDetect) { + this.phishingController.maybeUpdateState(); + } } triggerNetworkrequests() { diff --git a/test/e2e/tests/privacy/basic-functionality.spec.js b/test/e2e/tests/privacy/basic-functionality.spec.js index b0f9b54e9928..aef2f16728de 100644 --- a/test/e2e/tests/privacy/basic-functionality.spec.js +++ b/test/e2e/tests/privacy/basic-functionality.spec.js @@ -7,10 +7,17 @@ const { tinyDelayMs, defaultGanacheOptions, } = require('../../helpers'); +const { METAMASK_STALELIST_URL } = require('../phishing-controller/helpers'); const FixtureBuilder = require('../../fixture-builder'); async function mockApis(mockServer) { return [ + await mockServer.forGet(METAMASK_STALELIST_URL).thenCallback(() => { + return { + statusCode: 200, + body: [{ fakedata: true }], + }; + }), await mockServer .forGet('https://token.api.cx.metamask.io/tokens/1') .thenCallback(() => { diff --git a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js index 30cc64553fcc..60bd84965013 100644 --- a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js +++ b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js @@ -104,7 +104,6 @@ export default function PrivacySettings() { const defaultState = useSelector((state) => state.metamask); const { incomingTransactionsPreferences, - usePhishDetect, use4ByteResolution, useTokenDetection, useCurrencyRateCheck, @@ -116,8 +115,7 @@ export default function PrivacySettings() { const petnamesEnabled = useSelector(getPetnamesEnabled); const participateInMetaMetrics = useSelector(selectParticipateInMetaMetrics); - const [usePhishingDetection, setUsePhishingDetection] = - useState(usePhishDetect); + const [usePhishingDetection, setUsePhishingDetection] = useState(null); const [turnOn4ByteResolution, setTurnOn4ByteResolution] = useState(use4ByteResolution); const [turnOnTokenDetection, setTurnOnTokenDetection] = @@ -146,13 +144,18 @@ export default function PrivacySettings() { getExternalServicesOnboardingToggleState, ); + const phishingToggleState = + usePhishingDetection === null + ? externalServicesOnboardingToggleState + : usePhishingDetection; + const profileSyncingProps = useProfileSyncingProps( externalServicesOnboardingToggleState, ); const handleSubmit = () => { dispatch(toggleExternalServices(externalServicesOnboardingToggleState)); - dispatch(setUsePhishDetect(usePhishingDetection)); + dispatch(setUsePhishDetect(phishingToggleState)); dispatch(setUse4ByteResolution(turnOn4ByteResolution)); dispatch(setUseTokenDetection(turnOnTokenDetection)); dispatch( @@ -320,7 +323,7 @@ export default function PrivacySettings() { )} <Setting - value={usePhishingDetection} + value={phishingToggleState} setValue={setUsePhishingDetection} title={t('usePhishingDetection')} description={t('onboardingUsePhishingDetectionDescription', [ From 2aaf56590ba23a4cbaed1c13ef223a56665942e3 Mon Sep 17 00:00:00 2001 From: Norbert Elter <72046715+itsyoboieltr@users.noreply.github.com> Date: Fri, 14 Jun 2024 20:16:55 +0200 Subject: [PATCH 55/61] feat: Convert MetaMetricsController tests from mocha to jest (#25210) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25168?quickstart=1) This PR converts `app/scripts/controllers/metametrics.test.js` from mocha to jest. In particular, replaces instances of `assert` with `expect`, and removes `sinon` and uses `jest`'s mocking capabilities in its place. The `jest.config.js` was updated to include `app/scripts/controllers/metametrics.test.js` in the `testMatch` array. The `.mocharc.js` was updated to ignore the test. ## **Related issues** Fixes: #19355, #25092 ## **Manual testing steps** 1. Running `yarn jest -- app/scripts/controllers/metametrics.test.js` and seeing all tests pass 2. Running `yarn test:unit:mocha` and not seeing the metametrics tests run. ## **Screenshots/Recordings** Not applicable ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .eslintrc.js | 2 + .mocharc.js | 1 + app/scripts/controllers/metametrics.test.js | 588 ++++++++++---------- jest.config.js | 1 + 4 files changed, 291 insertions(+), 301 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index a2207e6ba560..3edfd2469d3f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -269,6 +269,7 @@ module.exports = { excludedFiles: [ 'app/scripts/controllers/app-state.test.js', 'app/scripts/controllers/mmi-controller.test.js', + 'app/scripts/controllers/metametrics.test.js', 'app/scripts/controllers/permissions/**/*.test.js', 'app/scripts/controllers/preferences.test.js', 'app/scripts/lib/**/*.test.js', @@ -300,6 +301,7 @@ module.exports = { '**/__snapshots__/*.snap', 'app/scripts/controllers/app-state.test.js', 'app/scripts/controllers/mmi-controller.test.ts', + 'app/scripts/controllers/metametrics.test.js', 'app/scripts/controllers/permissions/**/*.test.js', 'app/scripts/controllers/preferences.test.js', 'app/scripts/lib/**/*.test.js', diff --git a/.mocharc.js b/.mocharc.js index 5febd260a6cd..fc5b45ce387c 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -8,6 +8,7 @@ module.exports = { './app/scripts/controllers/app-state.test.js', './app/scripts/controllers/permissions/**/*.test.js', './app/scripts/controllers/mmi-controller.test.ts', + './app/scripts/controllers/metametrics.test.js', './app/scripts/controllers/preferences.test.js', './app/scripts/constants/error-utils.test.js', './app/scripts/metamask-controller.test.js', diff --git a/app/scripts/controllers/metametrics.test.js b/app/scripts/controllers/metametrics.test.js index 431a5d152c7f..43834f01a4b9 100644 --- a/app/scripts/controllers/metametrics.test.js +++ b/app/scripts/controllers/metametrics.test.js @@ -1,5 +1,3 @@ -import { strict as assert } from 'assert'; -import sinon from 'sinon'; import { toHex } from '@metamask/controller-utils'; import { NameType } from '@metamask/name-controller'; import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app'; @@ -9,7 +7,6 @@ import { METAMETRICS_BACKGROUND_PAGE_OBJECT, MetaMetricsUserTrait, } from '../../../shared/constants/metametrics'; -import waitUntilCalled from '../../../test/lib/wait-until-called'; import { CHAIN_IDS, CURRENCY_SYMBOLS } from '../../../shared/constants/network'; import * as Utils from '../lib/util'; import MetaMetricsController from './metametrics'; @@ -78,13 +75,13 @@ function getMockPreferencesStore({ currentLocale = LOCALE } = {}) { let preferencesStore = { currentLocale, }; - const subscribe = sinon.stub(); + const subscribe = jest.fn(); const updateState = (newState) => { preferencesStore = { ...preferencesStore, ...newState }; - subscribe.getCall(0).args[0](preferencesStore); + subscribe.mock.calls[0][0](preferencesStore); }; return { - getState: sinon.stub().returns(preferencesStore), + getState: jest.fn().mockReturnValue(preferencesStore), updateState, subscribe, }; @@ -145,27 +142,36 @@ function getMetaMetricsController({ describe('MetaMetricsController', function () { const now = new Date(); - let clock; beforeEach(function () { globalThis.sentry = { - startSession: sinon.fake(() => { - /** NOOP */ - }), - endSession: sinon.fake(() => { - /** NOOP */ - }), + startSession: jest.fn(), + endSession: jest.fn(), }; - clock = sinon.useFakeTimers(now.getTime()); - sinon.stub(Utils, 'generateRandomId').returns('DUMMY_RANDOM_ID'); + jest.useFakeTimers().setSystemTime(now.getTime()); + jest.spyOn(Utils, 'generateRandomId').mockReturnValue('DUMMY_RANDOM_ID'); }); describe('constructor', function () { it('should properly initialize', function () { - const mock = sinon.mock(segment); - mock - .expects('track') - .once() - .withArgs({ + const spy = jest.spyOn(segment, 'track'); + const metaMetricsController = getMetaMetricsController(); + expect(metaMetricsController.version).toStrictEqual(VERSION); + expect(metaMetricsController.chainId).toStrictEqual(FAKE_CHAIN_ID); + expect( + metaMetricsController.state.participateInMetaMetrics, + ).toStrictEqual(true); + expect(metaMetricsController.state.metaMetricsId).toStrictEqual( + TEST_META_METRICS_ID, + ); + expect(metaMetricsController.locale).toStrictEqual( + LOCALE.replace('_', '-'), + ); + expect(metaMetricsController.state.fragments).toStrictEqual({ + testid: SAMPLE_PERSISTED_EVENT, + }); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { event: 'sample non-persisted event failure', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, @@ -175,26 +181,9 @@ describe('MetaMetricsController', function () { }, messageId: 'sample-non-persisted-event-failure', timestamp: new Date(), - }); - const metaMetricsController = getMetaMetricsController(); - assert.strictEqual(metaMetricsController.version, VERSION); - assert.strictEqual(metaMetricsController.chainId, FAKE_CHAIN_ID); - assert.strictEqual( - metaMetricsController.state.participateInMetaMetrics, - true, - ); - assert.strictEqual( - metaMetricsController.state.metaMetricsId, - TEST_META_METRICS_ID, - ); - assert.strictEqual( - metaMetricsController.locale, - LOCALE.replace('_', '-'), + }, + spy.mock.calls[0][1], ); - assert.deepStrictEqual(metaMetricsController.state.fragments, { - testid: SAMPLE_PERSISTED_EVENT, - }); - mock.verify(); }); it('should update when network changes', function () { @@ -211,7 +200,7 @@ describe('MetaMetricsController', function () { chainId = '0x222'; networkDidChangeListener(); - assert.strictEqual(metaMetricsController.chainId, '0x222'); + expect(metaMetricsController.chainId).toStrictEqual('0x222'); }); it('should update when preferences changes', function () { @@ -219,20 +208,17 @@ describe('MetaMetricsController', function () { const metaMetricsController = getMetaMetricsController({ preferencesStore, }); - preferencesStore.updateState({ - currentLocale: 'en_UK', - }); - assert.strictEqual(metaMetricsController.locale, 'en-UK'); + preferencesStore.updateState({ currentLocale: 'en_UK' }); + expect(metaMetricsController.locale).toStrictEqual('en-UK'); }); }); describe('generateMetaMetricsId', function () { it('should generate an 0x prefixed hex string', function () { const metaMetricsController = getMetaMetricsController(); - assert.equal( + expect( metaMetricsController.generateMetaMetricsId().startsWith('0x'), - true, - ); + ).toStrictEqual(true); }); }); @@ -244,92 +230,79 @@ describe('MetaMetricsController', function () { }); // Starts off being empty. - assert.equal(metaMetricsController.state.metaMetricsId, null); + expect(metaMetricsController.state.metaMetricsId).toStrictEqual(null); // Create a new metametrics id. const clientMetaMetricsId = metaMetricsController.getMetaMetricsId(); - assert.equal(clientMetaMetricsId.startsWith('0x'), true); + expect(clientMetaMetricsId.startsWith('0x')).toStrictEqual(true); // Return same metametrics id. const sameMetaMetricsId = metaMetricsController.getMetaMetricsId(); - assert.equal(clientMetaMetricsId, sameMetaMetricsId); + expect(clientMetaMetricsId).toStrictEqual(sameMetaMetricsId); }); }); describe('identify', function () { - it('should call segment.identify for valid traits if user is participating in metametrics', async function () { + it('should call segment.identify for valid traits if user is participating in metametrics', function () { + const spy = jest.spyOn(segment, 'identify'); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: true, metaMetricsId: TEST_META_METRICS_ID, }); - const mock = sinon.mock(segment); - - mock.expects('identify').once().withArgs({ - userId: TEST_META_METRICS_ID, - traits: MOCK_TRAITS, - messageId: Utils.generateRandomId(), - timestamp: new Date(), - }); - metaMetricsController.identify({ ...MOCK_TRAITS, ...MOCK_INVALID_TRAITS, }); - - mock.verify(); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { + userId: TEST_META_METRICS_ID, + traits: MOCK_TRAITS, + messageId: Utils.generateRandomId(), + timestamp: new Date(), + }, + spy.mock.calls[0][1], + ); }); - it('should transform date type traits into ISO-8601 timestamp strings', async function () { + it('should transform date type traits into ISO-8601 timestamp strings', function () { + const spy = jest.spyOn(segment, 'identify'); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: true, metaMetricsId: TEST_META_METRICS_ID, }); - const mock = sinon.mock(segment); - - const mockDate = new Date(); - const mockDateISOString = mockDate.toISOString(); - - mock - .expects('identify') - .once() - .withArgs({ + metaMetricsController.identify({ test_date: new Date().toISOString() }); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { userId: TEST_META_METRICS_ID, traits: { - test_date: mockDateISOString, + test_date: new Date().toISOString(), }, messageId: Utils.generateRandomId(), timestamp: new Date(), - }); - - metaMetricsController.identify({ - test_date: mockDate, - }); - mock.verify(); + }, + spy.mock.calls[0][1], + ); }); it('should not call segment.identify if user is not participating in metametrics', function () { + const spy = jest.spyOn(segment, 'identify'); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: false, }); - const mock = sinon.mock(segment); - - mock.expects('identify').never(); - metaMetricsController.identify(MOCK_TRAITS); - mock.verify(); + expect(spy).toHaveBeenCalledTimes(0); }); - it('should not call segment.identify if there are no valid traits to identify', async function () { + it('should not call segment.identify if there are no valid traits to identify', function () { + const spy = jest.spyOn(segment, 'identify'); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: true, metaMetricsId: TEST_META_METRICS_ID, }); - const mock = sinon.mock(segment); - - mock.expects('identify').never(); - metaMetricsController.identify(MOCK_INVALID_TRAITS); - mock.verify(); + expect(spy).toHaveBeenCalledTimes(0); }); }); @@ -339,28 +312,35 @@ describe('MetaMetricsController', function () { participateInMetaMetrics: null, metaMetricsId: null, }); - assert.equal(metaMetricsController.state.participateInMetaMetrics, null); + expect( + metaMetricsController.state.participateInMetaMetrics, + ).toStrictEqual(null); await metaMetricsController.setParticipateInMetaMetrics(true); - assert.ok(globalThis.sentry.startSession.calledOnce); - assert.equal(metaMetricsController.state.participateInMetaMetrics, true); + expect(globalThis.sentry.startSession).toHaveBeenCalledTimes(1); + expect( + metaMetricsController.state.participateInMetaMetrics, + ).toStrictEqual(true); await metaMetricsController.setParticipateInMetaMetrics(false); - assert.equal(metaMetricsController.state.participateInMetaMetrics, false); + expect( + metaMetricsController.state.participateInMetaMetrics, + ).toStrictEqual(false); }); it('should generate and update the metaMetricsId when set to true', async function () { const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: null, metaMetricsId: null, }); - assert.equal(metaMetricsController.state.metaMetricsId, null); + expect(metaMetricsController.state.metaMetricsId).toStrictEqual(null); await metaMetricsController.setParticipateInMetaMetrics(true); - assert.equal(typeof metaMetricsController.state.metaMetricsId, 'string'); + expect(typeof metaMetricsController.state.metaMetricsId).toStrictEqual( + 'string', + ); }); it('should not nullify the metaMetricsId when set to false', async function () { const metaMetricsController = getMetaMetricsController(); await metaMetricsController.setParticipateInMetaMetrics(false); - assert.ok(globalThis.sentry.endSession.calledOnce); - assert.equal( - metaMetricsController.state.metaMetricsId, + expect(globalThis.sentry.endSession).toHaveBeenCalledTimes(1); + expect(metaMetricsController.state.metaMetricsId).toStrictEqual( TEST_META_METRICS_ID, ); }); @@ -368,11 +348,10 @@ describe('MetaMetricsController', function () { describe('submitEvent', function () { it('should not track an event if user is not participating in metametrics', function () { - const mock = sinon.mock(segment); + const spy = jest.spyOn(segment, 'track'); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: false, }); - mock.expects('track').never(); metaMetricsController.submitEvent({ event: 'Fake Event', category: 'Unit Test', @@ -380,18 +359,27 @@ describe('MetaMetricsController', function () { test: 1, }, }); - mock.verify(); + expect(spy).toHaveBeenCalledTimes(0); }); it('should track an event if user has not opted in, but isOptIn is true', function () { - const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: true, }); - mock - .expects('track') - .once() - .withArgs({ + const spy = jest.spyOn(segment, 'track'); + metaMetricsController.submitEvent( + { + event: 'Fake Event', + category: 'Unit Test', + properties: { + test: 1, + }, + }, + { isOptIn: true }, + ); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', anonymousId: METAMETRICS_ANONYMOUS_ID, context: DEFAULT_TEST_CONTEXT, @@ -401,7 +389,16 @@ describe('MetaMetricsController', function () { }, messageId: Utils.generateRandomId(), timestamp: new Date(), - }); + }, + spy.mock.calls[0][1], + ); + }); + + it('should track an event during optin and allow for metaMetricsId override', function () { + const metaMetricsController = getMetaMetricsController({ + participateInMetaMetrics: true, + }); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent( { event: 'Fake Event', @@ -410,20 +407,11 @@ describe('MetaMetricsController', function () { test: 1, }, }, - { isOptIn: true }, + { isOptIn: true, metaMetricsId: 'TESTID' }, ); - mock.verify(); - }); - - it('should track an event during optin and allow for metaMetricsId override', function () { - const mock = sinon.mock(segment); - const metaMetricsController = getMetaMetricsController({ - participateInMetaMetrics: true, - }); - mock - .expects('track') - .once() - .withArgs({ + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', userId: 'TESTID', context: DEFAULT_TEST_CONTEXT, @@ -433,7 +421,14 @@ describe('MetaMetricsController', function () { }, messageId: Utils.generateRandomId(), timestamp: new Date(), - }); + }, + spy.mock.calls[0][1], + ); + }); + + it('should track a legacy event', function () { + const metaMetricsController = getMetaMetricsController(); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent( { event: 'Fake Event', @@ -442,18 +437,11 @@ describe('MetaMetricsController', function () { test: 1, }, }, - { isOptIn: true, metaMetricsId: 'TESTID' }, + { matomoEvent: true }, ); - mock.verify(); - }); - - it('should track a legacy event', function () { - const mock = sinon.mock(segment); - const metaMetricsController = getMetaMetricsController(); - mock - .expects('track') - .once() - .withArgs({ + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, @@ -464,27 +452,24 @@ describe('MetaMetricsController', function () { }, messageId: Utils.generateRandomId(), timestamp: new Date(), - }); - metaMetricsController.submitEvent( - { - event: 'Fake Event', - category: 'Unit Test', - properties: { - test: 1, - }, }, - { matomoEvent: true }, + spy.mock.calls[0][1], ); - mock.verify(); }); it('should track a non legacy event', function () { - const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController(); - mock - .expects('track') - .once() - .withArgs({ + const spy = jest.spyOn(segment, 'track'); + metaMetricsController.submitEvent({ + event: 'Fake Event', + category: 'Unit Test', + properties: { + test: 1, + }, + }); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', properties: { test: 1, @@ -494,21 +479,14 @@ describe('MetaMetricsController', function () { userId: TEST_META_METRICS_ID, messageId: Utils.generateRandomId(), timestamp: new Date(), - }); - metaMetricsController.submitEvent({ - event: 'Fake Event', - category: 'Unit Test', - properties: { - test: 1, }, - }); - mock.verify(); + spy.mock.calls[0][1], + ); }); - it('should immediately flush queue if flushImmediately set to true', async function () { + it('should immediately flush queue if flushImmediately set to true', function () { const metaMetricsController = getMetaMetricsController(); - const flushStub = sinon.stub(segment, 'flush'); - const flushCalled = waitUntilCalled(flushStub, segment); + const spy = jest.spyOn(segment, 'flush'); metaMetricsController.submitEvent( { event: 'Fake Event', @@ -516,51 +494,48 @@ describe('MetaMetricsController', function () { }, { flushImmediately: true }, ); - assert.doesNotReject(flushCalled()); + expect(spy).not.toThrow(); }); - it('should throw if event or category not provided', function () { + it('should throw if event or category not provided', async function () { const metaMetricsController = getMetaMetricsController(); - assert.rejects( - () => metaMetricsController.submitEvent({ event: 'test' }), - /Must specify event and category\./u, - 'must specify category', - ); - assert.rejects( - () => metaMetricsController.submitEvent({ category: 'test' }), - /Must specify event and category\./u, - 'must specify event', - ); + await expect( + metaMetricsController.submitEvent({ event: 'test' }), + ).rejects.toThrow(/Must specify event and category\./u); + + await expect( + metaMetricsController.submitEvent({ category: 'test' }), + ).rejects.toThrow(/Must specify event and category\./u); }); - it('should throw if provided sensitiveProperties, when excludeMetaMetricsId is true', function () { + it('should throw if provided sensitiveProperties, when excludeMetaMetricsId is true', async function () { const metaMetricsController = getMetaMetricsController(); - assert.rejects( - () => - metaMetricsController.submitEvent( - { - event: 'Fake Event', - category: 'Unit Test', - sensitiveProperties: { foo: 'bar' }, - }, - { excludeMetaMetricsId: true }, - ), + await expect( + metaMetricsController.submitEvent( + { + event: 'Fake Event', + category: 'Unit Test', + sensitiveProperties: { foo: 'bar' }, + }, + { excludeMetaMetricsId: true }, + ), + ).rejects.toThrow( /sensitiveProperties was specified in an event payload that also set the excludeMetaMetricsId flag/u, ); }); it('should track sensitiveProperties in a separate, anonymous event', function () { const metaMetricsController = getMetaMetricsController(); - const spy = sinon.spy(segment, 'track'); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent({ event: 'Fake Event', category: 'Unit Test', sensitiveProperties: { foo: 'bar' }, }); - assert.ok(spy.calledTwice); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', anonymousId: METAMETRICS_ANONYMOUS_ID, context: DEFAULT_TEST_CONTEXT, @@ -570,17 +545,19 @@ describe('MetaMetricsController', function () { }, messageId: Utils.generateRandomId(), timestamp: new Date(), - }), + }, + spy.mock.calls[0][1], ); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, properties: DEFAULT_EVENT_PROPERTIES, messageId: Utils.generateRandomId(), timestamp: new Date(), - }), + }, + spy.mock.calls[1][1], ); }); }); @@ -588,15 +565,15 @@ describe('MetaMetricsController', function () { describe('Change Transaction XXX anonymous event namnes', function () { it('should change "Transaction Added" anonymous event names to "Transaction Added Anon"', function () { const metaMetricsController = getMetaMetricsController(); - const spy = sinon.spy(segment, 'track'); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent({ event: 'Transaction Added', category: 'Unit Test', sensitiveProperties: { foo: 'bar' }, }); - assert.ok(spy.calledTwice); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledWith( + { event: `Transaction Added Anon`, anonymousId: METAMETRICS_ANONYMOUS_ID, context: DEFAULT_TEST_CONTEXT, @@ -606,21 +583,22 @@ describe('MetaMetricsController', function () { }, messageId: Utils.generateRandomId(), timestamp: new Date(), - }), + }, + spy.mock.calls[0][1], ); }); it('should change "Transaction Submitted" anonymous event names to "Transaction Added Anon"', function () { const metaMetricsController = getMetaMetricsController(); - const spy = sinon.spy(segment, 'track'); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent({ event: 'Transaction Submitted', category: 'Unit Test', sensitiveProperties: { foo: 'bar' }, }); - assert.ok(spy.calledTwice); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledWith( + { event: `Transaction Submitted Anon`, anonymousId: METAMETRICS_ANONYMOUS_ID, context: DEFAULT_TEST_CONTEXT, @@ -630,21 +608,22 @@ describe('MetaMetricsController', function () { }, messageId: Utils.generateRandomId(), timestamp: new Date(), - }), + }, + spy.mock.calls[0][1], ); }); it('should change "Transaction Finalized" anonymous event names to "Transaction Added Anon"', function () { const metaMetricsController = getMetaMetricsController(); - const spy = sinon.spy(segment, 'track'); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent({ event: 'Transaction Finalized', category: 'Unit Test', sensitiveProperties: { foo: 'bar' }, }); - assert.ok(spy.calledTwice); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledWith( + { event: `Transaction Finalized Anon`, anonymousId: METAMETRICS_ANONYMOUS_ID, context: DEFAULT_TEST_CONTEXT, @@ -654,19 +633,25 @@ describe('MetaMetricsController', function () { }, messageId: Utils.generateRandomId(), timestamp: new Date(), - }), + }, + spy.mock.calls[0][1], ); }); }); describe('trackPage', function () { it('should track a page view', function () { - const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController(); - mock - .expects('page') - .once() - .withArgs({ + const spy = jest.spyOn(segment, 'page'); + metaMetricsController.trackPage({ + name: 'home', + params: null, + environmentType: ENVIRONMENT_TYPE_BACKGROUND, + page: METAMETRICS_BACKGROUND_PAGE_OBJECT, + }); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { name: 'home', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, @@ -676,42 +661,44 @@ describe('MetaMetricsController', function () { }, messageId: Utils.generateRandomId(), timestamp: new Date(), - }); - metaMetricsController.trackPage({ - name: 'home', - params: null, - environmentType: ENVIRONMENT_TYPE_BACKGROUND, - page: METAMETRICS_BACKGROUND_PAGE_OBJECT, - }); - mock.verify(); + }, + spy.mock.calls[0][1], + ); }); it('should not track a page view if user is not participating in metametrics', function () { - const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: false, }); - mock.expects('page').never(); + const spy = jest.spyOn(segment, 'page'); metaMetricsController.trackPage({ name: 'home', params: null, environmentType: ENVIRONMENT_TYPE_BACKGROUND, page: METAMETRICS_BACKGROUND_PAGE_OBJECT, }); - mock.verify(); + expect(spy).toHaveBeenCalledTimes(0); }); it('should track a page view if isOptInPath is true and user not yet opted in', function () { - const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController({ preferencesStore: getMockPreferencesStore({ participateInMetaMetrics: null, }), }); - mock - .expects('page') - .once() - .withArgs({ + const spy = jest.spyOn(segment, 'page'); + metaMetricsController.trackPage( + { + name: 'home', + params: null, + environmentType: ENVIRONMENT_TYPE_BACKGROUND, + page: METAMETRICS_BACKGROUND_PAGE_OBJECT, + }, + { isOptInPath: true }, + ); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { name: 'home', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, @@ -721,40 +708,18 @@ describe('MetaMetricsController', function () { }, messageId: Utils.generateRandomId(), timestamp: new Date(), - }); - metaMetricsController.trackPage( - { - name: 'home', - params: null, - environmentType: ENVIRONMENT_TYPE_BACKGROUND, - page: METAMETRICS_BACKGROUND_PAGE_OBJECT, }, - { isOptInPath: true }, + spy.mock.calls[0][1], ); - mock.verify(); }); it('multiple trackPage call with same actionId should result in same messageId being sent to segment', function () { - const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController({ preferencesStore: getMockPreferencesStore({ participateInMetaMetrics: null, }), }); - mock - .expects('page') - .twice() - .withArgs({ - name: 'home', - userId: TEST_META_METRICS_ID, - context: DEFAULT_TEST_CONTEXT, - properties: { - params: null, - ...DEFAULT_PAGE_PROPERTIES, - }, - messageId: DUMMY_ACTION_ID, - timestamp: new Date(), - }); + const spy = jest.spyOn(segment, 'page'); metaMetricsController.trackPage( { name: 'home', @@ -775,23 +740,37 @@ describe('MetaMetricsController', function () { }, { isOptInPath: true }, ); - mock.verify(); + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledWith( + { + name: 'home', + userId: TEST_META_METRICS_ID, + context: DEFAULT_TEST_CONTEXT, + properties: { + params: null, + ...DEFAULT_PAGE_PROPERTIES, + }, + messageId: DUMMY_ACTION_ID, + timestamp: new Date(), + }, + spy.mock.calls[0][1], + ); }); }); describe('deterministic messageId', function () { it('should use the actionId as messageId when provided', function () { const metaMetricsController = getMetaMetricsController(); - const spy = sinon.spy(segment, 'track'); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent({ event: 'Fake Event', category: 'Unit Test', properties: { foo: 'bar' }, actionId: '0x001', }); - assert.ok(spy.calledOnce); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, @@ -801,23 +780,23 @@ describe('MetaMetricsController', function () { }, messageId: '0x001', timestamp: new Date(), - }), + }, + spy.mock.calls[0][1], ); }); it('should append 0x000 to the actionId of anonymized event when tracking sensitiveProperties', function () { const metaMetricsController = getMetaMetricsController(); - const spy = sinon.spy(segment, 'track'); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent({ event: 'Fake Event', category: 'Unit Test', sensitiveProperties: { foo: 'bar' }, actionId: '0x001', }); - assert.ok(spy.calledTwice); - - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', anonymousId: METAMETRICS_ANONYMOUS_ID, context: DEFAULT_TEST_CONTEXT, @@ -827,10 +806,11 @@ describe('MetaMetricsController', function () { }, messageId: '0x001-0x000', timestamp: new Date(), - }), + }, + spy.mock.calls[0][1], ); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, @@ -839,22 +819,23 @@ describe('MetaMetricsController', function () { }, messageId: '0x001', timestamp: new Date(), - }), + }, + spy.mock.calls[1][1], ); }); it('should use the uniqueIdentifier as messageId when provided', function () { const metaMetricsController = getMetaMetricsController(); - const spy = sinon.spy(segment, 'track'); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent({ event: 'Fake Event', category: 'Unit Test', properties: { foo: 'bar' }, uniqueIdentifier: 'transaction-submitted-0000', }); - assert.ok(spy.calledOnce); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, @@ -864,22 +845,23 @@ describe('MetaMetricsController', function () { }, messageId: 'transaction-submitted-0000', timestamp: new Date(), - }), + }, + spy.mock.calls[0][1], ); }); it('should append 0x000 to the uniqueIdentifier of anonymized event when tracking sensitiveProperties', function () { const metaMetricsController = getMetaMetricsController(); - const spy = sinon.spy(segment, 'track'); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent({ event: 'Fake Event', category: 'Unit Test', sensitiveProperties: { foo: 'bar' }, uniqueIdentifier: 'transaction-submitted-0000', }); - assert.ok(spy.calledTwice); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', anonymousId: METAMETRICS_ANONYMOUS_ID, context: DEFAULT_TEST_CONTEXT, @@ -889,10 +871,11 @@ describe('MetaMetricsController', function () { }, messageId: 'transaction-submitted-0000-0x000', timestamp: new Date(), - }), + }, + spy.mock.calls[0][1], ); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, @@ -901,13 +884,14 @@ describe('MetaMetricsController', function () { }, messageId: 'transaction-submitted-0000', timestamp: new Date(), - }), + }, + spy.mock.calls[1][1], ); }); it('should combine the uniqueIdentifier and actionId as messageId when both provided', function () { const metaMetricsController = getMetaMetricsController(); - const spy = sinon.spy(segment, 'track'); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent({ event: 'Fake Event', category: 'Unit Test', @@ -915,9 +899,9 @@ describe('MetaMetricsController', function () { actionId: '0x001', uniqueIdentifier: 'transaction-submitted-0000', }); - assert.ok(spy.calledOnce); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, @@ -927,13 +911,14 @@ describe('MetaMetricsController', function () { }, messageId: 'transaction-submitted-0000-0x001', timestamp: new Date(), - }), + }, + spy.mock.calls[0][1], ); }); it('should append 0x000 to the combined uniqueIdentifier and actionId of anonymized event when tracking sensitiveProperties', function () { const metaMetricsController = getMetaMetricsController(); - const spy = sinon.spy(segment, 'track'); + const spy = jest.spyOn(segment, 'track'); metaMetricsController.submitEvent({ event: 'Fake Event', category: 'Unit Test', @@ -941,9 +926,9 @@ describe('MetaMetricsController', function () { actionId: '0x001', uniqueIdentifier: 'transaction-submitted-0000', }); - assert.ok(spy.calledTwice); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', anonymousId: METAMETRICS_ANONYMOUS_ID, context: DEFAULT_TEST_CONTEXT, @@ -953,10 +938,11 @@ describe('MetaMetricsController', function () { }, messageId: 'transaction-submitted-0000-0x001-0x000', timestamp: new Date(), - }), + }, + spy.mock.calls[0][1], ); - assert.ok( - spy.calledWith({ + expect(spy).toHaveBeenCalledWith( + { event: 'Fake Event', userId: TEST_META_METRICS_ID, context: DEFAULT_TEST_CONTEXT, @@ -965,7 +951,8 @@ describe('MetaMetricsController', function () { }, messageId: 'transaction-submitted-0000-0x001', timestamp: new Date(), - }), + }, + spy.mock.calls[1][1], ); }); }); @@ -1093,7 +1080,7 @@ describe('MetaMetricsController', function () { }, }); - assert.deepEqual(traits, { + expect(traits).toStrictEqual({ [MetaMetricsUserTrait.AddressBookEntries]: 3, [MetaMetricsUserTrait.InstallDateExt]: '', [MetaMetricsUserTrait.LedgerConnectionType]: 'web-hid', @@ -1182,7 +1169,7 @@ describe('MetaMetricsController', function () { useNativeCurrencyAsPrimaryCurrency: false, }); - assert.deepEqual(updatedTraits, { + expect(updatedTraits).toStrictEqual({ [MetaMetricsUserTrait.AddressBookEntries]: 4, [MetaMetricsUserTrait.NumberOfAccounts]: 3, [MetaMetricsUserTrait.NumberOfTokens]: 1, @@ -1242,8 +1229,7 @@ describe('MetaMetricsController', function () { useTokenDetection: true, useNativeCurrencyAsPrimaryCurrency: true, }); - - assert.equal(updatedTraits, null); + expect(updatedTraits).toStrictEqual(null); }); }); @@ -1252,7 +1238,7 @@ describe('MetaMetricsController', function () { const metaMetricsController = getMetaMetricsController({}); metaMetricsController.trackPage({}, { isOptIn: true }); const { segmentApiCalls } = metaMetricsController.store.getState(); - assert(Object.keys(segmentApiCalls).length > 0); + expect(Object.keys(segmentApiCalls).length > 0).toStrictEqual(true); }); it('should remove event from store when callback is invoked', function () { @@ -1260,22 +1246,22 @@ describe('MetaMetricsController', function () { const stubFn = (_, cb) => { cb(); }; - sinon.stub(segmentInstance, 'track').callsFake(stubFn); - sinon.stub(segmentInstance, 'page').callsFake(stubFn); + jest.spyOn(segmentInstance, 'track').mockImplementation(stubFn); + jest.spyOn(segmentInstance, 'page').mockImplementation(stubFn); const metaMetricsController = getMetaMetricsController({ segmentInstance, }); metaMetricsController.trackPage({}, { isOptIn: true }); const { segmentApiCalls } = metaMetricsController.store.getState(); - assert(Object.keys(segmentApiCalls).length === 0); + expect(Object.keys(segmentApiCalls).length === 0).toStrictEqual(true); }); }); afterEach(function () { // flush the queues manually after each test segment.flush(); - clock.restore(); - sinon.restore(); + jest.useRealTimers(); + jest.restoreAllMocks(); }); }); diff --git a/jest.config.js b/jest.config.js index f02cc20ab6b5..1b51294301ae 100644 --- a/jest.config.js +++ b/jest.config.js @@ -58,6 +58,7 @@ module.exports = { '<rootDir>/app/scripts/controllers/push-platform-notifications/**/*.test.ts', '<rootDir>/app/scripts/controllers/user-storage/**/*.test.ts', '<rootDir>/app/scripts/controllers/metamask-notifications/**/*.test.ts', + '<rootDir>/app/scripts/controllers/metametrics.test.js', '<rootDir>/app/scripts/flask/**/*.test.js', '<rootDir>/app/scripts/lib/**/*.test.(js|ts)', '<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js', From 23a303d21e3f17fe8dd457eb51f3535a8a3bd885 Mon Sep 17 00:00:00 2001 From: Ethan Wessel <ejwessel@gmail.com> Date: Fri, 14 Jun 2024 17:11:13 -0700 Subject: [PATCH 56/61] fix: Confirmation bridge verify backend (#25047) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25047?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Signed-off-by: Ethan Wessel <ethan.wessel@consensys.net> Co-authored-by: Erik Marks <25517051+rekmarks@users.noreply.github.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com> Co-authored-by: Erik Marks <rekmarks@protonmail.com> --- .../tx-verification-middleware.test.ts | 255 ++++++++++++++++++ .../tx-verification-middleware.ts | 115 ++++++++ app/scripts/metamask-controller.js | 6 + lavamoat/browserify/beta/policy.json | 200 ++++++++------ lavamoat/browserify/flask/policy.json | 206 ++++++++------ lavamoat/browserify/main/policy.json | 206 ++++++++------ lavamoat/browserify/mmi/policy.json | 206 ++++++++------ package.json | 3 + shared/constants/app.ts | 2 + shared/constants/first-party-contracts.ts | 26 +- shared/constants/verification.ts | 28 ++ ui/hooks/useFirstPartyContractName.ts | 10 +- yarn.lock | 5 +- 13 files changed, 928 insertions(+), 340 deletions(-) create mode 100644 app/scripts/lib/tx-verification/tx-verification-middleware.test.ts create mode 100644 app/scripts/lib/tx-verification/tx-verification-middleware.ts create mode 100644 shared/constants/verification.ts diff --git a/app/scripts/lib/tx-verification/tx-verification-middleware.test.ts b/app/scripts/lib/tx-verification/tx-verification-middleware.test.ts new file mode 100644 index 000000000000..110a2dc3040e --- /dev/null +++ b/app/scripts/lib/tx-verification/tx-verification-middleware.test.ts @@ -0,0 +1,255 @@ +import { NetworkController } from '@metamask/network-controller'; +import { JsonRpcParams, jsonrpc2, Hex } from '@metamask/utils'; +import { + EXPERIENCES_TYPE, + FIRST_PARTY_CONTRACT_NAMES, +} from '../../../../shared/constants/first-party-contracts'; +import { + createTxVerificationMiddleware, + TxParams, +} from './tx-verification-middleware'; + +const getMockNetworkController = (chainId: `0x${string}` = '0x1') => + ({ state: { providerConfig: { chainId } } } as unknown as NetworkController); + +const mockTrustedSigners: Partial<Record<EXPERIENCES_TYPE, Hex>> = { + [EXPERIENCES_TYPE.METAMASK_BRIDGE]: + '0xe672B534ccf9876a7554a1dD1685a2a5C2Cc8e8C', +}; + +const jsonRpcTemplate = { jsonrpc: jsonrpc2, id: 1 }; + +const getMiddlewareParams = (method: string, params: JsonRpcParams = []) => { + const req = { ...jsonRpcTemplate, method, params }; + const res = { ...jsonRpcTemplate, result: null }; + const next = jest.fn(); + const end = jest.fn(); + return { req, res, next, end }; +}; + +const getBridgeTxParams = (txParams: Partial<TxParams> = {}): [TxParams] => { + return [ + { + data: '0x1', + from: '0x1', + to: '0x1', + value: '0x1', + ...txParams, + }, + ]; +}; + +describe('tx verification middleware', () => { + it('ignores methods other than eth_sendTransaction', () => { + const middleware = createTxVerificationMiddleware( + getMockNetworkController(), + mockTrustedSigners, + ); + const { req, res, next, end } = getMiddlewareParams('foo'); + middleware(req, res, next, end); + + expect(next).toHaveBeenCalledTimes(1); + expect(end).not.toHaveBeenCalled(); + }); + + // @ts-expect-error Our test types are broken + it.each([ + ['null', null], + ['string', 'foo'], + ['plain object', {}], + ['empty array', []], + ['array with non-object', ['foo']], + ['non-string "data"', [{ data: 1 }]], + ['non-string "from"', [{ data: 'data', from: 1 }]], + ['non-string "to"', [{ data: 'data', from: 'from', to: 1 }]], + [ + 'non-string "value"', + [{ data: 'data', from: 'from', to: 'to', value: 1 }], + ], + [ + 'non-string "chainId"', + [{ data: 'data', from: 'from', to: 'to', value: 'value', chainId: 1 }], + ], + [ + 'non-"0x"-prefixed "chainId"', + [{ data: 'data', from: 'from', to: 'to', value: 'value', chainId: '1' }], + ], + ])( + 'ignores invalid params: %s', + (_: string, invalidParams: JsonRpcParams) => { + const middleware = createTxVerificationMiddleware( + getMockNetworkController(), + mockTrustedSigners, + ); + + const { req, res, next, end } = getMiddlewareParams( + 'eth_sendTransaction', + invalidParams, + ); + middleware(req, res, next, end); + + expect(next).toHaveBeenCalledTimes(1); + expect(end).not.toHaveBeenCalled(); + }, + ); + + // @ts-expect-error Our test types are broken + it.each(Object.keys(FIRST_PARTY_CONTRACT_NAMES['MetaMask Bridge']))( + 'ignores transactions that are not addressed to the bridge contract for chain %s', + (chainId: `0x${string}`) => { + const middleware = createTxVerificationMiddleware( + getMockNetworkController(), + mockTrustedSigners, + ); + + const { req, res, next, end } = getMiddlewareParams( + 'eth_sendTransaction', + getBridgeTxParams({ chainId, to: '0x1' }), + ); + middleware(req, res, next, end); + + expect(next).toHaveBeenCalledTimes(1); + expect(end).not.toHaveBeenCalled(); + }, + ); + + // @ts-expect-error Our test types are broken + it.each(['0x11111', '0x111', '0x222222'])( + 'ignores transactions that do not have a bridge contract deployed for chain %s', + (chainId: `0x${string}`) => { + const middleware = createTxVerificationMiddleware( + getMockNetworkController(), + mockTrustedSigners, + ); + + const { req, res, next, end } = getMiddlewareParams( + 'eth_sendTransaction', + getBridgeTxParams({ chainId, to: '0x1' }), + ); + middleware(req, res, next, end); + + expect(next).toHaveBeenCalledTimes(1); + expect(end).not.toHaveBeenCalled(); + }, + ); + + it('calls next() if reverse address mapping look up is undefined', () => { + const middleware = createTxVerificationMiddleware( + getMockNetworkController(), + mockTrustedSigners, + ); + + const { req, res, next, end } = getMiddlewareParams( + 'eth_sendTransaction', + getBridgeTxParams({ ...getFixtures().mapUndefined }), + ); + middleware(req, res, next, end); + + expect(next).toHaveBeenCalledTimes(1); + expect(end).not.toHaveBeenCalled(); + }); + + it('calls next() if chainId for `to` address does not match', () => { + const middleware = createTxVerificationMiddleware( + getMockNetworkController(), + mockTrustedSigners, + ); + + const { req, res, next, end } = getMiddlewareParams( + 'eth_sendTransaction', + getBridgeTxParams({ ...getFixtures().mapIncorrectChain }), + ); + middleware(req, res, next, end); + + expect(next).toHaveBeenCalledTimes(1); + expect(end).not.toHaveBeenCalled(); + }); + + it('calls next() if experience type for `to` address is not an experience to verify', () => { + const middleware = createTxVerificationMiddleware( + getMockNetworkController(), + mockTrustedSigners, + ); + + const { req, res, next, end } = getMiddlewareParams( + 'eth_sendTransaction', + getBridgeTxParams({ ...getFixtures().mapIncorrectExp }), + ); + middleware(req, res, next, end); + + expect(next).toHaveBeenCalledTimes(1); + expect(end).not.toHaveBeenCalled(); + }); + + it('passes through a valid bridge transaction', () => { + const middleware = createTxVerificationMiddleware( + getMockNetworkController(), + mockTrustedSigners, + ); + + const { req, res, next, end } = getMiddlewareParams( + 'eth_sendTransaction', + getBridgeTxParams({ ...getFixtures().valid }), + ); + middleware(req, res, next, end); + + expect(next).toHaveBeenCalledTimes(1); + expect(end).not.toHaveBeenCalled(); + }); + + it('rejects modified bridge transactions', () => { + const middleware = createTxVerificationMiddleware( + getMockNetworkController(), + mockTrustedSigners, + ); + + const { req, res, next, end } = getMiddlewareParams( + 'eth_sendTransaction', + getBridgeTxParams({ ...getFixtures().invalid }), + ); + middleware(req, res, next, end); + + expect(next).not.toHaveBeenCalled(); + expect(end).toHaveBeenCalledTimes(1); + }); +}); + +/** + * Returns bridge transaction validation fixtures. + * + * @returns The fixtures. + */ +function getFixtures() { + return { + mapIncorrectExp: { + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000f736f636b6574416461707465725632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002800000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000003a23f943181408eac424116af7b7790c94cb97a5000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000466ebb82ac1000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000009f295cd5f000000000000000000000000000e6b738da243e8fa2a0ed5915645789add5de515200000000000000000000000000000000000000000000000000000000000001280000019fd025dec0000000000000000000000000e672b534ccf9876a7554a1dd1685a2a5c2cc8e8c000000000000000000000000b8901acb165ed027e32754e0ffe830802919727f000000000000000000000000710bda329b2a6224e4b44833de30f38e7f81d564000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000466ebb82ac1000000000000000000000000000000000000000000000000000004614942c423e000000000000000000000000000000000000000000000000000000886c98b760000000000000000000000000000000000000000000000000000000019012a41ba800000000000000000000000000000000000000000000000000000000000000c40000000000000000000000000000000000000000000000005dedaf7e04c3f5c842c30ed9a4a19baceb915cdd3e865f0dad99ffca277743a20bac00e0f366e7265f1fcad502791ff49e9c5c98e1841a090df23ce5555051da1c', + from: '0xe672b534ccf9876a7554a1dd1685a2a5c2cc8e8c', + to: '0xc7bE520a13dC023A1b34C03F4Abdab8A43653F7B', + value: '0x470de4df820000', + }, + mapIncorrectChain: { + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000f736f636b6574416461707465725632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002800000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000003a23f943181408eac424116af7b7790c94cb97a5000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000466ebb82ac1000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000009f295cd5f000000000000000000000000000e6b738da243e8fa2a0ed5915645789add5de515200000000000000000000000000000000000000000000000000000000000001280000019fd025dec0000000000000000000000000e672b534ccf9876a7554a1dd1685a2a5c2cc8e8c000000000000000000000000b8901acb165ed027e32754e0ffe830802919727f000000000000000000000000710bda329b2a6224e4b44833de30f38e7f81d564000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000466ebb82ac1000000000000000000000000000000000000000000000000000004614942c423e000000000000000000000000000000000000000000000000000000886c98b760000000000000000000000000000000000000000000000000000000019012a41ba800000000000000000000000000000000000000000000000000000000000000c40000000000000000000000000000000000000000000000005dedaf7e04c3f5c842c30ed9a4a19baceb915cdd3e865f0dad99ffca277743a20bac00e0f366e7265f1fcad502791ff49e9c5c98e1841a090df23ce5555051da1c', + from: '0xe672b534ccf9876a7554a1dd1685a2a5c2cc8e8c', + to: `0xaEc23140408534b378bf5832defc426dF8604B59`, + value: '0x470de4df820000', + }, + mapUndefined: { + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000f736f636b6574416461707465725632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002800000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000003a23f943181408eac424116af7b7790c94cb97a5000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000466ebb82ac1000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000009f295cd5f000000000000000000000000000e6b738da243e8fa2a0ed5915645789add5de515200000000000000000000000000000000000000000000000000000000000001280000019fd025dec0000000000000000000000000e672b534ccf9876a7554a1dd1685a2a5c2cc8e8c000000000000000000000000b8901acb165ed027e32754e0ffe830802919727f000000000000000000000000710bda329b2a6224e4b44833de30f38e7f81d564000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000466ebb82ac1000000000000000000000000000000000000000000000000000004614942c423e000000000000000000000000000000000000000000000000000000886c98b760000000000000000000000000000000000000000000000000000000019012a41ba800000000000000000000000000000000000000000000000000000000000000c40000000000000000000000000000000000000000000000005dedaf7e04c3f5c842c30ed9a4a19baceb915cdd3e865f0dad99ffca277743a20bac00e0f366e7265f1fcad502791ff49e9c5c98e1841a090df23ce5555051da1c', + from: '0xe672b534ccf9876a7554a1dd1685a2a5c2cc8e8c', + to: '0x0439e60F02a8900a951603950d8D4527f400C3f9', + value: '0x470de4df820000', + }, + valid: { + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000f736f636b6574416461707465725632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002800000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000003a23f943181408eac424116af7b7790c94cb97a5000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000466ebb82ac1000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000009f295cd5f000000000000000000000000000e6b738da243e8fa2a0ed5915645789add5de515200000000000000000000000000000000000000000000000000000000000001280000019fd025dec0000000000000000000000000e672b534ccf9876a7554a1dd1685a2a5c2cc8e8c000000000000000000000000b8901acb165ed027e32754e0ffe830802919727f000000000000000000000000710bda329b2a6224e4b44833de30f38e7f81d564000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000466ebb82ac1000000000000000000000000000000000000000000000000000004614942c423e000000000000000000000000000000000000000000000000000000886c98b760000000000000000000000000000000000000000000000000000000019012a41ba800000000000000000000000000000000000000000000000000000000000000c40000000000000000000000000000000000000000000000005dedaf7e04c3f5c842c30ed9a4a19baceb915cdd3e865f0dad99ffca277743a20bac00e0f366e7265f1fcad502791ff49e9c5c98e1841a090df23ce5555051da1c', + from: '0xe672b534ccf9876a7554a1dd1685a2a5c2cc8e8c', + to: FIRST_PARTY_CONTRACT_NAMES['MetaMask Bridge']['0x1'], + value: '0x470de4df820000', + }, + invalid: { + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000466ebb82ac1000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000009f295cd5f000000000000000000000000000c8c0e780960f954c3426a32b6ab453248d632b59000000000000000000000000000000000000000000000000000000000000006c5a39b10a5d458d62482fa1e7e672b534ccf9876a7554a1dd1685a2a5c2cc8e8c0000a4b10002a9de92aa00576661f103ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd00dfeeddeadbeef8932eb23bad9bddb5cf81426f78279a53c6c3b710000000000000000000000000000000000000000', + from: '0xe672b534ccf9876a7554a1dd1685a2a5c2cc8e8c', + to: FIRST_PARTY_CONTRACT_NAMES['MetaMask Bridge']['0x1'], + value: '0x470de4df820000', + }, + } as const; +} diff --git a/app/scripts/lib/tx-verification/tx-verification-middleware.ts b/app/scripts/lib/tx-verification/tx-verification-middleware.ts new file mode 100644 index 000000000000..30782a98721b --- /dev/null +++ b/app/scripts/lib/tx-verification/tx-verification-middleware.ts @@ -0,0 +1,115 @@ +import { hashMessage } from '@ethersproject/hash'; +import { verifyMessage } from '@ethersproject/wallet'; +import type { NetworkController } from '@metamask/network-controller'; +import { rpcErrors } from '@metamask/rpc-errors'; +import { + Json, + JsonRpcParams, + hasProperty, + isObject, + Hex, +} from '@metamask/utils'; +import { + JsonRpcRequest, + JsonRpcResponse, + JsonRpcEngineEndCallback, + JsonRpcEngineNextCallback, +} from 'json-rpc-engine'; +import { + EXPERIENCES_TO_VERIFY, + getExperience, + TX_SIG_LEN, + TRUSTED_SIGNERS, +} from '../../../../shared/constants/verification'; +import { MESSAGE_TYPE } from '../../../../shared/constants/app'; + +export type TxParams = { + chainId?: `0x${string}`; + data: string; + from: string; + to: string; + value: string; +}; + +/** + * Creates a middleware function that verifies bridge transactions from the + * Portfolio. + * + * @param networkController - The network controller instance. + * @param trustedSigners + * @returns The middleware function. + */ +export function createTxVerificationMiddleware( + networkController: NetworkController, + trustedSigners = TRUSTED_SIGNERS, +) { + return function txVerificationMiddleware( + req: JsonRpcRequest<JsonRpcParams>, + _res: JsonRpcResponse<Json>, + next: JsonRpcEngineNextCallback, + end: JsonRpcEngineEndCallback, + ) { + if ( + req.method !== MESSAGE_TYPE.ETH_SEND_TRANSACTION || + !Array.isArray(req.params) || + !isValidParams(req.params) + ) { + return next(); + } + + // the tx object is the first element + const params = req.params[0]; + const chainId = + typeof params.chainId === 'string' + ? (params.chainId.toLowerCase() as Hex) + : networkController.state.providerConfig.chainId; + + const experienceType = getExperience( + params.to.toLowerCase() as Hex, + chainId, + ); + // if undefined then no address matched - skip OR if experience is not one we want to verify against - skip + if (!experienceType || !EXPERIENCES_TO_VERIFY.includes(experienceType)) { + return next(); + } + + const signature = `0x${params.data.slice(-TX_SIG_LEN)}`; + const addressToVerify = verifyMessage(hashParams(params), signature); + if (addressToVerify !== trustedSigners[experienceType]) { + return end(rpcErrors.invalidParams('Invalid transaction signature.')); + } + return next(); + }; +} + +function hashParams(params: TxParams): string { + const paramsToVerify = { + to: hashMessage(params.to.toLowerCase()), + from: hashMessage(params.from.toLowerCase()), + data: hashMessage( + params.data.toLowerCase().slice(0, params.data.length - TX_SIG_LEN), + ), + value: hashMessage(params.value.toLowerCase()), + }; + return hashMessage(JSON.stringify(paramsToVerify)); +} + +/** + * Checks if the params of a JSON-RPC request are valid `eth_sendTransaction` + * params. + * + * @param params - The params to validate. + * @returns Whether the params are valid. + */ +function isValidParams(params: Json[]): params is [TxParams] { + return ( + isObject(params[0]) && + typeof params[0].data === 'string' && + typeof params[0].from === 'string' && + typeof params[0].to === 'string' && + typeof params[0].value === 'string' && + (!hasProperty(params[0], 'chainId') || + (typeof params[0].chainId === 'string' && + params[0].chainId.startsWith('0x'))) + ); +} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index cc9e91e9e889..87cf408cb0e1 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -218,6 +218,7 @@ import { getSmartTransactionsOptInStatus, getCurrentChainSupportsSmartTransactions, } from '../../shared/modules/selectors'; +import { BaseUrl } from '../../shared/constants/urls'; import { ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) handleMMITransactionUpdate, @@ -328,6 +329,7 @@ import AuthenticationController from './controllers/authentication/authenticatio import UserStorageController from './controllers/user-storage/user-storage-controller'; import { PushPlatformNotificationsController } from './controllers/push-platform-notifications/push-platform-notifications'; import { MetamaskNotificationsController } from './controllers/metamask-notifications/metamask-notifications'; +import { createTxVerificationMiddleware } from './lib/tx-verification/tx-verification-middleware'; import { updateSecurityAlertResponse } from './lib/ppom/ppom-util'; import createEvmMethodsToNonEvmAccountReqFilterMiddleware from './lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware'; import { isEthAddress } from './lib/multichain/address'; @@ -5110,6 +5112,10 @@ export default class MetamaskController extends EventEmitter { engine.push(createLoggerMiddleware({ origin })); engine.push(this.permissionLogController.createMiddleware()); + if (origin === BaseUrl.Portfolio) { + engine.push(createTxVerificationMiddleware(this.networkController)); + } + ///: BEGIN:ONLY_INCLUDE_IF(blockaid) engine.push( createPPOMMiddleware( diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 2fe1806d1e1c..07e649936d21 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -227,12 +227,12 @@ "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/abi>@ethersproject/bytes": true, "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/keccak256": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true + "@ethersproject/bignumber": true, + "@ethersproject/hash": true } }, "@ethersproject/abi>@ethersproject/address": { @@ -254,18 +254,6 @@ "@ethersproject/bignumber": true } }, - "@ethersproject/abi>@ethersproject/hash": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/providers>@ethersproject/base64": true - } - }, "@ethersproject/abi>@ethersproject/keccak256": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, @@ -307,9 +295,36 @@ "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, - "@ethersproject/hdnode>@ethersproject/abstract-signer": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, "@ethersproject/hdnode>@ethersproject/transactions": true, - "@metamask/test-bundler>@ethersproject/abstract-provider": true + "@ethersproject/wallet>@ethersproject/abstract-provider": true + } + }, + "@ethersproject/hash": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/bignumber": true, + "@ethersproject/hash>@ethersproject/base64": true + } + }, + "@ethersproject/hash>@ethersproject/abstract-signer": { + "packages": { + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true + } + }, + "@ethersproject/hash>@ethersproject/base64": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true } }, "@ethersproject/hdnode": { @@ -327,12 +342,6 @@ "@ethersproject/hdnode>@ethersproject/wordlists": true } }, - "@ethersproject/hdnode>@ethersproject/abstract-signer": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true - } - }, "@ethersproject/hdnode>@ethersproject/basex": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, @@ -376,10 +385,10 @@ "@ethersproject/hdnode>@ethersproject/wordlists": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/hash": true } }, "@ethersproject/providers": { @@ -396,39 +405,26 @@ "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/abi>@ethersproject/bytes": true, "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, - "@ethersproject/hdnode>@ethersproject/abstract-signer": true, + "@ethersproject/hash": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, + "@ethersproject/hash>@ethersproject/base64": true, "@ethersproject/hdnode>@ethersproject/basex": true, "@ethersproject/hdnode>@ethersproject/sha2": true, "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/providers>@ethersproject/base64": true, - "@ethersproject/providers>@ethersproject/random": true, "@ethersproject/providers>@ethersproject/web": true, "@ethersproject/providers>bech32": true, - "@metamask/test-bundler>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/random": true, "@metamask/test-bundler>@ethersproject/networks": true } }, - "@ethersproject/providers>@ethersproject/base64": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true - } - }, "@ethersproject/providers>@ethersproject/random": { "globals": { "crypto.getRandomValues": true - }, - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/logger": true } }, "@ethersproject/providers>@ethersproject/rlp": { @@ -448,7 +444,59 @@ "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/providers>@ethersproject/base64": true + "@ethersproject/hash>@ethersproject/base64": true + } + }, + "@ethersproject/wallet": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/hash": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, + "@ethersproject/hdnode": true, + "@ethersproject/hdnode>@ethersproject/signing-key": true, + "@ethersproject/hdnode>@ethersproject/transactions": true, + "@ethersproject/wallet>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/json-wallets": true, + "@ethersproject/wallet>@ethersproject/random": true + } + }, + "@ethersproject/wallet>@ethersproject/abstract-provider": { + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/bignumber": true + } + }, + "@ethersproject/wallet>@ethersproject/json-wallets": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/hdnode": true, + "@ethersproject/hdnode>@ethersproject/pbkdf2": true, + "@ethersproject/hdnode>@ethersproject/transactions": true, + "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": true, + "@ethersproject/wallet>@ethersproject/random": true, + "ethereumjs-util>ethereum-cryptography>scrypt-js": true + } + }, + "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": { + "globals": { + "define": true + } + }, + "@ethersproject/wallet>@ethersproject/random": { + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/logger": true } }, "@keystonehq/bc-ur-registry-eth": { @@ -826,7 +874,7 @@ "packages": { "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, - "@metamask/providers>@metamask/rpc-errors": true + "@metamask/rpc-errors": true } }, "@metamask/approval-controller>@metamask/base-controller": { @@ -870,7 +918,7 @@ "@metamask/controller-utils": true, "@metamask/eth-query": true, "@metamask/metamask-eth-abis": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "bn.js": true, "lodash": true, @@ -1043,7 +1091,7 @@ }, "@metamask/eth-json-rpc-filters>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1058,7 +1106,7 @@ "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true, "@metamask/eth-json-rpc-middleware>safe-stable-stringify": true, "@metamask/eth-sig-util": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "pify": true, "sass-loader>klona": true @@ -1072,14 +1120,14 @@ }, "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } }, "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1749,7 +1797,7 @@ "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/json-rpc-engine": true, "@metamask/network-controller>@metamask/swappable-obj-proxy": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "browserify>assert": true, "uuid": true @@ -1788,14 +1836,14 @@ "packages": { "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "node-fetch": true } }, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1808,7 +1856,7 @@ }, "@metamask/network-controller>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1847,7 +1895,7 @@ "@metamask/permission-controller>@metamask/controller-utils": true, "@metamask/permission-controller>@metamask/json-rpc-engine": true, "@metamask/permission-controller>nanoid": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "deep-freeze-strict": true, "immer": true @@ -1881,7 +1929,7 @@ }, "@metamask/permission-controller>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1974,21 +2022,21 @@ "ethereumjs-util>ethereum-cryptography>hash.js": true } }, - "@metamask/providers>@metamask/rpc-errors": { - "packages": { - "@metamask/utils": true, - "eth-rpc-errors>fast-safe-stringify": true - } - }, "@metamask/queued-request-controller": { "packages": { "@metamask/base-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/selected-network-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true } }, + "@metamask/rpc-errors": { + "packages": { + "@metamask/utils": true, + "eth-rpc-errors>fast-safe-stringify": true + } + }, "@metamask/rpc-methods-flask>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2043,7 +2091,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/logging-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/signature-controller>@metamask/message-manager": true, "@metamask/utils": true, @@ -2197,7 +2245,7 @@ "@metamask/eth-query": true, "@metamask/metamask-eth-abis": true, "@metamask/network-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@ethereumjs/tx": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@ethereumjs/util": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@metamask/base-controller": true, @@ -2404,7 +2452,7 @@ }, "@metamask/snaps-controllers>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -2426,7 +2474,7 @@ }, "@metamask/snaps-rpc-methods": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-rpc-methods>@metamask/permission-controller": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, @@ -2443,7 +2491,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": true, "@metamask/utils": true, @@ -2461,7 +2509,7 @@ "fetch": true }, "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-sdk>fast-xml-parser": true, "@metamask/utils": true, "superstruct": true @@ -2501,7 +2549,7 @@ "fetch": true }, "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, "@metamask/snaps-utils>@metamask/permission-controller": true, @@ -2526,7 +2574,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-utils>@metamask/permission-controller>nanoid": true, "@metamask/utils": true, @@ -2568,14 +2616,6 @@ "semver": true } }, - "@metamask/test-bundler>@ethersproject/abstract-provider": { - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bignumber": true - } - }, "@metamask/test-bundler>@ethersproject/networks": { "packages": { "@ethersproject/abi>@ethersproject/logger": true @@ -2599,7 +2639,7 @@ "@metamask/gas-fee-controller": true, "@metamask/metamask-eth-abis": true, "@metamask/network-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/transaction-controller>@metamask/base-controller": true, "@metamask/transaction-controller>@metamask/controller-utils": true, "@metamask/transaction-controller>@metamask/nonce-tracker": true, @@ -2674,7 +2714,7 @@ "@metamask/base-controller": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/transaction-controller": true, "@metamask/user-operation-controller>@metamask/controller-utils": true, "@metamask/utils": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 853f45039ae3..ef730087d03c 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -227,12 +227,12 @@ "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/abi>@ethersproject/bytes": true, "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/keccak256": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true + "@ethersproject/bignumber": true, + "@ethersproject/hash": true } }, "@ethersproject/abi>@ethersproject/address": { @@ -254,18 +254,6 @@ "@ethersproject/bignumber": true } }, - "@ethersproject/abi>@ethersproject/hash": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/providers>@ethersproject/base64": true - } - }, "@ethersproject/abi>@ethersproject/keccak256": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, @@ -307,9 +295,36 @@ "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, - "@ethersproject/hdnode>@ethersproject/abstract-signer": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, "@ethersproject/hdnode>@ethersproject/transactions": true, - "@metamask/test-bundler>@ethersproject/abstract-provider": true + "@ethersproject/wallet>@ethersproject/abstract-provider": true + } + }, + "@ethersproject/hash": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/bignumber": true, + "@ethersproject/hash>@ethersproject/base64": true + } + }, + "@ethersproject/hash>@ethersproject/abstract-signer": { + "packages": { + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true + } + }, + "@ethersproject/hash>@ethersproject/base64": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true } }, "@ethersproject/hdnode": { @@ -327,12 +342,6 @@ "@ethersproject/hdnode>@ethersproject/wordlists": true } }, - "@ethersproject/hdnode>@ethersproject/abstract-signer": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true - } - }, "@ethersproject/hdnode>@ethersproject/basex": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, @@ -376,10 +385,10 @@ "@ethersproject/hdnode>@ethersproject/wordlists": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/hash": true } }, "@ethersproject/providers": { @@ -396,39 +405,26 @@ "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/abi>@ethersproject/bytes": true, "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, - "@ethersproject/hdnode>@ethersproject/abstract-signer": true, + "@ethersproject/hash": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, + "@ethersproject/hash>@ethersproject/base64": true, "@ethersproject/hdnode>@ethersproject/basex": true, "@ethersproject/hdnode>@ethersproject/sha2": true, "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/providers>@ethersproject/base64": true, - "@ethersproject/providers>@ethersproject/random": true, "@ethersproject/providers>@ethersproject/web": true, "@ethersproject/providers>bech32": true, - "@metamask/test-bundler>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/random": true, "@metamask/test-bundler>@ethersproject/networks": true } }, - "@ethersproject/providers>@ethersproject/base64": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true - } - }, "@ethersproject/providers>@ethersproject/random": { "globals": { "crypto.getRandomValues": true - }, - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/logger": true } }, "@ethersproject/providers>@ethersproject/rlp": { @@ -448,7 +444,59 @@ "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/providers>@ethersproject/base64": true + "@ethersproject/hash>@ethersproject/base64": true + } + }, + "@ethersproject/wallet": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/hash": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, + "@ethersproject/hdnode": true, + "@ethersproject/hdnode>@ethersproject/signing-key": true, + "@ethersproject/hdnode>@ethersproject/transactions": true, + "@ethersproject/wallet>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/json-wallets": true, + "@ethersproject/wallet>@ethersproject/random": true + } + }, + "@ethersproject/wallet>@ethersproject/abstract-provider": { + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/bignumber": true + } + }, + "@ethersproject/wallet>@ethersproject/json-wallets": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/hdnode": true, + "@ethersproject/hdnode>@ethersproject/pbkdf2": true, + "@ethersproject/hdnode>@ethersproject/transactions": true, + "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": true, + "@ethersproject/wallet>@ethersproject/random": true, + "ethereumjs-util>ethereum-cryptography>scrypt-js": true + } + }, + "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": { + "globals": { + "define": true + } + }, + "@ethersproject/wallet>@ethersproject/random": { + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/logger": true } }, "@keystonehq/bc-ur-registry-eth": { @@ -826,7 +874,7 @@ "packages": { "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, - "@metamask/providers>@metamask/rpc-errors": true + "@metamask/rpc-errors": true } }, "@metamask/approval-controller>@metamask/base-controller": { @@ -870,7 +918,7 @@ "@metamask/controller-utils": true, "@metamask/eth-query": true, "@metamask/metamask-eth-abis": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "bn.js": true, "lodash": true, @@ -1043,7 +1091,7 @@ }, "@metamask/eth-json-rpc-filters>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1058,7 +1106,7 @@ "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true, "@metamask/eth-json-rpc-middleware>safe-stable-stringify": true, "@metamask/eth-sig-util": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "pify": true, "sass-loader>klona": true @@ -1072,14 +1120,14 @@ }, "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } }, "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1749,7 +1797,7 @@ "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/json-rpc-engine": true, "@metamask/network-controller>@metamask/swappable-obj-proxy": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "browserify>assert": true, "uuid": true @@ -1788,14 +1836,14 @@ "packages": { "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "node-fetch": true } }, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1808,7 +1856,7 @@ }, "@metamask/network-controller>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1874,7 +1922,7 @@ "@metamask/permission-controller>@metamask/controller-utils": true, "@metamask/permission-controller>@metamask/json-rpc-engine": true, "@metamask/permission-controller>nanoid": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "deep-freeze-strict": true, "immer": true @@ -1908,7 +1956,7 @@ }, "@metamask/permission-controller>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -2053,16 +2101,10 @@ "ethereumjs-util>ethereum-cryptography>hash.js": true } }, - "@metamask/providers>@metamask/rpc-errors": { - "packages": { - "@metamask/utils": true, - "eth-rpc-errors>fast-safe-stringify": true - } - }, "@metamask/queued-request-controller": { "packages": { "@metamask/base-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/selected-network-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true @@ -2074,10 +2116,16 @@ }, "packages": { "@metamask/base-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true } }, + "@metamask/rpc-errors": { + "packages": { + "@metamask/utils": true, + "eth-rpc-errors>fast-safe-stringify": true + } + }, "@metamask/rpc-methods-flask>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2132,7 +2180,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/logging-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/signature-controller>@metamask/message-manager": true, "@metamask/utils": true, @@ -2286,7 +2334,7 @@ "@metamask/eth-query": true, "@metamask/metamask-eth-abis": true, "@metamask/network-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@ethereumjs/tx": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@ethereumjs/util": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@metamask/base-controller": true, @@ -2501,7 +2549,7 @@ "@metamask/base-controller": true, "@metamask/object-multiplex": true, "@metamask/post-message-stream": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>@metamask/json-rpc-middleware-stream": true, "@metamask/snaps-controllers>@metamask/permission-controller": true, @@ -2528,7 +2576,7 @@ }, "@metamask/snaps-controllers>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -2550,7 +2598,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>nanoid": true, "@metamask/utils": true, @@ -2615,7 +2663,7 @@ }, "@metamask/snaps-rpc-methods": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-rpc-methods>@metamask/permission-controller": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, @@ -2632,7 +2680,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": true, "@metamask/utils": true, @@ -2650,7 +2698,7 @@ "fetch": true }, "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-sdk>fast-xml-parser": true, "@metamask/utils": true, "superstruct": true @@ -2690,7 +2738,7 @@ "fetch": true }, "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, "@metamask/snaps-utils>@metamask/permission-controller": true, @@ -2715,7 +2763,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-utils>@metamask/permission-controller>nanoid": true, "@metamask/utils": true, @@ -2765,14 +2813,6 @@ "semver": true } }, - "@metamask/test-bundler>@ethersproject/abstract-provider": { - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bignumber": true - } - }, "@metamask/test-bundler>@ethersproject/networks": { "packages": { "@ethersproject/abi>@ethersproject/logger": true @@ -2796,7 +2836,7 @@ "@metamask/gas-fee-controller": true, "@metamask/metamask-eth-abis": true, "@metamask/network-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/transaction-controller>@metamask/base-controller": true, "@metamask/transaction-controller>@metamask/controller-utils": true, "@metamask/transaction-controller>@metamask/nonce-tracker": true, @@ -2871,7 +2911,7 @@ "@metamask/base-controller": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/transaction-controller": true, "@metamask/user-operation-controller>@metamask/controller-utils": true, "@metamask/utils": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 853f45039ae3..ef730087d03c 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -227,12 +227,12 @@ "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/abi>@ethersproject/bytes": true, "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/keccak256": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true + "@ethersproject/bignumber": true, + "@ethersproject/hash": true } }, "@ethersproject/abi>@ethersproject/address": { @@ -254,18 +254,6 @@ "@ethersproject/bignumber": true } }, - "@ethersproject/abi>@ethersproject/hash": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/providers>@ethersproject/base64": true - } - }, "@ethersproject/abi>@ethersproject/keccak256": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, @@ -307,9 +295,36 @@ "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, - "@ethersproject/hdnode>@ethersproject/abstract-signer": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, "@ethersproject/hdnode>@ethersproject/transactions": true, - "@metamask/test-bundler>@ethersproject/abstract-provider": true + "@ethersproject/wallet>@ethersproject/abstract-provider": true + } + }, + "@ethersproject/hash": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/bignumber": true, + "@ethersproject/hash>@ethersproject/base64": true + } + }, + "@ethersproject/hash>@ethersproject/abstract-signer": { + "packages": { + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true + } + }, + "@ethersproject/hash>@ethersproject/base64": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true } }, "@ethersproject/hdnode": { @@ -327,12 +342,6 @@ "@ethersproject/hdnode>@ethersproject/wordlists": true } }, - "@ethersproject/hdnode>@ethersproject/abstract-signer": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true - } - }, "@ethersproject/hdnode>@ethersproject/basex": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, @@ -376,10 +385,10 @@ "@ethersproject/hdnode>@ethersproject/wordlists": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/hash": true } }, "@ethersproject/providers": { @@ -396,39 +405,26 @@ "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/abi>@ethersproject/bytes": true, "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, - "@ethersproject/hdnode>@ethersproject/abstract-signer": true, + "@ethersproject/hash": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, + "@ethersproject/hash>@ethersproject/base64": true, "@ethersproject/hdnode>@ethersproject/basex": true, "@ethersproject/hdnode>@ethersproject/sha2": true, "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/providers>@ethersproject/base64": true, - "@ethersproject/providers>@ethersproject/random": true, "@ethersproject/providers>@ethersproject/web": true, "@ethersproject/providers>bech32": true, - "@metamask/test-bundler>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/random": true, "@metamask/test-bundler>@ethersproject/networks": true } }, - "@ethersproject/providers>@ethersproject/base64": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true - } - }, "@ethersproject/providers>@ethersproject/random": { "globals": { "crypto.getRandomValues": true - }, - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/logger": true } }, "@ethersproject/providers>@ethersproject/rlp": { @@ -448,7 +444,59 @@ "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/providers>@ethersproject/base64": true + "@ethersproject/hash>@ethersproject/base64": true + } + }, + "@ethersproject/wallet": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/hash": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, + "@ethersproject/hdnode": true, + "@ethersproject/hdnode>@ethersproject/signing-key": true, + "@ethersproject/hdnode>@ethersproject/transactions": true, + "@ethersproject/wallet>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/json-wallets": true, + "@ethersproject/wallet>@ethersproject/random": true + } + }, + "@ethersproject/wallet>@ethersproject/abstract-provider": { + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/bignumber": true + } + }, + "@ethersproject/wallet>@ethersproject/json-wallets": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/hdnode": true, + "@ethersproject/hdnode>@ethersproject/pbkdf2": true, + "@ethersproject/hdnode>@ethersproject/transactions": true, + "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": true, + "@ethersproject/wallet>@ethersproject/random": true, + "ethereumjs-util>ethereum-cryptography>scrypt-js": true + } + }, + "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": { + "globals": { + "define": true + } + }, + "@ethersproject/wallet>@ethersproject/random": { + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/logger": true } }, "@keystonehq/bc-ur-registry-eth": { @@ -826,7 +874,7 @@ "packages": { "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, - "@metamask/providers>@metamask/rpc-errors": true + "@metamask/rpc-errors": true } }, "@metamask/approval-controller>@metamask/base-controller": { @@ -870,7 +918,7 @@ "@metamask/controller-utils": true, "@metamask/eth-query": true, "@metamask/metamask-eth-abis": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "bn.js": true, "lodash": true, @@ -1043,7 +1091,7 @@ }, "@metamask/eth-json-rpc-filters>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1058,7 +1106,7 @@ "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true, "@metamask/eth-json-rpc-middleware>safe-stable-stringify": true, "@metamask/eth-sig-util": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "pify": true, "sass-loader>klona": true @@ -1072,14 +1120,14 @@ }, "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } }, "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1749,7 +1797,7 @@ "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/json-rpc-engine": true, "@metamask/network-controller>@metamask/swappable-obj-proxy": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "browserify>assert": true, "uuid": true @@ -1788,14 +1836,14 @@ "packages": { "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "node-fetch": true } }, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1808,7 +1856,7 @@ }, "@metamask/network-controller>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1874,7 +1922,7 @@ "@metamask/permission-controller>@metamask/controller-utils": true, "@metamask/permission-controller>@metamask/json-rpc-engine": true, "@metamask/permission-controller>nanoid": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "deep-freeze-strict": true, "immer": true @@ -1908,7 +1956,7 @@ }, "@metamask/permission-controller>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -2053,16 +2101,10 @@ "ethereumjs-util>ethereum-cryptography>hash.js": true } }, - "@metamask/providers>@metamask/rpc-errors": { - "packages": { - "@metamask/utils": true, - "eth-rpc-errors>fast-safe-stringify": true - } - }, "@metamask/queued-request-controller": { "packages": { "@metamask/base-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/selected-network-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true @@ -2074,10 +2116,16 @@ }, "packages": { "@metamask/base-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true } }, + "@metamask/rpc-errors": { + "packages": { + "@metamask/utils": true, + "eth-rpc-errors>fast-safe-stringify": true + } + }, "@metamask/rpc-methods-flask>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2132,7 +2180,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/logging-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/signature-controller>@metamask/message-manager": true, "@metamask/utils": true, @@ -2286,7 +2334,7 @@ "@metamask/eth-query": true, "@metamask/metamask-eth-abis": true, "@metamask/network-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@ethereumjs/tx": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@ethereumjs/util": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@metamask/base-controller": true, @@ -2501,7 +2549,7 @@ "@metamask/base-controller": true, "@metamask/object-multiplex": true, "@metamask/post-message-stream": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>@metamask/json-rpc-middleware-stream": true, "@metamask/snaps-controllers>@metamask/permission-controller": true, @@ -2528,7 +2576,7 @@ }, "@metamask/snaps-controllers>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -2550,7 +2598,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>nanoid": true, "@metamask/utils": true, @@ -2615,7 +2663,7 @@ }, "@metamask/snaps-rpc-methods": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-rpc-methods>@metamask/permission-controller": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, @@ -2632,7 +2680,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": true, "@metamask/utils": true, @@ -2650,7 +2698,7 @@ "fetch": true }, "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-sdk>fast-xml-parser": true, "@metamask/utils": true, "superstruct": true @@ -2690,7 +2738,7 @@ "fetch": true }, "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, "@metamask/snaps-utils>@metamask/permission-controller": true, @@ -2715,7 +2763,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-utils>@metamask/permission-controller>nanoid": true, "@metamask/utils": true, @@ -2765,14 +2813,6 @@ "semver": true } }, - "@metamask/test-bundler>@ethersproject/abstract-provider": { - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bignumber": true - } - }, "@metamask/test-bundler>@ethersproject/networks": { "packages": { "@ethersproject/abi>@ethersproject/logger": true @@ -2796,7 +2836,7 @@ "@metamask/gas-fee-controller": true, "@metamask/metamask-eth-abis": true, "@metamask/network-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/transaction-controller>@metamask/base-controller": true, "@metamask/transaction-controller>@metamask/controller-utils": true, "@metamask/transaction-controller>@metamask/nonce-tracker": true, @@ -2871,7 +2911,7 @@ "@metamask/base-controller": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/transaction-controller": true, "@metamask/user-operation-controller>@metamask/controller-utils": true, "@metamask/utils": true, diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 7e1c1320bc3d..80b66dded93f 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -227,12 +227,12 @@ "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/abi>@ethersproject/bytes": true, "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/keccak256": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true + "@ethersproject/bignumber": true, + "@ethersproject/hash": true } }, "@ethersproject/abi>@ethersproject/address": { @@ -254,18 +254,6 @@ "@ethersproject/bignumber": true } }, - "@ethersproject/abi>@ethersproject/hash": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/providers>@ethersproject/base64": true - } - }, "@ethersproject/abi>@ethersproject/keccak256": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, @@ -307,9 +295,36 @@ "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, - "@ethersproject/hdnode>@ethersproject/abstract-signer": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, "@ethersproject/hdnode>@ethersproject/transactions": true, - "@metamask/test-bundler>@ethersproject/abstract-provider": true + "@ethersproject/wallet>@ethersproject/abstract-provider": true + } + }, + "@ethersproject/hash": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/bignumber": true, + "@ethersproject/hash>@ethersproject/base64": true + } + }, + "@ethersproject/hash>@ethersproject/abstract-signer": { + "packages": { + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true + } + }, + "@ethersproject/hash>@ethersproject/base64": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true } }, "@ethersproject/hdnode": { @@ -327,12 +342,6 @@ "@ethersproject/hdnode>@ethersproject/wordlists": true } }, - "@ethersproject/hdnode>@ethersproject/abstract-signer": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true - } - }, "@ethersproject/hdnode>@ethersproject/basex": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, @@ -376,10 +385,10 @@ "@ethersproject/hdnode>@ethersproject/wordlists": { "packages": { "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/hash": true } }, "@ethersproject/providers": { @@ -396,39 +405,26 @@ "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/abi>@ethersproject/bytes": true, "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/hash": true, "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, - "@ethersproject/hdnode>@ethersproject/abstract-signer": true, + "@ethersproject/hash": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, + "@ethersproject/hash>@ethersproject/base64": true, "@ethersproject/hdnode>@ethersproject/basex": true, "@ethersproject/hdnode>@ethersproject/sha2": true, "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/providers>@ethersproject/base64": true, - "@ethersproject/providers>@ethersproject/random": true, "@ethersproject/providers>@ethersproject/web": true, "@ethersproject/providers>bech32": true, - "@metamask/test-bundler>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/random": true, "@metamask/test-bundler>@ethersproject/networks": true } }, - "@ethersproject/providers>@ethersproject/base64": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true - } - }, "@ethersproject/providers>@ethersproject/random": { "globals": { "crypto.getRandomValues": true - }, - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/logger": true } }, "@ethersproject/providers>@ethersproject/rlp": { @@ -448,7 +444,59 @@ "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/providers>@ethersproject/base64": true + "@ethersproject/hash>@ethersproject/base64": true + } + }, + "@ethersproject/wallet": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/hash": true, + "@ethersproject/hash>@ethersproject/abstract-signer": true, + "@ethersproject/hdnode": true, + "@ethersproject/hdnode>@ethersproject/signing-key": true, + "@ethersproject/hdnode>@ethersproject/transactions": true, + "@ethersproject/wallet>@ethersproject/abstract-provider": true, + "@ethersproject/wallet>@ethersproject/json-wallets": true, + "@ethersproject/wallet>@ethersproject/random": true + } + }, + "@ethersproject/wallet>@ethersproject/abstract-provider": { + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/bignumber": true + } + }, + "@ethersproject/wallet>@ethersproject/json-wallets": { + "packages": { + "@ethersproject/abi>@ethersproject/address": true, + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/keccak256": true, + "@ethersproject/abi>@ethersproject/logger": true, + "@ethersproject/abi>@ethersproject/properties": true, + "@ethersproject/abi>@ethersproject/strings": true, + "@ethersproject/hdnode": true, + "@ethersproject/hdnode>@ethersproject/pbkdf2": true, + "@ethersproject/hdnode>@ethersproject/transactions": true, + "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": true, + "@ethersproject/wallet>@ethersproject/random": true, + "ethereumjs-util>ethereum-cryptography>scrypt-js": true + } + }, + "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": { + "globals": { + "define": true + } + }, + "@ethersproject/wallet>@ethersproject/random": { + "packages": { + "@ethersproject/abi>@ethersproject/bytes": true, + "@ethersproject/abi>@ethersproject/logger": true } }, "@keystonehq/bc-ur-registry-eth": { @@ -1111,7 +1159,7 @@ "packages": { "@metamask/approval-controller>@metamask/base-controller": true, "@metamask/approval-controller>nanoid": true, - "@metamask/providers>@metamask/rpc-errors": true + "@metamask/rpc-errors": true } }, "@metamask/approval-controller>@metamask/base-controller": { @@ -1155,7 +1203,7 @@ "@metamask/controller-utils": true, "@metamask/eth-query": true, "@metamask/metamask-eth-abis": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "bn.js": true, "lodash": true, @@ -1328,7 +1376,7 @@ }, "@metamask/eth-json-rpc-filters>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -1343,7 +1391,7 @@ "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true, "@metamask/eth-json-rpc-middleware>safe-stable-stringify": true, "@metamask/eth-sig-util": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "pify": true, "sass-loader>klona": true @@ -1357,14 +1405,14 @@ }, "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } }, "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -2034,7 +2082,7 @@ "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/json-rpc-engine": true, "@metamask/network-controller>@metamask/swappable-obj-proxy": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "browserify>assert": true, "uuid": true @@ -2073,14 +2121,14 @@ "packages": { "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "node-fetch": true } }, "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -2093,7 +2141,7 @@ }, "@metamask/network-controller>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -2159,7 +2207,7 @@ "@metamask/permission-controller>@metamask/controller-utils": true, "@metamask/permission-controller>@metamask/json-rpc-engine": true, "@metamask/permission-controller>nanoid": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true, "deep-freeze-strict": true, "immer": true @@ -2193,7 +2241,7 @@ }, "@metamask/permission-controller>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -2338,16 +2386,10 @@ "ethereumjs-util>ethereum-cryptography>hash.js": true } }, - "@metamask/providers>@metamask/rpc-errors": { - "packages": { - "@metamask/utils": true, - "eth-rpc-errors>fast-safe-stringify": true - } - }, "@metamask/queued-request-controller": { "packages": { "@metamask/base-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/selected-network-controller": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/utils": true @@ -2359,10 +2401,16 @@ }, "packages": { "@metamask/base-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/utils": true } }, + "@metamask/rpc-errors": { + "packages": { + "@metamask/utils": true, + "eth-rpc-errors>fast-safe-stringify": true + } + }, "@metamask/rpc-methods-flask>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2417,7 +2465,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/logging-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/signature-controller>@metamask/controller-utils": true, "@metamask/signature-controller>@metamask/message-manager": true, "@metamask/utils": true, @@ -2571,7 +2619,7 @@ "@metamask/eth-query": true, "@metamask/metamask-eth-abis": true, "@metamask/network-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@ethereumjs/tx": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@ethereumjs/util": true, "@metamask/smart-transactions-controller>@metamask/transaction-controller>@metamask/base-controller": true, @@ -2786,7 +2834,7 @@ "@metamask/base-controller": true, "@metamask/object-multiplex": true, "@metamask/post-message-stream": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>@metamask/json-rpc-middleware-stream": true, "@metamask/snaps-controllers>@metamask/permission-controller": true, @@ -2813,7 +2861,7 @@ }, "@metamask/snaps-controllers>@metamask/json-rpc-engine": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/safe-event-emitter": true, "@metamask/utils": true } @@ -2835,7 +2883,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-controllers>nanoid": true, "@metamask/utils": true, @@ -2900,7 +2948,7 @@ }, "@metamask/snaps-rpc-methods": { "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-rpc-methods>@metamask/permission-controller": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, @@ -2917,7 +2965,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-rpc-methods>@metamask/permission-controller>nanoid": true, "@metamask/utils": true, @@ -2935,7 +2983,7 @@ "fetch": true }, "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-sdk>fast-xml-parser": true, "@metamask/utils": true, "superstruct": true @@ -2975,7 +3023,7 @@ "fetch": true }, "packages": { - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, "@metamask/snaps-sdk>@metamask/key-tree": true, "@metamask/snaps-utils>@metamask/permission-controller": true, @@ -3000,7 +3048,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, "@metamask/snaps-utils>@metamask/permission-controller>nanoid": true, "@metamask/utils": true, @@ -3050,14 +3098,6 @@ "semver": true } }, - "@metamask/test-bundler>@ethersproject/abstract-provider": { - "packages": { - "@ethersproject/abi>@ethersproject/bytes": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bignumber": true - } - }, "@metamask/test-bundler>@ethersproject/networks": { "packages": { "@ethersproject/abi>@ethersproject/logger": true @@ -3081,7 +3121,7 @@ "@metamask/gas-fee-controller": true, "@metamask/metamask-eth-abis": true, "@metamask/network-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/transaction-controller>@metamask/base-controller": true, "@metamask/transaction-controller>@metamask/controller-utils": true, "@metamask/transaction-controller>@metamask/nonce-tracker": true, @@ -3156,7 +3196,7 @@ "@metamask/base-controller": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, - "@metamask/providers>@metamask/rpc-errors": true, + "@metamask/rpc-errors": true, "@metamask/transaction-controller": true, "@metamask/user-operation-controller>@metamask/controller-utils": true, "@metamask/utils": true, diff --git a/package.json b/package.json index 15793428c358..9de85d783161 100644 --- a/package.json +++ b/package.json @@ -267,8 +267,10 @@ "@ethersproject/abi": "^5.6.4", "@ethersproject/bignumber": "^5.7.0", "@ethersproject/contracts": "^5.7.0", + "@ethersproject/hash": "^5.7.0", "@ethersproject/hdnode": "^5.6.2", "@ethersproject/providers": "^5.7.2", + "@ethersproject/wallet": "^5.7.0", "@fortawesome/fontawesome-free": "^5.13.0", "@keystonehq/bc-ur-registry-eth": "^0.19.1", "@keystonehq/metamask-airgapped-keyring": "^0.13.1", @@ -329,6 +331,7 @@ "@metamask/providers": "^14.0.2", "@metamask/queued-request-controller": "^0.10.0", "@metamask/rate-limit-controller": "^5.0.1", + "@metamask/rpc-errors": "^6.2.1", "@metamask/safe-event-emitter": "^3.1.1", "@metamask/scure-bip39": "^2.0.3", "@metamask/selected-network-controller": "^15.0.2", diff --git a/shared/constants/app.ts b/shared/constants/app.ts index db176b8bbe93..9aeb58235c5c 100644 --- a/shared/constants/app.ts +++ b/shared/constants/app.ts @@ -34,6 +34,8 @@ export const MESSAGE_TYPE = { ETH_GET_ENCRYPTION_PUBLIC_KEY: 'eth_getEncryptionPublicKey', ETH_GET_BLOCK_BY_NUMBER: 'eth_getBlockByNumber', ETH_REQUEST_ACCOUNTS: 'eth_requestAccounts', + ETH_SEND_TRANSACTION: 'eth_sendTransaction', + ETH_SEND_RAW_TRANSACTION: 'eth_sendRawTransaction', ETH_SIGN: 'eth_sign', ETH_SIGN_TRANSACTION: 'eth_signTransaction', ETH_SIGN_TYPED_DATA: 'eth_signTypedData', diff --git a/shared/constants/first-party-contracts.ts b/shared/constants/first-party-contracts.ts index 07c3860a5168..100ef1ec6c7c 100644 --- a/shared/constants/first-party-contracts.ts +++ b/shared/constants/first-party-contracts.ts @@ -1,23 +1,35 @@ import { Hex } from '@metamask/utils'; import { CHAIN_IDS } from './network'; +export enum EXPERIENCES_TYPE { + METAMASK_VALIDATOR_STAKING = 'MetaMask Validator Staking', + METAMASK_POOLED_STAKING = 'MetaMask Pooled Staking', + METAMASK_THIRD_PARTY_STAKING = 'MetaMask Third Party Staking', + METAMASK_POOLED_STAKING_V1 = 'MetaMask Pool Staking (v1)', + METAMASK_BRIDGE = 'MetaMask Bridge', + METAMASK_SWAPS = 'MetaMask Swaps', +} + /** * A map of first-party contract names to their addresses on various chains. */ -export const FIRST_PARTY_CONTRACT_NAMES: Record<string, Record<Hex, Hex>> = { - 'MetaMask Validator Staking': { +export const FIRST_PARTY_CONTRACT_NAMES: Record< + EXPERIENCES_TYPE, + Record<Hex, Hex> +> = { + [EXPERIENCES_TYPE.METAMASK_VALIDATOR_STAKING]: { [CHAIN_IDS.MAINNET]: '0xDc71aFFC862fceB6aD32BE58E098423A7727bEbd', }, - 'MetaMask Pooled Staking': { + [EXPERIENCES_TYPE.METAMASK_POOLED_STAKING]: { [CHAIN_IDS.MAINNET]: '0x4FEF9D741011476750A243aC70b9789a63dd47Df', }, - 'MetaMask Third Party Staking': { + [EXPERIENCES_TYPE.METAMASK_THIRD_PARTY_STAKING]: { [CHAIN_IDS.MAINNET]: '0x1f6692E78dDE07FF8da75769B6d7c716215bC7D0', }, - 'MetaMask Pool Staking (v1)': { + [EXPERIENCES_TYPE.METAMASK_POOLED_STAKING_V1]: { [CHAIN_IDS.MAINNET]: '0xc7bE520a13dC023A1b34C03F4Abdab8A43653F7B', }, - 'MetaMask Bridge': { + [EXPERIENCES_TYPE.METAMASK_BRIDGE]: { [CHAIN_IDS.MAINNET]: '0x0439e60F02a8900a951603950d8D4527f400C3f1', [CHAIN_IDS.OPTIMISM]: '0xB90357f2b86dbfD59c3502215d4060f71DF8ca0e', [CHAIN_IDS.BSC]: '0xaEc23140408534b378bf5832defc426dF8604B59', @@ -28,7 +40,7 @@ export const FIRST_PARTY_CONTRACT_NAMES: Record<string, Record<Hex, Hex>> = { [CHAIN_IDS.AVALANCHE]: '0x29106d08382d3c73bF477A94333C61Db1142E1B6', [CHAIN_IDS.LINEA_MAINNET]: '0xE3d0d2607182Af5B24f5C3C2E4990A053aDd64e3', }, - 'MetaMask Swaps': { + [EXPERIENCES_TYPE.METAMASK_SWAPS]: { [CHAIN_IDS.MAINNET]: '0x881D40237659C251811CEC9c364ef91dC08D300C', [CHAIN_IDS.BSC]: '0x1a1ec25DC08e98e5E93F1104B5e5cdD298707d31', [CHAIN_IDS.POLYGON]: '0x1a1ec25DC08e98e5E93F1104B5e5cdD298707d31', diff --git a/shared/constants/verification.ts b/shared/constants/verification.ts new file mode 100644 index 000000000000..ce6ddaed9ea9 --- /dev/null +++ b/shared/constants/verification.ts @@ -0,0 +1,28 @@ +import { Hex } from '@metamask/utils'; +import { + EXPERIENCES_TYPE, + FIRST_PARTY_CONTRACT_NAMES, +} from './first-party-contracts'; + +export const TX_SIG_LEN = 130; +export const EXPERIENCES_TO_VERIFY = [EXPERIENCES_TYPE.METAMASK_BRIDGE]; +export const TRUSTED_SIGNERS: Partial<Record<EXPERIENCES_TYPE, Hex>> = { + [EXPERIENCES_TYPE.METAMASK_BRIDGE]: + '0x533FbF047Ed13C20e263e2576e41c747206d1348', +}; + +// look up the corresponding experience provided an address on a chain id +export const getExperience = ( + address: Hex, + chainId: Hex, +): EXPERIENCES_TYPE | undefined => + ( + Object.entries(FIRST_PARTY_CONTRACT_NAMES) as [ + EXPERIENCES_TYPE, + Record<Hex, Hex>, + ][] + ).find( + ([, chainMap]) => + (chainMap[chainId]?.toLowerCase() as Hex) === + (address.toLowerCase() as Hex), + )?.[0]; diff --git a/ui/hooks/useFirstPartyContractName.ts b/ui/hooks/useFirstPartyContractName.ts index 005282886eb8..47468b472955 100644 --- a/ui/hooks/useFirstPartyContractName.ts +++ b/ui/hooks/useFirstPartyContractName.ts @@ -1,7 +1,10 @@ import { NameType } from '@metamask/name-controller'; import { useSelector } from 'react-redux'; import { getCurrentChainId } from '../selectors'; -import { FIRST_PARTY_CONTRACT_NAMES } from '../../shared/constants/first-party-contracts'; +import { + EXPERIENCES_TYPE, + FIRST_PARTY_CONTRACT_NAMES, +} from '../../shared/constants/first-party-contracts'; export type UseFirstPartyContractNameRequest = { value: string; @@ -25,8 +28,9 @@ export function useFirstPartyContractNames( return ( Object.keys(FIRST_PARTY_CONTRACT_NAMES).find( (name) => - FIRST_PARTY_CONTRACT_NAMES[name]?.[chainId]?.toLowerCase() === - normalizedValue, + FIRST_PARTY_CONTRACT_NAMES[name as EXPERIENCES_TYPE]?.[ + chainId + ]?.toLowerCase() === normalizedValue, ) ?? null ); }); diff --git a/yarn.lock b/yarn.lock index 53e38866f75d..e537151b9fa5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2826,7 +2826,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/wallet@npm:5.7.0": +"@ethersproject/wallet@npm:5.7.0, @ethersproject/wallet@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/wallet@npm:5.7.0" dependencies: @@ -24930,8 +24930,10 @@ __metadata: "@ethersproject/abi": "npm:^5.6.4" "@ethersproject/bignumber": "npm:^5.7.0" "@ethersproject/contracts": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" "@ethersproject/hdnode": "npm:^5.6.2" "@ethersproject/providers": "npm:^5.7.2" + "@ethersproject/wallet": "npm:^5.7.0" "@fortawesome/fontawesome-free": "npm:^5.13.0" "@keystonehq/bc-ur-registry-eth": "npm:^0.19.1" "@keystonehq/metamask-airgapped-keyring": "npm:^0.13.1" @@ -25006,6 +25008,7 @@ __metadata: "@metamask/providers": "npm:^14.0.2" "@metamask/queued-request-controller": "npm:^0.10.0" "@metamask/rate-limit-controller": "npm:^5.0.1" + "@metamask/rpc-errors": "npm:^6.2.1" "@metamask/safe-event-emitter": "npm:^3.1.1" "@metamask/scure-bip39": "npm:^2.0.3" "@metamask/selected-network-controller": "npm:^15.0.2" From 8b764fa4b0e90ea29cff6bed6e7b4d2065afa049 Mon Sep 17 00:00:00 2001 From: Derek Brans <dbrans@gmail.com> Date: Fri, 14 Jun 2024 20:51:44 -0400 Subject: [PATCH 57/61] fix: re-add patch to nonce-tracker that was incorrectly removed (#25342) --- ...k-nonce-tracker-npm-5.0.0-d81478218e.patch | 30 +++++++++++++++++++ package.json | 3 +- yarn.lock | 14 ++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 .yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch diff --git a/.yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch b/.yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch new file mode 100644 index 000000000000..fb9a5c1ef5f6 --- /dev/null +++ b/.yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch @@ -0,0 +1,30 @@ +diff --git a/dist/NonceTracker.js b/dist/NonceTracker.js +index 7cfa1e1962c930a425b3dbf6e1520450f0bf1747..2f4ff77a678fe0501e96a92d16f63a8e5f299401 100644 +--- a/dist/NonceTracker.js ++++ b/dist/NonceTracker.js +@@ -12,7 +12,6 @@ class NonceTracker { + constructor(opts) { + this.provider = opts.provider; + this.blockTracker = opts.blockTracker; +- this.web3 = new Web3Provider(opts.provider); + this.getPendingTransactions = opts.getPendingTransactions; + this.getConfirmedTransactions = opts.getConfirmedTransactions; + this.lockMap = {}; +@@ -96,7 +95,7 @@ class NonceTracker { + // we need to make sure our base count + // and pending count are from the same block + const blockNumber = await this.blockTracker.getLatestBlock(); +- const baseCount = await this.web3.getTransactionCount(address, blockNumber); ++ const baseCount = await new Web3Provider(this.provider).getTransactionCount(address, blockNumber); + assert_1.default(Number.isInteger(baseCount), `nonce-tracker - baseCount is not an integer - got: (${typeof baseCount}) "${baseCount}"`); + return { + name: 'network', +diff --git a/dist/NonceTracker.js.map b/dist/NonceTracker.js.map +index 70e16afc468187dddb2ba1a6752e60c0aadb0f82..0e9d43aed1f7c5ccc2e16f91318aaab88da104ea 100644 +--- a/dist/NonceTracker.js.map ++++ b/dist/NonceTracker.js.map +@@ -1 +1 @@ +-{"version":3,"file":"NonceTracker.js","sourceRoot":"","sources":["../src/NonceTracker.ts"],"names":[],"mappings":"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"} +\ No newline at end of file ++{"version":3,"file":"NonceTracker.js","sourceRoot":"","sources":["../src/NonceTracker.ts"],"names":[],"mappings":"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"} +\ No newline at end of file diff --git a/package.json b/package.json index 9de85d783161..08ae5a31307a 100644 --- a/package.json +++ b/package.json @@ -256,7 +256,8 @@ "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch", "@solana/web3.js/rpc-websockets": "^8.0.1", "@metamask/network-controller@npm:^19.0.0": "patch:@metamask/network-controller@npm%3A19.0.0#~/.yarn/patches/@metamask-network-controller-npm-19.0.0-a5e0d1fe14.patch", - "@metamask/gas-fee-controller@npm:^15.1.1": "patch:@metamask/gas-fee-controller@npm%3A15.1.2#~/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch" + "@metamask/gas-fee-controller@npm:^15.1.1": "patch:@metamask/gas-fee-controller@npm%3A15.1.2#~/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch", + "@metamask/nonce-tracker@npm:^5.0.0": "patch:@metamask/nonce-tracker@npm%3A5.0.0#~/.yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch" }, "dependencies": { "@babel/runtime": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch", diff --git a/yarn.lock b/yarn.lock index e537151b9fa5..8b513f4b5d76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5778,7 +5778,7 @@ __metadata: languageName: node linkType: hard -"@metamask/nonce-tracker@npm:^5.0.0": +"@metamask/nonce-tracker@npm:5.0.0": version: 5.0.0 resolution: "@metamask/nonce-tracker@npm:5.0.0" dependencies: @@ -5790,6 +5790,18 @@ __metadata: languageName: node linkType: hard +"@metamask/nonce-tracker@patch:@metamask/nonce-tracker@npm%3A5.0.0#~/.yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch": + version: 5.0.0 + resolution: "@metamask/nonce-tracker@patch:@metamask/nonce-tracker@npm%3A5.0.0#~/.yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch::version=5.0.0&hash=b362e2" + dependencies: + "@ethersproject/providers": "npm:^5.7.2" + async-mutex: "npm:^0.3.1" + peerDependencies: + "@metamask/eth-block-tracker": ">=9" + checksum: 10/89c3e5219edc104ecc5f7bfb81f818a0800f946c9dd11d54ac79558e4abdbc895032dc2d7fed400a2d46b03ee6370dc393d62ec15b6cc0f2d3b45bcba6240fe0 + languageName: node + linkType: hard + "@metamask/notification-controller@npm:^3.0.0": version: 3.0.0 resolution: "@metamask/notification-controller@npm:3.0.0" From 624763a179a0006f86fc1dc0931aebc0b7dd220c Mon Sep 17 00:00:00 2001 From: micaelae <100321200+micaelae@users.noreply.github.com> Date: Fri, 14 Jun 2024 23:41:16 -0600 Subject: [PATCH 58/61] fix: swap+send bugs in Version v12.0.0 release (#25307) --- test/data/transaction-data.json | 1388 +++++++++++++++++ .../tests/swap-send/swap-send-erc20.spec.ts | 3 +- .../e2e/tests/swap-send/swap-send-eth.spec.ts | 6 +- .../tests/swap-send/swap-send-test-utils.ts | 8 +- .../multichain/asset-picker-amount/index.scss | 12 +- .../send/components/recipient-content.tsx | 7 +- .../ui/unit-input/unit-input.component.js | 1 + ui/hooks/useSwappedTokenValue.js | 33 +- ui/hooks/useTransactionDisplayData.js | 3 +- ui/hooks/useTransactionDisplayData.test.js | 30 +- 10 files changed, 1468 insertions(+), 23 deletions(-) diff --git a/test/data/transaction-data.json b/test/data/transaction-data.json index bdcbd7cd6abf..ad2dacfe082c 100644 --- a/test/data/transaction-data.json +++ b/test/data/transaction-data.json @@ -1252,5 +1252,1393 @@ }, "hasRetried": false, "hasCancelled": false + }, + { + "nonce": "0x9", + "transactions": [ + { + "actionId": 1718133500046.724, + "approvalTxId": "5ce4f880-2827-11ef-9c65-d1738f73c46f", + "baseFeePerGas": "0x0", + "blockTimestamp": "0x6668a2fd", + "chainId": "0x38", + "defaultGasEstimates": { + "estimateType": "medium", + "gas": "0x51fc6", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "destinationTokenAddress": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3", + "destinationTokenAmount": "4990565483715933000", + "destinationTokenDecimals": 18, + "destinationTokenSymbol": "DAI", + "hash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "history": [], + "id": "5cf9b900-2827-11ef-9c65-d1738f73c46f", + "networkClientId": "899c28d9-9f01-43c6-be76-b5e9f3cfe8bc", + "origin": "metamask", + "r": "0x443ec5a1269c18767b078894d177b4067831ea9ddcb33ebf92670d6667940985", + "rawTx": "0x02f903f1380984b2d05e0084b2d05e0083051fc6943cb693656622fc470f0bb07d3f5813f7889bf82e80b90384048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c188380000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc30000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b82680400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000148c43c9ef600000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b826804000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d000000000000000000000000e9e7cea3dedca5984780bafc599bd69add087d560000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc3869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb0000000000000000000000000000000000000000aca7f7533c2098f78f35db24000000000000000000000000000000000000000000000000c001a0443ec5a1269c18767b078894d177b4067831ea9ddcb33ebf92670d6667940985a0519c27715e9ce0cab31e7738ffad7d454088c3e3c855f54b8a0965a17d999c62", + "s": "0x519c27715e9ce0cab31e7738ffad7d454088c3e3c855f54b8a0965a17d999c62", + "sendFlowHistory": [], + "sourceTokenAddress": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "sourceTokenAmount": "5000000000000000000", + "sourceTokenDecimals": 18, + "sourceTokenSymbol": "USDC", + "status": "confirmed", + "submittedTime": 1718133500335, + "swapAndSendRecipient": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "swapTokenValue": "5", + "time": 1718133500048, + "txParams": { + "data": "0x048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c188380000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc30000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b82680400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000148c43c9ef600000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b826804000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d000000000000000000000000e9e7cea3dedca5984780bafc599bd69add087d560000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc3869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb0000000000000000000000000000000000000000aca7f7533c2098f78f35db24000000000000000000000000000000000000000000000000", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gas": "0x51fc6", + "gasLimit": "0x51fc6", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00", + "nonce": "0x9", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "type": "0x2", + "value": "0x0" + }, + "txReceipt": { + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "contractAddress": null, + "cumulativeGasUsed": "0x30fb3e", + "effectiveGasPrice": "0xb2d05e00", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gasUsed": "0x401d6", + "logs": [ + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f40000", + "logIndex": "0x45", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x46", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838", + "0x0000000000000000000000003cb693656622fc470f0bb07d3f5813f7889bf82e" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f40000", + "logIndex": "0x47", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f40000", + "logIndex": "0x48", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x0000000000000000000000002354ef4df11afacb85a5c7f98b624072eccddbb1" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x49", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0xe9e7cea3dedca5984780bafc599bd69add087d56", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x00000000000000000000000000000000000000000000000045351670c8c8eb16", + "logIndex": "0x4a", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000002354ef4df11afacb85a5c7f98b624072eccddbb1", + "0x00000000000000000000000066fdb2eccfb58cf098eaa419e5efde841368e489" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x2354ef4df11afacb85a5c7f98b624072eccddbb1", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000005cf210c436771e7d4016000000000000000000000000000000000000000000005cfaf19326e57b4c5707", + "logIndex": "0x4b", + "removed": false, + "topics": [ + "0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x2354ef4df11afacb85a5c7f98b624072eccddbb1", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045351670c8c8eb16", + "logIndex": "0x4c", + "removed": false, + "topics": [ + "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x00000000000000000000000066fdb2eccfb58cf098eaa419e5efde841368e489" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000453047e918796cfd", + "logIndex": "0x4d", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x00000000000000000000000066fdb2eccfb58cf098eaa419e5efde841368e489", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x66fdb2eccfb58cf098eaa419e5efde841368e489", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000020c638a3898eb7869dcf0000000000000000000000000000000000000000000020af974dbd9430b354c8", + "logIndex": "0x4e", + "removed": false, + "topics": [ + "0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x66fdb2eccfb58cf098eaa419e5efde841368e489", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045351670c8c8eb16000000000000000000000000000000000000000000000000453047e918796cfd0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x4f", + "removed": false, + "topics": [ + "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x50", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000453047e918796cfd", + "logIndex": "0x51", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000045357415000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x52", + "removed": false, + "topics": [ + "0x0c18aae526accb31b01cf9a15bdf435e70632ee31efc4c5c0752c4262ea45d2f" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + } + ], + "logsBloom": "0x006000000040001000000000800004000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000002000c0000000010000012000040008000000240000000000000088000000000000000008000000000000000000000004000040000000000000002008000010000000020000000000000001000000000040008000000000000800084000004000000100020000000000000000004000000000000000000000000000004000000000000000000002000000020000000000001000000040100000001000000020000000000010000000004002000000100000000000800000008000000000000001000000", + "status": "0x1", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21", + "type": "0x2" + }, + "type": "swapAndSend", + "userEditedGasLimit": false, + "userFeeLevel": "medium", + "v": "0x1", + "verifiedOnBlockchain": true + } + ], + "initialTransaction": { + "actionId": 1718133500046.724, + "approvalTxId": "5ce4f880-2827-11ef-9c65-d1738f73c46f", + "baseFeePerGas": "0x0", + "blockTimestamp": "0x6668a2fd", + "chainId": "0x38", + "defaultGasEstimates": { + "estimateType": "medium", + "gas": "0x51fc6", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "destinationTokenAddress": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3", + "destinationTokenAmount": "4990565483715933000", + "destinationTokenDecimals": 18, + "destinationTokenSymbol": "DAI", + "hash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "history": [], + "id": "5cf9b900-2827-11ef-9c65-d1738f73c46f", + "networkClientId": "899c28d9-9f01-43c6-be76-b5e9f3cfe8bc", + "origin": "metamask", + "r": "0x443ec5a1269c18767b078894d177b4067831ea9ddcb33ebf92670d6667940985", + "rawTx": "0x02f903f1380984b2d05e0084b2d05e0083051fc6943cb693656622fc470f0bb07d3f5813f7889bf82e80b90384048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c188380000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc30000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b82680400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000148c43c9ef600000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b826804000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d000000000000000000000000e9e7cea3dedca5984780bafc599bd69add087d560000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc3869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb0000000000000000000000000000000000000000aca7f7533c2098f78f35db24000000000000000000000000000000000000000000000000c001a0443ec5a1269c18767b078894d177b4067831ea9ddcb33ebf92670d6667940985a0519c27715e9ce0cab31e7738ffad7d454088c3e3c855f54b8a0965a17d999c62", + "s": "0x519c27715e9ce0cab31e7738ffad7d454088c3e3c855f54b8a0965a17d999c62", + "sendFlowHistory": [], + "sourceTokenAddress": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "sourceTokenAmount": "5000000000000000000", + "sourceTokenDecimals": 18, + "sourceTokenSymbol": "USDC", + "status": "confirmed", + "submittedTime": 1718133500335, + "swapAndSendRecipient": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "swapTokenValue": "5", + "time": 1718133500048, + "txParams": { + "data": "0x048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c188380000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc30000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b82680400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000148c43c9ef600000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b826804000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d000000000000000000000000e9e7cea3dedca5984780bafc599bd69add087d560000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc3869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb0000000000000000000000000000000000000000aca7f7533c2098f78f35db24000000000000000000000000000000000000000000000000", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gas": "0x51fc6", + "gasLimit": "0x51fc6", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00", + "nonce": "0x9", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "type": "0x2", + "value": "0x0" + }, + "txReceipt": { + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "contractAddress": null, + "cumulativeGasUsed": "0x30fb3e", + "effectiveGasPrice": "0xb2d05e00", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gasUsed": "0x401d6", + "logs": [ + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f40000", + "logIndex": "0x45", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x46", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838", + "0x0000000000000000000000003cb693656622fc470f0bb07d3f5813f7889bf82e" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f40000", + "logIndex": "0x47", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f40000", + "logIndex": "0x48", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x0000000000000000000000002354ef4df11afacb85a5c7f98b624072eccddbb1" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x49", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0xe9e7cea3dedca5984780bafc599bd69add087d56", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x00000000000000000000000000000000000000000000000045351670c8c8eb16", + "logIndex": "0x4a", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000002354ef4df11afacb85a5c7f98b624072eccddbb1", + "0x00000000000000000000000066fdb2eccfb58cf098eaa419e5efde841368e489" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x2354ef4df11afacb85a5c7f98b624072eccddbb1", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000005cf210c436771e7d4016000000000000000000000000000000000000000000005cfaf19326e57b4c5707", + "logIndex": "0x4b", + "removed": false, + "topics": [ + "0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x2354ef4df11afacb85a5c7f98b624072eccddbb1", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045351670c8c8eb16", + "logIndex": "0x4c", + "removed": false, + "topics": [ + "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x00000000000000000000000066fdb2eccfb58cf098eaa419e5efde841368e489" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000453047e918796cfd", + "logIndex": "0x4d", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x00000000000000000000000066fdb2eccfb58cf098eaa419e5efde841368e489", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x66fdb2eccfb58cf098eaa419e5efde841368e489", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000020c638a3898eb7869dcf0000000000000000000000000000000000000000000020af974dbd9430b354c8", + "logIndex": "0x4e", + "removed": false, + "topics": [ + "0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x66fdb2eccfb58cf098eaa419e5efde841368e489", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045351670c8c8eb16000000000000000000000000000000000000000000000000453047e918796cfd0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x4f", + "removed": false, + "topics": [ + "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x50", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000453047e918796cfd", + "logIndex": "0x51", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000045357415000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x52", + "removed": false, + "topics": [ + "0x0c18aae526accb31b01cf9a15bdf435e70632ee31efc4c5c0752c4262ea45d2f" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + } + ], + "logsBloom": "0x006000000040001000000000800004000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000002000c0000000010000012000040008000000240000000000000088000000000000000008000000000000000000000004000040000000000000002008000010000000020000000000000001000000000040008000000000000800084000004000000100020000000000000000004000000000000000000000000000004000000000000000000002000000020000000000001000000040100000001000000020000000000010000000004002000000100000000000800000008000000000000001000000", + "status": "0x1", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21", + "type": "0x2" + }, + "type": "swapAndSend", + "userEditedGasLimit": false, + "userFeeLevel": "medium", + "v": "0x1", + "verifiedOnBlockchain": true + }, + "primaryTransaction": { + "actionId": 1718133500046.724, + "approvalTxId": "5ce4f880-2827-11ef-9c65-d1738f73c46f", + "baseFeePerGas": "0x0", + "blockTimestamp": "0x6668a2fd", + "chainId": "0x38", + "defaultGasEstimates": { + "estimateType": "medium", + "gas": "0x51fc6", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "destinationTokenAddress": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3", + "destinationTokenAmount": "4990565483715933000", + "destinationTokenDecimals": 18, + "destinationTokenSymbol": "DAI", + "hash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "history": [], + "id": "5cf9b900-2827-11ef-9c65-d1738f73c46f", + "networkClientId": "899c28d9-9f01-43c6-be76-b5e9f3cfe8bc", + "origin": "metamask", + "r": "0x443ec5a1269c18767b078894d177b4067831ea9ddcb33ebf92670d6667940985", + "rawTx": "0x02f903f1380984b2d05e0084b2d05e0083051fc6943cb693656622fc470f0bb07d3f5813f7889bf82e80b90384048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c188380000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc30000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b82680400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000148c43c9ef600000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b826804000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d000000000000000000000000e9e7cea3dedca5984780bafc599bd69add087d560000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc3869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb0000000000000000000000000000000000000000aca7f7533c2098f78f35db24000000000000000000000000000000000000000000000000c001a0443ec5a1269c18767b078894d177b4067831ea9ddcb33ebf92670d6667940985a0519c27715e9ce0cab31e7738ffad7d454088c3e3c855f54b8a0965a17d999c62", + "s": "0x519c27715e9ce0cab31e7738ffad7d454088c3e3c855f54b8a0965a17d999c62", + "sendFlowHistory": [], + "sourceTokenAddress": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "sourceTokenAmount": "5000000000000000000", + "sourceTokenDecimals": 18, + "sourceTokenSymbol": "USDC", + "status": "confirmed", + "submittedTime": 1718133500335, + "swapAndSendRecipient": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "swapTokenValue": "5", + "time": 1718133500048, + "txParams": { + "data": "0x048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c188380000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc30000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b82680400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000148c43c9ef600000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000043df73024b826804000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d000000000000000000000000e9e7cea3dedca5984780bafc599bd69add087d560000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc3869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb0000000000000000000000000000000000000000aca7f7533c2098f78f35db24000000000000000000000000000000000000000000000000", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gas": "0x51fc6", + "gasLimit": "0x51fc6", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00", + "nonce": "0x9", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "type": "0x2", + "value": "0x0" + }, + "txReceipt": { + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "contractAddress": null, + "cumulativeGasUsed": "0x30fb3e", + "effectiveGasPrice": "0xb2d05e00", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gasUsed": "0x401d6", + "logs": [ + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f40000", + "logIndex": "0x45", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x46", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838", + "0x0000000000000000000000003cb693656622fc470f0bb07d3f5813f7889bf82e" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f40000", + "logIndex": "0x47", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f40000", + "logIndex": "0x48", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x0000000000000000000000002354ef4df11afacb85a5c7f98b624072eccddbb1" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x49", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0xe9e7cea3dedca5984780bafc599bd69add087d56", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x00000000000000000000000000000000000000000000000045351670c8c8eb16", + "logIndex": "0x4a", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000002354ef4df11afacb85a5c7f98b624072eccddbb1", + "0x00000000000000000000000066fdb2eccfb58cf098eaa419e5efde841368e489" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x2354ef4df11afacb85a5c7f98b624072eccddbb1", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000005cf210c436771e7d4016000000000000000000000000000000000000000000005cfaf19326e57b4c5707", + "logIndex": "0x4b", + "removed": false, + "topics": [ + "0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x2354ef4df11afacb85a5c7f98b624072eccddbb1", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045351670c8c8eb16", + "logIndex": "0x4c", + "removed": false, + "topics": [ + "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x00000000000000000000000066fdb2eccfb58cf098eaa419e5efde841368e489" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000453047e918796cfd", + "logIndex": "0x4d", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x00000000000000000000000066fdb2eccfb58cf098eaa419e5efde841368e489", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x66fdb2eccfb58cf098eaa419e5efde841368e489", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000020c638a3898eb7869dcf0000000000000000000000000000000000000000000020af974dbd9430b354c8", + "logIndex": "0x4e", + "removed": false, + "topics": [ + "0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x66fdb2eccfb58cf098eaa419e5efde841368e489", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045351670c8c8eb16000000000000000000000000000000000000000000000000453047e918796cfd0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x4f", + "removed": false, + "topics": [ + "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x50", + "removed": false, + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000453047e918796cfd", + "logIndex": "0x51", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + }, + { + "address": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "blockHash": "0x2ad0174dc123330852694ddeaa1924450b6bba340485f18abe3a6681bc8896f7", + "blockNumber": "0x25b2338", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000045357415000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x52", + "removed": false, + "topics": [ + "0x0c18aae526accb31b01cf9a15bdf435e70632ee31efc4c5c0752c4262ea45d2f" + ], + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21" + } + ], + "logsBloom": "0x006000000040001000000000800004000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000002000c0000000010000012000040008000000240000000000000088000000000000000008000000000000000000000004000040000000000000002008000010000000020000000000000001000000000040008000000000000800084000004000000100020000000000000000004000000000000000000000000000004000000000000000000002000000020000000000001000000040100000001000000020000000000010000000004002000000100000000000800000008000000000000001000000", + "status": "0x1", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "transactionHash": "0x5be1ae5ae27c4e2a5542228b4f7967a660881dcbc71521a978ea6d9c3b3971fe", + "transactionIndex": "0x21", + "type": "0x2" + }, + "type": "swapAndSend", + "userEditedGasLimit": false, + "userFeeLevel": "medium", + "v": "0x1", + "verifiedOnBlockchain": true + }, + "hasRetried": false, + "hasCancelled": false + }, + { + "nonce": "0x0", + "transactions": [ + { + "actionId": 1717789986313.557, + "baseFeePerGas": "0x0", + "blockTimestamp": "0x66636524", + "chainId": "0x38", + "defaultGasEstimates": { + "estimateType": "medium", + "gas": "0x397cf", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "destinationTokenAddress": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "destinationTokenAmount": "33721280446418538542", + "destinationTokenDecimals": 18, + "destinationTokenSymbol": "USDC", + "firstRetryBlockNumber": "0x259650b", + "gasFeeEstimates": { + "high": { + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "low": { + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "medium": { + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "type": "fee-market" + }, + "gasFeeEstimatesLoaded": true, + "hash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "history": [], + "id": "8ed642e0-2507-11ef-99c4-53f3fc2768a2", + "networkClientId": "899c28d9-9f01-43c6-be76-b5e9f3cfe8bc", + "origin": "metamask", + "r": "0x7fbbe0d92a8da53a9bc98ef8144c6677ecb08050ea180548d93b7830cb407a2a", + "rawTx": "0x02f903d8388084b2d05e0084b2d05e00830397cf943cb693656622fc470f0bb07d3f5813f7889bf82e87b1a2bc2ec50000b90364048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c1883800000000000000000000000000000000000000000000000000000000000000000000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d00000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000018de76816d80000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000128c43c9ef6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb000000000000000000000000000000003736a41146b8f4bb97dbe80a5771808c000000000000000000000000000000000000000000000000c001a07fbbe0d92a8da53a9bc98ef8144c6677ecb08050ea180548d93b7830cb407a2aa04d050489b179ec7832166566d3769408ef6c407d0032243cdabeb99bab87d634", + "s": "0x4d050489b179ec7832166566d3769408ef6c407d0032243cdabeb99bab87d634", + "sendFlowHistory": [], + "sourceTokenAddress": "0x0000000000000000000000000000000000000000", + "sourceTokenAmount": "50000000000000000", + "sourceTokenDecimals": 18, + "sourceTokenSymbol": "BNB", + "status": "confirmed", + "submittedTime": 1717789986704, + "swapAndSendRecipient": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "swapTokenValue": "0.05", + "time": 1717789986319, + "txParams": { + "data": "0x048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c1883800000000000000000000000000000000000000000000000000000000000000000000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d00000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000018de76816d80000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000128c43c9ef6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb000000000000000000000000000000003736a41146b8f4bb97dbe80a5771808c000000000000000000000000000000000000000000000000", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gas": "0x397cf", + "gasLimit": "0x397cf", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00", + "nonce": "0x0", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "type": "0x2", + "value": "0xb1a2bc2ec50000" + }, + "txReceipt": { + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "contractAddress": null, + "cumulativeGasUsed": "0x2644bd", + "effectiveGasPrice": "0xb2d05e00", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gasUsed": "0x31a28", + "logs": [ + { + "address": "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x00000000000000000000000000000000000000000000000000b014d4c6ae2800", + "logIndex": "0x38", + "removed": false, + "topics": [ + "0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x00000000000000000000000000000000000000000000000000b014d4c6ae2800", + "logIndex": "0x39", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x000000000000000000000000d99c7f6c65857ac913a8f880a4cb84032ab2fc5b" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000001d3be028ce893dfbe", + "logIndex": "0x3a", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000d99c7f6c65857ac913a8f880a4cb84032ab2fc5b", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0xd99c7f6c65857ac913a8f880a4cb84032ab2fc5b", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000003ef046f04c7cafc1e5e20000000000000000000000000000000000000000000000179ff39de2fc5b390a", + "logIndex": "0x3b", + "removed": false, + "topics": [ + "0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0xd99c7f6c65857ac913a8f880a4cb84032ab2fc5b", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001d3be028ce893dfbe0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x3c", + "removed": false, + "topics": [ + "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000001d3be028ce893dfbe", + "logIndex": "0x3d", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000045357415000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x3e", + "removed": false, + "topics": [ + "0x0c18aae526accb31b01cf9a15bdf435e70632ee31efc4c5c0752c4262ea45d2f" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + } + ], + "logsBloom": "0x00600000000000000000000080000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000010000012000000008000000200000000000000000000400008000000000400000000000000000000004000040000000000000000008000010000000000000000000000001000000000040008000040001000800080000004000000000000000000000000000004000000000000000000000000004024000000000000000000002000000000000040000000000000000000000001040000000000080000000000000005002000000000000000000000000000000400000000001000000", + "status": "0x1", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e", + "type": "0x2" + }, + "type": "swapAndSend", + "userEditedGasLimit": false, + "userFeeLevel": "medium", + "v": "0x1", + "verifiedOnBlockchain": true + } + ], + "initialTransaction": { + "actionId": 1717789986313.557, + "baseFeePerGas": "0x0", + "blockTimestamp": "0x66636524", + "chainId": "0x38", + "defaultGasEstimates": { + "estimateType": "medium", + "gas": "0x397cf", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "destinationTokenAddress": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "destinationTokenAmount": "33721280446418538542", + "destinationTokenDecimals": 18, + "destinationTokenSymbol": "USDC", + "firstRetryBlockNumber": "0x259650b", + "gasFeeEstimates": { + "high": { + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "low": { + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "medium": { + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "type": "fee-market" + }, + "gasFeeEstimatesLoaded": true, + "hash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "history": [], + "id": "8ed642e0-2507-11ef-99c4-53f3fc2768a2", + "networkClientId": "899c28d9-9f01-43c6-be76-b5e9f3cfe8bc", + "origin": "metamask", + "r": "0x7fbbe0d92a8da53a9bc98ef8144c6677ecb08050ea180548d93b7830cb407a2a", + "rawTx": "0x02f903d8388084b2d05e0084b2d05e00830397cf943cb693656622fc470f0bb07d3f5813f7889bf82e87b1a2bc2ec50000b90364048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c1883800000000000000000000000000000000000000000000000000000000000000000000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d00000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000018de76816d80000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000128c43c9ef6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb000000000000000000000000000000003736a41146b8f4bb97dbe80a5771808c000000000000000000000000000000000000000000000000c001a07fbbe0d92a8da53a9bc98ef8144c6677ecb08050ea180548d93b7830cb407a2aa04d050489b179ec7832166566d3769408ef6c407d0032243cdabeb99bab87d634", + "s": "0x4d050489b179ec7832166566d3769408ef6c407d0032243cdabeb99bab87d634", + "sendFlowHistory": [], + "sourceTokenAddress": "0x0000000000000000000000000000000000000000", + "sourceTokenAmount": "50000000000000000", + "sourceTokenDecimals": 18, + "sourceTokenSymbol": "BNB", + "status": "confirmed", + "submittedTime": 1717789986704, + "swapAndSendRecipient": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "swapTokenValue": "0.05", + "time": 1717789986319, + "txParams": { + "data": "0x048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c1883800000000000000000000000000000000000000000000000000000000000000000000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d00000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000018de76816d80000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000128c43c9ef6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb000000000000000000000000000000003736a41146b8f4bb97dbe80a5771808c000000000000000000000000000000000000000000000000", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gas": "0x397cf", + "gasLimit": "0x397cf", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00", + "nonce": "0x0", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "type": "0x2", + "value": "0xb1a2bc2ec50000" + }, + "txReceipt": { + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "contractAddress": null, + "cumulativeGasUsed": "0x2644bd", + "effectiveGasPrice": "0xb2d05e00", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gasUsed": "0x31a28", + "logs": [ + { + "address": "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x00000000000000000000000000000000000000000000000000b014d4c6ae2800", + "logIndex": "0x38", + "removed": false, + "topics": [ + "0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x00000000000000000000000000000000000000000000000000b014d4c6ae2800", + "logIndex": "0x39", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x000000000000000000000000d99c7f6c65857ac913a8f880a4cb84032ab2fc5b" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000001d3be028ce893dfbe", + "logIndex": "0x3a", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000d99c7f6c65857ac913a8f880a4cb84032ab2fc5b", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0xd99c7f6c65857ac913a8f880a4cb84032ab2fc5b", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000003ef046f04c7cafc1e5e20000000000000000000000000000000000000000000000179ff39de2fc5b390a", + "logIndex": "0x3b", + "removed": false, + "topics": [ + "0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0xd99c7f6c65857ac913a8f880a4cb84032ab2fc5b", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001d3be028ce893dfbe0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x3c", + "removed": false, + "topics": [ + "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000001d3be028ce893dfbe", + "logIndex": "0x3d", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000045357415000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x3e", + "removed": false, + "topics": [ + "0x0c18aae526accb31b01cf9a15bdf435e70632ee31efc4c5c0752c4262ea45d2f" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + } + ], + "logsBloom": "0x00600000000000000000000080000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000010000012000000008000000200000000000000000000400008000000000400000000000000000000004000040000000000000000008000010000000000000000000000001000000000040008000040001000800080000004000000000000000000000000000004000000000000000000000000004024000000000000000000002000000000000040000000000000000000000001040000000000080000000000000005002000000000000000000000000000000400000000001000000", + "status": "0x1", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e", + "type": "0x2" + }, + "type": "swapAndSend", + "userEditedGasLimit": false, + "userFeeLevel": "medium", + "v": "0x1", + "verifiedOnBlockchain": true + }, + "primaryTransaction": { + "actionId": 1717789986313.557, + "baseFeePerGas": "0x0", + "blockTimestamp": "0x66636524", + "chainId": "0x38", + "defaultGasEstimates": { + "estimateType": "medium", + "gas": "0x397cf", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "destinationTokenAddress": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "destinationTokenAmount": "33721280446418538542", + "destinationTokenDecimals": 18, + "destinationTokenSymbol": "USDC", + "firstRetryBlockNumber": "0x259650b", + "gasFeeEstimates": { + "high": { + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "low": { + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "medium": { + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00" + }, + "type": "fee-market" + }, + "gasFeeEstimatesLoaded": true, + "hash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "history": [], + "id": "8ed642e0-2507-11ef-99c4-53f3fc2768a2", + "networkClientId": "899c28d9-9f01-43c6-be76-b5e9f3cfe8bc", + "origin": "metamask", + "r": "0x7fbbe0d92a8da53a9bc98ef8144c6677ecb08050ea180548d93b7830cb407a2a", + "rawTx": "0x02f903d8388084b2d05e0084b2d05e00830397cf943cb693656622fc470f0bb07d3f5813f7889bf82e87b1a2bc2ec50000b90364048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c1883800000000000000000000000000000000000000000000000000000000000000000000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d00000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000018de76816d80000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000128c43c9ef6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb000000000000000000000000000000003736a41146b8f4bb97dbe80a5771808c000000000000000000000000000000000000000000000000c001a07fbbe0d92a8da53a9bc98ef8144c6677ecb08050ea180548d93b7830cb407a2aa04d050489b179ec7832166566d3769408ef6c407d0032243cdabeb99bab87d634", + "s": "0x4d050489b179ec7832166566d3769408ef6c407d0032243cdabeb99bab87d634", + "sendFlowHistory": [], + "sourceTokenAddress": "0x0000000000000000000000000000000000000000", + "sourceTokenAmount": "50000000000000000", + "sourceTokenDecimals": 18, + "sourceTokenSymbol": "BNB", + "status": "confirmed", + "submittedTime": 1717789986704, + "swapAndSendRecipient": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "swapTokenValue": "0.05", + "time": 1717789986319, + "txParams": { + "data": "0x048226a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c1883800000000000000000000000000000000000000000000000000000000000000000000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d00000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000018de76816d80000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000128c43c9ef6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001ca9e03628c802fdb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d869584cd00000000000000000000000011ededebf63bef0ea2d2d071bdf88f71543ec6fb000000000000000000000000000000003736a41146b8f4bb97dbe80a5771808c000000000000000000000000000000000000000000000000", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gas": "0x397cf", + "gasLimit": "0x397cf", + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0xb2d05e00", + "nonce": "0x0", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "type": "0x2", + "value": "0xb1a2bc2ec50000" + }, + "txReceipt": { + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "contractAddress": null, + "cumulativeGasUsed": "0x2644bd", + "effectiveGasPrice": "0xb2d05e00", + "from": "0x141d32a89a1e0a5ef360034a2f60a4b917c18838", + "gasUsed": "0x31a28", + "logs": [ + { + "address": "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x00000000000000000000000000000000000000000000000000b014d4c6ae2800", + "logIndex": "0x38", + "removed": false, + "topics": [ + "0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x00000000000000000000000000000000000000000000000000b014d4c6ae2800", + "logIndex": "0x39", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x000000000000000000000000d99c7f6c65857ac913a8f880a4cb84032ab2fc5b" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000001d3be028ce893dfbe", + "logIndex": "0x3a", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000d99c7f6c65857ac913a8f880a4cb84032ab2fc5b", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0xd99c7f6c65857ac913a8f880a4cb84032ab2fc5b", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000003ef046f04c7cafc1e5e20000000000000000000000000000000000000000000000179ff39de2fc5b390a", + "logIndex": "0x3b", + "removed": false, + "topics": [ + "0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0xd99c7f6c65857ac913a8f880a4cb84032ab2fc5b", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b014d4c6ae2800000000000000000000000000000000000000000000000001d3be028ce893dfbe0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x3c", + "removed": false, + "topics": [ + "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", + "0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000001d3be028ce893dfbe", + "logIndex": "0x3d", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000bd7607133b9620320e745b3e0b1af717f8ea5889", + "0x000000000000000000000000141d32a89a1e0a5ef360034a2f60a4b917c18838" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + }, + { + "address": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "blockHash": "0xdf447bf7f6018f3b30ddc7004f45d8d55f68434865a05598ce4c1fd774642590", + "blockNumber": "0x259650c", + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000045357415000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x3e", + "removed": false, + "topics": [ + "0x0c18aae526accb31b01cf9a15bdf435e70632ee31efc4c5c0752c4262ea45d2f" + ], + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e" + } + ], + "logsBloom": "0x00600000000000000000000080000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000010000012000000008000000200000000000000000000400008000000000400000000000000000000004000040000000000000000008000010000000000000000000000001000000000040008000040001000800080000004000000000000000000000000000004000000000000000000000000004024000000000000000000002000000000000040000000000000000000000001040000000000080000000000000005002000000000000000000000000000000400000000001000000", + "status": "0x1", + "to": "0x3cb693656622fc470f0bb07d3f5813f7889bf82e", + "transactionHash": "0x5b13c4573b31d93bfb564c4f8506448bba16908b6974a4c0494a40d9aa622de7", + "transactionIndex": "0x2e", + "type": "0x2" + }, + "type": "swapAndSend", + "userEditedGasLimit": false, + "userFeeLevel": "medium", + "v": "0x1", + "verifiedOnBlockchain": true + }, + "hasRetried": false, + "hasCancelled": false } ] diff --git a/test/e2e/tests/swap-send/swap-send-erc20.spec.ts b/test/e2e/tests/swap-send/swap-send-erc20.spec.ts index eb20ea18f42d..10b18592f42b 100644 --- a/test/e2e/tests/swap-send/swap-send-erc20.spec.ts +++ b/test/e2e/tests/swap-send/swap-send-erc20.spec.ts @@ -21,6 +21,7 @@ describe('Swap-Send ERC20', function () { getSwapSendFixtures( this.test?.fullTitle(), SWAP_SEND_QUOTES_RESPONSE_TST_ETH, + '?sourceAmount=100000&sourceToken=0x581c3C1A2A4EBDE2A0Df29B5cf4c116E42945947&destinationToken=0x0000000000000000000000000000000000000000&sender=0x5cfe73b6021e818b776b421b1c4db2474086a7e1&recipient=0xc427D562164062a23a5cFf596A4a3208e72Acd28&slippage=2', ), async ({ driver, @@ -104,7 +105,7 @@ describe('Swap-Send ERC20', function () { 'Send TST as ETH', 'Confirmed', '-10 TST', - '-$0.00', + '', ); driver.summarizeErrorsAndExceptions(); diff --git a/test/e2e/tests/swap-send/swap-send-eth.spec.ts b/test/e2e/tests/swap-send/swap-send-eth.spec.ts index 4622a2000e24..244693d513a2 100644 --- a/test/e2e/tests/swap-send/swap-send-eth.spec.ts +++ b/test/e2e/tests/swap-send/swap-send-eth.spec.ts @@ -71,18 +71,20 @@ describe('Swap-Send ETH', function () { '≈ $38.84', ); + // TODO assert swap api request payload + await swapSendPage.submitSwap(); await swapSendPage.verifyHistoryEntry( 'Send ETH as TST', 'Pending', '-1 ETH', - '-$3,010.00', + '', ); await swapSendPage.verifyHistoryEntry( 'Send ETH as TST', 'Confirmed', '-1 ETH', - '-$3,010.00', + '', ); driver.summarizeErrorsAndExceptions(); diff --git a/test/e2e/tests/swap-send/swap-send-test-utils.ts b/test/e2e/tests/swap-send/swap-send-test-utils.ts index 94e4a8f0a0c9..a78cd2a27057 100644 --- a/test/e2e/tests/swap-send/swap-send-test-utils.ts +++ b/test/e2e/tests/swap-send/swap-send-test-utils.ts @@ -245,10 +245,11 @@ export class SwapSendPage { } export const mockSwapsApi = - (quotes = SWAP_SEND_QUOTES_RESPONSE_ETH_TST) => + (quotes: typeof SWAP_SEND_QUOTES_RESPONSE_ETH_TST, query: string) => async (mockServer: Mockttp) => { - return await mockServer + await mockServer .forGet(`${SWAPS_API_V2_BASE_URL}/v2/networks/1337/quotes`) + .withExactQuery(query) .always() .thenCallback(() => { return { @@ -261,6 +262,7 @@ export const mockSwapsApi = export const getSwapSendFixtures = ( title?: string, swapsQuotes = SWAP_SEND_QUOTES_RESPONSE_ETH_TST, + swapsQuery = '?sourceAmount=1000000000000000000&sourceToken=0x0000000000000000000000000000000000000000&destinationToken=0x581c3C1A2A4EBDE2A0Df29B5cf4c116E42945947&sender=0x5cfe73b6021e818b776b421b1c4db2474086a7e1&recipient=0xc427D562164062a23a5cFf596A4a3208e72Acd28&slippage=2', ) => { const ETH_CONVERSION_RATE_USD = 3010; return { @@ -296,7 +298,7 @@ export const getSwapSendFixtures = ( .build(), smartContract: SMART_CONTRACTS.HST, ethConversionInUsd: ETH_CONVERSION_RATE_USD, - testSpecificMock: mockSwapsApi(swapsQuotes), + testSpecificMock: mockSwapsApi(swapsQuotes, swapsQuery), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), title, }; diff --git a/ui/components/multichain/asset-picker-amount/index.scss b/ui/components/multichain/asset-picker-amount/index.scss index 573e71c83f05..b9f22ba6d1cf 100644 --- a/ui/components/multichain/asset-picker-amount/index.scss +++ b/ui/components/multichain/asset-picker-amount/index.scss @@ -36,7 +36,7 @@ .unit-input__inputs { // primary (i.e., input) and secondary (i.e., subtext) input sections & > div { - max-width: 125px; + max-width: 138px; white-space: nowrap; text-overflow: ellipsis; } @@ -51,7 +51,15 @@ text-overflow: ellipsis; overflow: hidden; - display: inline; + flex-wrap: nowrap; + + & > span.currency-display-component__text { + width: max-content; + } + + & > span.currency-display-component__suffix { + width: max-content; + } } // secondary field elements (e.g., value, symbols) diff --git a/ui/components/multichain/pages/send/components/recipient-content.tsx b/ui/components/multichain/pages/send/components/recipient-content.tsx index 6ca53ae62575..90a73a932c4b 100644 --- a/ui/components/multichain/pages/send/components/recipient-content.tsx +++ b/ui/components/multichain/pages/send/components/recipient-content.tsx @@ -25,6 +25,7 @@ import { getUseExternalServices, } from '../../../../../selectors'; import type { Quote } from '../../../../../ducks/send/swap-and-send-utils'; +import { isEqualCaseInsensitive } from '../../../../../../shared/modules/string-utils'; import { SendHexData, SendPageRow, QuoteCard } from '.'; export const SendPageRecipientContent = ({ @@ -59,8 +60,10 @@ export const SendPageRecipientContent = ({ const isLoadingInitialQuotes = !bestQuote && isSwapQuoteLoading; - const isBasicSend = - receiveAsset.details?.address === sendAsset.details?.address; + const isBasicSend = isEqualCaseInsensitive( + receiveAsset.details?.address ?? '', + sendAsset.details?.address ?? '', + ); const amount = isBasicSend ? sendAmount diff --git a/ui/components/ui/unit-input/unit-input.component.js b/ui/components/ui/unit-input/unit-input.component.js index e916cf5e2e3f..727a33e98c4a 100644 --- a/ui/components/ui/unit-input/unit-input.component.js +++ b/ui/components/ui/unit-input/unit-input.component.js @@ -95,6 +95,7 @@ export default class UnitInput extends PureComponent { } this.props.onBlur && this.props.onBlur(value); + this.unitInput.scrollTo && this.unitInput.scrollTo(0, 0); }; handleChange = (event) => { diff --git a/ui/hooks/useSwappedTokenValue.js b/ui/hooks/useSwappedTokenValue.js index a93140373829..c7007346d7c0 100644 --- a/ui/hooks/useSwappedTokenValue.js +++ b/ui/hooks/useSwappedTokenValue.js @@ -37,16 +37,16 @@ export function useSwappedTokenValue(transactionGroup, currentAsset) { const chainId = useSelector(getCurrentChainId); const isViewingReceivedTokenFromSwap = - currentAsset?.symbol === primaryTransaction.destinationTokenSymbol || - (isSwapsDefaultTokenAddress(currentAsset.address, chainId) && - isSwapsDefaultTokenSymbol( - primaryTransaction.destinationTokenSymbol, - chainId, - )); + type === TransactionType.swap && + (currentAsset?.symbol === primaryTransaction.destinationTokenSymbol || + (isSwapsDefaultTokenAddress(currentAsset.address, chainId) && + isSwapsDefaultTokenSymbol( + primaryTransaction.destinationTokenSymbol, + chainId, + ))); const swapTokenValue = - [TransactionType.swap, TransactionType.swapAndSend].includes(type) && - isViewingReceivedTokenFromSwap + [TransactionType.swap].includes(type) && isViewingReceivedTokenFromSwap ? getSwapsTokensReceivedFromTxMeta( primaryTransaction.destinationTokenSymbol, initialTransaction, @@ -69,8 +69,21 @@ export function useSwappedTokenValue(transactionGroup, currentAsset) { swapTokenValue || '', symbol, ); - const swapTokenFiatAmount = - swapTokenValue && isViewingReceivedTokenFromSwap && _swapTokenFiatAmount; + const _swapAndSendTokenFiatAmount = useTokenFiatAmount( + primaryTransaction.sourceTokenAddress, + swapTokenValue, + primaryTransaction.sourceTokenSymbol, + ); + + let swapTokenFiatAmount; + if (swapTokenValue) { + if (isViewingReceivedTokenFromSwap) { + swapTokenFiatAmount = _swapTokenFiatAmount; + } else if (type === TransactionType.swapAndSend) { + swapTokenFiatAmount = _swapAndSendTokenFiatAmount; + } + } + return { swapTokenValue, swapTokenFiatAmount, diff --git a/ui/hooks/useTransactionDisplayData.js b/ui/hooks/useTransactionDisplayData.js index 019a9ec13fa2..4b551b318b62 100644 --- a/ui/hooks/useTransactionDisplayData.js +++ b/ui/hooks/useTransactionDisplayData.js @@ -394,7 +394,8 @@ export function useTransactionDisplayData(transactionGroup) { recipientAddress, secondaryCurrency: (isTokenCategory && !tokenFiatAmount) || - (type === TransactionType.swap && !swapTokenFiatAmount) + ([TransactionType.swap, TransactionType.swapAndSend].includes(type) && + !swapTokenFiatAmount) ? undefined : secondaryCurrency, displayedStatusKey, diff --git a/ui/hooks/useTransactionDisplayData.test.js b/ui/hooks/useTransactionDisplayData.test.js index 60de4dccd295..5008e9898d24 100644 --- a/ui/hooks/useTransactionDisplayData.test.js +++ b/ui/hooks/useTransactionDisplayData.test.js @@ -171,10 +171,36 @@ const expectedResults = [ subtitle: 'metamask', subtitleContainsOrigin: true, date: formatDateWithYearContext(1585088013000), - primaryCurrency: '-0 BAT', + primaryCurrency: '-33.425656732428330864 BAT', senderAddress: '0x0a985a957b490f4d05bef05bc7ec556dd8535946', recipientAddress: '0xc6f6ca03d790168758285264bcbf7fb30d27322b', - secondaryCurrency: '-0 ETH', + secondaryCurrency: undefined, + isPending: false, + displayedStatusKey: TransactionStatus.confirmed, + }, + { + title: 'Send USDC as DAI', + category: TransactionType.swapAndSend, + subtitle: 'metamask', + subtitleContainsOrigin: true, + date: formatDateWithYearContext(1585088013000), + primaryCurrency: '-5 USDC', + senderAddress: '0x141d32a89a1e0a5ef360034a2f60a4b917c18838', + recipientAddress: '0x141d32a89a1e0a5ef360034a2f60a4b917c18838', + secondaryCurrency: undefined, + isPending: false, + displayedStatusKey: TransactionStatus.confirmed, + }, + { + title: 'Send BNB as USDC', + category: TransactionType.swapAndSend, + subtitle: 'metamask', + subtitleContainsOrigin: true, + date: formatDateWithYearContext(1585088013000), + primaryCurrency: '-0.05 BNB', + senderAddress: '0x141d32a89a1e0a5ef360034a2f60a4b917c18838', + recipientAddress: '0x141d32a89a1e0a5ef360034a2f60a4b917c18838', + secondaryCurrency: undefined, isPending: false, displayedStatusKey: TransactionStatus.confirmed, }, From 4147b2dd24d0516e7b21d580ae685669db73a27d Mon Sep 17 00:00:00 2001 From: legobeat <109787230+legobeat@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:39:15 +0900 Subject: [PATCH 59/61] fix: upgrade dependency ws (#25372) --- package.json | 2 ++ yarn.lock | 52 +++++++++++----------------------------------------- 2 files changed, 13 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index 08ae5a31307a..596e3acaf885 100644 --- a/package.json +++ b/package.json @@ -191,6 +191,8 @@ "regenerator-runtime@^0.13.4": "patch:regenerator-runtime@npm%3A0.13.7#./.yarn/patches/regenerator-runtime-npm-0.13.7-41bcbe64ea.patch", "regenerator-runtime@^0.13.7": "patch:regenerator-runtime@npm%3A0.13.7#./.yarn/patches/regenerator-runtime-npm-0.13.7-41bcbe64ea.patch", "regenerator-runtime@^0.11.0": "patch:regenerator-runtime@npm%3A0.13.7#./.yarn/patches/regenerator-runtime-npm-0.13.7-41bcbe64ea.patch", + "ws@8.13.0": "^8.17.1", + "ws@7.4.6": "^7.5.10", "jsdom@^16.7.0": "patch:jsdom@npm%3A16.7.0#./.yarn/patches/jsdom-npm-16.7.0-216c5c4bf9.patch", "trim": "^0.0.3", "@eslint/eslintrc@npm:^2.1.4": "patch:@eslint/eslintrc@npm%3A2.1.4#~/.yarn/patches/@eslint-eslintrc-npm-2.1.4-1ff4b5f908.patch", diff --git a/yarn.lock b/yarn.lock index 8b513f4b5d76..82e56c6428e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35711,9 +35711,9 @@ __metadata: languageName: node linkType: hard -"ws@npm:*, ws@npm:>=8.14.2, ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": - version: 8.16.0 - resolution: "ws@npm:8.16.0" +"ws@npm:*, ws@npm:>=8.14.2, ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": + version: 8.17.1 + resolution: "ws@npm:8.17.1" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -35722,52 +35722,22 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10/7c511c59e979bd37b63c3aea4a8e4d4163204f00bd5633c053b05ed67835481995f61a523b0ad2b603566f9a89b34cb4965cb9fab9649fbfebd8f740cea57f17 - languageName: node - linkType: hard - -"ws@npm:7.4.6": - version: 7.4.6 - resolution: "ws@npm:7.4.6" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10/150e3f917b7cde568d833a5ea6ccc4132e59c38d04218afcf2b6c7b845752bd011a9e0dc1303c8694d3c402a0bdec5893661a390b71ff88f0fc81a4e4e66b09c - languageName: node - linkType: hard - -"ws@npm:8.13.0": - version: 8.13.0 - resolution: "ws@npm:8.13.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10/1769532b6fdab9ff659f0b17810e7501831d34ecca23fd179ee64091dd93a51f42c59f6c7bb4c7a384b6c229aca8076fb312aa35626257c18081511ef62a161d + checksum: 10/4264ae92c0b3e59c7e309001e93079b26937aab181835fb7af79f906b22cd33b6196d96556dafb4e985742dd401e99139572242e9847661fdbc96556b9e6902d languageName: node linkType: hard "ws@npm:^6.1.0": - version: 6.2.2 - resolution: "ws@npm:6.2.2" + version: 6.2.3 + resolution: "ws@npm:6.2.3" dependencies: async-limiter: "npm:~1.0.0" - checksum: 10/bb791ac02ad7e59fd4208cc6dd3a5bf7a67dff4611a128ed33365996f9fc24fa0d699043559f1798b4bc8045639fd21a1fd3ceca81de560124444abd8e321afc + checksum: 10/19f8d1608317f4c98f63da6eebaa85260a6fe1ba459cbfedd83ebe436368177fb1e2944761e2392c6b7321cbb7a375c8a81f9e1be35d555b6b4647eb61eadd46 languageName: node linkType: hard -"ws@npm:^7, ws@npm:^7.2.0, ws@npm:^7.4.5, ws@npm:^7.4.6, ws@npm:^7.5.0": - version: 7.5.9 - resolution: "ws@npm:7.5.9" +"ws@npm:^7, ws@npm:^7.2.0, ws@npm:^7.4.5, ws@npm:^7.4.6, ws@npm:^7.5.0, ws@npm:^7.5.10": + version: 7.5.10 + resolution: "ws@npm:7.5.10" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -35776,7 +35746,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10/171e35012934bd8788150a7f46f963e50bac43a4dc524ee714c20f258693ac4d3ba2abadb00838fdac42a47af9e958c7ae7e6f4bc56db047ba897b8a2268cf7c + checksum: 10/9c796b84ba80ffc2c2adcdfc9c8e9a219ba99caa435c9a8d45f9ac593bba325563b3f83edc5eb067cc6d21b9a6bf2c930adf76dd40af5f58a5ca6859e81858f0 languageName: node linkType: hard From 3820f018f2c7bec4646530b5e50364b35bcc92f1 Mon Sep 17 00:00:00 2001 From: Corey Janssen <107953793+coreyjanssen@users.noreply.github.com> Date: Tue, 18 Jun 2024 02:02:28 -0700 Subject: [PATCH 60/61] fix: typo in proposed nickname settings (#23562) Deleting an extraneous "the" in the settings description for proposed nicknames. Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com> Co-authored-by: Howard Braham <howrad@gmail.com> --- app/_locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 4d251becd20a..2363bc51dc2d 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1775,7 +1775,7 @@ "message": "Proposed nicknames" }, "externalNameSourcesSettingDescription": { - "message": "We’ll fetch proposed nicknames for addresses you interact with from third-party sources like Etherscan, Infura, and Lens Protocol. These sources will be able to see the those addresses and your IP address. Your account address won’t be exposed to third parties." + "message": "We’ll fetch proposed nicknames for addresses you interact with from third-party sources like Etherscan, Infura, and Lens Protocol. These sources will be able to see those addresses and your IP address. Your account address won’t be exposed to third parties." }, "failed": { "message": "Failed" From ed0617634417df97905849f990300bcf4a6ed75f Mon Sep 17 00:00:00 2001 From: Matteo Scurati <matteo.scurati@gmail.com> Date: Tue, 18 Jun 2024 11:38:03 +0200 Subject: [PATCH 61/61] fix: display the correct symbol of a native currency (#25364) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR fixes a small bug in the display of certain types of notifications. Specifically, in the case of receiving or sending notifications of native currencies, the symbol of the native currency is now correctly displayed. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25364?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="387" alt="Screenshot 2024-06-17 at 11 16 01" src="https://github.com/MetaMask/metamask-extension/assets/1284304/5f66746e-7b32-45a3-899a-672ef65db44e"> ### **After** <img width="443" alt="Screenshot 2024-06-17 at 11 43 31" src="https://github.com/MetaMask/metamask-extension/assets/1284304/686351cd-7940-499b-9e42-f626fe705677"> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../eth-sent-received/eth-sent-received.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/pages/notifications/notification-components/eth-sent-received/eth-sent-received.tsx b/ui/pages/notifications/notification-components/eth-sent-received/eth-sent-received.tsx index 5b44e42f7112..ec857b45da94 100644 --- a/ui/pages/notifications/notification-components/eth-sent-received/eth-sent-received.tsx +++ b/ui/pages/notifications/notification-components/eth-sent-received/eth-sent-received.tsx @@ -63,8 +63,8 @@ const getTitle = (n: ETHNotification) => { }; const getDescription = (n: ETHNotification) => { - const { nativeCurrencyName } = getNativeCurrency(n); - const items = createTextItems([nativeCurrencyName], TextVariant.bodyMd); + const { nativeCurrencySymbol } = getNativeCurrency(n); + const items = createTextItems([nativeCurrencySymbol], TextVariant.bodyMd); return items; };