Commit 011d3669 authored by tom's avatar tom

Merge branch 'main' of github.com:blockscout/frontend into chakra-v3

parents 2750d34d 07388c62
......@@ -21,6 +21,7 @@ on:
- eth_sepolia
- eth_goerli
- filecoin
- immutable
- neon_devnet
- optimism
- optimism_celestia
......
......@@ -21,6 +21,7 @@ on:
- eth_sepolia
- eth_goerli
- filecoin
- immutable
- mekong
- neon_devnet
- optimism
......
......@@ -50,5 +50,27 @@ jobs:
test:
name: Run tests
needs: deploy_e2e
uses: blockscout/blockscout-ci-cd/.github/workflows/e2e_new.yaml@master
secrets: inherit
\ No newline at end of file
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: Get Vault credentials
id: retrieve-vault-secrets
uses: hashicorp/vault-action@v2.4.1
with:
url: https://vault.k8s.blockscout.com
role: ci-dev
path: github-jwt
method: jwt
tlsSkipVerify: false
exportToken: true
secrets: |
ci/data/dev/github token | WORKFLOW_TRIGGER_TOKEN ;
- name: Trigger tests
uses: convictional/trigger-workflow-and-wait@v1.6.1
with:
owner: blockscout
repo: blockscout-ci-cd
github_token: ${{ env.WORKFLOW_TRIGGER_TOKEN }}
workflow_file_name: e2e_new.yaml
ref: master
wait_interval: 30
......@@ -366,6 +366,7 @@
"celo_alfajores",
"garnet",
"gnosis",
"immutable",
"eth",
"eth_goerli",
"eth_sepolia",
......@@ -374,6 +375,7 @@
"neon_devnet",
"optimism",
"optimism_celestia",
"optimism_interop_0",
"optimism_sepolia",
"polygon",
"rari_testnet",
......
......@@ -35,6 +35,7 @@ const config: Feature<{
type: RollupType;
homepage: { showLatestBlocks: boolean };
outputRootsEnabled: boolean;
interopEnabled: boolean;
L2WithdrawalUrl: string | undefined;
parentChain: ParentChain;
DA: {
......@@ -50,6 +51,7 @@ const config: Feature<{
type,
L2WithdrawalUrl: type === 'optimistic' ? L2WithdrawalUrl : undefined,
outputRootsEnabled: type === 'optimistic' && getEnvValue('NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED') === 'true',
interopEnabled: type === 'optimistic' && getEnvValue('NEXT_PUBLIC_INTEROP_ENABLED') === 'true',
homepage: {
showLatestBlocks: getEnvValue('NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS') === 'true',
},
......
# Set of ENVs for Immutable network explorer
# https://explorer.immutable.com
# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=immutable"
# Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http
NEXT_PUBLIC_APP_HOST=localhost
NEXT_PUBLIC_APP_PORT=3000
NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
# Instance ENVs
NEXT_PUBLIC_AD_BANNER_PROVIDER=none
NEXT_PUBLIC_AD_TEXT_PROVIDER=none
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_API_BASE_PATH=/
NEXT_PUBLIC_API_HOST=immutable-mainnet.blockscout.com
NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_DEX_POOLS_ENABLED=true
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/immutable-mainnet.json
NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/immutable.json
NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x6166cece570f4731ccc94c2d17d854ce88496cd3b48e03b537959992ab6685c8
NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
NEXT_PUBLIC_HELIA_VERIFIED_FETCH_ENABLED=false
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['no-repeat center/100% 100% url(https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-skins/immutable.jpg)'],'text_color':['rgba(19, 19, 19, 1)']}
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_LOGOUT_URL=https://blockscout-immutable.us.auth0.com/v2/logout
NEXT_PUBLIC_MARKETPLACE_ENABLED=false
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=IMX
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=IMX
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/immutable-zkevm/pools'}}]
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/immutable-short.svg
NEXT_PUBLIC_NETWORK_ID=13371
NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/immutable.svg
NEXT_PUBLIC_NETWORK_NAME=Immutable
NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.immutable.com/
NEXT_PUBLIC_NETWORK_SHORT_NAME=Immutable
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/immutable.png
NEXT_PUBLIC_STATS_API_HOST=https://stats-immutable-mainnet.k8s.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=["miner"]
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'Rarible','collection_url':'https://rarible.com/collection/immutablex/{hash}/items','instance_url':'https://rarible.com/token/immutablex/{hash}:{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/rarible.png'}]
NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
# Set of ENVs for OP Interop Alpha 0 network explorer
# https://optimism-interop-alpha-0.blockscout.com
# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=optimism_interop_0"
# Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http
NEXT_PUBLIC_APP_HOST=localhost
NEXT_PUBLIC_APP_PORT=3000
NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
# Instance ENVs
NEXT_PUBLIC_AD_BANNER_PROVIDER=none
NEXT_PUBLIC_AD_TEXT_PROVIDER=none
NEXT_PUBLIC_API_BASE_PATH=/
NEXT_PUBLIC_API_HOST=optimism-interop-alpha-0.blockscout.com
NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
NEXT_PUBLIC_FAULT_PROOF_ENABLED=true
NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/optimism.json
NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(90deg, rgb(232, 52, 53) 0%, rgb(139, 28, 232) 100%)'],'text_color':['rgb(255, 255, 255)']}
NEXT_PUBLIC_INTEROP_ENABLED=true
NEXT_PUBLIC_IS_TESTNET=true
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism.svg
NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism.svg
NEXT_PUBLIC_NETWORK_ID=420120000
NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism.svg
NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism.svg
NEXT_PUBLIC_NETWORK_NAME=OP Interop Alpha 0
NEXT_PUBLIC_NETWORK_RPC_URL=https://interop-alpha-0.optimism.io
NEXT_PUBLIC_NETWORK_SHORT_NAME=OP Interop Alpha 0
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth-sepolia.blockscout.com/
NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://bridge.interop-alpha-0.optimism.io
NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED=false
NEXT_PUBLIC_ROLLUP_TYPE=optimistic
NEXT_PUBLIC_STATS_API_HOST=https://stats-optimism-interop-devnet-0.k8s-prod-1.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_WEB3_WALLETS=['token_pocket', 'metamask']
\ No newline at end of file
......@@ -346,6 +346,17 @@ const rollupSchema = yup
value => value === undefined,
),
}),
NEXT_PUBLIC_INTEROP_ENABLED: yup
.boolean()
.when('NEXT_PUBLIC_ROLLUP_TYPE', {
is: 'optimistic',
then: (schema) => schema,
otherwise: (schema) => schema.test(
'not-exist',
'NEXT_PUBLIC_INTEROP_ENABLED can only be used if NEXT_PUBLIC_ROLLUP_TYPE is set to \'optimistic\' ',
value => value === undefined,
),
}),
NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME: yup
.string()
.when('NEXT_PUBLIC_ROLLUP_TYPE', {
......
......@@ -5,3 +5,4 @@ NEXT_PUBLIC_FAULT_PROOF_ENABLED=true
NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS=true
NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED=false
NEXT_PUBLIC_ROLLUP_PARENT_CHAIN={'baseUrl':'https://explorer.duckchain.io'}
NEXT_PUBLIC_INTEROP_ENABLED=true
\ No newline at end of file
......@@ -114,6 +114,11 @@ module.exports = {
return null;
}
break;
case '/interop-messages':
if (process.env.NEXT_PUBLIC_INTEROP_ENABLED !== 'true') {
return null;
}
break;
case '/pools':
if (process.env.NEXT_PUBLIC_DEX_POOLS_ENABLED !== 'true') {
return null;
......
......@@ -2,11 +2,16 @@
The app instance can be customized by passing the following variables to the Node.js environment at runtime. Some of these variables have been deprecated, and their full list can be found in the [file](./DEPRECATED_ENVS.md).
**IMPORTANT NOTE!** For _production_ build purposes all json-like values should be single-quoted. If it contains a hash (`#`) or a dollar-sign (`$`) the whole value should be wrapped in single quotes as well (see `dotenv` [readme](https://github.com/bkeepers/dotenv#variable-substitution) for the reference)
## Read before you run the app
## Disclaimer about using variables
### Variables compulsoriness
Please note that in the tables below, the "Compulsoriness" column indicates whether the variable is required for starting up the application, except for the "App Features" section. All features are optional by definition; therefore, the "Compulsoriness" column indicates whether a certain variable is required or optional only within the context of that feature, not for the entire application.
Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will be exposed to the browser. So any user can obtain its values. Make sure that for all 3rd-party services keys (e.g., Sentri, Auth0, WalletConnect, etc.) in the services administration panel you have created a whitelist of allowed origins and have added your app domain into it. That will help you prevent using your key by unauthorized app, if someone gets its value.
### Disclaimer about using variables
Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will be exposed to the browser. So any user can obtain its values. Make sure that for all 3rd-party services keys (e.g., Auth0, WalletConnect, etc.) in the services administration panel you have created a whitelist of allowed origins and have added your app domain into it. That will help you prevent using your key by unauthorized app, if someone gets its value.
### Note about escaping variables values
All json-like values should be single-quoted. If it contains a hash (`#`) or a dollar-sign (`$`) the whole value should be wrapped in single quotes as well (see `dotenv` [readme](https://github.com/bkeepers/dotenv#variable-substitution) for the reference)
&nbsp;
......@@ -351,7 +356,7 @@ Settings for meta tags, OG tags and SEO
## App features
*Note* The variables which are marked as required should be passed as described in order to enable the particular feature, but they are not required in the whole app context.
*Note* The variables which are marked as required should be passed as described in order to enable the particular feature, but they are not required in the entire app context.
### My account
......@@ -461,6 +466,7 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi
| NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL | `string` | URL for L2 -> L1 withdrawals (Optimistic stack only) | Required for `optimistic` rollups | - | `https://app.optimism.io/bridge/withdraw` | v1.24.0+ |
| NEXT_PUBLIC_FAULT_PROOF_ENABLED | `boolean` | Set to `true` for chains with fault proof system enabled (Optimistic stack only) | - | - | `true` | v1.31.0+ |
| NEXT_PUBLIC_HAS_MUD_FRAMEWORK | `boolean` | Set to `true` for instances that use MUD framework (Optimistic stack only) | - | - | `true` | v1.33.0+ |
| NEXT_PUBLIC_INTEROP_ENABLED | `boolean` | Enables "Interop messages" page (Optimistic stack only) | - | `false` | `true` | v1.39.0+ |
| NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS | `boolean` | Set to `true` to display "Latest blocks" widget instead of "Latest batches" on the home page | - | - | `true` | v1.36.0+ |
| NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED | `boolean` | Enables "Output roots" page (Optimistic stack only) | - | `false` | `true` | v1.37.0+ |
| NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME | `string` | Set to customize L1 transaction status labels in the UI (e.g., "Sent to <chain-name>"). This setting is applicable only for Arbitrum-based chains. **DEPRECATED** _Use `NEXT_PUBLIC_ROLLUP_PARENT_CHAIN` instead_ | - | - | `DuckChain` | v1.37.0+ |
......
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 30 30">
<path fill="currentColor" fill-rule="evenodd" d="M8.455 6c.602 0 1.09.488 1.09 1.09v.864a6 6 0 0 0 10.91 0v-.863a1.091 1.091 0 0 1 2.181 0v.65a7.1 7.1 0 0 0 2.551 1.596 1.09 1.09 0 0 1-.738 2.053 9.3 9.3 0 0 1-1.813-.885v6.404h3.273a1.09 1.09 0 1 1 0 2.182h-3.273v3.273a1.09 1.09 0 0 1-2.181 0V19.09H9.545v3.273a1.09 1.09 0 1 1-2.181 0V19.09H4.09a1.09 1.09 0 1 1 0-2.182h3.273v-6.404a9.3 9.3 0 0 1-1.813.885 1.09 1.09 0 0 1-.738-2.053 7.1 7.1 0 0 0 2.55-1.596v-.65A1.094 1.094 0 0 1 8.456 6m7.636 10.91h4.363v-5.357a8.17 8.17 0 0 1-4.363 2.01zm-2.182-3.347v3.346H9.545v-5.356a8.18 8.18 0 0 0 4.364 2.01" clip-rule="evenodd"/>
</svg>
......@@ -82,6 +82,7 @@ import type {
} from 'types/api/ens';
import type { IndexingStatus } from 'types/api/indexingStatus';
import type { InternalTransactionsResponse } from 'types/api/internalTransaction';
import type { InteropMessageListResponse } from 'types/api/interop';
import type { LogsResponseTx, LogsResponseAddress } from 'types/api/log';
import type { MudWorldsResponse } from 'types/api/mudWorlds';
import type { NovesAccountHistoryResponse, NovesDescribeTxsResponse, NovesResponseData } from 'types/api/noves';
......@@ -1243,6 +1244,15 @@ export const RESOURCES = {
block_countdown: {
path: '/api',
},
// INTEROP
optimistic_l2_interop_messages: {
path: '/api/v2/optimism/interop/messages',
filterFields: [],
},
optimistic_l2_interop_messages_count: {
path: '/api/v2/optimism/interop/messages/count',
},
};
export type ResourceName = keyof typeof RESOURCES;
......@@ -1296,7 +1306,7 @@ export type PaginatedResources = 'blocks' | 'block_txs' | 'block_election_reward
'watchlist' | 'private_tags_address' | 'private_tags_tx' |
'domains_lookup' | 'addresses_lookup' | 'user_ops' | 'validators_stability' | 'validators_blackfort' | 'validators_zilliqa' | 'noves_address_history' |
'token_transfers_all' | 'scroll_l2_txn_batches' | 'scroll_l2_txn_batch_txs' | 'scroll_l2_txn_batch_blocks' |
'scroll_l2_deposits' | 'scroll_l2_withdrawals' | 'advanced_filter' | 'pools';
'scroll_l2_deposits' | 'scroll_l2_withdrawals' | 'advanced_filter' | 'pools' | 'optimistic_l2_interop_messages';
export type PaginatedResponse<Q extends PaginatedResources> = ResourcePayload<Q>;
......@@ -1473,6 +1483,8 @@ Q extends 'optimistic_l2_output_roots_count' ? number :
Q extends 'optimistic_l2_withdrawals_count' ? number :
Q extends 'optimistic_l2_deposits_count' ? number :
Q extends 'optimistic_l2_dispute_games_count' ? number :
Q extends 'optimistic_l2_interop_messages' ? InteropMessageListResponse :
Q extends 'optimistic_l2_interop_messages_count' ? number :
Q extends 'shibarium_withdrawals' ? ShibariumWithdrawalsResponse :
Q extends 'shibarium_deposits' ? ShibariumDepositsResponse :
Q extends 'shibarium_withdrawals_count' ? number :
......
......@@ -45,7 +45,7 @@ type TRewardsContext = {
openLoginModal: () => void;
closeLoginModal: () => void;
saveApiToken: (token: string | undefined) => void;
login: (refCode: string) => Promise<{ isNewUser?: boolean; invalidRefCodeError?: boolean }>;
login: (refCode: string) => Promise<{ isNewUser: boolean; reward: string | null; invalidRefCodeError?: boolean }>;
claim: () => Promise<void>;
};
......@@ -70,7 +70,7 @@ const initialState = {
openLoginModal: () => {},
closeLoginModal: () => {},
saveApiToken: () => {},
login: async() => ({}),
login: async() => ({ isNewUser: false, reward: null }),
claim: async() => {},
};
......@@ -211,10 +211,14 @@ export function RewardsContextProvider({ children }: Props) {
apiFetch('rewards_nonce') as Promise<RewardsNonceResponse>,
refCode ?
apiFetch('rewards_check_ref_code', { pathParams: { code: refCode } }) as Promise<RewardsCheckRefCodeResponse> :
Promise.resolve({ valid: true }),
Promise.resolve({ valid: true, reward: null }),
]);
if (!checkCodeResponse.valid) {
return { invalidRefCodeError: true };
return {
invalidRefCodeError: true,
isNewUser: false,
reward: null,
};
}
const message = getMessageToSign(address, nonceResponse.nonce, checkUserQuery.data?.exists, refCode);
const signature = await signMessageAsync({ message });
......@@ -229,7 +233,10 @@ export function RewardsContextProvider({ children }: Props) {
},
}) as RewardsLoginResponse;
saveApiToken(loginResponse.token);
return { isNewUser: loginResponse.created };
return {
isNewUser: loginResponse.created,
reward: checkCodeResponse.reward,
};
} catch (_error) {
errorToast(_error);
throw _error;
......
......@@ -115,6 +115,13 @@ export default function useNavItems(): ReturnType {
const rollupFeature = config.features.rollup;
const rollupInteropMessages = rollupFeature.isEnabled && rollupFeature.interopEnabled ? {
text: 'Interop messages',
nextRoute: { pathname: '/interop-messages' as const },
icon: 'interop',
isActive: pathname === '/interop-messages',
} : null;
if (rollupFeature.isEnabled && (
rollupFeature.type === 'optimistic' ||
rollupFeature.type === 'arbitrum' ||
......@@ -127,7 +134,8 @@ export default function useNavItems(): ReturnType {
internalTxs,
rollupDeposits,
rollupWithdrawals,
],
rollupInteropMessages,
].filter(Boolean),
[
blocks,
rollupTxnBatches,
......
......@@ -60,6 +60,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/advanced-filter': 'Root page',
'/pools': 'Root page',
'/pools/[hash]': 'Regular page',
'/interop-messages': 'Root page',
// service routes, added only to make typescript happy
'/login': 'Regular page',
......
......@@ -63,6 +63,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/advanced-filter': DEFAULT_TEMPLATE,
'/pools': DEFAULT_TEMPLATE,
'/pools/[hash]': DEFAULT_TEMPLATE,
'/interop-messages': DEFAULT_TEMPLATE,
// service routes, added only to make typescript happy
'/login': DEFAULT_TEMPLATE,
......
......@@ -60,6 +60,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/advanced-filter': '%network_name% advanced filter',
'/pools': '%network_name% DEX pools',
'/pools/[hash]': '%network_name% pool details',
'/interop-messages': '%network_name% interop messages',
// service routes, added only to make typescript happy
'/login': '%network_name% login',
......
......@@ -58,6 +58,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/advanced-filter': 'Advanced filter',
'/pools': 'DEX pools',
'/pools/[hash]': 'Pool details',
'/interop-messages': 'Interop messages',
// service routes, added only to make typescript happy
'/login': 'Login',
......
import type { ChainInfo, InteropMessage } from 'types/api/interop';
export const chain: ChainInfo = {
chain_id: 1,
chain_name: 'Ethereum',
chain_logo: 'https://example.com/logo.png',
instance_url: 'https://example.com',
};
export const interopMessageIn: InteropMessage = {
init_transaction_hash: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
nonce: 1,
payload: 'payload',
relay_transaction_hash: '0x62d597ebcf3e8d60096dd0363bc2f0f5e2df27ba1dacd696c51aa7c9409f3193',
sender: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
status: 'Relayed',
target: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
timestamp: '2022-10-10T14:34:30.000000Z',
init_chain: chain,
};
export const interopMessageIn1: InteropMessage = {
init_transaction_hash: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
nonce: 1,
payload: 'payload',
relay_transaction_hash: '0x62d597ebcf3e8d60096dd0363bc2f0f5e2df27ba1dacd696c51aa7c9409f3193',
sender: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
status: 'Sent',
target: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
timestamp: '2022-10-10T14:34:30.000000Z',
init_chain: null,
};
export const interopMessageOut: InteropMessage = {
init_transaction_hash: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
nonce: 1,
payload: 'payload',
relay_transaction_hash: '0x62d597ebcf3e8d60096dd0363bc2f0f5e2df27ba1dacd696c51aa7c9409f3193',
sender: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
status: 'Relayed',
target: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
timestamp: '2022-10-10T14:34:30.000000Z',
relay_chain: chain,
};
export const interopMessageOut1: InteropMessage = {
init_transaction_hash: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
nonce: 1,
payload: 'payload',
relay_transaction_hash: '0x62d597ebcf3e8d60096dd0363bc2f0f5e2df27ba1dacd696c51aa7c9409f3193',
sender: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
status: 'Failed',
target: '0x047A81aFB05D9B1f8844bf60fcA05DCCFbC584B9',
timestamp: '2022-10-10T14:34:30.000000Z',
relay_chain: null,
};
import type { TokenInfo } from 'types/api/token';
import type { TokenTransfer, TokenTransferResponse } from 'types/api/tokenTransfer';
import * as tokenInstanceMock from './tokenInstance';
export const erc20: TokenTransfer = {
from: {
hash: '0xd789a607CEac2f0E14867de4EB15b15C9FFB5859',
......@@ -86,6 +88,7 @@ export const erc721: TokenTransfer = {
},
total: {
token_id: '875879856',
token_instance: tokenInstanceMock.base,
},
transaction_hash: '0xf13bc7afe5e02b494dd2f22078381d36a4800ef94a0ccc147431db56c301e6cc',
type: 'token_transfer',
......@@ -135,6 +138,7 @@ export const erc1155A: TokenTransfer = {
token_id: '123',
value: '42',
decimals: null,
token_instance: null,
},
transaction_hash: '0x05d6589367633c032d757a69c5fb16c0e33e3994b0d9d1483f82aeee1f05d746',
type: 'token_minting',
......@@ -151,7 +155,7 @@ export const erc1155B: TokenTransfer = {
name: 'SastanaNFT',
symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY',
},
total: { token_id: '12345678', value: '100000000000000000000', decimals: null },
total: { token_id: '12345678', value: '100000000000000000000', decimals: null, token_instance: null },
};
export const erc1155C: TokenTransfer = {
......@@ -161,7 +165,7 @@ export const erc1155C: TokenTransfer = {
name: 'SastanaNFT',
symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY',
},
total: { token_id: '483200961027732618117991942553110860267520', value: '200000000000000000000', decimals: null },
total: { token_id: '483200961027732618117991942553110860267520', value: '200000000000000000000', decimals: null, token_instance: null },
};
export const erc1155D: TokenTransfer = {
......@@ -171,7 +175,7 @@ export const erc1155D: TokenTransfer = {
name: 'SastanaNFT',
symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY',
},
total: { token_id: '456', value: '42', decimals: null },
total: { token_id: '456', value: '42', decimals: null, token_instance: null },
};
export const erc404A: TokenTransfer = {
......@@ -213,6 +217,7 @@ export const erc404A: TokenTransfer = {
value: '42000000000000000000000000',
decimals: '18',
token_id: null,
token_instance: null,
},
transaction_hash: '0x05d6589367633c032d757a69c5fb16c0e33e3994b0d9d1483f82aeee1f05d746',
type: 'token_transfer',
......@@ -230,7 +235,7 @@ export const erc404B: TokenTransfer = {
name: 'SastanaNFT',
symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY',
},
total: { token_id: '4625304364899952' },
total: { token_id: '4625304364899952', token_instance: null },
};
export const mixTokens: TokenTransferResponse = {
......
......@@ -19,6 +19,7 @@ export const mintToken: TxStateChange = {
direction: 'from',
total: {
token_id: '15077554365819457090226168288698582604878106156134383525616269766016907608065',
token_instance: null,
},
},
],
......@@ -57,6 +58,7 @@ export const receiveMintedToken: TxStateChange = {
direction: 'to',
total: {
token_id: '15077554365819457090226168288698582604878106156134383525616269766016907608065',
token_instance: null,
},
},
],
......
......@@ -3,6 +3,7 @@ import type { Transaction } from 'types/api/transaction';
import * as addressMock from 'mocks/address/address';
import { publicTag, privateTag, watchlistName } from 'mocks/address/tag';
import * as interopMock from 'mocks/interop/interop';
import * as tokenTransferMock from 'mocks/tokens/tokenTransfer';
import * as decodedInputDataMock from 'mocks/txs/decodedInputData';
......@@ -423,3 +424,29 @@ export const withRecipientContract = {
...withRecipientEns,
to: addressMock.contract,
};
export const withInteropInMessage: Transaction = {
...base,
op_interop: {
init_chain: interopMock.chain,
nonce: 1,
payload: '0x',
init_transaction_hash: '0x01a8c328b0370068aaaef49c107f70901cd79adcda81e3599a88855532122e09',
sender: addressMock.hash,
status: 'Sent',
target: addressMock.hash,
},
};
export const withInteropOutMessage: Transaction = {
...base,
op_interop: {
relay_chain: interopMock.chain,
nonce: 1,
payload: '0xfa4b78b90000000000000000000000000000000000000000000000000000000005001bcfe835d1028984e9e6e7d016b77164eacbcc6cc061e9333c0b37982b504f7ea791000000000000000000000000a79b29ad7e0196c95b87f4663ded82fbf2e3add8',
relay_transaction_hash: '0x01a8c328b0370068aaaef49c107f70901cd79adcda81e3599a88855532122e09',
sender: addressMock.hash,
status: 'Sent',
target: addressMock.hash,
},
};
......@@ -380,6 +380,17 @@ export const mud: GetServerSideProps<Props> = async(context) => {
return base(context);
};
export const interopMessages: GetServerSideProps<Props> = async(context) => {
const rollupFeature = config.features.rollup;
if (!rollupFeature.isEnabled || !rollupFeature.interopEnabled) {
return {
notFound: true,
};
}
return base(context);
};
export const pools: GetServerSideProps<Props> = async(context) => {
if (!config.features.pools.isEnabled) {
return {
......
......@@ -47,6 +47,7 @@ declare module "nextjs-routes" {
| StaticRoute<"/graphiql">
| StaticRoute<"/">
| StaticRoute<"/internal-txs">
| StaticRoute<"/interop-messages">
| StaticRoute<"/login">
| StaticRoute<"/mud-worlds">
| DynamicRoute<"/name-domains/[name]", { "name": string }>
......
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import React from 'react';
import PageNextJs from 'nextjs/PageNextJs';
const InteropMessages = dynamic(() => import('ui/pages/InteropMessages'), { ssr: false });
const Page: NextPage = () => {
return (
<PageNextJs pathname="/interop-messages">
<InteropMessages/>
</PageNextJs>
);
};
export default Page;
export { interopMessages as getServerSideProps } from 'nextjs/getServerSideProps';
......@@ -97,4 +97,10 @@ export const ENVS_MAP: Record<string, Array<[string, string]>> = {
externalTxs: [
[ 'NEXT_PUBLIC_TX_EXTERNAL_TRANSACTIONS_CONFIG', '{"chain_name": "Solana", "chain_logo_url": "http://example.url", "explorer_url_template": "https://scan.io/tx/{hash}"}' ],
],
interop: [
[ 'NEXT_PUBLIC_ROLLUP_TYPE', 'optimistic' ],
[ 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL', 'https://localhost:3101' ],
[ 'NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL', 'https://localhost:3102' ],
[ 'NEXT_PUBLIC_INTEROP_ENABLED', 'true' ],
],
};
......@@ -86,6 +86,7 @@
| "integration/full"
| "integration/partial"
| "internal_txns"
| "interop"
| "key"
| "lightning_navbar"
| "lightning"
......
<svg viewBox="0 0 184 79" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.83 78.287h31.624c11.672 0 21.144-9.357 21.144-20.914V26.1c0-11.557-9.472-20.914-21.144-20.914H24.831c-11.672 0-21.144 9.357-21.144 20.914v31.272c0 11.557 9.472 20.914 21.144 20.914Z" fill="#CFE3FF" stroke="#7E94CE" stroke-width="1.125" stroke-linejoin="round"/>
<path d="M22.581 74.538h31.624c11.671 0 21.143-9.357 21.143-20.914V22.352c0-11.557-9.472-20.914-21.143-20.914H22.58c-11.672 0-21.143 9.357-21.143 20.914v31.272c0 11.557 9.471 20.914 21.143 20.914Z" fill="#fff" stroke="#7E94CE" stroke-width="1.125" stroke-linejoin="round"/>
<path d="M31.138 32.901c.143 6.487 7.717 15.4 7.717 15.4s7.662-9.333 8.028-15.4c.397-6.561-7.454-13.299-8.083-13.827-.026-.022-.054-.021-.079.001-.588.538-7.73 7.21-7.583 13.826Z" fill="#FD95AF" stroke="#F27DA2" stroke-width="2.143"/>
<path d="M52.963 43.002c3.149-6.104.29-17.6.29-17.6s-9.824 2.533-13.206 7.95c-3.653 5.85-1.66 18.191-1.49 19.197.008.04.038.058.076.047.904-.266 11.13-3.39 14.33-9.594Z" fill="#FEE231" stroke="#CCAD18" stroke-width="2.143"/>
<path d="M24.53 42.601c3.065 6.146 14.082 10.733 14.082 10.733s3.07-12.101.703-18.023c-2.562-6.403-13.087-9.628-13.926-9.876-.033-.01-.06.004-.072.037-.3.806-3.914 10.857-.786 17.129Z" fill="#7ED5EE" stroke="#3DA6C5" stroke-width="2.143"/>
<path d="M25.596 51.18c4.098 4.855 13.141 4.615 14.703 4.535a.25.25 0 0 0 .24-.248c.043-1.535.114-10.26-3.59-14.397-4.381-4.895-15.692-5.938-16.688-6.02-.041-.004-.068.023-.064.064.09.942 1.142 11.023 5.4 16.067Z" fill="#68AE19" stroke="#005225" stroke-width="2.143"/>
<path d="M42.49 40.333c-4.238 4.387-4.51 14.055-4.526 15.274a.127.127 0 0 0 .124.13c1.175.032 10.265.126 14.606-4.155 4.68-4.614 5.97-15.572 6.075-16.538.004-.04-.021-.067-.062-.065-.955.04-11.618.593-16.217 5.354Z" fill="#68AE19" stroke="#005225" stroke-width="2.143"/>
<path d="M129.795 78.287h31.624c11.671 0 21.143-9.357 21.143-20.914V26.1c0-11.557-9.472-20.914-21.143-20.914h-31.624c-11.672 0-21.143 9.357-21.143 20.914v31.272c0 11.557 9.471 20.914 21.143 20.914Z" fill="#CFE3FF" stroke="#7E94CE" stroke-width="1.125" stroke-linejoin="round"/>
<path d="M127.546 74.538h31.624c11.671 0 21.143-9.357 21.143-20.914V22.352c0-11.557-9.472-20.914-21.143-20.914h-31.624c-11.672 0-21.143 9.357-21.143 20.914v31.272c0 11.557 9.471 20.914 21.143 20.914Z" fill="#fff" stroke="#7E94CE" stroke-width="1.125" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M137.981 51.029a4.626 4.626 0 0 1-4.411-3.228l-3.136-9.883h-1.927a4.629 4.629 0 0 1-4.412-3.228l-1.863-5.872h6.988l-3.686-5.553h34.921l-3.686 5.553h6.988l-1.863 5.872a4.628 4.628 0 0 1-4.411 3.228h-1.928l-3.135 9.883a4.629 4.629 0 0 1-4.412 3.228h-10.027Zm-2.368-15.81c0 1.49 1.113 2.7 2.486 2.7 1.373 0 2.486-1.21 2.486-2.7 0-1.49-1.113-2.7-2.486-2.7-1.373 0-2.486 1.21-2.486 2.7Zm14.764 0c0 1.49-1.113 2.7-2.486 2.7-1.374 0-2.487-1.21-2.487-2.7 0-1.49 1.113-2.7 2.487-2.7 1.373 0 2.486 1.21 2.486 2.7Z" fill="#004293"/>
<path d="M77.313 78.287h31.623c11.672 0 21.144-9.357 21.144-20.914V26.1c0-11.557-9.472-20.914-21.144-20.914H77.313c-11.672 0-21.144 9.357-21.144 20.914v31.272c0 11.557 9.472 20.914 21.144 20.914Z" fill="#CFE3FF" stroke="#7E94CE" stroke-width="1.125" stroke-linejoin="round"/>
<path d="M75.064 74.538h31.623c11.672 0 21.144-9.357 21.144-20.914V22.352c0-11.557-9.472-20.914-21.144-20.914H75.064c-11.672 0-21.144 9.357-21.144 20.914v31.272c0 11.557 9.472 20.914 21.144 20.914Z" fill="#fff" stroke="#7E94CE" stroke-width="1.125" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M109.285 48.52h.013v2.028a5.795 5.795 0 0 1-5.795 5.796h-3.333v-.01H81.7a1.77 1.77 0 0 1-1.768-1.774v-1.486c.007-.066.011-.134.011-.202 0-1.043-.908-1.889-2.028-1.889-1.08 0-1.964.787-2.025 1.78l-.005.002v1.672a1.833 1.833 0 1 1-3.665 0v-7.123a2.324 2.324 0 0 1-.016-.238v-4.203c0-.98.792-1.774 1.769-1.774H85.56a1.687 1.687 0 1 1 0 3.374h-1.792c-1.032.014-1.865.917-1.865 2.029 0 1.12.846 2.028 1.889 2.028h.003c.123.033 9.006.045 15.868.05v-.009h.028a1.927 1.927 0 0 0 1.924-1.808l.004-.003v-4.316c0-.8.649-1.449 1.449-1.449h4.767c.8 0 1.449.65 1.449 1.45v6.075ZM97.713 26.796a2.65 2.65 0 0 0-.126.004c-1.258-.038-12.012-.044-15.724-.044l-.05-.001c-1.025 0-1.862.8-1.924 1.809l-.003.002v4.316c0 .8-.649 1.449-1.449 1.449H73.67a1.45 1.45 0 0 1-1.449-1.45v-6.085h-.016v-2.029a5.796 5.796 0 0 1 5.796-5.796h3.333v.033h18.469c.976 0 1.768.794 1.768 1.774v1.498a1.734 1.734 0 0 0 0 .36.777.777 0 0 0 .036.213c.195.854 1.009 1.493 1.984 1.493 1.077 0 1.957-.78 2.024-1.768l.003-.001v-.05l.001-.07v-.025l-.001-.043v-1.496a1.832 1.832 0 1 1 3.665 0v7.139c.011.094.016.173.016.234v4.203a1.77 1.77 0 0 1-1.769 1.773h-4.191c-.068 0-.135-.004-.202-.011h-7.195a1.687 1.687 0 1 1 0-3.374h1.771c1.043 0 1.889-.908 1.889-2.028s-.846-2.029-1.89-2.029Z" fill="#5353D3"/>
</svg>
<svg viewBox="0 0 181 86" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M135.242 8.795a13.983 13.983 0 0 1 13.995 0L167.98 19.63a13.982 13.982 0 0 1 6.985 12.106v21.697c0 4.992-2.662 9.606-6.985 12.105l-18.743 10.834a13.983 13.983 0 0 1-13.995 0l-18.743-10.834a13.984 13.984 0 0 1-6.985-12.106V31.735c0-4.993 2.663-9.607 6.985-12.106l18.743-10.834Z" fill="url(#a)"/>
<path d="M135.978 9.477a13.483 13.483 0 0 1 13.495 0l18.743 10.834a13.483 13.483 0 0 1 6.735 11.674V53.68c0 4.815-2.567 9.264-6.735 11.674l-18.743 10.834a13.483 13.483 0 0 1-13.495 0l-18.743-10.834a13.484 13.484 0 0 1-6.736-11.674V31.985c0-4.815 2.568-9.264 6.736-11.674l18.743-10.834Z" fill="url(#b)" stroke="#6BB171" stroke-width=".999"/>
<path d="M123.015 44.668a.295.295 0 0 0-.045-.158l-.859-1.388a.3.3 0 0 0-.314-.136l-6.966 1.387a.297.297 0 0 0-.198.14l-.741 1.227a.298.298 0 0 0-.004.303l.741 1.299a.3.3 0 0 0 .261.151h7.825a.3.3 0 0 0 .3-.3v-2.525Zm2.005 4.021a.294.294 0 0 0-.083.104l-.832 1.714a.3.3 0 0 0 .018.293l.831 1.298a.3.3 0 0 0 .253.138h11.904a.3.3 0 0 0 .3-.3V48.64a.304.304 0 0 0-.043-.156l-.879-1.447a.3.3 0 0 0-.333-.134l-4.165 1.09c1.316-1.105 2.438-2.234 3.362-3.387h.001c1.192-1.503 1.796-3.14 1.796-4.907 0-1.616-.505-2.953-1.533-3.981-1.024-1.04-2.529-1.536-4.458-1.536-1.131 0-2.172.222-3.117.67h-.001c-.268.13-.611.413-.965.747-.362.342-.763.763-1.151 1.197-.771.862-1.514 1.797-1.805 2.272-.06.097-.06.22.001.316l.784 1.257a.299.299 0 0 0 .254.141h3.913a.3.3 0 0 0 .3-.3c0-.787.16-1.346.438-1.716.288-.38.671-.569 1.183-.569.538 0 .892.16 1.12.437.242.292.382.722.382 1.326 0 .779-.28 1.598-.872 2.463a14.612 14.612 0 0 1-2.231 2.533l-.002.002c-.88.816-2.092 1.863-3.639 3.142a.254.254 0 0 0-.029.028l-.117.094a55.61 55.61 0 0 1-.585.467Zm15.193-12.003-.001.001c-1.088 1.632-1.615 3.84-1.615 6.593 0 2.785.527 5.008 1.615 6.64l.001.002c1.129 1.668 2.935 2.48 5.347 2.48 2.412 0 4.211-.812 5.324-2.48 1.105-1.633 1.64-3.857 1.64-6.642 0-2.753-.536-4.962-1.64-6.594-1.113-1.668-2.912-2.48-5.324-2.48s-4.218.812-5.347 2.48Zm7.227 3.03.001.002c.326.8.499 1.98.499 3.562 0 1.065-.063 1.939-.185 2.627-.118.651-.359 1.167-.711 1.56v.001c-.306.344-.781.54-1.484.54-.699 0-1.184-.195-1.507-.54-.336-.394-.569-.91-.687-1.561-.123-.688-.185-1.562-.185-2.627 0-1.582.173-2.762.499-3.562l.001-.002c.153-.382.379-.653.677-.833.301-.182.696-.283 1.202-.283.507 0 .902.101 1.203.283.297.18.524.451.677.833Zm8.802.304-.002.002c-.62.593-.911 1.422-.911 2.44 0 1.019.291 1.847.911 2.44l.002.002c.622.582 1.416.864 2.358.864.718 0 1.348-.164 1.877-.501l-3.74 5.347a.299.299 0 0 0-.003.34l.941 1.388a.3.3 0 0 0 .249.131h2.934c.11 0 .211-.06.264-.156l6.847-12.521a.3.3 0 0 0-.006-.299l-.793-1.316a.301.301 0 0 0-.414-.1l-2.142 1.315a.306.306 0 0 0-.089.084l-2.78 3.975c.072-.306.107-.638.107-.993 0-1.019-.291-1.847-.911-2.44-.61-.584-1.4-.866-2.341-.866-.942 0-1.736.282-2.358.864Zm11.185 8.612.005.006c.097.127.17.352.17.725s-.073.599-.17.725c-.093.121-.215.184-.402.184-.204 0-.318-.066-.395-.175-.091-.128-.159-.357-.159-.734 0-.386.068-.62.156-.747.092-.118.213-.18.398-.18.18 0 .302.063.397.196Zm-9.399-6.17c0-.383.068-.618.16-.749.077-.111.191-.178.394-.178.211 0 .329.069.409.18.093.131.162.364.162.747 0 .373-.073.599-.169.725-.093.121-.215.185-.402.185-.205 0-.319-.067-.395-.176-.091-.128-.159-.357-.159-.734Zm6.678 4.461c-.62.593-.911 1.421-.911 2.44s.291 1.847.911 2.44c.61.584 1.401.866 2.342.866.941 0 1.731-.282 2.341-.866.62-.593.911-1.421.911-2.44s-.291-1.847-.911-2.44c-.61-.584-1.4-.866-2.341-.866-.941 0-1.732.282-2.342.866Z" fill="#9EDF99" stroke="#6BB171" stroke-width=".6" stroke-linejoin="round"/>
<path d="M122.126 43.185a.3.3 0 0 0-.3-.3H114a.3.3 0 0 0-.3.3v2.526a.3.3 0 0 0 .3.3h7.826a.3.3 0 0 0 .3-.3v-2.526Zm2.005 4.022a.3.3 0 0 0-.114.235v3.012a.3.3 0 0 0 .3.3h11.905a.3.3 0 0 0 .3-.3v-3.296a.3.3 0 0 0-.3-.3h-5.54c1.499-1.217 2.761-2.461 3.782-3.734l.001-.001c1.192-1.502 1.796-3.14 1.796-4.906 0-1.616-.506-2.953-1.534-3.981-1.024-1.041-2.528-1.536-4.458-1.536-1.131 0-2.171.222-3.116.67h-.002c-.941.454-1.702 1.16-2.283 2.105l-.002.004c-.571.956-.864 2.133-.896 3.514a.301.301 0 0 0 .3.307h3.913a.3.3 0 0 0 .3-.3c0-.787.159-1.346.437-1.717.288-.38.672-.568 1.183-.568.538 0 .892.16 1.121.436.242.293.382.723.382 1.327 0 .779-.281 1.598-.873 2.463a14.613 14.613 0 0 1-2.231 2.533l-.002.001c-.879.817-2.091 1.864-3.639 3.143a.376.376 0 0 0-.029.027l-.116.095-.585.467Zm15.193-12.004-.001.002c-1.088 1.632-1.616 3.84-1.616 6.593 0 2.784.527 5.008 1.616 6.64l.001.002c1.128 1.668 2.934 2.48 5.347 2.48 2.412 0 4.211-.812 5.324-2.48 1.104-1.633 1.64-3.857 1.64-6.642 0-2.754-.536-4.962-1.64-6.594-1.113-1.669-2.912-2.48-5.324-2.48-2.413 0-4.219.812-5.347 2.48Zm7.226 3.03.001.003c.326.8.5 1.98.5 3.562 0 1.065-.063 1.939-.185 2.626-.119.652-.36 1.167-.711 1.562h-.001c-.305.344-.78.54-1.483.54-.699 0-1.185-.195-1.507-.54-.336-.394-.569-.91-.688-1.561-.122-.688-.185-1.562-.185-2.627 0-1.582.174-2.762.5-3.562v-.002c.153-.382.38-.653.677-.833.301-.182.696-.283 1.203-.283.507 0 .901.101 1.202.283.298.18.525.451.677.833Zm8.803.305-.002.002c-.62.593-.911 1.421-.911 2.44s.291 1.847.911 2.44l.002.002c.621.582 1.416.864 2.357.864.941 0 1.731-.282 2.342-.866.619-.593.91-1.421.91-2.44s-.291-1.847-.91-2.44c-.611-.584-1.401-.866-2.342-.866-.941 0-1.736.282-2.357.864Zm11.727-.224a.302.302 0 0 0-.264-.444h-2.934c-.11 0-.211.06-.264.156l-6.847 12.521a.3.3 0 0 0 .263.444h2.935a.3.3 0 0 0 .263-.156l6.848-12.521Zm-.542 8.835h-.001l.005.007c.097.126.17.352.17.725s-.073.598-.17.725c-.092.12-.214.184-.402.184-.204 0-.318-.066-.395-.175-.09-.128-.158-.357-.158-.734 0-.387.067-.62.155-.747.092-.118.214-.18.398-.18a.45.45 0 0 1 .398.195Zm-9.399-6.169c0-.383.068-.618.159-.75.078-.11.192-.177.394-.177.211 0 .33.068.409.18.093.131.163.364.163.747 0 .373-.073.598-.17.725-.092.121-.214.184-.402.184-.204 0-.318-.066-.395-.175-.09-.128-.158-.357-.158-.734Zm6.678 4.46c-.62.594-.911 1.422-.911 2.44 0 1.02.291 1.848.911 2.44.61.585 1.4.867 2.341.867.941 0 1.732-.282 2.342-.866.62-.593.911-1.421.911-2.44s-.291-1.847-.911-2.44c-.61-.584-1.401-.866-2.342-.866-.941 0-1.731.282-2.341.866Z" fill="#fff" stroke="#6BB171" stroke-width=".6" stroke-linejoin="round"/>
<path d="M60.254 4.092H17.878c-9.112 0-16.5 7.387-16.5 16.5v43.983c0 9.112 7.388 16.5 16.5 16.5h42.376c9.112 0 16.5-7.388 16.5-16.5V20.591c0-9.112-7.388-16.5-16.5-16.5Z" fill="url(#c)" stroke="#A7BFDA" stroke-width=".999"/>
<path d="M59.791 9.25H18.34c-6.903 0-12.499 5.597-12.499 12.5v41.666c0 6.903 5.596 12.5 12.5 12.5h41.45c6.903 0 12.5-5.597 12.5-12.5V21.75c0-6.903-5.597-12.5-12.5-12.5Z" stroke="#F8FBFF" stroke-width=".999"/>
<path d="M38.725 10.5h20.726c6.351 0 11.5 5.148 11.5 11.5v41.666c0 6.351-5.149 11.5-11.5 11.5H18c-6.352 0-11.5-5.149-11.5-11.5V22c0-6.352 5.148-11.5 11.5-11.5h20.725Z" fill="url(#d)" stroke="#B967AD" stroke-width=".999"/>
<path d="M28.513 54.808a.3.3 0 0 0 .247.13h4.288a.3.3 0 0 0 .247-.471l-4.172-6.02 4.063-6.106a.3.3 0 0 0 .007-.322l-1.02-1.682a.3.3 0 0 0-.4-.109l-3.111 1.683a.3.3 0 0 0-.116.112l-1.773 3.034-2.122-3.053a.3.3 0 0 0-.246-.13h-4.289a.3.3 0 0 0-.246.472l4.073 5.883-4.886 4.513a.3.3 0 0 0-.056.37l.967 1.676a.3.3 0 0 0 .26.15h4.132a.3.3 0 0 0 .26-.15l1.772-3.053 2.121 3.073Zm23.502-17.172a.3.3 0 0 0 .3-.3v-4.467a.3.3 0 0 0-.042-.154l-1.114-1.869a.3.3 0 0 0-.301-.143l-12.793 1.869a.3.3 0 0 0-.256.27l-.98 11.347a.3.3 0 0 0 .043.182l.98 1.608a.3.3 0 0 0 .256.144h4.914a.3.3 0 0 0 .29-.225c.122-.47.371-.838.75-1.113l.007-.005c.373-.289.86-.444 1.484-.444.856 0 1.46.24 1.864.678.409.442.636 1.103.636 2.03 0 .948-.218 1.671-.623 2.2-.387.503-.982.776-1.847.776-.743 0-1.29-.185-1.676-.52a2.45 2.45 0 0 1-.77-1.382.3.3 0 0 0-.294-.243H37.87a.3.3 0 0 0-.3.314c.062 1.32.424 2.494 1.091 3.516.67 1.024 1.617 1.823 2.833 2.4l.004.001c1.218.558 2.642.831 4.264.831 2.44 0 4.373-.693 5.754-2.115l.002-.002c1.375-1.438 2.048-3.365 2.048-5.746 0-1.289-.235-2.49-.709-3.602a6.226 6.226 0 0 0-2.28-2.75c-1.034-.718-2.329-1.066-3.862-1.066-.868 0-1.68.145-2.432.438a5.302 5.302 0 0 0-1.259.678v-3.136h8.991Z" fill="#FF96C6" stroke="#B967AD" stroke-width=".6" stroke-linejoin="round"/>
<path d="M27.397 52.947a.3.3 0 0 0 .247.13h4.288a.3.3 0 0 0 .246-.472l-4.172-6.019 4.064-6.106a.3.3 0 0 0-.25-.467h-4.132a.3.3 0 0 0-.259.15l-1.773 3.033-2.121-3.054a.3.3 0 0 0-.247-.129H19a.3.3 0 0 0-.247.471l4.107 5.933-4 6.197a.3.3 0 0 0 .252.462h4.132a.3.3 0 0 0 .259-.15l1.773-3.052 2.12 3.073Zm23.502-17.173a.3.3 0 0 0 .3-.3v-4.467a.3.3 0 0 0-.3-.3H36.992a.3.3 0 0 0-.3.3v12.954a.3.3 0 0 0 .3.3h4.914a.3.3 0 0 0 .29-.224c.122-.47.37-.838.75-1.114l.007-.005c.373-.288.86-.443 1.484-.443.856 0 1.46.24 1.864.677.408.443.635 1.104.635 2.03 0 .948-.218 1.672-.623 2.2-.386.504-.982.776-1.846.776-.743 0-1.29-.184-1.677-.52a2.45 2.45 0 0 1-.769-1.381.3.3 0 0 0-.294-.243h-4.973a.3.3 0 0 0-.3.314c.062 1.319.423 2.493 1.09 3.515.67 1.024 1.618 1.823 2.833 2.4l.004.002c1.219.558 2.643.831 4.264.831 2.44 0 4.374-.693 5.755-2.116l.001-.001c1.375-1.438 2.049-3.365 2.049-5.747 0-1.288-.236-2.49-.71-3.602a6.226 6.226 0 0 0-2.28-2.75c-1.034-.717-2.328-1.065-3.862-1.065-.868 0-1.68.145-2.431.437a5.301 5.301 0 0 0-1.26.679v-3.137H50.9Z" fill="#fff" stroke="#B967AD" stroke-width=".6" stroke-linejoin="round"/>
<path d="M163.376 4.092H121c-9.112 0-16.499 7.387-16.499 16.5v43.983c0 9.112 7.387 16.5 16.499 16.5h42.376c9.112 0 16.499-7.388 16.499-16.5V20.591c0-9.112-7.387-16.5-16.499-16.5Z" fill="url(#e)" stroke="#A7BFDA" stroke-width=".999"/>
<path d="M162.913 9.25h-41.451c-6.903 0-12.499 5.597-12.499 12.5v41.666c0 6.903 5.596 12.5 12.499 12.5h41.451c6.903 0 12.5-5.597 12.5-12.5V21.75c0-6.903-5.597-12.5-12.5-12.5Z" stroke="#F8FBFF" stroke-width=".999"/>
<path d="M141.847 10.5h20.726c6.351 0 11.5 5.148 11.5 11.5v41.666c0 6.351-5.149 11.5-11.5 11.5h-41.451c-6.352 0-11.501-5.149-11.501-11.5V22c0-6.352 5.149-11.5 11.501-11.5h20.725Z" fill="url(#f)" stroke="#6BB171" stroke-width=".999"/>
<path d="M123.015 44.667a.294.294 0 0 0-.045-.157l-.859-1.388a.3.3 0 0 0-.314-.136l-6.966 1.387a.297.297 0 0 0-.198.14l-.741 1.227a.298.298 0 0 0-.004.303l.741 1.299a.3.3 0 0 0 .261.151h7.825a.3.3 0 0 0 .3-.3v-2.526Zm2.005 4.022a.294.294 0 0 0-.083.104l-.832 1.714a.3.3 0 0 0 .018.292l.831 1.299a.3.3 0 0 0 .253.138h11.904a.3.3 0 0 0 .3-.3V48.64a.304.304 0 0 0-.043-.156l-.879-1.447a.3.3 0 0 0-.333-.134l-4.165 1.09c1.316-1.105 2.438-2.235 3.362-3.387l.001-.001c1.192-1.502 1.796-3.14 1.796-4.906 0-1.616-.505-2.953-1.533-3.981-1.024-1.041-2.529-1.536-4.458-1.536-1.131 0-2.172.222-3.117.67h-.001c-.268.13-.611.413-.965.747-.362.342-.763.763-1.151 1.197-.771.862-1.514 1.797-1.805 2.272-.06.097-.06.22.001.316l.784 1.257a.299.299 0 0 0 .254.14h3.913a.3.3 0 0 0 .3-.3c0-.786.16-1.345.438-1.716.288-.38.671-.568 1.183-.568.538 0 .892.16 1.12.436.242.293.382.723.382 1.327 0 .779-.28 1.598-.872 2.463a14.616 14.616 0 0 1-2.231 2.533l-.002.002c-.88.816-2.092 1.863-3.639 3.142a.245.245 0 0 0-.029.028l-.117.094c-.121.098-.316.254-.585.467Zm15.193-12.004-.001.002c-1.088 1.632-1.615 3.84-1.615 6.593 0 2.784.527 5.008 1.615 6.64l.001.002c1.129 1.668 2.935 2.48 5.347 2.48 2.412 0 4.211-.812 5.324-2.48 1.105-1.633 1.64-3.857 1.64-6.642 0-2.754-.536-4.962-1.64-6.594-1.113-1.669-2.912-2.48-5.324-2.48s-4.218.812-5.347 2.48Zm7.227 3.03.001.003c.326.8.499 1.98.499 3.562 0 1.065-.063 1.939-.185 2.626-.118.652-.359 1.167-.711 1.562-.306.344-.781.54-1.484.54-.699 0-1.184-.195-1.507-.54-.336-.394-.569-.91-.687-1.561-.123-.688-.185-1.562-.185-2.627 0-1.582.173-2.762.499-3.562l.001-.002c.153-.382.379-.653.677-.833.301-.182.696-.283 1.202-.283.507 0 .902.101 1.203.283.297.18.524.451.677.833Zm8.802.305-.002.002c-.62.593-.911 1.421-.911 2.44s.291 1.847.911 2.44l.002.002c.622.582 1.416.864 2.358.864.718 0 1.348-.164 1.877-.501l-3.74 5.347a.299.299 0 0 0-.003.34l.941 1.388a.3.3 0 0 0 .249.131h2.934c.11 0 .211-.06.264-.156l6.847-12.521a.3.3 0 0 0-.006-.299l-.793-1.316a.301.301 0 0 0-.414-.1l-2.142 1.315a.307.307 0 0 0-.089.084l-2.78 3.975c.072-.307.107-.638.107-.993 0-1.019-.291-1.847-.911-2.44-.61-.584-1.4-.866-2.341-.866-.942 0-1.736.282-2.358.864Zm11.185 8.611.005.007c.097.127.17.352.17.725s-.073.598-.17.725a.466.466 0 0 1-.402.184c-.204 0-.318-.066-.395-.175-.091-.128-.159-.357-.159-.734 0-.386.068-.62.156-.747.092-.118.213-.18.398-.18.18 0 .302.063.397.196Zm-9.399-6.169c0-.384.068-.618.16-.749.077-.112.191-.178.394-.178.211 0 .329.068.409.18.093.131.162.364.162.747 0 .373-.073.598-.169.725-.093.121-.215.184-.402.184-.205 0-.319-.066-.395-.175-.091-.128-.159-.357-.159-.734Zm6.678 4.46c-.62.594-.911 1.422-.911 2.44 0 1.02.291 1.848.911 2.44.61.585 1.401.867 2.342.867.941 0 1.731-.282 2.341-.866.62-.593.911-1.421.911-2.44s-.291-1.847-.911-2.44c-.61-.584-1.4-.866-2.341-.866-.941 0-1.732.282-2.342.866Z" fill="#9EDF99" stroke="#6BB171" stroke-width=".6" stroke-linejoin="round"/>
<path d="M122.126 43.185a.3.3 0 0 0-.3-.3H114a.3.3 0 0 0-.3.3v2.526a.3.3 0 0 0 .3.3h7.826a.3.3 0 0 0 .3-.3v-2.526Zm2.005 4.022a.3.3 0 0 0-.114.235v3.012a.3.3 0 0 0 .3.3h11.905a.3.3 0 0 0 .3-.3v-3.297a.3.3 0 0 0-.3-.3h-5.54c1.499-1.216 2.761-2.46 3.782-3.733l.001-.001c1.192-1.502 1.796-3.14 1.796-4.906 0-1.617-.506-2.953-1.534-3.982-1.024-1.04-2.528-1.535-4.458-1.535-1.131 0-2.171.222-3.116.67h-.002c-.941.454-1.702 1.16-2.283 2.105l-.002.004c-.571.956-.864 2.132-.896 3.514a.3.3 0 0 0 .3.307h3.913a.3.3 0 0 0 .3-.3c0-.787.159-1.346.437-1.717.288-.38.672-.568 1.183-.568.538 0 .892.16 1.121.436.242.293.382.723.382 1.327 0 .778-.281 1.598-.873 2.463a14.612 14.612 0 0 1-2.231 2.532l-.002.002c-.879.817-2.091 1.864-3.639 3.143a.377.377 0 0 0-.029.027l-.116.095-.585.467Zm15.193-12.004-.001.002c-1.088 1.632-1.616 3.84-1.616 6.593 0 2.784.527 5.008 1.616 6.64l.001.002c1.128 1.668 2.934 2.48 5.347 2.48 2.412 0 4.211-.812 5.324-2.48 1.104-1.633 1.64-3.858 1.64-6.642 0-2.754-.536-4.962-1.64-6.594-1.113-1.669-2.912-2.48-5.324-2.48-2.413 0-4.219.812-5.347 2.48Zm7.226 3.03.001.003c.326.8.5 1.98.5 3.562 0 1.065-.063 1.938-.185 2.626-.119.652-.36 1.167-.711 1.561h-.001c-.305.344-.78.54-1.483.54-.699 0-1.185-.194-1.507-.54-.336-.393-.569-.909-.688-1.56-.122-.688-.185-1.562-.185-2.627 0-1.582.174-2.762.5-3.563v-.001c.153-.382.38-.653.677-.833.301-.182.696-.283 1.203-.283.507 0 .901.101 1.202.283.298.18.525.451.677.833Zm8.803.305-.002.002c-.62.593-.911 1.421-.911 2.44s.291 1.847.911 2.44l.002.002c.621.582 1.416.864 2.357.864.941 0 1.731-.282 2.342-.866.619-.593.91-1.421.91-2.44s-.291-1.847-.91-2.44c-.611-.584-1.401-.866-2.342-.866-.941 0-1.736.282-2.357.864Zm11.727-.224a.302.302 0 0 0-.264-.444h-2.934c-.11 0-.211.06-.264.156l-6.847 12.52a.3.3 0 0 0 .263.445h2.935a.3.3 0 0 0 .263-.156l6.848-12.521Zm-.542 8.835h-.001l.005.007c.097.126.17.351.17.725 0 .373-.073.598-.17.725-.092.12-.214.184-.402.184-.204 0-.318-.066-.395-.175-.09-.128-.158-.357-.158-.734 0-.387.067-.62.155-.748.092-.118.214-.18.398-.18a.45.45 0 0 1 .398.196Zm-9.399-6.17c0-.383.068-.617.159-.748.078-.112.192-.178.394-.178.211 0 .33.068.409.18.093.131.163.364.163.747 0 .373-.073.598-.17.725-.092.12-.214.184-.402.184-.204 0-.318-.066-.395-.175-.09-.128-.158-.357-.158-.734Zm6.678 4.462c-.62.592-.911 1.421-.911 2.44s.291 1.847.911 2.44c.61.584 1.4.866 2.341.866.941 0 1.732-.282 2.342-.866.62-.593.911-1.421.911-2.44s-.291-1.848-.911-2.44c-.61-.584-1.401-.866-2.342-.866-.941 0-1.731.282-2.341.866Z" fill="#fff" stroke="#6BB171" stroke-width=".6" stroke-linejoin="round"/>
<path d="M95.99 3.608a14.19 14.19 0 0 0-14.202 0L58.353 17.154a14.19 14.19 0 0 0-7.089 12.286v27.12a14.19 14.19 0 0 0 7.089 12.286l23.435 13.546a14.19 14.19 0 0 0 14.203 0l23.435-13.546a14.191 14.191 0 0 0 7.088-12.286V29.44c0-5.067-2.702-9.75-7.088-12.286L95.991 3.608Z" fill="#ECF5FF" stroke="#A7BFDA" stroke-width=".86"/>
<path d="M88.89 2.133V43L53.534 22.564a13.75 13.75 0 0 1 5.033-5.037L82.003 3.98a13.751 13.751 0 0 1 6.886-1.847Z" fill="#F8FBFF"/>
<path d="M51.694 29.44v27.12c0 2.456.655 4.82 1.841 6.876L88.89 43 53.535 22.564a13.751 13.751 0 0 0-1.84 6.876Z" fill="url(#g)"/>
<path d="M126.084 56.571v-27.12c0-2.457-.655-4.82-1.841-6.876L88.889 43.011l35.354 20.436a13.753 13.753 0 0 0 1.841-6.876Z" fill="#E0EEFF"/>
<path d="M88.89 2.15v40.867l35.353-20.436a13.749 13.749 0 0 0-5.033-5.038L95.775 3.997A13.751 13.751 0 0 0 88.89 2.15Z" fill="url(#h)"/>
<path d="M58.565 68.472a13.751 13.751 0 0 1-5.03-5.036L88.89 43v40.867a13.75 13.75 0 0 1-6.884-1.847h-.002L58.568 68.473l-.003-.001Z" fill="url(#i)"/>
<path d="m95.775 82.02 23.435-13.547a13.749 13.749 0 0 0 5.033-5.037L88.889 43v40.867c2.378 0 4.756-.616 6.886-1.847Z" fill="#D1E5FE"/>
<path d="M82.864 8.643a12.04 12.04 0 0 1 12.05 0l20.692 11.96a12.04 12.04 0 0 1 6.015 10.424v23.946c0 4.3-2.293 8.272-6.015 10.424l-20.691 11.96a12.04 12.04 0 0 1-12.051 0l-20.692-11.96a12.04 12.04 0 0 1-6.014-10.424V31.027c0-4.3 2.292-8.272 6.014-10.424l20.692-11.96Z" fill="#A7BFDA"/>
<path d="M95.13 8.27a12.47 12.47 0 0 0-12.481 0L61.957 20.232a12.47 12.47 0 0 0-6.23 10.796v23.946a12.47 12.47 0 0 0 6.23 10.796l20.692 11.96a12.47 12.47 0 0 0 12.48 0l20.692-11.96a12.469 12.469 0 0 0 6.23-10.796V31.027c0-4.453-2.374-8.568-6.23-10.796L95.13 8.271Z" stroke="#F8FBFF" stroke-width=".86"/>
<path d="M83.08 9.015a11.61 11.61 0 0 1 11.62 0l20.691 11.96a11.61 11.61 0 0 1 5.8 10.052v23.946a11.61 11.61 0 0 1-5.8 10.051l-20.692 11.96a11.61 11.61 0 0 1-11.62 0l-20.691-11.96a11.61 11.61 0 0 1-5.8-10.051V31.027a11.61 11.61 0 0 1 5.8-10.051l20.691-11.96Z" stroke="#A7BFDA" stroke-width=".86"/>
<path d="M82.916 8.643a12.04 12.04 0 0 1 12.05 0l20.692 11.96a12.04 12.04 0 0 1 6.015 10.424v23.946c0 4.3-2.293 8.272-6.015 10.424l-20.692 11.96a12.04 12.04 0 0 1-12.05 0l-20.692-11.96a12.04 12.04 0 0 1-6.014-10.424V31.027c0-4.3 2.292-8.272 6.014-10.424l20.692-11.96Z" fill="#FFBA0D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M56.21 50.673v4.3c0 4.3 2.292 8.272 6.014 10.424l20.692 11.96a12.04 12.04 0 0 0 12.05 0l20.692-11.96a12.04 12.04 0 0 0 6.015-10.424v-4.3c0 4.3-2.293 8.272-6.015 10.424l-20.692 11.96a12.04 12.04 0 0 1-12.05 0l-20.692-11.96a12.04 12.04 0 0 1-6.014-10.424Z" fill="#E1910E"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M82.865 8.643a12.04 12.04 0 0 1 12.05 0l20.692 11.96a12.039 12.039 0 0 1 6.015 10.424v2.58c0-4.3-2.292-8.272-6.015-10.424l-20.691-11.96a12.04 12.04 0 0 0-12.05 0l-20.693 11.96a12.04 12.04 0 0 0-6.014 10.424v-2.58c0-4.3 2.292-8.272 6.014-10.424l20.692-11.96Z" fill="#FFD57C"/>
<path d="M83.13 9.015a11.61 11.61 0 0 1 11.621 0l20.692 11.96a11.61 11.61 0 0 1 5.8 10.052v23.946a11.61 11.61 0 0 1-5.8 10.051l-20.692 11.96a11.61 11.61 0 0 1-11.62 0l-20.692-11.96a11.61 11.61 0 0 1-5.8-10.051V31.027a11.61 11.61 0 0 1 5.8-10.051l20.692-11.96Z" stroke="#A05500" stroke-width=".86"/>
<g filter="url(#j)">
<path d="M92.115 50.74v-12.9l-1.72 1.72v9.46l1.72 1.72Z" fill="#A964FD" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M92.115 37.84h-6.45l1.72 1.72h3.01l1.72-1.72Z" fill="#A964FD" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M90.394 49.02v-9.46h-3.01v9.46h3.01Z" fill="#B77CFF" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="m87.384 44.667 3.01 3.01v-5.053l-3.01-3.01v5.053Z" fill="#DABCFF"/>
<path d="M85.665 50.74h6.45l-1.72-1.72h-3.01l-1.72 1.72Z" fill="#7A2CDA" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M85.665 37.84v12.9l1.72-1.72v-9.46l-1.72-1.72Z" fill="#7A2CDA" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M85.665 37.84h6.45m-6.45 0v12.9m0-12.9 1.72 1.72m4.73-1.72v12.9m0-12.9-1.72 1.72m1.72 11.18h-6.45m6.45 0-1.72-1.72m-4.73 1.72 1.72-1.72m3.01 0v-9.46m0 9.46h-3.01m0 0v-9.46m0 0h3.01" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
</g>
<g filter="url(#k)" stroke="#50119C" stroke-width=".86" stroke-linejoin="round">
<path d="M85.234 30.745v-6.45l-1.72 1.72v3.01l1.72 1.72Z" fill="#A964FD"/>
<path d="M85.235 24.295h-6.45l1.72 1.72h3.01l1.72-1.72Z" fill="#A964FD"/>
<path d="M83.514 29.025v-3.01h-3.01v3.01h3.01Z" fill="#B77CFF"/>
<path d="M78.785 30.745h6.45l-1.72-1.72h-3.01l-1.72 1.72Z" fill="#7A2CDA"/>
<path d="M78.785 24.295v6.45l1.72-1.72v-3.01l-1.72-1.72Z" fill="#7A2CDA"/>
<path d="M78.785 24.295h6.45m-6.45 0v6.45m0-6.45 1.72 1.72m4.73-1.72v6.45m0-6.45-1.72 1.72m1.72 4.73h-6.45m6.45 0-1.72-1.72m-4.73 1.72 1.72-1.72m3.01 0v-3.01m0 3.01h-3.01m0 0v-3.01m0 0h3.01"/>
</g>
<g filter="url(#l)" stroke="#50119C" stroke-width=".86" stroke-linejoin="round">
<path d="M99.21 30.745v-6.45l-1.72 1.72v3.01l1.72 1.72Z" fill="#A964FD"/>
<path d="M99.21 24.295h-6.45l1.72 1.72h3.01l1.72-1.72Z" fill="#A964FD"/>
<path d="M97.489 29.025v-3.01h-3.01v3.01h3.01Z" fill="#B77CFF"/>
<path d="M92.76 30.745h6.45l-1.72-1.72h-3.01l-1.72 1.72Z" fill="#7A2CDA"/>
<path d="M92.76 24.295v6.45l1.72-1.72v-3.01l-1.72-1.72Z" fill="#7A2CDA"/>
<path d="M92.76 24.295h6.45m-6.45 0v6.45m0-6.45 1.72 1.72m4.73-1.72v6.45m0-6.45-1.72 1.72m1.72 4.73h-6.45m6.45 0-1.72-1.72m-4.73 1.72 1.72-1.72m3.01 0v-3.01m0 3.01h-3.01m0 0v-3.01m0 0h3.01"/>
</g>
<g filter="url(#m)">
<path d="M78.784 57.405v-26.66l-1.72 1.72v23.22l1.72 1.72Z" fill="#A964FD" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M78.784 30.745h-6.45l1.72 1.72h3.01l1.72-1.72Z" fill="#A964FD" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M77.064 55.685v-23.22h-3.01v23.22h3.01Z" fill="#B77CFF" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="m74.055 51.641 3.01 3.01v-3.307l-3.01-3.01v3.307Zm0-4.084 3.01 3.01v-1.463l-3.01-3.01v1.463Z" fill="#DABCFF"/>
<path d="M72.335 57.405h6.45l-1.72-1.72h-3.01l-1.72 1.72Z" fill="#7A2CDA" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M72.335 30.745v26.66l1.72-1.72v-23.22l-1.72-1.72Z" fill="#7A2CDA" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M72.335 30.745h6.45m-6.45 0v26.66m0-26.66 1.72 1.72m4.73-1.72v26.66m0-26.66-1.72 1.72m1.72 24.94h-6.45m6.45 0-1.72-1.72m-4.73 1.72 1.72-1.72m3.01 0v-23.22m0 23.22h-3.01m0 0v-23.22m0 0h3.01" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
</g>
<g filter="url(#n)">
<path d="M105.659 57.405v-26.66l-1.72 1.72v23.22l1.72 1.72Z" fill="#A964FD" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M105.659 30.745h-6.45l1.72 1.72h3.01l1.72-1.72Z" fill="#A964FD" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M103.939 55.685v-23.22h-3.01v23.22h3.01Z" fill="#B77CFF" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="m100.93 41.238 3.01 3.01V40.94l-3.01-3.01v3.308Zm0-4.085 3.01 3.01V38.7l-3.01-3.01v1.463Z" fill="#DABCFF"/>
<path d="M99.21 57.405h6.449l-1.72-1.72h-3.01l-1.72 1.72Z" fill="#7A2CDA" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M99.21 30.745v26.66l1.719-1.72v-23.22l-1.72-1.72Z" fill="#7A2CDA" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
<path d="M99.21 30.745h6.449m-6.45 0v26.66m0-26.66 1.72 1.72m4.73-1.72v26.66m0-26.66-1.72 1.72m1.72 24.94h-6.45m6.45 0-1.72-1.72m-4.73 1.72 1.72-1.72m3.01 0v-23.22m0 23.22h-3.01m0 0v-23.22m0 0h3.01" stroke="#50119C" stroke-width=".86" stroke-linejoin="round"/>
</g>
<g style="mix-blend-mode:color-burn">
<mask id="o" maskUnits="userSpaceOnUse" x="48.954" y="13.265" width="23" height="61" fill="#000">
<path fill="#fff" d="M48.954 13.265h23v61h-23z"/>
<path d="M66.283 19.338c-.609 1.258-1.689 1.917-2.886 2.396-.137.08-.275.2-.334.32-.451 1.018-.883 2.076-1.315 3.074-.157.38-.275.739-.452 1.198.51-.659.962-1.218 1.414-1.757.824-.978 1.806-1.717 3.121-1.917 1.335-.22 2.67-.1 3.986.24.039.04.059.04.137.08-.334.499-.628 1.018-.942 1.477-.687.899-1.512 1.637-2.611 2.037-1.57.499-3.18.619-4.79.359-.158-.06-.295-.08-.452-.12a46.466 46.466 0 0 0-1.865 7.128c.314-.46.589-.978.864-1.438.687-1.178 1.55-2.116 2.866-2.575a9.093 9.093 0 0 1 3.082-.52c.334 0 .687.04 1.1.04-.197.48-.334.9-.491 1.298-.51 1.098-1.139 2.057-2.16 2.696-1.217.818-2.591 1.218-4.024 1.357-.452.04-.943.08-1.414.12a50.868 50.868 0 0 0-.707 7.367c.079-.08.099-.2.138-.319.157-.46.334-.938.51-1.438.55-1.437 1.473-2.535 2.867-3.194.962-.44 1.982-.699 3.023-.858.177 0 .353-.04.55-.08v.24c-.04.219-.079.498-.138.778-.334 1.437-.883 2.815-2.1 3.753-1.277 1.059-2.769 1.717-4.398 2.077-.157.02-.314.02-.51.06a40.27 40.27 0 0 0 .588 7.527c.177-.819.315-1.597.472-2.376.255-1.098.785-2.077 1.63-2.815 1.06-.899 2.296-1.478 3.592-1.957.137 0 .275-.08.49-.12-.02.719-.039 1.338-.117 1.957-.138 1.138-.452 2.176-1.178 3.035-1.237 1.437-2.729 2.535-4.516 3.154-.059 0-.117.04-.196.08.452 2.316 1.06 4.572 1.885 6.748.04-.399 0-.778.02-1.178.02-1.317.235-2.555 1.04-3.613a8.461 8.461 0 0 1 2.356-2.097c.471-.32.942-.599 1.472-.858.06.22.079.42.118.579.275 1.637.275 3.234-.55 4.712-.687 1.218-1.63 2.236-2.729 3.094-.412.32-.824.58-1.256.859.805 2.096 1.728 4.133 2.827 6.07 0-.12 0-.2-.02-.28-.058-.54-.137-1.138-.196-1.677a5.277 5.277 0 0 1 .589-2.895c.57-1.038 1.335-1.937 2.238-2.716.334-.26.668-.539 1.021-.858.49 1.178.766 2.316.805 3.474 0 .659-.04 1.318-.295 1.956a11.52 11.52 0 0 1-3.101 4.493c-.157.12-.138.2-.06.36a55.346 55.346 0 0 0 3.004 4.471s-.196.4-1.511-.459c-.314-.459-.629-.898-.923-1.397a92.016 92.016 0 0 1-1.787-2.955c-.117-.26-.235-.34-.51-.26-1.728.4-3.475.4-5.183-.08-1.217-.32-2.199-1.098-3.004-2.036-.353-.42-.667-.939-1-1.358-.02-.08-.06-.12-.099-.2l.118-.08c1.374-.459 2.787-.698 4.22-.578 1.434.08 2.592.778 3.613 1.797.236.24.451.459.726.658-.02-.08-.059-.16-.098-.24a53.484 53.484 0 0 1-2.395-5.69c-.059-.199-.137-.239-.334-.239-1.708.12-3.376-.2-4.947-.898-1.217-.54-2.061-1.478-2.71-2.616-.313-.499-.549-1.078-.843-1.697.569 0 1.08-.08 1.59-.08.981-.04 1.963.04 2.925.3 1.315.399 2.238 1.218 3.023 2.296.197.24.354.479.51.718-.49-2.136-.98-4.292-1.472-6.428-.785-.2-1.63-.36-2.414-.62-1.218-.419-2.356-1.018-3.26-1.996-.785-.858-1.59-2.735-1.688-3.893h.04c1.688.02 3.317.34 4.79 1.278.903.539 1.472 1.437 1.943 2.375.118.2.216.4.354.62-.197-2.137-.275-4.253-.118-6.39-1.06-.319-2.022-.738-2.906-1.317-1.295-.859-2.414-1.877-2.886-3.434a9.274 9.274 0 0 1-.431-2.536c-.02-.08 0-.16 0-.36.746.28 1.472.48 2.16.7.941.399 1.805.898 2.532 1.677.628.678.962 1.497 1.236 2.336.118.399.217.798.374 1.177 0-.12.02-.16.02-.279.176-2.056.45-4.093.863-6.11.04-.2.02-.359-.216-.439a9.5 9.5 0 0 1-3.868-3.434c-.687-1.058-.844-2.216-.824-3.474 0-.459.059-.898.118-1.437.589.32 1.158.559 1.649.858 1.1.64 2.061 1.418 2.69 2.536.49.858.608 1.837.687 2.815.039.3.039.619.117.898l.06-.24c.51-2.056 1.118-4.132 1.904-6.128.078-.2.078-.32-.099-.42-1.354-.978-2.375-2.216-3.121-3.753-.589-1.218-.589-2.456-.334-3.714.079-.46.197-.878.314-1.338l.04-.04c.863.54 1.668 1.159 2.355 1.937 1.06 1.138 1.63 2.456 1.512 4.093-.04.579-.098 1.218-.137 1.917.039-.08.059-.12.078-.2.432-.898.864-1.797 1.296-2.715.04-.12.04-.24.04-.36-.04-.818-.02-1.637.196-2.455.157-.62.392-1.258.844-1.717.53-.58 1.158-1.019 1.826-1.398.353-.24.706-.4 1.08-.579.058 0 .097.04.156.04-.02.3-.078.579-.098.878-.04 1.099-.294 2.197-.785 3.155Z"/>
</mask>
<path d="M66.283 19.338c-.609 1.258-1.689 1.917-2.886 2.396-.137.08-.275.2-.334.32-.451 1.018-.883 2.076-1.315 3.074-.157.38-.275.739-.452 1.198.51-.659.962-1.218 1.414-1.757.824-.978 1.806-1.717 3.121-1.917 1.335-.22 2.67-.1 3.986.24.039.04.059.04.137.08-.334.499-.628 1.018-.942 1.477-.687.899-1.512 1.637-2.611 2.037-1.57.499-3.18.619-4.79.359-.158-.06-.295-.08-.452-.12a46.466 46.466 0 0 0-1.865 7.128c.314-.46.589-.978.864-1.438.687-1.178 1.55-2.116 2.866-2.575a9.093 9.093 0 0 1 3.082-.52c.334 0 .687.04 1.1.04-.197.48-.334.9-.491 1.298-.51 1.098-1.139 2.057-2.16 2.696-1.217.818-2.591 1.218-4.024 1.357-.452.04-.943.08-1.414.12a50.868 50.868 0 0 0-.707 7.367c.079-.08.099-.2.138-.319.157-.46.334-.938.51-1.438.55-1.437 1.473-2.535 2.867-3.194.962-.44 1.982-.699 3.023-.858.177 0 .353-.04.55-.08v.24c-.04.219-.079.498-.138.778-.334 1.437-.883 2.815-2.1 3.753-1.277 1.059-2.769 1.717-4.398 2.077-.157.02-.314.02-.51.06a40.27 40.27 0 0 0 .588 7.527c.177-.819.315-1.597.472-2.376.255-1.098.785-2.077 1.63-2.815 1.06-.899 2.296-1.478 3.592-1.957.137 0 .275-.08.49-.12-.02.719-.039 1.338-.117 1.957-.138 1.138-.452 2.176-1.178 3.035-1.237 1.437-2.729 2.535-4.516 3.154-.059 0-.117.04-.196.08.452 2.316 1.06 4.572 1.885 6.748.04-.399 0-.778.02-1.178.02-1.317.235-2.555 1.04-3.613a8.461 8.461 0 0 1 2.356-2.097c.471-.32.942-.599 1.472-.858.06.22.079.42.118.579.275 1.637.275 3.234-.55 4.712-.687 1.218-1.63 2.236-2.729 3.094-.412.32-.824.58-1.256.859.805 2.096 1.728 4.133 2.827 6.07 0-.12 0-.2-.02-.28-.058-.54-.137-1.138-.196-1.677a5.277 5.277 0 0 1 .589-2.895c.57-1.038 1.335-1.937 2.238-2.716.334-.26.668-.539 1.021-.858.49 1.178.766 2.316.805 3.474 0 .659-.04 1.318-.295 1.956a11.52 11.52 0 0 1-3.101 4.493c-.157.12-.138.2-.06.36a55.346 55.346 0 0 0 3.004 4.471s-.196.4-1.511-.459c-.314-.459-.629-.898-.923-1.397a92.016 92.016 0 0 1-1.787-2.955c-.117-.26-.235-.34-.51-.26-1.728.4-3.475.4-5.183-.08-1.217-.32-2.199-1.098-3.004-2.036-.353-.42-.667-.939-1-1.358-.02-.08-.06-.12-.099-.2l.118-.08c1.374-.459 2.787-.698 4.22-.578 1.434.08 2.592.778 3.613 1.797.236.24.451.459.726.658-.02-.08-.059-.16-.098-.24a53.484 53.484 0 0 1-2.395-5.69c-.059-.199-.137-.239-.334-.239-1.708.12-3.376-.2-4.947-.898-1.217-.54-2.061-1.478-2.71-2.616-.313-.499-.549-1.078-.843-1.697.569 0 1.08-.08 1.59-.08.981-.04 1.963.04 2.925.3 1.315.399 2.238 1.218 3.023 2.296.197.24.354.479.51.718-.49-2.136-.98-4.292-1.472-6.428-.785-.2-1.63-.36-2.414-.62-1.218-.419-2.356-1.018-3.26-1.996-.785-.858-1.59-2.735-1.688-3.893h.04c1.688.02 3.317.34 4.79 1.278.903.539 1.472 1.437 1.943 2.375.118.2.216.4.354.62-.197-2.137-.275-4.253-.118-6.39-1.06-.319-2.022-.738-2.906-1.317-1.295-.859-2.414-1.877-2.886-3.434a9.274 9.274 0 0 1-.431-2.536c-.02-.08 0-.16 0-.36.746.28 1.472.48 2.16.7.941.399 1.805.898 2.532 1.677.628.678.962 1.497 1.236 2.336.118.399.217.798.374 1.177 0-.12.02-.16.02-.279.176-2.056.45-4.093.863-6.11.04-.2.02-.359-.216-.439a9.5 9.5 0 0 1-3.868-3.434c-.687-1.058-.844-2.216-.824-3.474 0-.459.059-.898.118-1.437.589.32 1.158.559 1.649.858 1.1.64 2.061 1.418 2.69 2.536.49.858.608 1.837.687 2.815.039.3.039.619.117.898l.06-.24c.51-2.056 1.118-4.132 1.904-6.128.078-.2.078-.32-.099-.42-1.354-.978-2.375-2.216-3.121-3.753-.589-1.218-.589-2.456-.334-3.714.079-.46.197-.878.314-1.338l.04-.04c.863.54 1.668 1.159 2.355 1.937 1.06 1.138 1.63 2.456 1.512 4.093-.04.579-.098 1.218-.137 1.917.039-.08.059-.12.078-.2.432-.898.864-1.797 1.296-2.715.04-.12.04-.24.04-.36-.04-.818-.02-1.637.196-2.455.157-.62.392-1.258.844-1.717.53-.58 1.158-1.019 1.826-1.398.353-.24.706-.4 1.08-.579.058 0 .097.04.156.04-.02.3-.078.579-.098.878-.04 1.099-.294 2.197-.785 3.155Z" fill="#000" fill-opacity=".16"/>
<path d="M66.283 19.338c-.609 1.258-1.689 1.917-2.886 2.396-.137.08-.275.2-.334.32-.451 1.018-.883 2.076-1.315 3.074-.157.38-.275.739-.452 1.198.51-.659.962-1.218 1.414-1.757.824-.978 1.806-1.717 3.121-1.917 1.335-.22 2.67-.1 3.986.24.039.04.059.04.137.08-.334.499-.628 1.018-.942 1.477-.687.899-1.512 1.637-2.611 2.037-1.57.499-3.18.619-4.79.359-.158-.06-.295-.08-.452-.12a46.466 46.466 0 0 0-1.865 7.128c.314-.46.589-.978.864-1.438.687-1.178 1.55-2.116 2.866-2.575a9.093 9.093 0 0 1 3.082-.52c.334 0 .687.04 1.1.04-.197.48-.334.9-.491 1.298-.51 1.098-1.139 2.057-2.16 2.696-1.217.818-2.591 1.218-4.024 1.357-.452.04-.943.08-1.414.12a50.868 50.868 0 0 0-.707 7.367c.079-.08.099-.2.138-.319.157-.46.334-.938.51-1.438.55-1.437 1.473-2.535 2.867-3.194.962-.44 1.982-.699 3.023-.858.177 0 .353-.04.55-.08v.24c-.04.219-.079.498-.138.778-.334 1.437-.883 2.815-2.1 3.753-1.277 1.059-2.769 1.717-4.398 2.077-.157.02-.314.02-.51.06a40.27 40.27 0 0 0 .588 7.527c.177-.819.315-1.597.472-2.376.255-1.098.785-2.077 1.63-2.815 1.06-.899 2.296-1.478 3.592-1.957.137 0 .275-.08.49-.12-.02.719-.039 1.338-.117 1.957-.138 1.138-.452 2.176-1.178 3.035-1.237 1.437-2.729 2.535-4.516 3.154-.059 0-.117.04-.196.08.452 2.316 1.06 4.572 1.885 6.748.04-.399 0-.778.02-1.178.02-1.317.235-2.555 1.04-3.613a8.461 8.461 0 0 1 2.356-2.097c.471-.32.942-.599 1.472-.858.06.22.079.42.118.579.275 1.637.275 3.234-.55 4.712-.687 1.218-1.63 2.236-2.729 3.094-.412.32-.824.58-1.256.859.805 2.096 1.728 4.133 2.827 6.07 0-.12 0-.2-.02-.28-.058-.54-.137-1.138-.196-1.677a5.277 5.277 0 0 1 .589-2.895c.57-1.038 1.335-1.937 2.238-2.716.334-.26.668-.539 1.021-.858.49 1.178.766 2.316.805 3.474 0 .659-.04 1.318-.295 1.956a11.52 11.52 0 0 1-3.101 4.493c-.157.12-.138.2-.06.36a55.346 55.346 0 0 0 3.004 4.471s-.196.4-1.511-.459c-.314-.459-.629-.898-.923-1.397a92.016 92.016 0 0 1-1.787-2.955c-.117-.26-.235-.34-.51-.26-1.728.4-3.475.4-5.183-.08-1.217-.32-2.199-1.098-3.004-2.036-.353-.42-.667-.939-1-1.358-.02-.08-.06-.12-.099-.2l.118-.08c1.374-.459 2.787-.698 4.22-.578 1.434.08 2.592.778 3.613 1.797.236.24.451.459.726.658-.02-.08-.059-.16-.098-.24a53.484 53.484 0 0 1-2.395-5.69c-.059-.199-.137-.239-.334-.239-1.708.12-3.376-.2-4.947-.898-1.217-.54-2.061-1.478-2.71-2.616-.313-.499-.549-1.078-.843-1.697.569 0 1.08-.08 1.59-.08.981-.04 1.963.04 2.925.3 1.315.399 2.238 1.218 3.023 2.296.197.24.354.479.51.718-.49-2.136-.98-4.292-1.472-6.428-.785-.2-1.63-.36-2.414-.62-1.218-.419-2.356-1.018-3.26-1.996-.785-.858-1.59-2.735-1.688-3.893h.04c1.688.02 3.317.34 4.79 1.278.903.539 1.472 1.437 1.943 2.375.118.2.216.4.354.62-.197-2.137-.275-4.253-.118-6.39-1.06-.319-2.022-.738-2.906-1.317-1.295-.859-2.414-1.877-2.886-3.434a9.274 9.274 0 0 1-.431-2.536c-.02-.08 0-.16 0-.36.746.28 1.472.48 2.16.7.941.399 1.805.898 2.532 1.677.628.678.962 1.497 1.236 2.336.118.399.217.798.374 1.177 0-.12.02-.16.02-.279.176-2.056.45-4.093.863-6.11.04-.2.02-.359-.216-.439a9.5 9.5 0 0 1-3.868-3.434c-.687-1.058-.844-2.216-.824-3.474 0-.459.059-.898.118-1.437.589.32 1.158.559 1.649.858 1.1.64 2.061 1.418 2.69 2.536.49.858.608 1.837.687 2.815.039.3.039.619.117.898l.06-.24c.51-2.056 1.118-4.132 1.904-6.128.078-.2.078-.32-.099-.42-1.354-.978-2.375-2.216-3.121-3.753-.589-1.218-.589-2.456-.334-3.714.079-.46.197-.878.314-1.338l.04-.04c.863.54 1.668 1.159 2.355 1.937 1.06 1.138 1.63 2.456 1.512 4.093-.04.579-.098 1.218-.137 1.917.039-.08.059-.12.078-.2.432-.898.864-1.797 1.296-2.715.04-.12.04-.24.04-.36-.04-.818-.02-1.637.196-2.455.157-.62.392-1.258.844-1.717.53-.58 1.158-1.019 1.826-1.398.353-.24.706-.4 1.08-.579.058 0 .097.04.156.04-.02.3-.078.579-.098.878-.04 1.099-.294 2.197-.785 3.155Z" stroke="#000" stroke-opacity=".16" stroke-width="2.15" stroke-linejoin="round" mask="url(#o)"/>
</g>
<path d="M64.993 18.478c-.608 1.258-1.688 1.917-2.886 2.396-.137.08-.274.2-.333.32-.452 1.018-.884 2.076-1.316 3.074-.157.38-.275.739-.451 1.198.51-.659.962-1.218 1.413-1.757.825-.978 1.806-1.717 3.122-1.917 1.335-.22 2.67-.1 3.985.24.04.04.059.04.138.08-.334.499-.629 1.018-.943 1.477-.687.899-1.511 1.637-2.61 2.037a10.27 10.27 0 0 1-4.791.359c-.157-.06-.295-.08-.452-.12a46.477 46.477 0 0 0-1.865 7.128c.314-.46.59-.978.864-1.438.687-1.178 1.551-2.116 2.866-2.575a9.092 9.092 0 0 1 3.083-.52c.333 0 .687.04 1.099.04-.196.48-.334.9-.49 1.298-.511 1.099-1.14 2.057-2.16 2.696-1.218.818-2.592 1.218-4.025 1.357-.452.04-.942.08-1.413.12a50.868 50.868 0 0 0-.707 7.368c.078-.08.098-.2.137-.32.157-.46.334-.938.51-1.438.55-1.437 1.473-2.535 2.867-3.194.962-.44 1.983-.699 3.023-.858.177 0 .354-.04.55-.08v.24c-.04.219-.079.498-.137.778-.334 1.437-.884 2.815-2.101 3.753-1.276 1.059-2.768 1.718-4.398 2.077-.157.02-.314.02-.51.06a40.27 40.27 0 0 0 .589 7.527c.177-.819.314-1.598.471-2.376.255-1.098.785-2.077 1.63-2.815 1.06-.899 2.296-1.478 3.592-1.957.138 0 .275-.08.491-.12-.02.719-.04 1.338-.118 1.957-.137 1.138-.451 2.176-1.178 3.035-1.236 1.437-2.729 2.535-4.515 3.154-.059 0-.118.04-.196.08.451 2.316 1.06 4.572 1.884 6.748.04-.399 0-.778.02-1.178.02-1.317.236-2.555 1.04-3.613a8.461 8.461 0 0 1 2.356-2.097 11.9 11.9 0 0 1 1.473-.858c.059.22.078.42.118.579.274 1.637.274 3.234-.55 4.712-.687 1.218-1.63 2.236-2.73 3.094-.411.32-.824.58-1.256.859.805 2.096 1.728 4.133 2.828 6.07 0-.12 0-.2-.02-.28-.06-.54-.138-1.138-.197-1.677a5.277 5.277 0 0 1 .59-2.895c.569-1.038 1.335-1.937 2.238-2.716.333-.26.667-.539 1.02-.858.491 1.178.766 2.316.805 3.474 0 .659-.039 1.318-.294 1.956a11.52 11.52 0 0 1-3.102 4.493c-.157.12-.137.2-.059.36a55.327 55.327 0 0 0 3.004 4.471s-.197.4-1.512-.459c-.314-.459-.628-.898-.923-1.397a90.378 90.378 0 0 1-1.786-2.955c-.118-.26-.236-.34-.51-.26-1.728.4-3.476.4-5.184-.08-1.217-.32-2.198-1.098-3.003-2.036-.354-.42-.668-.939-1.001-1.358-.02-.08-.06-.12-.099-.2l.118-.08c1.375-.459 2.788-.698 4.221-.578 1.433.08 2.592.778 3.612 1.797.236.24.452.459.727.658-.02-.08-.059-.16-.098-.24a53.463 53.463 0 0 1-2.395-5.69c-.06-.199-.138-.239-.334-.239-1.708.12-3.377-.2-4.947-.898-1.218-.54-2.062-1.478-2.71-2.616-.314-.499-.55-1.078-.844-1.697.57 0 1.08-.08 1.59-.08.982-.04 1.964.04 2.925.3 1.316.399 2.238 1.218 3.024 2.296.196.24.353.479.51.718-.49-2.136-.981-4.292-1.472-6.428-.785-.2-1.63-.36-2.415-.62-1.217-.419-2.356-1.018-3.259-1.996-.785-.858-1.59-2.735-1.688-3.893h.039c1.688.02 3.318.34 4.79 1.278.903.539 1.473 1.437 1.944 2.376.118.2.216.399.353.618-.196-2.136-.275-4.252-.117-6.388-1.06-.32-2.023-.74-2.906-1.318-1.296-.859-2.415-1.877-2.886-3.434a9.27 9.27 0 0 1-.432-2.536c-.02-.08 0-.16 0-.36.746.28 1.472.48 2.16.7.942.399 1.806.898 2.532 1.677.628.678.962 1.497 1.237 2.336.118.399.216.798.373 1.177 0-.12.02-.16.02-.279a53.12 53.12 0 0 1 .863-6.11c.04-.2.02-.359-.215-.439a9.502 9.502 0 0 1-3.868-3.434c-.687-1.058-.844-2.216-.825-3.474 0-.459.06-.898.118-1.437.59.32 1.159.559 1.65.858 1.099.64 2.06 1.418 2.689 2.536.49.858.608 1.837.687 2.815.04.3.04.619.118.898l.059-.24c.51-2.056 1.119-4.132 1.904-6.128.079-.2.079-.32-.098-.42-1.355-.978-2.376-2.216-3.122-3.753-.589-1.218-.589-2.456-.333-3.714.078-.46.196-.878.314-1.338l.039-.04c.864.54 1.669 1.159 2.356 1.937 1.06 1.138 1.63 2.456 1.512 4.093-.04.58-.099 1.218-.138 1.917.04-.08.059-.12.079-.2.432-.898.864-1.797 1.295-2.715.04-.12.04-.24.04-.36-.04-.818-.02-1.637.196-2.455.157-.62.393-1.258.844-1.717.53-.58 1.158-1.019 1.826-1.398.353-.24.707-.4 1.08-.579.059 0 .098.04.157.04-.02.3-.079.579-.098.878-.04 1.099-.295 2.197-.786 3.155Z" fill="#FFD57C"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M64.647 50.047c-1.26 3.726-2.24 5.921-4.306 8.904l-.622-1.43a2.854 2.854 0 0 1-.007.07c-.07-.187-.139-.373-.206-.56l-.071-.164-.045-.164a41.59 41.59 0 0 1-1.431-5.213l-.03-.105-.015-.112a29.85 29.85 0 0 1-.086-.431l.022-.012-.16-1.127-.039.18a40.27 40.27 0 0 1-.589-7.526c.046-.01.09-.017.132-.023l.063-1.312-.022.075a.551.551 0 0 1-.114.241c.059-2.495.294-4.951.707-7.367l.045-.004.277-1.196a8.15 8.15 0 0 1-.146.222 46.474 46.474 0 0 1 1.866-7.128l.139.033c.103.023.203.045.312.087 1.61.26 3.22.14 4.79-.36 1.1-.399 1.924-1.137 2.611-2.036.165-.24.324-.497.486-.759l.046-.074c-2.923 1.732-5.053 2.57-8.135 3.108l.42-1.075c-.172.215-.348.44-.532.677.073-.19.136-.362.196-.527.085-.233.163-.448.255-.671.177-.409.354-.827.532-1.25a113.8 113.8 0 0 1 .784-1.825.726.726 0 0 1 .203-.23h-.265a257.17 257.17 0 0 1-.802 1.685 63.337 63.337 0 0 0-1.866 4.691 56.278 56.278 0 0 0-1.118 3.937l-.059.24-.005-.019c-.785 3.807-1.117 7.949-1.337 10.7l-.044.557c-.046 1.659.036 3.31.188 4.973l-.09-.149c.089.786.204 1.612.341 2.453l.721 3.147.736 3.214a70.416 70.416 0 0 0-.073-.11c.216.752.44 1.46.671 2.1.095.025.146.086.188.227.344.968.717 1.932 1.117 2.883.45 1.022.864 1.935 1.253 2.756l.025.05.058.125c.365.765.71 1.447 1.044 2.06.042.047.078.11.115.192.245.429.497.855.753 1.278.324.501.64 1.022.933 1.515l.1.161c.24.408.494.775.75 1.146l.173.252c1.316.859 1.512.46 1.512.46a55.325 55.325 0 0 1-3.004-4.473c-.07-.143-.093-.222.015-.323l-1.016-1.815v.002c.02.08.02.16.02.28-1.1-1.937-2.023-3.974-2.827-6.07l.14-.09c.381-.247.749-.484 1.116-.769 1.1-.858 2.042-1.877 2.729-3.094.825-1.478.825-3.075.55-4.712a3.384 3.384 0 0 1-.044-.225 8.635 8.635 0 0 0-.028-.151Zm2.019 6.741c-.755 4.362-1.306 6.716-2.54 9.8a11.522 11.522 0 0 0 3.027-4.426c.255-.638.294-1.297.294-1.956-.038-1.14-.305-2.26-.781-3.418Zm-4.635 9.679c-3.288-.513-5.542-1.555-8.849-3.39.114.152.226.312.34.473.18.258.362.518.556.749.805.938 1.786 1.717 3.004 2.036 1.63.458 3.297.478 4.949.132Zm-3.407-8.086c-2.815-1.035-4.77-2.366-8.195-5.008l.12.26c.202.44.391.853.623 1.222.648 1.138 1.492 2.077 2.71 2.616 1.507.67 3.105.992 4.742.91Zm-2.106-8.512c-2.84-1.502-4.332-3.052-6.77-6.411a13.11 13.11 0 0 0-.166-.003h-.039c.098 1.158.903 3.035 1.688 3.893.903.978 2.042 1.577 3.26 1.997.533.176 1.093.306 1.644.434l.383.09Zm-.312-8.64c-2.329-1.938-3.622-3.769-5.678-7.464a16.117 16.117 0 0 1-.189-.07l-.01.027-.006.158c-.004.075-.007.123.005.171.02.858.177 1.717.432 2.536.471 1.557 1.59 2.575 2.886 3.434.787.515 1.635.904 2.56 1.209Zm1.045-8.499c-1.973-2.34-3.042-4.092-4.542-8.194l-.013.116c-.048.432-.09.805-.09 1.193-.02 1.258.137 2.416.824 3.474a9.499 9.499 0 0 0 3.821 3.411Zm2.6-7.899.012.001c-1.854-3.366-2.53-5.368-3.279-8.884l-.054.21c-.096.37-.188.722-.253 1.102-.255 1.258-.255 2.496.334 3.714.746 1.537 1.767 2.775 3.121 3.753a.318.318 0 0 1 .119.104ZM65.839 14.8c-.983 2.306-1.84 3.829-3.644 6.038 1.163-.476 2.205-1.133 2.798-2.36.491-.958.747-2.056.786-3.155.01-.15.03-.294.049-.439l.011-.084Zm-.102 14.161c-2.762 2.514-4.66 3.892-7.419 4.969.314-.026.627-.052.923-.079 1.433-.14 2.808-.539 4.025-1.357 1.02-.64 1.649-1.598 2.16-2.696.066-.168.128-.34.193-.517l.118-.32Zm-1.53 6.738c-2.631 3.117-4.301 4.833-6.995 6.633.067-.009.131-.014.193-.019l.167-.016c1.63-.36 3.122-1.018 4.398-2.077 1.217-.938 1.767-2.316 2.1-3.753.04-.186.07-.373.098-.541l.038-.227Zm-.38 7.236c-2.143 3.5-3.571 5.613-5.66 7.776 1.724-.627 3.169-1.705 4.372-3.103.727-.859 1.041-1.897 1.178-3.035.067-.526.091-1.051.11-1.638Z" fill="#E1910E"/>
<mask id="p" maskUnits="userSpaceOnUse" x="47.665" y="12.405" width="23" height="61" fill="#000">
<path fill="#fff" d="M47.665 12.405h23v61h-23z"/>
<path d="M64.994 18.478c-.609 1.258-1.689 1.917-2.886 2.396-.137.08-.275.2-.334.32-.451 1.018-.883 2.076-1.315 3.074-.157.38-.275.739-.452 1.198.51-.659.962-1.218 1.414-1.757.824-.978 1.806-1.717 3.121-1.917 1.335-.22 2.67-.1 3.986.24.039.04.058.04.137.08-.334.499-.628 1.018-.942 1.477-.687.899-1.512 1.637-2.611 2.037-1.571.499-3.18.619-4.79.359-.158-.06-.295-.08-.452-.12a46.489 46.489 0 0 0-1.865 7.128c.314-.46.589-.978.864-1.438.687-1.178 1.55-2.116 2.866-2.575a9.092 9.092 0 0 1 3.082-.52c.334 0 .687.04 1.1.04-.197.48-.334.9-.491 1.298-.51 1.099-1.139 2.057-2.16 2.696-1.217.818-2.591 1.218-4.024 1.357-.452.04-.943.08-1.414.12a50.868 50.868 0 0 0-.707 7.368c.079-.08.098-.2.138-.32.157-.46.334-.938.51-1.438.55-1.437 1.473-2.535 2.867-3.194.961-.44 1.982-.699 3.023-.858.177 0 .353-.04.55-.08v.24c-.04.219-.079.498-.138.778-.334 1.437-.883 2.815-2.1 3.753-1.277 1.059-2.769 1.718-4.398 2.077-.157.02-.314.02-.51.06a40.27 40.27 0 0 0 .588 7.527c.177-.819.314-1.598.471-2.376.256-1.098.786-2.077 1.63-2.815 1.06-.899 2.297-1.478 3.593-1.957.137 0 .275-.08.49-.12-.02.719-.039 1.338-.117 1.957-.138 1.138-.452 2.176-1.178 3.035-1.237 1.437-2.73 2.535-4.516 3.154-.059 0-.117.04-.196.08.452 2.316 1.06 4.572 1.885 6.748.039-.399 0-.778.02-1.178.019-1.317.235-2.555 1.04-3.613a8.461 8.461 0 0 1 2.356-2.097 11.9 11.9 0 0 1 1.472-.858c.06.22.079.42.118.579.275 1.637.275 3.234-.55 4.712-.687 1.218-1.63 2.236-2.729 3.094-.412.32-.824.58-1.256.859.805 2.096 1.728 4.133 2.827 6.07 0-.12 0-.2-.02-.28-.059-.54-.137-1.138-.196-1.677a5.277 5.277 0 0 1 .589-2.895c.57-1.038 1.335-1.937 2.238-2.716.334-.26.668-.539 1.02-.858.492 1.178.767 2.316.806 3.474 0 .659-.04 1.318-.295 1.956a11.52 11.52 0 0 1-3.102 4.493c-.157.12-.137.2-.058.36a55.327 55.327 0 0 0 3.003 4.471s-.196.4-1.511-.459c-.314-.459-.629-.898-.923-1.397a90.378 90.378 0 0 1-1.787-2.955c-.117-.26-.235-.34-.51-.26-1.728.4-3.475.4-5.183-.08-1.217-.32-2.199-1.098-3.004-2.036-.353-.42-.667-.939-1-1.358-.02-.08-.06-.12-.1-.2l.119-.08c1.374-.459 2.788-.698 4.22-.578 1.434.08 2.592.778 3.613 1.797.236.24.452.459.726.658-.02-.08-.059-.16-.098-.24a53.484 53.484 0 0 1-2.395-5.69c-.059-.199-.137-.239-.334-.239-1.708.12-3.376-.2-4.947-.898-1.217-.54-2.061-1.478-2.71-2.616-.313-.499-.549-1.078-.843-1.697.569 0 1.08-.08 1.59-.08.981-.04 1.963.04 2.925.3 1.315.399 2.238 1.218 3.023 2.296.197.24.354.479.51.718-.49-2.136-.98-4.292-1.472-6.428-.785-.2-1.63-.36-2.414-.62-1.218-.419-2.356-1.018-3.26-1.996-.785-.858-1.59-2.735-1.688-3.893h.04c1.688.02 3.317.34 4.79 1.278.903.539 1.472 1.437 1.943 2.376.118.2.216.399.354.618-.197-2.136-.275-4.252-.118-6.388-1.06-.32-2.022-.74-2.906-1.318-1.295-.859-2.414-1.877-2.886-3.434a9.27 9.27 0 0 1-.431-2.536c-.02-.08 0-.16 0-.36.746.28 1.472.48 2.16.7.941.399 1.805.898 2.532 1.677.628.678.962 1.497 1.236 2.336.118.399.216.798.373 1.177 0-.12.02-.16.02-.279.177-2.056.452-4.093.864-6.11.04-.2.02-.359-.216-.439a9.503 9.503 0 0 1-3.868-3.434c-.687-1.058-.844-2.216-.824-3.474 0-.459.059-.898.118-1.437.589.32 1.158.559 1.649.858 1.1.64 2.061 1.418 2.69 2.536.49.858.608 1.837.686 2.815.04.3.04.619.118.898l.06-.24c.51-2.056 1.118-4.132 1.904-6.128.078-.2.078-.32-.099-.42-1.354-.978-2.375-2.216-3.121-3.753-.59-1.218-.59-2.456-.334-3.714.079-.46.196-.878.314-1.338l.04-.04c.863.54 1.668 1.159 2.355 1.937 1.06 1.138 1.63 2.456 1.512 4.093-.04.58-.098 1.218-.137 1.917.039-.08.059-.12.078-.2.432-.898.864-1.797 1.296-2.715.04-.12.04-.24.04-.36-.04-.818-.02-1.637.196-2.455.157-.62.392-1.258.844-1.717.53-.58 1.158-1.019 1.825-1.398.354-.24.707-.4 1.08-.579.06 0 .098.04.157.04-.02.3-.078.579-.098.878-.04 1.099-.294 2.197-.785 3.155Z"/>
</mask>
<path d="M64.994 18.478c-.609 1.258-1.689 1.917-2.886 2.396-.137.08-.275.2-.334.32-.451 1.018-.883 2.076-1.315 3.074-.157.38-.275.739-.452 1.198.51-.659.962-1.218 1.414-1.757.824-.978 1.806-1.717 3.121-1.917 1.335-.22 2.67-.1 3.986.24.039.04.058.04.137.08-.334.499-.628 1.018-.942 1.477-.687.899-1.512 1.637-2.611 2.037-1.571.499-3.18.619-4.79.359-.158-.06-.295-.08-.452-.12a46.489 46.489 0 0 0-1.865 7.128c.314-.46.589-.978.864-1.438.687-1.178 1.55-2.116 2.866-2.575a9.092 9.092 0 0 1 3.082-.52c.334 0 .687.04 1.1.04-.197.48-.334.9-.491 1.298-.51 1.099-1.139 2.057-2.16 2.696-1.217.818-2.591 1.218-4.024 1.357-.452.04-.943.08-1.414.12a50.868 50.868 0 0 0-.707 7.368c.079-.08.098-.2.138-.32.157-.46.334-.938.51-1.438.55-1.437 1.473-2.535 2.867-3.194.961-.44 1.982-.699 3.023-.858.177 0 .353-.04.55-.08v.24c-.04.219-.079.498-.138.778-.334 1.437-.883 2.815-2.1 3.753-1.277 1.059-2.769 1.718-4.398 2.077-.157.02-.314.02-.51.06a40.27 40.27 0 0 0 .588 7.527c.177-.819.314-1.598.471-2.376.256-1.098.786-2.077 1.63-2.815 1.06-.899 2.297-1.478 3.593-1.957.137 0 .275-.08.49-.12-.02.719-.039 1.338-.117 1.957-.138 1.138-.452 2.176-1.178 3.035-1.237 1.437-2.73 2.535-4.516 3.154-.059 0-.117.04-.196.08.452 2.316 1.06 4.572 1.885 6.748.039-.399 0-.778.02-1.178.019-1.317.235-2.555 1.04-3.613a8.461 8.461 0 0 1 2.356-2.097 11.9 11.9 0 0 1 1.472-.858c.06.22.079.42.118.579.275 1.637.275 3.234-.55 4.712-.687 1.218-1.63 2.236-2.729 3.094-.412.32-.824.58-1.256.859.805 2.096 1.728 4.133 2.827 6.07 0-.12 0-.2-.02-.28-.059-.54-.137-1.138-.196-1.677a5.277 5.277 0 0 1 .589-2.895c.57-1.038 1.335-1.937 2.238-2.716.334-.26.668-.539 1.02-.858.492 1.178.767 2.316.806 3.474 0 .659-.04 1.318-.295 1.956a11.52 11.52 0 0 1-3.102 4.493c-.157.12-.137.2-.058.36a55.327 55.327 0 0 0 3.003 4.471s-.196.4-1.511-.459c-.314-.459-.629-.898-.923-1.397a90.378 90.378 0 0 1-1.787-2.955c-.117-.26-.235-.34-.51-.26-1.728.4-3.475.4-5.183-.08-1.217-.32-2.199-1.098-3.004-2.036-.353-.42-.667-.939-1-1.358-.02-.08-.06-.12-.1-.2l.119-.08c1.374-.459 2.788-.698 4.22-.578 1.434.08 2.592.778 3.613 1.797.236.24.452.459.726.658-.02-.08-.059-.16-.098-.24a53.484 53.484 0 0 1-2.395-5.69c-.059-.199-.137-.239-.334-.239-1.708.12-3.376-.2-4.947-.898-1.217-.54-2.061-1.478-2.71-2.616-.313-.499-.549-1.078-.843-1.697.569 0 1.08-.08 1.59-.08.981-.04 1.963.04 2.925.3 1.315.399 2.238 1.218 3.023 2.296.197.24.354.479.51.718-.49-2.136-.98-4.292-1.472-6.428-.785-.2-1.63-.36-2.414-.62-1.218-.419-2.356-1.018-3.26-1.996-.785-.858-1.59-2.735-1.688-3.893h.04c1.688.02 3.317.34 4.79 1.278.903.539 1.472 1.437 1.943 2.376.118.2.216.399.354.618-.197-2.136-.275-4.252-.118-6.388-1.06-.32-2.022-.74-2.906-1.318-1.295-.859-2.414-1.877-2.886-3.434a9.27 9.27 0 0 1-.431-2.536c-.02-.08 0-.16 0-.36.746.28 1.472.48 2.16.7.941.399 1.805.898 2.532 1.677.628.678.962 1.497 1.236 2.336.118.399.216.798.373 1.177 0-.12.02-.16.02-.279.177-2.056.452-4.093.864-6.11.04-.2.02-.359-.216-.439a9.503 9.503 0 0 1-3.868-3.434c-.687-1.058-.844-2.216-.824-3.474 0-.459.059-.898.118-1.437.589.32 1.158.559 1.649.858 1.1.64 2.061 1.418 2.69 2.536.49.858.608 1.837.686 2.815.04.3.04.619.118.898l.06-.24c.51-2.056 1.118-4.132 1.904-6.128.078-.2.078-.32-.099-.42-1.354-.978-2.375-2.216-3.121-3.753-.59-1.218-.59-2.456-.334-3.714.079-.46.196-.878.314-1.338l.04-.04c.863.54 1.668 1.159 2.355 1.937 1.06 1.138 1.63 2.456 1.512 4.093-.04.58-.098 1.218-.137 1.917.039-.08.059-.12.078-.2.432-.898.864-1.797 1.296-2.715.04-.12.04-.24.04-.36-.04-.818-.02-1.637.196-2.455.157-.62.392-1.258.844-1.717.53-.58 1.158-1.019 1.825-1.398.354-.24.707-.4 1.08-.579.06 0 .098.04.157.04-.02.3-.078.579-.098.878-.04 1.099-.294 2.197-.785 3.155Z" stroke="#A05500" stroke-width="2.15" stroke-linejoin="round" mask="url(#p)"/>
<g style="mix-blend-mode:color-burn">
<mask id="q" maskUnits="userSpaceOnUse" x="105.809" y="13.265" width="23" height="61" fill="#000">
<path fill="#fff" d="M105.809 13.265h23v61h-23z"/>
<path d="M111.48 19.338c.609 1.258 1.689 1.917 2.886 2.396.138.08.275.2.334.32.452 1.018.883 2.076 1.315 3.074.157.38.275.739.452 1.198a58.068 58.068 0 0 0-1.414-1.757c-.824-.978-1.806-1.717-3.121-1.917-1.335-.22-2.67-.1-3.985.24-.04.04-.059.04-.138.08.334.499.628 1.018.942 1.477.688.899 1.512 1.637 2.612 2.037 1.57.499 3.18.619 4.79.359.157-.06.294-.08.451-.12a46.43 46.43 0 0 1 1.865 7.128c-.314-.46-.589-.978-.863-1.438-.688-1.178-1.551-2.116-2.867-2.575a9.088 9.088 0 0 0-3.082-.52c-.334 0-.687.04-1.099.04.196.48.333.9.49 1.298.511 1.098 1.139 2.057 2.16 2.696 1.217.818 2.591 1.218 4.025 1.357.451.04.942.08 1.413.12.412 2.416.648 4.872.707 7.367-.079-.08-.098-.2-.138-.319-.157-.46-.333-.938-.51-1.438-.55-1.437-1.472-2.535-2.866-3.194-.962-.44-1.983-.699-3.024-.858-.176 0-.353-.04-.549-.08v.24c.039.219.078.498.137.778.334 1.437.883 2.815 2.101 3.753 1.276 1.059 2.768 1.717 4.397 2.077.157.02.314.02.511.06a40.287 40.287 0 0 1-.589 7.527c-.177-.819-.314-1.597-.471-2.376-.256-1.098-.786-2.077-1.63-2.815-1.06-.899-2.297-1.478-3.593-1.957-.137 0-.274-.08-.49-.12.019.719.039 1.338.117 1.957.138 1.138.452 2.176 1.178 3.035 1.237 1.437 2.729 2.535 4.516 3.154.059 0 .118.04.196.08-.451 2.316-1.06 4.572-1.885 6.748-.039-.399 0-.778-.019-1.178-.02-1.317-.236-2.555-1.041-3.613a8.456 8.456 0 0 0-2.356-2.097c-.471-.32-.942-.599-1.472-.858-.059.22-.079.42-.118.579-.275 1.637-.275 3.234.55 4.712.687 1.218 1.629 2.236 2.729 3.094.412.32.824.58 1.256.859-.805 2.096-1.727 4.133-2.827 6.07 0-.12 0-.2.02-.28.059-.54.137-1.138.196-1.677a5.274 5.274 0 0 0-.589-2.895c-.569-1.038-1.335-1.937-2.238-2.716a18.02 18.02 0 0 1-1.021-.858c-.491 1.178-.765 2.316-.805 3.474 0 .659.04 1.318.295 1.956a11.509 11.509 0 0 0 3.102 4.493c.157.12.137.2.059.36a55.375 55.375 0 0 1-3.004 4.471s.196.4 1.512-.459c.314-.459.628-.898.922-1.397a90.923 90.923 0 0 0 1.787-2.955c.118-.26.235-.34.51-.26 1.728.4 3.475.4 5.183-.08 1.217-.32 2.199-1.098 3.004-2.036.353-.42.667-.939 1.001-1.358.02-.08.059-.12.098-.2l-.118-.08c-1.374-.459-2.787-.698-4.22-.578-1.434.08-2.592.778-3.613 1.797-.235.24-.451.459-.726.658.019-.08.059-.16.098-.24a53.462 53.462 0 0 0 2.395-5.69c.059-.199.137-.239.334-.239 1.708.12 3.377-.2 4.947-.898 1.217-.54 2.062-1.478 2.709-2.616.315-.499.55-1.078.845-1.697-.57 0-1.08-.08-1.591-.08-.981-.04-1.963.04-2.925.3-1.315.399-2.238 1.218-3.023 2.296-.197.24-.354.479-.511.718.491-2.136.982-4.292 1.473-6.428.785-.2 1.629-.36 2.415-.62 1.217-.419 2.355-1.018 3.258-1.996.786-.858 1.591-2.735 1.689-3.893h-.039c-1.689.02-3.318.34-4.791 1.278-.903.539-1.472 1.437-1.943 2.375-.118.2-.216.4-.354.62.197-2.137.275-4.253.118-6.39 1.06-.319 2.022-.738 2.906-1.317 1.295-.859 2.414-1.877 2.886-3.434a9.297 9.297 0 0 0 .432-2.536c.019-.08 0-.16 0-.36-.746.28-1.473.48-2.16.7-.942.399-1.806.898-2.533 1.677-.628.678-.962 1.497-1.236 2.336-.118.399-.216.798-.373 1.177 0-.12-.02-.16-.02-.279a53.307 53.307 0 0 0-.864-6.11c-.039-.2-.019-.359.216-.439a9.506 9.506 0 0 0 3.868-3.434c.687-1.058.844-2.216.824-3.474 0-.459-.059-.898-.118-1.437-.589.32-1.158.559-1.649.858-1.099.64-2.061 1.418-2.689 2.536-.491.858-.609 1.837-.687 2.815-.04.3-.04.619-.118.898l-.059-.24c-.511-2.056-1.119-4.132-1.904-6.128-.079-.2-.079-.32.098-.42 1.354-.978 2.375-2.216 3.121-3.753.589-1.218.589-2.456.334-3.714-.079-.46-.196-.878-.314-1.338l-.039-.04c-.864.54-1.669 1.159-2.356 1.937-1.06 1.138-1.63 2.456-1.512 4.093.039.579.098 1.218.138 1.917a.829.829 0 0 1-.079-.2c-.432-.898-.864-1.797-1.296-2.715-.039-.12-.039-.24-.039-.36.039-.818.02-1.637-.196-2.455-.157-.62-.393-1.258-.845-1.717-.53-.58-1.158-1.019-1.825-1.398-.354-.24-.707-.4-1.08-.579-.059 0-.098.04-.157.04.019.3.078.579.098.878.039 1.099.295 2.197.785 3.155Z"/>
</mask>
<path d="M111.48 19.338c.609 1.258 1.689 1.917 2.886 2.396.138.08.275.2.334.32.452 1.018.883 2.076 1.315 3.074.157.38.275.739.452 1.198a58.068 58.068 0 0 0-1.414-1.757c-.824-.978-1.806-1.717-3.121-1.917-1.335-.22-2.67-.1-3.985.24-.04.04-.059.04-.138.08.334.499.628 1.018.942 1.477.688.899 1.512 1.637 2.612 2.037 1.57.499 3.18.619 4.79.359.157-.06.294-.08.451-.12a46.43 46.43 0 0 1 1.865 7.128c-.314-.46-.589-.978-.863-1.438-.688-1.178-1.551-2.116-2.867-2.575a9.088 9.088 0 0 0-3.082-.52c-.334 0-.687.04-1.099.04.196.48.333.9.49 1.298.511 1.098 1.139 2.057 2.16 2.696 1.217.818 2.591 1.218 4.025 1.357.451.04.942.08 1.413.12.412 2.416.648 4.872.707 7.367-.079-.08-.098-.2-.138-.319-.157-.46-.333-.938-.51-1.438-.55-1.437-1.472-2.535-2.866-3.194-.962-.44-1.983-.699-3.024-.858-.176 0-.353-.04-.549-.08v.24c.039.219.078.498.137.778.334 1.437.883 2.815 2.101 3.753 1.276 1.059 2.768 1.717 4.397 2.077.157.02.314.02.511.06a40.287 40.287 0 0 1-.589 7.527c-.177-.819-.314-1.597-.471-2.376-.256-1.098-.786-2.077-1.63-2.815-1.06-.899-2.297-1.478-3.593-1.957-.137 0-.274-.08-.49-.12.019.719.039 1.338.117 1.957.138 1.138.452 2.176 1.178 3.035 1.237 1.437 2.729 2.535 4.516 3.154.059 0 .118.04.196.08-.451 2.316-1.06 4.572-1.885 6.748-.039-.399 0-.778-.019-1.178-.02-1.317-.236-2.555-1.041-3.613a8.456 8.456 0 0 0-2.356-2.097c-.471-.32-.942-.599-1.472-.858-.059.22-.079.42-.118.579-.275 1.637-.275 3.234.55 4.712.687 1.218 1.629 2.236 2.729 3.094.412.32.824.58 1.256.859-.805 2.096-1.727 4.133-2.827 6.07 0-.12 0-.2.02-.28.059-.54.137-1.138.196-1.677a5.274 5.274 0 0 0-.589-2.895c-.569-1.038-1.335-1.937-2.238-2.716a18.02 18.02 0 0 1-1.021-.858c-.491 1.178-.765 2.316-.805 3.474 0 .659.04 1.318.295 1.956a11.509 11.509 0 0 0 3.102 4.493c.157.12.137.2.059.36a55.375 55.375 0 0 1-3.004 4.471s.196.4 1.512-.459c.314-.459.628-.898.922-1.397a90.923 90.923 0 0 0 1.787-2.955c.118-.26.235-.34.51-.26 1.728.4 3.475.4 5.183-.08 1.217-.32 2.199-1.098 3.004-2.036.353-.42.667-.939 1.001-1.358.02-.08.059-.12.098-.2l-.118-.08c-1.374-.459-2.787-.698-4.22-.578-1.434.08-2.592.778-3.613 1.797-.235.24-.451.459-.726.658.019-.08.059-.16.098-.24a53.462 53.462 0 0 0 2.395-5.69c.059-.199.137-.239.334-.239 1.708.12 3.377-.2 4.947-.898 1.217-.54 2.062-1.478 2.709-2.616.315-.499.55-1.078.845-1.697-.57 0-1.08-.08-1.591-.08-.981-.04-1.963.04-2.925.3-1.315.399-2.238 1.218-3.023 2.296-.197.24-.354.479-.511.718.491-2.136.982-4.292 1.473-6.428.785-.2 1.629-.36 2.415-.62 1.217-.419 2.355-1.018 3.258-1.996.786-.858 1.591-2.735 1.689-3.893h-.039c-1.689.02-3.318.34-4.791 1.278-.903.539-1.472 1.437-1.943 2.375-.118.2-.216.4-.354.62.197-2.137.275-4.253.118-6.39 1.06-.319 2.022-.738 2.906-1.317 1.295-.859 2.414-1.877 2.886-3.434a9.297 9.297 0 0 0 .432-2.536c.019-.08 0-.16 0-.36-.746.28-1.473.48-2.16.7-.942.399-1.806.898-2.533 1.677-.628.678-.962 1.497-1.236 2.336-.118.399-.216.798-.373 1.177 0-.12-.02-.16-.02-.279a53.307 53.307 0 0 0-.864-6.11c-.039-.2-.019-.359.216-.439a9.506 9.506 0 0 0 3.868-3.434c.687-1.058.844-2.216.824-3.474 0-.459-.059-.898-.118-1.437-.589.32-1.158.559-1.649.858-1.099.64-2.061 1.418-2.689 2.536-.491.858-.609 1.837-.687 2.815-.04.3-.04.619-.118.898l-.059-.24c-.511-2.056-1.119-4.132-1.904-6.128-.079-.2-.079-.32.098-.42 1.354-.978 2.375-2.216 3.121-3.753.589-1.218.589-2.456.334-3.714-.079-.46-.196-.878-.314-1.338l-.039-.04c-.864.54-1.669 1.159-2.356 1.937-1.06 1.138-1.63 2.456-1.512 4.093.039.579.098 1.218.138 1.917a.829.829 0 0 1-.079-.2c-.432-.898-.864-1.797-1.296-2.715-.039-.12-.039-.24-.039-.36.039-.818.02-1.637-.196-2.455-.157-.62-.393-1.258-.845-1.717-.53-.58-1.158-1.019-1.825-1.398-.354-.24-.707-.4-1.08-.579-.059 0-.098.04-.157.04.019.3.078.579.098.878.039 1.099.295 2.197.785 3.155Z" fill="#000" fill-opacity=".16"/>
<path d="M111.48 19.338c.609 1.258 1.689 1.917 2.886 2.396.138.08.275.2.334.32.452 1.018.883 2.076 1.315 3.074.157.38.275.739.452 1.198a58.068 58.068 0 0 0-1.414-1.757c-.824-.978-1.806-1.717-3.121-1.917-1.335-.22-2.67-.1-3.985.24-.04.04-.059.04-.138.08.334.499.628 1.018.942 1.477.688.899 1.512 1.637 2.612 2.037 1.57.499 3.18.619 4.79.359.157-.06.294-.08.451-.12a46.43 46.43 0 0 1 1.865 7.128c-.314-.46-.589-.978-.863-1.438-.688-1.178-1.551-2.116-2.867-2.575a9.088 9.088 0 0 0-3.082-.52c-.334 0-.687.04-1.099.04.196.48.333.9.49 1.298.511 1.098 1.139 2.057 2.16 2.696 1.217.818 2.591 1.218 4.025 1.357.451.04.942.08 1.413.12.412 2.416.648 4.872.707 7.367-.079-.08-.098-.2-.138-.319-.157-.46-.333-.938-.51-1.438-.55-1.437-1.472-2.535-2.866-3.194-.962-.44-1.983-.699-3.024-.858-.176 0-.353-.04-.549-.08v.24c.039.219.078.498.137.778.334 1.437.883 2.815 2.101 3.753 1.276 1.059 2.768 1.717 4.397 2.077.157.02.314.02.511.06a40.287 40.287 0 0 1-.589 7.527c-.177-.819-.314-1.597-.471-2.376-.256-1.098-.786-2.077-1.63-2.815-1.06-.899-2.297-1.478-3.593-1.957-.137 0-.274-.08-.49-.12.019.719.039 1.338.117 1.957.138 1.138.452 2.176 1.178 3.035 1.237 1.437 2.729 2.535 4.516 3.154.059 0 .118.04.196.08-.451 2.316-1.06 4.572-1.885 6.748-.039-.399 0-.778-.019-1.178-.02-1.317-.236-2.555-1.041-3.613a8.456 8.456 0 0 0-2.356-2.097c-.471-.32-.942-.599-1.472-.858-.059.22-.079.42-.118.579-.275 1.637-.275 3.234.55 4.712.687 1.218 1.629 2.236 2.729 3.094.412.32.824.58 1.256.859-.805 2.096-1.727 4.133-2.827 6.07 0-.12 0-.2.02-.28.059-.54.137-1.138.196-1.677a5.274 5.274 0 0 0-.589-2.895c-.569-1.038-1.335-1.937-2.238-2.716a18.02 18.02 0 0 1-1.021-.858c-.491 1.178-.765 2.316-.805 3.474 0 .659.04 1.318.295 1.956a11.509 11.509 0 0 0 3.102 4.493c.157.12.137.2.059.36a55.375 55.375 0 0 1-3.004 4.471s.196.4 1.512-.459c.314-.459.628-.898.922-1.397a90.923 90.923 0 0 0 1.787-2.955c.118-.26.235-.34.51-.26 1.728.4 3.475.4 5.183-.08 1.217-.32 2.199-1.098 3.004-2.036.353-.42.667-.939 1.001-1.358.02-.08.059-.12.098-.2l-.118-.08c-1.374-.459-2.787-.698-4.22-.578-1.434.08-2.592.778-3.613 1.797-.235.24-.451.459-.726.658.019-.08.059-.16.098-.24a53.462 53.462 0 0 0 2.395-5.69c.059-.199.137-.239.334-.239 1.708.12 3.377-.2 4.947-.898 1.217-.54 2.062-1.478 2.709-2.616.315-.499.55-1.078.845-1.697-.57 0-1.08-.08-1.591-.08-.981-.04-1.963.04-2.925.3-1.315.399-2.238 1.218-3.023 2.296-.197.24-.354.479-.511.718.491-2.136.982-4.292 1.473-6.428.785-.2 1.629-.36 2.415-.62 1.217-.419 2.355-1.018 3.258-1.996.786-.858 1.591-2.735 1.689-3.893h-.039c-1.689.02-3.318.34-4.791 1.278-.903.539-1.472 1.437-1.943 2.375-.118.2-.216.4-.354.62.197-2.137.275-4.253.118-6.39 1.06-.319 2.022-.738 2.906-1.317 1.295-.859 2.414-1.877 2.886-3.434a9.297 9.297 0 0 0 .432-2.536c.019-.08 0-.16 0-.36-.746.28-1.473.48-2.16.7-.942.399-1.806.898-2.533 1.677-.628.678-.962 1.497-1.236 2.336-.118.399-.216.798-.373 1.177 0-.12-.02-.16-.02-.279a53.307 53.307 0 0 0-.864-6.11c-.039-.2-.019-.359.216-.439a9.506 9.506 0 0 0 3.868-3.434c.687-1.058.844-2.216.824-3.474 0-.459-.059-.898-.118-1.437-.589.32-1.158.559-1.649.858-1.099.64-2.061 1.418-2.689 2.536-.491.858-.609 1.837-.687 2.815-.04.3-.04.619-.118.898l-.059-.24c-.511-2.056-1.119-4.132-1.904-6.128-.079-.2-.079-.32.098-.42 1.354-.978 2.375-2.216 3.121-3.753.589-1.218.589-2.456.334-3.714-.079-.46-.196-.878-.314-1.338l-.039-.04c-.864.54-1.669 1.159-2.356 1.937-1.06 1.138-1.63 2.456-1.512 4.093.039.579.098 1.218.138 1.917a.829.829 0 0 1-.079-.2c-.432-.898-.864-1.797-1.296-2.715-.039-.12-.039-.24-.039-.36.039-.818.02-1.637-.196-2.455-.157-.62-.393-1.258-.845-1.717-.53-.58-1.158-1.019-1.825-1.398-.354-.24-.707-.4-1.08-.579-.059 0-.098.04-.157.04.019.3.078.579.098.878.039 1.099.295 2.197.785 3.155Z" stroke="#000" stroke-opacity=".16" stroke-width="2.15" stroke-linejoin="round" mask="url(#q)"/>
</g>
<path d="M112.771 18.478c.608 1.258 1.688 1.917 2.886 2.396.137.08.275.2.334.32.451 1.018.883 2.076 1.315 3.074.157.38.275.739.451 1.198a58.114 58.114 0 0 0-1.413-1.757c-.825-.978-1.806-1.717-3.122-1.917-1.335-.22-2.67-.1-3.985.24-.039.04-.059.04-.137.08.333.499.628 1.018.942 1.477.687.899 1.512 1.637 2.611 2.037 1.571.499 3.18.619 4.79.359.157-.06.295-.08.452-.12a46.546 46.546 0 0 1 1.865 7.128c-.314-.46-.589-.978-.864-1.438-.687-1.178-1.551-2.116-2.866-2.575a9.092 9.092 0 0 0-3.082-.52c-.334 0-.688.04-1.1.04.196.48.334.9.491 1.298.51 1.099 1.139 2.057 2.159 2.696 1.218.818 2.592 1.218 4.025 1.357.452.04.942.08 1.414.12.412 2.416.647 4.872.706 7.368-.078-.08-.098-.2-.137-.32-.157-.46-.334-.938-.511-1.438-.549-1.437-1.472-2.535-2.866-3.194-.962-.44-1.983-.699-3.023-.858-.177 0-.354-.04-.55-.08v.24c.039.219.079.498.138.778.333 1.437.883 2.815 2.1 3.753 1.276 1.059 2.768 1.718 4.398 2.077.157.02.314.02.51.06a40.203 40.203 0 0 1-.589 7.527c-.176-.819-.314-1.598-.471-2.376-.255-1.098-.785-2.077-1.629-2.815-1.061-.899-2.297-1.478-3.593-1.957-.137 0-.275-.08-.491-.12.02.719.039 1.338.118 1.957.137 1.138.451 2.176 1.178 3.035 1.237 1.437 2.729 2.535 4.515 3.154.059 0 .118.04.197.08-.452 2.316-1.061 4.572-1.885 6.748-.039-.399 0-.778-.02-1.178-.019-1.317-.235-2.555-1.04-3.613a8.47 8.47 0 0 0-2.356-2.097c-.471-.32-.942-.599-1.473-.858-.058.22-.078.42-.117.579-.275 1.637-.275 3.234.549 4.712.688 1.218 1.63 2.236 2.729 3.094.413.32.825.58 1.257.859-.805 2.096-1.728 4.133-2.827 6.07 0-.12 0-.2.019-.28.059-.54.138-1.138.197-1.677a5.283 5.283 0 0 0-.589-2.895c-.57-1.038-1.335-1.937-2.238-2.716-.334-.26-.668-.539-1.021-.858-.491 1.178-.766 2.316-.805 3.474 0 .659.039 1.318.294 1.956a11.53 11.53 0 0 0 3.102 4.493c.157.12.138.2.059.36a55.357 55.357 0 0 1-3.004 4.471s.197.4 1.512-.459c.314-.459.628-.898.923-1.397.608-.979 1.217-1.957 1.786-2.955.118-.26.236-.34.511-.26 1.727.4 3.475.4 5.183-.08 1.217-.32 2.198-1.098 3.003-2.036.354-.42.668-.939 1.002-1.358.019-.08.058-.12.098-.2l-.118-.08c-1.374-.459-2.788-.698-4.221-.578-1.433.08-2.591.778-3.612 1.797-.236.24-.452.459-.727.658.02-.08.059-.16.098-.24a53.469 53.469 0 0 0 2.396-5.69c.059-.199.137-.239.333-.239 1.708.12 3.377-.2 4.948-.898 1.217-.54 2.061-1.478 2.709-2.616.314-.499.55-1.078.844-1.697-.569 0-1.08-.08-1.59-.08-.982-.04-1.963.04-2.925.3-1.316.399-2.238 1.218-3.024 2.296-.196.24-.353.479-.51.718.491-2.136.981-4.292 1.472-6.428.786-.2 1.63-.36 2.415-.62 1.217-.419 2.356-1.018 3.259-1.996.785-.858 1.59-2.735 1.688-3.893h-.039c-1.688.02-3.318.34-4.79 1.278-.903.539-1.473 1.437-1.944 2.376-.118.2-.216.399-.353.618.196-2.136.275-4.252.118-6.388 1.06-.32 2.022-.74 2.905-1.318 1.296-.859 2.415-1.877 2.886-3.434a9.297 9.297 0 0 0 .432-2.536c.02-.08 0-.16 0-.36-.746.28-1.472.48-2.159.7-.943.399-1.807.898-2.533 1.677-.628.678-.962 1.497-1.237 2.336-.118.399-.216.798-.373 1.177 0-.12-.019-.16-.019-.279a53.305 53.305 0 0 0-.864-6.11c-.04-.2-.02-.359.216-.439a9.498 9.498 0 0 0 3.867-3.434c.687-1.058.844-2.216.825-3.474 0-.459-.059-.898-.118-1.437-.589.32-1.158.559-1.649.858-1.1.64-2.062 1.418-2.69 2.536-.491.858-.608 1.837-.687 2.815-.039.3-.039.619-.118.898a20.4 20.4 0 0 0-.059-.24c-.51-2.056-1.119-4.132-1.904-6.128-.078-.2-.078-.32.098-.42 1.355-.978 2.376-2.216 3.122-3.753.589-1.218.589-2.456.334-3.714-.079-.46-.197-.878-.315-1.338l-.039-.04c-.864.54-1.669 1.159-2.356 1.937-1.06 1.138-1.629 2.456-1.511 4.093.039.58.098 1.218.137 1.917-.039-.08-.059-.12-.078-.2-.432-.898-.864-1.797-1.296-2.715-.039-.12-.039-.24-.039-.36.039-.818.019-1.637-.197-2.455-.157-.62-.392-1.258-.844-1.717-.53-.58-1.158-1.019-1.826-1.398-.353-.24-.707-.4-1.08-.579-.058 0-.098.04-.157.04.02.3.079.579.099.878.039 1.099.294 2.197.785 3.155Z" fill="#FFD57C"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M113.118 50.048c1.261 3.725 2.24 5.92 4.306 8.903l.623-1.432a.86.86 0 0 0 .006.071c.071-.188.141-.376.209-.566l.068-.157.043-.157a41.54 41.54 0 0 0 1.435-5.228l.027-.097.015-.104c.03-.146.059-.292.087-.44a.407.407 0 0 0-.023-.011l.161-1.128.039.182c.432-2.496.628-4.992.589-7.527a2.003 2.003 0 0 0-.132-.023l-.064-1.314c.009.026.016.051.023.077a.551.551 0 0 0 .114.241 50.783 50.783 0 0 0-.707-7.367l-.045-.004-.278-1.197c.048.075.097.15.147.223a46.543 46.543 0 0 0-1.865-7.128l-.139.033c-.104.023-.204.045-.313.087-1.61.26-3.22.14-4.79-.36-1.1-.399-1.924-1.137-2.611-2.036a19.248 19.248 0 0 1-.532-.833c2.923 1.732 5.053 2.57 8.135 3.108l-.42-1.077c.171.216.348.44.532.679-.073-.19-.136-.363-.195-.527a16.808 16.808 0 0 0-.256-.671 147.49 147.49 0 0 1-.532-1.25 113.8 113.8 0 0 0-.784-1.825.707.707 0 0 0-.203-.23h.266c.264.562.529 1.118.794 1.67a63.425 63.425 0 0 1 1.881 4.729 56.425 56.425 0 0 1 1.11 3.914l.059.24.005-.018c.785 3.807 1.116 7.948 1.336 10.698l.046.568c.045 1.655-.037 3.303-.189 4.963l.089-.148a48.93 48.93 0 0 1-.342 2.46c-.24 1.043-.479 2.09-.719 3.139l-.736 3.214.072-.11c-.215.752-.44 1.46-.67 2.1-.095.025-.146.086-.188.227-.34.96-.71 1.916-1.107 2.86a111.02 111.02 0 0 1-1.277 2.809l-.011.02-.054.114c-.367.77-.713 1.456-1.049 2.073a.752.752 0 0 0-.114.19c-.242.425-.492.847-.746 1.266-.33.51-.653 1.042-.951 1.544l-.089.144a19.06 19.06 0 0 1-.75 1.146l-.173.252c-1.315.859-1.512.46-1.512.46a55.355 55.355 0 0 0 3.004-4.473c.07-.143.093-.222-.015-.323l1.016-1.816v.003c-.019.08-.019.16-.019.28 1.099-1.938 2.022-3.974 2.827-6.07l-.14-.09a15.39 15.39 0 0 1-1.117-.769c-1.099-.858-2.042-1.877-2.729-3.094-.824-1.478-.824-3.075-.549-4.712.016-.069.029-.144.044-.225l.027-.15Zm-2.019 6.74c.755 4.362 1.306 6.716 2.54 9.8a11.523 11.523 0 0 1-3.027-4.426c-.255-.639-.294-1.297-.294-1.956.038-1.14.305-2.26.781-3.417Zm4.635 9.679c3.288-.513 5.542-1.555 8.849-3.39-.114.151-.226.312-.339.473-.18.258-.363.518-.557.749-.805.938-1.786 1.717-3.004 2.036-1.631.458-3.297.478-4.949.132Zm3.407-8.086c2.815-1.036 4.77-2.366 8.195-5.008l-.12.26c-.202.44-.391.853-.623 1.222-.648 1.138-1.492 2.076-2.709 2.616-1.508.67-3.107.992-4.743.91Zm2.105-8.512c2.841-1.502 4.333-3.052 6.77-6.411a4.65 4.65 0 0 1 .167-.003h.039c-.098 1.158-.903 3.035-1.688 3.893-.903.978-2.042 1.577-3.259 1.996-.533.177-1.094.307-1.645.435l-.384.09Zm.312-8.64c2.329-1.938 3.623-3.769 5.679-7.464l.189-.07.011.028c.001.064.003.115.006.157.003.075.006.123-.006.17a9.296 9.296 0 0 1-.432 2.537c-.471 1.557-1.59 2.575-2.886 3.434a10.79 10.79 0 0 1-2.561 1.209Zm-1.045-8.498c1.973-2.34 3.043-4.093 4.543-8.196l.013.117c.049.431.091.805.091 1.193.019 1.258-.138 2.416-.825 3.474a9.494 9.494 0 0 1-3.822 3.412Zm-2.598-7.9-.013.001c1.854-3.366 2.529-5.368 3.279-8.885l.054.21c.097.37.188.723.253 1.103.256 1.258.256 2.496-.333 3.713-.746 1.538-1.767 2.776-3.122 3.754a.315.315 0 0 0-.118.104Zm-5.989-10.03c.983 2.305 1.839 3.828 3.643 6.037-1.162-.476-2.204-1.133-2.797-2.36-.491-.959-.746-2.057-.786-3.155-.009-.15-.029-.294-.049-.439l-.011-.083Zm.103 14.16c2.761 2.514 4.659 3.892 7.418 4.969l-.923-.079c-1.433-.14-2.807-.539-4.025-1.357-1.021-.64-1.649-1.598-2.159-2.696-.066-.168-.129-.34-.194-.517l-.117-.32Zm1.53 6.739c2.63 3.116 4.3 4.831 6.994 6.632a4.18 4.18 0 0 0-.193-.019 3.78 3.78 0 0 1-.167-.016c-1.63-.36-3.122-1.019-4.398-2.077-1.217-.938-1.767-2.316-2.101-3.753-.039-.187-.069-.373-.097-.541l-.038-.226Zm.38 7.236c2.142 3.5 3.57 5.612 5.658 7.775-1.723-.628-3.168-1.705-4.371-3.103-.727-.859-1.041-1.897-1.178-3.035a16.932 16.932 0 0 1-.109-1.637Z" fill="#E1910E"/>
<mask id="r" maskUnits="userSpaceOnUse" x="107.1" y="12.405" width="23" height="61" fill="#000">
<path fill="#fff" d="M107.1 12.405h23v61h-23z"/>
<path d="M112.771 18.478c.608 1.258 1.688 1.917 2.886 2.396.137.08.275.2.334.32.451 1.018.883 2.076 1.315 3.074.157.38.275.739.451 1.198a58.114 58.114 0 0 0-1.413-1.757c-.825-.978-1.806-1.717-3.122-1.917-1.335-.22-2.67-.1-3.985.24-.039.04-.059.04-.137.08.333.499.628 1.018.942 1.477.687.899 1.512 1.637 2.611 2.037 1.571.499 3.18.619 4.79.359.157-.06.295-.08.452-.12a46.546 46.546 0 0 1 1.865 7.128c-.314-.46-.589-.978-.864-1.438-.687-1.178-1.551-2.116-2.866-2.575a9.092 9.092 0 0 0-3.082-.52c-.334 0-.688.04-1.1.04.196.48.334.9.491 1.298.51 1.099 1.139 2.057 2.159 2.696 1.218.818 2.592 1.218 4.025 1.357.452.04.942.08 1.414.12.412 2.416.647 4.872.706 7.368-.078-.08-.098-.2-.137-.32-.157-.46-.334-.938-.511-1.438-.549-1.437-1.472-2.535-2.866-3.194-.962-.44-1.983-.699-3.023-.858-.177 0-.354-.04-.55-.08v.24c.039.219.079.498.138.778.333 1.437.883 2.815 2.1 3.753 1.276 1.059 2.768 1.718 4.398 2.077.157.02.314.02.51.06a40.203 40.203 0 0 1-.589 7.527c-.176-.819-.314-1.598-.471-2.376-.255-1.098-.785-2.077-1.629-2.815-1.061-.899-2.297-1.478-3.593-1.957-.137 0-.275-.08-.491-.12.02.719.039 1.338.118 1.957.137 1.138.451 2.176 1.178 3.035 1.237 1.437 2.729 2.535 4.515 3.154.059 0 .118.04.197.08-.452 2.316-1.061 4.572-1.885 6.748-.039-.399 0-.778-.02-1.178-.019-1.317-.235-2.555-1.04-3.613a8.47 8.47 0 0 0-2.356-2.097c-.471-.32-.942-.599-1.473-.858-.058.22-.078.42-.117.579-.275 1.637-.275 3.234.549 4.712.688 1.218 1.63 2.236 2.729 3.094.413.32.825.58 1.257.859-.805 2.096-1.728 4.133-2.827 6.07 0-.12 0-.2.019-.28.059-.54.138-1.138.197-1.677a5.283 5.283 0 0 0-.589-2.895c-.57-1.038-1.335-1.937-2.238-2.716-.334-.26-.668-.539-1.021-.858-.491 1.178-.766 2.316-.805 3.474 0 .659.039 1.318.294 1.956a11.53 11.53 0 0 0 3.102 4.493c.157.12.138.2.059.36a55.357 55.357 0 0 1-3.004 4.471s.197.4 1.512-.459c.314-.459.628-.898.923-1.397.608-.979 1.217-1.957 1.786-2.955.118-.26.236-.34.511-.26 1.727.4 3.475.4 5.183-.08 1.217-.32 2.198-1.098 3.003-2.036.354-.42.668-.939 1.002-1.358.019-.08.058-.12.098-.2l-.118-.08c-1.374-.459-2.788-.698-4.221-.578-1.433.08-2.591.778-3.612 1.797-.236.24-.452.459-.727.658.02-.08.059-.16.098-.24a53.469 53.469 0 0 0 2.396-5.69c.059-.199.137-.239.333-.239 1.708.12 3.377-.2 4.948-.898 1.217-.54 2.061-1.478 2.709-2.616.314-.499.55-1.078.844-1.697-.569 0-1.08-.08-1.59-.08-.982-.04-1.963.04-2.925.3-1.316.399-2.238 1.218-3.024 2.296-.196.24-.353.479-.51.718.491-2.136.981-4.292 1.472-6.428.786-.2 1.63-.36 2.415-.62 1.217-.419 2.356-1.018 3.259-1.996.785-.858 1.59-2.735 1.688-3.893h-.039c-1.688.02-3.318.34-4.79 1.278-.903.539-1.473 1.437-1.944 2.376-.118.2-.216.399-.353.618.196-2.136.275-4.252.118-6.388 1.06-.32 2.022-.74 2.905-1.318 1.296-.859 2.415-1.877 2.886-3.434a9.297 9.297 0 0 0 .432-2.536c.02-.08 0-.16 0-.36-.746.28-1.472.48-2.159.7-.943.399-1.807.898-2.533 1.677-.628.678-.962 1.497-1.237 2.336-.118.399-.216.798-.373 1.177 0-.12-.019-.16-.019-.279a53.305 53.305 0 0 0-.864-6.11c-.04-.2-.02-.359.216-.439a9.498 9.498 0 0 0 3.867-3.434c.687-1.058.844-2.216.825-3.474 0-.459-.059-.898-.118-1.437-.589.32-1.158.559-1.649.858-1.1.64-2.062 1.418-2.69 2.536-.491.858-.608 1.837-.687 2.815-.039.3-.039.619-.118.898a20.4 20.4 0 0 0-.059-.24c-.51-2.056-1.119-4.132-1.904-6.128-.078-.2-.078-.32.098-.42 1.355-.978 2.376-2.216 3.122-3.753.589-1.218.589-2.456.334-3.714-.079-.46-.197-.878-.315-1.338l-.039-.04c-.864.54-1.669 1.159-2.356 1.937-1.06 1.138-1.629 2.456-1.511 4.093.039.58.098 1.218.137 1.917-.039-.08-.059-.12-.078-.2-.432-.898-.864-1.797-1.296-2.715-.039-.12-.039-.24-.039-.36.039-.818.019-1.637-.197-2.455-.157-.62-.392-1.258-.844-1.717-.53-.58-1.158-1.019-1.826-1.398-.353-.24-.707-.4-1.08-.579-.058 0-.098.04-.157.04.02.3.079.579.099.878.039 1.099.294 2.197.785 3.155Z"/>
</mask>
<path d="M112.771 18.478c.608 1.258 1.688 1.917 2.886 2.396.137.08.275.2.334.32.451 1.018.883 2.076 1.315 3.074.157.38.275.739.451 1.198a58.114 58.114 0 0 0-1.413-1.757c-.825-.978-1.806-1.717-3.122-1.917-1.335-.22-2.67-.1-3.985.24-.039.04-.059.04-.137.08.333.499.628 1.018.942 1.477.687.899 1.512 1.637 2.611 2.037 1.571.499 3.18.619 4.79.359.157-.06.295-.08.452-.12a46.546 46.546 0 0 1 1.865 7.128c-.314-.46-.589-.978-.864-1.438-.687-1.178-1.551-2.116-2.866-2.575a9.092 9.092 0 0 0-3.082-.52c-.334 0-.688.04-1.1.04.196.48.334.9.491 1.298.51 1.099 1.139 2.057 2.159 2.696 1.218.818 2.592 1.218 4.025 1.357.452.04.942.08 1.414.12.412 2.416.647 4.872.706 7.368-.078-.08-.098-.2-.137-.32-.157-.46-.334-.938-.511-1.438-.549-1.437-1.472-2.535-2.866-3.194-.962-.44-1.983-.699-3.023-.858-.177 0-.354-.04-.55-.08v.24c.039.219.079.498.138.778.333 1.437.883 2.815 2.1 3.753 1.276 1.059 2.768 1.718 4.398 2.077.157.02.314.02.51.06a40.203 40.203 0 0 1-.589 7.527c-.176-.819-.314-1.598-.471-2.376-.255-1.098-.785-2.077-1.629-2.815-1.061-.899-2.297-1.478-3.593-1.957-.137 0-.275-.08-.491-.12.02.719.039 1.338.118 1.957.137 1.138.451 2.176 1.178 3.035 1.237 1.437 2.729 2.535 4.515 3.154.059 0 .118.04.197.08-.452 2.316-1.061 4.572-1.885 6.748-.039-.399 0-.778-.02-1.178-.019-1.317-.235-2.555-1.04-3.613a8.47 8.47 0 0 0-2.356-2.097c-.471-.32-.942-.599-1.473-.858-.058.22-.078.42-.117.579-.275 1.637-.275 3.234.549 4.712.688 1.218 1.63 2.236 2.729 3.094.413.32.825.58 1.257.859-.805 2.096-1.728 4.133-2.827 6.07 0-.12 0-.2.019-.28.059-.54.138-1.138.197-1.677a5.283 5.283 0 0 0-.589-2.895c-.57-1.038-1.335-1.937-2.238-2.716-.334-.26-.668-.539-1.021-.858-.491 1.178-.766 2.316-.805 3.474 0 .659.039 1.318.294 1.956a11.53 11.53 0 0 0 3.102 4.493c.157.12.138.2.059.36a55.357 55.357 0 0 1-3.004 4.471s.197.4 1.512-.459c.314-.459.628-.898.923-1.397.608-.979 1.217-1.957 1.786-2.955.118-.26.236-.34.511-.26 1.727.4 3.475.4 5.183-.08 1.217-.32 2.198-1.098 3.003-2.036.354-.42.668-.939 1.002-1.358.019-.08.058-.12.098-.2l-.118-.08c-1.374-.459-2.788-.698-4.221-.578-1.433.08-2.591.778-3.612 1.797-.236.24-.452.459-.727.658.02-.08.059-.16.098-.24a53.469 53.469 0 0 0 2.396-5.69c.059-.199.137-.239.333-.239 1.708.12 3.377-.2 4.948-.898 1.217-.54 2.061-1.478 2.709-2.616.314-.499.55-1.078.844-1.697-.569 0-1.08-.08-1.59-.08-.982-.04-1.963.04-2.925.3-1.316.399-2.238 1.218-3.024 2.296-.196.24-.353.479-.51.718.491-2.136.981-4.292 1.472-6.428.786-.2 1.63-.36 2.415-.62 1.217-.419 2.356-1.018 3.259-1.996.785-.858 1.59-2.735 1.688-3.893h-.039c-1.688.02-3.318.34-4.79 1.278-.903.539-1.473 1.437-1.944 2.376-.118.2-.216.399-.353.618.196-2.136.275-4.252.118-6.388 1.06-.32 2.022-.74 2.905-1.318 1.296-.859 2.415-1.877 2.886-3.434a9.297 9.297 0 0 0 .432-2.536c.02-.08 0-.16 0-.36-.746.28-1.472.48-2.159.7-.943.399-1.807.898-2.533 1.677-.628.678-.962 1.497-1.237 2.336-.118.399-.216.798-.373 1.177 0-.12-.019-.16-.019-.279a53.305 53.305 0 0 0-.864-6.11c-.04-.2-.02-.359.216-.439a9.498 9.498 0 0 0 3.867-3.434c.687-1.058.844-2.216.825-3.474 0-.459-.059-.898-.118-1.437-.589.32-1.158.559-1.649.858-1.1.64-2.062 1.418-2.69 2.536-.491.858-.608 1.837-.687 2.815-.039.3-.039.619-.118.898a20.4 20.4 0 0 0-.059-.24c-.51-2.056-1.119-4.132-1.904-6.128-.078-.2-.078-.32.098-.42 1.355-.978 2.376-2.216 3.122-3.753.589-1.218.589-2.456.334-3.714-.079-.46-.197-.878-.315-1.338l-.039-.04c-.864.54-1.669 1.159-2.356 1.937-1.06 1.138-1.629 2.456-1.511 4.093.039.58.098 1.218.137 1.917-.039-.08-.059-.12-.078-.2-.432-.898-.864-1.797-1.296-2.715-.039-.12-.039-.24-.039-.36.039-.818.019-1.637-.197-2.455-.157-.62-.392-1.258-.844-1.717-.53-.58-1.158-1.019-1.826-1.398-.353-.24-.707-.4-1.08-.579-.058 0-.098.04-.157.04.02.3.079.579.099.878.039 1.099.294 2.197.785 3.155Z" stroke="#A05500" stroke-width="2.15" stroke-linejoin="round" mask="url(#r)"/>
<defs>
<linearGradient id="a" x1="109.566" y1="40.326" x2="174.913" y2="40.326" gradientUnits="userSpaceOnUse">
<stop stop-color="#D5E8FF"/>
<stop offset="1" stop-color="#89BEFF"/>
</linearGradient>
<linearGradient id="b" x1="110" y1="5" x2="190.936" y2="56.174" gradientUnits="userSpaceOnUse">
<stop offset=".1" stop-color="#ACEEBD"/>
<stop offset=".9" stop-color="#E3F0B6"/>
</linearGradient>
<linearGradient id="c" x1="39.066" y1="-.409" x2="39.066" y2="85.575" gradientUnits="userSpaceOnUse">
<stop stop-color="#ECF5FF"/>
<stop offset="1" stop-color="#D1E5FE"/>
</linearGradient>
<linearGradient id="d" x1="6" y1="5" x2="86.936" y2="56.174" gradientUnits="userSpaceOnUse">
<stop offset=".1" stop-color="#FCC0FF"/>
<stop offset=".9" stop-color="#FFD5B3"/>
</linearGradient>
<linearGradient id="e" x1="142.188" y1="-.409" x2="142.188" y2="85.575" gradientUnits="userSpaceOnUse">
<stop stop-color="#ECF5FF"/>
<stop offset="1" stop-color="#D1E5FE"/>
</linearGradient>
<linearGradient id="f" x1="109.122" y1="10" x2="183.13" y2="63.92" gradientUnits="userSpaceOnUse">
<stop offset=".1" stop-color="#ACEEBD"/>
<stop offset=".9" stop-color="#E3F0B6"/>
</linearGradient>
<linearGradient id="g" x1="70.292" y1="22.564" x2="70.292" y2="63.436" gradientUnits="userSpaceOnUse">
<stop stop-color="#E0EEFF"/>
<stop offset="1" stop-color="#F8FBFF"/>
</linearGradient>
<linearGradient id="h" x1="88.889" y1="4.193" x2="124.149" y2="4.193" gradientUnits="userSpaceOnUse">
<stop stop-color="#E0EEFF"/>
<stop offset="1" stop-color="#F8FBFF"/>
</linearGradient>
<linearGradient id="i" x1="54.382" y1="63.425" x2="88.889" y2="63.425" gradientUnits="userSpaceOnUse">
<stop stop-color="#D1E5FE"/>
<stop offset="1" stop-color="#F8FBFF"/>
</linearGradient>
<filter id="j" x="85.234" y="37.41" width="7.31" height="15.48" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1.72"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix values="0 0 0 0 0.882353 0 0 0 0 0.568627 0 0 0 0 0.054902 0 0 0 1 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_2138_22191"/>
<feBlend in="SourceGraphic" in2="effect1_dropShadow_2138_22191" result="shape"/>
</filter>
<filter id="k" x="78.355" y="23.865" width="7.31" height="9.03" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1.72"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix values="0 0 0 0 0.882353 0 0 0 0 0.568627 0 0 0 0 0.054902 0 0 0 1 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_2138_22191"/>
<feBlend in="SourceGraphic" in2="effect1_dropShadow_2138_22191" result="shape"/>
</filter>
<filter id="l" x="92.329" y="23.865" width="7.31" height="9.03" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1.72"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix values="0 0 0 0 0.882353 0 0 0 0 0.568627 0 0 0 0 0.054902 0 0 0 1 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_2138_22191"/>
<feBlend in="SourceGraphic" in2="effect1_dropShadow_2138_22191" result="shape"/>
</filter>
<filter id="m" x="71.904" y="30.315" width="7.31" height="29.24" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1.72"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix values="0 0 0 0 0.882353 0 0 0 0 0.568627 0 0 0 0 0.054902 0 0 0 1 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_2138_22191"/>
<feBlend in="SourceGraphic" in2="effect1_dropShadow_2138_22191" result="shape"/>
</filter>
<filter id="n" x="98.779" y="30.315" width="7.31" height="29.24" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1.72"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix values="0 0 0 0 0.882353 0 0 0 0 0.568627 0 0 0 0 0.054902 0 0 0 1 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_2138_22191"/>
<feBlend in="SourceGraphic" in2="effect1_dropShadow_2138_22191" result="shape"/>
</filter>
</defs>
</svg>
import type { InteropMessage } from 'types/api/interop';
import { ADDRESS_HASH } from './addressParams';
import { TX_HASH } from './tx';
export const INTEROP_MESSAGE: InteropMessage = {
init_transaction_hash: TX_HASH,
nonce: 52,
payload: '0x4f0edcc90000000000000000000000007da521cbbe62e89cd75e0993c78b8c68c25f696b',
relay_chain: {
chain_id: 420120000,
chain_name: 'Optimism Testnet',
chain_logo: null,
instance_url: 'https://optimism-interop-alpha-0.blockscout.com/',
},
relay_transaction_hash: TX_HASH,
sender: ADDRESS_HASH,
status: 'Relayed',
target: ADDRESS_HASH,
timestamp: '2025-02-20T01:05:14.000000Z',
};
......@@ -110,6 +110,7 @@ export const TOKEN_TRANSFER_ERC_721: TokenTransfer = {
...TOKEN_TRANSFER_ERC_20,
total: {
token_id: '35870',
token_instance: null,
},
token: TOKEN_INFO_ERC_721,
};
......@@ -120,6 +121,7 @@ export const TOKEN_TRANSFER_ERC_1155: TokenTransfer = {
token_id: '35870',
value: '123',
decimals: '18',
token_instance: null,
},
token: TOKEN_INFO_ERC_1155,
};
......@@ -130,6 +132,7 @@ export const TOKEN_TRANSFER_ERC_404: TokenTransfer = {
token_id: '35870',
value: '123',
decimals: '18',
token_instance: null,
},
token: TOKEN_INFO_ERC_404,
};
......
......@@ -32,6 +32,7 @@ export const STATE_CHANGE_TOKEN: TxStateChange = {
direction: 'to',
total: {
token_id: '1621395',
token_instance: null,
},
},
],
......
......@@ -4,56 +4,58 @@ import { scroller, Element } from 'react-scroll';
import useUpdateEffect from 'lib/hooks/useUpdateEffect';
import type { ButtonProps } from './button';
import { Button } from './button';
import type { LinkProps } from './link';
import { Link } from './link';
interface CollapsibleDetailsProps extends ButtonProps {
interface CollapsibleDetailsProps extends LinkProps {
children: React.ReactNode;
id?: string;
isExpanded?: boolean;
text?: [string, string];
noScroll?: boolean;
}
const SCROLL_CONFIG = {
duration: 500,
smooth: true,
};
const CUT_ID = 'CollapsibleDetails';
export const CollapsibleDetails = (props: CollapsibleDetailsProps) => {
const CUT_ID = 'CollapsibleDetails';
const { children, id = CUT_ID, onClick, isExpanded: isExpandedProp = false, text: textProp, loading, ...rest } = props;
const { children, id = CUT_ID, onClick, isExpanded: isExpandedProp = false, text: textProp, loading, noScroll, ...rest } = props;
const [ isExpanded, setIsExpanded ] = React.useState(isExpandedProp);
const handleClick = React.useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
const handleClick = React.useCallback((event: React.MouseEvent<HTMLAnchorElement>) => {
setIsExpanded((flag) => !flag);
scroller.scrollTo(id, {
duration: 500,
smooth: true,
});
if (!noScroll) {
scroller.scrollTo(id, SCROLL_CONFIG);
}
onClick?.(event);
}, [ id, onClick ]);
}, [ id, noScroll, onClick ]);
useUpdateEffect(() => {
setIsExpanded(isExpandedProp);
isExpandedProp && scroller.scrollTo(id, {
duration: 500,
smooth: true,
});
}, [ isExpandedProp, id ]);
isExpandedProp && !noScroll && scroller.scrollTo(id, SCROLL_CONFIG);
}, [ isExpandedProp, id, noScroll ]);
const text = isExpanded ? (textProp?.[1] ?? 'Hide details') : (textProp?.[0] ?? 'View details');
return (
<>
<Button
variant="link"
<Link
textStyle="sm"
textDecorationLine="underline"
textDecorationStyle="dashed"
w="fit-content"
onClick={ handleClick }
loadingSkeleton={ loading }
loading={ loading }
{ ...rest }
>
<Element name={ id }>{ text }</Element>
</Button>
</Link>
{ isExpanded && children }
</>
);
......@@ -62,7 +64,7 @@ export const CollapsibleDetails = (props: CollapsibleDetailsProps) => {
interface CollapsibleListProps<T> extends FlexProps {
items: Array<T>;
renderItem: (item: T, index: number) => React.ReactNode;
triggerProps?: ButtonProps;
triggerProps?: LinkProps;
cutLength?: number;
}
......@@ -81,8 +83,7 @@ export const CollapsibleList = <T,>(props: CollapsibleListProps<T>) => {
<Flex flexDir="column" w="100%" { ...rest }>
{ items.slice(0, isExpanded ? undefined : cutLength).map(renderItem) }
{ items.length > cutLength && (
<Button
variant="link"
<Link
textStyle="sm"
textDecorationLine="underline"
textDecorationStyle="dashed"
......@@ -92,7 +93,7 @@ export const CollapsibleList = <T,>(props: CollapsibleListProps<T>) => {
{ ...triggerProps }
>
{ isExpanded ? 'Hide' : 'Show all' }
</Button>
</Link>
) }
</Flex>
);
......
......@@ -11,13 +11,15 @@ const PRESETS = {
eth: 'https://eth.blockscout.com',
eth_goerli: 'https://eth-goerli.blockscout.com',
eth_sepolia: 'https://eth-sepolia.blockscout.com',
garnet: 'https://explorer.garnetchain.com',
filecoin: 'https://filecoin.blockscout.com',
garnet: 'https://explorer.garnetchain.com',
gnosis: 'https://gnosis.blockscout.com',
immutable: 'https://explorer.immutable.com',
mekong: 'https://mekong.blockscout.com',
neon_devnet: 'https://neon-devnet.blockscout.com',
optimism: 'https://optimism.blockscout.com',
optimism_celestia: 'https://opcelestia-raspberry.gelatoscout.com',
optimism_interop_0: 'https://optimism-interop-alpha-0.blockscout.com',
optimism_sepolia: 'https://optimism-sepolia.blockscout.com',
polygon: 'https://polygon.blockscout.com',
rari_testnet: 'https://rari-testnet.cloud.blockscout.com',
......
export interface ChainInfo {
chain_id: number;
chain_name: string | null;
chain_logo: string | null;
instance_url: string;
}
export type MessageStatus = 'Sent' | 'Relayed' | 'Failed';
export interface InteropMessage {
init_transaction_hash: string;
init_chain?: ChainInfo | null;
nonce: number;
payload: string;
relay_chain?: ChainInfo | null;
relay_transaction_hash: string | null;
sender: string;
status: MessageStatus;
target: string;
timestamp: string;
}
export interface InteropMessageListResponse {
items: Array<InteropMessage>;
next_page_params?: {
init_transaction_hash: string;
items_count: number;
timestamp: number;
};
}
......@@ -12,6 +12,8 @@ export type RewardsConfigResponse = {
export type RewardsCheckRefCodeResponse = {
valid: boolean;
is_custom: boolean;
reward: string | null;
};
export type RewardsNonceResponse = {
......
......@@ -59,10 +59,12 @@ export interface TokenInstance {
holder_address_hash: string | null;
image_url: string | null;
animation_url: string | null;
media_url?: string | null;
media_type?: string | null;
external_app_url: string | null;
metadata: Record<string, unknown> | null;
owner: AddressParam | null;
thumbnails: Partial<Record<ThumbnailSize, string>> | null;
thumbnails: ({ original: string } & Partial<Record<Exclude<ThumbnailSize, 'original'>, string>>) | null;
}
export interface TokenInstanceMetadataSocketMessage {
......
import type { AddressParam } from './addressParams';
import type { TokenInfo, TokenType } from './token';
import type { TokenInfo, TokenInstance, TokenType } from './token';
export type Erc20TotalPayload = {
decimals: string | null;
......@@ -8,20 +8,24 @@ export type Erc20TotalPayload = {
export type Erc721TotalPayload = {
token_id: string | null;
token_instance: TokenInstance | null;
};
export type Erc1155TotalPayload = {
decimals: string | null;
value: string;
token_id: string | null;
token_instance: TokenInstance | null;
};
export type Erc404TotalPayload = {
decimals: string;
value: string;
token_id: null;
token_instance: TokenInstance | null;
} | {
token_id: string;
token_instance: TokenInstance | null;
};
export type TokenTransfer = (
......
......@@ -3,6 +3,7 @@ import type { ArbitrumBatchStatus, ArbitrumL2TxData } from './arbitrumL2';
import type { BlockTransactionsResponse } from './block';
import type { DecodedInput } from './decodedInput';
import type { Fee } from './fee';
import type { ChainInfo, MessageStatus } from './interop';
import type { NovesTxTranslation } from './noves';
import type { OptimisticL2WithdrawalStatus } from './optimisticL2';
import type { ScrollL2BlockStatus } from './scrollL2';
......@@ -107,6 +108,8 @@ export type Transaction = {
scroll?: ScrollTransactionData;
// EIP-7702
authorization_list?: Array<TxAuthorization>;
// Interop
op_interop?: InteropTransactionInfo;
};
type ArbitrumTransactionData = {
......@@ -215,3 +218,15 @@ export interface TxAuthorization {
chain_id: number;
nonce: number;
}
export interface InteropTransactionInfo {
nonce: number;
payload: string;
init_chain?: ChainInfo | null;
relay_chain?: ChainInfo | null;
init_transaction_hash?: string;
relay_transaction_hash?: string;
sender: string;
status: MessageStatus;
target: string;
}
......@@ -33,6 +33,7 @@ const NFTItem = ({ token, value, isLoading, withTokenLink, ...tokenInstance }: P
<NftMedia
mb="18px"
data={ tokenInstance }
size="md"
isLoading={ isLoading }
autoplayVideo={ false }
/>
......
import { chakra, Text, Flex } from '@chakra-ui/react';
import React from 'react';
import type { InteropMessage } from 'types/api/interop';
import { PopoverBody, PopoverCloseTriggerWrapper, PopoverContent, PopoverRoot, PopoverTrigger } from 'toolkit/chakra/popover';
import AdditionalInfoButton from 'ui/shared/AdditionalInfoButton';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
type Props = {
payload: InteropMessage['payload'];
isLoading?: boolean;
className?: string;
};
const InteropMessageAdditionalInfo = ({ payload, isLoading, className }: Props) => {
return (
<PopoverRoot positioning={{ placement: 'right-start' }}>
<PopoverTrigger>
<AdditionalInfoButton loading={ isLoading } className={ className }/>
</PopoverTrigger>
<PopoverContent w="330px">
<PopoverBody>
<Flex alignItems="center" justifyContent="space-between" mb={ 3 }>
<Text color="text.secondary" fontWeight="600">Message payload</Text>
<PopoverCloseTriggerWrapper>
<CopyToClipboard text={ payload }/>
</PopoverCloseTriggerWrapper>
</Flex>
<Text>
{ payload }
</Text>
</PopoverBody>
</PopoverContent>
</PopoverRoot>
);
};
export default React.memo(chakra(InteropMessageAdditionalInfo));
import React from 'react';
import type { ChainInfo } from 'types/api/interop';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import type { EntityProps } from 'ui/shared/entities/tx/TxEntity';
import TxEntityInterop from 'ui/shared/entities/tx/TxEntityInterop';
type Props = {
relay_transaction_hash?: string | null;
relay_chain?: ChainInfo | null;
truncation?: EntityProps['truncation'];
isLoading?: boolean;
};
const InteropMessageDestinationTx = (props: Props) => {
if (props.relay_chain !== undefined) {
return (
<TxEntityInterop
chain={ props.relay_chain }
hash={ props.relay_transaction_hash }
isLoading={ props.isLoading }
truncation={ props.truncation || 'constant' }
/>
);
}
if (!props.relay_transaction_hash) {
return 'N/A';
}
return (
<TxEntity
hash={ props.relay_transaction_hash }
isLoading={ props.isLoading }
noIcon
truncation={ props.truncation || 'constant' }
/>
);
};
export default InteropMessageDestinationTx;
import React from 'react';
import type { ChainInfo } from 'types/api/interop';
import type { EntityProps } from 'ui/shared/entities/tx/TxEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxEntityInterop from 'ui/shared/entities/tx/TxEntityInterop';
type Props = {
init_transaction_hash?: string | null;
init_chain?: ChainInfo | null;
isLoading?: boolean;
truncation?: EntityProps['truncation'];
};
const InteropMessageSourceTx = (props: Props) => {
if (props.init_chain !== undefined) {
return (
<TxEntityInterop
chain={ props.init_chain }
hash={ props.init_transaction_hash }
isLoading={ props.isLoading }
truncation={ props.truncation || 'constant' }
/>
);
}
if (!props.init_transaction_hash) {
return 'N/A';
}
return (
<TxEntity
hash={ props.init_transaction_hash }
isLoading={ props.isLoading }
noIcon
truncation={ props.truncation || 'constant' }
/>
);
};
export default InteropMessageSourceTx;
import { Flex, HStack, Text, Grid } from '@chakra-ui/react';
import React from 'react';
import type { InteropMessage } from 'types/api/interop';
import AddressFromToIcon from 'ui/shared/address/AddressFromToIcon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import AddressEntityInterop from 'ui/shared/entities/address/AddressEntityInterop';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import InteropMessageStatus from 'ui/shared/statusTag/InteropMessageStatus';
import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip';
import InteropMessageAdditionalInfo from './InteropMessageAdditionalInfo';
import InteropMessageDestinationTx from './InteropMessageDestinationTx';
import InteropMessageSourceTx from './InteropMessageSourceTx';
interface Props {
item: InteropMessage;
isLoading?: boolean;
}
const InteropMessagesListItem = ({ item, isLoading }: Props) => {
return (
<ListItemMobile rowGap={ 2 }>
<Flex alignItems="center" justifyContent="space-between" w="100%">
<InteropMessageStatus status={ item.status } isLoading={ isLoading }/>
<InteropMessageAdditionalInfo payload={ item.payload } isLoading={ isLoading }/>
</Flex>
<Flex alignItems="flex-start" flexDirection="column" gap={ 2 } w="100%">
<HStack w="100%">
<Text fontWeight={ 500 } flexGrow={ 1 }>#{ item.nonce }</Text>
<TimeAgoWithTooltip timestamp={ item.timestamp } isLoading={ isLoading } color="text.secondary"/>
</HStack>
<Grid templateColumns="120px 1fr" rowGap={ 2 }>
<Text as="span" color="text.secondary">Source tx</Text>
<InteropMessageSourceTx { ...item } isLoading={ isLoading }/>
<Text as="span" color="text.secondary">Destination tx</Text>
<InteropMessageDestinationTx { ...item } isLoading={ isLoading }/>
</Grid>
<Flex gap={ 2 } justifyContent="space-between" mt={ 2 }>
{ item.init_chain !== undefined ? (
<AddressEntityInterop
chain={ item.init_chain }
address={{ hash: item.sender }}
isLoading={ isLoading }
truncation="constant"
/>
) : (
<AddressEntity address={{ hash: item.sender }} isLoading={ isLoading } truncation="constant"/>
) }
<AddressFromToIcon
isLoading={ isLoading }
type={ item.init_chain !== undefined ? 'in' : 'out' }
/>
{ item.relay_chain !== undefined ? (
<AddressEntityInterop
chain={ item.relay_chain }
address={{ hash: item.target }}
isLoading={ isLoading }
truncation="constant"
/>
) : (
<AddressEntity address={{ hash: item.target }} isLoading={ isLoading } truncation="constant"/>
) }
</Flex>
</Flex>
</ListItemMobile>
);
};
export default React.memo(InteropMessagesListItem);
import React from 'react';
import type { InteropMessage } from 'types/api/interop';
import { TableBody, TableColumnHeader, TableHeaderSticky, TableRoot, TableRow } from 'toolkit/chakra/table';
import InteropMessagesTableItem from './InteropMessagesTableItem';
interface Props {
items?: Array<InteropMessage>;
top: number;
isLoading?: boolean;
}
const InteropMessagesTable = ({ items, top, isLoading }: Props) => {
return (
<TableRoot tableLayout="auto">
<TableHeaderSticky top={ top }>
<TableRow>
<TableColumnHeader/>
<TableColumnHeader>Message</TableColumnHeader>
<TableColumnHeader>Age</TableColumnHeader>
<TableColumnHeader>Status</TableColumnHeader>
<TableColumnHeader>Source tx</TableColumnHeader>
<TableColumnHeader>Destination tx</TableColumnHeader>
<TableColumnHeader>Sender</TableColumnHeader>
<TableColumnHeader>In/Out</TableColumnHeader>
<TableColumnHeader>Target</TableColumnHeader>
</TableRow>
</TableHeaderSticky>
<TableBody>
{ items?.map((item, index) => (
<InteropMessagesTableItem
key={ item.init_transaction_hash + '_' + index }
item={ item }
isLoading={ isLoading }
/>
)) }
</TableBody>
</TableRoot>
);
};
export default React.memo(InteropMessagesTable);
import React from 'react';
import type { InteropMessage } from 'types/api/interop';
import { Skeleton } from 'toolkit/chakra/skeleton';
import { TableCell, TableRow } from 'toolkit/chakra/table';
import AddressFromToIcon from 'ui/shared/address/AddressFromToIcon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import AddressEntityInterop from 'ui/shared/entities/address/AddressEntityInterop';
import InteropMessageStatus from 'ui/shared/statusTag/InteropMessageStatus';
import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip';
import InteropMessageAdditionalInfo from './InteropMessageAdditionalInfo';
import InteropMessageDestinationTx from './InteropMessageDestinationTx';
import InteropMessageSourceTx from './InteropMessageSourceTx';
interface Props {
item: InteropMessage;
isLoading?: boolean;
}
const InteropMessagesTableItem = ({ item, isLoading }: Props) => {
return (
<TableRow>
<TableCell>
<InteropMessageAdditionalInfo payload={ item.payload } isLoading={ isLoading }/>
</TableCell>
<TableCell>
<Skeleton loading={ isLoading } fontWeight="700">
{ item.nonce }
</Skeleton>
</TableCell>
<TableCell>
<TimeAgoWithTooltip timestamp={ item.timestamp } isLoading={ isLoading } color="text.secondary"/>
</TableCell>
<TableCell>
<InteropMessageStatus status={ item.status } isLoading={ isLoading }/>
</TableCell>
<TableCell>
<InteropMessageSourceTx { ...item } isLoading={ isLoading }/>
</TableCell>
<TableCell>
<InteropMessageDestinationTx { ...item } isLoading={ isLoading }/>
</TableCell>
<TableCell>
{ item.init_chain !== undefined ?
<AddressEntityInterop address={{ hash: item.target }} isLoading={ isLoading } truncation="constant" chain={ item.init_chain }/> :
<AddressEntity address={{ hash: item.target }} isLoading={ isLoading } truncation="constant"/>
}
</TableCell>
<TableCell>
<AddressFromToIcon
isLoading={ isLoading }
type={ item.init_chain !== undefined ? 'in' : 'out' }
/>
</TableCell>
<TableCell>
{ item.relay_chain !== undefined ?
<AddressEntityInterop address={{ hash: item.target }} isLoading={ isLoading } truncation="constant" chain={ item.relay_chain }/> :
<AddressEntity address={{ hash: item.target }} isLoading={ isLoading } truncation="constant"/>
}
</TableCell>
</TableRow>
);
};
export default React.memo(InteropMessagesTableItem);
import React from 'react';
import * as interopMessageMock from 'mocks/interop/interop';
import { test, expect } from 'playwright/lib';
import InteropMessages from './InteropMessages';
test('default view +@mobile', async({ render, mockTextAd, mockAssetResponse, mockApiResponse }) => {
await mockTextAd();
await mockAssetResponse(interopMessageMock.chain.chain_logo as string, './playwright/mocks/image_s.jpg');
await mockApiResponse('optimistic_l2_interop_messages', {
items: [
interopMessageMock.interopMessageIn,
interopMessageMock.interopMessageIn1,
interopMessageMock.interopMessageOut,
interopMessageMock.interopMessageOut1,
],
next_page_params: {
init_transaction_hash: '1',
items_count: 4,
timestamp: 1719456000,
},
});
await mockApiResponse('optimistic_l2_interop_messages_count', 4000000);
const component = await render(<InteropMessages/>);
await expect(component).toHaveScreenshot();
});
import { Box } from '@chakra-ui/react';
import React from 'react';
import useApiQuery from 'lib/api/useApiQuery';
import { INTEROP_MESSAGE } from 'stubs/interop';
import { generateListStub } from 'stubs/utils';
import { Skeleton } from 'toolkit/chakra/skeleton';
import InteropMessagesListItem from 'ui/interopMessages/InteropMessagesListItem';
import InteropMessagesTable from 'ui/interopMessages/InteropMessagesTable';
import { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay';
import PageTitle from 'ui/shared/Page/PageTitle';
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
import StickyPaginationWithText from 'ui/shared/StickyPaginationWithText';
const InteropMessages = () => {
const interopMessagesQuery = useQueryWithPages({
resourceName: 'optimistic_l2_interop_messages',
options: {
placeholderData: generateListStub<'optimistic_l2_interop_messages'>(INTEROP_MESSAGE, 50, { next_page_params: {
init_transaction_hash: '',
items_count: 50,
timestamp: 0,
} }),
},
});
const countQuery = useApiQuery('optimistic_l2_interop_messages_count', {
queryOptions: {
placeholderData: 1927029,
},
});
const text = (() => {
if (countQuery.isError) {
return null;
}
return (
<Skeleton loading={ countQuery.isPlaceholderData }>
A total of { countQuery.data?.toLocaleString() } messages found
</Skeleton>
);
})();
const actionBar = <StickyPaginationWithText text={ text } pagination={ interopMessagesQuery.pagination }/>;
const content = (
<>
<Box hideFrom="lg">
{ interopMessagesQuery.data?.items.map((item, index) => (
<InteropMessagesListItem
key={ item.init_transaction_hash + (interopMessagesQuery.isPlaceholderData ? index : '') }
item={ item }
isLoading={ interopMessagesQuery.isPlaceholderData }
/>
)) }
</Box>
<Box hideBelow="lg">
<InteropMessagesTable
items={ interopMessagesQuery.data?.items }
top={ interopMessagesQuery.pagination.isVisible ? ACTION_BAR_HEIGHT_DESKTOP : 0 }
isLoading={ interopMessagesQuery.isPlaceholderData }
/>
</Box>
</>
);
return (
<>
<PageTitle
title="Interop messages"
withTextAd
/>
<DataListDisplay
isError={ interopMessagesQuery.isError }
itemsNum={ interopMessagesQuery.data?.items.length }
emptyText="There are no interop messages."
actionBar={ actionBar }
>
{ content }
</DataListDisplay>
</>
);
};
export default InteropMessages;
......@@ -5,12 +5,12 @@ import config from 'configs/app';
import { useRewardsContext } from 'lib/contexts/rewards';
import { apos } from 'lib/html-entities';
import { Alert } from 'toolkit/chakra/alert';
import { Image } from 'toolkit/chakra/image';
import { Link } from 'toolkit/chakra/link';
import { Skeleton } from 'toolkit/chakra/skeleton';
import DailyRewardClaimButton from 'ui/rewards/dashboard/DailyRewardClaimButton';
import RewardsDashboardCard from 'ui/rewards/dashboard/RewardsDashboardCard';
import RewardsDashboardCardValue from 'ui/rewards/dashboard/RewardsDashboardCardValue';
import RewardsDashboardInfoCard from 'ui/rewards/dashboard/RewardsDashboardInfoCard';
import RewardsReadOnlyInputWithCopy from 'ui/rewards/RewardsReadOnlyInputWithCopy';
import AdBanner from 'ui/shared/ad/AdBanner';
import PageTitle from 'ui/shared/Page/PageTitle';
......@@ -53,7 +53,7 @@ const RewardsDashboard = () => {
<span>
The Blockscout Merits Program is just getting started! Learn more about the details,
features, and future plans in our{ ' ' }
<Link external href="https://www.blog.blockscout.com/blockscout-merits-rewarding-block-explorer-skills">
<Link external href={ `https://merits.blockscout.com/?tab=users&utm_source=${ config.chain.id }&utm_medium=text-banner` }>
blog post
</Link>.
</span>
......@@ -69,12 +69,6 @@ const RewardsDashboard = () => {
description="Claim your daily Merits and any Merits received from referrals."
direction="column-reverse"
contentAfter={ <DailyRewardClaimButton/> }
>
<RewardsDashboardCardValue
label="Total balance"
value={ balancesQuery.data?.total || 'N/A' }
isLoading={ balancesQuery.isPending }
withIcon
hint={ (
<>
Total number of Merits earned from all activities.{ ' ' }
......@@ -83,6 +77,11 @@ const RewardsDashboard = () => {
</Link>
</>
) }
>
<RewardsDashboardCardValue
value={ balancesQuery.data?.total || 'N/A' }
isLoading={ balancesQuery.isPending }
withIcon
/>
</RewardsDashboardCard>
<RewardsDashboardCard
......@@ -91,7 +90,6 @@ const RewardsDashboard = () => {
direction="column-reverse"
>
<RewardsDashboardCardValue
label="Referrals"
value={ referralsQuery.data?.referrals ?
`${ referralsQuery.data?.referrals } user${ Number(referralsQuery.data?.referrals) === 1 ? '' : 's' }` :
'N/A'
......@@ -110,29 +108,26 @@ const RewardsDashboard = () => {
</Link>
</>
) }
hint={ (
<>
See the{ ' ' }
<Link external href="https://docs.blockscout.com/using-blockscout/merits/streak-rewards">docs</Link>{ ' ' }
to learn how your streak number affects daily rewards
</>
) }
direction="column-reverse"
>
<RewardsDashboardCardValue
label="Streak"
value={
dailyRewardQuery.data?.streak ?
`${ dailyRewardQuery.data?.streak } day${ Number(dailyRewardQuery.data?.streak) === 1 ? '' : 's' }` :
'N/A'
}
isLoading={ dailyRewardQuery.isPending }
hint={ (
<>
See the{ ' ' }
<Link external href="https://docs.blockscout.com/using-blockscout/merits/streak-rewards">
docs
</Link>{ ' ' }
to learn how your streak number affects daily rewards
</>
) }
/>
</RewardsDashboardCard>
</Flex>
<Flex gap={ 6 } flexDirection={{ base: 'column', md: 'row' }}>
<Flex w="full" gap={ 6 } flexDirection={{ base: 'column', md: 'row' }}>
<RewardsDashboardCard
title="Referral program"
description={ (
......@@ -169,46 +164,38 @@ const RewardsDashboard = () => {
/>
</Flex>
</RewardsDashboardCard>
<RewardsDashboardCard
<RewardsDashboardInfoCard
title="Badges"
description={ (
<Flex flexDir="column" gap={ 2 }>
<span>
Collect limited and legendary badges by completing different Blockscout related tasks.
Go to the badges website to see what{ apos }s available and start your collection today.
</span>
</Flex>
) }
>
<Flex
flex={ 1 }
gap={ 4 }
pl={ 10 }
pr={ 7 }
py={{ base: 4, lg: 0 }}
flexDirection={{ base: 'column', lg: 'row' }}
justifyContent="space-between"
alignItems="center"
>
<Image
src="/static/badges.svg"
alt="Badges"
w="260px"
h="86px"
fallback={ <Skeleton loading w="260px" h="86px"/> }
description={ `Collect limited and legendary badges by completing different Blockscout related tasks.
Go to the badges website to see what${ apos }s available and start your collection today.` }
imageSrc="/static/merits/badges.svg"
imageWidth="260px"
imageHeight="86px"
linkText="View badges"
linkHref={ `https://merits.blockscout.com/?tab=badges&utm_source=${ config.chain.id }&utm_medium=badges` }
/>
<Link
external
href="https://merits.blockscout.com/?tab=badges&utm_source=blockscout&utm_medium=dashboard"
textStyle="md"
fontWeight="500"
>
View badges
</Link>
</Flex>
</RewardsDashboardCard>
<Flex w="full" gap={ 6 } flexDirection={{ base: 'column', md: 'row' }}>
<RewardsDashboardInfoCard
title="Blockscout campaigns"
description="Join Blockscout activities to earn bonus Merits and exclusive rewards from our partners!"
imageSrc="/static/merits/campaigns.svg"
imageWidth="180px"
imageHeight="76px"
linkText="Check campaigns"
linkHref={ `https://merits.blockscout.com/?tab=campaigns&utm_source=${ config.chain.id }&utm_medium=campaigns` }
/>
<RewardsDashboardInfoCard
title="Use your Merits"
description="Spend your Merits to get exclusive discounts and offers across several web3 products!"
imageSrc="/static/merits/offers.svg"
imageWidth="180px"
imageHeight="86px"
linkText="Check offers"
linkHref={ `https://merits.blockscout.com/?tab=redeem&utm_source=${ config.chain.id }&utm_medium=redeem` }
/>
</Flex>
<Flex gap={ 6 } flexDirection={{ base: 'column', md: 'row' }}>
<Flex w="full" gap={ 6 } flexDirection={{ base: 'column', md: 'row' }}>
<RewardsDashboardCard
title="Activity"
description="Earn Merits for your everyday Blockscout activities. You deserve to be rewarded for choosing open-source public goods!"
......
......@@ -97,7 +97,16 @@ const TokenInstanceContent = () => {
{
id: 'token_transfers',
title: 'Token transfers',
component: <TokenTransfer transfersQuery={ transfersQuery } tokenId={ id } tokenQuery={ tokenQuery } shouldRender={ !isLoading } tabsHeight={ 80 }/>,
component: (
<TokenTransfer
transfersQuery={ transfersQuery }
tokenId={ id }
tokenQuery={ tokenQuery }
tokenInstance={ tokenInstanceQuery.data }
shouldRender={ !isLoading }
tabsHeight={ 80 }
/>
),
},
shouldFetchHolders ?
{
......
import { Box } from '@chakra-ui/react';
import React from 'react';
import * as tokenInstanceMock from 'mocks/tokens/tokenInstance';
import { mixTokens } from 'mocks/tokens/tokenTransfer';
import { test, expect } from 'playwright/lib';
import TokenTransfers from './TokenTransfers';
test('base view +@mobile', async({ render, mockTextAd, mockApiResponse }) => {
test('base view +@mobile', async({ render, mockTextAd, mockApiResponse, mockAssetResponse }) => {
await mockAssetResponse(tokenInstanceMock.base.image_url as string, './playwright/mocks/image_s.jpg');
await mockTextAd();
await mockApiResponse('token_transfers_all', mixTokens, { queryParams: { type: [] } });
const component = await render(<Box pt={{ base: '106px', lg: 0 }}> <TokenTransfers/> </Box>);
......
......@@ -2,6 +2,7 @@ import { useRouter } from 'next/router';
import React from 'react';
import type { TabItemRegular } from 'toolkit/components/AdaptiveTabs/types';
import type { EntityTag as TEntityTag } from 'ui/shared/EntityTags/types';
import config from 'configs/app';
import { useAppContext } from 'lib/contexts/app';
......@@ -31,6 +32,7 @@ import TxUserOps from 'ui/tx/TxUserOps';
import useTxQuery from 'ui/tx/useTxQuery';
const txInterpretation = config.features.txInterpretation;
const rollupFeature = config.features.rollup;
const TransactionPageContent = () => {
const router = useRouter();
......@@ -78,10 +80,21 @@ const TransactionPageContent = () => {
const activeTab = useActiveTabFromQuery(tabs);
const txTags: Array<TEntityTag> = data?.transaction_tag ?
[ { slug: data.transaction_tag, name: data.transaction_tag, tagType: 'private_tag' as const, ordinal: 1 } ] : [];
if (rollupFeature.isEnabled && rollupFeature.interopEnabled && data?.op_interop) {
if (data.op_interop.init_chain !== undefined) {
txTags.push({ slug: 'relay_tx', name: 'Relay tx', tagType: 'custom' as const, ordinal: 0 });
}
if (data.op_interop.relay_chain !== undefined) {
txTags.push({ slug: 'init_tx', name: 'Source tx', tagType: 'custom' as const, ordinal: 0 });
}
}
const tags = (
<EntityTags
isLoading={ isPlaceholderData }
tags={ data?.transaction_tag ? [ { slug: data.transaction_tag, name: data.transaction_tag, tagType: 'private_tag' as const, ordinal: 10 } ] : [] }
tags={ txTags }
/>
);
......
......@@ -2,10 +2,12 @@ import { Flex, Text } from '@chakra-ui/react';
import React from 'react';
import { Badge } from 'toolkit/chakra/badge';
import Hint from 'ui/shared/Hint';
type Props = {
title?: string;
title: string;
description: string | React.ReactNode;
hint?: string | React.ReactNode;
availableSoon?: boolean;
blurFilter?: boolean;
contentAfter?: React.ReactNode;
......@@ -15,7 +17,7 @@ type Props = {
};
const RewardsDashboardCard = ({
title, description, availableSoon, contentAfter,
title, description, hint, availableSoon, contentAfter,
direction = 'column', children, blurFilter,
}: Props) => {
return (
......@@ -36,12 +38,11 @@ const RewardsDashboardCard = ({
p={{ base: 1.5, md: 3 }}
w={{ base: 'full', md: direction === 'row' ? '340px' : 'full' }}
>
{ title && (
<Flex alignItems="center" gap={ 2 }>
<Text fontSize={{ base: 'md', md: 'lg' }} fontWeight="500">{ title }</Text>
{ hint && <Hint label={ hint }/> }
{ availableSoon && <Badge colorPalette="blue">Available soon</Badge> }
</Flex>
) }
<Text as="div" fontSize="sm">
{ description }
</Text>
......
......@@ -7,7 +7,7 @@ import Hint from 'ui/shared/Hint';
import MeritsIcon from '../MeritsIcon';
type Props = {
label: string;
label?: string;
value: number | string | undefined;
withIcon?: boolean;
hint?: string | React.ReactNode;
......@@ -16,6 +16,7 @@ type Props = {
const RewardsDashboardCard = ({ label, value, withIcon, hint, isLoading }: Props) => (
<Flex key={ label } flexDirection="column" alignItems="center" gap={ 2 }>
{ label && (
<Flex alignItems="center" gap={ 1 }>
{ hint && (
<Hint label={ hint }/>
......@@ -24,6 +25,7 @@ const RewardsDashboardCard = ({ label, value, withIcon, hint, isLoading }: Props
{ label }
</Text>
</Flex>
) }
<Skeleton
loading={ isLoading }
display="flex"
......
import { Flex } from '@chakra-ui/react';
import React from 'react';
import { Image } from 'toolkit/chakra/image';
import { Link } from 'toolkit/chakra/link';
import { Skeleton } from 'toolkit/chakra/skeleton';
import RewardsDashboardCard from './RewardsDashboardCard';
type Props = {
title: string;
description: string | React.ReactNode;
imageSrc: string;
imageWidth: string;
imageHeight: string;
linkText: string;
linkHref: string;
};
const RewardsDashboardInfoCard = ({ title, description, imageSrc, imageWidth, imageHeight, linkText, linkHref }: Props) => (
<RewardsDashboardCard
title={ title }
description={ description }
>
<Flex
flex={ 1 }
gap={ 4 }
pl={ 10 }
pr={ 7 }
py={{ base: 4, lg: 0 }}
flexDirection={{ base: 'column', lg: 'row' }}
justifyContent="space-between"
alignItems="center"
>
<Image
src={ imageSrc }
alt={ title }
w={ imageWidth }
h={ imageHeight }
fallback={ <Skeleton loading w={ imageWidth } h={ imageHeight }/> }
/>
<Link
external
href={ linkHref }
fontSize="md"
fontWeight="500"
>
{ linkText }
</Link>
</Flex>
</RewardsDashboardCard>
);
export default RewardsDashboardInfoCard;
......@@ -26,6 +26,7 @@ const RewardsLoginModal = () => {
const [ isLoginStep, setIsLoginStep ] = React.useState(true);
const [ isReferral, setIsReferral ] = React.useState(false);
const [ customReferralReward, setCustomReferralReward ] = React.useState<string | null>(null);
const [ authModalInitialScreen, setAuthModalInitialScreen ] = React.useState<Screen>();
const authModal = useDisclosure();
......@@ -33,13 +34,13 @@ const RewardsLoginModal = () => {
if (!isLoginModalOpen) {
setIsLoginStep(true);
setIsReferral(false);
setCustomReferralReward(null);
}
}, [ isLoginModalOpen, setIsLoginStep, setIsReferral ]);
}, [ isLoginModalOpen ]);
const goNext = useCallback((isReferral: boolean) => {
if (isReferral) {
setIsReferral(true);
}
const goNext = useCallback((isReferral: boolean, reward: string | null) => {
setIsReferral(isReferral);
setCustomReferralReward(reward);
setIsLoginStep(false);
}, [ setIsLoginStep, setIsReferral ]);
......@@ -78,7 +79,7 @@ const RewardsLoginModal = () => {
<DialogBody>
{ isLoginStep ?
<LoginStepContent goNext={ goNext } openAuthModal={ handleAuthModalOpen } closeModal={ closeLoginModal }/> :
<CongratsStepContent isReferral={ isReferral }/>
<CongratsStepContent isReferral={ isReferral } customReferralReward={ customReferralReward }/>
}
</DialogBody>
</DialogContent>
......
......@@ -13,14 +13,17 @@ import RewardsReadOnlyInputWithCopy from '../../RewardsReadOnlyInputWithCopy';
type Props = {
isReferral: boolean;
customReferralReward: string | null;
};
const CongratsStepContent = ({ isReferral }: Props) => {
const CongratsStepContent = ({ isReferral, customReferralReward }: Props) => {
const { referralsQuery, rewardsConfigQuery } = useRewardsContext();
const registrationReward = rewardsConfigQuery.data?.rewards.registration;
const registrationWithReferralReward = rewardsConfigQuery.data?.rewards.registration_with_referral;
const referralReward = Number(registrationWithReferralReward) - Number(registrationReward);
const registrationReward = Number(rewardsConfigQuery.data?.rewards.registration);
const registrationWithReferralReward = customReferralReward ?
Number(customReferralReward) + registrationReward :
Number(rewardsConfigQuery.data?.rewards.registration_with_referral);
const referralReward = registrationWithReferralReward - registrationReward;
const refLink = referralsQuery.data?.link || 'N/A';
const shareText = `I joined the @blockscout Merits Program and got my first ${ registrationReward || 'N/A' } #Merits! Use this link for a sign-up bonus and start earning rewards with @blockscout block explorer.\n\n${ refLink }`; // eslint-disable-line max-len
......@@ -41,7 +44,7 @@ const CongratsStepContent = ({ isReferral }: Props) => {
<MeritsIcon boxSize={{ base: isReferral ? 8 : 12, md: 12 }} mr={{ base: isReferral ? 1 : 2, md: 2 }}/>
<Skeleton loading={ rewardsConfigQuery.isLoading }>
<Text fontSize={{ base: isReferral ? '24px' : '30px', md: '30px' }} fontWeight="700" color={ textColor }>
+{ rewardsConfigQuery.data?.rewards[ isReferral ? 'registration_with_referral' : 'registration' ] || 'N/A' }
+{ (isReferral ? registrationWithReferralReward : registrationReward) || 'N/A' }
</Text>
</Skeleton>
{ isReferral && (
......
......@@ -18,7 +18,7 @@ import { Switch } from 'toolkit/chakra/switch';
import useProfileQuery from 'ui/snippets/auth/useProfileQuery';
type Props = {
goNext: (isReferral: boolean) => void;
goNext: (isReferral: boolean, reward: string | null) => void;
closeModal: () => void;
openAuthModal: (isAuth: boolean, trySharedLogin?: boolean) => void;
};
......@@ -58,12 +58,12 @@ const LoginStepContent = ({ goNext, closeModal, openAuthModal }: Props) => {
try {
setRefCodeError(false);
setIsLoading(true);
const { isNewUser, invalidRefCodeError } = await login(isSignUp && isRefCodeUsed ? refCode : '');
const { isNewUser, reward, invalidRefCodeError } = await login(isSignUp && isRefCodeUsed ? refCode : '');
if (invalidRefCodeError) {
setRefCodeError(true);
} else {
if (isNewUser) {
goNext(isRefCodeUsed);
goNext(isRefCodeUsed, reward);
} else {
closeModal();
router.push({ pathname: '/account/merits' }, undefined, { shallow: true });
......@@ -71,14 +71,11 @@ const LoginStepContent = ({ goNext, closeModal, openAuthModal }: Props) => {
}
} catch (error) {}
setIsLoading(false);
}, [ login, goNext, setIsLoading, router, closeModal, refCode, setRefCodeError, isRefCodeUsed, isSignUp ]);
}, [ login, goNext, router, closeModal, refCode, isRefCodeUsed, isSignUp ]);
React.useEffect(() => {
if (isSignUp && isRefCodeUsed && refCode.length > 0 && refCode.length !== 6) {
setRefCodeError(true);
} else {
setRefCodeError(false);
}
const isInvalid = isSignUp && isRefCodeUsed && refCode.length > 0 && refCode.length !== 6 && refCode.length !== 12;
setRefCodeError(isInvalid);
}, [ refCode, isRefCodeUsed, isSignUp ]);
const handleButtonClick = React.useCallback(() => {
......@@ -118,7 +115,7 @@ const LoginStepContent = ({ goNext, closeModal, openAuthModal }: Props) => {
return (
<>
<Image
src="/static/merits_program.png"
src="/static/merits/merits_program.png"
alt="Merits program"
mb={ 3 }
fallback={ <Skeleton loading w="full" h="120px" mb={ 3 }/> }
......@@ -150,7 +147,7 @@ const LoginStepContent = ({ goNext, closeModal, openAuthModal }: Props) => {
mt={ 3 }
invalid={ refCodeError }
helperText="The code should be in format XXXXXX"
errorText={ refCodeError ? 'Incorrect code or format' : undefined }
errorText={ refCodeError ? 'Incorrect code or format (6 or 12 characters)' : undefined }
>
<Input
value={ refCode }
......
import { Box } from '@chakra-ui/react';
import React from 'react';
import * as tokenInstanceMock from 'mocks/tokens/tokenInstance';
import * as tokenTransferMock from 'mocks/tokens/tokenTransfer';
import { test, expect, devices } from 'playwright/lib';
......@@ -23,7 +24,8 @@ const data = [
tokenTransferMock.erc1155D,
];
test('without tx info', async({ render }) => {
test('without tx info', async({ render, mockAssetResponse }) => {
await mockAssetResponse(tokenInstanceMock.base.image_url as string, './playwright/mocks/image_s.jpg');
const component = await render(
<Box pt={{ base: '134px', lg: 6 }}>
<TokenTransferList
......@@ -36,7 +38,8 @@ test('without tx info', async({ render }) => {
await expect(component).toHaveScreenshot();
});
test('with tx info', async({ render }) => {
test('with tx info', async({ render, mockAssetResponse }) => {
await mockAssetResponse(tokenInstanceMock.base.image_url as string, './playwright/mocks/image_s.jpg');
const component = await render(
<Box pt={{ base: '134px', lg: 6 }}>
<TokenTransferList
......
......@@ -68,7 +68,7 @@ const TokenTransferListItem = ({
) }
</Flex>
{ total && 'token_id' in total && total.token_id !== null && token && (
<NftEntity hash={ token.address } id={ total.token_id } isLoading={ isLoading }/>
<NftEntity hash={ token.address } id={ total.token_id } instance={ total.token_instance } isLoading={ isLoading }/>
) }
{ showTxInfo && txHash && (
<Flex justifyContent="space-between" alignItems="center" lineHeight="24px" width="100%">
......
import { Box } from '@chakra-ui/react';
import React from 'react';
import * as tokenInstanceMock from 'mocks/tokens/tokenInstance';
import * as tokenTransferMock from 'mocks/tokens/tokenTransfer';
import { test, expect } from 'playwright/lib';
import TokenTransferTable from './TokenTransferTable';
test('without tx info', async({ render }) => {
test('without tx info', async({ render, mockAssetResponse }) => {
await mockAssetResponse(tokenInstanceMock.base.image_url as string, './playwright/mocks/image_s.jpg');
const component = await render(
<Box pt={{ base: '134px', lg: 6 }}>
<TokenTransferTable
......@@ -20,7 +22,8 @@ test('without tx info', async({ render }) => {
await expect(component).toHaveScreenshot();
});
test('with tx info', async({ render }) => {
test('with tx info', async({ render, mockAssetResponse }) => {
await mockAssetResponse(tokenInstanceMock.base.image_url as string, './playwright/mocks/image_s.jpg');
const component = await render(
<Box pt={{ base: '134px', lg: 6 }}>
<TokenTransferTable
......
......@@ -76,6 +76,7 @@ const TokenTransferTableItem = ({
<NftEntity
hash={ token.address }
id={ total.token_id }
instance={ total.token_instance }
isLoading={ isLoading }
/>
) }
......
......@@ -44,6 +44,7 @@ const TokenTransferSnippet = ({ data, isLoading, noAddressIcons = true }: Props)
<TokenTransferSnippetNft
token={ data.token }
tokenId={ total.token_id }
instance={ total.token_instance }
value="1"
/>
);
......@@ -56,6 +57,7 @@ const TokenTransferSnippet = ({ data, isLoading, noAddressIcons = true }: Props)
key={ total.token_id }
token={ data.token }
tokenId={ total.token_id }
instance={ total.token_instance }
value={ total.value }
/>
);
......
import { chakra } from '@chakra-ui/react';
import React from 'react';
import type { TokenInfo } from 'types/api/token';
import type { TokenInfo, TokenInstance } from 'types/api/token';
import NftEntity from 'ui/shared/entities/nft/NftEntity';
import TokenEntity from 'ui/shared/entities/token/TokenEntity';
......@@ -10,9 +10,10 @@ interface Props {
token: TokenInfo;
value: string;
tokenId: string | null;
instance?: TokenInstance | null;
}
const NftTokenTransferSnippet = ({ value, token, tokenId }: Props) => {
const NftTokenTransferSnippet = ({ value, token, tokenId, instance }: Props) => {
const num = value === '1' ? '' : value;
const tokenIdContent = (() => {
......@@ -28,6 +29,7 @@ const NftTokenTransferSnippet = ({ value, token, tokenId }: Props) => {
<NftEntity
hash={ token.address }
id={ tokenId }
instance={ instance }
fontWeight={ 600 }
variant="content"
maxW={{ base: '100%', lg: '150px' }}
......
import React from 'react';
import * as addressMock from 'mocks/address/address';
import * as interopMock from 'mocks/interop/interop';
import { test, expect } from 'playwright/lib';
import AddressEntityInterop from './AddressEntityInterop';
test.use({ viewport: { width: 180, height: 140 } });
test('with chain icon', async({ render, mockAssetResponse }) => {
await mockAssetResponse('https://example.com/logo.png', './playwright/mocks/image_svg.svg');
const component = await render(
<AddressEntityInterop
address={ addressMock.withoutName }
chain={ interopMock.chain }
/>,
);
await expect(component).toHaveScreenshot();
});
test('with chain icon stub +@dark-mode', async({ render }) => {
const component = await render(
<AddressEntityInterop
address={ addressMock.withoutName }
chain={{ ...interopMock.chain, chain_logo: null }}
/>,
);
await expect(component).toHaveScreenshot();
});
import { Box, chakra, Flex } from '@chakra-ui/react';
import React from 'react';
import type { ChainInfo } from 'types/api/interop';
import { route } from 'nextjs-routes';
import { Image } from 'toolkit/chakra/image';
import { Tooltip } from 'toolkit/chakra/tooltip';
import IconSvg from 'ui/shared/IconSvg';
import { distributeEntityProps } from '../base/utils';
import * as AddressEntity from './AddressEntity';
interface Props extends AddressEntity.EntityProps {
chain: ChainInfo | null;
}
const IconStub = () => {
return (
<Flex
position="absolute"
bottom="-2px"
right="4px"
alignItems="center"
justifyContent="center"
borderRadius="base"
background={{ _light: 'gray.100', _dark: 'gray.700' }}
width="14px"
height="14px"
border="1px solid"
borderColor="global.body.bg"
>
<IconSvg
name="networks/icon-placeholder"
width="10px"
height="10px"
color="text.secondary"
/>
</Flex>
);
};
const AddressEntryInterop = (props: Props) => {
const partsProps = distributeEntityProps(props);
const href = props.chain?.instance_url ? props.chain.instance_url.replace(/\/$/, '') + route({
pathname: '/address/[hash]',
query: {
...props.query,
hash: props.address.hash,
},
}) : null;
const addressIcon = (
<Box position="relative">
<AddressEntity.Icon { ...partsProps.icon }/>
{ !props.isLoading && (
props.chain?.chain_logo ? (
<Image
position="absolute"
bottom="-3px"
right="4px"
src={ props.chain.chain_logo }
alt={ props.chain.chain_name || 'external chain logo' }
width="14px"
height="14px"
borderRadius="base"
/>
) : (
<IconStub/>
)
) }
</Box>
);
return (
<AddressEntity.Container>
{ props.chain && (
<Tooltip content={ `Address on ${ props.chain.chain_name ? props.chain.chain_name : 'external chain' } (chain id ${ props.chain.chain_id })` }>
{ addressIcon }
</Tooltip>
) }
{ !props.chain && addressIcon }
{ href ? (
<AddressEntity.Link { ...partsProps.link } href={ href } isExternal>
<AddressEntity.Content { ...partsProps.content }/>
</AddressEntity.Link>
) : (
<AddressEntity.Content { ...partsProps.content }/>
) }
<AddressEntity.Copy { ...partsProps.copy }/>
</AddressEntity.Container>
);
};
export default chakra(AddressEntryInterop);
import { chakra } from '@chakra-ui/react';
import React from 'react';
import type { TokenInstance } from 'types/api/token';
import { route } from 'nextjs-routes';
import * as EntityBase from 'ui/shared/entities/base/components';
import NftMedia from 'ui/shared/nft/NftMedia';
import { distributeEntityProps } from '../base/utils';
import { distributeEntityProps, getIconProps } from '../base/utils';
const Container = EntityBase.Container;
const Icon = (props: EntityBase.IconBaseProps) => {
type IconProps = EntityBase.IconBaseProps & {
instance?: TokenInstance | null;
};
const ICON_MEDIA_TYPES = [ 'image' as const ];
const Icon = (props: IconProps) => {
if (props.noIcon) {
return null;
}
if (props.instance) {
const styles = getIconProps(props.variant ?? 'heading');
const fallback = (
<EntityBase.Icon
{ ...props }
variant={ props.variant ?? 'heading' }
name={ props.name ?? 'nft_shield' }
marginRight={ 0 }
/>
);
return (
<NftMedia
data={ props.instance }
isLoading={ props.isLoading }
boxSize={ styles.boxSize }
size="sm"
allowedTypes={ ICON_MEDIA_TYPES }
borderRadius="sm"
flexShrink={ 0 }
mr={ 2 }
fallback={ fallback }
/>
);
}
return (
<EntityBase.Icon
{ ...props }
......@@ -53,6 +88,7 @@ const Content = chakra((props: ContentProps) => {
export interface EntityProps extends EntityBase.EntityBaseProps {
hash: string;
id: string;
instance?: TokenInstance | null;
}
const NftEntity = (props: EntityProps) => {
......
import React from 'react';
import * as interopMock from 'mocks/interop/interop';
import { test, expect } from 'playwright/lib';
import TxEntityInterop from './TxEntityInterop';
const hash = '0x376db52955d5bce114d0ccea2dcf22289b4eae1b86bcae5a59bb5fdbfef48899';
test.use({ viewport: { width: 180, height: 30 } });
test('with chain icon', async({ render, mockAssetResponse }) => {
await mockAssetResponse('https://example.com/logo.png', './playwright/mocks/image_svg.svg');
const component = await render(
<TxEntityInterop
hash={ hash }
chain={ interopMock.chain }
/>,
);
await expect(component).toHaveScreenshot();
});
test('with chain icon stub +@dark-mode', async({ render }) => {
const component = await render(
<TxEntityInterop
hash={ hash }
chain={{ ...interopMock.chain, chain_logo: null }}
/>,
);
await expect(component).toHaveScreenshot();
});
import { Box, chakra } from '@chakra-ui/react';
import React from 'react';
import type { ChainInfo } from 'types/api/interop';
import { route } from 'nextjs-routes';
import stripTrailingSlash from 'lib/stripTrailingSlash';
import { Image } from 'toolkit/chakra/image';
import { Skeleton } from 'toolkit/chakra/skeleton';
import { Tooltip } from 'toolkit/chakra/tooltip';
import IconSvg from 'ui/shared/IconSvg';
import { distributeEntityProps } from '../base/utils';
import * as TxEntity from './TxEntity';
type Props = {
chain: ChainInfo | null;
hash?: string | null;
} & Omit<TxEntity.EntityProps, 'hash'>;
const IconStub = ({ isLoading }: { isLoading?: boolean }) => {
return (
<Skeleton
loading={ !isLoading }
display="flex"
minWidth="20px"
h="20px"
borderRadius="full"
background={{ _light: 'blackAlpha.100', _dark: 'whiteAlpha.100' }}
alignItems="center"
justifyContent="center"
mr={ 2 }
>
<IconSvg
name="networks/icon-placeholder"
width="16px"
height="16px"
color="text.secondary"
display="block"
/>
</Skeleton>
);
};
const TxEntityInterop = ({ chain, hash, ...props }: Props) => {
const partsProps = distributeEntityProps(props);
const href = (chain?.instance_url && hash) ? stripTrailingSlash(chain.instance_url) + route({
pathname: '/tx/[hash]',
query: {
...props.query,
hash: hash,
},
}) : null;
return (
<TxEntity.Container { ...partsProps.container }>
{ chain && (
<Tooltip content={ `${ chain.chain_name ? chain.chain_name : 'External chain' } (chain id ${ chain.chain_id })` }>
<Box>
{ chain.chain_logo ? (
<Image
src={ chain.chain_logo }
alt={ chain.chain_name || 'external chain logo' }
width="20px"
height="20px"
mr={ 2 }
borderRadius="base"
/>
) : (
<IconStub isLoading={ props.isLoading }/>
) }
</Box>
</Tooltip>
) }
{ !chain && (
<IconStub/>
) }
{ hash && (
<>
{ href ? (
<TxEntity.Link { ...partsProps.link } hash={ hash } href={ href } isExternal>
<TxEntity.Content { ...partsProps.content } hash={ hash }/>
</TxEntity.Link>
) : (
<TxEntity.Content { ...partsProps.content } hash={ hash }/>
) }
<TxEntity.Copy { ...partsProps.copy } hash={ hash }/>
</>
) }
{ !hash && (
'N/A'
) }
</TxEntity.Container>
);
};
export default chakra(TxEntityInterop);
......@@ -3,29 +3,55 @@ import React from 'react';
import { LinkOverlay } from 'toolkit/chakra/link';
import { mediaStyleProps } from './utils';
import type { MediaElementProps } from './utils';
interface Props {
src: string;
onLoad: () => void;
onError: () => void;
onClick?: () => void;
}
interface Props extends MediaElementProps<'a'> {}
const NftHtml = ({ src, transport, onLoad, onError, onClick, ...rest }: Props) => {
const ref = React.useRef<HTMLIFrameElement>(null);
const [ isLoaded, setIsLoaded ] = React.useState(false);
const handleLoad = React.useCallback(() => {
setIsLoaded(true);
onLoad?.();
}, [ onLoad ]);
const loadViaHttp = React.useCallback(async() => {
if (!ref.current) {
return;
}
ref.current.src = src;
ref.current.onload = handleLoad;
onError && (ref.current.onerror = onError);
}, [ src, handleLoad, onError ]);
React.useEffect(() => {
switch (transport) {
case 'ipfs': {
// Currently we don't support IPFS video loading
onError?.();
break;
}
case 'http':
loadViaHttp();
break;
}
}, [ loadViaHttp, onError, transport ]);
const NftHtml = ({ src, onLoad, onError, onClick }: Props) => {
return (
<LinkOverlay
onClick={ onClick }
h="100%"
{ ...mediaStyleProps }
{ ...rest }
>
<chakra.iframe
src={ src }
ref={ ref }
h="100%"
w="100%"
sandbox="allow-scripts"
onLoad={ onLoad }
onError={ onError }
opacity={ isLoaded ? 1 : 0 }
/>
</LinkOverlay>
);
......
import { chakra } from '@chakra-ui/react';
import React from 'react';
import NftMediaFullscreenModal from './NftMediaFullscreenModal';
interface Props {
src: string;
open: boolean;
onOpenChange: ({ open }: { open: boolean }) => void;
}
const NftHtmlFullscreen = ({ src, open, onOpenChange }: Props) => {
return (
<NftMediaFullscreenModal open={ open } onOpenChange={ onOpenChange }>
<chakra.iframe
w="90vw"
h="90vh"
src={ src }
sandbox="allow-scripts"
/>
</NftMediaFullscreenModal>
);
};
export default NftHtmlFullscreen;
......@@ -2,30 +2,66 @@ import React from 'react';
import { Image } from 'toolkit/chakra/image';
import { mediaStyleProps } from './utils';
import useLoadImageViaIpfs from './useLoadImageViaIpfs';
import type { MediaElementProps } from './utils';
interface Props {
src: string;
srcSet?: string;
onLoad: () => void;
onError: () => void;
onClick?: () => void;
}
interface Props extends MediaElementProps<'img'> {}
const NftImage = ({ src, srcSet, onLoad, onError, transport, onClick, ...rest }: Props) => {
const ref = React.useRef<HTMLImageElement>(null);
const [ isLoaded, setIsLoaded ] = React.useState(false);
const handleLoad = React.useCallback(() => {
setIsLoaded(true);
onLoad?.();
}, [ onLoad ]);
const loadImageViaIpfs = useLoadImageViaIpfs();
const loadViaHttp = React.useCallback(async() => {
if (!ref.current) {
return;
}
ref.current.src = src;
srcSet && (ref.current.srcset = srcSet);
ref.current.onload = handleLoad;
onError && (ref.current.onerror = onError);
}, [ src, srcSet, handleLoad, onError ]);
const loadViaIpfs = React.useCallback(() => {
loadImageViaIpfs(src)
.then((src) => {
if (src && ref.current) {
ref.current.src = src;
handleLoad();
}
})
.catch(onError);
}, [ handleLoad, loadImageViaIpfs, onError, src ]);
React.useEffect(() => {
switch (transport) {
case 'ipfs':
loadViaIpfs();
break;
case 'http':
loadViaHttp();
break;
}
}, [ loadViaHttp, loadViaIpfs, transport ]);
const NftImage = ({ src, srcSet, onLoad, onError, onClick }: Props) => {
return (
<Image
ref={ ref }
w="100%"
h="100%"
src={ src }
srcSet={ srcSet }
opacity={ isLoaded ? 1 : 0 }
alt="Token instance image"
onError={ onError }
onLoad={ onLoad }
onClick={ onClick }
{ ...mediaStyleProps }
{ ...rest }
/>
);
};
export default NftImage;
export default React.memo(NftImage);
import React from 'react';
import { Image } from 'toolkit/chakra/image';
import NftMediaFullscreenModal from './NftMediaFullscreenModal';
interface Props {
src: string;
open: boolean;
onOpenChange: ({ open }: { open: boolean }) => void;
}
const NftImageFullscreen = ({ src, open, onOpenChange }: Props) => {
const imgRef = React.useRef<HTMLImageElement>(null);
const [ hasDimensions, setHasDimensions ] = React.useState<boolean>(true);
const checkWidth = React.useCallback(() => {
if (imgRef.current?.getBoundingClientRect().width === 0) {
setHasDimensions(false);
}
}, [ ]);
return (
<NftMediaFullscreenModal open={ open } onOpenChange={ onOpenChange }>
<Image
src={ src }
alt="Token instance image"
maxH="90vh"
maxW="90vw"
ref={ imgRef }
onLoad={ checkWidth }
{ ...(hasDimensions ? {} : { width: '90vw', height: '90vh' }) }
/>
</NftMediaFullscreenModal>
);
};
export default NftImageFullscreen;
......@@ -66,7 +66,7 @@ test.describe('image', () => {
} as TokenInstance;
await render(
<Box boxSize="250px">
<NftMedia data={ data }/>
<NftMedia data={ data } size="md"/>
</Box>,
);
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 250, height: 250 } });
......@@ -84,7 +84,7 @@ test.describe('image', () => {
await mockAssetResponse(THUMBNAIL_URL, './playwright/mocks/image_md.jpg');
await render(
<Box boxSize="250px">
<NftMedia data={ data }/>
<NftMedia data={ data } size="md"/>
</Box>,
);
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 250, height: 250 } });
......@@ -95,7 +95,7 @@ test.describe('image', () => {
animation_url: MEDIA_URL,
image_url: null,
} as TokenInstance;
const component = await render(<NftMedia data={ data } w="250px"/>);
const component = await render(<NftMedia data={ data } w="250px" size="md"/>);
await component.getByRole('img', { name: 'Token instance image' }).hover();
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 250, height: 250 } });
});
......
import { AspectRatio, Box, chakra } from '@chakra-ui/react';
import type { HTMLChakraProps } from '@chakra-ui/react';
import { AspectRatio, Box } from '@chakra-ui/react';
import React from 'react';
import { useInView } from 'react-intersection-observer';
......@@ -9,45 +10,63 @@ import { useDisclosure } from 'toolkit/hooks/useDisclosure';
import NftFallback from './NftFallback';
import NftHtml from './NftHtml';
import NftHtmlFullscreen from './NftHtmlFullscreen';
import NftImage from './NftImage';
import NftImageFullscreen from './NftImageFullscreen';
import NftMediaFullscreenModal from './NftMediaFullscreenModal';
import NftVideo from './NftVideo';
import NftVideoFullscreen from './NftVideoFullscreen';
import useNftMediaInfo from './useNftMediaInfo';
import type { MediaType, Size } from './utils';
import { mediaStyleProps } from './utils';
interface Props {
interface Props extends Omit<HTMLChakraProps<'div'>, 'size'> {
data: TokenInstance;
className?: string;
size?: Size;
allowedTypes?: Array<MediaType>;
isLoading?: boolean;
withFullscreen?: boolean;
autoplayVideo?: boolean;
fallback?: React.ReactNode;
}
const NftMedia = ({ data, className, isLoading, withFullscreen, autoplayVideo }: Props) => {
const NftMedia = ({ data, size = 'original', allowedTypes, isLoading, withFullscreen, autoplayVideo, fallback, ...rest }: Props) => {
const [ isMediaLoading, setIsMediaLoading ] = React.useState(true);
const [ isLoadingError, setIsLoadingError ] = React.useState(false);
const [ isMediaLoadingError, setIsMediaLoadingError ] = React.useState(false);
const [ mediaInfoIndex, setMediaInfoIndex ] = React.useState(0);
const [ mediaInfoField, setMediaInfoField ] = React.useState<'animation_url' | 'image_url'>('animation_url');
const { ref, inView } = useInView({ triggerOnce: true });
const mediaInfo = useNftMediaInfo({ data, isEnabled: !isLoading && inView });
const mediaInfoQuery = useNftMediaInfo({ data, size, allowedTypes, field: mediaInfoField, isEnabled: !isLoading && inView });
React.useEffect(() => {
if (!isLoading && !mediaInfo) {
if (!mediaInfoQuery.isPending && !mediaInfoQuery.data) {
if (mediaInfoField === 'animation_url') {
setMediaInfoField('image_url');
} else {
setIsMediaLoadingError(true);
setIsMediaLoading(false);
setIsLoadingError(true);
}
}, [ isLoading, mediaInfo ]);
}
}, [ mediaInfoQuery.isPending, mediaInfoQuery.data, mediaInfoField ]);
const handleMediaLoaded = React.useCallback(() => {
setIsMediaLoading(false);
}, []);
const handleMediaLoadError = React.useCallback(() => {
if (mediaInfoQuery.data) {
if (mediaInfoIndex < mediaInfoQuery.data.length - 1) {
setMediaInfoIndex(mediaInfoIndex + 1);
return;
} else if (mediaInfoField === 'animation_url') {
setMediaInfoField('image_url');
setMediaInfoIndex(0);
return;
}
}
setIsMediaLoading(false);
setIsLoadingError(true);
}, []);
setIsMediaLoadingError(true);
}, [ mediaInfoField, mediaInfoIndex, mediaInfoQuery.data ]);
const { open, onOpen, onOpenChange } = useDisclosure();
......@@ -56,57 +75,27 @@ const NftMedia = ({ data, className, isLoading, withFullscreen, autoplayVideo }:
return null;
}
if (!mediaInfo || isLoadingError) {
if (isMediaLoadingError) {
const styleProps = withFullscreen ? {} : mediaStyleProps;
return <NftFallback { ...styleProps }/>;
return fallback ?? <NftFallback { ...styleProps }/>;
}
const mediaInfo = mediaInfoQuery.data?.[mediaInfoIndex];
const props = {
onLoad: handleMediaLoaded,
onError: handleMediaLoadError,
...(withFullscreen ? { onClick: onOpen } : {}),
...(size !== 'sm' ? mediaStyleProps : {}),
};
switch (mediaInfo.mediaType) {
switch (mediaInfo?.mediaType) {
case 'video': {
return <NftVideo { ...props } src={ mediaInfo.src } autoPlay={ autoplayVideo } instance={ data }/>;
}
case 'html':
return <NftHtml { ...props } src={ mediaInfo.src }/>;
case 'image': {
if (mediaInfo.srcType === 'url' && data.thumbnails) {
const srcSet = data.thumbnails['250x250'] && data.thumbnails['500x500'] ? `${ data.thumbnails['500x500'] } 2x` : undefined;
const src = (srcSet ? data.thumbnails['250x250'] : undefined) || data.thumbnails['500x500'] || data.thumbnails.original;
if (src) {
return <NftImage { ...props } src={ src } srcSet={ srcSet }/>;
}
}
return <NftImage { ...props } src={ mediaInfo.src }/>;
}
default:
return null;
}
})();
const modal = (() => {
if (!mediaInfo || !withFullscreen || isLoading) {
return null;
return <NftVideo { ...props } src={ mediaInfo.src } transport={ mediaInfo.transport } autoPlay={ autoplayVideo } instance={ data }/>;
}
const props = {
open,
onOpenChange,
};
switch (mediaInfo.mediaType) {
case 'video':
return <NftVideoFullscreen { ...props } src={ mediaInfo.src }/>;
case 'html':
return <NftHtmlFullscreen { ...props } src={ mediaInfo.src }/>;
return <NftHtml { ...props } src={ mediaInfo.src } transport={ mediaInfo.transport }/>;
case 'image': {
const src = mediaInfo.srcType === 'url' && data.thumbnails?.original ? data.thumbnails.original : mediaInfo.src;
return <NftImageFullscreen { ...props } src={ src }/>;
return <NftImage { ...props } src={ mediaInfo.src } srcSet={ mediaInfo.srcSet } transport={ mediaInfo.transport }/>;
}
default:
return null;
......@@ -114,13 +103,14 @@ const NftMedia = ({ data, className, isLoading, withFullscreen, autoplayVideo }:
})();
return (
<>
<AspectRatio
ref={ ref }
className={ className }
ratio={ 1 / 1 }
overflow="hidden"
borderRadius="md"
isolation="isolate"
{ ...rest }
>
<>
<Box
......@@ -132,11 +122,14 @@ const NftMedia = ({ data, className, isLoading, withFullscreen, autoplayVideo }:
>
{ content }
</Box>
{ modal }
{ isMediaLoading && <Skeleton loading position="absolute" left={ 0 } top={ 0 } w="100%" h="100%" zIndex="1"/> }
</>
</AspectRatio>
{ open && (
<NftMediaFullscreenModal open={ open } onOpenChange={ onOpenChange } data={ data } allowedTypes={ allowedTypes } field={ mediaInfoField }/>
) }
</>
);
};
export default chakra(NftMedia);
export default React.memo(NftMedia);
import React from 'react';
import type { TokenInstance } from 'types/api/token';
import { DialogContent, DialogRoot, DialogHeader } from 'toolkit/chakra/dialog';
import NftHtml from './NftHtml';
import NftImage from './NftImage';
import NftVideo from './NftVideo';
import useNftMediaInfo from './useNftMediaInfo';
import type { MediaType } from './utils';
interface Props {
open: boolean;
onOpenChange: ({ open }: { open: boolean }) => void;
children: React.ReactNode;
data: TokenInstance;
allowedTypes?: Array<MediaType>;
field: 'animation_url' | 'image_url';
}
const NftMediaFullscreenModal = ({ open, onOpenChange, children }: Props) => {
const NftMediaFullscreenModal = ({ open, onOpenChange, data, allowedTypes, field }: Props) => {
const [ mediaInfoIndex, setMediaInfoIndex ] = React.useState(0);
const mediaInfoQuery = useNftMediaInfo({ data, size: 'original', allowedTypes, field, isEnabled: true });
const handleMediaLoadError = React.useCallback(() => {
if (mediaInfoQuery.data) {
if (mediaInfoIndex < mediaInfoQuery.data.length - 1) {
setMediaInfoIndex(mediaInfoIndex + 1);
return;
}
}
// FIXME: maybe we should display something if the media is not loaded
}, [ mediaInfoIndex, mediaInfoQuery.data ]);
const content = (() => {
const mediaInfo = mediaInfoQuery.data?.[mediaInfoIndex];
switch (mediaInfo?.mediaType) {
case 'video':
return (
<NftVideo
src={ mediaInfo.src }
transport={ mediaInfo.transport }
onError={ handleMediaLoadError }
maxW="90vw"
maxH="90vh"
objectFit="contain"
autoPlay
instance={ data }
/>
);
case 'html':
return (
<NftHtml
src={ mediaInfo.src }
transport={ mediaInfo.transport }
onError={ handleMediaLoadError }
w="90vw"
h="90vh"
/>
);
case 'image':
return (
<NftImage
src={ mediaInfo.src }
srcSet={ mediaInfo.srcSet }
transport={ mediaInfo.transport }
onError={ handleMediaLoadError }
maxW="90vw"
maxH="90vh"
objectFit="contain"/>
);
default:
return null;
}
})();
return (
<DialogRoot open={ open } onOpenChange={ onOpenChange } motionPreset="none">
<DialogContent w="unset" maxW="100vw" p={ 0 } background="none" boxShadow="none">
<DialogHeader/>
{ children }
{ content }
</DialogContent>
</DialogRoot>
);
......
import { chakra } from '@chakra-ui/react';
import { verifiedFetch } from '@helia/verified-fetch';
import React from 'react';
import type { TokenInstance } from 'types/api/token';
import config from 'configs/app';
import useLoadImageViaIpfs from './useLoadImageViaIpfs';
import useNftMediaInfo from './useNftMediaInfo';
import type { MediaElementProps, Size } from './utils';
import { videoPlayProps } from './utils';
import { mediaStyleProps, videoPlayProps } from './utils';
interface Props {
src: string;
interface Props extends MediaElementProps<'video'> {
instance: TokenInstance;
autoPlay?: boolean;
onLoad: () => void;
onError: () => void;
onClick?: () => void;
size?: Size;
}
const NftVideo = ({ src, instance, autoPlay = true, onLoad, onError, onClick }: Props) => {
const POSTER_ALLOWED_TYPES = [ 'image' as const ];
const NftVideo = ({ src, transport, instance, autoPlay = true, onLoad, size = 'original', onError, onClick, ...rest }: Props) => {
const ref = React.useRef<HTMLVideoElement>(null);
const controller = React.useRef<AbortController | null>(null);
const fetchVideoPoster = React.useCallback(async() => {
const mediaInfoQuery = useNftMediaInfo({ data: instance, size, field: 'image_url', isEnabled: true, allowedTypes: POSTER_ALLOWED_TYPES });
const loadImageViaIpfs = useLoadImageViaIpfs();
const handleMouseEnter = React.useCallback(() => {
!autoPlay && ref.current?.play();
}, [ autoPlay ]);
const handleMouseLeave = React.useCallback(() => {
!autoPlay && ref.current?.pause();
}, [ autoPlay ]);
const loadViaHttp = React.useCallback(async() => {
if (!ref.current) {
return;
}
try {
if (!config.UI.views.nft.verifiedFetch.isEnabled) {
throw new Error('Helia verified fetch is disabled');
ref.current.src = src;
onLoad && (ref.current.oncanplaythrough = onLoad);
onError && (ref.current.onerror = onError);
}, [ src, onLoad, onError ]);
React.useEffect(() => {
switch (transport) {
case 'ipfs': {
// Currently we don't support IPFS video loading
onError?.();
break;
}
const imageUrl = typeof instance.metadata?.image === 'string' ? instance.metadata.image : undefined;
if (!imageUrl) {
throw new Error('No image URL found');
case 'http':
loadViaHttp();
break;
}
controller.current = new AbortController();
const response = await verifiedFetch(imageUrl, { signal: controller.current.signal });
const blob = await response.blob();
const src = URL.createObjectURL(blob);
ref.current.poster = src;
}, [ loadViaHttp, onError, transport ]);
// we want to call onLoad right after the poster is loaded
// otherwise, the skeleton will be shown underneath the element until the video is loaded
onLoad();
} catch (error) {
const src = instance.thumbnails?.['500x500'] || instance.thumbnails?.original || instance.image_url;
if (src) {
ref.current.poster = src;
const loadPosterViaHttp = React.useCallback(async(src: string) => {
if (!ref.current || !ref.current.poster) {
return;
}
const poster = new Image();
poster.src = src;
// we want to call onLoad right after the poster is loaded
// otherwise, the skeleton will be shown underneath the element until the video is loaded
const poster = new Image();
poster.src = ref.current.poster;
poster.onload = onLoad;
}
onLoad && (poster.onload = onLoad);
ref.current.poster = poster.src;
}, [ onLoad ]);
const loadPosterViaIpfs = React.useCallback((url: string) => {
loadImageViaIpfs(url)
.then((src) => {
if (src && ref.current) {
ref.current.poster = src;
onLoad?.();
}
}, [ instance.image_url, instance.metadata?.image, instance.thumbnails, onLoad ]);
})
.catch(onError);
}, [ loadImageViaIpfs, onError, onLoad ]);
React.useEffect(() => {
!autoPlay && fetchVideoPoster();
return () => {
controller.current?.abort();
};
// run only on mount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
if (autoPlay) {
return;
}
const handleMouseEnter = React.useCallback(() => {
!autoPlay && ref.current?.play();
}, [ autoPlay ]);
if (!mediaInfoQuery.isPending && mediaInfoQuery.data) {
const mediaInfo = mediaInfoQuery.data[0];
switch (mediaInfo.transport) {
case 'ipfs':
loadPosterViaIpfs(mediaInfo.src);
break;
case 'http':
loadPosterViaHttp(mediaInfo.src);
break;
}
}
const handleMouseLeave = React.useCallback(() => {
!autoPlay && ref.current?.pause();
}, [ autoPlay ]);
}, [ autoPlay, loadPosterViaHttp, loadPosterViaIpfs, mediaInfoQuery.data, mediaInfoQuery.isPending ]);
return (
<chakra.video
ref={ ref }
{ ...videoPlayProps }
autoPlay={ autoPlay }
src={ src }
onCanPlayThrough={ onLoad }
onError={ onError }
borderRadius="md"
onClick={ onClick }
onMouseEnter={ handleMouseEnter }
onMouseLeave={ handleMouseLeave }
{ ...mediaStyleProps }
{ ...rest }
/>
);
};
......
import { chakra } from '@chakra-ui/react';
import React from 'react';
import NftMediaFullscreenModal from './NftMediaFullscreenModal';
import { videoPlayProps } from './utils';
interface Props {
src: string;
open: boolean;
onOpenChange: ({ open }: { open: boolean }) => void;
}
const NftVideoFullscreen = ({ src, open, onOpenChange }: Props) => {
return (
<NftMediaFullscreenModal open={ open } onOpenChange={ onOpenChange }>
<chakra.video
{ ...videoPlayProps }
src={ src }
maxH="90vh"
maxW="90vw"
autoPlay={ true }
/>
</NftMediaFullscreenModal>
);
};
export default NftVideoFullscreen;
import { verifiedFetch } from '@helia/verified-fetch';
import React from 'react';
export default function useLoadImageViaIpfs() {
return React.useCallback(async(url: string) => {
const response = await verifiedFetch(url);
if (response.status !== 200) {
throw new Error('Failed to load image');
}
const blob = await response.blob();
const src = URL.createObjectURL(blob);
return src;
}, [ ]);
}
import { verifiedFetch } from '@helia/verified-fetch';
import type { UseQueryResult } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';
import React from 'react';
import type { TokenInstance } from 'types/api/token';
......@@ -8,151 +7,169 @@ import type { StaticRoute } from 'nextjs-routes';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import type { ResourceError } from 'lib/api/resources';
import useFetch from 'lib/hooks/useFetch';
import type { MediaType, SrcType } from './utils';
import type { MediaType, Size, TransportType } from './utils';
import { getPreliminaryMediaType } from './utils';
interface Params {
data: TokenInstance;
size: Size;
allowedTypes?: Array<MediaType>;
field: 'animation_url' | 'image_url';
isEnabled: boolean;
}
interface AssetsData {
imageUrl: string | undefined;
animationUrl: string | undefined;
}
type TransportType = 'http' | 'ipfs';
type ReturnType =
{
interface MediaInfo {
src: string;
srcSet?: string;
mediaType: MediaType;
srcType: SrcType;
} |
{
mediaType: undefined;
} |
null;
export default function useNftMediaInfo({ data, isEnabled }: Params): ReturnType | null {
const assetsData = composeAssetsData(data);
const httpPrimaryQuery = useNftMediaTypeQuery(assetsData.http.animationUrl, isEnabled);
const ipfsPrimaryQuery = useFetchAssetViaIpfs(
assetsData.ipfs.animationUrl,
httpPrimaryQuery.data?.mediaType,
isEnabled && (httpPrimaryQuery.data === null || Boolean(httpPrimaryQuery.data?.mediaType)),
);
const httpSecondaryQuery = useNftMediaTypeQuery(assetsData.http.imageUrl, isEnabled && !httpPrimaryQuery.data && !ipfsPrimaryQuery);
const ipfsSecondaryQuery = useFetchAssetViaIpfs(
assetsData.ipfs.imageUrl,
httpSecondaryQuery.data?.mediaType,
isEnabled && (httpSecondaryQuery.data === null || Boolean(httpSecondaryQuery.data?.mediaType)),
);
return React.useMemo(() => {
return ipfsPrimaryQuery || httpPrimaryQuery.data || ipfsSecondaryQuery || httpSecondaryQuery.data || null;
}, [ httpPrimaryQuery.data, httpSecondaryQuery.data, ipfsPrimaryQuery, ipfsSecondaryQuery ]);
}
function composeAssetsData(data: TokenInstance): Record<TransportType, AssetsData> {
return {
http: {
imageUrl: data.image_url || undefined,
animationUrl: data.animation_url || undefined,
},
ipfs: {
imageUrl: typeof data.metadata?.image === 'string' ? data.metadata.image : undefined,
animationUrl: typeof data.metadata?.animation_url === 'string' ? data.metadata.animation_url : undefined,
},
};
transport: TransportType;
}
// As of now we fetch only images via IPFS because video streaming has performance issues
// Also, we don't want to store the entire file content in the ReactQuery cache, so we don't use useQuery hook here
function useFetchAssetViaIpfs(url: string | undefined, mediaType: MediaType | undefined, isEnabled: boolean): ReturnType | null {
const [ result, setResult ] = React.useState<ReturnType | null>({ mediaType: undefined });
const controller = React.useRef<AbortController | null>(null);
export default function useNftMediaInfo({ data, size, allowedTypes, field, isEnabled }: Params): UseQueryResult<Array<MediaInfo> | null> {
const url = data[field];
const query = useQuery({
queryKey: [ 'nft-media-info', data.id, url, size, ...(allowedTypes ? allowedTypes : []) ],
queryFn: async() => {
const metadataField = field === 'animation_url' ? 'animation_url' : 'image';
const mediaType = await getMediaType(data, field);
const fetchAsset = React.useCallback(async(url: string) => {
try {
controller.current = new AbortController();
const response = await verifiedFetch(url, { signal: controller.current.signal });
if (response.status === 200) {
const blob = await response.blob();
const src = URL.createObjectURL(blob);
setResult({ mediaType: 'image', src, srcType: 'blob' });
return;
if (!mediaType || (allowedTypes ? !allowedTypes.includes(mediaType) : false)) {
return null;
}
} catch (error) {}
setResult(null);
}, []);
React.useEffect(() => {
if (isEnabled) {
if (config.UI.views.nft.verifiedFetch.isEnabled && mediaType === 'image' && url && url.includes('ipfs')) {
fetchAsset(url);
} else {
setResult(null);
}
} else {
setResult({ mediaType: undefined });
}
}, [ fetchAsset, url, mediaType, isEnabled ]);
const cdnData = getCdnData(data, size, mediaType);
const ipfsData = getIpfsData(data.metadata?.[metadataField], mediaType);
React.useEffect(() => {
return () => {
controller.current?.abort();
};
}, []);
return [
cdnData,
ipfsData,
url ? { src: url, mediaType, transport: 'http' as const } : undefined,
].filter(Boolean);
},
enabled: isEnabled,
});
return result;
return query;
}
function useNftMediaTypeQuery(url: string | undefined, enabled: boolean) {
const fetch = useFetch();
async function getMediaType(data: TokenInstance, field: Params['field']): Promise<MediaType | undefined> {
const url = data[field];
return useQuery<ReturnType | null, ResourceError<unknown>, ReturnType | null>({
queryKey: [ 'nft-media-type', url ],
queryFn: async() => {
if (!url) {
return null;
return;
}
// media could be either image, gif, video or html-page
// so we pre-fetch the resources in order to get its content type
// have to do it via Node.js due to strict CSP for connect-src
// but in order not to abuse our server firstly we check file url extension
// and if it is valid we will trust it and display corresponding media component
// If the media_url is the same as the url, we can use the media_type field to determine the media type.
if (url === data.media_url) {
const mediaType = castMimeTypeToMediaType(data.media_type || undefined);
if (mediaType) {
return mediaType;
}
}
// Media can be an image, video, or HTML page.
// We pre-fetch the resources to determine their content type.
// We must do this via Node.js due to strict CSP for connect-src.
// To avoid overloading our server, we first check the file URL extension.
// If it is valid, we will trust it and display the corresponding media component.
const preliminaryType = getPreliminaryMediaType(url);
if (preliminaryType) {
return { mediaType: preliminaryType, src: url, srcType: 'url' };
return preliminaryType;
}
const mediaType = await (async() => {
try {
const mediaTypeResourceUrl = route({ pathname: '/node-api/media-type' as StaticRoute<'/api/media-type'>['pathname'], query: { url } });
const response = await fetch<{ type: MediaType | undefined }, ResourceError>(mediaTypeResourceUrl, undefined, { resource: 'media-type' });
const response = await fetch(mediaTypeResourceUrl);
const payload = await response.json() as { type: MediaType | undefined };
return 'type' in response ? response.type : undefined;
return payload.type;
} catch (error) {
return;
}
})();
}
if (!mediaType) {
return null;
function castMimeTypeToMediaType(mimeType: string | undefined): MediaType | undefined {
if (!mimeType) {
return;
}
return { mediaType, src: url, srcType: 'url' };
},
enabled,
placeholderData: { mediaType: undefined },
staleTime: Infinity,
});
if (mimeType.startsWith('image/')) {
return 'image';
}
if (mimeType.startsWith('video/')) {
return 'video';
}
}
function getCdnData(data: TokenInstance, size: Size, mediaType: MediaType): MediaInfo | undefined {
// CDN is only used for images
if (mediaType !== 'image') {
return;
}
if (!data.thumbnails) {
return;
}
switch (size) {
case 'sm': {
return {
src: data.thumbnails['60x60'] || data.thumbnails['250x250'] || data.thumbnails['500x500'] || data.thumbnails['original'],
// the smallest thumbnail is already greater than sm size by two times
// so there is no need to pass srcSet
srcSet: undefined,
mediaType: 'image',
transport: 'http',
};
}
case 'md': {
const srcSet = data.thumbnails['250x250'] && data.thumbnails['500x500'] ? `${ data.thumbnails['500x500'] } 2x` : undefined;
const src = (srcSet ? data.thumbnails['250x250'] : undefined) || data.thumbnails['500x500'] || data.thumbnails.original;
return {
src,
srcSet,
mediaType: 'image',
transport: 'http',
};
}
default: {
if (data.thumbnails.original) {
return {
src: data.thumbnails.original,
mediaType: 'image',
transport: 'http',
};
}
}
}
}
function getIpfsData(url: unknown, mediaType: MediaType): MediaInfo | undefined {
if (!config.UI.views.nft.verifiedFetch.isEnabled) {
return;
}
// Currently we only load images via IPFS
if (mediaType !== 'image') {
return;
}
if (typeof url !== 'string') {
return;
}
if (!url.includes('ipfs')) {
return;
}
return {
src: url,
mediaType,
transport: 'ipfs',
};
}
import type { HTMLChakraProps } from '@chakra-ui/react';
import type React from 'react';
export type MediaType = 'image' | 'video' | 'html';
export type TransportType = 'http' | 'ipfs';
// Currently we have only 3 sizes:
// sm = max-width<=30px
// md = max-width<=250px
// original
export type Size = 'sm' | 'md' | 'original';
export type SrcType = 'url' | 'blob';
export type MediaElementProps<As extends React.ElementType> = HTMLChakraProps<As> & {
src: string;
srcSet?: string;
transport: TransportType;
onLoad?: () => void;
onError?: () => void;
onClick?: () => void;
};
// https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Image_types
const IMAGE_EXTENSIONS = [
'.jpg', 'jpeg',
'.png',
'.jpg', 'jpeg', '.jfif', '.pjpeg', '.pjp',
'.png', '.apng',
'.avif',
'.gif',
'.svg',
'.webp',
];
const VIDEO_EXTENSIONS = [
......
......@@ -129,11 +129,9 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
}
scrollToTop();
router.push({ pathname: router.pathname, query: nextPageQuery }, undefined, { shallow: true })
.then(() => {
setPage(prev => clamp(prev - 1, 1, Infinity));
page === 2 && queryClient.removeQueries({ queryKey: [ resourceName ] });
});
router.push({ pathname: router.pathname, query: nextPageQuery }, undefined, { shallow: true });
}, [ router, page, pageParams, scrollToTop, queryClient, resourceName ]);
const resetPage = useCallback(() => {
......
import React from 'react';
import type { InteropMessage } from 'types/api/interop';
import type { StatusTagType } from './StatusTag';
import StatusTag from './StatusTag';
export interface Props {
status: InteropMessage['status'];
isLoading?: boolean;
}
const InteropMessageStatus = ({ status, isLoading }: Props) => {
let type: StatusTagType;
switch (status) {
case 'Relayed': {
type = 'ok';
break;
}
case 'Failed': {
type = 'error';
break;
}
case 'Sent': {
type = 'pending';
break;
}
default:
type = 'pending';
break;
}
return <StatusTag type={ type } text={ status } isLoading={ isLoading }/>;
};
export default InteropMessageStatus;
......@@ -28,6 +28,7 @@ const AuthModalScreenOtpCode = ({ email, onSuccess, isAuth }: Props) => {
const apiFetch = useApiFetch();
const recaptcha = useReCaptcha();
const [ isCodeSending, setIsCodeSending ] = React.useState(false);
const [ resendAttempts, setResendAttempts ] = React.useState(0);
const formApi = useForm<OtpCodeFormFields>({
mode: 'onBlur',
......@@ -92,6 +93,7 @@ const AuthModalScreenOtpCode = ({ email, onSuccess, isAuth }: Props) => {
description: apiError?.message || getErrorMessage(error) || 'Something went wrong',
});
} finally {
setResendAttempts((prev) => prev + 1);
setIsCodeSending(false);
}
}, [ apiFetch, email, formApi, recaptcha ]);
......@@ -108,7 +110,7 @@ const AuthModalScreenOtpCode = ({ email, onSuccess, isAuth }: Props) => {
and enter your code below.
</Text>
<AuthModalFieldOtpCode isDisabled={ isCodeSending }/>
<ReCaptcha ref={ recaptcha.ref }/>
<ReCaptcha key={ resendAttempts } ref={ recaptcha.ref }/>
<Button
variant="link"
columnGap={ 2 }
......
......@@ -24,6 +24,7 @@ const TokenInventoryItem = ({ item, token, isLoading }: Props) => {
data={ item }
isLoading={ isLoading }
autoplayVideo={ false }
size="md"
/>
);
......
......@@ -2,6 +2,7 @@ import { Box } from '@chakra-ui/react';
import React from 'react';
import { tokenInfoERC20a, tokenInfoERC721a, tokenInfoERC1155a } from 'mocks/tokens/tokenInfo';
import * as tokenInstanceMock from 'mocks/tokens/tokenInstance';
import * as tokenTransferMock from 'mocks/tokens/tokenTransfer';
import { test, expect } from 'playwright/lib';
......@@ -33,7 +34,8 @@ test('erc20 +@mobile', async({ render }) => {
await expect(component).toHaveScreenshot();
});
test('erc721 +@mobile', async({ render }) => {
test('erc721 +@mobile', async({ render, mockAssetResponse }) => {
await mockAssetResponse(tokenInstanceMock.base.image_url as string, './playwright/mocks/image_s.jpg');
const component = await render(
<Box pt={{ base: '134px', lg: '100px' }}>
<TokenTransfer
......
......@@ -4,7 +4,7 @@ import { useRouter } from 'next/router';
import React from 'react';
import type { SocketMessage } from 'lib/socket/types';
import type { TokenInfo } from 'types/api/token';
import type { TokenInfo, TokenInstance } from 'types/api/token';
import type { ResourceError } from 'lib/api/resources';
import useGradualIncrement from 'lib/hooks/useGradualIncrement';
......@@ -25,12 +25,13 @@ const TABS_HEIGHT = 88;
type Props = {
transfersQuery: QueryWithPagesResult<'token_transfers'> | QueryWithPagesResult<'token_instance_transfers'>;
tokenId?: string;
tokenInstance?: TokenInstance;
tokenQuery: UseQueryResult<TokenInfo, ResourceError<unknown>>;
shouldRender?: boolean;
tabsHeight?: number;
};
const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, tabsHeight = TABS_HEIGHT, shouldRender = true }: Props) => {
const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, tabsHeight = TABS_HEIGHT, tokenInstance, shouldRender = true }: Props) => {
const isMobile = useIsMobile();
const isMounted = useIsMounted();
const router = useRouter();
......@@ -81,6 +82,7 @@ const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, tabsHeight = TABS_
socketInfoNum={ newItemsCount }
tokenId={ tokenId }
token={ token }
instance={ tokenInstance }
isLoading={ isLoading }
/>
</Box>
......@@ -94,7 +96,7 @@ const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, tabsHeight = TABS_
isLoading={ isLoading }
/>
) }
<TokenTransferList data={ data?.items } tokenId={ tokenId } isLoading={ isLoading }/>
<TokenTransferList data={ data?.items } tokenId={ tokenId } instance={ tokenInstance } isLoading={ isLoading }/>
</Box>
</>
) : null;
......
import { Box } from '@chakra-ui/react';
import React from 'react';
import type { TokenInstance } from 'types/api/token';
import type { TokenTransfer } from 'types/api/tokenTransfer';
import TokenTransferListItem from 'ui/token/TokenTransfer/TokenTransferListItem';
......@@ -8,10 +9,11 @@ import TokenTransferListItem from 'ui/token/TokenTransfer/TokenTransferListItem'
interface Props {
data: Array<TokenTransfer>;
tokenId?: string;
instance?: TokenInstance;
isLoading?: boolean;
}
const TokenTransferList = ({ data, tokenId, isLoading }: Props) => {
const TokenTransferList = ({ data, tokenId, instance, isLoading }: Props) => {
return (
<Box>
{ data.map((item, index) => (
......@@ -19,6 +21,7 @@ const TokenTransferList = ({ data, tokenId, isLoading }: Props) => {
key={ item.transaction_hash + item.block_hash + item.log_index + '_' + index }
{ ...item }
tokenId={ tokenId }
instance={ instance }
isLoading={ isLoading }
/>
)) }
......
import { Grid, Flex } from '@chakra-ui/react';
import React from 'react';
import type { TokenInstance } from 'types/api/token';
import type { TokenTransfer } from 'types/api/tokenTransfer';
import getCurrencyValue from 'lib/getCurrencyValue';
......@@ -14,7 +15,7 @@ import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip';
import TruncatedValue from 'ui/shared/TruncatedValue';
type Props = TokenTransfer & { tokenId?: string; isLoading?: boolean };
type Props = TokenTransfer & { tokenId?: string; isLoading?: boolean; instance?: TokenInstance };
const TokenTransferListItem = ({
token,
......@@ -26,6 +27,7 @@ const TokenTransferListItem = ({
timestamp,
tokenId,
isLoading,
instance,
}: Props) => {
const { usd, valueStr } = total && 'value' in total && total.value !== null ? getCurrencyValue({
value: total.value,
......@@ -94,6 +96,7 @@ const TokenTransferListItem = ({
<NftEntity
hash={ token.address }
id={ total.token_id }
instance={ instance || total.token_instance }
noLink={ Boolean(tokenId && tokenId === total.token_id) }
isLoading={ isLoading }
/>
......
import React from 'react';
import type { TokenInfo } from 'types/api/token';
import type { TokenInfo, TokenInstance } from 'types/api/token';
import type { TokenTransfer } from 'types/api/tokenTransfer';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
......@@ -19,9 +19,10 @@ interface Props {
tokenId?: string;
isLoading?: boolean;
token: TokenInfo;
instance?: TokenInstance;
}
const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socketInfoNum, tokenId, isLoading, token }: Props) => {
const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socketInfoNum, tokenId, isLoading, token, instance }: Props) => {
const tokenType = token.type;
......@@ -58,6 +59,7 @@ const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socket
key={ item.transaction_hash + item.block_hash + item.log_index + '_' + index }
{ ...item }
tokenId={ tokenId }
instance={ instance }
isLoading={ isLoading }
/>
)) }
......
import { Flex, Box } from '@chakra-ui/react';
import React from 'react';
import type { TokenInstance } from 'types/api/token';
import type { TokenTransfer } from 'types/api/tokenTransfer';
import getCurrencyValue from 'lib/getCurrencyValue';
......@@ -13,7 +14,7 @@ import NftEntity from 'ui/shared/entities/nft/NftEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip';
type Props = TokenTransfer & { tokenId?: string; isLoading?: boolean };
type Props = TokenTransfer & { tokenId?: string; isLoading?: boolean; instance?: TokenInstance };
const TokenTransferTableItem = ({
token,
......@@ -25,6 +26,7 @@ const TokenTransferTableItem = ({
timestamp,
tokenId,
isLoading,
instance,
}: Props) => {
const { usd, valueStr } = total && 'value' in total && total.value !== null ? getCurrencyValue({
value: total.value,
......@@ -79,6 +81,7 @@ const TokenTransferTableItem = ({
<NftEntity
hash={ token.address }
id={ total.token_id }
instance={ instance || total.token_instance }
noLink={ Boolean(tokenId && tokenId === total.token_id) }
isLoading={ isLoading }
/>
......
......@@ -112,6 +112,7 @@ const TokenInstanceDetails = ({ data, token, scrollRef, isLoading }: Props) => {
<NftMedia
data={ data }
isLoading={ isLoading }
size="md"
withFullscreen
w="250px"
flexShrink={ 0 }
......
......@@ -76,6 +76,7 @@ const TokenTransfersListItem = ({ item, isLoading }: Props) => {
<NftEntity
hash={ item.token.address }
id={ item.total.token_id }
instance={ item.total.token_instance }
isLoading={ isLoading }
noIcon
/>
......
......@@ -68,6 +68,7 @@ const TokenTransferTableItem = ({ item, isLoading }: Props) => {
<NftEntity
hash={ item.token.address }
id={ item.total.token_id }
instance={ item.total.token_instance }
isLoading={ isLoading }
maxW="140px"
/>
......
import { Grid, Text, Flex, Box } from '@chakra-ui/react';
import React from 'react';
import type { InteropTransactionInfo } from 'types/api/transaction';
import config from 'configs/app';
import { CollapsibleDetails } from 'toolkit/chakra/collapsible';
import InteropMessageDestinationTx from 'ui/interopMessages/InteropMessageDestinationTx';
import InteropMessageSourceTx from 'ui/interopMessages/InteropMessageSourceTx';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import * as DetailedInfo from 'ui/shared/DetailedInfo/DetailedInfo';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import AddressEntityInterop from 'ui/shared/entities/address/AddressEntityInterop';
import InteropMessageStatus from 'ui/shared/statusTag/InteropMessageStatus';
const rollupFeature = config.features.rollup;
type Props = {
data?: InteropTransactionInfo;
isLoading: boolean;
};
const TxDetailsInterop = ({ data, isLoading }: Props) => {
const hasInterop = rollupFeature.isEnabled && rollupFeature.interopEnabled;
if (!hasInterop || !data) {
return null;
}
const details = (
<Grid
gridTemplateColumns="100px 1fr"
textStyle="sm"
bgColor={{ _light: 'blackAlpha.50', _dark: 'whiteAlpha.50' }}
px={ 4 }
py={ 2 }
mt={ 3 }
w="100%"
rowGap={ 4 }
borderRadius="md"
>
<Text color="text.secondary">Message id</Text>
<Text>{ data.nonce }</Text>
<Text color="text.secondary">Interop status</Text>
<Box>
<InteropMessageStatus status={ data.status }/>
</Box>
<Text color="text.secondary">Sender</Text>
{ data.init_chain !== undefined ? (
<AddressEntityInterop
chain={ data.init_chain }
address={{ hash: data.sender }}
isLoading={ isLoading }
truncation="constant"
/>
) : (
<AddressEntity address={{ hash: data.sender }} isLoading={ isLoading } truncation="constant"/>
) }
<Text color="text.secondary">Target</Text>
{ data.relay_chain !== undefined ? (
<AddressEntityInterop
chain={ data.relay_chain }
address={{ hash: data.target }}
isLoading={ isLoading }
truncation="constant"
/>
) : (
<AddressEntity address={{ hash: data.target }} isLoading={ isLoading } truncation="constant"/>
) }
<Text color="text.secondary">Payload</Text>
<Flex overflow="hidden">
<Text
wordBreak="break-all"
whiteSpace="normal"
overflow="hidden"
flex="1"
>
{ data.payload }
</Text>
<CopyToClipboard text={ data.payload }/>
</Flex>
</Grid>
);
if (data.init_chain !== undefined) {
return (
<>
<DetailedInfo.ItemLabel
hint="The originating transaction that initiated the cross-L2 message on the source chain"
isLoading={ isLoading }
>
Interop source tx
</DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue>
<InteropMessageSourceTx { ...data } isLoading={ isLoading }/>
<CollapsibleDetails variant="secondary" noScroll ml={ 3 }>
{ details }
</CollapsibleDetails>
</DetailedInfo.ItemValue>
</>
);
}
if (data.relay_chain !== undefined) {
return (
<>
<DetailedInfo.ItemLabel
hint="The transaction that relays the cross-L2 message to its destination chain"
isLoading={ isLoading }
>
Interop relay tx
</DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue>
<InteropMessageDestinationTx { ...data } isLoading={ isLoading }/>
<CollapsibleDetails variant="secondary" noScroll ml={ 3 }>
{ details }
</CollapsibleDetails>
</DetailedInfo.ItemValue>
</>
);
}
return null;
};
export default TxDetailsInterop;
import React from 'react';
import * as tokenInstanceMock from 'mocks/tokens/tokenInstance';
import * as txMock from 'mocks/txs/tx';
import { ENVS_MAP } from 'playwright/fixtures/mockEnvs';
import { test, expect } from 'playwright/lib';
......@@ -27,7 +28,8 @@ test('creating contact', async({ render, page }) => {
});
});
test('with token transfer +@mobile', async({ render, page }) => {
test('with token transfer +@mobile', async({ render, page, mockAssetResponse }) => {
await mockAssetResponse(tokenInstanceMock.base.image_url as string, './playwright/mocks/image_s.jpg');
const component = await render(<TxInfo data={ txMock.withTokenTransfer } isLoading={ false }/>);
await expect(component).toHaveScreenshot({
......@@ -127,11 +129,40 @@ test('arbitrum L1 status', async({ render, mockEnvs }) => {
await expect(statusElement).toHaveScreenshot();
});
test('with external txs +@mobile', async({ render, mockEnvs, mockApiResponse, mockAssetResponse }) => {
test('with external txs +@mobile', async({ page, render, mockEnvs, mockApiResponse, mockAssetResponse }) => {
await mockEnvs(ENVS_MAP.externalTxs);
await mockApiResponse('tx_external_transactions', [ 'tx1', 'tx2', 'tx3' ], { pathParams: { hash: txMock.base.hash } });
await mockAssetResponse('http://example.url', './playwright/mocks/image_s.jpg');
const component = await render(<TxInfo data={ txMock.base } isLoading={ false }/>);
await expect(component).toHaveScreenshot();
await expect(component).toHaveScreenshot({
mask: [ page.locator(pwConfig.adsBannerSelector) ],
maskColor: pwConfig.maskColor,
});
});
test('with interop message in +@mobile', async({ render, page, mockEnvs, mockAssetResponse }) => {
await mockEnvs(ENVS_MAP.interop);
await mockAssetResponse('https://example.com/logo.png', './playwright/mocks/image_s.jpg');
const component = await render(<TxInfo data={ txMock.withInteropInMessage } isLoading={ false }/>);
await page.getByText('View details').first().click();
await expect(page.getByText('Interop status')).toBeVisible();
await expect(component).toHaveScreenshot({
mask: [ page.locator(pwConfig.adsBannerSelector) ],
maskColor: pwConfig.maskColor,
});
});
test('with interop message out +@mobile', async({ page, render, mockEnvs, mockAssetResponse }) => {
await mockEnvs(ENVS_MAP.interop);
await mockAssetResponse('https://example.com/logo.png', './playwright/mocks/image_s.jpg');
const component = await render(<TxInfo data={ txMock.withInteropOutMessage } isLoading={ false }/>);
await component.getByText('View details').first().click();
await expect(component.getByText('Interop status')).toBeVisible();
await expect(component).toHaveScreenshot({
mask: [ page.locator(pwConfig.adsBannerSelector) ],
maskColor: pwConfig.maskColor,
});
});
......@@ -35,6 +35,7 @@ import * as DetailedInfo from 'ui/shared/DetailedInfo/DetailedInfo';
import DetailedInfoSponsoredItem from 'ui/shared/DetailedInfo/DetailedInfoSponsoredItem';
import DetailedInfoTimestamp from 'ui/shared/DetailedInfo/DetailedInfoTimestamp';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import AddressEntityInterop from 'ui/shared/entities/address/AddressEntityInterop';
import BatchEntityL2 from 'ui/shared/entities/block/BatchEntityL2';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
......@@ -61,11 +62,10 @@ import TxExternalTxs from 'ui/tx/TxExternalTxs';
import TxSocketAlert from 'ui/tx/TxSocketAlert';
import ZkSyncL2TxnBatchHashesInfo from 'ui/txnBatches/zkSyncL2/ZkSyncL2TxnBatchHashesInfo';
import TxDetailsInterop from './TxDetailsInterop';
import TxDetailsWithdrawalStatusArbitrum from './TxDetailsWithdrawalStatusArbitrum';
import TxInfoScrollFees from './TxInfoScrollFees';
const rollupFeature = config.features.rollup;
interface Props {
data: Transaction | undefined;
isLoading: boolean;
......@@ -73,6 +73,7 @@ interface Props {
}
const externalTxFeature = config.features.externalTxs;
const rollupFeature = config.features.rollup;
const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
const [ isExpanded, setIsExpanded ] = React.useState(false);
......@@ -129,6 +130,8 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
</Tooltip>
) : null;
const hasInterop = rollupFeature.isEnabled && rollupFeature.interopEnabled && data.op_interop;
return (
<DetailedInfo.Container templateColumns={{ base: 'minmax(0, 1fr)', lg: 'max-content minmax(728px, auto)' }}>
......@@ -146,6 +149,8 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
</GridItem>
) }
<TxDetailsInterop data={ data.op_interop } isLoading={ isLoading }/>
<DetailedInfo.ItemLabel
hint="Unique character string (TxID) assigned to every verified transaction"
isLoading={ isLoading }
......@@ -486,6 +491,52 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
{ data.token_transfers && <TxDetailsTokenTransfers data={ data.token_transfers } txHash={ data.hash } isOverflow={ data.token_transfers_overflow }/> }
{ hasInterop && data.op_interop?.target && (
<>
<DetailedInfo.ItemLabel
isLoading={ isLoading }
hint="The target address where this cross-chain transaction is executed"
>
Interop target
</DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue flexWrap="nowrap">
{ data.op_interop?.relay_chain !== undefined ? (
<AddressEntityInterop
chain={ data.op_interop.relay_chain }
address={{ hash: data.op_interop.target }}
isLoading={ isLoading }
truncation="dynamic"
/>
) : (
<AddressEntity address={{ hash: data.op_interop.target }} isLoading={ isLoading } truncation="dynamic"/>
) }
</DetailedInfo.ItemValue>
</>
) }
{ hasInterop && data.op_interop?.target && (
<>
<DetailedInfo.ItemLabel
isLoading={ isLoading }
hint="The target address where this cross-chain transaction is executed"
>
Interop target
</DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue flexWrap="nowrap">
{ data.op_interop?.relay_chain !== undefined ? (
<AddressEntityInterop
chain={ data.op_interop.relay_chain }
address={{ hash: data.op_interop.target }}
isLoading={ isLoading }
truncation="dynamic"
/>
) : (
<AddressEntity address={{ hash: data.op_interop.target }} isLoading={ isLoading } truncation="dynamic"/>
) }
</DetailedInfo.ItemValue>
</>
) }
<DetailedInfo.ItemDivider/>
{ (data.arbitrum?.commitment_transaction.hash || data.arbitrum?.confirmation_transaction.hash) &&
......
......@@ -51,7 +51,7 @@ const TxAdditionalInfo = ({ hash, tx, isMobile, isLoading, className }: Props) =
<AdditionalInfoButton loading={ isLoading } className={ className }/>
</PopoverTrigger>
<PopoverContent w="330px">
<PopoverBody textStyle="sm">
<PopoverBody>
<Heading level="3" mb={ 6 }>Additional info </Heading>
{ content }
</PopoverBody>
......
......@@ -7,7 +7,7 @@
resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7"
integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==
"@adraffy/ens-normalize@1.11.0", "@adraffy/ens-normalize@^1.10.1":
"@adraffy/ens-normalize@^1.10.1":
version "1.11.0"
resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33"
integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==
......@@ -114,6 +114,15 @@
"@babel/highlight" "^7.24.7"
picocolors "^1.0.0"
"@babel/code-frame@^7.26.2":
version "7.26.2"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85"
integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
dependencies:
"@babel/helper-validator-identifier" "^7.25.9"
js-tokens "^4.0.0"
picocolors "^1.0.0"
"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1":
version "7.20.1"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30"
......@@ -536,6 +545,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d"
integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==
"@babel/helper-string-parser@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c"
integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1":
version "7.19.1"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
......@@ -551,6 +565,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db"
integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==
"@babel/helper-validator-identifier@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7"
integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
"@babel/helper-validator-option@^7.18.6":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
......@@ -576,31 +595,13 @@
"@babel/traverse" "^7.19.0"
"@babel/types" "^7.19.0"
"@babel/helpers@^7.20.1":
version "7.20.1"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.1.tgz#2ab7a0fcb0a03b5bf76629196ed63c2d7311f4c9"
integrity sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==
dependencies:
"@babel/template" "^7.18.10"
"@babel/traverse" "^7.20.1"
"@babel/types" "^7.20.0"
"@babel/helpers@^7.22.0":
version "7.22.3"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.3.tgz#53b74351da9684ea2f694bf0877998da26dd830e"
integrity sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==
dependencies:
"@babel/template" "^7.21.9"
"@babel/traverse" "^7.22.1"
"@babel/types" "^7.22.3"
"@babel/helpers@^7.25.0":
version "7.25.6"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.25.6.tgz#57ee60141829ba2e102f30711ffe3afab357cc60"
integrity sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==
"@babel/helpers@^7.20.1", "@babel/helpers@^7.22.0", "@babel/helpers@^7.25.0":
version "7.27.0"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.0.tgz#53d156098defa8243eab0f32fa17589075a1b808"
integrity "sha1-U9FWCY3vqCQ+qw8y+hdYkHWhuAg= sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg=="
dependencies:
"@babel/template" "^7.25.0"
"@babel/types" "^7.25.6"
"@babel/template" "^7.27.0"
"@babel/types" "^7.27.0"
"@babel/highlight@^7.18.6":
version "7.18.6"
......@@ -657,6 +658,13 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b"
integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==
"@babel/parser@^7.27.0":
version "7.27.0"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.0.tgz#3d7d6ee268e41d2600091cbd4e145ffee85a44ec"
integrity "sha1-PX1u4mjkHSYACRy9ThRf/uhaROw= sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg=="
dependencies:
"@babel/types" "^7.27.0"
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2"
......@@ -1375,78 +1383,21 @@
"@babel/helper-validator-option" "^7.18.6"
"@babel/plugin-transform-typescript" "^7.18.6"
"@babel/runtime-corejs3@^7.20.7":
version "7.21.0"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz#6e4939d9d9789ff63e2dc58e88f13a3913a24eba"
integrity sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==
dependencies:
core-js-pure "^3.25.1"
regenerator-runtime "^0.13.11"
"@babel/runtime-corejs3@^7.22.15", "@babel/runtime-corejs3@^7.23.1":
version "7.23.2"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.23.2.tgz#a5cd9d8b408fb946b2f074b21ea40c04e516795c"
integrity sha512-54cIh74Z1rp4oIjsHjqN+WM4fMyCBYe+LpZ9jWm51CZ1fbH3SkAzQD/3XLoNkjbJ7YEmjobLXyvQrFypRHOrXw==
"@babel/runtime-corejs3@^7.20.7", "@babel/runtime-corejs3@^7.22.15", "@babel/runtime-corejs3@^7.23.1":
version "7.27.0"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.27.0.tgz#c766df350ec7a2caf3ed64e3659b100954589413"
integrity "sha1-x2bfNQ7Hosrz7WTjZZsQCVRYlBM= sha512-UWjX6t+v+0ckwZ50Y5ShZLnlk95pP5MyW/pon9tiYzl3+18pkTHTFNTKr7rQbfRXPkowt2QAn30o1b6oswszew=="
dependencies:
core-js-pure "^3.30.2"
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3":
version "7.19.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.4.tgz#a42f814502ee467d55b38dd1c256f53a7b885c78"
integrity sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.12.0", "@babel/runtime@^7.8.7":
version "7.20.13"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.13.tgz#7055ab8a7cff2b8f6058bf6ae45ff84ad2aded4b"
integrity sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==
dependencies:
regenerator-runtime "^0.13.11"
"@babel/runtime@^7.12.1", "@babel/runtime@^7.3.1", "@babel/runtime@^7.9.2":
version "7.21.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
dependencies:
regenerator-runtime "^0.13.11"
"@babel/runtime@^7.21.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.0.tgz#584c450063ffda59697021430cb47101b085951e"
integrity sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.23.5":
version "7.23.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.6.tgz#c05e610dc228855dc92ef1b53d07389ed8ab521d"
integrity sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.5", "@babel/runtime@^7.26.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.27.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.0.tgz#fbee7cf97c709518ecc1f590984481d5460d4762"
integrity "sha1-++58+XxwlRjswfWQmESB1UYNR2I= sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw=="
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.26.0":
version "7.26.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1"
integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.5.5":
version "7.20.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.7.tgz#fcb41a5a70550e04a7b708037c7c32f7f356d8fd"
integrity sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==
dependencies:
regenerator-runtime "^0.13.11"
"@babel/runtime@^7.8.4":
version "7.20.1"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9"
integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==
dependencies:
regenerator-runtime "^0.13.10"
"@babel/template@^7.18.10", "@babel/template@^7.3.3":
version "7.18.10"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71"
......@@ -1483,6 +1434,15 @@
"@babel/parser" "^7.25.0"
"@babel/types" "^7.25.0"
"@babel/template@^7.27.0":
version "7.27.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4"
integrity "sha1-slPlQGzB3xxX3NGPEXYMLb9AwLQ= sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA=="
dependencies:
"@babel/code-frame" "^7.26.2"
"@babel/parser" "^7.27.0"
"@babel/types" "^7.27.0"
"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1", "@babel/traverse@^7.22.1", "@babel/traverse@^7.7.2":
version "7.23.6"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5"
......@@ -1557,6 +1517,14 @@
"@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0"
"@babel/types@^7.27.0":
version "7.27.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.0.tgz#ef9acb6b06c3173f6632d993ecb6d4ae470b4559"
integrity "sha1-75rLawbDFz9mMtmT7LbUrkcLRVk= sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg=="
dependencies:
"@babel/helper-string-parser" "^7.25.9"
"@babel/helper-validator-identifier" "^7.25.9"
"@bcoe/v8-coverage@^0.2.3":
version "0.2.3"
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
......@@ -1676,16 +1644,6 @@
"@ethersproject/solidity" "^5.7.0"
jshashes "^1.0.8"
"@coinbase/wallet-sdk@4.2.3":
version "4.2.3"
resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-4.2.3.tgz#a30fa0605b24bc42c37f52a62d2442bcbb7734af"
integrity sha512-BcyHZ/Ec84z0emORzqdXDv4P0oV+tV3a0OirfA8Ko1JGBIAVvB+hzLvZzCDvnuZx7MTK+Dd8Y9Tjlo446BpCIg==
dependencies:
"@noble/hashes" "^1.4.0"
clsx "^1.2.1"
eventemitter3 "^5.0.1"
preact "^10.24.2"
"@coinbase/wallet-sdk@4.3.0":
version "4.3.0"
resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-4.3.0.tgz#03b8fce92ac2b3b7cf132f64d6008ac081569b4e"
......@@ -2241,17 +2199,6 @@
ethereum-cryptography "^2.0.0"
micro-ftch "^0.3.1"
"@ethersproject/address@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37"
integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==
dependencies:
"@ethersproject/bignumber" "^5.7.0"
"@ethersproject/bytes" "^5.7.0"
"@ethersproject/keccak256" "^5.7.0"
"@ethersproject/logger" "^5.7.0"
"@ethersproject/rlp" "^5.7.0"
"@ethersproject/bignumber@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2"
......@@ -2288,21 +2235,6 @@
resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892"
integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==
"@ethersproject/properties@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30"
integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==
dependencies:
"@ethersproject/logger" "^5.7.0"
"@ethersproject/rlp@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304"
integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==
dependencies:
"@ethersproject/bytes" "^5.7.0"
"@ethersproject/logger" "^5.7.0"
"@ethersproject/sha2@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb"
......@@ -2312,18 +2244,6 @@
"@ethersproject/logger" "^5.7.0"
hash.js "1.1.7"
"@ethersproject/signing-key@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3"
integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==
dependencies:
"@ethersproject/bytes" "^5.7.0"
"@ethersproject/logger" "^5.7.0"
"@ethersproject/properties" "^5.7.0"
bn.js "^5.2.1"
elliptic "6.5.4"
hash.js "1.1.7"
"@ethersproject/solidity@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8"
......@@ -2345,21 +2265,6 @@
"@ethersproject/constants" "^5.7.0"
"@ethersproject/logger" "^5.7.0"
"@ethersproject/transactions@5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b"
integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==
dependencies:
"@ethersproject/address" "^5.7.0"
"@ethersproject/bignumber" "^5.7.0"
"@ethersproject/bytes" "^5.7.0"
"@ethersproject/constants" "^5.7.0"
"@ethersproject/keccak256" "^5.7.0"
"@ethersproject/logger" "^5.7.0"
"@ethersproject/properties" "^5.7.0"
"@ethersproject/rlp" "^5.7.0"
"@ethersproject/signing-key" "^5.7.0"
"@fastify/busboy@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8"
......@@ -3575,17 +3480,6 @@
resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.1.tgz#e89b840a7af8097a8ed4953d8dc8470d1302d3ef"
integrity sha512-ihb3B0T/wJm1eUuArYP4lCTSEoZsClHhuWyfo/kMX3m/odpqNcPfsz5O2A3NT7dXCAgWPGDQGPqygCpgeniKMw==
"@metamask/sdk-communication-layer@0.31.0":
version "0.31.0"
resolved "https://registry.yarnpkg.com/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.31.0.tgz#0acc063b62aa09d044c7aab65801712d760e53b2"
integrity sha512-V9CxdzabDPjQVgmKGHsyU3SYt4Af27g+4DbGCx0fLoHqN/i1RBDZqs/LYbJX3ykJCANzE+llz/MolMCMrzM2RA==
dependencies:
bufferutil "^4.0.8"
date-fns "^2.29.3"
debug "^4.3.4"
utf-8-validate "^5.0.2"
uuid "^8.3.2"
"@metamask/sdk-communication-layer@0.32.0":
version "0.32.0"
resolved "https://registry.yarnpkg.com/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.32.0.tgz#89710e807806836138ea5018b087731d6acab627"
......@@ -3597,13 +3491,6 @@
utf-8-validate "^5.0.2"
uuid "^8.3.2"
"@metamask/sdk-install-modal-web@0.31.2":
version "0.31.2"
resolved "https://registry.yarnpkg.com/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.31.2.tgz#bb8c92a6844a632be8525e7bb5a35924a926d6cd"
integrity sha512-KPv36kQjmTwErU8g2neuHHSgkD5+1hp4D6ERfk5Kc2r73aOYNCdG9wDGRUmFmcY2MKkeK1EuDyZfJ4FPU30fxQ==
dependencies:
"@paulmillr/qr" "^0.2.1"
"@metamask/sdk-install-modal-web@0.32.0":
version "0.32.0"
resolved "https://registry.yarnpkg.com/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.32.0.tgz#86f80420ca364fa0d7710016fa5c81f95537ab23"
......@@ -3611,31 +3498,6 @@
dependencies:
"@paulmillr/qr" "^0.2.1"
"@metamask/sdk@0.31.2":
version "0.31.2"
resolved "https://registry.yarnpkg.com/@metamask/sdk/-/sdk-0.31.2.tgz#2ec1c1c7cf6a444e65104862e83814a493047d72"
integrity sha512-6MWON2g1j7XwAHWam4trusGxeyhQweNLEHPsfuIxSwcsXoEm08Jj80OglJxQI4KwjcDnjSWBkQGG3mmK6ug/cA==
dependencies:
"@babel/runtime" "^7.26.0"
"@metamask/onboarding" "^1.0.1"
"@metamask/providers" "16.1.0"
"@metamask/sdk-communication-layer" "0.31.0"
"@metamask/sdk-install-modal-web" "0.31.2"
"@paulmillr/qr" "^0.2.1"
bowser "^2.9.0"
cross-fetch "^4.0.0"
debug "^4.3.4"
eciesjs "^0.4.11"
eth-rpc-errors "^4.0.3"
eventemitter2 "^6.4.9"
obj-multiplex "^1.0.0"
pump "^3.0.0"
readable-stream "^3.6.2"
socket.io-client "^4.5.1"
tslib "^2.6.0"
util "^0.12.4"
uuid "^8.3.2"
"@metamask/sdk@0.32.0":
version "0.32.0"
resolved "https://registry.yarnpkg.com/@metamask/sdk/-/sdk-0.32.0.tgz#f0e179746fe69dccd032a9026884b45b519c1975"
......@@ -3922,20 +3784,6 @@
dependencies:
"@noble/hashes" "1.4.0"
"@noble/curves@1.6.0", "@noble/curves@^1.4.0", "@noble/curves@^1.6.0", "@noble/curves@~1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b"
integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==
dependencies:
"@noble/hashes" "1.5.0"
"@noble/curves@1.7.0", "@noble/curves@~1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45"
integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==
dependencies:
"@noble/hashes" "1.6.0"
"@noble/curves@1.8.0":
version "1.8.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.0.tgz#fe035a23959e6aeadf695851b51a87465b5ba8f7"
......@@ -3943,13 +3791,20 @@
dependencies:
"@noble/hashes" "1.7.0"
"@noble/curves@1.8.1":
"@noble/curves@1.8.1", "@noble/curves@~1.8.1":
version "1.8.1"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.1.tgz#19bc3970e205c99e4bdb1c64a4785706bce497ff"
integrity sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==
dependencies:
"@noble/hashes" "1.7.1"
"@noble/curves@^1.4.0", "@noble/curves@^1.6.0", "@noble/curves@~1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b"
integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==
dependencies:
"@noble/hashes" "1.5.0"
"@noble/curves@~1.4.0":
version "1.4.2"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9"
......@@ -3977,22 +3832,12 @@
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0"
integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==
"@noble/hashes@1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5"
integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==
"@noble/hashes@1.6.1", "@noble/hashes@~1.6.0":
version "1.6.1"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5"
integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==
"@noble/hashes@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.0.tgz#5d9e33af2c7d04fee35de1519b80c958b2e35e39"
integrity sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==
"@noble/hashes@1.7.1":
"@noble/hashes@1.7.1", "@noble/hashes@~1.7.1":
version "1.7.1"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.1.tgz#5738f6d765710921e7a751e00c20ae091ed8db0f"
integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==
......@@ -5130,119 +4975,116 @@
prop-types "^15.7.2"
tslib "^2.3.0"
"@reown/appkit-adapter-wagmi@1.6.7":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@reown/appkit-adapter-wagmi/-/appkit-adapter-wagmi-1.6.7.tgz#dbb6cb7b1d9d0ab338487147d3985a001db702bb"
integrity sha512-CS6X0OE4hfZJ6K5wpHGxCFqS7dAWnS7SSg6LsBFFtGJTflIAxL6oY84SVSvKByAigQUwGHd5DTvGPQKaFunPQA==
dependencies:
"@reown/appkit" "1.6.7"
"@reown/appkit-common" "1.6.7"
"@reown/appkit-core" "1.6.7"
"@reown/appkit-polyfills" "1.6.7"
"@reown/appkit-scaffold-ui" "1.6.7"
"@reown/appkit-ui" "1.6.7"
"@reown/appkit-utils" "1.6.7"
"@reown/appkit-wallet" "1.6.7"
"@walletconnect/universal-provider" "2.18.0"
"@walletconnect/utils" "2.18.0"
"@reown/appkit-adapter-wagmi@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@reown/appkit-adapter-wagmi/-/appkit-adapter-wagmi-1.7.0.tgz#62d31fdb801b3a1f78fa75e6863464d8b925a8d5"
integrity sha512-5xkwFQCu8Ezb2J3nnVv8fLjEoBjADggBrxYmOwPDzT6D5heWtkRC/HYx2STiy+vsbj0G8Vs/x+SXq753CR94/Q==
dependencies:
"@reown/appkit" "1.7.0"
"@reown/appkit-common" "1.7.0"
"@reown/appkit-controllers" "1.7.0"
"@reown/appkit-polyfills" "1.7.0"
"@reown/appkit-scaffold-ui" "1.7.0"
"@reown/appkit-utils" "1.7.0"
"@reown/appkit-wallet" "1.7.0"
"@walletconnect/universal-provider" "2.19.1"
valtio "1.13.2"
optionalDependencies:
"@wagmi/connectors" ">=5.7"
"@reown/appkit-common@1.6.7":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@reown/appkit-common/-/appkit-common-1.6.7.tgz#34d4df120a8d6b714b315931ca7f4db94606ba27"
integrity sha512-gfJOC8mkauNz2Lu3bjLmvKLAKsSaHCv4OKUZF62s70Y0otj8RC+qhU+6XCmsb56C0sJAIG0Unb8/Ky3ICpGLEQ==
"@reown/appkit-common@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@reown/appkit-common/-/appkit-common-1.7.0.tgz#484b14bc18efa9c79334c66ecc24453d73c93dd5"
integrity sha512-yJc5lQLt64+ZjhagqZar/H9S9EDKiZa9z/4mII4ZTpRiOfSlKvRS+tLcjiqJNr+dTft4nVbF71sbnVLZ/ON2UQ==
dependencies:
big.js "6.2.2"
dayjs "1.11.10"
viem "2.x"
dayjs "1.11.13"
viem ">=2.23.5"
"@reown/appkit-core@1.6.7":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@reown/appkit-core/-/appkit-core-1.6.7.tgz#17f6c071b5a0dfaa2e37fe834de1c36803c570fb"
integrity sha512-kws78pLqEGmlHy56UuCJc8WMeeRySLhy+5klo56Kpykp+L5pvZdH5moE0oNqk6ysGWmWpTW1T3Yskoo1bKI8ng==
"@reown/appkit-controllers@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@reown/appkit-controllers/-/appkit-controllers-1.7.0.tgz#ad9c085aea4e7610878fb37d33cdc0fa81a5b888"
integrity sha512-npFnrPQdm4t5YT+ai+525sQRnZdAQjGMKQ11hYBKifAZafx8xr7yObvyxeR9d6aM0ku+OSFHErbALKM9iJFtXw==
dependencies:
"@reown/appkit-common" "1.6.7"
"@reown/appkit-wallet" "1.6.7"
"@walletconnect/universal-provider" "2.18.0"
"@reown/appkit-common" "1.7.0"
"@reown/appkit-wallet" "1.7.0"
"@walletconnect/universal-provider" "2.19.1"
valtio "1.13.2"
viem "2.x"
viem ">=2.23.5"
"@reown/appkit-polyfills@1.6.7":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@reown/appkit-polyfills/-/appkit-polyfills-1.6.7.tgz#850c9da80983a0c3a30856f61d993043b5637a02"
integrity sha512-SnO+K3+BTJwjIKee+RbGSmP+uwnMEVCS3njzQ8IXP4YrRERgPS1naxmfj3NqxlomtZD0zUeylIA3VTkMcTCgYg==
"@reown/appkit-polyfills@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@reown/appkit-polyfills/-/appkit-polyfills-1.7.0.tgz#effd8a85979480cc33a4e1bc2dee1dc77bb3b9ad"
integrity sha512-j7pHuOvnaXUJmd+Hj2WYkBDxar3LM71Z/FY8Qr8OaQsb+e6U9ho033npYXHEAkfjTv4mB/B0Y7yTKAJhxV9Lpg==
dependencies:
buffer "6.0.3"
"@reown/appkit-scaffold-ui@1.6.7":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@reown/appkit-scaffold-ui/-/appkit-scaffold-ui-1.6.7.tgz#8ce8451edf4ce6f483a21901b1125adea8b21f64"
integrity sha512-5C94XJkp0VCR4xKtnNRB2TLfgWKuCDinLCnIajCSoL5MdZiiyVVsF5+Y2XH1SgCpw0G8MF1NPoEC3N1SMJmWrw==
dependencies:
"@reown/appkit-common" "1.6.7"
"@reown/appkit-core" "1.6.7"
"@reown/appkit-ui" "1.6.7"
"@reown/appkit-utils" "1.6.7"
"@reown/appkit-wallet" "1.6.7"
"@reown/appkit-scaffold-ui@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@reown/appkit-scaffold-ui/-/appkit-scaffold-ui-1.7.0.tgz#415081d3973fdf55ff806b5e3e03b5b89a83a47e"
integrity sha512-BNlN01gOpcqf4w5iYLz10FN574cZqhwobHSKKSgthTb2DBZpaSeIK2K+97ku2uGb8o00m+9aFyKaRDOU3XpNNQ==
dependencies:
"@reown/appkit-common" "1.7.0"
"@reown/appkit-controllers" "1.7.0"
"@reown/appkit-ui" "1.7.0"
"@reown/appkit-utils" "1.7.0"
"@reown/appkit-wallet" "1.7.0"
lit "3.1.0"
"@reown/appkit-ui@1.6.7":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@reown/appkit-ui/-/appkit-ui-1.6.7.tgz#8190af457d59dd4e42502149af4882310ec0120b"
integrity sha512-Y9lKaATDBtACkST2Vl19h24qK611WpAv+dkVuoHI8BIEVJtp+44YD6mrVOJWovKsdrbt/WrmObY7mS+17cywZQ==
"@reown/appkit-ui@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@reown/appkit-ui/-/appkit-ui-1.7.0.tgz#78328e98635e1c9bf78b22d40f4bff1fa238aca0"
integrity sha512-a2sCBE3Me9dbsqW0544S/3FIoJh/RER4ZhU4e7I2rfskdTX6W5Orw/vm9wK2ItesVDD0SB3WpyQ3F/4bCkJt/w==
dependencies:
lit "3.1.0"
qrcode "1.5.3"
"@reown/appkit-utils@1.6.7":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@reown/appkit-utils/-/appkit-utils-1.6.7.tgz#8b7779eb9bc65579b647a102c7ef40317397f3b2"
integrity sha512-zSDF8VhfMEFx/UCZB6vHHTD7QDO5gsixq86/JqqUinOQWumuBkmbzGoK0YqyNvAN9O/pGoPhQ/eJp3pY9PAADA==
"@reown/appkit-utils@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@reown/appkit-utils/-/appkit-utils-1.7.0.tgz#346b31e936cf2b0a5156744a51427bd81d533f2a"
integrity sha512-D88Lzms0RFgocBrJmeUB7jHG+ZlU2hDQgwjTHvXW+UlMdH1fUb2btPLYyt2dqI0X3ubAcPsQPmpH458G7sUKPA==
dependencies:
"@reown/appkit-common" "1.6.7"
"@reown/appkit-core" "1.6.7"
"@reown/appkit-polyfills" "1.6.7"
"@reown/appkit-wallet" "1.6.7"
"@reown/appkit-common" "1.7.0"
"@reown/appkit-controllers" "1.7.0"
"@reown/appkit-polyfills" "1.7.0"
"@reown/appkit-wallet" "1.7.0"
"@walletconnect/logger" "2.1.2"
"@walletconnect/universal-provider" "2.18.0"
"@walletconnect/universal-provider" "2.19.1"
valtio "1.13.2"
viem "2.x"
viem ">=2.23.5"
"@reown/appkit-wallet@1.6.7":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@reown/appkit-wallet/-/appkit-wallet-1.6.7.tgz#236830d91f4d3b2863c0d8f0cda541c50de2de11"
integrity sha512-QCn1KQzkF50Qr6ZpbK4RwTLDjZwmlqNd/OvHMboPW+su904aakPyQP2OTaTtrs2bqeWQ3OktF2oBkI9IwbIb5g==
"@reown/appkit-wallet@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@reown/appkit-wallet/-/appkit-wallet-1.7.0.tgz#4789756b91aaea2e8aff3f4cb26284a0f1a01b6d"
integrity sha512-hXrPe5ZYbxAwyytdBcWT504lJ+L8ckXDcSGZg62nk+7sck3jqpXmwn24mI4eS/ThTj3ExxlOG4bcGiXu1EBFwQ==
dependencies:
"@reown/appkit-common" "1.6.7"
"@reown/appkit-polyfills" "1.6.7"
"@reown/appkit-common" "1.7.0"
"@reown/appkit-polyfills" "1.7.0"
"@walletconnect/logger" "2.1.2"
zod "3.22.4"
"@reown/appkit@1.6.7":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@reown/appkit/-/appkit-1.6.7.tgz#fefa0dd384b9c3fee3af97c41fdf01f83ef93e2c"
integrity sha512-Vy6MJvZZcwkBDzwpcU24KIeoA/DFOzRLYUp4Az/sVmpUTpjATjY1OaVK1OkSg/pIs7MsU1BUw+JJdkXU6vbBjw==
dependencies:
"@reown/appkit-common" "1.6.7"
"@reown/appkit-core" "1.6.7"
"@reown/appkit-polyfills" "1.6.7"
"@reown/appkit-scaffold-ui" "1.6.7"
"@reown/appkit-ui" "1.6.7"
"@reown/appkit-utils" "1.6.7"
"@reown/appkit-wallet" "1.6.7"
"@walletconnect/types" "2.18.0"
"@walletconnect/universal-provider" "2.18.0"
"@walletconnect/utils" "2.18.0"
"@reown/appkit@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@reown/appkit/-/appkit-1.7.0.tgz#8443199d2f030555317e4da94b1f86a80b361718"
integrity sha512-/F+By2dfoXJNuAdq/atRM1wt5PlWjUSpIQnk4j3rIFxmch0XJnw6YZzdMaDH0dNfzP2+ymUFsN7CFt7Se4QgoA==
dependencies:
"@reown/appkit-common" "1.7.0"
"@reown/appkit-controllers" "1.7.0"
"@reown/appkit-polyfills" "1.7.0"
"@reown/appkit-scaffold-ui" "1.7.0"
"@reown/appkit-ui" "1.7.0"
"@reown/appkit-utils" "1.7.0"
"@reown/appkit-wallet" "1.7.0"
"@walletconnect/types" "2.19.1"
"@walletconnect/universal-provider" "2.19.1"
bs58 "6.0.0"
valtio "1.13.2"
viem "2.x"
viem ">=2.23.5"
"@rollbar/react@0.12.0-beta":
version "0.12.0-beta"
resolved "https://registry.yarnpkg.com/@rollbar/react/-/react-0.12.0-beta.tgz#b80dfab1535ece358a0e98a4f26aadee8b54edda"
integrity sha512-8udBX0lJwdBBq+O/jqDXpg/giHt8bo/Us1IlTkHEdCBO18Cjj7sxWJ80OPFxiPRNwZgZnhf2HbxQxvLN+4FeJA==
"@rollbar/react@0.12.1":
version "0.12.1"
resolved "https://registry.yarnpkg.com/@rollbar/react/-/react-0.12.1.tgz#2c8ac9a06b1f6ba75d67346f55fee3c120100865"
integrity sha512-qi1ahC4WRXTrqh7hkBM0H5cSKh4TBA5A9jKliokphxikmZsAfbQEvwjIM6IFkqEljeWt1nAfuuFC5w32sLqoTg==
dependencies:
tiny-invariant "^1.1.0"
......@@ -5345,14 +5187,6 @@
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz#427d5549943a9c6fce808e39ea64dbe60d4047f1"
integrity sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==
"@safe-global/safe-apps-provider@0.18.4":
version "0.18.4"
resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.4.tgz#53df912aa20d933f6b14c5bcb0737a8cd47def57"
integrity sha512-SWYeG3gyTO6wGHMSokfHakZ9isByn2mHsM0VohIorYFFEyGGmJ89btnTm+DqDUSoQtvWAatZB7XNy6CaYMvqtg==
dependencies:
"@safe-global/safe-apps-sdk" "^9.1.0"
events "^3.3.0"
"@safe-global/safe-apps-provider@0.18.5":
version "0.18.5"
resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.5.tgz#745a932bda3739a8a298ae44ec6c465f6c4773b7"
......@@ -5396,10 +5230,10 @@
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.8.tgz#8f23646c352f020c83bca750a82789e246d42b50"
integrity sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg==
"@scure/base@~1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.1.tgz#dd0b2a533063ca612c17aa9ad26424a2ff5aa865"
integrity sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==
"@scure/base@~1.2.2", "@scure/base@~1.2.4":
version "1.2.4"
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.4.tgz#002eb571a35d69bdb4c214d0995dff76a8dcd2a9"
integrity sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==
"@scure/bip32@1.3.1":
version "1.3.1"
......@@ -5428,7 +5262,16 @@
"@noble/hashes" "~1.4.0"
"@scure/base" "~1.1.6"
"@scure/bip32@1.5.0", "@scure/bip32@^1.5.0":
"@scure/bip32@1.6.2":
version "1.6.2"
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.2.tgz#093caa94961619927659ed0e711a6e4bf35bffd0"
integrity sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==
dependencies:
"@noble/curves" "~1.8.1"
"@noble/hashes" "~1.7.1"
"@scure/base" "~1.2.2"
"@scure/bip32@^1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.5.0.tgz#dd4a2e1b8a9da60e012e776d954c4186db6328e6"
integrity sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw==
......@@ -5437,15 +5280,6 @@
"@noble/hashes" "~1.5.0"
"@scure/base" "~1.1.7"
"@scure/bip32@1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.0.tgz#6dbc6b4af7c9101b351f41231a879d8da47e0891"
integrity sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA==
dependencies:
"@noble/curves" "~1.7.0"
"@noble/hashes" "~1.6.0"
"@scure/base" "~1.2.1"
"@scure/bip39@1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a"
......@@ -5462,13 +5296,13 @@
"@noble/hashes" "~1.5.0"
"@scure/base" "~1.1.8"
"@scure/bip39@1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.0.tgz#c8f9533dbd787641b047984356531d84485f19be"
integrity sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A==
"@scure/bip39@1.5.4":
version "1.5.4"
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.4.tgz#07fd920423aa671be4540d59bdd344cc1461db51"
integrity sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==
dependencies:
"@noble/hashes" "~1.6.0"
"@scure/base" "~1.2.1"
"@noble/hashes" "~1.7.1"
"@scure/base" "~1.2.4"
"@sideway/address@^4.1.3":
version "4.1.4"
......@@ -7241,16 +7075,16 @@
"@types/babel__core" "^7.20.5"
react-refresh "^0.14.2"
"@wagmi/connectors@5.6.0":
version "5.6.0"
resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-5.6.0.tgz#5c9f3aae2eb423efb4e3fbc471e0cf259cb2e7e3"
integrity sha512-yFVzJ0k/tj/QFvoBkU3phYPE3FhpdaSwWPruYBgCANGoL2bV9pDoeOIVvHRTJraldGw4X6I2zvIVZtSapKHaUw==
"@wagmi/connectors@5.7.11":
version "5.7.11"
resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-5.7.11.tgz#bcd98c9378366f5eea728760c232e5460938ac19"
integrity sha512-vJWOXMeYWmczvlsEZHq52yOoC2qu5kU8Saj6Bo+BtyfYcX1tJODZTKed3TMIoKhUx0W3vna1UIwG7GskmxGKKA==
dependencies:
"@coinbase/wallet-sdk" "4.2.3"
"@metamask/sdk" "0.31.2"
"@safe-global/safe-apps-provider" "0.18.4"
"@coinbase/wallet-sdk" "4.3.0"
"@metamask/sdk" "0.32.0"
"@safe-global/safe-apps-provider" "0.18.5"
"@safe-global/safe-apps-sdk" "9.1.0"
"@walletconnect/ethereum-provider" "2.17.0"
"@walletconnect/ethereum-provider" "2.19.1"
cbw-sdk "npm:@coinbase/wallet-sdk@3.9.3"
"@wagmi/connectors@>=5.7":
......@@ -7265,10 +7099,10 @@
"@walletconnect/ethereum-provider" "2.17.0"
cbw-sdk "npm:@coinbase/wallet-sdk@3.9.3"
"@wagmi/core@2.16.0":
version "2.16.0"
resolved "https://registry.yarnpkg.com/@wagmi/core/-/core-2.16.0.tgz#b997b2544cd80b4aac4df25ccb2436bf77f9fbe1"
integrity sha512-sy4n7Jv6YCbT2jp4zQ/9H6l0A8StsN7P8mm2BRuODgW2w6Fj4j6h2xgYJD2tIjJHkLU/nvPJ7audZ55X7XQU/g==
"@wagmi/core@2.16.7":
version "2.16.7"
resolved "https://registry.yarnpkg.com/@wagmi/core/-/core-2.16.7.tgz#9ca06583c7a546b25d86ec7ee4d4d1376b1ee6e2"
integrity sha512-Kpgrw6OXV0VBhDs4toQVKQ0NK5yUO6uxEqnvRGjNjbO85d93Gbfsp5BlxSLeWq6iVMSBFSitdl5i9W7b1miq1g==
dependencies:
eventemitter3 "5.0.1"
mipd "0.0.7"
......@@ -7296,10 +7130,10 @@
lodash.isequal "4.5.0"
uint8arrays "3.1.0"
"@walletconnect/core@2.18.0":
version "2.18.0"
resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.18.0.tgz#749b57000823eceb1c667d38531e7eae206df349"
integrity sha512-i/olu/IwYtBiWYqyfNUMxq4b6QS5dv+ZVVGmLT2buRwdH6MGETN0Bx3/z6rXJzd1sNd+QL07fxhSFxCekL57tA==
"@walletconnect/core@2.19.1":
version "2.19.1"
resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.19.1.tgz#71738940341b438326b65b3f49226decbe070bae"
integrity sha512-rMvpZS0tQXR/ivzOxN1GkHvw3jRRMlI/jRX5g7ZteLgg2L0ZcANsFvAU5IxILxIKcIkTCloF9TcfloKVbK3qmw==
dependencies:
"@walletconnect/heartbeat" "1.2.2"
"@walletconnect/jsonrpc-provider" "1.0.14"
......@@ -7312,11 +7146,11 @@
"@walletconnect/relay-auth" "1.1.0"
"@walletconnect/safe-json" "1.0.2"
"@walletconnect/time" "1.0.2"
"@walletconnect/types" "2.18.0"
"@walletconnect/utils" "2.18.0"
"@walletconnect/types" "2.19.1"
"@walletconnect/utils" "2.19.1"
"@walletconnect/window-getters" "1.0.1"
es-toolkit "1.33.0"
events "3.3.0"
lodash.isequal "4.5.0"
uint8arrays "3.1.0"
"@walletconnect/environment@^1.0.1":
......@@ -7342,6 +7176,23 @@
"@walletconnect/utils" "2.17.0"
events "3.3.0"
"@walletconnect/ethereum-provider@2.19.1":
version "2.19.1"
resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.19.1.tgz#1618d6bc98aad839e682940f451d1e9a2b2e46d0"
integrity sha512-bs8Kiwdw3cGb8ITO8+YymesGfFnucJreQmVbZ0vl/Ogoh38n1T5w0ekjmD/NjTDS3oZaUQyBm3V2UjIBR0qedw==
dependencies:
"@walletconnect/jsonrpc-http-connection" "1.0.8"
"@walletconnect/jsonrpc-provider" "1.0.14"
"@walletconnect/jsonrpc-types" "1.0.4"
"@walletconnect/jsonrpc-utils" "1.0.8"
"@walletconnect/keyvaluestorage" "1.1.1"
"@walletconnect/modal" "2.7.0"
"@walletconnect/sign-client" "2.19.1"
"@walletconnect/types" "2.19.1"
"@walletconnect/universal-provider" "2.19.1"
"@walletconnect/utils" "2.19.1"
events "3.3.0"
"@walletconnect/events@1.0.1", "@walletconnect/events@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@walletconnect/events/-/events-1.0.1.tgz#2b5f9c7202019e229d7ccae1369a9e86bda7816c"
......@@ -7532,19 +7383,19 @@
"@walletconnect/utils" "2.17.0"
events "3.3.0"
"@walletconnect/sign-client@2.18.0":
version "2.18.0"
resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.18.0.tgz#33480ee3e711d31c947860125ac26cf31bb9bcb5"
integrity sha512-oUjlRIsbHxMSRif2WvMRdvm6tMsQjMj07rl7YVcKVvZ1gF1/9GcbJPjzL/U87fv8qAQkVhIlbEg2vHaVYf6J/g==
"@walletconnect/sign-client@2.19.1":
version "2.19.1"
resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.19.1.tgz#6cfbb4ee0eaf3a8774a8c70ff65ba23177e8f388"
integrity sha512-OgBHRPo423S02ceN3lAzcZ3MYb1XuLyTTkKqLmKp/icYZCyRzm3/ynqJDKndiBLJ5LTic0y07LiZilnliYqlvw==
dependencies:
"@walletconnect/core" "2.18.0"
"@walletconnect/core" "2.19.1"
"@walletconnect/events" "1.0.1"
"@walletconnect/heartbeat" "1.2.2"
"@walletconnect/jsonrpc-utils" "1.0.8"
"@walletconnect/logger" "2.1.2"
"@walletconnect/time" "1.0.2"
"@walletconnect/types" "2.18.0"
"@walletconnect/utils" "2.18.0"
"@walletconnect/types" "2.19.1"
"@walletconnect/utils" "2.19.1"
events "3.3.0"
"@walletconnect/time@1.0.2", "@walletconnect/time@^1.0.2":
......@@ -7566,10 +7417,10 @@
"@walletconnect/logger" "2.1.2"
events "3.3.0"
"@walletconnect/types@2.18.0":
version "2.18.0"
resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.18.0.tgz#dda74a0aeb5a4790a860a1d8eba439f19a07cb54"
integrity sha512-g0jU+6LUuw3E/EPAQfHNK2xK/95IpRfz68tdNAFckLmefZU6kzoE1mIM1SrPJq8rT9kUPp6/APMQE+ReH2OdBA==
"@walletconnect/types@2.19.1":
version "2.19.1"
resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.19.1.tgz#ec78c5a05238e220871cca3e360193584af2d968"
integrity sha512-XWWGLioddH7MjxhyGhylL7VVariVON2XatJq/hy0kSGJ1hdp31z194nHN5ly9M495J9Hw8lcYjGXpsgeKvgxzw==
dependencies:
"@walletconnect/events" "1.0.1"
"@walletconnect/heartbeat" "1.2.2"
......@@ -7593,10 +7444,10 @@
"@walletconnect/utils" "2.17.0"
events "3.3.0"
"@walletconnect/universal-provider@2.18.0":
version "2.18.0"
resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.18.0.tgz#0c8cde53cada6491e516233589d084a6aa4b0cd5"
integrity sha512-zF/e1NAipLqYjNNgM+XZTchh94efaxciBmgcDOaLznS97R7S/1bYj5okQCAEDKx9RALhEKqZKoyo9jwn4p3BVA==
"@walletconnect/universal-provider@2.19.1":
version "2.19.1"
resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.19.1.tgz#9908431b766fffcb0f617f3fdb7e85f27f05f9de"
integrity sha512-4rdLvJ2TGDIieNWW3sZw2MXlX65iHpTuKb5vyvUHQtjIVNLj+7X/09iUAI/poswhtspBK0ytwbH+AIT/nbGpjg==
dependencies:
"@walletconnect/events" "1.0.1"
"@walletconnect/jsonrpc-http-connection" "1.0.8"
......@@ -7605,11 +7456,11 @@
"@walletconnect/jsonrpc-utils" "1.0.8"
"@walletconnect/keyvaluestorage" "1.1.1"
"@walletconnect/logger" "2.1.2"
"@walletconnect/sign-client" "2.18.0"
"@walletconnect/types" "2.18.0"
"@walletconnect/utils" "2.18.0"
"@walletconnect/sign-client" "2.19.1"
"@walletconnect/types" "2.19.1"
"@walletconnect/utils" "2.19.1"
es-toolkit "1.33.0"
events "3.3.0"
lodash "4.17.21"
"@walletconnect/utils@2.17.0":
version "2.17.0"
......@@ -7633,12 +7484,11 @@
query-string "7.1.3"
uint8arrays "3.1.0"
"@walletconnect/utils@2.18.0":
version "2.18.0"
resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.18.0.tgz#1caa15eb6704dcfce03b58d96d44a58ef7b103ec"
integrity sha512-6AUXIcjSxTHGRsTtmUP/oqudtwRILrQqrJsH3jS5T28FFDzZt7+On6fR4mXzi64k4nNYeWg1wMCGLEdtxmGbZQ==
"@walletconnect/utils@2.19.1":
version "2.19.1"
resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.19.1.tgz#16cbc173cd3b28cbf86ca5c6e362057810da07f9"
integrity sha512-aOwcg+Hpph8niJSXLqkU25pmLR49B8ECXp5gFQDW5IeVgXHoOoK7w8a79GBhIBheMLlIt1322sTKQ7Rq5KzzFg==
dependencies:
"@ethersproject/transactions" "5.7.0"
"@noble/ciphers" "1.2.1"
"@noble/curves" "1.8.1"
"@noble/hashes" "1.7.1"
......@@ -7648,13 +7498,15 @@
"@walletconnect/relay-auth" "1.1.0"
"@walletconnect/safe-json" "1.0.2"
"@walletconnect/time" "1.0.2"
"@walletconnect/types" "2.18.0"
"@walletconnect/types" "2.19.1"
"@walletconnect/window-getters" "1.0.1"
"@walletconnect/window-metadata" "1.0.1"
bs58 "6.0.0"
detect-browser "5.3.0"
elliptic "6.6.1"
query-string "7.1.3"
uint8arrays "3.1.0"
viem "2.23.2"
"@walletconnect/window-getters@1.0.1", "@walletconnect/window-getters@^1.0.1":
version "1.0.1"
......@@ -8352,16 +8204,16 @@ abitype@1.0.5:
resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.5.tgz#29d0daa3eea867ca90f7e4123144c1d1270774b6"
integrity sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==
abitype@1.0.6, abitype@^1.0.6:
abitype@1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.8.tgz#3554f28b2e9d6e9f35eb59878193eabd1b9f46ba"
integrity sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==
abitype@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.6.tgz#76410903e1d88e34f1362746e2d407513c38565b"
integrity sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==
abitype@1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.7.tgz#876a0005d211e1c9132825d45bcee7b46416b284"
integrity sha512-ZfYYSktDQUwc2eduYu8C4wOs+RDPmnRYMh7zNfzeMtGGgb0U+6tLGjixUic6mXf5xKKCcgT5Qp6cv39tOARVFw==
abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
......@@ -8789,9 +8641,9 @@ axe-core@^4.10.0:
integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==
axios@^1.4.0, axios@^1.6.2:
version "1.7.7"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f"
integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==
version "1.8.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.4.tgz#78990bb4bc63d2cae072952d374835950a82f447"
integrity "sha1-eJkLtLxj0srgcpUtN0g1lQqC9Ec= sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw=="
dependencies:
follow-redirects "^1.15.6"
form-data "^4.0.0"
......@@ -9550,11 +9402,6 @@ core-js-compat@^3.25.1:
dependencies:
browserslist "^4.21.4"
core-js-pure@^3.25.1:
version "3.30.1"
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.30.1.tgz#7d93dc89e7d47b8ef05d7e79f507b0e99ea77eec"
integrity sha512-nXBEVpmUnNRhz83cHd9JRQC52cTMcuXAmR56+9dSMpRdpeA4I1PX6yjmhd71Eyc/wXNsdBdUDIj1QTIeZpU5Tg==
core-js-pure@^3.30.2:
version "3.31.0"
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.31.0.tgz#052fd9e82fbaaf86457f5db1fadcd06f15966ff2"
......@@ -10079,10 +9926,10 @@ dateformat@^4.6.3:
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5"
integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==
dayjs@1.11.10:
version "1.11.10"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0"
integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==
dayjs@1.11.13:
version "1.11.13"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
dayjs@^1.11.5:
version "1.11.5"
......@@ -10479,19 +10326,6 @@ electron-to-chromium@^1.5.28:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.28.tgz#aee074e202c6ee8a0030a9c2ef0b3fe9f967d576"
integrity sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==
elliptic@6.5.4:
version "6.5.4"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
dependencies:
bn.js "^4.11.9"
brorand "^1.1.0"
hash.js "^1.0.0"
hmac-drbg "^1.0.1"
inherits "^2.0.4"
minimalistic-assert "^1.0.1"
minimalistic-crypto-utils "^1.0.1"
elliptic@6.6.1, elliptic@^6.5.7:
version "6.6.1"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06"
......@@ -10826,6 +10660,11 @@ es-toolkit@1.31.0:
resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.31.0.tgz#f4fc1382aea09cb239afa38f3c724a5658ff3163"
integrity sha512-vwS0lv/tzjM2/t4aZZRAgN9I9TP0MSkWuvt6By+hEXfG/uLs8yg2S1/ayRXH/x3pinbLgVJYT+eppueg3cM6tg==
es-toolkit@1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.33.0.tgz#bcc9d92ef2e1ed4618c00dd30dfda9faddf4a0b7"
integrity sha512-X13Q/ZSc+vsO1q600bvNK4bxgXMkHcf//RxCmYDaRY5DAcT+eoXjY5hoAPGMdRnWQjvyLEcyauG3b6hz76LNqg==
esbuild@^0.20.0:
version "0.20.2"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1"
......@@ -14039,7 +13878,7 @@ lodash.throttle@^4.1.1:
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==
lodash@4.17.21, lodash@^4.15.0, lodash@^4.17.21:
lodash@^4.15.0, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
......@@ -14892,10 +14731,23 @@ os-tmpdir@~1.0.2:
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
ox@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ox/-/ox-0.1.2.tgz#0f791be2ccabeaf4928e6d423498fe1c8094e560"
integrity sha512-ak/8K0Rtphg9vnRJlbOdaX9R7cmxD2MiSthjWGaQdMk3D7hrAlDoM+6Lxn7hN52Za3vrXfZ7enfke/5WjolDww==
ox@0.6.7:
version "0.6.7"
resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.7.tgz#afd53f2ecef68b8526660e9d29dee6e6b599a832"
integrity sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==
dependencies:
"@adraffy/ens-normalize" "^1.10.1"
"@noble/curves" "^1.6.0"
"@noble/hashes" "^1.5.0"
"@scure/bip32" "^1.5.0"
"@scure/bip39" "^1.4.0"
abitype "^1.0.6"
eventemitter3 "5.0.1"
ox@0.6.9:
version "0.6.9"
resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.9.tgz#da1ee04fa10de30c8d04c15bfb80fe58b1f554bd"
integrity sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==
dependencies:
"@adraffy/ens-normalize" "^1.10.1"
"@noble/curves" "^1.6.0"
......@@ -15507,9 +15359,9 @@ pretty-format@^29.0.0, pretty-format@^29.3.1:
react-is "^18.0.0"
prismjs@^1.27.0:
version "1.29.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12"
integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==
version "1.30.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.30.0.tgz#d9709969d9d4e16403f6f348c63553b19f0975a9"
integrity "sha1-2XCZadnU4WQD9vNIxjVTsZ8Jdak= sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="
prismjs@~1.27.0:
version "1.27.0"
......@@ -16189,21 +16041,6 @@ regenerate@^1.4.2:
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
regenerator-runtime@^0.13.10:
version "0.13.10"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee"
integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==
regenerator-runtime@^0.13.11:
version "0.13.11"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
regenerator-runtime@^0.13.4:
version "0.13.9"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
regenerator-runtime@^0.14.0:
version "0.14.0"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45"
......@@ -18020,6 +17857,11 @@ use-sync-external-store@1.2.0, use-sync-external-store@^1.0.0:
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
use-sync-external-store@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc"
integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==
utf-8-validate@^5.0.2:
version "5.0.10"
resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2"
......@@ -18094,34 +17936,32 @@ varint@^6.0.0:
resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0"
integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==
viem@2.21.54:
version "2.21.54"
resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.54.tgz#76d6f86ab8809078f1ac140ac1a2beadbc86b9f6"
integrity sha512-G9mmtbua3UtnVY9BqAtWdNp+3AO+oWhD0B9KaEsZb6gcrOWgmA4rz02yqEMg+qW9m6KgKGie7q3zcHqJIw6AqA==
viem@2.23.14, viem@>=2.23.5:
version "2.23.14"
resolved "https://registry.yarnpkg.com/viem/-/viem-2.23.14.tgz#87b2c93b37014c354d1624183cce685f88c56a97"
integrity sha512-ol8UKYT418u+7Lg83Ut7WJe7iOn1daGAqaofCoPe5z7eGR/XCu3ydja7eL7Z5ffwp6r0RoXeWkpun78UYhKygA==
dependencies:
"@noble/curves" "1.7.0"
"@noble/hashes" "1.6.1"
"@scure/bip32" "1.6.0"
"@scure/bip39" "1.5.0"
abitype "1.0.7"
"@noble/curves" "1.8.1"
"@noble/hashes" "1.7.1"
"@scure/bip32" "1.6.2"
"@scure/bip39" "1.5.4"
abitype "1.0.8"
isows "1.0.6"
ox "0.1.2"
webauthn-p256 "0.0.10"
ws "8.18.0"
ox "0.6.9"
ws "8.18.1"
viem@2.x:
version "2.21.32"
resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.32.tgz#b7f43b2004967036f83500260290cee45189f62a"
integrity sha512-2oXt5JNIb683oy7C8wuIJ/SeL3XtHVMEQpy1U2TA6WMnJQ4ScssRvyPwYLcaP6mKlrGXE/cR/V7ncWpvLUVPYQ==
viem@2.23.2:
version "2.23.2"
resolved "https://registry.yarnpkg.com/viem/-/viem-2.23.2.tgz#db395c8cf5f4fb5572914b962fb8ce5db09f681c"
integrity sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==
dependencies:
"@adraffy/ens-normalize" "1.11.0"
"@noble/curves" "1.6.0"
"@noble/hashes" "1.5.0"
"@scure/bip32" "1.5.0"
"@scure/bip39" "1.4.0"
abitype "1.0.6"
"@noble/curves" "1.8.1"
"@noble/hashes" "1.7.1"
"@scure/bip32" "1.6.2"
"@scure/bip39" "1.5.4"
abitype "1.0.8"
isows "1.0.6"
webauthn-p256 "0.0.10"
ox "0.6.7"
ws "8.18.0"
viem@^1.20.3:
......@@ -18193,14 +18033,14 @@ w3c-xmlserializer@^3.0.0:
dependencies:
xml-name-validator "^4.0.0"
wagmi@2.14.0:
version "2.14.0"
resolved "https://registry.yarnpkg.com/wagmi/-/wagmi-2.14.0.tgz#f2d7358b7f29a8a8e012b779d51bf83da269299e"
integrity sha512-IO/jPEqHTMAg4/SV4Dg3UR4AeACATyrNprwSpI0FlKEhAjmmNz8N+fa9vI24TUqJ3svLFdA32rjXJvNazeZv9g==
wagmi@2.14.15:
version "2.14.15"
resolved "https://registry.yarnpkg.com/wagmi/-/wagmi-2.14.15.tgz#d7081f045e00ec9bf9e7076fe8c6f506f2a96094"
integrity sha512-sRa7FsEmgph1KsIK93wCS2MhZgUae18jI/+Ger+INSxytJbhzNkukpHxWlNfV/Skl8zxDAQfxucotZLi8UadZQ==
dependencies:
"@wagmi/connectors" "5.6.0"
"@wagmi/core" "2.16.0"
use-sync-external-store "1.2.0"
"@wagmi/connectors" "5.7.11"
"@wagmi/core" "2.16.7"
use-sync-external-store "1.4.0"
walker@^1.0.8:
version "1.0.8"
......@@ -18227,14 +18067,6 @@ web-tree-sitter@=0.20.3:
resolved "https://registry.yarnpkg.com/web-tree-sitter/-/web-tree-sitter-0.20.3.tgz#3dd17b283ad63b1d8c07c5ea814f0fefb2b1f776"
integrity sha512-zKGJW9r23y3BcJusbgvnOH2OYAW40MXAOi9bi3Gcc7T4Gms9WWgXF8m6adsJWpGJEhgOzCrfiz1IzKowJWrtYw==
webauthn-p256@0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/webauthn-p256/-/webauthn-p256-0.0.10.tgz#877e75abe8348d3e14485932968edf3325fd2fdd"
integrity sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA==
dependencies:
"@noble/curves" "^1.4.0"
"@noble/hashes" "^1.4.0"
webauthn-p256@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/webauthn-p256/-/webauthn-p256-0.0.5.tgz#0baebd2ba8a414b21cc09c0d40f9dd0be96a06bd"
......@@ -18472,6 +18304,11 @@ ws@8.18.0, ws@^8.17.1, ws@^8.9.0:
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
ws@8.18.1:
version "8.18.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb"
integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==
ws@^7.3.1, ws@^7.5.1:
version "7.5.10"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment