From 82e585bd5924414d4ed40f88326e69e3796dfd93 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Wed, 27 Nov 2024 10:37:08 +0100 Subject: [PATCH 01/36] feat(wallet): Make GH Releases for wallet production releases (#3954) * feat(wallet): Make GH Releases for wallet production releases * upload artifact again * fmt * fmt with dprint * chore: Always create drafted releases * chore: Temporary add `workflow_dipsatch` for testing purposes * chore: Remove `workflow_dipsatch` * chore: Pin `@elgohr/create-release` --- .github/workflows/apps_wallet_prod_build.yml | 42 ++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/.github/workflows/apps_wallet_prod_build.yml b/.github/workflows/apps_wallet_prod_build.yml index 964ee7d1411..ade6a448804 100644 --- a/.github/workflows/apps_wallet_prod_build.yml +++ b/.github/workflows/apps_wallet_prod_build.yml @@ -39,6 +39,48 @@ jobs: echo "artifact_name=${artifact_name}" >> $GITHUB_ENV - name: Build Wallet run: pnpm wallet build + - name: Get Previous Tag + id: prev_tag + run: | + tags=$(git tag --list 'wallet-v*.*.*' --sort=-creatordate) + current_tag=$(echo "$tags" | sed -n 1p) + prev_tag=$(echo "$tags" | sed -n 2p) + if [ -z "$prev_tag" ]; then + echo "No previous tag found. Skipping changelog generation." + echo "PREV_TAG=none" >> $GITHUB_ENV + else + echo "PREV_TAG=$prev_tag" >> $GITHUB_ENV + fi + echo "CURRENT_TAG=$current_tag" >> $GITHUB_ENV + + - name: Generate Changelog + id: generate_changelog + run: | + if [ "${{ env.PREV_TAG }}" = "none" ]; then + echo "No previous tag found. Skipping changelog generation." + echo "changelog=No previous tag found. Changelog generation skipped." >> $GITHUB_ENV + else + git log ${{ env.PREV_TAG }}..${{ env.CURRENT_TAG }} --pretty=format:"- %s by @%an in #%h" -- ./apps/wallet > CHANGELOG.md + changelog=$(cat CHANGELOG.md) + echo "changelog=$changelog" >> $GITHUB_ENV + fi + + - name: Get version from tag + id: version + run: echo "::set-output name=version::${GITHUB_REF#refs/tags/wallet-v}" + + - name: Create GitHub Release + uses: elgohr/create-release@c5ea99036abb741a89f8bf1f2cd7fba845e3313a # pin@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.CURRENT_TAG }} + release_name: IOTA Wallet v${{ steps.version.outputs.version }} + body: | + ## Changelog + {{ env.changelog }} + draft: true + prerelease: false - name: Upload artifacts uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4 with: From c0ed32d7711f43bc917d9f86920acb18f976c669 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Wed, 27 Nov 2024 10:55:02 +0100 Subject: [PATCH 02/36] fix(tooling-general): Fix Apps Wallet prod build workflow (#4265) * fix: Use correct name of gh action to make gh releases * chore: add workflow_dispatch --- .github/workflows/apps_wallet_prod_build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/apps_wallet_prod_build.yml b/.github/workflows/apps_wallet_prod_build.yml index ade6a448804..7fe6657ef78 100644 --- a/.github/workflows/apps_wallet_prod_build.yml +++ b/.github/workflows/apps_wallet_prod_build.yml @@ -1,6 +1,7 @@ name: Build Wallet App (Prod) on: + workflow_dispatch: push: tags: - "wallet-v[0-9]+.[0-9]+.[0-9]+" @@ -70,7 +71,7 @@ jobs: run: echo "::set-output name=version::${GITHUB_REF#refs/tags/wallet-v}" - name: Create GitHub Release - uses: elgohr/create-release@c5ea99036abb741a89f8bf1f2cd7fba845e3313a # pin@v5 + uses: elgohr/Github-Release-Action@c5ea99036abb741a89f8bf1f2cd7fba845e3313a # pin@v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: From 207bfa04863b141f062e2c47b30597fb3248f6d4 Mon Sep 17 00:00:00 2001 From: Sergiu Popescu <44298302+sergiupopescu199@users.noreply.github.com> Date: Wed, 27 Nov 2024 10:59:59 +0100 Subject: [PATCH 03/36] fix(iota-indexer): fix failing test (#4173) * fix(iota-indexer): fix failing test * fixup! fix(iota-indexer): fix failing test * fixup! fixup! fix(iota-indexer): fix failing test * fixup! fixup! fixup! fix(iota-indexer): fix failing test * fix(*): add rest api sync flag * fix(*): fallback to rest api * Update crates/iota-indexer/src/test_utils.rs Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> * fixup! fix(*): fallback to rest api --------- Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- crates/iota-cluster-test/src/cluster.rs | 4 ++-- crates/iota-indexer/src/test_utils.rs | 9 ++++++--- crates/iota-indexer/tests/common/mod.rs | 6 +++--- crates/iota-indexer/tests/rpc-tests/read_api.rs | 1 + crates/iota/src/iota_commands.rs | 4 ++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/iota-cluster-test/src/cluster.rs b/crates/iota-cluster-test/src/cluster.rs index 20eee208d0b..3c1d993f992 100644 --- a/crates/iota-cluster-test/src/cluster.rs +++ b/crates/iota-cluster-test/src/cluster.rs @@ -264,7 +264,7 @@ impl Cluster for LocalNewCluster { Some(pg_address.clone()), fullnode_url.clone(), ReaderWriterConfig::writer_mode(None), - data_ingestion_path.clone(), + Some(data_ingestion_path.clone()), None, ) .await; @@ -274,7 +274,7 @@ impl Cluster for LocalNewCluster { Some(pg_address), fullnode_url.clone(), ReaderWriterConfig::reader_mode(indexer_address.to_string()), - data_ingestion_path, + Some(data_ingestion_path), None, ) .await; diff --git a/crates/iota-indexer/src/test_utils.rs b/crates/iota-indexer/src/test_utils.rs index 4058acc5634..3d9bf3f80cc 100644 --- a/crates/iota-indexer/src/test_utils.rs +++ b/crates/iota-indexer/src/test_utils.rs @@ -44,7 +44,7 @@ pub async fn start_test_indexer( db_url: Option, rpc_url: String, reader_writer_config: ReaderWriterConfig, - data_ingestion_path: PathBuf, + data_ingestion_path: Option, new_database: Option<&str>, ) -> (PgIndexerStore, JoinHandle>) { start_test_indexer_impl( @@ -53,7 +53,7 @@ pub async fn start_test_indexer( reader_writer_config, // reset_database false, - Some(data_ingestion_path), + data_ingestion_path, CancellationToken::new(), new_database, ) @@ -86,11 +86,14 @@ pub async fn start_test_indexer_impl( let mut config = IndexerConfig { db_url: Some(db_url.clone().into()), + // As fallback sync mechanism enable Rest Api if `data_ingestion_path` was not provided + remote_store_url: data_ingestion_path + .is_none() + .then_some(format!("{rpc_url}/api/v1")), rpc_client_url: rpc_url, reset_db: true, fullnode_sync_worker: true, rpc_server_worker: false, - remote_store_url: None, data_ingestion_path, ..Default::default() }; diff --git a/crates/iota-indexer/tests/common/mod.rs b/crates/iota-indexer/tests/common/mod.rs index 55273b8a1d9..23ccf354899 100644 --- a/crates/iota-indexer/tests/common/mod.rs +++ b/crates/iota-indexer/tests/common/mod.rs @@ -114,7 +114,7 @@ pub async fn start_test_cluster_with_read_write_indexer( builder_modifier: Option TestClusterBuilder>>, ) -> (TestCluster, PgIndexerStore, HttpClient) { let temp = tempdir().unwrap().into_path(); - let mut builder = TestClusterBuilder::new().with_data_ingestion_dir(temp.clone()); + let mut builder = TestClusterBuilder::new(); if let Some(builder_modifier) = builder_modifier { builder = builder_modifier(builder); @@ -127,7 +127,7 @@ pub async fn start_test_cluster_with_read_write_indexer( Some(get_indexer_db_url(None)), cluster.rpc_url().to_string(), ReaderWriterConfig::writer_mode(None), - temp.clone(), + None, database_name, ) .await; @@ -305,7 +305,7 @@ pub async fn start_simulacrum_rest_api_with_write_indexer( Some(get_indexer_db_url(None)), format!("http://{}", server_url), ReaderWriterConfig::writer_mode(None), - data_ingestion_path, + Some(data_ingestion_path), database_name, ) .await; diff --git a/crates/iota-indexer/tests/rpc-tests/read_api.rs b/crates/iota-indexer/tests/rpc-tests/read_api.rs index 5d0d17f7e05..382c6ea4ad3 100644 --- a/crates/iota-indexer/tests/rpc-tests/read_api.rs +++ b/crates/iota-indexer/tests/rpc-tests/read_api.rs @@ -1158,6 +1158,7 @@ fn get_total_transaction_blocks() { runtime.block_on(async move { indexer_wait_for_checkpoint(store, checkpoint).await; + let total_transaction_blocks = client.get_total_transaction_blocks().await.unwrap(); let fullnode_checkpoint = cluster diff --git a/crates/iota/src/iota_commands.rs b/crates/iota/src/iota_commands.rs index 0e37b2f016b..b4eb64d0724 100644 --- a/crates/iota/src/iota_commands.rs +++ b/crates/iota/src/iota_commands.rs @@ -755,7 +755,7 @@ async fn start( Some(pg_address.clone()), fullnode_url.clone(), ReaderWriterConfig::writer_mode(None), - data_ingestion_path.clone(), + Some(data_ingestion_path.clone()), None, ) .await; @@ -766,7 +766,7 @@ async fn start( Some(pg_address.clone()), fullnode_url.clone(), ReaderWriterConfig::reader_mode(indexer_address.to_string()), - data_ingestion_path, + Some(data_ingestion_path), None, ) .await; From ea7499c5f48866fdbf0092a6f3f60beb5dd5a227 Mon Sep 17 00:00:00 2001 From: JCNoguera <88061365+VmMad@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:13:44 +0100 Subject: [PATCH 04/36] fix(wallet): toast overlay connecting dapp buttons (#4243) --- apps/wallet/src/ui/app/shared/toaster/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/wallet/src/ui/app/shared/toaster/index.tsx b/apps/wallet/src/ui/app/shared/toaster/index.tsx index d5ff889a72c..47c7d8dcb64 100644 --- a/apps/wallet/src/ui/app/shared/toaster/index.tsx +++ b/apps/wallet/src/ui/app/shared/toaster/index.tsx @@ -37,8 +37,10 @@ function getBottomSpace(pathname: string, isMenuVisible: boolean, isBottomNavSpa '/accounts/manage', ].includes(pathname); - if (overlayWithActionButton || isBottomNavSpace) { - return '!bottom-16'; + const matchDynamicPaths = ['/dapp/connect'].some((path) => pathname.startsWith(path)); + + if (overlayWithActionButton || isBottomNavSpace || matchDynamicPaths) { + return '!bottom-20'; } return ''; From c010a5ddd47557df2c5bc0db80de0f4d6bb3963b Mon Sep 17 00:00:00 2001 From: JCNoguera <88061365+VmMad@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:39:24 +0100 Subject: [PATCH 05/36] fix(wallet, dashboard): use validator image when possible (#4247) * fix(wallet, dashboard): use validator image when possible * fix: remove unnecessary change * feat: add missing image in dashboard --- .../Dialogs/Staking/views/DetailsView.tsx | 2 +- .../components/Dialogs/Staking/views/Validator.tsx | 14 ++++++++++---- .../ui/app/staking/validators/ValidatorLogo.tsx | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/wallet-dashboard/components/Dialogs/Staking/views/DetailsView.tsx b/apps/wallet-dashboard/components/Dialogs/Staking/views/DetailsView.tsx index 79106443924..7e81f984e79 100644 --- a/apps/wallet-dashboard/components/Dialogs/Staking/views/DetailsView.tsx +++ b/apps/wallet-dashboard/components/Dialogs/Staking/views/DetailsView.tsx @@ -108,7 +108,7 @@ export function DetailsView({ @@ -47,7 +48,12 @@ export function Validator({ return ( - + {showAction && ( diff --git a/apps/wallet/src/ui/app/staking/validators/ValidatorLogo.tsx b/apps/wallet/src/ui/app/staking/validators/ValidatorLogo.tsx index dcb8954a274..bf8d05a97b6 100644 --- a/apps/wallet/src/ui/app/staking/validators/ValidatorLogo.tsx +++ b/apps/wallet/src/ui/app/staking/validators/ValidatorLogo.tsx @@ -82,7 +82,7 @@ export function ValidatorLogo({ Date: Wed, 27 Nov 2024 13:36:07 +0100 Subject: [PATCH 06/36] feat: rebrand toasts (#4261) Co-authored-by: Bran <52735957+brancoder@users.noreply.github.com> --- apps/wallet-dashboard/components/Toaster.tsx | 40 +++++++++++++++++++ apps/wallet-dashboard/components/index.ts | 1 + .../providers/AppProviders.tsx | 9 +---- 3 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 apps/wallet-dashboard/components/Toaster.tsx diff --git a/apps/wallet-dashboard/components/Toaster.tsx b/apps/wallet-dashboard/components/Toaster.tsx new file mode 100644 index 00000000000..12b29435158 --- /dev/null +++ b/apps/wallet-dashboard/components/Toaster.tsx @@ -0,0 +1,40 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import toast, { Toaster as ToasterLib, type ToastType, resolveValue } from 'react-hot-toast'; +import { Snackbar, SnackbarType } from '@iota/apps-ui-kit'; + +export type ToasterProps = { + bottomNavEnabled?: boolean; +}; + +export function Toaster() { + function getSnackbarType(type: ToastType): SnackbarType { + switch (type) { + case 'success': + return SnackbarType.Default; + case 'error': + return SnackbarType.Error; + case 'loading': + return SnackbarType.Default; + default: + return SnackbarType.Default; + } + } + + return ( + + {(t) => ( +
+ toast.dismiss(t.id)} + text={resolveValue(t.message, t)} + type={getSnackbarType(t.type)} + showClose + duration={t.duration} + /> +
+ )} +
+ ); +} diff --git a/apps/wallet-dashboard/components/index.ts b/apps/wallet-dashboard/components/index.ts index c1320cc7447..d35471140d9 100644 --- a/apps/wallet-dashboard/components/index.ts +++ b/apps/wallet-dashboard/components/index.ts @@ -23,3 +23,4 @@ export * from './ExplorerLink'; export * from './Dialogs'; export * from './ValidatorStakingData'; export * from './tiles'; +export * from './Toaster'; diff --git a/apps/wallet-dashboard/providers/AppProviders.tsx b/apps/wallet-dashboard/providers/AppProviders.tsx index 342a6fa6c34..69b2cebb513 100644 --- a/apps/wallet-dashboard/providers/AppProviders.tsx +++ b/apps/wallet-dashboard/providers/AppProviders.tsx @@ -3,7 +3,7 @@ 'use client'; -import { PopupProvider } from '@/components'; +import { PopupProvider, Toaster } from '@/components'; import { GrowthBookProvider } from '@growthbook/growthbook-react'; import { IotaClientProvider, lightTheme, darkTheme, WalletProvider } from '@iota/dapp-kit'; import { getAllNetworks, getDefaultNetwork } from '@iota/iota-sdk/client'; @@ -11,7 +11,6 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useState } from 'react'; import { growthbook } from '@/lib/utils'; import { Popup } from '@/components/Popup'; -import { Toaster } from 'react-hot-toast'; import { ThemeProvider } from '@iota/core'; growthbook.init(); @@ -40,11 +39,7 @@ export function AppProviders({ children }: React.PropsWithChildren) { {children} - + From 5c63706b638378d6a2d6b3c1f1ae2164c57a5e24 Mon Sep 17 00:00:00 2001 From: Panteleymonchuk Date: Wed, 27 Nov 2024 16:21:06 +0200 Subject: [PATCH 07/36] feat(dashboard): update activity page (#4251) * feat(dashboard): update activity page * fix(dashboard): update layout height --- .../app/(protected)/activity/page.tsx | 37 ++++++------------- .../app/(protected)/layout.tsx | 2 +- apps/wallet-dashboard/app/globals.css | 2 +- 3 files changed, 14 insertions(+), 27 deletions(-) diff --git a/apps/wallet-dashboard/app/(protected)/activity/page.tsx b/apps/wallet-dashboard/app/(protected)/activity/page.tsx index 63a84224f75..14f4bc516da 100644 --- a/apps/wallet-dashboard/app/(protected)/activity/page.tsx +++ b/apps/wallet-dashboard/app/(protected)/activity/page.tsx @@ -4,34 +4,21 @@ 'use client'; import React from 'react'; -import { useCurrentAccount } from '@iota/dapp-kit'; -import { VirtualList, TransactionTile } from '@/components'; -import { useQueryTransactionsByAddress } from '@iota/core'; -import { getExtendedTransaction } from '@/lib/utils/transaction'; -import { IotaTransactionBlockResponse } from '@iota/iota-sdk/client'; +import { Panel, Title, TitleSize } from '@iota/apps-ui-kit'; +import { TransactionsList } from '@/components'; function ActivityPage(): JSX.Element { - const currentAccount = useCurrentAccount(); - const { data: transactions, error } = useQueryTransactionsByAddress(currentAccount?.address); - - if (error) { - return
{error?.message}
; - } - - const virtualItem = (rawTransaction: IotaTransactionBlockResponse): JSX.Element => { - const transaction = getExtendedTransaction(rawTransaction, currentAccount?.address || ''); - return ; - }; - return ( -
-

Your Activity

-
- 100} - render={virtualItem} - /> +
+
+ +
+ + </div> + <div className="px-sm pb-md pt-sm"> + <TransactionsList /> + </div> + </Panel> </div> </div> ); diff --git a/apps/wallet-dashboard/app/(protected)/layout.tsx b/apps/wallet-dashboard/app/(protected)/layout.tsx index 79f7a084546..2ba32059a9b 100644 --- a/apps/wallet-dashboard/app/(protected)/layout.tsx +++ b/apps/wallet-dashboard/app/(protected)/layout.tsx @@ -17,7 +17,7 @@ function DashboardLayout({ children }: PropsWithChildren): JSX.Element { }; return ( - <div className="h-full"> + <div className="min-h-full"> <div className="fixed left-0 top-0 z-50 h-full"> <Sidebar /> </div> diff --git a/apps/wallet-dashboard/app/globals.css b/apps/wallet-dashboard/app/globals.css index f4151e588f5..82c7527e111 100644 --- a/apps/wallet-dashboard/app/globals.css +++ b/apps/wallet-dashboard/app/globals.css @@ -6,7 +6,7 @@ html, body { - height: 100%; + min-height: 100%; @apply bg-gray-100 dark:bg-gray-900; @apply text-gray-900 dark:text-gray-100; } From de4df8e2274291d5365e545585a4fafe00515cc9 Mon Sep 17 00:00:00 2001 From: Marc Espin <mespinsanz@gmail.com> Date: Wed, 27 Nov 2024 17:20:59 +0100 Subject: [PATCH 08/36] docs(ts-sdk): Update outdated TS SDK Docs (#4255) * docs(ts-sdk): Update outdated TS SDK Docs * ' * use Network enum * fix usage of Network * fix reference of Network.Custom --- dapps/kiosk-cli/index.js | 4 ++-- .../kiosk/src/context/KioskClientContext.tsx | 5 +++-- .../developer/standards/wallet-standard.mdx | 6 +++--- .../ts-sdk/kiosk/advanced-examples.mdx | 4 ++-- .../kiosk/kiosk-client/introduction.mdx | 21 +++++++------------ .../kiosk-transaction/purchasing.mdx | 5 ++--- 6 files changed, 20 insertions(+), 25 deletions(-) diff --git a/dapps/kiosk-cli/index.js b/dapps/kiosk-cli/index.js index a54976a9a9a..aff1f965b12 100644 --- a/dapps/kiosk-cli/index.js +++ b/dapps/kiosk-cli/index.js @@ -34,7 +34,7 @@ import { } from '@iota/iota-sdk/utils'; import { bcs } from '@iota/iota-sdk/bcs'; import { program } from 'commander'; -import { KIOSK_LISTING, KioskClient, KioskTransaction, Network } from '@iota/kiosk'; +import { KIOSK_LISTING, KioskClient, KioskTransaction } from '@iota/kiosk'; import { IotaClient, getFullnodeUrl } from '@iota/iota-sdk/client'; import { Ed25519Keypair } from '@iota/iota-sdk/keypairs/ed25519'; import { Transaction } from '@iota/iota-sdk/transactions'; @@ -49,7 +49,7 @@ const client = new IotaClient({ url: getFullnodeUrl('testnet') }); const kioskClient = new KioskClient({ client, - network: Network.TESTNET, + network: 'testnet', }); /** diff --git a/dapps/kiosk/src/context/KioskClientContext.tsx b/dapps/kiosk/src/context/KioskClientContext.tsx index e193465a553..1aa6339edfd 100644 --- a/dapps/kiosk/src/context/KioskClientContext.tsx +++ b/dapps/kiosk/src/context/KioskClientContext.tsx @@ -3,7 +3,8 @@ // SPDX-License-Identifier: Apache-2.0 import { useIotaClient, useIotaClientContext } from '@iota/dapp-kit'; -import { KioskClient, Network } from '@iota/kiosk'; +import { NetworkId } from '@iota/iota-sdk/client'; +import { KioskClient } from '@iota/kiosk'; import { createContext, ReactNode, useContext, useMemo } from 'react'; export const KioskClientContext = createContext<KioskClient | undefined>(undefined); @@ -15,7 +16,7 @@ export function KioskClientProvider({ children }: { children: ReactNode }) { () => new KioskClient({ client: iotaClient, - network: network as Network, + network: network as NetworkId, }), [iotaClient, network], ); diff --git a/docs/content/developer/standards/wallet-standard.mdx b/docs/content/developer/standards/wallet-standard.mdx index 8cc9142dde4..4a529531af1 100644 --- a/docs/content/developer/standards/wallet-standard.mdx +++ b/docs/content/developer/standards/wallet-standard.mdx @@ -20,7 +20,7 @@ Create a class that represents your wallet. Use the `Wallet` interface from `@iota/wallet-standard` to help ensure your class adheres to the standard. ```tsx -import { IOTA_DEVNET_CHAIN, Wallet } from '@iota/wallet-standard'; +import { SUPPORTED_CHAINS, Wallet } from '@iota/wallet-standard'; class YourWallet implements Wallet { get version() { @@ -35,7 +35,7 @@ class YourWallet implements Wallet { } // Return the IOTA chains that your wallet supports. get chains() { - return [IOTA_DEVNET_CHAIN]; + return SUPPORTED_CHAINS; } } ``` @@ -152,7 +152,7 @@ class YourWallet implements Wallet { address: walletAccount.iotaAddress, publicKey: walletAccount.pubkey, // The IOTA chains that your wallet supports. - chains: [IOTA_DEVNET_CHAIN], + chains: [SUPPORTED_CHAINS], // The features that this account supports. This can be a subset of the wallet's supported features. // These features must exist on the wallet as well. features: [ diff --git a/docs/content/references/ts-sdk/kiosk/advanced-examples.mdx b/docs/content/references/ts-sdk/kiosk/advanced-examples.mdx index 181ec1ed41d..1948d65c4f1 100644 --- a/docs/content/references/ts-sdk/kiosk/advanced-examples.mdx +++ b/docs/content/references/ts-sdk/kiosk/advanced-examples.mdx @@ -12,9 +12,9 @@ const otherType = `${packageId}::other_module::OtherStruct<${packageId}::other_c // initialize a kioskClient. const kioskClient = new KioskClient({ client: new IotaClient({ - url: getFullnodeUrl('testnet'), + url: getFullnodeUrl(Network.Testnet), }), - network: Network.TESTNET, + network: Network.Testnet, }); ``` diff --git a/docs/content/references/ts-sdk/kiosk/kiosk-client/introduction.mdx b/docs/content/references/ts-sdk/kiosk/kiosk-client/introduction.mdx index 73bea1b8fce..e52f56bc105 100644 --- a/docs/content/references/ts-sdk/kiosk/kiosk-client/introduction.mdx +++ b/docs/content/references/ts-sdk/kiosk/kiosk-client/introduction.mdx @@ -7,38 +7,33 @@ Kiosk Client is the base for all Kiosk SDK functionality. ## Creating a kiosk client -You can follow the example to create a `KioskClient`. The client currently supports `MAINNET` and -`TESTNET`. View next section for usage in other networks. - -_IOTA Kiosk rules and extensions are not supported in Devnet due to network wipes (that would -require constantly changing the package IDs)._ - +You can follow the example to create a `KioskClient`. View next section for usage in custom networks. ```typescript -import { KioskClient, Network } from '@iota/kiosk'; -import { getFullnodeUrl, IotaClient } from '@iota/iota-sdk/client'; +import { KioskClient } from '@iota/kiosk'; +import { getFullnodeUrl, IotaClient, Network } from '@iota/iota-sdk/client'; // We need a IOTA Client. You can re-use the IotaClient of your project // (it's not recommended to create a new one). -const client = new IotaClient({ url: getFullnodeUrl('testnet') }); +const client = new IotaClient({ url: getFullnodeUrl(Network.Testnet) }); // Now we can use it to create a kiosk Client. const kioskClient = new KioskClient({ client, - network: Network.TESTNET, + network: Network.Testnet, }); ``` -### Using KioskClient on devnet or localnet +### Using KioskClient on custom networks -To use all the functionality of Kiosk SDK outside of `MAINNET` and `TESTNET`, use `Network.CUSTOM` +To use all the functionality of Kiosk SDK outside of official networks, use `Network.Custom` as the network, and pass the `packageIds` for the rules and extensions you want to use. ```typescript // constructing it for custom network use. const kioskClient = new KioskClient({ client, - network: Network.CUSTOM, + network: Network.Custom, packageIds: { kioskLockRulePackageId: '0x...', royaltyRulePackageId: '0x...', diff --git a/docs/content/references/ts-sdk/kiosk/kiosk-client/kiosk-transaction/purchasing.mdx b/docs/content/references/ts-sdk/kiosk/kiosk-client/kiosk-transaction/purchasing.mdx index 0e2492241ce..771150f2592 100644 --- a/docs/content/references/ts-sdk/kiosk/kiosk-client/kiosk-transaction/purchasing.mdx +++ b/docs/content/references/ts-sdk/kiosk/kiosk-client/kiosk-transaction/purchasing.mdx @@ -1,9 +1,8 @@ # Purchasing from a kiosk One of the base functionalities of the SDK is a seamless purchasing flow, allowing for ease of rules -resolving (hiding away the calls). The SDK supports all four rules by default, and works for -`TESTNET` and `MAINNET`. To support other networks, -[follow the instructions in the Introduction](../introduction#using-kioskclient-on-devnet-or-localnet). +resolving (hiding away the calls). To use custom networks, +[follow the instructions in the Introduction](../introduction#using-kioskclient-on-custom-networks). ## How to purchase From 7f082f2e820436f99e2af03c2e2902592686a2c1 Mon Sep 17 00:00:00 2001 From: evavirseda <evirseda@boxfish.studio> Date: Wed, 27 Nov 2024 19:15:25 +0100 Subject: [PATCH 09/36] feat(wallet): change delete account action to destructive color (#4253) --- apps/wallet/src/ui/app/pages/accounts/manage/RemoveDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wallet/src/ui/app/pages/accounts/manage/RemoveDialog.tsx b/apps/wallet/src/ui/app/pages/accounts/manage/RemoveDialog.tsx index e657642946d..807ef298573 100644 --- a/apps/wallet/src/ui/app/pages/accounts/manage/RemoveDialog.tsx +++ b/apps/wallet/src/ui/app/pages/accounts/manage/RemoveDialog.tsx @@ -59,7 +59,7 @@ export function RemoveDialog({ isOpen, setOpen, accountID }: RemoveDialogProps) /> <Button fullWidth - type={ButtonType.Primary} + type={ButtonType.Destructive} text="Remove" onClick={handleRemove} /> From 1dd90acf929d1663a78ab6a1ddc968d05bc5772b Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Thu, 28 Nov 2024 11:30:22 +0100 Subject: [PATCH 10/36] feat(iota): don't require key generation for client.yaml if there is already one (#3978) * feat(iota): don't require key generation for client.yaml if there is already one * print if existing address will be used as active address * Update crates/iota/src/iota_commands.rs Co-authored-by: Thibault Martinez <thibault@iota.org> --------- Co-authored-by: Thibault Martinez <thibault@iota.org> --- crates/iota/src/iota_commands.rs | 39 +++++++++++++++++++------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/crates/iota/src/iota_commands.rs b/crates/iota/src/iota_commands.rs index b4eb64d0724..54cad050dae 100644 --- a/crates/iota/src/iota_commands.rs +++ b/crates/iota/src/iota_commands.rs @@ -1201,29 +1201,36 @@ async fn prompt_if_no_config( .unwrap_or(&iota_config_dir()?) .join(IOTA_KEYSTORE_FILENAME); let mut keystore = Keystore::from(FileBasedKeystore::new(&keystore_path)?); - let key_scheme = if accept_defaults { - SignatureScheme::ED25519 + // Get an existing address or generate a new one + let active_address = if let Some(existing_address) = keystore.addresses().first() { + println!("Using existing address {existing_address} as active address."); + *existing_address } else { + let key_scheme = if accept_defaults { + SignatureScheme::ED25519 + } else { + println!( + "Select key scheme to generate keypair (0 for ed25519, 1 for secp256k1, 2: for secp256r1):" + ); + match SignatureScheme::from_flag(read_line()?.trim()) { + Ok(s) => s, + Err(e) => return Err(anyhow!("{e}")), + } + }; + let (new_address, phrase, scheme) = + keystore.generate_and_add_new_key(key_scheme, None, None, None)?; + let alias = keystore.get_alias_by_address(&new_address)?; println!( - "Select key scheme to generate keypair (0 for ed25519, 1 for secp256k1, 2: for secp256r1):" + "Generated new keypair and alias for address with scheme {:?} [{alias}: {new_address}]", + scheme.to_string() ); - match SignatureScheme::from_flag(read_line()?.trim()) { - Ok(s) => s, - Err(e) => return Err(anyhow!("{e}")), - } + println!("Secret Recovery Phrase : [{phrase}]"); + new_address }; - let (new_address, phrase, scheme) = - keystore.generate_and_add_new_key(key_scheme, None, None, None)?; - let alias = keystore.get_alias_by_address(&new_address)?; - println!( - "Generated new keypair and alias for address with scheme {:?} [{alias}: {new_address}]", - scheme.to_string() - ); - println!("Secret Recovery Phrase : [{phrase}]"); let alias = env.alias().clone(); IotaClientConfig::new(keystore) .with_envs([env]) - .with_active_address(new_address) + .with_active_address(active_address) .with_active_env(alias) .persisted(wallet_conf_path) .save()?; From 64bca645258c3b13572557806791caa79d254c58 Mon Sep 17 00:00:00 2001 From: Samuel Rufinatscha <samuel.rufinatscha@iota.org> Date: Thu, 28 Nov 2024 12:01:51 +0100 Subject: [PATCH 11/36] Review iota-graphql test coverage (#4135) * documentation: review iota-graphql test coverage * documentation: reference the transactional test runner * fix: refer tests.rs module * fix: coverage for dynamic queries * fix: coverage for filter options WIP * fix: restructure coverage * docs: Add missing queries * fix: location paths * fix: format * fix: add missing filter options * fix: remove link * fix: graphql highlights --- crates/iota-graphql-e2e-tests/README.md | 8 + .../mutation/executeTransactionBlock.md | 118 +++++++++ .../coverage/query/address.md | 191 ++++++++++++++ .../coverage/query/availableRange.md | 43 ++++ .../coverage/query/chainIdentifier.md | 16 ++ .../coverage/query/checkpoint.md | 69 ++++++ .../coverage/query/checkpoints.md | 96 ++++++++ .../coverage/query/coinMetadata.md | 45 ++++ .../coverage/query/coins.md | 156 ++++++++++++ .../coverage/query/dryRunTransactionBlock.md | 90 +++++++ .../coverage/query/epoch.md | 107 ++++++++ .../coverage/query/events.md | 49 ++++ .../coverage/query/latestPackage.md | 232 ++++++++++++++++++ .../coverage/query/object.md | 165 +++++++++++++ .../coverage/query/objects.md | 187 ++++++++++++++ .../coverage/query/owner.md | 156 ++++++++++++ .../coverage/query/package.md | 232 ++++++++++++++++++ .../coverage/query/packages.md | 230 +++++++++++++++++ .../coverage/query/protocolConfig.md | 59 +++++ .../coverage/query/serviceConfig.md | 37 +++ .../coverage/query/transactionBlock.md | 74 ++++++ .../coverage/query/transactionBlocks.md | 175 +++++++++++++ .../coverage/query/type.md | 28 +++ crates/iota-graphql-rpc/README.md | 11 + 24 files changed, 2574 insertions(+) create mode 100644 crates/iota-graphql-e2e-tests/coverage/mutation/executeTransactionBlock.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/address.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/availableRange.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/chainIdentifier.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/checkpoint.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/checkpoints.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/coinMetadata.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/coins.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/dryRunTransactionBlock.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/epoch.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/events.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/latestPackage.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/object.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/objects.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/owner.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/package.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/packages.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/protocolConfig.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/serviceConfig.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/transactionBlock.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/transactionBlocks.md create mode 100644 crates/iota-graphql-e2e-tests/coverage/query/type.md diff --git a/crates/iota-graphql-e2e-tests/README.md b/crates/iota-graphql-e2e-tests/README.md index 4e0c24eee8a..a0001d1c739 100644 --- a/crates/iota-graphql-e2e-tests/README.md +++ b/crates/iota-graphql-e2e-tests/README.md @@ -1,6 +1,14 @@ End-to-end tests for GraphQL service, built on top of the transactional test runner. +# Testing through the transactional test runner + +This crate specifically tests GraphQL queries in an e2e manner against the Indexer database. +The tests are executed through the [transactional test runner](../iota-transactional-test-runner), mediated by the [test.rs](tests/tests.rs) module. + +Each test is defined in a `.move` file, which contains various statements that are executed in a transactional manner. +In addition to the `.move` file, there is a corresponding `.exp` file that contains the expected output of the transactional test. + # Local Set-up These tests require a running instance of the `postgres` service, with a diff --git a/crates/iota-graphql-e2e-tests/coverage/mutation/executeTransactionBlock.md b/crates/iota-graphql-e2e-tests/coverage/mutation/executeTransactionBlock.md new file mode 100644 index 00000000000..708215005ff --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/mutation/executeTransactionBlock.md @@ -0,0 +1,118 @@ +Query: `executeTransactionBlock` + +```graphql +mutation { + executeTransactionBlock(txBytes: $tx, signatures: $sigs) { + effects { + transactionBlock { + digest + } + status + lamportVersion + errors + dependencies { + edges { + node { + digest + bcs + } + } + } + gasEffects { + __typename + gasObject { + digest + storageRebate + bcs + } + gasSummary { + computationCost + computationCostBurned + storageCost + storageRebate + nonRefundableStorageFee + } + } + unchangedSharedObjects { + edges { + node { + __typename + } + } + } + objectChanges { + edges { + node { + idCreated + idDeleted + } + } + } + balanceChanges { + edges { + node { + amount + } + } + } + events { + edges { + node { + timestamp + } + } + } + timestamp + epoch { + referenceGasPrice + endTimestamp + totalCheckpoints + totalTransactions + totalGasFees + totalStakeRewards + fundSize + netInflow + fundInflow + fundOutflow + systemStateVersion + iotaTotalSupply + iotaTreasuryCapId + liveObjectSetDigest + } + checkpoint { + previousCheckpointDigest + networkTotalTransactions + } + bcs + } + errors + } +} +``` + +tested by [crates/iota-graphql-rpc/tests/e2e_tests.rs](../../../iota-graphql-rpc/tests/e2e_tests.rs): + +```graphql +{ + executeTransactionBlock(txBytes: $tx, signatures: $sigs) { + effects { + transactionBlock { + digest + } + } + errors + } +} +``` + +tested by [crates/iota-graphql-rpc/tests/e2e_tests.rs](../../../iota-graphql-rpc/tests/e2e_tests.rs): + +```graphql +mutation { + executeTransactionBlock(txBytes: "{}", signatures: "{}") { + effects { + status + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/address.md b/crates/iota-graphql-e2e-tests/coverage/query/address.md new file mode 100644 index 00000000000..7cc2ff3aa0e --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/address.md @@ -0,0 +1,191 @@ +Query: `address` + +```graphql +{ + address(address: "0x1") { + address + objects { + edges { + node { + digest + storageRebate + bcs + } + } + } + balance { + coinObjectCount + totalBalance + } + balances { + edges { + node { + coinObjectCount + totalBalance + } + } + } + coins { + edges { + node { + digest + storageRebate + bcs + coinBalance + } + } + } + stakedIotas { + edges { + node { + digest + storageRebate + bcs + poolId + principal + estimatedReward + } + } + } + transactionBlocks { + edges { + node { + digest + bcs + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/call/owned_objects.move](../../../iota-graphql-e2e-tests/tests/call/owned_objects.move): + +```graphql +//# run-graphql +{ + address(address: "0x42") { + objects { + edges { + node { + owner { + __typename + ... on AddressOwner { + owner { + address + } + } + } + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/transaction_block_effects/balance_changes.move](../../../iota-graphql-e2e-tests/tests/transaction_block_effects/balance_changes.move): + +```graphql +//# run-graphql +{ + address(address: "@{C}") { + transactionBlocks(last: 1) { + nodes { + effects { + balanceChanges { + pageInfo { + hasPreviousPage + hasNextPage + startCursor + endCursor + } + edges { + node { + amount + } + cursor + } + } + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/consistency/coins.move](../../../iota-graphql-e2e-tests/tests/consistency/coins.move): + +```graphql +//# run-graphql +{ + queryCoins: coins(type: "@{P0}::fake::FAKE") { + edges { + cursor + node { + owner { + ... on AddressOwner { + owner { + address + coins(type: "@{P0}::fake::FAKE") { + edges { + cursor + node { + contents { + json + } + } + } + } + } + } + } + contents { + json + } + } + } + } + addressCoinsA: address(address: "@{A}") { + coins(type: "@{P0}::fake::FAKE") { + edges { + cursor + node { + contents { + json + } + } + } + } + } + addressCoinsB: address(address: "@{B}") { + coins(type: "@{P0}::fake::FAKE") { + edges { + cursor + node { + contents { + json + } + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/consistency/staked_iota.move](../../../iota-graphql-e2e-tests/tests/consistency/staked_iota.move): + +```graphql +//# run-graphql +{ + address(address: "@{C}") { + stakedIotas { + edges { + cursor + node { + principal + } + } + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/availableRange.md b/crates/iota-graphql-e2e-tests/coverage/query/availableRange.md new file mode 100644 index 00000000000..5b76a865112 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/availableRange.md @@ -0,0 +1,43 @@ +Query: `availableRange` + +```graphql +{ + availableRange { + first { + digest + } + last { + digest + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/available_range/available_range.move](../../../iota-graphql-e2e-tests/tests/available_range/available_range.move): + +```graphql +//# run-graphql +{ + availableRange { + first { + digest + sequenceNumber + } + last { + digest + sequenceNumber + } + } + + first: checkpoint(id: { sequenceNumber: 0 } ) { + digest + sequenceNumber + } + + last: checkpoint { + digest + sequenceNumber + } +} +``` + diff --git a/crates/iota-graphql-e2e-tests/coverage/query/chainIdentifier.md b/crates/iota-graphql-e2e-tests/coverage/query/chainIdentifier.md new file mode 100644 index 00000000000..9dda9821f3e --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/chainIdentifier.md @@ -0,0 +1,16 @@ +Query: `chainIdentifier` + +```graphql +{ + chainIdentifier +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/epoch/chain_identifier.move](../../../iota-graphql-e2e-tests/tests/epoch/chain_identifier.move): + +```graphql +//# run-graphql +{ +chainIdentifier +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/checkpoint.md b/crates/iota-graphql-e2e-tests/coverage/query/checkpoint.md new file mode 100644 index 00000000000..278b5a5d8fc --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/checkpoint.md @@ -0,0 +1,69 @@ +Query: `checkpoint` + +```graphql +{ + checkpoint(id: null) { + digest + sequenceNumber + timestamp + validatorSignatures + previousCheckpointDigest + networkTotalTransactions + rollingGasSummary { + computationCost + computationCostBurned + storageCost + storageRebate + nonRefundableStorageFee + } + epoch { + referenceGasPrice + endTimestamp + totalCheckpoints + totalTransactions + totalGasFees + totalStakeRewards + fundSize + netInflow + fundInflow + fundOutflow + systemStateVersion + iotaTotalSupply + iotaTreasuryCapId + liveObjectSetDigest + } + transactionBlocks { + edges { + node { + digest + bcs + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/call/simple.move](../../../iota-graphql-e2e-tests/tests/call/simple.move): + +```graphql +//# run-graphql +{ + checkpoint { + sequenceNumber + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/transactions/at_checkpoint.move](../../../iota-graphql-e2e-tests/tests/transactions/at_checkpoint.move): + +```graphql +//# run-graphql +{ # Via a checkpoint query + c0: checkpoint(id: { sequenceNumber: 0 }) { transactionBlocks { nodes { ...Tx } } } + c1: checkpoint(id: { sequenceNumber: 1 }) { transactionBlocks { nodes { ...Tx } } } + c2: checkpoint(id: { sequenceNumber: 2 }) { transactionBlocks { nodes { ...Tx } } } + c3: checkpoint(id: { sequenceNumber: 3 }) { transactionBlocks { nodes { ...Tx } } } + c4: checkpoint(id: { sequenceNumber: 4 }) { transactionBlocks { nodes { ...Tx } } } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/checkpoints.md b/crates/iota-graphql-e2e-tests/coverage/query/checkpoints.md new file mode 100644 index 00000000000..35e1d963e78 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/checkpoints.md @@ -0,0 +1,96 @@ +Query: `checkpoints` + +```graphql +{ + checkpoints(after: null, first: null, last: null, before: null) { + edges { + node { + digest + sequenceNumber + timestamp + validatorSignatures + previousCheckpointDigest + networkTotalTransactions + rollingGasSummary { + computationCost + computationCostBurned + storageCost + storageRebate + nonRefundableStorageFee + } + epoch { + referenceGasPrice + endTimestamp + totalCheckpoints + totalTransactions + totalGasFees + totalStakeRewards + fundSize + netInflow + fundInflow + fundOutflow + systemStateVersion + iotaTotalSupply + iotaTreasuryCapId + liveObjectSetDigest + } + transactionBlocks { + edges { + node { + digest + bcs + } + } + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/limits/output_node_estimation.move](../../../iota-graphql-e2e-tests/tests/limits/output_node_estimation.move): + +```graphql +//# run-graphql --show-usage +# build on previous example with nested connection +{ + checkpoints { # 1 + nodes { # 1 + transactionBlocks { # 20 + edges { # 20 + txns: node { # 400 + digest # 400 + } + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/consistency/checkpoints/transaction_blocks.move](../../../iota-graphql-e2e-tests/tests/consistency/checkpoints/transaction_blocks.move): + +```graphql +{ + checkpoints { + nodes { + sequenceNumber + transactionBlocks(filter: { signAddress: "@{A}"}) { + edges { + cursor + node { + digest + sender { + objects(last: 1) { + edges { + cursor + } + } + } + } + } + } + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/coinMetadata.md b/crates/iota-graphql-e2e-tests/coverage/query/coinMetadata.md new file mode 100644 index 00000000000..40324539394 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/coinMetadata.md @@ -0,0 +1,45 @@ +Query: `coinMetadata` + +```graphql +{ + coinMetadata(coinType: "@{test}::fake::FAKE") { + digest + storageRebate + bcs + decimals + name + symbol + description + iconUrl + supply + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/call/coin_metadata.move](../../../iota-graphql-e2e-tests/tests/call/coin_metadata.move): + +```graphql +//# run-graphql +{ + coinMetadata(coinType: "@{test}::fake::FAKE") { + decimals + name + symbol + description + iconUrl + supply + } +} + +//# run-graphql +{ + coinMetadata(coinType: "@{test}::fake::FAKE") { + decimals + name + symbol + description + iconUrl + supply + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/coins.md b/crates/iota-graphql-e2e-tests/coverage/query/coins.md new file mode 100644 index 00000000000..c1034e2a691 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/coins.md @@ -0,0 +1,156 @@ +Query: `type` + +```graphql +{ + coins(first: null, last: null, after: null) { + edges { + node { + address + objects { + edges { + node { + digest + storageRebate + bcs + } + } + } + balance { + coinObjectCount + totalBalance + } + balances { + edges { + node { + coinObjectCount + totalBalance + } + } + } + coins { + edges { + node { + digest + storageRebate + bcs + coinBalance + } + } + } + stakedIotas { + edges { + node { + digest + storageRebate + bcs + poolId + principal + estimatedReward + } + } + } + version + status + digest + owner { + __typename + } + previousTransactionBlock { + digest + bcs + } + storageRebate + receivedTransactionBlocks { + edges { + node { + digest + bcs + } + } + } + bcs + contents { + __typename + data + } + display { + value + error + } + dynamicField( + name: {type: "0x0000000000000000000000000000000000000000000000000000000000000001::string::String", bcs: "A2RmNQ=="} + ) { + __typename + } + dynamicObjectField( + name: {type: "0x0000000000000000000000000000000000000000000000000000000000000001::string::String", bcs: "A2RmNQ=="} + ) { + __typename + } + dynamicFields { + edges { + node { + __typename + } + } + } + coinBalance + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/objects/coin.move](../../../iota-graphql-e2e-tests/tests/objects/coin.move): + +```graphql +//# run-graphql +fragment C on Coin { + coinBalance + contents { type { repr } } +} + +{ + iotaCoins: coins { + edges { + cursor + node { ...C } + } + } + + fakeCoins: coins(type: "@{P0}::fake::FAKE") { + edges { + cursor + node { ...C } + } + } + + address(address: "@{A}") { + coins { + edges { + cursor + node { ...C } + } + } + + allBalances: balances { + edges { + cursor + node { + coinType { repr } + coinObjectCount + totalBalance + } + } + } + + firstBalance: balances(first: 1) { + edges { cursor } + } + + lastBalance: balances(last: 1) { + edges { cursor } + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/dryRunTransactionBlock.md b/crates/iota-graphql-e2e-tests/coverage/query/dryRunTransactionBlock.md new file mode 100644 index 00000000000..c02bea1a742 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/dryRunTransactionBlock.md @@ -0,0 +1,90 @@ +Query: `dryRunTransactionBlock` + +```graphql +{ + dryRunTransactionBlock( + txBytes: "AAIAIC3Pg7fIBNN95RZluYu1Ll8icKxoO/oGYoEAfLP0szGAAAjoAwAAAAAAAAICAAEBAQABAQIAAAEAAA==" + txMeta: {} + ) { + transaction { + digest + sender { + address + } + gasInput { + gasSponsor { + address + } + gasPayment { + edges { + node { + digest + storageRebate + bcs + } + } + } + gasPrice + gasBudget + } + } + error + results { + mutatedReferences { + input { + __typename + ... on Input { + ix + } + ... on Result { + cmd + ix + } + } + type { + repr + } + bcs + } + returnValues { + type { + repr + signature + layout + abilities + } + bcs + } + } + } +} +``` + +tested by [crates/iota-graphql-rpc/tests/e2e_tests.rs](../../../iota-graphql-rpc/tests/e2e_tests.rs): + +```graphql +{ + dryRunTransactionBlock(txBytes: $tx, txMeta: {}) { + results { + mutatedReferences { + input { + __typename + } + } + } + transaction { + digest + sender { + address + } + gasInput { + gasSponsor { + address + } + gasPrice + } + } + error + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/epoch.md b/crates/iota-graphql-e2e-tests/coverage/query/epoch.md new file mode 100644 index 00000000000..cd5f8245498 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/epoch.md @@ -0,0 +1,107 @@ +Query: `epoch` + +```graphql +{ + epoch(id: 1) { + epochId + referenceGasPrice + validatorSet { + totalStake + pendingActiveValidatorsId + pendingActiveValidatorsSize + stakingPoolMappingsId + stakingPoolMappingsSize + inactivePoolsId + inactivePoolsSize + validatorCandidatesId + validatorCandidatesSize + } + startTimestamp + endTimestamp + totalCheckpoints + totalTransactions + totalGasFees + totalStakeRewards + fundSize + netInflow + fundInflow + fundOutflow + protocolConfigs { + __typename + } + systemStateVersion + iotaTotalSupply + iotaTreasuryCapId + liveObjectSetDigest + checkpoints { + edges { + node { + previousCheckpointDigest + networkTotalTransactions + } + } + } + transactionBlocks { + edges { + node { + digest + bcs + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/validator/validator.move](../../../iota-graphql-e2e-tests/tests/validator/validator.move): + +```graphql +{ + epoch(id: 1) { + validatorSet { + activeValidators { + nodes { + name + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/consistency/epochs/checkpoints.move](../../../iota-graphql-e2e-tests/tests/consistency/epochs/checkpoints.move): + +```graphql +//# run-graphql --cursors {"s":3,"c":4} {"s":7,"c":8} {"s":9,"c":10} +# View checkpoints before the last checkpoint in each epoch, from the perspective of the first +# checkpoint in the next epoch. +{ + checkpoint { + sequenceNumber + } + epoch_0: epoch(id: 0) { + epochId + checkpoints(before: "@{cursor_0}") { + nodes { + sequenceNumber + } + } + } + epoch_1: epoch(id: 1) { + epochId + checkpoints(before: "@{cursor_1}") { + nodes { + sequenceNumber + } + } + } + epoch_2: epoch(id: 2) { + epochId + checkpoints(before: "@{cursor_2}") { + nodes { + sequenceNumber + } + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/events.md b/crates/iota-graphql-e2e-tests/coverage/query/events.md new file mode 100644 index 00000000000..ea0100eb520 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/events.md @@ -0,0 +1,49 @@ +Query: `events` + +```graphql +{ + events(first: null, last: null, after: null, before: null, filter: null) { + edges { + node { + __typename + data + timestamp + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/event_connection/no_filter.move](../../../iota-graphql-e2e-tests/tests/event_connection/no_filter.move): + +```graphql +//# run-graphql +{ + events { + pageInfo { + hasPreviousPage + hasNextPage + startCursor + endCursor + } + nodes { + json + } + } +} + +//# run-graphql --cursors {"tx":2,"e":19,"c":1} +{ + events(after: "@{cursor_0}") { + pageInfo { + hasPreviousPage + hasNextPage + startCursor + endCursor + } + nodes { + json + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/latestPackage.md b/crates/iota-graphql-e2e-tests/coverage/query/latestPackage.md new file mode 100644 index 00000000000..f6ccf36ae32 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/latestPackage.md @@ -0,0 +1,232 @@ +Query: `latestPackage` + +```graphql +{ + latestPackage(address: "0x1") { + address + objects { + edges { + node { + digest + storageRebate + bcs + } + } + } + balance { + coinObjectCount + totalBalance + } + balances { + edges { + node { + coinObjectCount + totalBalance + } + } + } + coins { + edges { + node { + digest + storageRebate + bcs + coinBalance + } + } + } + stakedIotas { + edges { + node { + digest + storageRebate + bcs + poolId + principal + estimatedReward + } + } + } + version + status + digest + owner { + __typename + } + previousTransactionBlock { + digest + bcs + } + storageRebate + receivedTransactionBlocks { + edges { + node { + digest + bcs + } + } + } + bcs + packageVersions { + edges { + node { + digest + storageRebate + bcs + moduleBcs + } + } + } + latestPackage { + digest + storageRebate + bcs + moduleBcs + } + module(name: "address") { + bytes + disassembly + } + modules { + edges { + node { + name + package { + digest + storageRebate + bcs + moduleBcs + } + datatype(name: "Char") { + abilities + asMoveEnum { + abilities + name + variants { + name + __typename + } + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + asMoveStruct { + abilities + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + datatypes { + edges { + node { + abilities + asMoveEnum { + abilities + name + variants { + name + __typename + } + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + asMoveStruct { + abilities + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + } + } + __typename + fileFormatVersion + bytes + disassembly + } + } + } + linkage { + version + __typename + } + typeOrigins { + __typename + } + moduleBcs + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/packages/versioning.move](../../../iota-graphql-e2e-tests/tests/packages/versioning.move): + +```graphql +//# run-graphql +{ + latestPackage(address: "@{P0}") { + version + module(name: "m") { + functions { nodes { name } } + } + + packageVersions { + nodes { + address + version + } + } + } + + firstPackage: package(address: "@{P0}", version: 1) { + address + version + module(name: "m") { + functions { nodes { name } } + } + + packageVersions { + nodes { + address + version + } + } + } + + packages(first: 10) { + nodes { + address + version + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/object.md b/crates/iota-graphql-e2e-tests/coverage/query/object.md new file mode 100644 index 00000000000..62b2c246845 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/object.md @@ -0,0 +1,165 @@ +Query: `object` + +```graphql +{ + object(address: "0x1") { + address + objects { + edges { + node { + digest + } + } + } + balance { + coinType { + repr + signature + layout + abilities + } + coinObjectCount + totalBalance + } + balances { + edges { + node { + coinObjectCount + } + } + } + coins { + edges { + node { + digest + } + } + } + stakedIotas { + edges { + node { + digest + } + } + } + version + status + digest + owner { + __typename + } + previousTransactionBlock { + digest + bcs + } + storageRebate + receivedTransactionBlocks { + edges { + node { + digest + bcs + } + } + } + bcs + dynamicField( + name: {type: "0x0000000000000000000000000000000000000000000000000000000000000001::string::String", bcs: "A2RmMQ=="} + ) { + __typename + } + dynamicObjectField( + name: {type: "0x0000000000000000000000000000000000000000000000000000000000000001::string::String", bcs: "A2RmNQ=="} + ) { + name { + bcs + } + } + dynamicFields { + edges { + node { + name { + __typename + } + } + } + } + asMoveObject { + digest + } + asMovePackage { + digest + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/call/owned_objects.move](../../../iota-graphql-e2e-tests/tests/call/owned_objects.move): + +```graphql +//# run-graphql +{ + object(address: "0x42") { + objects { + edges { + node { + owner { + __typename + ... on AddressOwner { + owner { + address + } + } + } + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/transactions/random.move](../../../iota-graphql-e2e-tests/tests/transactions/random.move): + +```graphql +//# run-graphql +{ + object(address: "0x8") { + address + version + asMoveObject { + contents { + type { repr } + json + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/call/dynamic_fields.move](../../../iota-graphql-e2e-tests/tests/call/dynamic_fields.move): + +```graphql +//# run-graphql +{ + object(address: "@{obj_2_0}") { + dynamicFields { + nodes { + name { + type { + repr + } + data + bcs + } + value { + ... on MoveObject { + __typename + } + ... on MoveValue { + __typename + } + } + } + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/objects.md b/crates/iota-graphql-e2e-tests/coverage/query/objects.md new file mode 100644 index 00000000000..b48d531f62a --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/objects.md @@ -0,0 +1,187 @@ +Query: `objects` + +```graphql +{ + objects(first: null, last: null, after: null, filter: null) { + edges { + node { + address + objects { + edges { + node { + digest + } + } + } + balance { + coinType { + repr + signature + layout + abilities + } + coinObjectCount + totalBalance + } + balances { + edges { + node { + coinObjectCount + } + } + } + coins { + edges { + node { + digest + } + } + } + stakedIotas { + edges { + node { + digest + } + } + } + version + status + digest + owner { + __typename + } + previousTransactionBlock { + digest + bcs + } + storageRebate + receivedTransactionBlocks { + edges { + node { + digest + bcs + } + } + } + bcs + dynamicField( + name: {type: "0x0000000000000000000000000000000000000000000000000000000000000001::string::String", bcs: "A2RmMQ=="} + ) { + __typename + } + dynamicObjectField( + name: {type: "0x0000000000000000000000000000000000000000000000000000000000000001::string::String", bcs: "A2RmNQ=="} + ) { + name { + bcs + } + } + dynamicFields { + edges { + node { + name { + __typename + } + } + } + } + asMoveObject { + digest + } + asMovePackage { + digest + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/consistency/performance/many_objects.move](../../../iota-graphql-e2e-tests/tests/consistency/performance/many_objects.move): + +```graphql +//# run-graphql +{ + last_2: objects(last: 2, filter: {type: "@{Test}"}) { + nodes { + version + asMoveObject { + owner { + ... on AddressOwner { + owner { + address + } + } + } + contents { + json + type { + repr + } + } + } + } + } + last_4_objs_owned_by_A: address(address: "@{A}") { + objects(last: 4) { + nodes { + owner { + ... on AddressOwner { + owner { + address + } + } + } + contents { + json + type { + repr + } + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/consistency/objects_pagination.move](../../../iota-graphql-e2e-tests/tests/consistency/objects_pagination.move): + +```graphql +//# run-graphql --cursors @{obj_6_0,2} +{ + before_obj_6_0_at_checkpoint_2: objects(filter: {type: "@{Test}"}, before: "@{cursor_0}") { + nodes { + version + asMoveObject { + contents { + type { + repr + } + json + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/coverage/query/objects.md](../../../iota-graphql-e2e-tests/coverage/query/objects.md): + +```graphql +//# run-graphql +{ + objects(filter: {type: "0x2::coin"}) { + edges { + node { + asMoveObject { + contents { + type { + repr + } + } + } + } + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/owner.md b/crates/iota-graphql-e2e-tests/coverage/query/owner.md new file mode 100644 index 00000000000..4c7236775b3 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/owner.md @@ -0,0 +1,156 @@ +Query: `owner` + +```graphql +{ + owner(address: "0x1", rootVersion: null) { + address + objects { + edges { + node { + address + } + } + } + balance { + coinType { + repr + signature + layout + abilities + } + coinObjectCount + totalBalance + } + coins { + edges { + node { + balance { + coinObjectCount + totalBalance + } + } + } + } + stakedIotas { + edges { + node { + digest + } + } + } + asAddress { + address + } + asObject { + digest + } + dynamicField( + name: {type: "0x0000000000000000000000000000000000000000000000000000000000000001::string::String", bcs: "A2RmNQ=="} + ) { + __typename + } + dynamicObjectField( + name: {type: "0x0000000000000000000000000000000000000000000000000000000000000001::string::String", bcs: "A2RmNQ=="} + ) { + __typename + } + dynamicFields { + edges { + node { + __typename + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/call/owned_objects.move](../../../iota-graphql-e2e-tests/tests/call/owned_objects.move): + +```graphql +//# run-graphql +{ + owner(address: "0x42") { + objects { + edges { + node { + owner { + __typename + ... on AddressOwner { + owner { + address + } + } + } + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/call/dynamic_fields.move](../../../iota-graphql-e2e-tests/tests/call/dynamic_fields.move): + +```graphql +//# run-graphql +{ + owner(address: "@{obj_2_0}") { + dynamicFields { + nodes { + name { + type { + repr + } + data + bcs + } + value { + ... on MoveObject { + __typename + } + ... on MoveValue { + bcs + data + __typename + } + } + } + } + } +} + +//# run-graphql +{ + owner(address: "@{obj_2_0}") { + dynamicField(name: {type: "u64", bcs: "AAAAAAAAAAA="}) { + name { + type { + repr + } + data + bcs + } + value { + ... on MoveValue { + __typename + bcs + data + } + } + } + } +} + +//# run-graphql +{ + owner(address: "@{obj_2_0}") { + dynamicObjectField(name: {type: "u64", bcs: "AAAAAAAAAAA="}) { + value { + ... on MoveObject { + __typename + } + } + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/package.md b/crates/iota-graphql-e2e-tests/coverage/query/package.md new file mode 100644 index 00000000000..00d014d1da7 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/package.md @@ -0,0 +1,232 @@ +Query: `package` + +```graphql +{ + package(address: "0x1") { + address + objects { + edges { + node { + digest + storageRebate + bcs + } + } + } + balance { + coinObjectCount + totalBalance + } + balances { + edges { + node { + coinObjectCount + totalBalance + } + } + } + coins { + edges { + node { + digest + storageRebate + bcs + coinBalance + } + } + } + stakedIotas { + edges { + node { + digest + storageRebate + bcs + poolId + principal + estimatedReward + } + } + } + version + status + digest + owner { + __typename + } + previousTransactionBlock { + digest + bcs + } + storageRebate + receivedTransactionBlocks { + edges { + node { + digest + bcs + } + } + } + bcs + packageVersions { + edges { + node { + digest + storageRebate + bcs + moduleBcs + } + } + } + latestPackage { + digest + storageRebate + bcs + moduleBcs + } + module(name: "address") { + bytes + disassembly + } + modules { + edges { + node { + name + package { + digest + storageRebate + bcs + moduleBcs + } + datatype(name: "Char") { + abilities + asMoveEnum { + abilities + name + variants { + name + __typename + } + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + asMoveStruct { + abilities + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + datatypes { + edges { + node { + abilities + asMoveEnum { + abilities + name + variants { + name + __typename + } + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + asMoveStruct { + abilities + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + } + } + __typename + fileFormatVersion + bytes + disassembly + } + } + } + linkage { + version + __typename + } + typeOrigins { + __typename + } + moduleBcs + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/packages/versioning.move](../../../iota-graphql-e2e-tests/tests/packages/versioning.move): + +```graphql +//# run-graphql +{ + latestPackage(address: "@{P0}") { + version + module(name: "m") { + functions { nodes { name } } + } + + packageVersions { + nodes { + address + version + } + } + } + + firstPackage: package(address: "@{P0}", version: 1) { + address + version + module(name: "m") { + functions { nodes { name } } + } + + packageVersions { + nodes { + address + version + } + } + } + + packages(first: 10) { + nodes { + address + version + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/packages.md b/crates/iota-graphql-e2e-tests/coverage/query/packages.md new file mode 100644 index 00000000000..04d1dfbf6df --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/packages.md @@ -0,0 +1,230 @@ +Query: `package` + +```graphql +{ + packages(first: null, last: 5, after: null, filter: null) { + edges { + node { + address + objects { + edges { + node { + digest + storageRebate + bcs + } + } + } + balance { + coinObjectCount + totalBalance + } + balances { + edges { + node { + coinObjectCount + totalBalance + } + } + } + coins { + edges { + node { + digest + storageRebate + bcs + coinBalance + } + } + } + stakedIotas { + edges { + node { + digest + storageRebate + bcs + poolId + principal + estimatedReward + } + } + } + version + status + digest + owner { + __typename + } + previousTransactionBlock { + digest + bcs + } + storageRebate + receivedTransactionBlocks { + edges { + node { + digest + bcs + } + } + } + bcs + packageVersions { + edges { + node { + digest + storageRebate + bcs + moduleBcs + } + } + } + latestPackage { + digest + storageRebate + bcs + moduleBcs + } + module(name: "address") { + bytes + disassembly + } + modules { + edges { + node { + name + package { + digest + storageRebate + bcs + moduleBcs + } + datatype(name: "Char") { + abilities + asMoveEnum { + abilities + name + variants { + name + __typename + } + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + asMoveStruct { + abilities + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + datatypes { + edges { + node { + abilities + asMoveEnum { + abilities + name + variants { + name + __typename + } + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + asMoveStruct { + abilities + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + name + __typename + typeParameters { + isPhantom + __typename + constraints + } + } + } + } + __typename + fileFormatVersion + bytes + disassembly + } + } + } + linkage { + version + __typename + } + typeOrigins { + __typename + } + moduleBcs + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/packages/versioning.move](../../../iota-graphql-e2e-tests/tests/packages/versioning.move): + +```graphql +//# run-graphql +{ # Querying packages with checkpoint bounds + before: packages(first: 10, filter: { beforeCheckpoint: 1 }) { + nodes { + address + version + previousTransactionBlock { + effects { checkpoint { sequenceNumber } } + } + } + } + + after: packages(first: 10, filter: { afterCheckpoint: 1 }) { + nodes { + address + version + previousTransactionBlock { + effects { checkpoint { sequenceNumber } } + } + } + } + + between: packages(first: 10, filter: { afterCheckpoint: 1, beforeCheckpoint: 3 }) { + nodes { + address + version + previousTransactionBlock { + effects { checkpoint { sequenceNumber } } + } + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/protocolConfig.md b/crates/iota-graphql-e2e-tests/coverage/query/protocolConfig.md new file mode 100644 index 00000000000..876ae677796 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/protocolConfig.md @@ -0,0 +1,59 @@ +Query: `protocolConfig` + +```graphql +{ + protocolConfig(protocolVersion: 1) { + protocolVersion + featureFlags { + key + value + __typename + } + configs { + key + value + __typename + } + config(key: "address_from_bytes_cost_base") { + key + value + __typename + } + featureFlag(key: "bridge") { + key + value + __typename + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/epoch/protocol_configs.move](../../../iota-graphql-e2e-tests/tests/epoch/protocol_configs.move): + +```graphql +//# run-graphql +{ + protocolConfig { + protocolVersion + config(key: "max_move_identifier_len") { + value + } + featureFlag(key: "bridge") { + value + } + } +} + +//# run-graphql +{ + protocolConfig(protocolVersion: 1) { + protocolVersion + config(key: "max_move_identifier_len") { + value + } + featureFlag(key: "bridge") { + value + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/serviceConfig.md b/crates/iota-graphql-e2e-tests/coverage/query/serviceConfig.md new file mode 100644 index 00000000000..97960565217 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/serviceConfig.md @@ -0,0 +1,37 @@ +Query: `serviceConfig` + +```graphql +{ + serviceConfig { + isEnabled(feature:COINS) + availableVersions + enabledFeatures + maxQueryDepth + maxQueryNodes + maxOutputNodes + maxDbQueryCost + defaultPageSize + maxPageSize + mutationTimeoutMs + requestTimeoutMs + maxQueryPayloadSize + maxTypeArgumentDepth + maxTypeArgumentWidth + maxTypeNodes + maxMoveValueDepth + maxTransactionIds + maxScanLimit + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/call/simple.move](../../../iota-graphql-e2e-tests/tests/call/simple.move): + +```graphql +//# run-graphql +{ + serviceConfig { + availableVersions + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/transactionBlock.md b/crates/iota-graphql-e2e-tests/coverage/query/transactionBlock.md new file mode 100644 index 00000000000..1273c8687c8 --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/transactionBlock.md @@ -0,0 +1,74 @@ +Query: `transactionBlock` + +```graphql +{ + transactionBlock(digest: "63X49x2QuuYNduExZWoJjfXut3s3WDWZ7Tr7nXJu32ZT") { + digest + sender { + address + balance { + coinObjectCount + totalBalance + } + balances { + edges { + node { + coinObjectCount + totalBalance + } + } + } + stakedIotas { + edges { + node { + digest + storageRebate + bcs + poolId + principal + estimatedReward + } + } + } + transactionBlocks { + edges { + node { + digest + bcs + } + } + } + } + gasInput { + gasPrice + gasBudget + } + kind { + __typename + } + signatures + effects { + status + errors + timestamp + } + expiration { + referenceGasPrice + endTimestamp + totalCheckpoints + totalTransactions + totalGasFees + totalStakeRewards + fundSize + netInflow + fundInflow + fundOutflow + systemStateVersion + iotaTotalSupply + iotaTreasuryCapId + liveObjectSetDigest + } + bcs + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/transactionBlocks.md b/crates/iota-graphql-e2e-tests/coverage/query/transactionBlocks.md new file mode 100644 index 00000000000..3fff42b23aa --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/transactionBlocks.md @@ -0,0 +1,175 @@ +Query: `transactionBlocks` + +```graphql +{ + transactionBlocks(first: null, last: null, after: null, scanLimit: null) { + edges { + node { + digest + sender { + address + balance { + coinObjectCount + totalBalance + } + balances { + edges { + node { + coinObjectCount + totalBalance + } + } + } + stakedIotas { + edges { + node { + digest + storageRebate + bcs + poolId + principal + estimatedReward + } + } + } + transactionBlocks { + edges { + node { + digest + bcs + } + } + } + } + gasInput { + gasPrice + gasBudget + } + kind { + __typename + } + signatures + effects { + status + errors + timestamp + } + expiration { + referenceGasPrice + endTimestamp + totalCheckpoints + totalTransactions + totalGasFees + totalStakeRewards + fundSize + netInflow + fundInflow + fundOutflow + systemStateVersion + iotaTotalSupply + iotaTreasuryCapId + liveObjectSetDigest + } + bcs + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/consistency/balances.move](../../../iota-graphql-e2e-tests/tests/consistency/balances.move): + +```graphql +//# run-graphql --cursors {"c":2,"t":1,"i":false} +# Emulating viewing transaction blocks at checkpoint 2. Fake coin balance should be 700. +{ + transactionBlocks(first: 1, after: "@{cursor_0}", filter: {signAddress: "@{A}"}) { + nodes { + sender { + fakeCoinBalance: balance(type: "@{P0}::fake::FAKE") { + totalBalance + } + allBalances: balances { + nodes { + coinType { + repr + } + coinObjectCount + totalBalance + } + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/transaction_block_effects/object_changes.move](../../../iota-graphql-e2e-tests/tests/transaction_block_effects/object_changes.move): + +```graphql +//# run-graphql +{ + transactionBlocks(first: 1) { + nodes { + effects { + objectChanges { + pageInfo { + hasPreviousPage + hasNextPage + startCursor + endCursor + } + edges { + cursor + } + } + } + } + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/tests/consistency/epochs/transaction_blocks.move](../../../iota-graphql-e2e-tests/tests/consistency/epochs/transaction_blocks.move): + +```graphql +//# run-graphql --cursors {"t":5,"i":false,"c":6} +# Verify that with a cursor, we are locked into a view as if we were at the checkpoint stored in +# the cursor. Compare against `without_cursor`, which should show the latest state at the actual +# latest checkpoint. There should only be 1 transaction block in the `with_cursor` query, but +# multiple in the second +{ + checkpoint { + sequenceNumber + } + with_cursor: transactionBlocks(after: "@{cursor_0}", filter: {signAddress: "@{A}"}) { + edges { + cursor + node { + digest + sender { + objects { + edges { + cursor + } + } + } + } + } + } + without_cursor: transactionBlocks(filter: {signAddress: "@{A}"}) { + edges { + cursor + node { + digest + sender { + objects { + edges { + cursor + } + } + } + } + } + } +} +``` diff --git a/crates/iota-graphql-e2e-tests/coverage/query/type.md b/crates/iota-graphql-e2e-tests/coverage/query/type.md new file mode 100644 index 00000000000..72155a597bf --- /dev/null +++ b/crates/iota-graphql-e2e-tests/coverage/query/type.md @@ -0,0 +1,28 @@ +Query: `type` + +```graphql +{ + type(type: "vector<u64>") { + repr + signature + layout + abilities + __typename + } +} +``` + +tested by [crates/iota-graphql-e2e-tests/coverage/query/type.md](../../../iota-graphql-e2e-tests/coverage/query/type.md): + +```graphql +//# run-graphql +# Happy path -- primitive type with generic parameter + +{ + type(type: "vector<u64>") { + repr + signature + layout + } +} +``` diff --git a/crates/iota-graphql-rpc/README.md b/crates/iota-graphql-rpc/README.md index 55ee84500fb..c7dadc63929 100644 --- a/crates/iota-graphql-rpc/README.md +++ b/crates/iota-graphql-rpc/README.md @@ -125,6 +125,9 @@ To run it with the `iota start` subcommand, switch to the root directory of the ## Running tests +The crate provides test coverage for server functionality, covering client validation, query validation, reading and writing data, query limits, and health checks. +For query tests, please see the `iota-graphql-e2e-tests` crate. + To run the tests, a running postgres database is required. To do so, follow the [Indexer database setup](../iota-indexer/README.md#database-setup) to set up a database. @@ -136,3 +139,11 @@ cargo nextest run -p iota-graphql-rpc --features pg_integration --no-fail-fast - To check for compatibility with json-rpc `pnpm --filter @iota/graphql-transport test:e2e` + +## To re-generate the GraphQL schema after code changes + +In order to re-generate the GraphQL schema ([schema.graphql](schema.graphql)), run the following command: + +```sh +cargo run --bin iota-graphql-rpc generate-schema +``` From f9aa341004b77253800f64e5a4debcb4fc2f8b83 Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Thu, 28 Nov 2024 13:10:27 +0100 Subject: [PATCH 12/36] feat(CI): add Move IDE Tests workflow (#4226) * feat(CI): add Move IDE Tests workflow * don't run move-ide-test if draft * Address review comments * Run on any change in external crates, fix test command * Rename diff output to isExternalCrates --- .github/actions/diffs/action.yml | 5 + .github/workflows/_move_ide.yml | 96 +++++++++++++++++++ .github/workflows/hierarchy.yml | 10 ++ .../editors/code/scripts/create.sh | 23 +++-- 4 files changed, 122 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/_move_ide.yml diff --git a/.github/actions/diffs/action.yml b/.github/actions/diffs/action.yml index 4e6922ba60f..ac54e779fdd 100644 --- a/.github/actions/diffs/action.yml +++ b/.github/actions/diffs/action.yml @@ -10,6 +10,9 @@ outputs: isMove: description: True when changes happened to the Move code value: "${{ steps.diff.outputs.isMove }}" + isExternalCrates: + description: True when changes happened in external crates + value: "${{ steps.diff.outputs.isExternalCrates }}" isReleaseNotesEligible: description: True when changes happened in Release Notes eligible paths value: "${{ steps.diff.outputs.isReleaseNotesEligible }}" @@ -56,6 +59,8 @@ runs: - "examples/**" - "iota_programmability/**" - ".github/workflows/_move_tests.yml" + isExternalCrates: + - "external-crates/move/crates/**" isReleaseNotesEligible: - "consensus/**" - "crates/**" diff --git a/.github/workflows/_move_ide.yml b/.github/workflows/_move_ide.yml new file mode 100644 index 00000000000..5878489c9aa --- /dev/null +++ b/.github/workflows/_move_ide.yml @@ -0,0 +1,96 @@ +name: Move IDE + +on: workflow_call + +concurrency: + group: move-ide-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + move-auto-formatter-test: + name: Move Auto-formatter Test + runs-on: [self-hosted] + + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1 + with: + ref: ${{ github.event.inputs.iota_repo_ref || github.ref }} + + - name: Setup Node + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + with: + node-version: "20" + + - name: Install dependencies + working-directory: ./external-crates/move/crates/move-analyzer/prettier-plugin + run: npm install && npm i web-tree-sitter + + - name: Run npm test + working-directory: ./external-crates/move/crates/move-analyzer/prettier-plugin + shell: bash + run: npm run test + + move-ide-test: + name: Move IDE Test + runs-on: [self-hosted] + + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1 + with: + ref: ${{ github.event.inputs.iota_repo_ref || github.ref }} + + - name: Setup Node + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + with: + node-version: "20" + + - name: Install dependencies and start Xvfb (emulate a display so VS Code can be started) + working-directory: ./external-crates/move/crates/move-analyzer/editors/code + run: | + sudo apt install libgtk-3-0 -y + sudo apt-get install -y xvfb x11-apps x11-xkb-utils libx11-6 libx11-xcb1 + set -eux + # Start server + /usr/bin/Xvfb :99 -screen 0 1024x768x24 & + sleep 1 + ps aux | grep Xvfb --color=always | grep -v grep + sudo add-apt-repository ppa:kisak/kisak-mesa -y + sudo apt update + sudo apt upgrade -y + npm install && npm install --save-dev @types/node @types/semver + + - name: Build move-analyzer + run: | + cargo build --bin move-analyzer + mkdir -p ~/.iota/bin + cp ./target/debug/move-analyzer* ~/.iota/bin + + - name: Run npm test + working-directory: ./external-crates/move/crates/move-analyzer/editors/code + shell: bash + run: npm run pretest && DISPLAY=:99.0 npm run test + + move-vscode-extension-build: + name: Move VSCode extension build + runs-on: [self-hosted] + + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1 + with: + ref: ${{ github.event.inputs.iota_repo_ref || github.ref }} + + - name: Setup Node + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + with: + node-version: "20" + + - name: Install dependencies + working-directory: ./external-crates/move/crates/move-analyzer/editors/code + run: npm install && npm install --save-dev @types/node @types/semver + + - name: Build VSCode extension + working-directory: ./external-crates/move/crates/move-analyzer/editors/code + run: npm run package diff --git a/.github/workflows/hierarchy.yml b/.github/workflows/hierarchy.yml index 88862232da1..6456b3e033a 100644 --- a/.github/workflows/hierarchy.yml +++ b/.github/workflows/hierarchy.yml @@ -22,6 +22,7 @@ jobs: isMove: ${{ steps.diff.outputs.isMove }} isDoc: ${{ steps.diff.outputs.isDoc }} isReleaseNotesEligible: ${{ steps.diff.outputs.isReleaseNotesEligible }} + isExternalCrates: ${{ steps.diff.outputs.isExternalCrates }} isWallet: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), 'iota-wallet')) }} isExplorer: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), 'iota-explorer')) }} isTypescriptSDK: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), '@iota/iota-sdk')) }} @@ -148,3 +149,12 @@ jobs: - typos uses: ./.github/workflows/_ledgernano.yml secrets: inherit + + move-ide: + if: (!cancelled() && !failure()) && needs.diff.outputs.isExternalCrates == 'true' && github.event.pull_request.draft == false + needs: + - diff + - dprint-format + - license-check + - typos + uses: ./.github/workflows/_move_ide.yml diff --git a/external-crates/move/crates/move-analyzer/editors/code/scripts/create.sh b/external-crates/move/crates/move-analyzer/editors/code/scripts/create.sh index a63c8adc9fa..f94940ab8fa 100755 --- a/external-crates/move/crates/move-analyzer/editors/code/scripts/create.sh +++ b/external-crates/move/crates/move-analyzer/editors/code/scripts/create.sh @@ -43,9 +43,8 @@ do fi done -# these will have to change if we want a different network/version -NETWORK="alphanet" -VERSION="0.4.0" +# these will have to change if we want a different version +VERSION="0.7.2-rc" # a map from os version identifiers in Iota's binary distribution to os version identifiers # representing VSCode's target platforms used for creating platform-specific plugin distributions @@ -55,7 +54,7 @@ SUPPORTED_OS[macos-arm64]=darwin-arm64 SUPPORTED_OS[linux-x86_64]=linux-x64 #SUPPORTED_OS[windows-x86_64]=win32-x64 -TMP_DIR=$( mktemp -d -t vscode-create ) +TMP_DIR=$( mktemp -d -t vscode-createXXX ) trap "clean_tmp_dir $TMP_DIR" EXIT LANG_SERVER_DIR="language-server" @@ -64,21 +63,21 @@ rm -rf $LANG_SERVER_DIR mkdir $LANG_SERVER_DIR for DIST_OS VSCODE_OS in "${(@kv)SUPPORTED_OS}"; do - # Iota distribution identifier - IOTA_DISTRO=$NETWORK"-v"$VERSION - # name of the Iota distribution archive file, for example iota-testnet-v1.0.0-macos-arm64.tgz - IOTA_ARCHIVE="iota-"$IOTA_DISTRO"-"$DIST_OS".tgz" + # IOTA distribution identifier + IOTA_VERSION="v"$VERSION + # name of the Iota distribution archive file, for example iota-v1.0.0-macos-arm64.tgz + IOTA_ARCHIVE="iota-"$IOTA_VERSION"-"$DIST_OS".tgz" # a path to downloaded Iota archive IOTA_ARCHIVE_PATH=$TMP_DIR"/"$IOTA_ARCHIVE - # download Iota archive file to a given location and uncompress it - curl https://github.com/iotaledger/iota/releases/download/"$IOTA_DISTRO"/"$IOTA_ARCHIVE" -L -o $IOTA_ARCHIVE_PATH + # download IOTA archive file to a given location and uncompress it + curl https://github.com/iotaledger/iota/releases/download/"$IOTA_VERSION"/"$IOTA_ARCHIVE" -L -o $IOTA_ARCHIVE_PATH tar -xf $IOTA_ARCHIVE_PATH --directory $TMP_DIR # names of the move-analyzer binary, both the one becoming part of the extension ($SERVER_BIN) # and the one in the Iota archive ($ARCHIVE_SERVER_BIN) SERVER_BIN="move-analyzer" - ARCHIVE_SERVER_BIN=$SERVER_BIN"-"$DIST_OS + ARCHIVE_SERVER_BIN=$SERVER_BIN if [[ "$DIST_OS" == *"windows"* ]]; then SERVER_BIN="$SERVER_BIN".exe ARCHIVE_SERVER_BIN="$ARCHIVE_SERVER_BIN".exe @@ -86,7 +85,7 @@ for DIST_OS VSCODE_OS in "${(@kv)SUPPORTED_OS}"; do # copy move-analyzer binary to the appropriate location where it's picked up when bundling the # extension - SRC_SERVER_BIN_LOC=$TMP_DIR"/external-crates/move/target/release/"$ARCHIVE_SERVER_BIN + SRC_SERVER_BIN_LOC=$TMP_DIR"/"$ARCHIVE_SERVER_BIN DST_SERVER_BIN_LOC=$LANG_SERVER_DIR"/"$SERVER_BIN cp $SRC_SERVER_BIN_LOC $DST_SERVER_BIN_LOC From 3ff8bf8927182923f01b239d2ced84280f48bb3a Mon Sep 17 00:00:00 2001 From: Samuel Rufinatscha <samuel.rufinatscha@iota.org> Date: Thu, 28 Nov 2024 14:33:46 +0100 Subject: [PATCH 13/36] [iota-faucet] Enable the use of batched mode on faucet (#4110) * fix: Pass at least one coin to the faucet batch queue * fix: Clippy * fix: Rework split point * fix: Enable `batch_enabled` flag for existing batch tests * fix: Add test_faucet_batch_concurrent_requests test * fix: Fix comment * fix: Remove wrong comment --- .../iota-faucet/src/faucet/simple_faucet.rs | 36 ++- crates/iota/tests/cli_tests.rs | 270 +++++++++++++++++- 2 files changed, 293 insertions(+), 13 deletions(-) diff --git a/crates/iota-faucet/src/faucet/simple_faucet.rs b/crates/iota-faucet/src/faucet/simple_faucet.rs index 1a168c35c48..eafb50d4a4a 100644 --- a/crates/iota-faucet/src/faucet/simple_faucet.rs +++ b/crates/iota-faucet/src/faucet/simple_faucet.rs @@ -119,6 +119,11 @@ impl SimpleFaucet { .map(|q| GasCoin::try_from(&q.1).unwrap()) .filter(|coin| coin.0.balance.value() >= (config.amount * config.num_coins as u64)) .collect::<Vec<GasCoin>>(); + + if coins.is_empty() { + return Err(FaucetError::NoGasCoinAvailable); + } + let metrics = FaucetMetrics::new(prometheus_registry); let wal = WriteAheadLog::open(wal_path); @@ -131,16 +136,19 @@ impl SimpleFaucet { config.max_request_queue_length as usize, ); - // This is to handle the case where there is only 1 coin, we want it to go to - // the normal queue - let split_point = if coins.len() > 10 { - coins.len() / 2 + // Split the coins eventually into two pools: one for the gas pool and one for + // the batch pool. The batch pool will only be populated if the batch feature is + // enabled. + let split_point = if config.batch_enabled { + if coins.len() > 1 { + 1 // At least one coin goes to the gas pool the rest to the batch pool + } else { + 0 // Only one coin available, all coins go to the batch pool. This is safe as we have already checked above that `coins` is not empty. + } } else { - coins.len() + coins.len() // All coins go to the gas pool if batch is disabled }; - // Put half of the coins in the old faucet impl queue, and put half in the other - // queue for batch coins. In the test cases we create an account with 5 - // coins so we just let this run with a minimum of 5 coins + for (coins_processed, coin) in coins.iter().enumerate() { let coin_id = *coin.id(); if let Some(write_ahead_log::Entry { @@ -946,6 +954,7 @@ impl Faucet for SimpleFaucet { { return Err(FaucetError::BatchSendQueueFull); } + let mut task_map = self.task_id_cache.lock().await; task_map.insert( id, @@ -1035,6 +1044,7 @@ pub async fn batch_transfer_gases( "Batch transfer attempted of size: {:?}", total_requests ); let total_iota_needed: u64 = requests.iter().flat_map(|(_, _, amounts)| amounts).sum(); + // This loop is utilized to grab a coin that is large enough for the request loop { let gas_coin_response = faucet @@ -1292,7 +1302,10 @@ mod tests { #[tokio::test] async fn test_batch_transfer_interface() { let test_cluster = TestClusterBuilder::new().build().await; - let config: FaucetConfig = Default::default(); + let config: FaucetConfig = FaucetConfig { + batch_enabled: true, + ..Default::default() + }; let coin_amount = config.amount; let prom_registry = Registry::new(); let tmp = tempfile::tempdir().unwrap(); @@ -1892,7 +1905,10 @@ mod tests { #[tokio::test] async fn test_amounts_transferred_on_batch() { let test_cluster = TestClusterBuilder::new().build().await; - let config: FaucetConfig = Default::default(); + let config: FaucetConfig = FaucetConfig { + batch_enabled: true, + ..Default::default() + }; let address = test_cluster.get_address_0(); let mut context = test_cluster.wallet; let gas_coins = context diff --git a/crates/iota/tests/cli_tests.rs b/crates/iota/tests/cli_tests.rs index 3f75f606082..aaded6cecdb 100644 --- a/crates/iota/tests/cli_tests.rs +++ b/crates/iota/tests/cli_tests.rs @@ -55,8 +55,8 @@ use iota_test_transaction_builder::batch_make_transfer_transactions; use iota_types::{ base_types::{IotaAddress, ObjectID}, crypto::{ - Ed25519IotaSignature, IotaKeyPair, IotaSignatureInner, Secp256k1IotaSignature, - SignatureScheme, get_key_pair, + AccountKeyPair, Ed25519IotaSignature, IotaKeyPair, IotaSignatureInner, + Secp256k1IotaSignature, SignatureScheme, get_key_pair, }, error::IotaObjectResponseError, gas_coin::GasCoin, @@ -4168,8 +4168,10 @@ async fn test_faucet() -> Result<(), anyhow::Error> { let wallet_config = test_cluster.swarm.dir().join(IOTA_CLIENT_CONFIG); let mut context = WalletContext::new(&wallet_config, None, None)?; + let (address, _): (_, AccountKeyPair) = get_key_pair(); + let faucet_result = IotaClientCommands::Faucet { - address: None, + address: Some(KeyIdentity::Address(address)), url: Some("http://127.0.0.1:5003/gas".to_string()), } .execute(&mut context) @@ -4180,6 +4182,268 @@ async fn test_faucet() -> Result<(), anyhow::Error> { unreachable!("Invalid response"); }; + sleep(Duration::from_secs(5)).await; + + let gas_objects_after = context + .get_gas_objects_owned_by_address(address, None) + .await + .unwrap() + .len(); + assert_eq!(gas_objects_after, 1); + + Ok(()) +} + +#[sim_test] +async fn test_faucet_batch() -> Result<(), anyhow::Error> { + let test_cluster = TestClusterBuilder::new() + .with_fullnode_rpc_port(9000) + .build() + .await; + + let context = test_cluster.wallet; + + let tmp = tempfile::tempdir().unwrap(); + let prom_registry = prometheus::Registry::new(); + let config = iota_faucet::FaucetConfig { + batch_enabled: true, + ..Default::default() + }; + + let prometheus_registry = prometheus::Registry::new(); + let app_state = std::sync::Arc::new(iota_faucet::AppState { + faucet: iota_faucet::SimpleFaucet::new( + context, + &prometheus_registry, + &tmp.path().join("faucet.wal"), + config.clone(), + ) + .await + .unwrap(), + config, + }); + tokio::spawn(async move { iota_faucet::start_faucet(app_state, 10, &prom_registry).await }); + + // Wait for the faucet to be up + sleep(Duration::from_secs(1)).await; + let wallet_config = test_cluster.swarm.dir().join(IOTA_CLIENT_CONFIG); + let mut context = WalletContext::new(&wallet_config, None, None)?; + + let (address_1, _): (_, AccountKeyPair) = get_key_pair(); + let (address_2, _): (_, AccountKeyPair) = get_key_pair(); + let (address_3, _): (_, AccountKeyPair) = get_key_pair(); + + assert_ne!(address_1, address_2); + assert_ne!(address_1, address_3); + assert_ne!(address_2, address_3); + + for address in [address_1, address_2, address_3].iter() { + let gas_objects_after = context + .get_gas_objects_owned_by_address(*address, None) + .await + .unwrap() + .len(); + assert_eq!(gas_objects_after, 0); + } + + for address in [address_1, address_2, address_3].iter() { + let faucet_result = IotaClientCommands::Faucet { + address: Some(KeyIdentity::Address(*address)), + url: Some("http://127.0.0.1:5003/v1/gas".to_string()), + } + .execute(&mut context) + .await?; + + if let IotaClientCommandResult::NoOutput = faucet_result { + } else { + unreachable!("Invalid response"); + }; + } + + // we need to wait a minimum of 10 seconds for gathering the batch + some time + // for transaction to be sequenced + sleep(Duration::from_secs(15)).await; + + for address in [address_1, address_2, address_3].iter() { + let gas_objects_after = context + .get_gas_objects_owned_by_address(*address, None) + .await + .unwrap() + .len(); + assert_eq!(gas_objects_after, 1); + } + + // try with a new batch + let (address_4, _): (_, AccountKeyPair) = get_key_pair(); + let (address_5, _): (_, AccountKeyPair) = get_key_pair(); + let (address_6, _): (_, AccountKeyPair) = get_key_pair(); + + assert_ne!(address_4, address_5); + assert_ne!(address_4, address_6); + assert_ne!(address_5, address_6); + + for address in [address_4, address_5, address_6].iter() { + let gas_objects_after = context + .get_gas_objects_owned_by_address(*address, None) + .await + .unwrap() + .len(); + assert_eq!(gas_objects_after, 0); + } + + for address in [address_4, address_5, address_6].iter() { + let faucet_result = IotaClientCommands::Faucet { + address: Some(KeyIdentity::Address(*address)), + url: Some("http://127.0.0.1:5003/v1/gas".to_string()), + } + .execute(&mut context) + .await?; + + if let IotaClientCommandResult::NoOutput = faucet_result { + } else { + unreachable!("Invalid response"); + }; + } + + // we need to wait a minimum of 10 seconds for gathering the batch + some time + // for transaction to be sequenced + sleep(Duration::from_secs(15)).await; + + for address in [address_4, address_5, address_6].iter() { + let gas_objects_after = context + .get_gas_objects_owned_by_address(*address, None) + .await + .unwrap() + .len(); + assert_eq!(gas_objects_after, 1); + } + + Ok(()) +} + +#[sim_test] +async fn test_faucet_batch_concurrent_requests() -> Result<(), anyhow::Error> { + let test_cluster = TestClusterBuilder::new() + .with_fullnode_rpc_port(9000) + .build() + .await; + + let context = test_cluster.wallet; + + let tmp = tempfile::tempdir().unwrap(); + let prom_registry = prometheus::Registry::new(); + let config = iota_faucet::FaucetConfig { + batch_enabled: true, + ..Default::default() + }; + + let prometheus_registry = prometheus::Registry::new(); + let app_state = std::sync::Arc::new(iota_faucet::AppState { + faucet: iota_faucet::SimpleFaucet::new( + context, + &prometheus_registry, + &tmp.path().join("faucet.wal"), + config.clone(), + ) + .await + .unwrap(), + config, + }); + tokio::spawn(async move { iota_faucet::start_faucet(app_state, 10, &prom_registry).await }); + + // Wait for the faucet to be up + sleep(Duration::from_secs(1)).await; + + let wallet_config = test_cluster.swarm.dir().join(IOTA_CLIENT_CONFIG); + let context = WalletContext::new(&wallet_config, None, None)?; // Use immutable context + + // Generate multiple addresses + let addresses: Vec<_> = (0..6) + .map(|_| get_key_pair::<AccountKeyPair>().0) + .collect::<Vec<IotaAddress>>(); + + // Ensure all addresses have zero gas objects initially + for address in &addresses { + assert_eq!( + context + .get_gas_objects_owned_by_address(*address, None) + .await + .unwrap() + .len(), + 0 + ); + } + + // First batch: send faucet requests concurrently for all addresses + let first_batch_results: Vec<_> = futures::future::join_all(addresses.iter().map(|address| { + let wallet_config = wallet_config.clone(); + async move { + let mut context = WalletContext::new(&wallet_config, None, None)?; // Use mutable context (for faucet requests) + IotaClientCommands::Faucet { + address: Some(KeyIdentity::Address(*address)), + url: Some("http://127.0.0.1:5003/v1/gas".to_string()), + } + .execute(&mut context) + .await + } + })) + .await; + + // Ensure all results are `NoOutput` indicating requests were batched + for result in first_batch_results { + assert!(matches!(result, Ok(IotaClientCommandResult::NoOutput))); + } + + // Wait for the first batch to complete + sleep(Duration::from_secs(15)).await; + + // Validate gas objects after the first batch + for address in &addresses { + assert_eq!( + context + .get_gas_objects_owned_by_address(*address, None) + .await + .unwrap() + .len(), + 1 + ); + } + + // Second batch: send faucet requests again for all addresses + let second_batch_results: Vec<_> = futures::future::join_all(addresses.iter().map(|address| { + let wallet_config = wallet_config.clone(); + async move { + let mut context = WalletContext::new(&wallet_config, None, None)?; // Use mutable context + IotaClientCommands::Faucet { + address: Some(KeyIdentity::Address(*address)), + url: Some("http://127.0.0.1:5003/v1/gas".to_string()), + } + .execute(&mut context) + .await + } + })) + .await; + + // Ensure all results are `NoOutput` for the second batch + for result in second_batch_results { + assert!(matches!(result, Ok(IotaClientCommandResult::NoOutput))); + } + + // Wait for the second batch to complete + sleep(Duration::from_secs(15)).await; + + // Validate gas objects after the second batch + for address in &addresses { + assert_eq!( + context + .get_gas_objects_owned_by_address(*address, None) + .await + .unwrap() + .len(), + 2 + ); + } + Ok(()) } From b627c887c0a23ae6dacbcd42b4a00d2a2f2c724d Mon Sep 17 00:00:00 2001 From: Samuel Rufinatscha <samuel.rufinatscha@iota.org> Date: Thu, 28 Nov 2024 15:09:18 +0100 Subject: [PATCH 14/36] Fix `StructTag` conversion for `iotax_queryEvents` Indexer-RPC method (#4289) * fix: convert the struct tag into a complete canonical string in order for the indexer's `MoveEventType` filter to work * fix: clippy --- crates/iota-indexer/src/indexer_reader.rs | 3 +- .../tests/rpc-tests/indexer_api.rs | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/crates/iota-indexer/src/indexer_reader.rs b/crates/iota-indexer/src/indexer_reader.rs index 3915588184f..1fa26c1969c 100644 --- a/crates/iota-indexer/src/indexer_reader.rs +++ b/crates/iota-indexer/src/indexer_reader.rs @@ -1161,7 +1161,8 @@ impl<U: R2D2Connection> IndexerReader<U> { ) } EventFilter::MoveEventType(struct_tag) => { - format!("event_type = '{}'", struct_tag) + let formatted_struct_tag = struct_tag.to_canonical_string(true); + format!("event_type = '{formatted_struct_tag}'") } EventFilter::MoveEventModule { package, module } => { let package_module_prefix = format!("{}::{}", package.to_hex_literal(), module); diff --git a/crates/iota-indexer/tests/rpc-tests/indexer_api.rs b/crates/iota-indexer/tests/rpc-tests/indexer_api.rs index c830f7ae7a7..49f4e35ff80 100644 --- a/crates/iota-indexer/tests/rpc-tests/indexer_api.rs +++ b/crates/iota-indexer/tests/rpc-tests/indexer_api.rs @@ -185,6 +185,38 @@ fn query_events_supported_events() { }); } +#[test] +fn query_validator_epoch_info_event() { + let ApiTestSetup { + runtime, + store, + client, + cluster, + } = ApiTestSetup::get_or_init(); + + runtime.block_on(async move { + indexer_wait_for_checkpoint(store, 1).await; + + cluster.force_new_epoch().await; + + let result = client.query_events(EventFilter::MoveEventType("0x0000000000000000000000000000000000000000000000000000000000000003::validator_set::ValidatorEpochInfoEventV1".parse().unwrap()), None, None, None).await; + assert!(result.is_ok()); + assert!(!result.unwrap().data.is_empty()); + + let result = client.query_events(EventFilter::MoveEventType("0x3::validator_set::ValidatorEpochInfoEventV1".parse().unwrap()), None, None, None).await; + assert!(result.is_ok()); + assert!(!result.unwrap().data.is_empty()); + + let result = client.query_events(EventFilter::MoveEventType("0x0003::validator_set::ValidatorEpochInfoEventV1".parse().unwrap()), None, None, None).await; + assert!(result.is_ok()); + assert!(!result.unwrap().data.is_empty()); + + let result = client.query_events(EventFilter::MoveEventType("0x1::validator_set::ValidatorEpochInfoEventV1".parse().unwrap()), None, None, None).await; + assert!(result.is_ok()); + assert!(result.unwrap().data.is_empty()); + }); +} + #[test] fn test_get_owned_objects() -> Result<(), anyhow::Error> { let ApiTestSetup { From baed3f70db2b26d1617489f2987ec95b85d5cd1b Mon Sep 17 00:00:00 2001 From: Thibault Martinez <thibault@iota.org> Date: Thu, 28 Nov 2024 15:43:38 +0100 Subject: [PATCH 15/36] chore(*): bump rust toolchain to 1.82 (#4235) --- crates/iota-graphql-rpc-client/src/response.rs | 2 ++ crates/iota-graphql-rpc-client/src/simple_client.rs | 2 +- crates/iota-replay/src/data_fetcher.rs | 6 ++++-- crates/iota-replay/src/types.rs | 2 +- crates/iota-source-validation/src/error.rs | 4 ++-- crates/iota-source-validation/src/lib.rs | 6 +++--- rust-toolchain.toml | 2 +- scripts/generate_files/Dockerfile | 2 +- 8 files changed, 15 insertions(+), 11 deletions(-) diff --git a/crates/iota-graphql-rpc-client/src/response.rs b/crates/iota-graphql-rpc-client/src/response.rs index 2100a1aac94..40c24e93cf8 100644 --- a/crates/iota-graphql-rpc-client/src/response.rs +++ b/crates/iota-graphql-rpc-client/src/response.rs @@ -40,6 +40,7 @@ impl GraphqlResponse { }) } + #[allow(clippy::result_large_err)] pub fn graphql_version(&self) -> Result<String, ClientError> { Ok(self .headers @@ -90,6 +91,7 @@ impl GraphqlResponse { self.full_response.errors.clone() } + #[allow(clippy::result_large_err)] pub fn usage(&self) -> Result<Option<BTreeMap<String, u64>>, ClientError> { Ok(match self.full_response.extensions.get("usage").cloned() { Some(Value::Object(obj)) => Some( diff --git a/crates/iota-graphql-rpc-client/src/simple_client.rs b/crates/iota-graphql-rpc-client/src/simple_client.rs index 852ece48b8c..f78f8ca3753 100644 --- a/crates/iota-graphql-rpc-client/src/simple_client.rs +++ b/crates/iota-graphql-rpc-client/src/simple_client.rs @@ -117,7 +117,7 @@ impl SimpleClient { } } -#[allow(clippy::type_complexity)] +#[allow(clippy::type_complexity, clippy::result_large_err)] pub fn resolve_variables( vars: &[GraphqlQueryVariable], ) -> Result<(BTreeMap<String, String>, BTreeMap<String, Value>), ClientError> { diff --git a/crates/iota-replay/src/data_fetcher.rs b/crates/iota-replay/src/data_fetcher.rs index 4bf7a73d398..70749a03dbe 100644 --- a/crates/iota-replay/src/data_fetcher.rs +++ b/crates/iota-replay/src/data_fetcher.rs @@ -522,7 +522,7 @@ impl DataFetcher for RemoteFetcher { u64::from_str(&w["reference_gas_price"].to_string().replace('\"', "")).unwrap() } else { return Err(ReplayEngineError::UnexpectedEventFormat { - event: event.clone(), + event: Box::new(event.clone()), }); }; @@ -639,7 +639,9 @@ pub fn extract_epoch_and_version(ev: IotaEvent) -> Result<(u64, u64), ReplayEngi return Ok((epoch, version)); } - Err(ReplayEngineError::UnexpectedEventFormat { event: ev }) + Err(ReplayEngineError::UnexpectedEventFormat { + event: Box::new(ev), + }) } #[derive(Clone)] diff --git a/crates/iota-replay/src/types.rs b/crates/iota-replay/src/types.rs index 993868020a6..05c90fffe71 100644 --- a/crates/iota-replay/src/types.rs +++ b/crates/iota-replay/src/types.rs @@ -166,7 +166,7 @@ pub enum ReplayEngineError { InvalidEpochChangeTx { epoch: u64 }, #[error("Unexpected event format {:#?}", event)] - UnexpectedEventFormat { event: IotaEvent }, + UnexpectedEventFormat { event: Box<IotaEvent> }, #[error("Unable to find event for epoch {epoch}")] EventNotFound { epoch: u64 }, diff --git a/crates/iota-source-validation/src/error.rs b/crates/iota-source-validation/src/error.rs index 36cb79955fb..c9060245b5e 100644 --- a/crates/iota-source-validation/src/error.rs +++ b/crates/iota-source-validation/src/error.rs @@ -49,8 +49,8 @@ pub enum Error { module: Symbol, }, - #[error("Dependency ID contains a Iota object, not a Move package: {0}")] - ObjectFoundWhenPackageExpected(ObjectID, IotaRawMoveObject), + #[error("Dependency ID contains a Iota object, not a Move package: {}", .0.0)] + ObjectFoundWhenPackageExpected(Box<(ObjectID, IotaRawMoveObject)>), #[error("Could not deserialize on-chain dependency {address}::{module}.")] OnChainDependencyDeserializationError { diff --git a/crates/iota-source-validation/src/lib.rs b/crates/iota-source-validation/src/lib.rs index 38009f1fe89..18a3942c7cc 100644 --- a/crates/iota-source-validation/src/lib.rs +++ b/crates/iota-source-validation/src/lib.rs @@ -414,9 +414,9 @@ impl<'a> BytecodeSourceVerifier<'a> { match obj { IotaRawData::Package(pkg) => Ok(pkg), - IotaRawData::MoveObject(move_obj) => { - Err(Error::ObjectFoundWhenPackageExpected(obj_id, move_obj)) - } + IotaRawData::MoveObject(move_obj) => Err(Error::ObjectFoundWhenPackageExpected( + Box::new((obj_id, move_obj)), + )), } } } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 4cef0b738ff..76fcadb5b32 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.81" +channel = "1.82" diff --git a/scripts/generate_files/Dockerfile b/scripts/generate_files/Dockerfile index 7b832715976..334aa855498 100644 --- a/scripts/generate_files/Dockerfile +++ b/scripts/generate_files/Dockerfile @@ -1,7 +1,7 @@ FROM node:20-bookworm # Accept a build argument for the Rust version -ARG RUST_VERSION=1.81 +ARG RUST_VERSION=1.82 # Get USER_ID from build-args ARG USER_ID=1000 From b6a9a71a90b2c932e6090d86a0e8f253d0faabff Mon Sep 17 00:00:00 2001 From: Thibault Martinez <thibault@iota.org> Date: Thu, 28 Nov 2024 16:54:05 +0100 Subject: [PATCH 16/36] fix(*): rustls RUSTSEC-2024-0399 (#4248) --- Cargo.lock | 38 +++++++++++++++++----------------- Cargo.toml | 2 +- crates/iota-storage/Cargo.toml | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 029a587e761..a6985400c04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,7 +191,7 @@ dependencies = [ "rand 0.8.5", "rcgen", "ring 0.17.8", - "rustls 0.23.13", + "rustls 0.23.18", "rustls-webpki 0.102.8", "serde", "serde_json", @@ -1625,7 +1625,7 @@ dependencies = [ "hyper 1.4.1", "hyper-util", "pin-project-lite", - "rustls 0.23.13", + "rustls 0.23.18", "rustls-pemfile 2.1.3", "rustls-pki-types", "tokio", @@ -2708,7 +2708,7 @@ dependencies = [ "quinn-proto", "rand 0.8.5", "rstest", - "rustls 0.23.13", + "rustls 0.23.18", "serde", "shared-crypto", "strum_macros 0.26.4", @@ -5436,7 +5436,7 @@ dependencies = [ "hyper 1.4.1", "hyper-util", "log", - "rustls 0.23.13", + "rustls 0.23.18", "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", @@ -7655,7 +7655,7 @@ dependencies = [ "move-core-types", "rand 0.8.5", "reqwest 0.12.7", - "rustls 0.23.13", + "rustls 0.23.18", "serde", "serde_json", "serde_with", @@ -7903,7 +7903,7 @@ dependencies = [ "percent-encoding", "prometheus", "reqwest 0.12.7", - "rustls 0.23.13", + "rustls 0.23.18", "serde", "serde_json", "tap", @@ -8023,7 +8023,7 @@ dependencies = [ "rand 0.8.5", "rcgen", "reqwest 0.12.7", - "rustls 0.23.13", + "rustls 0.23.18", "rustls-webpki 0.102.8", "tokio", "tokio-rustls 0.26.0", @@ -8510,7 +8510,7 @@ dependencies = [ "http 1.1.0", "jsonrpsee-core", "pin-project", - "rustls 0.23.13", + "rustls 0.23.18", "rustls-pki-types", "rustls-platform-verifier", "soketto", @@ -8563,7 +8563,7 @@ dependencies = [ "hyper-util", "jsonrpsee-core", "jsonrpsee-types", - "rustls 0.23.13", + "rustls 0.23.18", "rustls-platform-verifier", "serde", "serde_json", @@ -11949,7 +11949,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.0.0", - "rustls 0.23.13", + "rustls 0.23.18", "socket2", "thiserror", "tokio", @@ -11966,7 +11966,7 @@ dependencies = [ "rand 0.8.5", "ring 0.17.8", "rustc-hash 2.0.0", - "rustls 0.23.13", + "rustls 0.23.18", "slab", "thiserror", "tinyvec", @@ -12397,7 +12397,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.13", + "rustls 0.23.18", "rustls-native-certs 0.7.3", "rustls-pemfile 2.1.3", "rustls-pki-types", @@ -12865,9 +12865,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" dependencies = [ "aws-lc-rs", "log", @@ -12938,9 +12938,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-platform-verifier" @@ -12953,7 +12953,7 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.13", + "rustls 0.23.18", "rustls-native-certs 0.7.3", "rustls-platform-verifier-android", "rustls-webpki 0.102.8", @@ -14790,7 +14790,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.13", + "rustls 0.23.18", "rustls-pki-types", "tokio", ] @@ -15554,7 +15554,7 @@ dependencies = [ "flate2", "log", "once_cell", - "rustls 0.23.13", + "rustls 0.23.18", "rustls-pki-types", "url", "webpki-roots 0.26.6", diff --git a/Cargo.toml b/Cargo.toml index 55279866086..d9a5cb5b76b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -302,7 +302,7 @@ reqwest = { version = "0.12", default-features = false, features = ["http2", "js roaring = "0.10.6" rocksdb = { version = "0.21.0", default-features = false, features = ["snappy", "lz4", "zstd", "zlib", "multi-threaded-cf"] } rstest = "0.16.0" -rustls = { version = "0.23", default-features = false, features = ["std", "tls12", "ring"] } +rustls = { version = "0.23.18", default-features = false, features = ["std", "tls12", "ring"] } schemars = { version = "0.8.21", features = ["either"] } scopeguard = "1.1" serde = { version = "1.0.144", features = ["derive", "rc"] } diff --git a/crates/iota-storage/Cargo.toml b/crates/iota-storage/Cargo.toml index bc6d3a66e96..fda14adfb6e 100644 --- a/crates/iota-storage/Cargo.toml +++ b/crates/iota-storage/Cargo.toml @@ -70,7 +70,7 @@ iota-types = { workspace = true, features = ["test-utils"] } [target.'cfg(msim)'.dependencies] # external dependencies axum.workspace = true -rustls = "0.23" +rustls = "0.23.18" # internal dependencies iota-simulator.workspace = true From c4bcdf9f089520b160034ec0d4b299c2d4bddc92 Mon Sep 17 00:00:00 2001 From: Thibault Martinez <thibault@iota.org> Date: Thu, 28 Nov 2024 17:02:09 +0100 Subject: [PATCH 17/36] fix(ci): labeler.yml for explorer (#4295) --- .github/labeler.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 83af79e05b4..9c85e15b9f1 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,6 +1,6 @@ -Documentation: +documentation: - changed-files: - any-glob-to-any-file: docs/content/**/* -iota-explorer: +explorer: - changed-files: - - any-glob-to-any-file: explorer/**/* + - any-glob-to-any-file: apps/explorer/**/* From 5a9a8f352b44f58a9b405794cc9f089f970ac0e3 Mon Sep 17 00:00:00 2001 From: Alexander Sporn <github@alexsporn.de> Date: Thu, 28 Nov 2024 17:39:42 +0100 Subject: [PATCH 18/36] Adapt CODEOWNERS to new team names (#4302) --- .github/CODEOWNERS | 84 +++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 45652f18036..f77a9c2b71b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,41 +1,41 @@ # Default fallback, if no other path below this matches -* @iotaledger/l1-core @iotaledger/core-node @iotaledger/core-consensus +* @iotaledger/sc-platform @iotaledger/core-protocol # Everything within the SDK folder -/sdk/ @iotaledger/boxfish @iotaledger/l1-core @iotaledger/tooling +/sdk/ @iotaledger/tooling # Changes to the genesis builder should be approved by Konstantinos or Mirko at least /crates/iota-genesis-builder/ @kodemartin @miker83z # vm-language team -/iota-execution/ @miker83z @valeriyr -/external-crates/ @miker83z @valeriyr +/iota-execution/ @iotaledger/vm-language +/external-crates/ @iotaledger/vm-language -# l1-core-infra team -/docker/ @iotaledger/l1-core-infra @iotaledger/core-node @iotaledger/devops-admin -/crates/iota-json-rpc*/ @iotaledger/l1-core-infra -/crates/iota-graphql*/ @iotaledger/l1-core-infra -/crates/iota-indexer*/ @iotaledger/l1-core-infra -/crates/iota-data-ingestion*/ @iotaledger/l1-core-infra -/crates/iota-analytics-indexer/ @iotaledger/l1-core-infra +# infrastructure team +/docker/ @iotaledger/infrastructure @iotaledger/node @iotaledger/devops-admin +/crates/iota-json-rpc*/ @iotaledger/infrastructure +/crates/iota-graphql*/ @iotaledger/infrastructure +/crates/iota-indexer*/ @iotaledger/infrastructure +/crates/iota-data-ingestion*/ @iotaledger/infrastructure +/crates/iota-analytics-indexer/ @iotaledger/infrastructure -# core-node team -/crates/iota-archival/ @iotaledger/core-node -/crates/iota-authority-aggregation/ @iotaledger/core-node @iotaledger/core-consensus -/crates/iota-config/ @iotaledger/core-node -/crates/iota-core/ @iotaledger/core-node @iotaledger/core-consensus -/crates/iota-network/ @iotaledger/core-node -/crates/iota-network-stack/ @iotaledger/core-node -/crates/iota-node/ @iotaledger/core-node -/crates/iota-types/ @iotaledger/core-node @iotaledger/l1-core -/crates/iota-protocol-config/ @iotaledger/core-node @iotaledger/l1-core -/crates/iota-protocol-config-macros/ @iotaledger/core-node @iotaledger/l1-core -/crates/iota-rest-api/ @iotaledger/core-node @iotaledger/l1-core-infra -/crates/iota-snapshot/ @iotaledger/core-node -/crates/iota-storage/ @iotaledger/core-node +# node team +/crates/iota-archival/ @iotaledger/node +/crates/iota-authority-aggregation/ @iotaledger/node @iotaledger/consensus +/crates/iota-config/ @iotaledger/node +/crates/iota-core/ @iotaledger/node @iotaledger/consensus +/crates/iota-network/ @iotaledger/node +/crates/iota-network-stack/ @iotaledger/node +/crates/iota-node/ @iotaledger/node +/crates/iota-types/ @iotaledger/node @iotaledger/sc-platform +/crates/iota-protocol-config/ @iotaledger/node @iotaledger/sc-platform +/crates/iota-protocol-config-macros/ @iotaledger/node @iotaledger/sc-platform +/crates/iota-rest-api/ @iotaledger/node @iotaledger/infrastructure +/crates/iota-snapshot/ @iotaledger/node +/crates/iota-storage/ @iotaledger/node -# core-consensus team -/consensus/ @iotaledger/core-consensus +# consensus team +/consensus/ @iotaledger/consensus # dev-tools team /crates/iota/ @iotaledger/dev-tools @@ -45,21 +45,21 @@ /crates/iota-transaction-builder/ @iotaledger/dev-tools # Frontend apps to be looked after by Boxfish Studio or the tooling team -/apps/ @iotaledger/boxfish @iotaledger/tooling -/dapps/ @iotaledger/boxfish @iotaledger/tooling -/linting/ @iotaledger/boxfish @iotaledger/tooling -/.husky/ @iotaledger/boxfish @iotaledger/tooling -/.changeset/ @iotaledger/boxfish @iotaledger/tooling -.eslintrc.js @iotaledger/boxfish @iotaledger/tooling -.lintstagedrc.json @iotaledger/boxfish @iotaledger/tooling -.npmrc @iotaledger/boxfish @iotaledger/tooling -.prettierignore @iotaledger/boxfish @iotaledger/tooling -graphql.config.ts @iotaledger/boxfish @iotaledger/tooling -package.json @iotaledger/boxfish @iotaledger/tooling -pnpm-workspace.yaml @iotaledger/boxfish @iotaledger/tooling -prettier.config.js @iotaledger/boxfish @iotaledger/tooling -turbo.json @iotaledger/boxfish @iotaledger/tooling -vercel.json @iotaledger/boxfish @iotaledger/tooling +/apps/ @iotaledger/tooling +/dapps/ @iotaledger/tooling +/linting/ @iotaledger/tooling +/.husky/ @iotaledger/tooling +/.changeset/ @iotaledger/tooling +.eslintrc.js @iotaledger/tooling +.lintstagedrc.json @iotaledger/tooling +.npmrc @iotaledger/tooling +.prettierignore @iotaledger/tooling +graphql.config.ts @iotaledger/tooling +package.json @iotaledger/tooling +pnpm-workspace.yaml @iotaledger/tooling +prettier.config.js @iotaledger/tooling +turbo.json @iotaledger/tooling +vercel.json @iotaledger/tooling # Docs and examples are for DevEx to approve upon /docs/ @iotaledger/devx From 74c388e94f284f148538be031d02a43740d8c208 Mon Sep 17 00:00:00 2001 From: Luca Moser <me+github@lucamoser.ch> Date: Thu, 28 Nov 2024 21:01:36 +0100 Subject: [PATCH 19/36] fix(docs): Typo in node docker install (#4304) Signed-off-by: Luca Moser <me@lucamoser.ch> --- nre/docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nre/docker/README.md b/nre/docker/README.md index e015e6077f6..640e94dabd3 100644 --- a/nre/docker/README.md +++ b/nre/docker/README.md @@ -7,7 +7,7 @@ Tested using: ## Prerequisites and Setup -1. Confirm you have either [Docker Engine](https://docs.docker.com/engine/install/) or [Docker Desktop](https://docs.docker.com/desktop/install/linux-install/) instllled, as well as [Docker Compose](https://github.com/docker/compose#linux). +1. Confirm you have either [Docker Engine](https://docs.docker.com/engine/install/) or [Docker Desktop](https://docs.docker.com/desktop/install/linux-install/) installed, as well as [Docker Compose](https://github.com/docker/compose#linux). 2. Update [validator.yaml](../config/validator.yaml) and place it in the same directory as `docker-compose.yaml`. From 42fbfb284929d17876e1e20cc9aba5dc1b68cefa Mon Sep 17 00:00:00 2001 From: Hans Moog <3293976+hmoog@users.noreply.github.com> Date: Fri, 29 Nov 2024 07:32:26 +0000 Subject: [PATCH 20/36] fix(docker):iota-private-network (#4293) * fixed config * addressed dprint error --------- Co-authored-by: Hans Moog <hmoog@users.noreply.github.com> --- docker/iota-private-network/configs/genesis-template.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/iota-private-network/configs/genesis-template.yaml b/docker/iota-private-network/configs/genesis-template.yaml index 0ce6832306c..1650e388275 100644 --- a/docker/iota-private-network/configs/genesis-template.yaml +++ b/docker/iota-private-network/configs/genesis-template.yaml @@ -45,3 +45,4 @@ validator_config_info: network_address: /dns/validator-4/tcp/8080/http p2p_address: /dns/validator-4/udp/8084 stake: 20000000000000000 +migration_sources: [] From d26dc3c1f3e436df38a2ce8e403a3bd727a0cb97 Mon Sep 17 00:00:00 2001 From: Valerii Reutov <valeriy.reutov@gmail.com> Date: Fri, 29 Nov 2024 11:01:15 +0200 Subject: [PATCH 21/36] fix(move-analyzer): change the publisher name (#4294) --- .../move/crates/move-analyzer/editors/code/package.json | 2 +- .../crates/move-analyzer/editors/code/src/extension.ts | 2 +- .../crates/move-analyzer/editors/code/tests/ext.test.ts | 2 +- .../crates/move-analyzer/editors/code/tests/lsp.test.ts | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/external-crates/move/crates/move-analyzer/editors/code/package.json b/external-crates/move/crates/move-analyzer/editors/code/package.json index 0f6737c2c29..7528263217d 100644 --- a/external-crates/move/crates/move-analyzer/editors/code/package.json +++ b/external-crates/move/crates/move-analyzer/editors/code/package.json @@ -2,7 +2,7 @@ "name": "iota-move", "displayName": "IOTA Move", "description": "A Move language integrated development environment for IOTA.", - "publisher": "iota-foundation", + "publisher": "iotaledger", "icon": "images/move.png", "license": "Apache-2.0", "version": "1.0.0", diff --git a/external-crates/move/crates/move-analyzer/editors/code/src/extension.ts b/external-crates/move/crates/move-analyzer/editors/code/src/extension.ts index a414f1827a6..b9115931b95 100644 --- a/external-crates/move/crates/move-analyzer/editors/code/src/extension.ts +++ b/external-crates/move/crates/move-analyzer/editors/code/src/extension.ts @@ -9,7 +9,7 @@ import * as vscode from 'vscode'; /** Information related to this extension itself, such as its identifier and version. */ export class Extension { /** The string used to uniquely identify this particular extension to VS Code. */ - readonly identifier = 'iota-foundation.iota-move'; + readonly identifier = 'iotaledger.iota-move'; private readonly extension: vscode.Extension<unknown>; diff --git a/external-crates/move/crates/move-analyzer/editors/code/tests/ext.test.ts b/external-crates/move/crates/move-analyzer/editors/code/tests/ext.test.ts index 093d0b24f62..266761ed8e8 100644 --- a/external-crates/move/crates/move-analyzer/editors/code/tests/ext.test.ts +++ b/external-crates/move/crates/move-analyzer/editors/code/tests/ext.test.ts @@ -8,7 +8,7 @@ import * as vscode from 'vscode'; Mocha.suite('ext', () => { Mocha.test('ext_exists', () => { - const ext = vscode.extensions.getExtension('iota-foundation.iota-move'); + const ext = vscode.extensions.getExtension('iotaledger.iota-move'); assert.ok(ext); }); }); diff --git a/external-crates/move/crates/move-analyzer/editors/code/tests/lsp.test.ts b/external-crates/move/crates/move-analyzer/editors/code/tests/lsp.test.ts index 0dc0512d528..f824eb30d98 100644 --- a/external-crates/move/crates/move-analyzer/editors/code/tests/lsp.test.ts +++ b/external-crates/move/crates/move-analyzer/editors/code/tests/lsp.test.ts @@ -24,7 +24,7 @@ const PRIMITIVE_TYPES = ['u8', 'u16', 'u32', 'u64', 'u128', 'u256', 'bool', 'vec Mocha.suite('LSP', () => { Mocha.test('textDocument/documentSymbol', async () => { - const ext = vscode.extensions.getExtension('iota-foundation.iota-move'); + const ext = vscode.extensions.getExtension('iotaledger.iota-move'); assert.ok(ext); await ext.activate(); // Synchronous waiting for activation to complete @@ -69,7 +69,7 @@ Mocha.suite('LSP', () => { }); Mocha.test('textDocument/hover for definition in the same module', async () => { - const ext = vscode.extensions.getExtension('iota-foundation.iota-move'); + const ext = vscode.extensions.getExtension('iotaledger.iota-move'); assert.ok(ext); await ext.activate(); // Synchronous waiting for activation to complete @@ -108,7 +108,7 @@ Mocha.suite('LSP', () => { }); Mocha.test('textDocument/hover for definition in an external module', async () => { - const ext = vscode.extensions.getExtension('iota-foundation.iota-move'); + const ext = vscode.extensions.getExtension('iotaledger.iota-move'); assert.ok(ext); await ext.activate(); // Synchronous waiting for activation to complete @@ -147,7 +147,7 @@ Mocha.suite('LSP', () => { }); Mocha.test('textDocument/completion', async () => { - const ext = vscode.extensions.getExtension('iota-foundation.iota-move'); + const ext = vscode.extensions.getExtension('iotaledger.iota-move'); assert.ok(ext); await ext.activate(); // Synchronous waiting for activation to complete From d899a6c404871ba0e3374209ef059ba744e83a60 Mon Sep 17 00:00:00 2001 From: Mario <mario.sarcevic@iota.org> Date: Fri, 29 Nov 2024 10:50:28 +0100 Subject: [PATCH 22/36] feat(core): Add hook with logic to check if an asset is 'Transferable'. (#4159) * feat(tooling-core): Add hook with logic to check if an asset is 'Transferabe'. Remove old util * feat(apps-core): Use useQuery in place of useEffect in useIsAssetTransferable * feat(apps-core): Improve early return condition in useIsAssetTransferable * feat(apps-core): Improve per PR comments --- apps/core/src/hooks/index.ts | 1 + apps/core/src/hooks/useIsAssetTransferable.ts | 50 +++++++++++++++++++ apps/core/src/utils/index.ts | 1 - apps/core/src/utils/isAssetTransferable.ts | 10 ---- .../(protected)/assets/[objectId]/page.tsx | 7 ++- .../ui/app/pages/home/nft-details/index.tsx | 10 ++-- .../ui/app/pages/home/nft-transfer/index.tsx | 8 +-- 7 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 apps/core/src/hooks/useIsAssetTransferable.ts delete mode 100644 apps/core/src/utils/isAssetTransferable.ts diff --git a/apps/core/src/hooks/index.ts b/apps/core/src/hooks/index.ts index 2ffa7f95688..026f01c6656 100644 --- a/apps/core/src/hooks/index.ts +++ b/apps/core/src/hooks/index.ts @@ -24,6 +24,7 @@ export * from './useGetKioskContents'; export * from './useZodForm'; export * from './useElementDimensions'; export * from './useIotaCoinData'; +export * from './useIsAssetTransferable'; export * from './useLocalStorage'; export * from './useTokenPrice'; export * from './useKioskClient'; diff --git a/apps/core/src/hooks/useIsAssetTransferable.ts b/apps/core/src/hooks/useIsAssetTransferable.ts new file mode 100644 index 00000000000..7f5e75890a8 --- /dev/null +++ b/apps/core/src/hooks/useIsAssetTransferable.ts @@ -0,0 +1,50 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { useIotaClient } from '@iota/dapp-kit'; +import { IotaMoveNormalizedStruct, IotaObjectData } from '@iota/iota-sdk/client'; +import { useQuery } from '@tanstack/react-query'; + +function getObjectTypeParams(obj: IotaObjectData | null | undefined) { + const objectType = + obj?.type ?? + (obj?.content?.dataType === 'package' ? 'package' : obj?.content?.type) ?? + null; + + return objectType?.split('<')[0]?.split('::') || []; +} + +export function useIsAssetTransferable(obj: IotaObjectData | null | undefined) { + const client = useIotaClient(); + const [packageId, moduleName, functionName] = getObjectTypeParams(obj); + + return useQuery({ + // eslint-disable-next-line @tanstack/query/exhaustive-deps + queryKey: ['is-asset-transferable', packageId, moduleName, functionName], + queryFn: async () => { + if (!packageId || !moduleName || !functionName) { + return undefined; + } + + return await client.getNormalizedMoveStruct({ + package: packageId, + module: moduleName, + struct: functionName, + }); + }, + select: (moveNormalizedStruct: IotaMoveNormalizedStruct | undefined): boolean => { + if (!moveNormalizedStruct) { + return false; + } + + const structAbilities = moveNormalizedStruct?.abilities?.abilities ?? null; + + if (!structAbilities) { + return false; + } + + return structAbilities.includes('Store'); + }, + enabled: !!packageId && !!moduleName && !!functionName, + }); +} diff --git a/apps/core/src/utils/index.ts b/apps/core/src/utils/index.ts index 8cbb31afa73..4d57564fa92 100644 --- a/apps/core/src/utils/index.ts +++ b/apps/core/src/utils/index.ts @@ -1,7 +1,6 @@ // Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -export * from './isAssetTransferable'; export * from './calculateStakeShare'; export * from './chunkArray'; export * from './formatAmount'; diff --git a/apps/core/src/utils/isAssetTransferable.ts b/apps/core/src/utils/isAssetTransferable.ts deleted file mode 100644 index 4dad0779706..00000000000 --- a/apps/core/src/utils/isAssetTransferable.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import { IotaObjectData } from '@iota/iota-sdk/client'; - -export const isAssetTransferable = (obj: IotaObjectData | null | undefined): boolean => - // TODO: Either the type abilities will be added to 'IotaParsedData' and - // we need to check if the object has the 'store' ability or there will be a new endpoint - // that returns the "transferable" status of a MoveType. - !!obj && obj.content?.dataType === 'moveObject'; // && obj.content.hasPublicTransfer; diff --git a/apps/wallet-dashboard/app/(protected)/assets/[objectId]/page.tsx b/apps/wallet-dashboard/app/(protected)/assets/[objectId]/page.tsx index 7f42d41f04b..563d7a9e9c0 100644 --- a/apps/wallet-dashboard/app/(protected)/assets/[objectId]/page.tsx +++ b/apps/wallet-dashboard/app/(protected)/assets/[objectId]/page.tsx @@ -6,7 +6,7 @@ import React, { useCallback } from 'react'; import { useParams } from 'next/navigation'; import { Button, RouteLink, SendAssetPopup, VisualAssetDetailsCard } from '@/components'; -import { isAssetTransferable, useGetObject } from '@iota/core'; +import { useIsAssetTransferable, useGetObject } from '@iota/core'; import { usePopups } from '@/hooks'; import { useCurrentAccount } from '@iota/dapp-kit'; import { ASSETS_ROUTE } from '@/lib/constants/routes.constants'; @@ -15,6 +15,7 @@ const VisualAssetDetailPage = () => { const params = useParams(); const objectId = params.objectId as string; const { data: asset } = useGetObject(objectId); + const { data: isAssetTransferable } = useIsAssetTransferable(asset?.data); const activeAccount = useCurrentAccount(); const { openPopup, closePopup } = usePopups(); @@ -25,8 +26,6 @@ const VisualAssetDetailPage = () => { } }, [asset, openPopup, closePopup]); - const assetIsTransferable = asset?.data ? isAssetTransferable(asset?.data) : false; - return ( <div className="flex h-full w-full flex-col space-y-4 px-40"> <RouteLink path={ASSETS_ROUTE.path} title="Back" /> @@ -35,7 +34,7 @@ const VisualAssetDetailPage = () => { ) : ( <div className="flex justify-center p-20">Asset not found</div> )} - {assetIsTransferable && activeAccount ? ( + {isAssetTransferable && activeAccount ? ( <Button onClick={showSendAssetPopup}>Send Asset</Button> ) : null} </div> diff --git a/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx b/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx index ab9508a19f0..3879f492cea 100644 --- a/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx +++ b/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx @@ -7,7 +7,7 @@ import { Collapsible } from '_app/shared/collapse'; import { ExplorerLink, ExplorerLinkType, Loading, NFTDisplayCard, PageTemplate } from '_components'; import { useNFTBasicData, useOwnedNFT } from '_hooks'; import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import { isAssetTransferable, useGetKioskContents, useGetNFTMeta } from '@iota/core'; +import { useIsAssetTransferable, useGetKioskContents, useGetNFTMeta } from '@iota/core'; import { formatAddress } from '@iota/iota-sdk/utils'; import cl from 'clsx'; import { Link, Navigate, useNavigate, useSearchParams } from 'react-router-dom'; @@ -24,7 +24,8 @@ function NFTDetailsPage() { const nftId = searchParams.get('objectId'); const accountAddress = useActiveAddress(); const { data: objectData, isPending: isNftLoading } = useOwnedNFT(nftId || '', accountAddress); - const isTransferable = isAssetTransferable(objectData); + const { data: isAssetTransferable, isLoading: isCheckingAssetTransferability } = + useIsAssetTransferable(objectData); const { nftFields, fileExtensionType, filePath } = useNFTBasicData(objectData); const address = useActiveAddress(); const { data } = useGetKioskContents(address); @@ -55,7 +56,8 @@ function NFTDetailsPage() { objectData.owner.AddressOwner) || ''; const isGuardLoading = useUnlockedGuard(); - const isPending = isNftLoading || isPendingDisplay || isGuardLoading; + const isPending = + isNftLoading || isPendingDisplay || isGuardLoading || isCheckingAssetTransferability; function handleMoreAboutKiosk() { window.open('https://docs.iota.org/references/ts-sdk/kiosk/', '_blank'); @@ -241,7 +243,7 @@ function NFTDetailsPage() { ) : ( <div className="flex flex-1 items-end"> <Button - disabled={!isTransferable} + disabled={!isAssetTransferable} onClick={handleSend} text="Send" fullWidth diff --git a/apps/wallet/src/ui/app/pages/home/nft-transfer/index.tsx b/apps/wallet/src/ui/app/pages/home/nft-transfer/index.tsx index d8dcaf5af50..bae076ae8a2 100644 --- a/apps/wallet/src/ui/app/pages/home/nft-transfer/index.tsx +++ b/apps/wallet/src/ui/app/pages/home/nft-transfer/index.tsx @@ -8,21 +8,23 @@ import { useOwnedNFT } from '_hooks'; import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; import { Navigate, useNavigate, useParams } from 'react-router-dom'; import { TransferNFTForm } from './TransferNFTForm'; -import { isAssetTransferable } from '@iota/core'; +import { useIsAssetTransferable } from '@iota/core'; function NftTransferPage() { const { nftId } = useParams(); const address = useActiveAddress(); // verify that the nft is owned by the user and is transferable const { data: ownedNFT, isPending: isNftLoading } = useOwnedNFT(nftId || '', address); + const { data: isAssetTransferable, isLoading: isCheckingAssetTransferability } = + useIsAssetTransferable(ownedNFT); const navigate = useNavigate(); const isGuardLoading = useUnlockedGuard(); - const isPending = isNftLoading || isGuardLoading; + const isPending = isNftLoading || isGuardLoading || isCheckingAssetTransferability; return ( <Overlay showModal title="Send NFT" closeOverlay={() => navigate('/nfts')} showBackButton> <Loading loading={isPending}> <div className="flex h-full w-full flex-col gap-md"> - {nftId && !!ownedNFT && isAssetTransferable(ownedNFT) ? ( + {nftId && !!ownedNFT && isAssetTransferable ? ( <> <div className="w-[172px] self-center"> <NFTDisplayCard objectId={nftId} wideView /> From 978fa075d887311ee360f6c2dc083a8194784f03 Mon Sep 17 00:00:00 2001 From: Thibault Martinez <thibault@iota.org> Date: Fri, 29 Nov 2024 12:33:25 +0100 Subject: [PATCH 23/36] fix(iota-types): elided_named_lifetimes 1.83 compiler warning (#4309) --- crates/iota-types/src/crypto.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/iota-types/src/crypto.rs b/crates/iota-types/src/crypto.rs index e9887a20102..a78c50b3ca7 100644 --- a/crates/iota-types/src/crypto.rs +++ b/crates/iota-types/src/crypto.rs @@ -1390,7 +1390,7 @@ impl<const STRONG_THRESHOLD: bool> AuthorityQuorumSignInfo<STRONG_THRESHOLD> { pub fn authorities<'a>( &'a self, committee: &'a Committee, - ) -> impl Iterator<Item = IotaResult<&AuthorityName>> { + ) -> impl Iterator<Item = IotaResult<&'a AuthorityName>> { self.signers_map.iter().map(|i| { committee .authority_by_index(i) From 28aeefca2cb3bf4daddd9270dfd50d11547e70af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bego=C3=B1a=20=C3=81lvarez=20de=20la=20Cruz?= <balvarez@boxfish.studio> Date: Fri, 29 Nov 2024 13:48:21 +0100 Subject: [PATCH 24/36] fix(explorer): validator info event query (#4307) --- apps/core/src/hooks/useGetValidatorsEvents.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/core/src/hooks/useGetValidatorsEvents.ts b/apps/core/src/hooks/useGetValidatorsEvents.ts index c0511d73aae..7be52ae4227 100644 --- a/apps/core/src/hooks/useGetValidatorsEvents.ts +++ b/apps/core/src/hooks/useGetValidatorsEvents.ts @@ -12,7 +12,7 @@ type GetValidatorsEvent = { // NOTE: This copies the query limit from our Rust JSON RPC backend, this needs to be kept in sync! const QUERY_MAX_RESULT_LIMIT = 50; -const VALIDATORS_EVENTS_QUERY = '0x3::validator_set::ValidatorEpochInfoEventV2'; +const VALIDATORS_EVENTS_QUERY = '0x3::validator_set::ValidatorEpochInfoEventV1'; //TODO: get validatorEvents by validator address export function useGetValidatorsEvents({ limit, order }: GetValidatorsEvent) { From 5494cff825325e79e9828963c3b9d4c8ed7b29a5 Mon Sep 17 00:00:00 2001 From: Marc Espin <mespinsanz@gmail.com> Date: Fri, 29 Nov 2024 16:51:12 +0100 Subject: [PATCH 25/36] refactor(tooling): Split Theme into `Theme` and `ThemePreference` (#4239) * refactor(tooling): Split Theme into `Theme` and `ThemePreference` * fmt * fixes * fix: Avoid setting the preference to system on every load * typo * fmt * fix explorer * chore: Add `iota-` prefixes to theme localstorage key in dashboard and wallet * fix: Proper loading reactivity --------- Co-authored-by: evavirseda <evirseda@boxfish.studio> --- .../components/providers/ThemeProvider.tsx | 86 +++++++++++++------ apps/core/src/contexts/ThemeContext.tsx | 8 +- apps/core/src/enums/theme.enums.ts | 5 ++ .../src/components/header/ThemeSwitcher.tsx | 39 ++------- .../app/(protected)/layout.tsx | 11 ++- apps/wallet-dashboard/app/page.tsx | 6 +- .../staking-overview/StartStaking.tsx | 1 + .../providers/AppProviders.tsx | 2 +- .../components/menu/content/ThemeSettings.tsx | 10 +-- .../menu/content/WalletSettingsMenuList.tsx | 4 +- apps/wallet/src/ui/index.tsx | 2 +- 11 files changed, 96 insertions(+), 78 deletions(-) diff --git a/apps/core/src/components/providers/ThemeProvider.tsx b/apps/core/src/components/providers/ThemeProvider.tsx index 43a65cfa558..c69bbf78e13 100644 --- a/apps/core/src/components/providers/ThemeProvider.tsx +++ b/apps/core/src/components/providers/ThemeProvider.tsx @@ -1,8 +1,8 @@ // Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { PropsWithChildren, useState, useEffect, useCallback } from 'react'; -import { Theme } from '../../enums'; +import { PropsWithChildren, useState, useEffect } from 'react'; +import { Theme, ThemePreference } from '../../enums'; import { ThemeContext } from '../../contexts'; interface ThemeProviderProps { @@ -12,40 +12,72 @@ interface ThemeProviderProps { export function ThemeProvider({ children, appId }: PropsWithChildren<ThemeProviderProps>) { const storageKey = `theme_${appId}`; - const getSystemTheme = () => - window.matchMedia('(prefers-color-scheme: dark)').matches ? Theme.Dark : Theme.Light; + const getSystemTheme = () => { + return window.matchMedia('(prefers-color-scheme: dark)').matches ? Theme.Dark : Theme.Light; + }; - const getInitialTheme = () => { - if (typeof window === 'undefined') { - return Theme.System; - } else { - const storedTheme = localStorage?.getItem(storageKey); - return storedTheme ? (storedTheme as Theme) : Theme.System; - } + const getThemePreference = () => { + const storedTheme = localStorage?.getItem(storageKey) as ThemePreference | null; + return storedTheme ? storedTheme : ThemePreference.System; }; - const [theme, setTheme] = useState<Theme>(getInitialTheme); + const [systemTheme, setSystemTheme] = useState<Theme>(Theme.Light); + const [themePreference, setThemePreference] = useState<ThemePreference>(ThemePreference.System); + const [isLoadingPreference, setIsLoadingPreference] = useState(true); - const applyTheme = useCallback((currentTheme: Theme) => { - const selectedTheme = currentTheme === Theme.System ? getSystemTheme() : currentTheme; - const documentElement = document.documentElement.classList; - documentElement.toggle(Theme.Dark, selectedTheme === Theme.Dark); - documentElement.toggle(Theme.Light, selectedTheme === Theme.Light); + // Load the theme values on client + useEffect(() => { + if (typeof window === 'undefined') return; + + setSystemTheme(getSystemTheme()); + setThemePreference(getThemePreference()); + + // Make the theme preference listener wait + // until the preference is loaded in the next render + setIsLoadingPreference(false); }, []); + // When the theme preference changes.. useEffect(() => { - if (typeof window === 'undefined') return; + if (typeof window === 'undefined' || isLoadingPreference) return; + + // Update localStorage with the new preference + localStorage.setItem(storageKey, themePreference); - localStorage.setItem(storageKey, theme); - applyTheme(theme); + // In case of SystemPreference, listen for system theme changes + if (themePreference === ThemePreference.System) { + const handleSystemThemeChange = () => { + const systemTheme = getSystemTheme(); + setSystemTheme(systemTheme); + }; + const systemThemeMatcher = window.matchMedia('(prefers-color-scheme: dark)'); + systemThemeMatcher.addEventListener('change', handleSystemThemeChange); + return () => systemThemeMatcher.removeEventListener('change', handleSystemThemeChange); + } + }, [themePreference, storageKey, isLoadingPreference]); - if (theme === Theme.System) { - const systemTheme = window.matchMedia('(prefers-color-scheme: dark)'); - const handleSystemThemeChange = () => applyTheme(Theme.System); - systemTheme.addEventListener('change', handleSystemThemeChange); - return () => systemTheme.removeEventListener('change', handleSystemThemeChange); + // Derive the active theme from the preference + const theme = (() => { + switch (themePreference) { + case ThemePreference.Dark: + return Theme.Dark; + case ThemePreference.Light: + return Theme.Light; + case ThemePreference.System: + return systemTheme; } - }, [theme, applyTheme, storageKey]); + })(); + + // When the theme (preference or derived) changes update the CSS class + useEffect(() => { + const documentElement = document.documentElement.classList; + documentElement.toggle(Theme.Dark, theme === Theme.Dark); + documentElement.toggle(Theme.Light, theme === Theme.Light); + }, [theme]); - return <ThemeContext.Provider value={{ theme, setTheme }}>{children}</ThemeContext.Provider>; + return ( + <ThemeContext.Provider value={{ theme, setThemePreference, themePreference }}> + {children} + </ThemeContext.Provider> + ); } diff --git a/apps/core/src/contexts/ThemeContext.tsx b/apps/core/src/contexts/ThemeContext.tsx index 3406e50d5c1..b24c0de824d 100644 --- a/apps/core/src/contexts/ThemeContext.tsx +++ b/apps/core/src/contexts/ThemeContext.tsx @@ -2,14 +2,16 @@ // SPDX-License-Identifier: Apache-2.0 import { createContext } from 'react'; -import { Theme } from '../enums'; +import { Theme, ThemePreference } from '../enums'; export interface ThemeContextType { theme: Theme; - setTheme: (theme: Theme) => void; + themePreference: ThemePreference; + setThemePreference: (theme: ThemePreference) => void; } export const ThemeContext = createContext<ThemeContextType>({ theme: Theme.Light, - setTheme: () => {}, + themePreference: ThemePreference.System, + setThemePreference: () => {}, }); diff --git a/apps/core/src/enums/theme.enums.ts b/apps/core/src/enums/theme.enums.ts index 2df40a61af4..1225b1eb403 100644 --- a/apps/core/src/enums/theme.enums.ts +++ b/apps/core/src/enums/theme.enums.ts @@ -4,5 +4,10 @@ export enum Theme { Light = 'light', Dark = 'dark', +} + +export enum ThemePreference { + Light = 'light', + Dark = 'dark', System = 'system', } diff --git a/apps/explorer/src/components/header/ThemeSwitcher.tsx b/apps/explorer/src/components/header/ThemeSwitcher.tsx index d8dc4c2fb24..b947cafe76c 100644 --- a/apps/explorer/src/components/header/ThemeSwitcher.tsx +++ b/apps/explorer/src/components/header/ThemeSwitcher.tsx @@ -3,46 +3,21 @@ import { Button, ButtonType } from '@iota/apps-ui-kit'; import { DarkMode, LightMode } from '@iota/ui-icons'; -import { useEffect, useLayoutEffect } from 'react'; -import { useTheme, Theme } from '@iota/core'; +import { useTheme, Theme, ThemePreference } from '@iota/core'; export function ThemeSwitcher(): React.JSX.Element { - const { theme, setTheme } = useTheme(); + const { theme, themePreference, setThemePreference } = useTheme(); const ThemeIcon = theme === Theme.Dark ? DarkMode : LightMode; function handleOnClick(): void { - const newTheme = theme === Theme.Light ? Theme.Dark : Theme.Light; - setTheme(newTheme); - saveThemeToLocalStorage(newTheme); + const newTheme = + themePreference === ThemePreference.Light + ? ThemePreference.Dark + : ThemePreference.Light; + setThemePreference(newTheme); } - function saveThemeToLocalStorage(newTheme: Theme): void { - localStorage.setItem('theme', newTheme); - } - - function updateDocumentClass(theme: Theme): void { - document.documentElement.classList.toggle('dark', theme === Theme.Dark); - } - - useLayoutEffect(() => { - const storedTheme = localStorage.getItem('theme') as Theme | null; - if (storedTheme) { - setTheme(storedTheme); - updateDocumentClass(storedTheme); - } else { - const prefersDarkTheme = window.matchMedia('(prefers-color-scheme: dark)').matches; - const preferredTheme = prefersDarkTheme ? Theme.Dark : Theme.Light; - - setTheme(preferredTheme); - updateDocumentClass(preferredTheme); - } - }, []); - - useEffect(() => { - updateDocumentClass(theme); - }, [theme]); - return ( <Button type={ButtonType.Ghost} diff --git a/apps/wallet-dashboard/app/(protected)/layout.tsx b/apps/wallet-dashboard/app/(protected)/layout.tsx index 2ba32059a9b..11f91a62413 100644 --- a/apps/wallet-dashboard/app/(protected)/layout.tsx +++ b/apps/wallet-dashboard/app/(protected)/layout.tsx @@ -6,14 +6,17 @@ import { Notifications } from '@/components/index'; import React, { type PropsWithChildren } from 'react'; import { Button } from '@iota/apps-ui-kit'; import { Sidebar, TopNav } from './components'; -import { Theme, useTheme } from '@iota/core'; +import { ThemePreference, useTheme } from '@iota/core'; function DashboardLayout({ children }: PropsWithChildren): JSX.Element { - const { theme, setTheme } = useTheme(); + const { theme, themePreference, setThemePreference } = useTheme(); const toggleTheme = () => { - const newTheme = theme === Theme.Light ? Theme.Dark : Theme.Light; - setTheme(newTheme); + const newTheme = + themePreference === ThemePreference.Light + ? ThemePreference.Dark + : ThemePreference.Light; + setThemePreference(newTheme); }; return ( diff --git a/apps/wallet-dashboard/app/page.tsx b/apps/wallet-dashboard/app/page.tsx index 7626f88bb2c..c96c01faec9 100644 --- a/apps/wallet-dashboard/app/page.tsx +++ b/apps/wallet-dashboard/app/page.tsx @@ -31,14 +31,14 @@ function HomeDashboardPage(): JSX.Element { <main className="flex h-screen"> <div className="relative hidden sm:flex md:w-1/3"> <video + key={theme} + src={videoSrc} autoPlay muted loop className="absolute right-0 top-0 h-full w-full min-w-fit object-cover" disableRemotePlayback - > - <source src={videoSrc} type="video/mp4" /> - </video> + ></video> </div> <div className="flex h-full w-full flex-col items-center justify-between p-md sm:p-2xl"> <IotaLogoWeb width={130} height={32} /> diff --git a/apps/wallet-dashboard/components/staking-overview/StartStaking.tsx b/apps/wallet-dashboard/components/staking-overview/StartStaking.tsx index 4496fd485a8..bbf9d7a77a7 100644 --- a/apps/wallet-dashboard/components/staking-overview/StartStaking.tsx +++ b/apps/wallet-dashboard/components/staking-overview/StartStaking.tsx @@ -47,6 +47,7 @@ export function StartStaking() { </div> <div className="relative w-full overflow-hidden"> <video + key={videoSrc} src={videoSrc} autoPlay loop diff --git a/apps/wallet-dashboard/providers/AppProviders.tsx b/apps/wallet-dashboard/providers/AppProviders.tsx index 69b2cebb513..f6712288174 100644 --- a/apps/wallet-dashboard/providers/AppProviders.tsx +++ b/apps/wallet-dashboard/providers/AppProviders.tsx @@ -36,7 +36,7 @@ export function AppProviders({ children }: React.PropsWithChildren) { }, ]} > - <ThemeProvider appId="dashboard"> + <ThemeProvider appId="iota-dashboard"> <PopupProvider> {children} <Toaster /> diff --git a/apps/wallet/src/ui/app/components/menu/content/ThemeSettings.tsx b/apps/wallet/src/ui/app/components/menu/content/ThemeSettings.tsx index 42b14994da6..6d016fbdb4d 100644 --- a/apps/wallet/src/ui/app/components/menu/content/ThemeSettings.tsx +++ b/apps/wallet/src/ui/app/components/menu/content/ThemeSettings.tsx @@ -2,24 +2,24 @@ // SPDX-License-Identifier: Apache-2.0 import { RadioButton } from '@iota/apps-ui-kit'; -import { Theme, useTheme } from '@iota/core'; +import { ThemePreference, useTheme } from '@iota/core'; import { Overlay } from '_components'; import { useNavigate } from 'react-router-dom'; export function ThemeSettings() { - const { theme, setTheme } = useTheme(); + const { themePreference, setThemePreference } = useTheme(); const navigate = useNavigate(); return ( <Overlay showModal title="Theme" closeOverlay={() => navigate('/')} showBackButton> <div className="flex w-full flex-col"> - {Object.entries(Theme).map(([key, value]) => ( + {Object.entries(ThemePreference).map(([key, value]) => ( <div className="px-md" key={value}> <RadioButton label={key} - isChecked={theme === value} - onChange={() => setTheme(value)} + isChecked={themePreference === value} + onChange={() => setThemePreference(value)} /> </div> ))} diff --git a/apps/wallet/src/ui/app/components/menu/content/WalletSettingsMenuList.tsx b/apps/wallet/src/ui/app/components/menu/content/WalletSettingsMenuList.tsx index 51ab79d6a45..d2a5da8f49c 100644 --- a/apps/wallet/src/ui/app/components/menu/content/WalletSettingsMenuList.tsx +++ b/apps/wallet/src/ui/app/components/menu/content/WalletSettingsMenuList.tsx @@ -31,7 +31,7 @@ import { ampli } from '_src/shared/analytics/ampli'; import { useTheme, getCustomNetwork } from '@iota/core'; function MenuList() { - const { theme } = useTheme(); + const { themePreference } = useTheme(); const navigate = useNavigate(); const activeAccount = useActiveAccount(); const networkUrl = useNextMenuUrl(true, '/network'); @@ -84,7 +84,7 @@ function MenuList() { } const autoLockSubtitle = handleAutoLockSubtitle(); - const themeSubtitle = theme.charAt(0).toUpperCase() + theme.slice(1); + const themeSubtitle = themePreference.charAt(0).toUpperCase() + themePreference.slice(1); const MENU_ITEMS = [ { title: 'Network', diff --git a/apps/wallet/src/ui/index.tsx b/apps/wallet/src/ui/index.tsx index 8598908f346..f3ef312b1c3 100644 --- a/apps/wallet/src/ui/index.tsx +++ b/apps/wallet/src/ui/index.tsx @@ -96,7 +96,7 @@ function AppWrapper() { > <KioskClientProvider> <AccountsFormProvider> - <ThemeProvider appId="wallet"> + <ThemeProvider appId="iota-wallet"> <UnlockAccountProvider> <div className={cn( From 32dca2736623b4e8b60853af8e771bea94b88d96 Mon Sep 17 00:00:00 2001 From: Hans Moog <3293976+hmoog@users.noreply.github.com> Date: Mon, 2 Dec 2024 08:17:22 +0000 Subject: [PATCH 26/36] fix(docker): grafana local config + private network (#4299) * fixed grafana local config + private network * Make grafana-local compatible with iota-private-network * Use external network * Update prometheus.yaml * Make grafana-local compatible with iota-private-network * Add README.md * Format files --------- Co-authored-by: Hans Moog <hmoog@users.noreply.github.com> Co-authored-by: Piotr Macek <4007944+piotrm50@users.noreply.github.com> --- docker/grafana-local/README.md | 7 +++++ docker/grafana-local/docker-compose.yaml | 14 +++++++++ docker/grafana-local/prometheus.yaml | 36 ++++++++++++++---------- 3 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 docker/grafana-local/README.md diff --git a/docker/grafana-local/README.md b/docker/grafana-local/README.md new file mode 100644 index 00000000000..ca46614ea00 --- /dev/null +++ b/docker/grafana-local/README.md @@ -0,0 +1,7 @@ +# Prometheus and Grafana monitoring for `iota-private-network` + +This docker-compose configuration allows launching instances of the Prometheus and Grafana applications for monitoring of locally deployed `iota-private-network`. + +In order to run this monitoring setup, you first need to have `iota-private-network` setup running, because it creates the network that Prometheus and Grafana join. + +To deploy the setup, simply run `docker compose up -d`. diff --git a/docker/grafana-local/docker-compose.yaml b/docker/grafana-local/docker-compose.yaml index 8e8a71e18a6..1ad59567d55 100644 --- a/docker/grafana-local/docker-compose.yaml +++ b/docker/grafana-local/docker-compose.yaml @@ -6,6 +6,8 @@ services: volumes: - ./tempo.yaml:/etc/tempo.yaml - ${TMPDIR}/tempo-data:/tmp/tempo + networks: + iota-network: ports: - "14268:14268" # jaeger ingest - "3200:3200" # tempo @@ -20,13 +22,19 @@ services: - --config.file=/etc/prometheus.yaml - --web.enable-remote-write-receiver - --enable-feature=exemplar-storage + networks: + iota-network: volumes: - ./prometheus.yaml:/etc/prometheus.yaml ports: - "9090:9090" + extra_hosts: + - "host.docker.internal:host-gateway" grafana: image: grafana/grafana:10.1.1 + networks: + iota-network: volumes: - ./grafana-datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml - ./dashboards:/etc/grafana/provisioning/dashboards @@ -42,6 +50,8 @@ services: image: prom/node-exporter:latest container_name: node-exporter restart: unless-stopped + networks: + iota-network: volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro @@ -53,3 +63,7 @@ services: - "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)" ports: - "9100:9100" +networks: + iota-network: + external: + name: iota-private-network_iota-network diff --git a/docker/grafana-local/prometheus.yaml b/docker/grafana-local/prometheus.yaml index 9192a853a3d..93bd06973b5 100644 --- a/docker/grafana-local/prometheus.yaml +++ b/docker/grafana-local/prometheus.yaml @@ -5,53 +5,59 @@ global: scrape_configs: - job_name: "prometheus" static_configs: - - targets: ["localhost:9090", "host.docker.internal:9184"] + - targets: ["localhost:9090"] - job_name: "Validator_0" static_configs: - - targets: ["host.docker.internal:2002"] + - targets: ["validator-1:9184"] labels: host: validator0 network: local - job_name: "Validator_1" static_configs: - - targets: ["host.docker.internal:2012"] + - targets: ["validator-2:9184"] labels: host: validator1 network: local - job_name: "Validator_2" static_configs: - - targets: ["host.docker.internal:2022"] + - targets: ["validator-3:9184"] labels: host: validator2 network: local - job_name: "Validator_3" static_configs: - - targets: ["host.docker.internal:2032"] + - targets: ["validator-4:9184"] labels: host: validator3 network: local - - job_name: "Client_1" + - job_name: "Fullnode_0" static_configs: - - targets: ["host.docker.internal:8081"] + - targets: ["fullnode-1:9184"] labels: - host: client1 + host: fullnode0 network: local - - job_name: "Client_2" + - job_name: "Fullnode_1" static_configs: - - targets: ["host.docker.internal:8082"] + - targets: ["fullnode-2:9184"] labels: - host: client2 + host: fullnode1 network: local - - job_name: "Client_3" + - job_name: "Fullnode_2" static_configs: - - targets: ["host.docker.internal:8083"] + - targets: ["fullnode-3:9184"] labels: - host: client3 + host: fullnode2 + network: local + - job_name: "Fullnode_3" + static_configs: + - targets: ["fullnode-4:9184"] + labels: + host: fullnode3 network: local - job_name: "tempo" static_configs: - targets: ["tempo:3200"] - - job_name: "node" + - job_name: "node-exporter" static_configs: - targets: ["host.docker.internal:9100"] labels: From f3388e13d30345f35c39bdd4bbbfe20c2c39cef5 Mon Sep 17 00:00:00 2001 From: Sergiu Popescu <44298302+sergiupopescu199@users.noreply.github.com> Date: Mon, 2 Dec 2024 12:59:34 +0100 Subject: [PATCH 27/36] Fix: Cannot find rates for staking pool (#4313) * fix(iota-json-rpc): include candidate validators * fix(iota-indexer): include candidate validators * fix(iota-graphql-rpc): include candidate validators * fixup! fix(iota-graphql-rpc): include candidate validators * Update crates/iota-indexer/src/apis/governance_api.rs Co-authored-by: Samuel Rufinatscha <samuel.rufinatscha@iota.org> * Update crates/iota-indexer/src/apis/governance_api.rs Co-authored-by: Samuel Rufinatscha <samuel.rufinatscha@iota.org> * refactor(iota-json-rpc): add utility function and split functions better * refactor(iota-indexer, iota-graphql-rpc): add utility function and split functions better * fixup! refactor(iota-json-rpc): add utility function and split functions better * fixup! refactor(iota-indexer, iota-graphql-rpc): add utility function and split functions better * Update crates/iota-json-rpc/src/governance_api.rs Co-authored-by: Konstantinos Demartinos <konstantinos.demartinos@iota.org> * Update crates/iota-json-rpc/src/governance_api.rs Co-authored-by: Konstantinos Demartinos <konstantinos.demartinos@iota.org> * fix(iota-json-rpc, iota-indexer): fix doc test --------- Co-authored-by: Samuel Rufinatscha <samuel.rufinatscha@iota.org> Co-authored-by: Konstantinos Demartinos <konstantinos.demartinos@iota.org> --- .../src/server/exchange_rates_task.rs | 4 +- .../iota-graphql-rpc/src/types/validator.rs | 36 ++- .../iota-indexer/src/apis/governance_api.rs | 298 ++++++++++++------ crates/iota-json-rpc/src/governance_api.rs | 214 ++++++++++--- 4 files changed, 397 insertions(+), 155 deletions(-) diff --git a/crates/iota-graphql-rpc/src/server/exchange_rates_task.rs b/crates/iota-graphql-rpc/src/server/exchange_rates_task.rs index 10c69cf90d8..d39d8f3597c 100644 --- a/crates/iota-graphql-rpc/src/server/exchange_rates_task.rs +++ b/crates/iota-graphql-rpc/src/server/exchange_rates_task.rs @@ -2,7 +2,7 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use iota_indexer::apis::{GovernanceReadApi, governance_api::exchange_rates}; +use iota_indexer::apis::GovernanceReadApi; use tokio::sync::watch; use tokio_util::sync::CancellationToken; use tracing::{error, info}; @@ -48,7 +48,7 @@ impl TriggerExchangeRatesTask { if let Ok(latest_iota_system_state) = latest_iota_system_state { let db = self.db.clone(); let governance_api = GovernanceReadApi::new(db.inner) ; - exchange_rates(&governance_api, &latest_iota_system_state) + governance_api.exchange_rates( &latest_iota_system_state) .await .map_err(|e| error!("Failed to fetch exchange rates: {:?}", e)) .ok(); diff --git a/crates/iota-graphql-rpc/src/types/validator.rs b/crates/iota-graphql-rpc/src/types/validator.rs index 5da4992d84c..7d70342693f 100644 --- a/crates/iota-graphql-rpc/src/types/validator.rs +++ b/crates/iota-graphql-rpc/src/types/validator.rs @@ -9,7 +9,8 @@ use async_graphql::{ dataloader::Loader, *, }; -use iota_indexer::apis::{GovernanceReadApi, governance_api::exchange_rates}; +use futures::TryFutureExt; +use iota_indexer::apis::GovernanceReadApi; use iota_json_rpc::governance_api::median_apy_from_exchange_rates; use iota_types::{ base_types::IotaAddress as NativeIotaAddress, @@ -37,6 +38,7 @@ use crate::{ validator_credentials::ValidatorCredentials, }, }; + #[derive(Clone, Debug)] pub(crate) struct Validator { pub validator_summary: NativeIotaValidatorSummary, @@ -75,20 +77,30 @@ impl Loader<u64> for Db { .map_err(|_| Error::Internal("Failed to fetch latest Iota system state".to_string()))?; let governance_api = GovernanceReadApi::new(self.inner.clone()); - let pending_validators_exchange_rate = governance_api - .pending_validators_exchange_rate() - .await - .map_err(|e| { - Error::Internal(format!( - "Error fetching pending validators exchange rates. {e}" - )) - })?; - - let mut exchange_rates = exchange_rates(&governance_api, &latest_iota_system_state) + let (candidate_rates, pending_rates) = tokio::try_join!( + governance_api + .candidate_validators_exchange_rate(&latest_iota_system_state) + .map_err(|e| { + Error::Internal(format!( + "Error fetching candidate validators exchange rates. {e}" + )) + }), + governance_api + .pending_validators_exchange_rate() + .map_err(|e| { + Error::Internal(format!( + "Error fetching pending validators exchange rates. {e}" + )) + }) + )?; + + let mut exchange_rates = governance_api + .exchange_rates(&latest_iota_system_state) .await .map_err(|e| Error::Internal(format!("Error fetching exchange rates. {e}")))?; - exchange_rates.extend(pending_validators_exchange_rate.into_iter()); + exchange_rates.extend(candidate_rates.into_iter()); + exchange_rates.extend(pending_rates.into_iter()); let mut results = BTreeMap::new(); diff --git a/crates/iota-indexer/src/apis/governance_api.rs b/crates/iota-indexer/src/apis/governance_api.rs index e82247cbf5c..44a4f51c947 100644 --- a/crates/iota-indexer/src/apis/governance_api.rs +++ b/crates/iota-indexer/src/apis/governance_api.rs @@ -2,7 +2,7 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use std::{collections::BTreeMap, sync::Arc}; +use std::{collections::BTreeMap, fmt::Debug, sync::Arc}; use async_trait::async_trait; use cached::{Cached, SizedCache}; @@ -15,14 +15,18 @@ use iota_json_rpc_types::{ }; use iota_open_rpc::Module; use iota_types::{ + MoveTypeTagTrait, base_types::{IotaAddress, MoveObjectType, ObjectID}, committee::EpochId, + dynamic_field::DynamicFieldInfo, governance::StakedIota, + id::ID, iota_serde::BigInt, iota_system_state::{PoolTokenExchangeRate, iota_system_state_summary::IotaSystemStateSummary}, timelock::timelocked_staked_iota::TimelockedStakedIota, }; use jsonrpsee::{RpcModule, core::RpcResult}; +use serde::{Serialize, de::DeserializeOwned}; use tokio::sync::Mutex; use crate::{errors::IndexerError, indexer_reader::IndexerReader}; @@ -30,6 +34,8 @@ use crate::{errors::IndexerError, indexer_reader::IndexerReader}; /// Maximum amount of staked objects for querying. const MAX_QUERY_STAKED_OBJECTS: usize = 1000; +type ValidatorTable = (IotaAddress, ObjectID, ObjectID, u64, bool); + #[derive(Clone)] pub struct GovernanceReadApi<T: R2D2Connection + 'static> { inner: IndexerReader<T>, @@ -62,7 +68,7 @@ impl<T: R2D2Connection + 'static> GovernanceReadApi<T> { self.get_latest_iota_system_state().await?; let epoch = system_state_summary.epoch; - let exchange_rate_table = exchange_rates(self, &system_state_summary).await?; + let exchange_rate_table = self.exchange_rates(&system_state_summary).await?; let apys = iota_json_rpc::governance_api::calculate_apys(exchange_rate_table); @@ -167,10 +173,17 @@ impl<T: R2D2Connection + 'static> GovernanceReadApi<T> { let system_state_summary = self.get_latest_iota_system_state().await?; let epoch = system_state_summary.epoch; - let rates = exchange_rates(self, &system_state_summary) + let (candidate_rates, pending_rates) = tokio::try_join!( + self.candidate_validators_exchange_rate(&system_state_summary), + self.pending_validators_exchange_rate() + )?; + + let rates = self + .exchange_rates(&system_state_summary) .await? .into_iter() - .chain(self.pending_validators_exchange_rate().await?.into_iter()) + .chain(candidate_rates.into_iter()) + .chain(pending_rates.into_iter()) .map(|rates| (rates.pool_id, rates)) .collect::<BTreeMap<_, _>>(); @@ -226,7 +239,8 @@ impl<T: R2D2Connection + 'static> GovernanceReadApi<T> { let system_state_summary = self.get_latest_iota_system_state().await?; let epoch = system_state_summary.epoch; - let rates = exchange_rates(self, &system_state_summary) + let rates = self + .exchange_rates(&system_state_summary) .await? .into_iter() .map(|rates| (rates.pool_id, rates)) @@ -294,10 +308,10 @@ impl<T: R2D2Connection + 'static> GovernanceReadApi<T> { ret } - // Get validator exchange rates + /// Get validator exchange rates async fn validator_exchange_rates( &self, - tables: Vec<(IotaAddress, ObjectID, ObjectID, u64, bool)>, + tables: Vec<ValidatorTable>, ) -> Result<Vec<ValidatorExchangeRates>, IndexerError> { if tables.is_empty() { return Ok(vec![]); @@ -337,7 +351,90 @@ impl<T: R2D2Connection + 'static> GovernanceReadApi<T> { Ok(exchange_rates) } - /// Check if there is any pending validator and get its exchange rates + /// Caches exchange rates for validators for the given epoch, the cache size + /// is 1, it will be cleared when the epoch changes. Rates are in + /// descending order by epoch. + pub async fn exchange_rates( + &self, + system_state_summary: &IotaSystemStateSummary, + ) -> Result<Vec<ValidatorExchangeRates>, IndexerError> { + let epoch = system_state_summary.epoch; + + let mut cache = self.exchange_rates_cache.lock().await; + + // Check if the exchange rates for the current epoch are cached + if let Some(cached_rates) = cache.cache_get(&epoch) { + return Ok(cached_rates.clone()); + } + + // Cache miss: compute exchange rates + let exchange_rates = self.compute_exchange_rates(system_state_summary).await?; + + // Store in cache + cache.cache_set(epoch, exchange_rates.clone()); + + Ok(exchange_rates) + } + + /// Compute Exchange Rates for Active & Inactive validators + async fn compute_exchange_rates( + &self, + system_state_summary: &IotaSystemStateSummary, + ) -> Result<Vec<ValidatorExchangeRates>, IndexerError> { + let (active_rates, inactive_rates) = tokio::try_join!( + self.active_validators_exchange_rate(system_state_summary), + self.inactive_validators_exchange_rate(system_state_summary) + )?; + + Ok(active_rates + .into_iter() + .chain(inactive_rates.into_iter()) + .collect()) + } + + /// Check for validators in the `Active` state and get its exchange rate + async fn active_validators_exchange_rate( + &self, + system_state_summary: &IotaSystemStateSummary, + ) -> Result<Vec<ValidatorExchangeRates>, IndexerError> { + let tables = system_state_summary + .active_validators + .iter() + .map(|validator| { + ( + validator.iota_address, + validator.staking_pool_id, + validator.exchange_rates_id, + validator.exchange_rates_size, + true, + ) + }) + .collect(); + + self.validator_exchange_rates(tables).await + } + + /// Check for validators in the `Inactive` state and get its exchange rate + async fn inactive_validators_exchange_rate( + &self, + system_state_summary: &IotaSystemStateSummary, + ) -> Result<Vec<ValidatorExchangeRates>, IndexerError> { + let tables = self + .validator_summary_from_system_state( + system_state_summary.inactive_pools_id, + system_state_summary.inactive_pools_size, + |df| bcs::from_bytes::<ID>(&df.bcs_name).map_err(Into::into), + ) + .await?; + + self.validator_exchange_rates(tables).await + } + + /// Check for validators in the `Pending` state and get its exchange rate. + /// For these validators, their exchange rates should not be cached as + /// their state can occur during an epoch or across multiple ones. In + /// contrast, exchange rates for `Active` and `Inactive` validators can + /// be cached, as their state changes only at epoch change. pub async fn pending_validators_exchange_rate( &self, ) -> Result<Vec<ValidatorExchangeRates>, IndexerError> { @@ -356,10 +453,113 @@ impl<T: R2D2Connection + 'static> GovernanceReadApi<T> { false, ) }) - .collect::<Vec<(IotaAddress, ObjectID, ObjectID, u64, bool)>>(); + .collect::<Vec<ValidatorTable>>(); self.validator_exchange_rates(tables).await } + + /// Check for validators in the `Candidate` state and get its exchange rate. + /// For these validators, their exchange rates should not be cached as + /// their state can occur during an epoch or across multiple ones. In + /// contrast, exchange rates for `Active` and `Inactive` validators can + /// be cached, as their state changes only at epoch change. + pub async fn candidate_validators_exchange_rate( + &self, + system_state_summary: &IotaSystemStateSummary, + ) -> Result<Vec<ValidatorExchangeRates>, IndexerError> { + let tables = self + .validator_summary_from_system_state( + system_state_summary.validator_candidates_id, + system_state_summary.validator_candidates_size, + |df| bcs::from_bytes::<IotaAddress>(&df.bcs_name).map_err(Into::into), + ) + .await?; + + self.validator_exchange_rates(tables).await + } + + /// Fetches validator status information from `StateRead`. + /// + /// This makes sense for validators not included in + /// `IotaSystemStateSummary`. `IotaSystemStateSummary` only contains + /// information about `Active` validators. To retrieve information about + /// `Inactive`, `Candidate`, and `Pending` validators, we need to access + /// dynamic fields within specific Move tables. + /// + /// To retrieve validator status information, this function utilizes the + /// corresponding `table_id` (an `ObjectID` value) and a `limit` to specify + /// the number of records to fetch. Both the `table_id` and `limit` can + /// be obtained from `IotaSystemStateSummary` in the caller. + /// Additionally, keys are extracted from the table `DynamicFieldInfo` + /// values according to the `key` closure. This helps in identifying the + /// specific validator within the table. + /// + /// # Example + /// + /// ```text + /// // Get inactive validators + /// let system_state_summary = self.get_latest_iota_system_state().await?; + /// let _ = self.validator_summary_from_system_state( + /// // ID of the object that maps from a staking pool ID to the inactive validator that has that pool as its staking pool + /// system_state_summary.inactive_pools_id, + /// // Number of inactive staking pools + /// system_state_summary.inactive_pools_size, + /// // Extract the `ID` of the `Inactive` validator from the `DynamicFieldInfo` in the `system_state_summary.inactive_pools_id` table + /// |df| bcs::from_bytes::<ID>(&df.bcs_name).map_err(Into::into), + /// ).await?; + /// ``` + /// + /// # Example + /// + /// ```text + /// // Get candidate validators + /// let system_state_summary = self.get_latest_iota_system_state().await?; + /// let _ = self.validator_summary_from_system_state( + /// // ID of the object that stores preactive validators, mapping their addresses to their Validator structs + /// system_state_summary.validator_candidates_id, + /// // Number of preactive validators + /// system_state_summary.validator_candidates_size, + /// // Extract the `IotaAddress` of the `Candidate` validator from the `DynamicFieldInfo` in the `system_state_summary.validator_candidates_id` table + /// |df| bcs::from_bytes::<IotaAddress>(&df.bcs_name).map_err(Into::into), + /// ).await?; + /// ``` + async fn validator_summary_from_system_state<K, F>( + &self, + table_id: ObjectID, + validator_size: u64, + key: F, + ) -> Result<Vec<ValidatorTable>, IndexerError> + where + F: Fn(DynamicFieldInfo) -> Result<K, IndexerError>, + K: MoveTypeTagTrait + Serialize + DeserializeOwned + Debug + Send + 'static, + { + let dynamic_fields = self + .inner + .get_dynamic_fields_in_blocking_task(table_id, None, validator_size as usize) + .await?; + + let mut tables = Vec::with_capacity(dynamic_fields.len()); + + for df in dynamic_fields { + let key = key(df)?; + let validator_candidate = self + .inner + .spawn_blocking(move |this| { + iota_types::iota_system_state::get_validator_from_table(&this, table_id, &key) + }) + .await?; + + tables.push(( + validator_candidate.iota_address, + validator_candidate.staking_pool_id, + validator_candidate.exchange_rates_id, + validator_candidate.exchange_rates_size, + false, + )); + } + + Ok(tables) + } } fn stake_status( @@ -388,86 +588,6 @@ fn stake_status( } } -/// Cached exchange rates for validators for the given epoch, the cache size is -/// 1, it will be cleared when the epoch changes. rates are in descending order -/// by epoch. -pub async fn exchange_rates( - state: &GovernanceReadApi<impl R2D2Connection>, - system_state_summary: &IotaSystemStateSummary, -) -> Result<Vec<ValidatorExchangeRates>, IndexerError> { - let epoch = system_state_summary.epoch; - - let mut cache = state.exchange_rates_cache.lock().await; - - // Check if the exchange rates for the current epoch are cached - if let Some(cached_rates) = cache.cache_get(&epoch) { - return Ok(cached_rates.clone()); - } - - // Cache miss: compute exchange rates - let exchange_rates = compute_exchange_rates(state, system_state_summary).await?; - - // Store in cache - cache.cache_set(epoch, exchange_rates.clone()); - - Ok(exchange_rates) -} - -pub async fn compute_exchange_rates( - state: &GovernanceReadApi<impl R2D2Connection>, - system_state_summary: &IotaSystemStateSummary, -) -> Result<Vec<ValidatorExchangeRates>, IndexerError> { - // Get validator rate tables - let mut tables = vec![]; - - for validator in &system_state_summary.active_validators { - tables.push(( - validator.iota_address, - validator.staking_pool_id, - validator.exchange_rates_id, - validator.exchange_rates_size, - true, - )); - } - - // Get inactive validator rate tables - for df in state - .inner - .get_dynamic_fields_in_blocking_task( - system_state_summary.inactive_pools_id, - None, - system_state_summary.inactive_pools_size as usize, - ) - .await? - { - let pool_id: iota_types::id::ID = bcs::from_bytes(&df.bcs_name).map_err(|e| { - iota_types::error::IotaError::ObjectDeserialization { - error: e.to_string(), - } - })?; - let inactive_pools_id = system_state_summary.inactive_pools_id; - let validator = state - .inner - .spawn_blocking(move |this| { - iota_types::iota_system_state::get_validator_from_table( - &this, - inactive_pools_id, - &pool_id, - ) - }) - .await?; - tables.push(( - validator.iota_address, - validator.staking_pool_id, - validator.exchange_rates_id, - validator.exchange_rates_size, - false, - )); - } - - state.validator_exchange_rates(tables).await -} - #[async_trait] impl<T: R2D2Connection + 'static> GovernanceReadApiServer for GovernanceReadApi<T> { async fn get_stakes_by_ids( diff --git a/crates/iota-json-rpc/src/governance_api.rs b/crates/iota-json-rpc/src/governance_api.rs index e4ad229134c..9b06df2f513 100644 --- a/crates/iota-json-rpc/src/governance_api.rs +++ b/crates/iota-json-rpc/src/governance_api.rs @@ -2,7 +2,7 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use std::{cmp::max, collections::BTreeMap, sync::Arc}; +use std::{cmp::max, collections::BTreeMap, fmt::Debug, sync::Arc}; use async_trait::async_trait; use cached::{SizedCache, proc_macro::cached}; @@ -17,9 +17,10 @@ use iota_json_rpc_types::{ use iota_metrics::spawn_monitored_task; use iota_open_rpc::Module; use iota_types::{ + MoveTypeTagTrait, base_types::{IotaAddress, ObjectID}, committee::EpochId, - dynamic_field::get_dynamic_field_from_store, + dynamic_field::{DynamicFieldInfo, get_dynamic_field_from_store}, error::{IotaError, UserInputError}, governance::StakedIota, id::ID, @@ -33,6 +34,7 @@ use iota_types::{ }; use itertools::Itertools; use jsonrpsee::{RpcModule, core::RpcResult}; +use serde::{Serialize, de::DeserializeOwned}; use statrs::statistics::{Data, Median}; use tracing::{info, instrument}; @@ -42,6 +44,9 @@ use crate::{ error::{Error, IotaRpcInputError, RpcInterimResult}, logger::FutureWithTracing as _, }; + +type ValidatorTable = (IotaAddress, ObjectID, ObjectID, u64, bool); + #[derive(Clone)] pub struct GovernanceReadApi { state: Arc<dyn StateRead>, @@ -198,8 +203,10 @@ impl GovernanceReadApi { let rates = exchange_rates(&self.state, system_state_summary.epoch) .await? .into_iter() - // Try to find for any pending active validator - .chain(pending_validator_exchange_rate(&self.state)?.into_iter()) + // Try to find for any candidate validator exchange rate + .chain(candidate_validators_exchange_rate(&self.state)?.into_iter()) + // Try to find for any pending validator exchange rate + .chain(pending_validators_exchange_rate(&self.state)?.into_iter()) .map(|rates| (rates.pool_id, rates)) .collect::<BTreeMap<_, _>>(); @@ -527,54 +534,16 @@ async fn exchange_rates( state: &Arc<dyn StateRead>, _current_epoch: EpochId, ) -> RpcInterimResult<Vec<ValidatorExchangeRates>> { - let system_state = state.get_system_state()?; - let system_state_summary: IotaSystemStateSummary = - system_state.into_iota_system_state_summary(); - - // Get validator rate tables - let mut tables = vec![]; - - for validator in system_state_summary.active_validators { - tables.push(( - validator.iota_address, - validator.staking_pool_id, - validator.exchange_rates_id, - validator.exchange_rates_size, - true, - )); - } - - // Get inactive validator rate tables - for df in state.get_dynamic_fields( - system_state_summary.inactive_pools_id, - None, - system_state_summary.inactive_pools_size as usize, - )? { - let pool_id: ID = - bcs::from_bytes(&df.1.bcs_name).map_err(|e| IotaError::ObjectDeserialization { - error: e.to_string(), - })?; - let validator = get_validator_from_table( - state.get_object_store().as_ref(), - system_state_summary.inactive_pools_id, - &pool_id, - )?; // TODO(wlmyng): roll this into StateReadError - tables.push(( - validator.iota_address, - validator.staking_pool_id, - validator.exchange_rates_id, - validator.exchange_rates_size, - false, - )); - } - - validator_exchange_rates(state, tables) + Ok(active_validators_exchange_rates(state)? + .into_iter() + .chain(inactive_validators_exchange_rates(state)?.into_iter()) + .collect()) } /// Get validator exchange rates fn validator_exchange_rates( state: &Arc<dyn StateRead>, - tables: Vec<(IotaAddress, ObjectID, ObjectID, u64, bool)>, + tables: Vec<ValidatorTable>, ) -> RpcInterimResult<Vec<ValidatorExchangeRates>> { if tables.is_empty() { return Ok(vec![]); @@ -586,8 +555,8 @@ fn validator_exchange_rates( let mut rates = state .get_dynamic_fields(exchange_rates_id, None, exchange_rates_size as usize)? .into_iter() - .map(|df| { - let epoch: EpochId = bcs::from_bytes(&df.1.bcs_name).map_err(|e| { + .map(|(_object_id, df)| { + let epoch: EpochId = bcs::from_bytes(&df.bcs_name).map_err(|e| { IotaError::ObjectDeserialization { error: e.to_string(), } @@ -616,8 +585,51 @@ fn validator_exchange_rates( Ok(exchange_rates) } -/// Check if there is any pending validator and get its exchange rates -fn pending_validator_exchange_rate( +/// Check for validators in the `Active` state and get its exchange rate +fn active_validators_exchange_rates( + state: &Arc<dyn StateRead>, +) -> RpcInterimResult<Vec<ValidatorExchangeRates>> { + let system_state_summary = state.get_system_state()?.into_iota_system_state_summary(); + + let tables = system_state_summary + .active_validators + .into_iter() + .map(|validator| { + ( + validator.iota_address, + validator.staking_pool_id, + validator.exchange_rates_id, + validator.exchange_rates_size, + true, + ) + }) + .collect(); + + validator_exchange_rates(state, tables) +} + +/// Check for validators in the `Inactive` state and get its exchange rate +fn inactive_validators_exchange_rates( + state: &Arc<dyn StateRead>, +) -> RpcInterimResult<Vec<ValidatorExchangeRates>> { + let system_state_summary = state.get_system_state()?.into_iota_system_state_summary(); + + let tables = validator_summary_from_system_state( + state, + system_state_summary.inactive_pools_id, + system_state_summary.inactive_pools_size, + |df| bcs::from_bytes::<ID>(&df.bcs_name).map_err(Into::into), + )?; + + validator_exchange_rates(state, tables) +} + +/// Check for validators in the `Pending` state and get its exchange rate. For +/// these validators, their exchange rates should not be cached as their state +/// can occur during an epoch or across multiple ones. In contrast, exchange +/// rates for `Active` and `Inactive` validators can be cached, as their state +/// changes only at epoch change. +fn pending_validators_exchange_rate( state: &Arc<dyn StateRead>, ) -> RpcInterimResult<Vec<ValidatorExchangeRates>> { let system_state = state.get_system_state()?; @@ -636,10 +648,108 @@ fn pending_validator_exchange_rate( false, ) }) - .collect::<Vec<(IotaAddress, ObjectID, ObjectID, u64, bool)>>(); + .collect::<Vec<ValidatorTable>>(); validator_exchange_rates(state, tables) } + +/// Check for validators in the `Candidate` state and get its exchange rate. For +/// these validators, their exchange rates should not be cached as their state +/// can occur during an epoch or across multiple ones. In contrast, exchange +/// rates for `Active` and `Inactive` validators can be cached, as their state +/// changes only at epoch change. +fn candidate_validators_exchange_rate( + state: &Arc<dyn StateRead>, +) -> RpcInterimResult<Vec<ValidatorExchangeRates>> { + let system_state_summary = state.get_system_state()?.into_iota_system_state_summary(); + + // From validator_candidates_id table get validator info using as key its + // IotaAddress + let tables = validator_summary_from_system_state( + state, + system_state_summary.validator_candidates_id, + system_state_summary.validator_candidates_size, + |df| bcs::from_bytes::<IotaAddress>(&df.bcs_name).map_err(Into::into), + )?; + + validator_exchange_rates(state, tables) +} + +/// Fetches validator status information from `StateRead`. +/// +/// This makes sense for validators not included in `IotaSystemStateSummary`. +/// `IotaSystemStateSummary` only contains information about `Active` +/// validators. To retrieve information about `Inactive`, `Candidate`, and +/// `Pending` validators, we need to access dynamic fields within specific +/// Move tables. +/// +/// To retrieve validator status information, this function utilizes the +/// corresponding `table_id` (an `ObjectID` value) and a `limit` to specify the +/// number of records to fetch. Both the `table_id` and `limit` can be obtained +/// from `IotaSystemStateSummary` in the caller. Additionally, keys are +/// extracted from the table `DynamicFieldInfo` values according to the `key` +/// closure. This helps in identifying the specific validator within the table. +/// +/// # Example +/// +/// ```text +/// // Get inactive validators +/// let system_state_summary = state.get_system_state()?.into_iota_system_state_summary(); +/// let _ = validator_summary_from_system_state( +/// state, +/// // ID of the object that maps from a staking pool ID to the inactive validator that has that pool as its staking pool. +/// system_state_summary.inactive_pools_id, +/// // Number of inactive staking pools. +/// system_state_summary.inactive_pools_size, +/// // Extract the `ID` of the `Inactive` validator from the `DynamicFieldInfo` in the `system_state_summary.inactive_pools_id` table +/// |df| bcs::from_bytes::<ID>(&df.bcs_name).map_err(Into::into), +/// ).unwrap(); +/// ``` +/// +/// # Example +/// +/// ```text +/// // Get candidate validators +/// let system_state_summary = state.get_system_state()?.into_iota_system_state_summary(); +/// let _ = validator_summary_from_system_state( +/// state, +/// // ID of the object that stores preactive validators, mapping their addresses to their Validator structs +/// system_state_summary.validator_candidates_id, +/// // Number of preactive validators +/// system_state_summary.validator_candidates_size, +/// // Extract the `IotaAddress` of the `Candidate` validator from the `DynamicFieldInfo` in the `system_state_summary.validator_candidates_id` table +/// |df| bcs::from_bytes::<IotaAddress>(&df.bcs_name).map_err(Into::into), +/// ).unwrap(); +/// ``` +fn validator_summary_from_system_state<K, F>( + state: &Arc<dyn StateRead>, + table_id: ObjectID, + limit: u64, + key: F, +) -> RpcInterimResult<Vec<ValidatorTable>> +where + F: Fn(DynamicFieldInfo) -> RpcInterimResult<K>, + K: MoveTypeTagTrait + Serialize + DeserializeOwned + Debug, +{ + let object_store = state.get_object_store(); + + state + .get_dynamic_fields(table_id, None, limit as usize)? + .into_iter() + .map(|(_object_id, df)| { + let validator_summary = get_validator_from_table(object_store, table_id, &key(df)?)?; + + Ok(( + validator_summary.iota_address, + validator_summary.staking_pool_id, + validator_summary.exchange_rates_id, + validator_summary.exchange_rates_size, + false, + )) + }) + .collect() +} + #[derive(Clone, Debug)] pub struct ValidatorExchangeRates { pub address: IotaAddress, From 92619057be345a7fbf4f698fb13f6296297c517c Mon Sep 17 00:00:00 2001 From: Thibault Martinez <thibault@iota.org> Date: Mon, 2 Dec 2024 15:29:55 +0100 Subject: [PATCH 28/36] feat(ci): PR team labeler (#4318) * feat(ci): PR team labeler * fmt * tmp use pull_request * ignore hornet * revert pull_request_target * rename to TEAM_LABELER_TOKEN * revert to pull_request_target --- .github/workflows/labeler.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index b58d4fefc37..02ed863940c 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,16 +1,25 @@ name: Pull Request Labeler -on: - - pull_request_target +on: pull_request_target jobs: triage: permissions: contents: read pull-requests: write - runs-on: self-hosted + runs-on: ubuntu-latest steps: - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # pin@v5 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" + + team-label: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: equitybee/team-label-action@732147c0a9129eb90b16261d14860954fe5ce42a # v1.0.3 + with: + repo-token: ${{ secrets.TEAM_LABELER_TOKEN }} + organization-name: iotaledger + ignore-labels: devs, iota-foundation, iota-sdk, hornet From a284e0ef66ef3fdde2155c1e2f4c52791be0ba13 Mon Sep 17 00:00:00 2001 From: Thibault Martinez <thibault@iota.org> Date: Tue, 3 Dec 2024 09:55:01 +0100 Subject: [PATCH 29/36] chore(ci): clean version pin comments (#4317) * chore(ci): clean version pin comments * labeler --- .github/actions/diffs/action.yml | 4 +- .github/actions/turbo-diffs/action.yml | 6 +-- .github/workflows/_cargo_deny.yml | 4 +- .github/workflows/_docs_lint.yml | 4 +- .github/workflows/_docusaurus.yml | 6 +-- .github/workflows/_e2e.yml | 10 ++-- .github/workflows/_execution_cut.yml | 6 +-- .github/workflows/_external_rust_tests.yml | 6 +-- .github/workflows/_ledgernano.yml | 6 +-- .github/workflows/_move_ide.yml | 12 ++--- .github/workflows/_move_tests.yml | 4 +- .github/workflows/_rust.yml | 8 ++-- .github/workflows/_rust_lints.yml | 8 ++-- .github/workflows/_rust_tests.yml | 22 ++++----- .github/workflows/_turborepo.yml | 18 +++---- .github/workflows/_typos.yml | 4 +- .github/workflows/apps_backend_deploy.yml | 10 ++-- .github/workflows/apps_explorer_deploy.yml | 10 ++-- .github/workflows/apps_ui_kit_deploy.yml | 8 ++-- .../apps_wallet_dashboard_deploy.yml | 10 ++-- .../workflows/apps_wallet_nightly_build.yml | 10 ++-- .github/workflows/apps_wallet_prod_build.yml | 12 ++--- .github/workflows/apps_wallet_rc_build.yml | 10 ++-- .github/workflows/build_nightly.yml | 6 +-- .github/workflows/changesets.yml | 8 ++-- .github/workflows/changesets_ci.yml | 10 ++-- .github/workflows/changesets_ci_comment.yml | 8 ++-- .github/workflows/changesets_publish.yml | 6 +-- .github/workflows/crate_docs.yml | 6 +-- .github/workflows/develop_ci_slack_report.yml | 2 +- .github/workflows/hierarchy.yml | 6 +-- .github/workflows/labeler.yml | 6 +-- .github/workflows/links_checker.yml | 8 ++-- .github/workflows/nightly.yml | 4 +- .github/workflows/preview_wiki.yml | 8 ++-- .github/workflows/release.yml | 14 +++--- .github/workflows/release_docker.yml | 48 +++++++++---------- .github/workflows/release_notes_monitor.yml | 6 +-- .github/workflows/release_wiki.yml | 6 +-- .github/workflows/simulator_nightly.yml | 12 ++--- .github/workflows/split_cluster.yml | 4 +- .github/workflows/stale.yml | 2 +- .github/workflows/tag.yml | 4 +- 43 files changed, 186 insertions(+), 186 deletions(-) diff --git a/.github/actions/diffs/action.yml b/.github/actions/diffs/action.yml index ac54e779fdd..c7bc240b392 100644 --- a/.github/actions/diffs/action.yml +++ b/.github/actions/diffs/action.yml @@ -20,9 +20,9 @@ outputs: runs: using: composite steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Detect Changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # pin@v3 + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: diff with: filters: | diff --git a/.github/actions/turbo-diffs/action.yml b/.github/actions/turbo-diffs/action.yml index 5ecf523d527..60e9302aca9 100644 --- a/.github/actions/turbo-diffs/action.yml +++ b/.github/actions/turbo-diffs/action.yml @@ -7,11 +7,11 @@ outputs: runs: using: composite steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 0 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 - - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" - id: changes diff --git a/.github/workflows/_cargo_deny.yml b/.github/workflows/_cargo_deny.yml index 911cdca4016..aab5dac50a3 100644 --- a/.github/workflows/_cargo_deny.yml +++ b/.github/workflows/_cargo_deny.yml @@ -17,12 +17,12 @@ jobs: name: cargo deny (bans, licenses, sources) runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - run: cargo deny --manifest-path ${{ inputs.manifest-path || './Cargo.toml' }} check bans licenses sources advisories: name: cargo deny (advisories) runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - run: cargo deny --manifest-path ${{ inputs.manifest-path || './Cargo.toml' }} check advisories diff --git a/.github/workflows/_docs_lint.yml b/.github/workflows/_docs_lint.yml index 58435476537..35314d3f409 100644 --- a/.github/workflows/_docs_lint.yml +++ b/.github/workflows/_docs_lint.yml @@ -12,8 +12,8 @@ jobs: runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Spell Check Docs - uses: crate-ci/typos@945d407a5fc9097f020969446a16f581612ab4df # pin@v1.24.5 + uses: crate-ci/typos@945d407a5fc9097f020969446a16f581612ab4df # v1.24.5 with: files: ./docs/content diff --git a/.github/workflows/_docusaurus.yml b/.github/workflows/_docusaurus.yml index b62d6eb2f32..e13b4f0e13b 100644 --- a/.github/workflows/_docusaurus.yml +++ b/.github/workflows/_docusaurus.yml @@ -12,12 +12,12 @@ jobs: runs-on: self-hosted steps: - name: Checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" diff --git a/.github/workflows/_e2e.yml b/.github/workflows/_e2e.yml index 21cccf3a81c..c68e7efb83f 100644 --- a/.github/workflows/_e2e.yml +++ b/.github/workflows/_e2e.yml @@ -48,11 +48,11 @@ jobs: ports: - 5432:5432 steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - run: cargo build --bin iota --features indexer --profile dev - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" @@ -89,7 +89,7 @@ jobs: - name: Run Explorer e2e tests if: inputs.isTypescriptSDK || inputs.isExplorer || inputs.isRust || github.ref_name == 'develop' run: pnpm --filter iota-explorer playwright test - - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4 + - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if: always() with: name: playwright-report-explorer @@ -115,7 +115,7 @@ jobs: if: inputs.isWallet || inputs.isRust || inputs.isTypescriptSDK || github.ref_name == 'develop' run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- pnpm --filter iota-wallet playwright test - - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4 + - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if: always() with: name: playwright-report-wallet diff --git a/.github/workflows/_execution_cut.yml b/.github/workflows/_execution_cut.yml index 14cf87f9679..9c231940a39 100644 --- a/.github/workflows/_execution_cut.yml +++ b/.github/workflows/_execution_cut.yml @@ -11,13 +11,13 @@ jobs: name: cutting a new execution layer runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install cargo-hakari, and cache the binary - uses: baptiste0928/cargo-install@904927dbe77864e0f2281519fe9d5bd097a220b3 # pin@v3 + uses: baptiste0928/cargo-install@904927dbe77864e0f2281519fe9d5bd097a220b3 # v3.1.1 with: crate: cargo-hakari locked: true - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Make cut run: ./scripts/execution_layer.py cut for_ci_test - name: Check execution builds diff --git a/.github/workflows/_external_rust_tests.yml b/.github/workflows/_external_rust_tests.yml index 015ff4b7676..e787b85f668 100644 --- a/.github/workflows/_external_rust_tests.yml +++ b/.github/workflows/_external_rust_tests.yml @@ -27,8 +27,8 @@ jobs: IOTA_SKIP_SIMTESTS: 1 runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # pin@v2 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # v2.44.38 with: tool: nextest - name: Install python dependencies @@ -70,6 +70,6 @@ jobs: runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Run Cargo Udeps run: cargo +nightly ci-udeps-external ${{ matrix.flags }} diff --git a/.github/workflows/_ledgernano.yml b/.github/workflows/_ledgernano.yml index 0d9484caf47..316714d376e 100644 --- a/.github/workflows/_ledgernano.yml +++ b/.github/workflows/_ledgernano.yml @@ -11,11 +11,11 @@ jobs: name: Ledgernano runs-on: self-hosted steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4.0.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: "20" cache: "pnpm" diff --git a/.github/workflows/_move_ide.yml b/.github/workflows/_move_ide.yml index 5878489c9aa..d6fba17c64c 100644 --- a/.github/workflows/_move_ide.yml +++ b/.github/workflows/_move_ide.yml @@ -13,12 +13,12 @@ jobs: steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: ref: ${{ github.event.inputs.iota_repo_ref || github.ref }} - name: Setup Node - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: "20" @@ -37,12 +37,12 @@ jobs: steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: ref: ${{ github.event.inputs.iota_repo_ref || github.ref }} - name: Setup Node - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: "20" @@ -78,12 +78,12 @@ jobs: steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: ref: ${{ github.event.inputs.iota_repo_ref || github.ref }} - name: Setup Node - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: "20" diff --git a/.github/workflows/_move_tests.yml b/.github/workflows/_move_tests.yml index b2c2be4b930..a98c7ad8f3f 100644 --- a/.github/workflows/_move_tests.yml +++ b/.github/workflows/_move_tests.yml @@ -20,8 +20,8 @@ jobs: timeout-minutes: 10 runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # pin@v2 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # v2.44.38 with: tool: nextest - name: Run move tests diff --git a/.github/workflows/_rust.yml b/.github/workflows/_rust.yml index da0c28dc2da..f95a7642424 100644 --- a/.github/workflows/_rust.yml +++ b/.github/workflows/_rust.yml @@ -44,8 +44,8 @@ jobs: outputs: components: ${{ steps.filter.outputs.changes }} steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # pin@v3 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: filter with: list-files: "json" @@ -57,8 +57,8 @@ jobs: outputs: components: ${{ steps.filter.outputs.changes }} steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # pin@v3 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: filter with: list-files: "json" diff --git a/.github/workflows/_rust_lints.yml b/.github/workflows/_rust_lints.yml index e42b1b1eb76..43410a38234 100644 --- a/.github/workflows/_rust_lints.yml +++ b/.github/workflows/_rust_lints.yml @@ -21,7 +21,7 @@ jobs: if: (!cancelled() && inputs.isRust) runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install latest nightly run: rustup toolchain install nightly --component rustfmt --allow-downgrade - name: Check Rust formatting @@ -31,7 +31,7 @@ jobs: if: (!cancelled() && inputs.isRust) runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Check Cargo.toml format and sorting run: | pushd "scripts/cargo_sort" @@ -51,11 +51,11 @@ jobs: - rustfmt runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 # TODO(bradh): debug and re-enable this; the caching is breaking the clippy build # Enable caching of the 'librocksdb-sys' crate by additionally caching the # 'librocksdb-sys' src directory which is managed by cargo - # - uses: bmwill/rust-cache@v1 # Fork of 'Swatinem/rust-cache' which allows caching additional paths + # - uses: bmwill/rust-cache@cb2cf0cc7c5198d3364b9630e2c3d457f160790c # v1.4.0 # Fork of 'Swatinem/rust-cache' which allows caching additional paths # with: # path: ~/.cargo/registry/src/**/librocksdb-sys-* diff --git a/.github/workflows/_rust_tests.yml b/.github/workflows/_rust_tests.yml index 7b2857f27fc..5b18626d2ac 100644 --- a/.github/workflows/_rust_tests.yml +++ b/.github/workflows/_rust_tests.yml @@ -36,8 +36,8 @@ jobs: IOTA_SKIP_SIMTESTS: 1 runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # pin@v2 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # v2.44.38 with: tool: nextest - name: cargo test @@ -72,7 +72,7 @@ jobs: runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Run Cargo Udeps run: cargo +nightly ci-udeps ${{ matrix.flags }} @@ -89,8 +89,8 @@ jobs: - [self-hosted] fail-fast: false steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # Pin v4 - - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # pin@v2 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # v2.44.38 with: tool: nextest - name: benchmark (smoke) @@ -103,7 +103,7 @@ jobs: run: | cargo doc --all-features --workspace --no-deps - name: Install cargo-hakari, and cache the binary - uses: baptiste0928/cargo-install@904927dbe77864e0f2281519fe9d5bd097a220b3 # pin@v3 + uses: baptiste0928/cargo-install@904927dbe77864e0f2281519fe9d5bd097a220b3 # v3.1.1 with: crate: cargo-hakari locked: true @@ -123,8 +123,8 @@ jobs: env: MSIM_WATCHDOG_TIMEOUT_MS: 60000 steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # pin@v2 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # v2.44.38 with: tool: nextest - name: setup filter @@ -164,7 +164,7 @@ jobs: # timeout-minutes: 45 # runs-on: [self-hosted] # steps: - # - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + # - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 # - name: Setup environment # run: .github/scripts/rosetta/setup.sh @@ -216,8 +216,8 @@ jobs: ports: - 5432:5432 steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # pin@v2 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # v2.44.38 with: tool: nextest - name: Install postgresql-client diff --git a/.github/workflows/_turborepo.yml b/.github/workflows/_turborepo.yml index 4e1742f79b1..7d4c7d6142b 100644 --- a/.github/workflows/_turborepo.yml +++ b/.github/workflows/_turborepo.yml @@ -12,10 +12,10 @@ jobs: runs-on: self-hosted steps: - name: Checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" - name: Run audit @@ -26,12 +26,12 @@ jobs: runs-on: self-hosted steps: - name: Checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" @@ -41,7 +41,7 @@ jobs: run: pnpm manypkg check - name: Turbo Cache id: turbo-cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: .turbo key: turbo-${{ runner.os }}-${{ github.sha }} @@ -50,7 +50,7 @@ jobs: - name: Lint run: pnpm turbo lint - name: Install wasm-pack for mbf package - uses: jetli/wasm-pack-action@0d096b08b4e5a7de8c28de67e11e945404e9eefa # pin@v0.4.0 + uses: jetli/wasm-pack-action@0d096b08b4e5a7de8c28de67e11e945404e9eefa # v0.4.0 with: version: "latest" - name: Build @@ -66,7 +66,7 @@ jobs: - name: Wallet Extension Preview Package if: steps.wallet-diff.outcome == 'failure' run: pnpm --filter iota-wallet pack:zip - - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4 + - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if: steps.wallet-diff.outcome == 'failure' with: name: wallet-extension diff --git a/.github/workflows/_typos.yml b/.github/workflows/_typos.yml index 05f6a69030f..1747c0ca15a 100644 --- a/.github/workflows/_typos.yml +++ b/.github/workflows/_typos.yml @@ -12,9 +12,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Actions Repository - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Check spelling - uses: crate-ci/typos@945d407a5fc9097f020969446a16f581612ab4df # pin@v1.24.5 + uses: crate-ci/typos@945d407a5fc9097f020969446a16f581612ab4df # v1.24.5 with: config: ./.typos.toml diff --git a/.github/workflows/apps_backend_deploy.yml b/.github/workflows/apps_backend_deploy.yml index 38c919e73f5..63c5b01a9e6 100644 --- a/.github/workflows/apps_backend_deploy.yml +++ b/.github/workflows/apps_backend_deploy.yml @@ -19,10 +19,10 @@ jobs: pull-requests: write runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" @@ -42,7 +42,7 @@ jobs: fi - name: Turbo Cache id: turbo-cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: node_modules/.cache/turbo key: turbo-${{ runner.os }}-${{ github.sha }} @@ -64,7 +64,7 @@ jobs: run: echo "DEPLOY_URL=$(cat vercel_output.txt | awk 'END{print}')" >> $GITHUB_OUTPUT - name: Comment on pull request if: ${{ inputs.isProd == false }} - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/apps_explorer_deploy.yml b/.github/workflows/apps_explorer_deploy.yml index 10badc709fc..0b57bb6b97c 100644 --- a/.github/workflows/apps_explorer_deploy.yml +++ b/.github/workflows/apps_explorer_deploy.yml @@ -30,10 +30,10 @@ jobs: pull-requests: write runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" @@ -53,7 +53,7 @@ jobs: fi - name: Turbo Cache id: turbo-cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: node_modules/.cache/turbo key: turbo-${{ runner.os }}-${{ github.sha }} @@ -80,7 +80,7 @@ jobs: run: vercel alias ${{ steps.deploy_url.outputs.DEPLOY_URL }} $EXPLORER_VERCEL_PROJECT_STAGING_URL --token=${{ secrets.VERCEL_TOKEN }} --scope=${{ secrets.VERCEL_SCOPE }} - name: Comment on pull request if: ${{ inputs.isProd == false && inputs.isStaging == false }} - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/apps_ui_kit_deploy.yml b/.github/workflows/apps_ui_kit_deploy.yml index bbb003fb875..3c2f4e753f5 100644 --- a/.github/workflows/apps_ui_kit_deploy.yml +++ b/.github/workflows/apps_ui_kit_deploy.yml @@ -19,10 +19,10 @@ jobs: pull-requests: write runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" @@ -54,7 +54,7 @@ jobs: run: echo "DEPLOY_URL=$(cat vercel_output.txt | awk 'END{print}')" >> $GITHUB_OUTPUT - name: Comment on pull request if: ${{ inputs.isProd == false }} - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/apps_wallet_dashboard_deploy.yml b/.github/workflows/apps_wallet_dashboard_deploy.yml index 97bd8ae6670..d3ae3f5f284 100644 --- a/.github/workflows/apps_wallet_dashboard_deploy.yml +++ b/.github/workflows/apps_wallet_dashboard_deploy.yml @@ -19,10 +19,10 @@ jobs: pull-requests: write runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" @@ -42,7 +42,7 @@ jobs: fi - name: Turbo Cache id: turbo-cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: node_modules/.cache/turbo key: turbo-${{ runner.os }}-${{ github.sha }} @@ -66,7 +66,7 @@ jobs: run: echo "DEPLOY_URL=$(cat vercel_output.txt | awk 'END{print}')" >> $GITHUB_OUTPUT - name: Comment on pull request if: ${{ inputs.isProd == false }} - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/apps_wallet_nightly_build.yml b/.github/workflows/apps_wallet_nightly_build.yml index 267b940df18..32c5e429273 100644 --- a/.github/workflows/apps_wallet_nightly_build.yml +++ b/.github/workflows/apps_wallet_nightly_build.yml @@ -25,10 +25,10 @@ jobs: export artifact_name="wallet-nightly-$(date -Idate)" echo "artifact_name=${artifact_name}" >> $GITHUB_ENV - name: Checking out - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" @@ -36,7 +36,7 @@ jobs: run: pnpm install --frozen-lockfile - name: Turbo Cache id: turbo-cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: node_modules/.cache/turbo key: turbo-${{ runner.os }}-${{ github.sha }} @@ -45,7 +45,7 @@ jobs: - name: Build Wallet run: pnpm wallet build:nightly - name: Upload artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ env.artifact_name }} path: | diff --git a/.github/workflows/apps_wallet_prod_build.yml b/.github/workflows/apps_wallet_prod_build.yml index 7fe6657ef78..3deb10ac329 100644 --- a/.github/workflows/apps_wallet_prod_build.yml +++ b/.github/workflows/apps_wallet_prod_build.yml @@ -19,10 +19,10 @@ jobs: runs-on: [self-hosted] steps: - name: Checking out the repository - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # pin@v3 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4.0.0 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: "20" cache: "pnpm" @@ -30,7 +30,7 @@ jobs: run: pnpm install --frozen-lockfile - name: get-npm-version id: package-version - uses: martinbeentjes/npm-get-version-action@3cf273023a0dda27efcd3164bdfb51908dd46a5b # pin@v1.3.1 + uses: martinbeentjes/npm-get-version-action@3cf273023a0dda27efcd3164bdfb51908dd46a5b # v1.3.1 with: path: apps/wallet - name: Create artifact name @@ -71,7 +71,7 @@ jobs: run: echo "::set-output name=version::${GITHUB_REF#refs/tags/wallet-v}" - name: Create GitHub Release - uses: elgohr/Github-Release-Action@c5ea99036abb741a89f8bf1f2cd7fba845e3313a # pin@v5 + uses: elgohr/Github-Release-Action@c5ea99036abb741a89f8bf1f2cd7fba845e3313a # v5.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -83,7 +83,7 @@ jobs: draft: true prerelease: false - name: Upload artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ env.artifact_name }} path: | diff --git a/.github/workflows/apps_wallet_rc_build.yml b/.github/workflows/apps_wallet_rc_build.yml index 625c6cbc23f..bfbf13ac1f3 100644 --- a/.github/workflows/apps_wallet_rc_build.yml +++ b/.github/workflows/apps_wallet_rc_build.yml @@ -21,10 +21,10 @@ jobs: runs-on: [self-hosted] steps: - name: Checking out ${{ env.iota_branch }} - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # pin@v3 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4.0.0 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: "20" cache: "pnpm" @@ -32,7 +32,7 @@ jobs: run: pnpm install --frozen-lockfile - name: get-npm-version id: package-version - uses: martinbeentjes/npm-get-version-action@3cf273023a0dda27efcd3164bdfb51908dd46a5b # pin@v1.3.1 + uses: martinbeentjes/npm-get-version-action@3cf273023a0dda27efcd3164bdfb51908dd46a5b # v1.3.1 with: path: apps/wallet - name: Create artifact name @@ -43,7 +43,7 @@ jobs: - name: Build Wallet run: pnpm wallet build:rc - name: Upload artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ env.artifact_name }} path: | diff --git a/.github/workflows/build_nightly.yml b/.github/workflows/build_nightly.yml index 15f9a91e015..23e1dd3c61f 100644 --- a/.github/workflows/build_nightly.yml +++ b/.github/workflows/build_nightly.yml @@ -53,7 +53,7 @@ jobs: echo "artifact_name=${artifact_name}" >> $GITHUB_ENV - name: Install Foundry - uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # pin@v1 + uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 - name: Install PostgreSQL library headers shell: bash @@ -69,7 +69,7 @@ jobs: echo "os_type=${system_os}-${arch}" >> $GITHUB_ENV - name: Checking out ${{ env.iota_branch }} - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: ${{ env.iota_branch }} @@ -79,7 +79,7 @@ jobs: [ -f ~/.cargo/env ] && source ~/.cargo/env ; cargo build --release --bin iota --bin iota-indexer --features indexer - name: Upload artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ env.artifact_name }} path: | diff --git a/.github/workflows/changesets.yml b/.github/workflows/changesets.yml index 73737505b89..6c01337fad6 100644 --- a/.github/workflows/changesets.yml +++ b/.github/workflows/changesets.yml @@ -14,19 +14,19 @@ jobs: runs-on: self-hosted steps: - name: checkout code repository - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 0 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" - name: Install dependencies run: pnpm install --frozen-lockfile - name: Create Release Pull Request - uses: changesets/action@f13b1baaa620fde937751f5d2c3572b9da32af23 # pin@v1 + uses: changesets/action@f13b1baaa620fde937751f5d2c3572b9da32af23 # v1.4.5 with: # Generates src/version.ts file using genVersion # https://github.com/changesets/action#with-version-script diff --git a/.github/workflows/changesets_ci.yml b/.github/workflows/changesets_ci.yml index 59449264009..ba30a3e6a97 100644 --- a/.github/workflows/changesets_ci.yml +++ b/.github/workflows/changesets_ci.yml @@ -10,12 +10,12 @@ jobs: runs-on: self-hosted steps: - name: checkout code repository - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 0 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" @@ -26,7 +26,7 @@ jobs: run: echo "hasChanges=$(pnpm list --filter "...[$(git rev-parse HEAD^1)]" --depth -1 --json | jq "any(.[] | select(.private != true) ; length > 0)")" >> $GITHUB_OUTPUT - name: Get changed files in the changesets folder id: has-changesets - uses: tj-actions/changed-files@c3a1bb2c992d77180ae65be6ae6c166cf40f857c # pin@v45 + uses: tj-actions/changed-files@c3a1bb2c992d77180ae65be6ae6c166cf40f857c # v45.0.3 with: files: | .changeset/** @@ -35,7 +35,7 @@ jobs: run: | echo "true" > missing-changeset.txt - name: Upload missing changeset artifact - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if: steps.has-changesets.outputs.any_changed != 'true' && steps.diff.outputs.hasChanges == 'true' with: name: missing-changeset diff --git a/.github/workflows/changesets_ci_comment.yml b/.github/workflows/changesets_ci_comment.yml index 5bdac435ed9..3deda7d99e4 100644 --- a/.github/workflows/changesets_ci_comment.yml +++ b/.github/workflows/changesets_ci_comment.yml @@ -16,14 +16,14 @@ jobs: github.event.workflow_run.conclusion == 'success' steps: - name: Get workflow run information - uses: potiuk/get-workflow-origin@c657bb36aef4a7402bbe9b2e09a820320f8ff447 # pin@v1 + uses: potiuk/get-workflow-origin@c657bb36aef4a7402bbe9b2e09a820320f8ff447 # v1.0.0 id: source-run-info with: token: ${{ secrets.GITHUB_TOKEN }} sourceRunId: ${{ github.event.workflow_run.id }} - name: "Download artifact" - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 id: get-artifact if: steps.source-run-info.outputs.pullRequestNumber with: @@ -46,7 +46,7 @@ jobs: return 'true'; - name: Comment PR - uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # pin@v2 + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 if: steps.get-artifact.outputs.result == 'true' && steps.source-run-info.outputs.pullRequestNumber with: pr_number: ${{ steps.source-run-info.outputs.pullRequestNumber }} @@ -58,7 +58,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Remove outdated comments - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 if: steps.get-artifact.outputs.result == 'false' && steps.source-run-info.outputs.pullRequestNumber env: ISSUE_NUMBER: ${{ steps.source-run-info.outputs.pullRequestNumber }} diff --git a/.github/workflows/changesets_publish.yml b/.github/workflows/changesets_publish.yml index 61d8bdf7870..42c0d958f58 100644 --- a/.github/workflows/changesets_publish.yml +++ b/.github/workflows/changesets_publish.yml @@ -10,12 +10,12 @@ jobs: runs-on: self-hosted steps: - name: checkout code repository - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 0 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: "20" cache: "pnpm" diff --git a/.github/workflows/crate_docs.yml b/.github/workflows/crate_docs.yml index 427fa9dea15..8fb8baf1d59 100644 --- a/.github/workflows/crate_docs.yml +++ b/.github/workflows/crate_docs.yml @@ -16,16 +16,16 @@ jobs: runs-on: self-hosted steps: - name: Checkout sources - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Generate documentation - uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # pin@v1.0.3 + uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # v1.0.1 with: command: doc args: --workspace --exclude "iota-benchmark" --no-deps - name: Deploy documentation - uses: peaceiris/actions-gh-pages@373f7f263a76c20808c831209c920827a82a2847 # pin@v3 + uses: peaceiris/actions-gh-pages@373f7f263a76c20808c831209c920827a82a2847 # v3.9.3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: gh-pages diff --git a/.github/workflows/develop_ci_slack_report.yml b/.github/workflows/develop_ci_slack_report.yml index b024aa65b33..1dc6c0561e1 100644 --- a/.github/workflows/develop_ci_slack_report.yml +++ b/.github/workflows/develop_ci_slack_report.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest if: github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'timed_out' steps: - - uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # pin@v2 + - uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # v2.5.0 with: status: ${{ github.event.workflow_run.conclusion }} notification_title: " ${{github.event.workflow_run.name}} - ${{github.event.workflow_run.conclusion}} on ${{github.event.workflow_run.head_branch}}" diff --git a/.github/workflows/hierarchy.yml b/.github/workflows/hierarchy.yml index 6456b3e033a..9c61f02a77d 100644 --- a/.github/workflows/hierarchy.yml +++ b/.github/workflows/hierarchy.yml @@ -32,7 +32,7 @@ jobs: isGraphQlTransport: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), '@iota/graphql-transport')) }} isLedgerjs: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), '@iota/ledgerjs-hw-app-iota')) }} steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Detect Changes (turbo) uses: "./.github/actions/turbo-diffs" id: turbo @@ -46,7 +46,7 @@ jobs: group: dprint-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Check dprint formatting run: dprint check @@ -62,7 +62,7 @@ jobs: if: (!cancelled() && needs.diff.outputs.isRust == 'true') runs-on: [self-hosted] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Run license check run: cargo ci-license diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 02ed863940c..096893042f8 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -9,15 +9,15 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # pin@v5 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" team-label: runs-on: ubuntu-latest steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - uses: equitybee/team-label-action@732147c0a9129eb90b16261d14860954fe5ce42a # v1.0.3 with: repo-token: ${{ secrets.TEAM_LABELER_TOKEN }} diff --git a/.github/workflows/links_checker.yml b/.github/workflows/links_checker.yml index 3d17cbeed50..96ee42b70a7 100644 --- a/.github/workflows/links_checker.yml +++ b/.github/workflows/links_checker.yml @@ -16,11 +16,11 @@ jobs: LYCHEE_OUT: ./lychee/links-report steps: ## Check out code using Git - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Check all links at *.md and doc files id: lychee - uses: lycheeverse/lychee-action@2b973e86fc7b1f6b36a93795fe2c9c6ae1118621 # pin@v1.10.0 + uses: lycheeverse/lychee-action@2b973e86fc7b1f6b36a93795fe2c9c6ae1118621 # v1.10.0 with: token: ${{ secrets.GITHUB_TOKEN }} output: ${{ env.LYCHEE_OUT }} @@ -38,14 +38,14 @@ jobs: './**/*.md' - name: Find the last report issue open - uses: micalevisk/last-issue-action@0d40124cc99ac8601c2516007f0c98ef3d27537b # pin@v2.3 + uses: micalevisk/last-issue-action@0d40124cc99ac8601c2516007f0c98ef3d27537b # v2.3.0 id: last-issue with: state: open labels: broken-links - name: Create or update report - uses: peter-evans/create-issue-from-file@e8ef132d6df98ed982188e460ebb3b5d4ef3a9cd # pin@v4 + uses: peter-evans/create-issue-from-file@e8ef132d6df98ed982188e460ebb3b5d4ef3a9cd # v5.0.1 with: title: Link checker report content-filepath: ${{ env.LYCHEE_OUT }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 60f3267e804..27268340ad9 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -51,10 +51,10 @@ jobs: run: | brew install postgresql - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: cargo build - uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # pin@v1.0.3 + uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # v1.0.1 with: command: build args: --all-targets --all-features --release diff --git a/.github/workflows/preview_wiki.yml b/.github/workflows/preview_wiki.yml index 9057346f314..fa9b9733b3a 100644 --- a/.github/workflows/preview_wiki.yml +++ b/.github/workflows/preview_wiki.yml @@ -24,15 +24,15 @@ jobs: runs-on: self-hosted if: github.event.pull_request.draft == false steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install pnpm - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 with: run_install: false - name: Set up Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: 20 cache: "pnpm" @@ -61,7 +61,7 @@ jobs: working-directory: ./docs/site - name: Update PR with Deployment URL - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d63f45ebb51..7addd9967a9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -64,7 +64,7 @@ jobs: echo "iota_version=${iota_version}" >> $GITHUB_ENV - name: Check out ${{ env.iota_tag }} - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: ${{ env.iota_tag }} @@ -96,11 +96,11 @@ jobs: - name: Setup caching # Fork of 'Swatinem/rust-cache' which allows caching additional paths - uses: bmwill/rust-cache@fb63fcd7a959767755b88b5af2f5cbf65fb8a127 # pin@v1 + uses: bmwill/rust-cache@cb2cf0cc7c5198d3364b9630e2c3d457f160790c # v1.4.0 - name: Install nexttest (Windows) if: ${{ matrix.os == 'windows-latest' }} - uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # pin@v2 + uses: taiki-e/install-action@375e0c7f08a66b8c2ba7e7eef31a6f91043a81b0 # v2.44.38 with: tool: nextest @@ -187,7 +187,7 @@ jobs: # choco push iota.${{ env.iota_version }}.nupkg --source https://push.chocolatey.org/ - name: Upload release artifacts for ${{ matrix.os }} platform - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: iota-binaries-${{ matrix.os }} if-no-files-found: error @@ -195,7 +195,7 @@ jobs: ./tmp/iota-${{ env.iota_tag }}-${{ env.os_type }}.tgz - name: Attach artifacts to ${{ env.iota_tag }} release in GH - uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # pin@v2 + uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8 with: tag_name: ${{ env.iota_tag }} files: | @@ -213,7 +213,7 @@ jobs: # run: | # echo "iota_tag=$(echo ${{ env.TAG_NAME }} | sed s/'refs\/tags\/'//)" >> $GITHUB_ENV # echo "versionless_tag=$(echo ${{ env.TAG_NAME }} | sed s/'refs\/tags\/'// | sed s/'testnet\-v'//)" >> $GITHUB_ENV -# - uses: mislav/bump-homebrew-formula-action@b3327118b2153c82da63fd9cbf58942146ee99f0 # pin@v3 +# - uses: mislav/bump-homebrew-formula-action@b3327118b2153c82da63fd9cbf58942146ee99f0 # v3.1.0 # with: # formula-name: iota # create-pullrequest: true @@ -233,7 +233,7 @@ jobs: # runs-on: ubuntu-latest # steps: # - name: Dispatch Tagging of images in DockerHub, in MystenLabs/sui-operations -# uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # pin@v3.0.0 +# uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3.0.0 # with: # repository: iotaledger/iota # token: ${{ secrets.DOCKER_BINARY_BUILDS_DISPATCH }} diff --git a/.github/workflows/release_docker.yml b/.github/workflows/release_docker.yml index 0a729c2e815..ba9cb957cad 100644 --- a/.github/workflows/release_docker.yml +++ b/.github/workflows/release_docker.yml @@ -33,17 +33,17 @@ jobs: environment: release steps: - name: Checkout code - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Set up QEMU - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # pin@v3 + uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # pin@v3 + uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 - name: Docker meta for iota-node id: meta-node - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # pin@v5 + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 with: images: iotaledger/iota-node # mapping semver tags to networks @@ -61,7 +61,7 @@ jobs: type=raw,value=mainnet,enable=${{ github.event_name == 'release' && !contains(github.ref, '-alpha') && !contains(github.ref, '-beta') && !contains(github.ref, '-rc') }} - name: Login to Docker Registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # pin@v3 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: username: ${{ secrets.DOCKER_REGISTRY_USERNAME }} password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }} @@ -74,7 +74,7 @@ jobs: echo "BUILD_DATE=$(date -u +'%Y-%m-%d')" >> $GITHUB_ENV - name: Build and push Docker image for iota-node - uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # pin@v6 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0 with: context: . file: docker/iota-node/Dockerfile @@ -92,17 +92,17 @@ jobs: environment: release steps: - name: Checkout code - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Set up QEMU - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # pin@v3 + uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # pin@v3 + uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 - name: Docker meta for iota-indexer id: meta-indexer - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # pin@v5 + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 with: images: iotaledger/iota-indexer # mapping semver tags to networks @@ -120,7 +120,7 @@ jobs: type=raw,value=mainnet,enable=${{ github.event_name == 'release' && !contains(github.ref, '-alpha') && !contains(github.ref, '-beta') && !contains(github.ref, '-rc') }} - name: Login to Docker Registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # pin@v3 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: username: ${{ secrets.DOCKER_REGISTRY_USERNAME }} password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }} @@ -133,7 +133,7 @@ jobs: echo "BUILD_DATE=$(date -u +'%Y-%m-%d')" >> $GITHUB_ENV - name: Build and push Docker image for iota-indexer - uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # pin@v6 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0 with: context: . file: docker/iota-indexer/Dockerfile @@ -151,17 +151,17 @@ jobs: environment: release steps: - name: Checkout code - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Set up QEMU - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # pin@v3 + uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # pin@v3 + uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 - name: Docker meta for iota-tools id: meta-tools - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # pin@v5 + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 with: images: iotaledger/iota-tools # mapping semver tags to networks @@ -179,7 +179,7 @@ jobs: type=raw,value=mainnet,enable=${{ github.event_name == 'release' && !contains(github.ref, '-alpha') && !contains(github.ref, '-beta') && !contains(github.ref, '-rc') }} - name: Login to Docker Registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # pin@v3 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: username: ${{ secrets.DOCKER_REGISTRY_USERNAME }} password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }} @@ -192,7 +192,7 @@ jobs: echo "BUILD_DATE=$(date -u +'%Y-%m-%d')" >> $GITHUB_ENV - name: Build and push Docker image for iota-tools - uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # pin@v6 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0 with: context: . file: docker/iota-tools/Dockerfile @@ -210,17 +210,17 @@ jobs: environment: release steps: - name: Checkout code - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Set up QEMU - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # pin@v3 + uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # pin@v3 + uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 - name: Docker meta for iota-graphql-rpc id: meta-tools - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # pin@v5 + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 with: images: iotaledger/iota-graphql-rpc # mapping semver tags to networks @@ -238,7 +238,7 @@ jobs: type=raw,value=mainnet,enable=${{ github.event_name == 'release' && !contains(github.ref, '-alpha') && !contains(github.ref, '-beta') && !contains(github.ref, '-rc') }} - name: Login to Docker Registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # pin@v3 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: username: ${{ secrets.DOCKER_REGISTRY_USERNAME }} password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }} @@ -251,7 +251,7 @@ jobs: echo "BUILD_DATE=$(date -u +'%Y-%m-%d')" >> $GITHUB_ENV - name: Build and push Docker image for iota-graphql-rpc - uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # pin@v6 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0 with: context: . file: docker/iota-graphql-rpc/Dockerfile diff --git a/.github/workflows/release_notes_monitor.yml b/.github/workflows/release_notes_monitor.yml index f19fc19bb40..c3c18d815f1 100644 --- a/.github/workflows/release_notes_monitor.yml +++ b/.github/workflows/release_notes_monitor.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout iota repo develop branch - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 0 ref: develop @@ -63,7 +63,7 @@ jobs: echo "release_notes=${rel_notes}" >> $GITHUB_ENV - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # pin@v4 + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} @@ -78,7 +78,7 @@ jobs: echo "slack_id=$(echo ${slack_id} | tr -d '"')" >> $GITHUB_ENV - name: Post to a Slack channel - uses: slackapi/slack-github-action@34c3fd73326693ef04728f8611669d918a2d781d # pin@v1.19.0 + uses: slackapi/slack-github-action@34c3fd73326693ef04728f8611669d918a2d781d # v1.19.0 env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} with: diff --git a/.github/workflows/release_wiki.yml b/.github/workflows/release_wiki.yml index a62173cd58a..84570f0c164 100644 --- a/.github/workflows/release_wiki.yml +++ b/.github/workflows/release_wiki.yml @@ -13,15 +13,15 @@ jobs: wiki-release: runs-on: self-hosted steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install pnpm - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 + uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 with: run_install: false - name: Set up Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: 20 cache: "pnpm" diff --git a/.github/workflows/simulator_nightly.yml b/.github/workflows/simulator_nightly.yml index 55c4ceeee16..234a9013788 100644 --- a/.github/workflows/simulator_nightly.yml +++ b/.github/workflows/simulator_nightly.yml @@ -35,12 +35,12 @@ jobs: steps: - name: Install Teleport - uses: teleport-actions/setup@176c25dfcd19cd31a252f275d579822b243e7b9c # pin@v1 + uses: teleport-actions/setup@176c25dfcd19cd31a252f275d579822b243e7b9c # v1.0.6 with: version: 11.3.1 - name: Authorize against Teleport id: auth - uses: teleport-actions/auth@685adaf480dc79262a99220eb158a92136d5abd9 # pin@v2 + uses: teleport-actions/auth@685adaf480dc79262a99220eb158a92136d5abd9 # v2.0.3 with: # Specify the publically accessible address of your Teleport proxy. proxy: proxy.iota-int.com:443 @@ -84,10 +84,10 @@ jobs: if: github.event_name == 'schedule' && failure() steps: - - uses: technote-space/workflow-conclusion-action@45ce8e0eb155657ab8ccf346ade734257fd196a5 # pin@v3 + - uses: technote-space/workflow-conclusion-action@45ce8e0eb155657ab8ccf346ade734257fd196a5 # v3.0.3 - name: Checkout iota repo develop branch - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Get iota commit env: @@ -122,7 +122,7 @@ jobs: echo "oncall_name=$(echo ${oncall_name})" >> $GITHUB_ENV - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # pin@v4 + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} @@ -134,7 +134,7 @@ jobs: echo "slack_id=$(echo ${slack_id} | tr -d '"')" >> $GITHUB_ENV - name: Post to slack - uses: slackapi/slack-github-action@37ebaef184d7626c5f204ab8d3baff4262dd30f0 # pin@v1 + uses: slackapi/slack-github-action@37ebaef184d7626c5f204ab8d3baff4262dd30f0 # v1.27.0 env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} IOTA_SHA: ${{ env.iota_sha }} diff --git a/.github/workflows/split_cluster.yml b/.github/workflows/split_cluster.yml index 31ce2cc9389..3c45c361d91 100644 --- a/.github/workflows/split_cluster.yml +++ b/.github/workflows/split_cluster.yml @@ -18,7 +18,7 @@ jobs: # runs-on: self-hosted # steps: # - name: Checkout code repository - # uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + # uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 # with: # fetch-depth: 0 # - name: Run split cluster check script @@ -31,7 +31,7 @@ jobs: runs-on: self-hosted steps: - name: Checkout code repository - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 0 - name: Run split cluster check script diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 35b73fe7bb7..f0c82a67fa7 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,7 +11,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # pin@v9 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 60 diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index 9063759a502..62b3c8d8943 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -36,10 +36,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Tag - uses: julbme/gh-action-manage-tag@8daf6387badea2c6b8f989bd0f82b5a9ef1d84e6 # pin@v1 + uses: julbme/gh-action-manage-tag@8daf6387badea2c6b8f989bd0f82b5a9ef1d84e6 # v1.0.1 with: name: ${{ env.TAG_NAME }} state: present From acc345d03eed8b566dafb12dc03d47f6d65eca7d Mon Sep 17 00:00:00 2001 From: Thibault Martinez <thibault@iota.org> Date: Tue, 3 Dec 2024 11:10:21 +0100 Subject: [PATCH 30/36] chore(ci): re-enable rosetta-validation (#3780) --- .github/workflows/_rust_tests.yml | 65 +++++++++++++++---------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/.github/workflows/_rust_tests.yml b/.github/workflows/_rust_tests.yml index 5b18626d2ac..da2303c56e4 100644 --- a/.github/workflows/_rust_tests.yml +++ b/.github/workflows/_rust_tests.yml @@ -159,39 +159,38 @@ jobs: eval ${command} - # # Disabled - # rosetta-validation: - # timeout-minutes: 45 - # runs-on: [self-hosted] - # steps: - # - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - - # - name: Setup environment - # run: .github/scripts/rosetta/setup.sh - # shell: bash - - # - name: Start local IOTA network - # run: | - # iota start --no-full-node & - # shell: bash - - # - name: Start Rosetta servers - # run: .github/scripts/rosetta/start_rosetta.sh - # shell: bash - - # - name: Sleep for 20 seconds - # run: sleep 20s - # shell: bash - - # - name: Run check:construction test - # run: | - # ./bin/rosetta-cli --configuration-file rosetta_cli.json check:construction - # shell: bash - - # - name: Run check:data test - # run: | - # ./bin/rosetta-cli --configuration-file rosetta_cli.json check:data - # shell: bash + rosetta-validation: + timeout-minutes: 45 + runs-on: [self-hosted] + steps: + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + + - name: Setup environment + run: .github/scripts/rosetta/setup.sh + shell: bash + + - name: Start local IOTA network + run: | + iota start --no-full-node & + shell: bash + + - name: Start Rosetta servers + run: .github/scripts/rosetta/start_rosetta.sh + shell: bash + + - name: Sleep for 20 seconds + run: sleep 20s + shell: bash + + - name: Run check:construction test + run: | + ./bin/rosetta-cli --configuration-file rosetta_cli.json check:construction + shell: bash + + - name: Run check:data test + run: | + ./bin/rosetta-cli --configuration-file rosetta_cli.json check:data + shell: bash graphql-rpc: name: graphql-rpc From e45e2a1265d617501203219e27322f4147726e19 Mon Sep 17 00:00:00 2001 From: Thibault Martinez <thibault@iota.org> Date: Tue, 3 Dec 2024 11:11:21 +0100 Subject: [PATCH 31/36] chore(ci): ignore boxfish from team-labeler (#4331) --- .github/workflows/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 096893042f8..c2931635e82 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -22,4 +22,4 @@ jobs: with: repo-token: ${{ secrets.TEAM_LABELER_TOKEN }} organization-name: iotaledger - ignore-labels: devs, iota-foundation, iota-sdk, hornet + ignore-labels: devs, iota-foundation, iota-sdk, hornet, boxfish From d12200cd20df50f7ad93db6bb0398c3eb20f93f1 Mon Sep 17 00:00:00 2001 From: evavirseda <evirseda@boxfish.studio> Date: Tue, 3 Dec 2024 15:42:41 +0100 Subject: [PATCH 32/36] feat(tooling): fix logo/avatar/icon image, move to core and cleanup debris (#4249) * feat: fix logo/avatar/icon image, move to core and cleanup debris * fix lint * fix import --- apps/core/src/components/coin/CoinIcon.tsx | 2 +- apps/core/src/components/icon/ImageIcon.tsx | 26 +++---- .../core/src/hooks/stake/useValidatorInfo.tsx | 1 - .../explorer/src/components/IotaTokenCard.tsx | 5 +- .../src/components/owned-coins/CoinIcon.tsx | 45 ----------- .../components/owned-coins/OwnedCoinView.tsx | 4 +- .../src/components/owned-coins/index.ts | 1 - apps/explorer/src/components/ui/ImageIcon.tsx | 75 ------------------- apps/explorer/src/components/ui/index.ts | 1 - .../components/validator/ValidatorMeta.tsx | 3 +- .../utils/generateValidatorsTableColumns.tsx | 18 +++-- .../transaction-summary/BalanceChanges.tsx | 3 +- .../transaction-summary/ObjectDisplay.tsx | 3 +- .../app/components/receipt-card/TxnAmount.tsx | 9 ++- 14 files changed, 38 insertions(+), 158 deletions(-) delete mode 100644 apps/explorer/src/components/owned-coins/CoinIcon.tsx delete mode 100644 apps/explorer/src/components/ui/ImageIcon.tsx diff --git a/apps/core/src/components/coin/CoinIcon.tsx b/apps/core/src/components/coin/CoinIcon.tsx index 1ced5642085..e5cd595c6cc 100644 --- a/apps/core/src/components/coin/CoinIcon.tsx +++ b/apps/core/src/components/coin/CoinIcon.tsx @@ -22,7 +22,7 @@ function NonIotaCoin({ coinType, size = ImageIconSize.Full, rounded }: NonIotaCo src={coinMeta?.iconUrl} label={coinMeta?.name || coinType} fallback={coinMeta?.name || coinType} - size={size} + size={coinMeta?.iconUrl ? ImageIconSize.Full : size} rounded={rounded} /> </div> diff --git a/apps/core/src/components/icon/ImageIcon.tsx b/apps/core/src/components/icon/ImageIcon.tsx index 3f1e76a6d31..6e71eba90cd 100644 --- a/apps/core/src/components/icon/ImageIcon.tsx +++ b/apps/core/src/components/icon/ImageIcon.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import React, { useState } from 'react'; +import { useState } from 'react'; import cn from 'clsx'; export enum ImageIconSize { @@ -43,7 +43,7 @@ function FallBackAvatar({ str, rounded, size = ImageIconSize.Large }: FallBackAv <div className={cn( 'flex h-full w-full items-center justify-center bg-neutral-96 bg-gradient-to-r capitalize text-neutral-10 dark:bg-neutral-12 dark:text-neutral-92', - { 'rounded-full': rounded }, + { 'rounded-full': rounded, 'rounded-lg': !rounded }, generateTextSize(size), )} > @@ -54,18 +54,14 @@ function FallBackAvatar({ str, rounded, size = ImageIconSize.Large }: FallBackAv export function ImageIcon({ src, label, alt = label, fallback, rounded, size }: ImageIconProps) { const [error, setError] = useState(false); - return ( - <div role="img" aria-label={label} className={size}> - {error || !src ? ( - <FallBackAvatar rounded={rounded} str={fallback} size={size} /> - ) : ( - <img - src={src} - alt={alt} - className="flex h-full w-full items-center justify-center rounded-full object-cover" - onError={() => setError(true)} - /> - )} - </div> + return error || !src ? ( + <FallBackAvatar rounded={rounded} str={fallback} size={size} /> + ) : ( + <img + src={src} + alt={alt} + className={cn('flex items-center justify-center rounded-full object-cover', size)} + onError={() => setError(true)} + /> ); } diff --git a/apps/core/src/hooks/stake/useValidatorInfo.tsx b/apps/core/src/hooks/stake/useValidatorInfo.tsx index 2ae4d23c933..f8d6dcd5a2f 100644 --- a/apps/core/src/hooks/stake/useValidatorInfo.tsx +++ b/apps/core/src/hooks/stake/useValidatorInfo.tsx @@ -36,7 +36,6 @@ export function useValidatorInfo({ validatorAddress }: { validatorAddress: strin system, isPendingValidators, errorValidators, - currentEpoch, validatorSummary, name: validatorSummary?.name || '', diff --git a/apps/explorer/src/components/IotaTokenCard.tsx b/apps/explorer/src/components/IotaTokenCard.tsx index 19bb5fa8286..51383f08d43 100644 --- a/apps/explorer/src/components/IotaTokenCard.tsx +++ b/apps/explorer/src/components/IotaTokenCard.tsx @@ -3,9 +3,8 @@ // SPDX-License-Identifier: Apache-2.0 import { Panel } from '@iota/apps-ui-kit'; -import { COIN_GECKO_IOTA_URL, useIotaCoinData } from '@iota/core'; -import { ButtonOrLink, ImageIconSize } from '~/components/ui'; -import { CoinIcon } from './owned-coins'; +import { COIN_GECKO_IOTA_URL, CoinIcon, ImageIconSize, useIotaCoinData } from '@iota/core'; +import { ButtonOrLink } from '~/components/ui'; import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; export function IotaTokenCard(): JSX.Element { diff --git a/apps/explorer/src/components/owned-coins/CoinIcon.tsx b/apps/explorer/src/components/owned-coins/CoinIcon.tsx deleted file mode 100644 index a0263d92afe..00000000000 --- a/apps/explorer/src/components/owned-coins/CoinIcon.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import { useCoinMetadata } from '@iota/core'; -import { IotaLogoMark } from '@iota/ui-icons'; -import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; -import { cx } from 'class-variance-authority'; -import { ImageIcon, ImageIconSize } from '../ui'; - -interface NonIotaCoinProps { - coinType: string; - size?: ImageIconSize; - rounded?: boolean; -} - -function NonIotaCoin({ coinType, size = ImageIconSize.Full, rounded }: NonIotaCoinProps) { - const { data: coinMeta } = useCoinMetadata(coinType); - return ( - <div className="flex h-full w-full items-center justify-center rounded-full bg-neutral-96 dark:bg-neutral-92"> - <ImageIcon - src={coinMeta?.iconUrl} - label={coinMeta?.name || coinType} - fallback={coinMeta?.name || coinType} - size={size} - rounded={rounded} - /> - </div> - ); -} -export interface CoinIconProps { - coinType: string; - size?: ImageIconSize; - rounded?: boolean; -} - -export function CoinIcon({ coinType, size = ImageIconSize.Full, rounded }: CoinIconProps) { - return coinType === IOTA_TYPE_ARG ? ( - <div className={cx(size)}> - <IotaLogoMark className="h-full w-full" /> - </div> - ) : ( - <NonIotaCoin rounded={rounded} size={size} coinType={coinType} /> - ); -} diff --git a/apps/explorer/src/components/owned-coins/OwnedCoinView.tsx b/apps/explorer/src/components/owned-coins/OwnedCoinView.tsx index 5f072935dcb..d2a53c74e03 100644 --- a/apps/explorer/src/components/owned-coins/OwnedCoinView.tsx +++ b/apps/explorer/src/components/owned-coins/OwnedCoinView.tsx @@ -2,11 +2,10 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { useFormatCoin } from '@iota/core'; +import { useFormatCoin, ImageIconSize, CoinIcon } from '@iota/core'; import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; import clsx from 'clsx'; import { useState } from 'react'; -import { CoinIcon } from './CoinIcon'; import { type CoinBalanceVerified } from './OwnedCoins'; import CoinsPanel from './OwnedCoinsPanel'; import { @@ -19,7 +18,6 @@ import { ImageType, } from '@iota/apps-ui-kit'; import { ArrowUp, RecognizedBadge } from '@iota/ui-icons'; -import { ImageIconSize } from '../ui'; type OwnedCoinViewProps = { coin: CoinBalanceVerified; diff --git a/apps/explorer/src/components/owned-coins/index.ts b/apps/explorer/src/components/owned-coins/index.ts index 21ab7bc1bfe..c2516466466 100644 --- a/apps/explorer/src/components/owned-coins/index.ts +++ b/apps/explorer/src/components/owned-coins/index.ts @@ -1,7 +1,6 @@ // Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -export * from './CoinIcon'; export * from './CoinItem'; export * from './OwnedCoinView'; export * from './OwnedCoins'; diff --git a/apps/explorer/src/components/ui/ImageIcon.tsx b/apps/explorer/src/components/ui/ImageIcon.tsx deleted file mode 100644 index 0366a9c741a..00000000000 --- a/apps/explorer/src/components/ui/ImageIcon.tsx +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import { useState } from 'react'; -import cn from 'clsx'; - -export enum ImageIconSize { - Small = 'w-5 h-5', - Medium = 'w-8 h-8', - Large = 'w-10 h-10', - Full = 'w-full h-full', -} - -export interface ImageIconProps { - src: string | null | undefined; - label: string; - fallback: string; - alt?: string; - rounded?: boolean; - size?: ImageIconSize; -} - -function FallBackAvatar({ - str, - rounded, - size = ImageIconSize.Large, -}: { - str: string; - rounded?: boolean; - size?: ImageIconSize; -}) { - function generateTextSize(size: ImageIconSize) { - switch (size) { - case ImageIconSize.Small: - return 'text-label-sm'; - case ImageIconSize.Medium: - return 'text-label-md'; - case ImageIconSize.Large: - return 'text-title-lg'; - case ImageIconSize.Full: - return 'text-display-lg'; - } - } - return ( - <div - className={cn( - 'flex items-center justify-center bg-neutral-96 bg-gradient-to-r capitalize text-neutral-10 dark:bg-neutral-92 dark:text-primary-100', - { 'rounded-full': rounded, 'rounded-lg': !rounded }, - size, - generateTextSize(size), - )} - > - {str?.slice(0, 2)} - </div> - ); -} - -export function ImageIcon({ src, label, alt = label, fallback, rounded, size }: ImageIconProps) { - const [error, setError] = useState(false); - return ( - <div role="img" aria-label={label} className={size}> - {error || !src ? ( - <FallBackAvatar rounded={rounded} str={fallback} size={size} /> - ) : ( - <img - src={src} - alt={alt} - className="flex h-full w-full items-center justify-center rounded-full object-cover" - onError={() => setError(true)} - /> - )} - </div> - ); -} diff --git a/apps/explorer/src/components/ui/index.ts b/apps/explorer/src/components/ui/index.ts index 6cf3f4c845d..7c58503ad94 100644 --- a/apps/explorer/src/components/ui/index.ts +++ b/apps/explorer/src/components/ui/index.ts @@ -9,7 +9,6 @@ export * from './modal'; export * from './ButtonOrLink'; export * from './ExpandableList'; export * from './FilterList'; -export * from './ImageIcon'; export * from './InternalLink'; export * from './Link'; export * from './LinkWithQuery'; diff --git a/apps/explorer/src/components/validator/ValidatorMeta.tsx b/apps/explorer/src/components/validator/ValidatorMeta.tsx index 386048bdebd..1b04666cf06 100644 --- a/apps/explorer/src/components/validator/ValidatorMeta.tsx +++ b/apps/explorer/src/components/validator/ValidatorMeta.tsx @@ -6,7 +6,8 @@ import { Badge, BadgeType, KeyValueInfo, Panel } from '@iota/apps-ui-kit'; import { type IotaValidatorSummary } from '@iota/iota-sdk/client'; import toast from 'react-hot-toast'; import { ArrowTopRight } from '@iota/ui-icons'; -import { AddressLink, ImageIcon, ImageIconSize } from '~/components/ui'; +import { AddressLink } from '~/components/ui'; +import { ImageIcon, ImageIconSize } from '@iota/core'; type ValidatorMetaProps = { validatorData: IotaValidatorSummary; diff --git a/apps/explorer/src/lib/ui/utils/generateValidatorsTableColumns.tsx b/apps/explorer/src/lib/ui/utils/generateValidatorsTableColumns.tsx index b053b889695..4bbb5b5805f 100644 --- a/apps/explorer/src/lib/ui/utils/generateValidatorsTableColumns.tsx +++ b/apps/explorer/src/lib/ui/utils/generateValidatorsTableColumns.tsx @@ -3,12 +3,12 @@ import { Badge, BadgeType, TableCellBase, TableCellText } from '@iota/apps-ui-kit'; import type { ColumnDef } from '@tanstack/react-table'; -import { type ApyByValidator, formatPercentageDisplay } from '@iota/core'; +import { type ApyByValidator, formatPercentageDisplay, ImageIcon, ImageIconSize } from '@iota/core'; import { ampli, getValidatorMoveEvent, VALIDATOR_LOW_STAKE_GRACE_PERIOD } from '~/lib'; import { StakeColumn } from '~/components'; import type { IotaEvent, IotaValidatorSummary } from '@iota/iota-sdk/dist/cjs/client'; import clsx from 'clsx'; -import { ImageIcon, ImageIconSize, ValidatorLink } from '~/components/ui'; +import { ValidatorLink } from '~/components/ui'; interface generateValidatorsTableColumnsArgs { atRiskValidators: [string, string][]; @@ -39,12 +39,14 @@ function ValidatorWithImage({ } label={ <div className="flex items-center gap-x-2.5 text-neutral-40 dark:text-neutral-60"> - <ImageIcon - src={validator.imageUrl} - size={ImageIconSize.Medium} - label={validator.name} - fallback={validator.name} - /> + <div className="h-8 w-8"> + <ImageIcon + src={validator.imageUrl} + label={validator.name} + fallback={validator.name} + size={validator.imageUrl ? ImageIconSize.Full : ImageIconSize.Medium} + /> + </div> <span className={clsx('text-label-lg', { 'text-neutral-10 dark:text-neutral-92': highlightValidatorName, diff --git a/apps/explorer/src/pages/transaction-result/transaction-summary/BalanceChanges.tsx b/apps/explorer/src/pages/transaction-result/transaction-summary/BalanceChanges.tsx index 3aae316b78e..8597bec0a25 100644 --- a/apps/explorer/src/pages/transaction-result/transaction-summary/BalanceChanges.tsx +++ b/apps/explorer/src/pages/transaction-result/transaction-summary/BalanceChanges.tsx @@ -20,10 +20,11 @@ import { getRecognizedUnRecognizedTokenChanges, useCoinMetadata, useFormatCoin, + ImageIconSize, + CoinIcon, } from '@iota/core'; import { RecognizedBadge } from '@iota/ui-icons'; import { useMemo } from 'react'; -import { CoinIcon, ImageIconSize } from '~/components'; import { AddressLink, CollapsibleCard } from '~/components/ui'; import { BREAK_POINT, useMediaQuery } from '~/hooks'; diff --git a/apps/explorer/src/pages/transaction-result/transaction-summary/ObjectDisplay.tsx b/apps/explorer/src/pages/transaction-result/transaction-summary/ObjectDisplay.tsx index 69ab37b5f45..278df5ca5c4 100644 --- a/apps/explorer/src/pages/transaction-result/transaction-summary/ObjectDisplay.tsx +++ b/apps/explorer/src/pages/transaction-result/transaction-summary/ObjectDisplay.tsx @@ -3,10 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 import { Card, CardAction, CardActionType, CardBody, CardImage, CardType } from '@iota/apps-ui-kit'; +import { ImageIcon } from '@iota/core'; import { type DisplayFieldsResponse } from '@iota/iota-sdk/client'; import { ArrowTopRight } from '@iota/ui-icons'; import { useState } from 'react'; -import { ImageIcon, ObjectModal } from '~/components/ui'; +import { ObjectModal } from '~/components/ui'; interface ObjectDisplayProps { objectId: string; diff --git a/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx b/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx index 912937bde97..2a89a992eb3 100644 --- a/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx +++ b/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx @@ -12,6 +12,7 @@ import { CardType, ImageType, } from '@iota/apps-ui-kit'; +import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; interface TxnAmountProps { amount: string | number | bigint; @@ -28,8 +29,12 @@ export function TxnAmount({ amount, coinType, subtitle, approximation }: TxnAmou return Number(amount) !== 0 ? ( <Card type={CardType.Filled}> <CardImage type={ImageType.BgSolid}> - <div className="h-10 w-10 items-center justify-center rounded-full border border-shader-neutral-light-8 text-neutral-10 dark:text-neutral-92"> - <CoinIcon coinType={coinType} size={ImageIconSize.Full} rounded /> + <div className="flex h-full w-full items-center justify-center rounded-full border border-shader-neutral-light-8 text-neutral-10 dark:text-neutral-92"> + <CoinIcon + coinType={coinType} + rounded + size={coinType === IOTA_TYPE_ARG ? ImageIconSize.Small : ImageIconSize.Full} + /> </div> </CardImage> <CardBody From 1c2f8a60e37f8ace2236efc81a508710aed93844 Mon Sep 17 00:00:00 2001 From: "Ching-Hua (Vivian) Lin" <jkrvivian@gmail.com> Date: Tue, 3 Dec 2024 23:22:40 +0800 Subject: [PATCH 33/36] cherry pick (rest-api): avoid panicking when constructing response headers (#4178) Co-authored-by: Bing-Yang <51323441+bingyanglin@users.noreply.github.com> --- crates/iota-rest-api/src/response.rs | 84 +++++++++++----------------- 1 file changed, 33 insertions(+), 51 deletions(-) diff --git a/crates/iota-rest-api/src/response.rs b/crates/iota-rest-api/src/response.rs index 03cba9bc36e..881a582babb 100644 --- a/crates/iota-rest-api/src/response.rs +++ b/crates/iota-rest-api/src/response.rs @@ -130,61 +130,43 @@ pub async fn append_info_headers( State(state): State<RestService>, response: Response, ) -> impl IntoResponse { - let latest_checkpoint = state.reader.inner().get_latest_checkpoint().unwrap(); - let lowest_available_checkpoint = state - .reader - .inner() - .get_lowest_available_checkpoint() - .unwrap(); + let mut headers = HeaderMap::new(); + + if let Ok(chain_id) = state.chain_id().to_string().try_into() { + headers.insert(X_IOTA_CHAIN_ID, chain_id); + } + + if let Ok(chain) = state.chain_id().chain().as_str().try_into() { + headers.insert(X_IOTA_CHAIN, chain); + } + + if let Ok(latest_checkpoint) = state.reader.inner().get_latest_checkpoint() { + headers.insert(X_IOTA_EPOCH, latest_checkpoint.epoch().into()); + headers.insert( + X_IOTA_CHECKPOINT_HEIGHT, + latest_checkpoint.sequence_number.into(), + ); + headers.insert(X_IOTA_TIMESTAMP_MS, latest_checkpoint.timestamp_ms.into()); + } + + if let Ok(lowest_available_checkpoint) = state.reader.inner().get_lowest_available_checkpoint() + { + headers.insert( + X_IOTA_LOWEST_AVAILABLE_CHECKPOINT, + lowest_available_checkpoint.into(), + ); + } - let lowest_available_checkpoint_objects = state + if let Ok(lowest_available_checkpoint_objects) = state .reader .inner() .get_lowest_available_checkpoint_objects() - .unwrap(); - - let mut headers = HeaderMap::new(); - - headers.insert( - X_IOTA_CHAIN_ID, - state.chain_id().to_string().try_into().unwrap(), - ); - headers.insert( - X_IOTA_CHAIN, - state.chain_id().chain().as_str().try_into().unwrap(), - ); - headers.insert( - X_IOTA_EPOCH, - latest_checkpoint.epoch().to_string().try_into().unwrap(), - ); - headers.insert( - X_IOTA_CHECKPOINT_HEIGHT, - latest_checkpoint - .sequence_number() - .to_string() - .try_into() - .unwrap(), - ); - headers.insert( - X_IOTA_TIMESTAMP_MS, - latest_checkpoint - .timestamp_ms - .to_string() - .try_into() - .unwrap(), - ); - headers.insert( - X_IOTA_LOWEST_AVAILABLE_CHECKPOINT, - lowest_available_checkpoint.to_string().try_into().unwrap(), - ); - - headers.insert( - X_IOTA_LOWEST_AVAILABLE_CHECKPOINT_OBJECTS, - lowest_available_checkpoint_objects - .to_string() - .try_into() - .unwrap(), - ); + { + headers.insert( + X_IOTA_LOWEST_AVAILABLE_CHECKPOINT_OBJECTS, + lowest_available_checkpoint_objects.into(), + ); + } (headers, response) } From 130ccae339daaf524544b97ce4ae68835334b892 Mon Sep 17 00:00:00 2001 From: JCNoguera <88061365+VmMad@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:54:58 +0100 Subject: [PATCH 34/36] fix(wallet): use correct gas estimation in preview send form (#4339) --- .../src/ui/app/pages/home/transfer-coin/PreviewTransfer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/PreviewTransfer.tsx b/apps/wallet/src/ui/app/pages/home/transfer-coin/PreviewTransfer.tsx index c2288f7a4eb..faed355c243 100644 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/PreviewTransfer.tsx +++ b/apps/wallet/src/ui/app/pages/home/transfer-coin/PreviewTransfer.tsx @@ -6,7 +6,7 @@ import { ExplorerLink, ExplorerLinkType, TxnAmount } from '_components'; import { useActiveAddress } from '_src/ui/app/hooks/useActiveAddress'; import { parseAmount, useCoinMetadata, useFormatCoin } from '@iota/core'; import { Divider, KeyValueInfo } from '@iota/apps-ui-kit'; -import { formatAddress } from '@iota/iota-sdk/utils'; +import { formatAddress, IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; export type PreviewTransferProps = { coinType: string; @@ -26,7 +26,7 @@ export function PreviewTransfer({ const accountAddress = useActiveAddress(); const { data: metadata } = useCoinMetadata(coinType); const amountWithoutDecimals = parseAmount(amount, metadata?.decimals ?? 0); - const [formattedGasBudgetEstimation, gasToken] = useFormatCoin(gasBudget, coinType); + const [formattedGasBudgetEstimation, gasToken] = useFormatCoin(gasBudget, IOTA_TYPE_ARG); return ( <div className="flex w-full flex-col gap-md"> From ca08313679746547918bb53cdb4ce02adee2763e Mon Sep 17 00:00:00 2001 From: Thibault Martinez <thibault@iota.org> Date: Tue, 3 Dec 2024 17:11:32 +0100 Subject: [PATCH 35/36] chore(ci): ignore firefly in team labeler (#4341) --- .github/workflows/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index c2931635e82..c2c9f77151e 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -22,4 +22,4 @@ jobs: with: repo-token: ${{ secrets.TEAM_LABELER_TOKEN }} organization-name: iotaledger - ignore-labels: devs, iota-foundation, iota-sdk, hornet, boxfish + ignore-labels: devs, iota-foundation, iota-sdk, hornet, boxfish, firefly From 82c06b3f6795dbdaffa238d74bdb2ed1d34e5dd1 Mon Sep 17 00:00:00 2001 From: cpl121 <100352899+cpl121@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:16:55 +0100 Subject: [PATCH 36/36] feat(sdk): add wallet extension to dapp-kit (#4323) --- sdk/dapp-kit/src/constants/walletDefaults.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/dapp-kit/src/constants/walletDefaults.ts b/sdk/dapp-kit/src/constants/walletDefaults.ts index 57ded2ec1e6..f68f3c26873 100644 --- a/sdk/dapp-kit/src/constants/walletDefaults.ts +++ b/sdk/dapp-kit/src/constants/walletDefaults.ts @@ -20,7 +20,7 @@ export const DEFAULT_WALLET_FILTER = (wallet: WalletWithRequiredFeatures) => export const DEFAULT_PREFERRED_WALLETS = [IOTA_WALLET_NAME]; -const WALLET_CHROME_EXTENSION_ID = 'TODO'; +const WALLET_CHROME_EXTENSION_ID = 'iidjkmdceolghepehaaddojmnjnkkija'; export const WALLET_DOWNLOAD_URL = 'https://chromewebstore.google.com/detail/' + WALLET_CHROME_EXTENSION_ID;