diff --git a/applications/tari_dan_app_utilities/src/template_manager/implementation/cmap_semaphore.rs b/applications/tari_dan_app_utilities/src/template_manager/implementation/cmap_semaphore.rs index 72f55b3ff..763e34831 100644 --- a/applications/tari_dan_app_utilities/src/template_manager/implementation/cmap_semaphore.rs +++ b/applications/tari_dan_app_utilities/src/template_manager/implementation/cmap_semaphore.rs @@ -54,7 +54,7 @@ pub struct ConcurrentMapSemaphoreGuard<'a, K: Hash + Eq> { key: K, } -impl<'a, K: Hash + Eq> ConcurrentMapSemaphoreGuard<'a, K> { +impl ConcurrentMapSemaphoreGuard<'_, K> { pub fn access(&self) -> MutexGuard<'_, ()> { // Unwrap: only errors if the mutex is poisoned, which is a bug self.map_mutex.lock().unwrap() diff --git a/applications/tari_dan_wallet_cli/src/table.rs b/applications/tari_dan_wallet_cli/src/table.rs index 71caad024..c9f595269 100644 --- a/applications/tari_dan_wallet_cli/src/table.rs +++ b/applications/tari_dan_wallet_cli/src/table.rs @@ -30,7 +30,7 @@ pub struct Table<'t, 's> { is_row_count_enabled: bool, } -impl<'t, 's> Table<'t, 's> { +impl<'t> Table<'t, '_> { pub fn new() -> Self { Self { titles: None, @@ -141,7 +141,7 @@ impl<'t, 's> Table<'t, 's> { } } -impl<'t, 's> Default for Table<'t, 's> { +impl Default for Table<'_, '_> { fn default() -> Self { Self::new() } diff --git a/applications/tari_dan_wallet_daemon/build.rs b/applications/tari_dan_wallet_daemon/build.rs index 358020bec..3c0446f92 100644 --- a/applications/tari_dan_wallet_daemon/build.rs +++ b/applications/tari_dan_wallet_daemon/build.rs @@ -28,10 +28,12 @@ fn exit_on_ci() { } } -const BUILD: &[(&str, &str)] = &[ - ("../../bindings", "tsc"), - ("../../clients/javascript/wallet_daemon_client", "build"), - ("../tari_dan_wallet_web_ui", "build"), +const BUILD: &[(&str, &[&str])] = &[ + ("../../bindings", &["ci"]), + ("../../bindings", &["run", "tsc"]), + ("../../clients/javascript/wallet_daemon_client", &["ci"]), + ("../../clients/javascript/wallet_daemon_client", &["run", "build"]), + ("../tari_dan_wallet_web_ui", &["run", "build"]), ]; fn main() -> Result<(), Box> { @@ -45,14 +47,20 @@ fn main() -> Result<(), Box> { let npm = if cfg!(windows) { "npm.cmd" } else { "npm" }; - for (target, build_cmd) in BUILD { + for (target, args) in BUILD { if let Err(error) = Command::new(npm).arg("ci").current_dir(target).status() { println!("cargo:warning='npm ci' error : {:?}", error); exit_on_ci(); + break; } - match Command::new(npm).args(["run", build_cmd]).current_dir(target).output() { + match Command::new(npm).args(*args).current_dir(target).output() { Ok(output) if !output.status.success() => { - println!("cargo:warning='npm run build' exited with non-zero status code"); + println!( + "cargo:warning='npm {}' in {} exited with non-zero status code", + args.iter().map(|s| s.to_string()).collect::>().join(" "), + target + ); + println!("cargo:warning=Status: {}", output.status); println!("cargo:warning=Output: {}", String::from_utf8_lossy(&output.stdout)); println!("cargo:warning=Error: {}", String::from_utf8_lossy(&output.stderr)); exit_on_ci(); diff --git a/applications/tari_dan_wallet_web_ui/package-lock.json b/applications/tari_dan_wallet_web_ui/package-lock.json index 6292e85f1..de8b1a8ab 100644 --- a/applications/tari_dan_wallet_web_ui/package-lock.json +++ b/applications/tari_dan_wallet_web_ui/package-lock.json @@ -15,8 +15,8 @@ "@mui/x-data-grid": "^6.0.2", "@tanstack/react-query": "^4.33.0", "@tanstack/react-query-devtools": "^4.33.0", - "@tari-project/typescript-bindings": "^1.0.3", - "@tari-project/wallet_jrpc_client": "^1.0.8", + "@tari-project/typescript-bindings": "file:../../bindings", + "@tari-project/wallet_jrpc_client": "file:../../clients/javascript/wallet_jrpc_client", "@walletconnect/core": "^2.13.3", "@walletconnect/web3wallet": "^1.12.3", "file-saver": "^2.0.5", @@ -34,10 +34,20 @@ "@types/react-dom": "^18.0.11", "@vitejs/plugin-react-swc": "^3.0.0", "prettier": "^3.3.2", - "typescript": "^4.9.3", + "typescript": "^4.9.5", "vite": "^4.5.5" } }, + "../../bindings": { + "name": "@tari-project/typescript-bindings", + "version": "1.2.0", + "license": "ISC", + "devDependencies": { + "shx": "^0.3.4", + "typescript": "^5.3.3" + } + }, + "../../clients/javascript/wallet_jrpc_client": {}, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", @@ -2022,17 +2032,12 @@ } }, "node_modules/@tari-project/typescript-bindings": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tari-project/typescript-bindings/-/typescript-bindings-1.0.3.tgz", - "integrity": "sha512-CWJAxXgorgDXWO3U3gg/LOB3KoYgrq63zYwR1Z0tEZW0HkkA4BKlyHywRn/WpgvoCCAmAMOM6pO2jV5x1iqM/w==" + "resolved": "../../bindings", + "link": true }, "node_modules/@tari-project/wallet_jrpc_client": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@tari-project/wallet_jrpc_client/-/wallet_jrpc_client-1.0.8.tgz", - "integrity": "sha512-Dar8cIM7FzlbzOxch8QAuBQnSvaPlowBtDrGaswGl+F9SxGiDyQmQ0a8lHyQIhT58fY7XFYeip0miH6gzbDIWQ==", - "dependencies": { - "@tari-project/typescript-bindings": "1.0.3" - } + "resolved": "../../clients/javascript/wallet_jrpc_client", + "link": true }, "node_modules/@types/file-saver": { "version": "2.0.7", diff --git a/applications/tari_dan_wallet_web_ui/package.json b/applications/tari_dan_wallet_web_ui/package.json index 87cff79f5..735c43434 100644 --- a/applications/tari_dan_wallet_web_ui/package.json +++ b/applications/tari_dan_wallet_web_ui/package.json @@ -16,8 +16,8 @@ "@mui/x-data-grid": "^6.0.2", "@tanstack/react-query": "^4.33.0", "@tanstack/react-query-devtools": "^4.33.0", - "@tari-project/typescript-bindings": "^1.0.3", - "@tari-project/wallet_jrpc_client": "^1.0.8", + "@tari-project/typescript-bindings": "file:../../bindings", + "@tari-project/wallet_jrpc_client": "file:../../clients/javascript/wallet_jrpc_client", "@walletconnect/core": "^2.13.3", "@walletconnect/web3wallet": "^1.12.3", "file-saver": "^2.0.5", @@ -35,7 +35,7 @@ "@types/react-dom": "^18.0.11", "@vitejs/plugin-react-swc": "^3.0.0", "prettier": "^3.3.2", - "typescript": "^4.9.3", + "typescript": "^4.9.5", "vite": "^4.5.5" } } diff --git a/applications/tari_dan_wallet_web_ui/src/Components/NFTList.tsx b/applications/tari_dan_wallet_web_ui/src/Components/NFTList.tsx index c8919c9d2..473520a8a 100644 --- a/applications/tari_dan_wallet_web_ui/src/Components/NFTList.tsx +++ b/applications/tari_dan_wallet_web_ui/src/Components/NFTList.tsx @@ -23,12 +23,11 @@ import React from "react"; import FetchStatusCheck from "./FetchStatusCheck"; import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material"; -import type { ListAccountNftResponse } from "@tari-project/typescript-bindings/wallet-daemon-client"; import type { apiError } from "../api/helpers/types"; import { DataTableCell } from "./StyledComponents"; -import { renderJson, toHexString } from "../utils/helpers"; +import { toHexString } from "../utils/helpers"; import { IoCheckmarkOutline, IoCloseOutline } from "react-icons/io5"; -import type { NonFungibleId, NonFungibleToken } from "@tari-project/typescript-bindings"; +import type { NonFungibleId, NonFungibleToken, ListAccountNftResponse } from "@tari-project/typescript-bindings"; import { convertCborValue } from "../utils/cbor"; function NftsList({ nft }: { nft: NonFungibleToken }) { @@ -96,7 +95,7 @@ export default function NFTList(props: NftListProps) { - {nftsListData?.nfts.map((nft: NonFungibleToken, index) => )} + {nftsListData?.nfts.map((nft: NonFungibleToken, index: number) => )} diff --git a/applications/tari_dan_wallet_web_ui/src/api/hooks/useAccounts.tsx b/applications/tari_dan_wallet_web_ui/src/api/hooks/useAccounts.tsx index 12368e976..c63510bb3 100644 --- a/applications/tari_dan_wallet_web_ui/src/api/hooks/useAccounts.tsx +++ b/applications/tari_dan_wallet_web_ui/src/api/hooks/useAccounts.tsx @@ -34,8 +34,11 @@ import { } from "../../utils/json_rpc"; import { apiError } from "../helpers/types"; import queryClient from "../queryClient"; -import type { ComponentAccessRules, ConfidentialTransferInputSelection } from "@tari-project/typescript-bindings"; -import type { ComponentAddressOrName } from "@tari-project/typescript-bindings/wallet-daemon-client"; +import type { + ComponentAccessRules, + ConfidentialTransferInputSelection, + ComponentAddressOrName, +} from "@tari-project/typescript-bindings"; // Fees are passed as strings because Amount is tagged export const useAccountsClaimBurn = (account: string, claimProof: string, fee: number) => { diff --git a/applications/tari_dan_wallet_web_ui/src/routes/AccountDetails/AccountDetails.tsx b/applications/tari_dan_wallet_web_ui/src/routes/AccountDetails/AccountDetails.tsx index a0c2319f7..9355271e8 100644 --- a/applications/tari_dan_wallet_web_ui/src/routes/AccountDetails/AccountDetails.tsx +++ b/applications/tari_dan_wallet_web_ui/src/routes/AccountDetails/AccountDetails.tsx @@ -31,13 +31,11 @@ import TableCell from "@mui/material/TableCell"; import TableBody from "@mui/material/TableBody"; import { useParams } from "react-router-dom"; import { useAccountsGetBalances, useAccountsGet, useAccountNFTsList } from "../../api/hooks/useAccounts"; -import { renderJson, shortenString } from "../../utils/helpers"; +import { shortenString } from "../../utils/helpers"; import { DataTableCell } from "../../Components/StyledComponents"; import CopyToClipboard from "../../Components/CopyToClipboard"; import FetchStatusCheck from "../../Components/FetchStatusCheck"; -import { substateIdToString } from "@tari-project/typescript-bindings"; -import type { BalanceEntry } from "@tari-project/typescript-bindings/wallet-daemon-client"; -import { IoCheckmarkOutline, IoCloseOutline } from "react-icons/io5"; +import { substateIdToString, BalanceEntry } from "@tari-project/typescript-bindings"; import NFTList from "../../Components/NFTList"; function BalanceRow(props: BalanceEntry) { diff --git a/applications/tari_dan_wallet_web_ui/src/routes/AssetVault/Components/Assets.tsx b/applications/tari_dan_wallet_web_ui/src/routes/AssetVault/Components/Assets.tsx index 0900b7223..ec72e8fae 100644 --- a/applications/tari_dan_wallet_web_ui/src/routes/AssetVault/Components/Assets.tsx +++ b/applications/tari_dan_wallet_web_ui/src/routes/AssetVault/Components/Assets.tsx @@ -37,11 +37,10 @@ import { DataTableCell } from "../../../Components/StyledComponents"; import { useAccountNFTsList, useAccountsGetBalances } from "../../../api/hooks/useAccounts"; import useAccountStore from "../../../store/accountStore"; import { shortenString } from "../../../utils/helpers"; -import type { BalanceEntry } from "@tari-project/typescript-bindings/wallet-daemon-client"; import NFTList from "../../../Components/NFTList"; import { Button } from "@mui/material"; import { SendMoneyDialog } from "./SendMoney"; -import { ResourceAddress, ResourceType, VaultId } from "@tari-project/typescript-bindings"; +import { ResourceAddress, ResourceType, VaultId, BalanceEntry } from "@tari-project/typescript-bindings"; interface TabPanelProps { children?: React.ReactNode; @@ -193,7 +192,7 @@ function Assets({ accountName }: { accountName: string }) { token_symbol, vault_address, }: BalanceEntry, - i, + i: number, ) => ( b.resource_type === "NonFungible" && b.balance > 0) - .map((b) => b.resource_address) as string[]; + ?.filter((b: BalanceEntry) => b.resource_type === "NonFungible" && b.balance > 0) + .map((b: BalanceEntry) => b.resource_address) as string[]; // TODO: we should have separate calls for confidential and non-confidential transfers const { mutateAsync: sendIt } = useAccountsTransfer( diff --git a/applications/tari_dan_wallet_web_ui/src/routes/Settings/Components/ViewVaultBalance.tsx b/applications/tari_dan_wallet_web_ui/src/routes/Settings/Components/ViewVaultBalance.tsx index b09f2858b..cd7c5e970 100644 --- a/applications/tari_dan_wallet_web_ui/src/routes/Settings/Components/ViewVaultBalance.tsx +++ b/applications/tari_dan_wallet_web_ui/src/routes/Settings/Components/ViewVaultBalance.tsx @@ -28,7 +28,7 @@ import Box from "@mui/material/Box"; import { useTheme } from "@mui/material/styles"; import { Divider } from "@mui/material"; import { confidentialViewVaultBalance } from "../../../utils/json_rpc"; -import { ConfidentialViewVaultBalanceRequest } from "@tari-project/typescript-bindings/wallet-daemon-client"; +import { ConfidentialViewVaultBalanceRequest } from "@tari-project/typescript-bindings"; function ViewVaultBalanceForm() { const [formState, setFormState] = useState({ diff --git a/applications/tari_dan_wallet_web_ui/src/routes/Transactions/TransactionDetails.tsx b/applications/tari_dan_wallet_web_ui/src/routes/Transactions/TransactionDetails.tsx index 3436fad54..6c2561db6 100644 --- a/applications/tari_dan_wallet_web_ui/src/routes/Transactions/TransactionDetails.tsx +++ b/applications/tari_dan_wallet_web_ui/src/routes/Transactions/TransactionDetails.tsx @@ -108,7 +108,7 @@ export default function TransactionDetails() { const handleDownload = () => { const json = JSON.stringify(data, null, 2); const blob = new Blob([json], { type: "application/json" }); - const filename = `tx-${data?.transaction?.id}.json` || "tx-unknown_id.json"; + const filename = `tx-${data?.transaction?.V1?.id}.json` || "tx-unknown_id.json"; saveAs(blob, filename); }; @@ -129,6 +129,8 @@ export default function TransactionDetails() { } }; + const transaction = data.transaction.V1; + if (data.status === "Rejected" || data.status === "InvalidTransaction") { return ( <> @@ -137,7 +139,7 @@ export default function TransactionDetails() { Transaction Hash - {data.transaction.id} + {transaction.id} Timestamp @@ -177,7 +179,7 @@ export default function TransactionDetails() { Transaction Hash - {data.transaction.id} + {transaction.id} Timestamp @@ -258,8 +260,8 @@ export default function TransactionDetails() { Fee Instructions - {data.transaction?.fee_instructions?.length ? ( - + {transaction?.fee_instructions?.length ? ( + ) : ( Empty )} @@ -270,8 +272,8 @@ export default function TransactionDetails() { Instructions - {data.transaction?.instructions?.length ? ( - + {transaction?.instructions?.length ? ( + ) : ( Empty )} @@ -312,11 +314,11 @@ export default function TransactionDetails() { Signers - {data.transaction?.signatures?.length ? ( + {transaction?.signatures?.length ? ( - {data.transaction.signatures.map((item: TransactionSignature, i: number) => { + {transaction.signatures.map((item: TransactionSignature, i: number) => { return ( {item.public_key} diff --git a/applications/tari_dan_wallet_web_ui/src/routes/Transactions/Transactions.tsx b/applications/tari_dan_wallet_web_ui/src/routes/Transactions/Transactions.tsx index 19bdee7d4..198ba5535 100644 --- a/applications/tari_dan_wallet_web_ui/src/routes/Transactions/Transactions.tsx +++ b/applications/tari_dan_wallet_web_ui/src/routes/Transactions/Transactions.tsx @@ -77,40 +77,43 @@ export default function Transactions({ accountName }: { accountName: string }) { {data?.transactions ?.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) - .map((t: [Transaction, FinalizeResult | null, TransactionStatus, string]) => { - if (t?.[0]?.id !== undefined) { - const hash = t[0].id; - return ( - - - - {hash} - - - - - - {t?.[1]?.fee_receipt.total_fees_paid || 0} - - - - - - - ); + .map(([t, result, status, _s]: [Transaction, FinalizeResult | null, TransactionStatus, string]) => { + const tx = t.V1; + if (!tx?.id) { + return <>; } + + const hash = tx.id; + return ( + + + + {hash} + + + + + + {result?.fee_receipt.total_fees_paid || 0} + + + + + + + ); })} {emptyRows(page, rowsPerPage, data?.transactions) > 0 && ( { - const date = new Date(exp * 1000); + const date = new Date(Number(exp * 1000n)); const formattedDate = `${date.toISOString().slice(0, 10)} ${date.toISOString().slice(11, 16)}`; return ( diff --git a/applications/tari_dan_wallet_web_ui/src/routes/Wallet/Components/Accounts.tsx b/applications/tari_dan_wallet_web_ui/src/routes/Wallet/Components/Accounts.tsx index c459cf0e3..8d4d090fe 100644 --- a/applications/tari_dan_wallet_web_ui/src/routes/Wallet/Components/Accounts.tsx +++ b/applications/tari_dan_wallet_web_ui/src/routes/Wallet/Components/Accounts.tsx @@ -50,7 +50,7 @@ import { } from "../../../api/hooks/useAccounts"; import FetchStatusCheck from "../../../Components/FetchStatusCheck"; import queryClient from "../../../api/queryClient"; -import type { AccountInfo } from "@tari-project/typescript-bindings/wallet-daemon-client"; +import type { AccountInfo } from "@tari-project/typescript-bindings"; function Account(account: AccountInfo, index: number) { const { pathname } = useLocation(); diff --git a/applications/tari_dan_wallet_web_ui/src/utils/helpers.tsx b/applications/tari_dan_wallet_web_ui/src/utils/helpers.tsx index 7d96b0d1e..cc745b037 100644 --- a/applications/tari_dan_wallet_web_ui/src/utils/helpers.tsx +++ b/applications/tari_dan_wallet_web_ui/src/utils/helpers.tsx @@ -61,7 +61,7 @@ export const renderJson = (json: any) => { export function toHexString(byteArray: any): string { if (Array.isArray(byteArray)) { - return Array.from(byteArray, function(byte) { + return Array.from(byteArray, function (byte) { return ("0" + (byte & 0xff).toString(16)).slice(-2); }).join(""); } @@ -110,11 +110,7 @@ export function shortenString(string: string | null | undefined, start: number = return string.substring(0, start) + "..." + string.slice(-end); } -export function emptyRows( - page: number, - rowsPerPage: number, - array: Array<[Transaction, FinalizeResult | null, TransactionStatus, string]> | undefined, -) { +export function emptyRows(page: number, rowsPerPage: number, array: Array | undefined) { if (array === undefined) { return 0; } diff --git a/applications/tari_dan_wallet_web_ui/src/utils/json_rpc.tsx b/applications/tari_dan_wallet_web_ui/src/utils/json_rpc.tsx index a48e40a7d..81f291e08 100644 --- a/applications/tari_dan_wallet_web_ui/src/utils/json_rpc.tsx +++ b/applications/tari_dan_wallet_web_ui/src/utils/json_rpc.tsx @@ -33,8 +33,6 @@ import type { AccountsGetBalancesResponse, AccountsListRequest, AccountsListResponse, - AuthGetAllJwtRequest, - AuthGetAllJwtResponse, AuthRevokeTokenRequest, AuthRevokeTokenResponse, ClaimBurnRequest, @@ -77,8 +75,14 @@ import type { TemplatesGetResponse, SubstatesListRequest, SubstatesListResponse, -} from "@tari-project/typescript-bindings/wallet-daemon-client"; -import { AccountGetDefaultRequest, TemplatesGetRequest, WalletDaemonClient } from "@tari-project/wallet_jrpc_client"; +} from "@tari-project/wallet_jrpc_client"; +import { + AccountGetDefaultRequest, + TemplatesGetRequest, + WalletDaemonClient, + AuthGetAllJwtResponse, + AuthGetAllJwtRequest, +} from "@tari-project/wallet_jrpc_client"; let clientInstance: WalletDaemonClient | null = null; let pendingClientInstance: Promise | null = null; diff --git a/applications/tari_indexer/src/substate_storage_sqlite/sqlite_substate_store_factory.rs b/applications/tari_indexer/src/substate_storage_sqlite/sqlite_substate_store_factory.rs index 00c2c9ac4..b5ca87859 100644 --- a/applications/tari_indexer/src/substate_storage_sqlite/sqlite_substate_store_factory.rs +++ b/applications/tari_indexer/src/substate_storage_sqlite/sqlite_substate_store_factory.rs @@ -865,7 +865,7 @@ impl<'a> Deref for SqliteSubstateStoreWriteTransaction<'a> { } } -impl<'a> DerefMut for SqliteSubstateStoreWriteTransaction<'a> { +impl DerefMut for SqliteSubstateStoreWriteTransaction<'_> { fn deref_mut(&mut self) -> &mut Self::Target { self.transaction.as_mut().unwrap() } diff --git a/applications/tari_swarm_daemon/src/process_manager/executables/manager.rs b/applications/tari_swarm_daemon/src/process_manager/executables/manager.rs index cf0980f41..c20cbd553 100644 --- a/applications/tari_swarm_daemon/src/process_manager/executables/manager.rs +++ b/applications/tari_swarm_daemon/src/process_manager/executables/manager.rs @@ -181,7 +181,7 @@ pub struct Executables<'a> { executables: &'a [Executable], } -impl<'a> Executables<'a> { +impl Executables<'_> { pub fn get(&self, instance_type: InstanceType) -> Option<&Executable> { self.executables.iter().find(|e| e.instance_type == instance_type) } diff --git a/applications/tari_validator_node_cli/src/table.rs b/applications/tari_validator_node_cli/src/table.rs index 71caad024..c9f595269 100644 --- a/applications/tari_validator_node_cli/src/table.rs +++ b/applications/tari_validator_node_cli/src/table.rs @@ -30,7 +30,7 @@ pub struct Table<'t, 's> { is_row_count_enabled: bool, } -impl<'t, 's> Table<'t, 's> { +impl<'t> Table<'t, '_> { pub fn new() -> Self { Self { titles: None, @@ -141,7 +141,7 @@ impl<'t, 's> Table<'t, 's> { } } -impl<'t, 's> Default for Table<'t, 's> { +impl Default for Table<'_, '_> { fn default() -> Self { Self::new() } diff --git a/applications/tari_validator_node_web_ui/src/routes/Transactions/TransactionDetails.tsx b/applications/tari_validator_node_web_ui/src/routes/Transactions/TransactionDetails.tsx index 9672819d8..5560c5de5 100644 --- a/applications/tari_validator_node_web_ui/src/routes/Transactions/TransactionDetails.tsx +++ b/applications/tari_validator_node_web_ui/src/routes/Transactions/TransactionDetails.tsx @@ -20,13 +20,13 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import {useEffect, useState} from "react"; -import {useParams} from "react-router-dom"; +import { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; // import { transactionsGet } from '../../utils/json_rpc'; -import {Accordion, AccordionDetails, AccordionSummary} from "../../Components/Accordion"; -import {Alert, Button, Fade, Grid, Table, TableBody, TableCell, TableContainer, TableRow} from "@mui/material"; +import { Accordion, AccordionDetails, AccordionSummary } from "../../Components/Accordion"; +import { Alert, Button, Fade, Grid, Table, TableBody, TableCell, TableContainer, TableRow } from "@mui/material"; import Typography from "@mui/material/Typography"; -import {DataTableCell, StyledPaper} from "../../Components/StyledComponents"; +import { DataTableCell, StyledPaper } from "../../Components/StyledComponents"; import PageHeading from "../../Components/PageHeading"; import Events from "./Events"; import Logs from "./Logs"; @@ -36,278 +36,279 @@ import Substates from "./Substates"; import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; import Loading from "../../Components/Loading"; -import {getDownSubstates, getTransaction, getUpSubstates} from "../../utils/json_rpc"; -import {displayDuration} from "../../utils/helpers"; +import { getDownSubstates, getTransaction, getUpSubstates } from "../../utils/json_rpc"; +import { displayDuration } from "../../utils/helpers"; import type { - Event, - ExecutedTransaction, - ExecuteResult, - LogEntry, - SubstateRecord, + Event, + ExecutedTransaction, + ExecuteResult, + LogEntry, + SubstateRecord, } from "@tari-project/typescript-bindings"; -import {getRejectReasonFromTransactionResult, rejectReasonToString} from "@tari-project/typescript-bindings"; +import { getRejectReasonFromTransactionResult, rejectReasonToString } from "@tari-project/typescript-bindings"; import StatusChip from "../../Components/StatusChip"; export default function TransactionDetails() { - const {transactionHash} = useParams(); - const [state, setState] = useState(); - const [upSubstate, setUpSubstate] = useState([]); - const [downSubstate, setDownSubstate] = useState([]); - const [events, setEvents] = useState(); - const [fee, setFee] = useState(); - const [logs, setLogs] = useState(); - const [expandedPanels, setExpandedPanels] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(); + const { transactionHash } = useParams(); + const [state, setState] = useState(); + const [upSubstate, setUpSubstate] = useState([]); + const [downSubstate, setDownSubstate] = useState([]); + const [events, setEvents] = useState(); + const [fee, setFee] = useState(); + const [logs, setLogs] = useState(); + const [expandedPanels, setExpandedPanels] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(); - const getTransactionByHash = () => { - setLoading(true); - Promise.all([ - getUpSubstates({transaction_id: String(transactionHash)}), - getDownSubstates({transaction_id: String(transactionHash)}), - getTransaction({transaction_id: String(transactionHash)}), - ]) - .then(([upSubstates, downSubstates, transaction]) => { - setState(transaction["transaction"]); - setError(undefined); - setUpSubstate(upSubstates["substates"]); - setDownSubstate(downSubstates["substates"]); - setEvents( - upSubstates["substates"].reduce( - (acc: Event[], cur: SubstateRecord) => - "TransactionReceipt" in cur?.substate_value && cur?.substate_value?.TransactionReceipt?.events - ? acc.concat(cur?.substate_value?.TransactionReceipt?.events) - : acc, - [], - ), - ); - setLogs( - upSubstates["substates"].reduce( - (acc: LogEntry[], cur: SubstateRecord) => - "TransactionReceipt" in cur?.substate_value && cur?.substate_value?.TransactionReceipt?.events - ? acc.concat(cur?.substate_value?.TransactionReceipt?.logs) - : acc, - [], - ), - ); - setFee( - upSubstates["substates"].reduce( - (acc: number, cur: SubstateRecord) => - acc + - Number( - ("TransactionReceipt" in cur?.substate_value && - cur?.substate_value?.TransactionReceipt?.fee_receipt?.total_fees_paid) || - 0, - ), - 0, - ), - ); - }) - .catch((err) => { - setError(err && err.message ? err.message : `Unknown error: ${JSON.stringify(err)}`); - }) - .finally(() => { - setLoading(false); - }); - }; + const getTransactionByHash = () => { + setLoading(true); + Promise.all([ + getUpSubstates({ transaction_id: String(transactionHash) }), + getDownSubstates({ transaction_id: String(transactionHash) }), + getTransaction({ transaction_id: String(transactionHash) }), + ]) + .then(([upSubstates, downSubstates, transaction]) => { + setState(transaction["transaction"]); + setError(undefined); + setUpSubstate(upSubstates["substates"]); + setDownSubstate(downSubstates["substates"]); + setEvents( + upSubstates["substates"].reduce( + (acc: Event[], cur: SubstateRecord) => + "TransactionReceipt" in cur?.substate_value && cur?.substate_value?.TransactionReceipt?.events + ? acc.concat(cur?.substate_value?.TransactionReceipt?.events) + : acc, + [], + ), + ); + setLogs( + upSubstates["substates"].reduce( + (acc: LogEntry[], cur: SubstateRecord) => + "TransactionReceipt" in cur?.substate_value && cur?.substate_value?.TransactionReceipt?.events + ? acc.concat(cur?.substate_value?.TransactionReceipt?.logs) + : acc, + [], + ), + ); + setFee( + upSubstates["substates"].reduce( + (acc: number, cur: SubstateRecord) => + acc + + Number( + ("TransactionReceipt" in cur?.substate_value && + cur?.substate_value?.TransactionReceipt?.fee_receipt?.total_fees_paid) || + 0, + ), + 0, + ), + ); + }) + .catch((err) => { + setError(err && err.message ? err.message : `Unknown error: ${JSON.stringify(err)}`); + }) + .finally(() => { + setLoading(false); + }); + }; - useEffect(() => { - getTransactionByHash(); - }, []); + useEffect(() => { + getTransactionByHash(); + }, []); - const handleChange = (panel: string) => (event: React.SyntheticEvent, isExpanded: boolean) => { - setExpandedPanels((prevExpandedPanels) => { - if (isExpanded) { - return [...prevExpandedPanels, panel]; - } else { - return prevExpandedPanels.filter((p) => p !== panel); - } - }); - }; + const handleChange = (panel: string) => (event: React.SyntheticEvent, isExpanded: boolean) => { + setExpandedPanels((prevExpandedPanels) => { + if (isExpanded) { + return [...prevExpandedPanels, panel]; + } else { + return prevExpandedPanels.filter((p) => p !== panel); + } + }); + }; - const renderResult = (result: ExecuteResult) => { - if (result) { - if ("Accept" in result.finalize.result) { - return Accepted; - } - return {rejectReasonToString(getRejectReasonFromTransactionResult(result.finalize.result))}; - } else { - return In progress; - } - }; + const renderResult = (result: ExecuteResult) => { + if (result) { + if ("Accept" in result.finalize.result) { + return Accepted; + } + return {rejectReasonToString(getRejectReasonFromTransactionResult(result.finalize.result))}; + } else { + return In progress; + } + }; - const expandAll = () => { - setExpandedPanels(["panel1", "panel2", "panel3", "panel4", "panel5"]); - }; + const expandAll = () => { + setExpandedPanels(["panel1", "panel2", "panel3", "panel4", "panel5"]); + }; - const collapseAll = () => { - setExpandedPanels([]); - }; - if (state === undefined) { - return <>; - } - const {result, transaction, finalized_time, final_decision} = state; - const decision = typeof final_decision === 'object' ? "Abort" : final_decision; - const abortReason = final_decision !== null && typeof final_decision === 'object' ? final_decision.Abort : null; - return ( - <> - - Transaction Details - - - - {loading ? ( - - ) : ( - -
- {error ? ( - {error} - ) : ( - <> - -
- - - Transaction Hash - {transactionHash} - - - Timestamp - Timestamp - - - Total Fees - {fee} - - {final_decision && ( - - Status - - - - - )} - {abortReason && ( - - Abort reason - {abortReason} - - )} - - Result - - {renderResult(result)} -
- Executed - in {result.execution_time ? displayDuration(result.execution_time) : "--"}, - Finalized in{" "} - {finalized_time ? displayDuration(finalized_time) : "--"} -
-
-
-
-
-
- More Info -
- - -
-
- - )} - {transaction?.fee_instructions && ( - - - Fee Instructions - - - - - - )} - {transaction?.instructions && ( - - - Instructions - - - - - - )} - {result && events && ( - - - Events - - - - - - )} - {result && logs && ( - - - Logs - - - - - - )} - {upSubstate && ( - - - Substates - - - - - - )} - - - )} - - - - ); + const collapseAll = () => { + setExpandedPanels([]); + }; + if (state === undefined) { + return <>; + } + const { result, transaction: container, finalized_time, final_decision } = state; + const transaction = container.V1; + const decision = typeof final_decision === "object" ? "Abort" : final_decision; + const abortReason = final_decision !== null && typeof final_decision === "object" ? final_decision.Abort : null; + return ( + <> + + Transaction Details + + + + {loading ? ( + + ) : ( + +
+ {error ? ( + {error} + ) : ( + <> + + + + + Transaction Hash + {transactionHash} + + + Timestamp + Timestamp + + + Total Fees + {fee} + + {final_decision && ( + + Status + + + + + )} + {abortReason && ( + + Abort reason + {abortReason} + + )} + + Result + + {renderResult(result)} +
+ Executed + in {result.execution_time ? displayDuration(result.execution_time) : "--"}, + Finalized in{" "} + {finalized_time ? displayDuration(finalized_time) : "--"} +
+
+
+
+
+
+ More Info +
+ + +
+
+ + )} + {transaction?.fee_instructions && ( + + + Fee Instructions + + + + + + )} + {transaction?.instructions && ( + + + Instructions + + + + + + )} + {result && events && ( + + + Events + + + + + + )} + {result && logs && ( + + + Logs + + + + + + )} + {upSubstate && ( + + + Substates + + + + + + )} +
+
+ )} +
+
+ + ); } diff --git a/bindings/dist/index.d.ts b/bindings/dist/index.d.ts index 7e3e7cf5b..a68eb4f38 100644 --- a/bindings/dist/index.d.ts +++ b/bindings/dist/index.d.ts @@ -112,6 +112,7 @@ export * from "./types/TransactionReceiptAddress"; export * from "./types/TransactionResult"; export * from "./types/TransactionSignature"; export * from "./types/TransactionStatus"; +export * from "./types/TransactionV1"; export * from "./types/Type"; export * from "./types/UnclaimedConfidentialOutput"; export * from "./types/UnclaimedConfidentialOutputAddress"; diff --git a/bindings/dist/index.js b/bindings/dist/index.js index ebd36777e..4a091d8cc 100644 --- a/bindings/dist/index.js +++ b/bindings/dist/index.js @@ -114,6 +114,7 @@ export * from "./types/TransactionReceiptAddress"; export * from "./types/TransactionResult"; export * from "./types/TransactionSignature"; export * from "./types/TransactionStatus"; +export * from "./types/TransactionV1"; export * from "./types/Type"; export * from "./types/UnclaimedConfidentialOutput"; export * from "./types/UnclaimedConfidentialOutputAddress"; diff --git a/bindings/dist/types/Transaction.d.ts b/bindings/dist/types/Transaction.d.ts index 9abee9336..3c8b4e768 100644 --- a/bindings/dist/types/Transaction.d.ts +++ b/bindings/dist/types/Transaction.d.ts @@ -1,15 +1,4 @@ -import type { Epoch } from "./Epoch"; -import type { Instruction } from "./Instruction"; -import type { SubstateRequirement } from "./SubstateRequirement"; -import type { TransactionSignature } from "./TransactionSignature"; -import type { VersionedSubstateId } from "./VersionedSubstateId"; -export interface Transaction { - id: string; - fee_instructions: Array; - instructions: Array; - inputs: Array; - min_epoch: Epoch | null; - max_epoch: Epoch | null; - signatures: Array; - filled_inputs: Array; -} +import type { TransactionV1 } from "./TransactionV1"; +export type Transaction = { + V1: TransactionV1; +}; diff --git a/bindings/dist/types/TransactionV1.d.ts b/bindings/dist/types/TransactionV1.d.ts new file mode 100644 index 000000000..c478b900c --- /dev/null +++ b/bindings/dist/types/TransactionV1.d.ts @@ -0,0 +1,15 @@ +import type { Epoch } from "./Epoch"; +import type { Instruction } from "./Instruction"; +import type { SubstateRequirement } from "./SubstateRequirement"; +import type { TransactionSignature } from "./TransactionSignature"; +import type { VersionedSubstateId } from "./VersionedSubstateId"; +export interface TransactionV1 { + id: string; + fee_instructions: Array; + instructions: Array; + inputs: Array; + min_epoch: Epoch | null; + max_epoch: Epoch | null; + signatures: Array; + filled_inputs: Array; +} diff --git a/bindings/dist/types/TransactionV1.js b/bindings/dist/types/TransactionV1.js new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/bindings/dist/types/TransactionV1.js @@ -0,0 +1 @@ +export {}; diff --git a/bindings/package-lock.json b/bindings/package-lock.json index 822dd76e0..73103f8ce 100644 --- a/bindings/package-lock.json +++ b/bindings/package-lock.json @@ -1,12 +1,12 @@ { "name": "@tari-project/typescript-bindings", - "version": "1.0.4", + "version": "1.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tari-project/typescript-bindings", - "version": "1.0.4", + "version": "1.1.0", "license": "ISC", "devDependencies": { "shx": "^0.3.4", diff --git a/bindings/package.json b/bindings/package.json index f3e188ef0..fe1a99cae 100644 --- a/bindings/package.json +++ b/bindings/package.json @@ -1,6 +1,6 @@ { "name": "@tari-project/typescript-bindings", - "version": "1.1.0", + "version": "1.2.0", "description": "", "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/bindings/src/index.ts b/bindings/src/index.ts index fadd8abd1..a1cca4c30 100644 --- a/bindings/src/index.ts +++ b/bindings/src/index.ts @@ -115,6 +115,7 @@ export * from "./types/TransactionReceiptAddress"; export * from "./types/TransactionResult"; export * from "./types/TransactionSignature"; export * from "./types/TransactionStatus"; +export * from "./types/TransactionV1"; export * from "./types/Type"; export * from "./types/UnclaimedConfidentialOutput"; export * from "./types/UnclaimedConfidentialOutputAddress"; diff --git a/bindings/src/types/Transaction.ts b/bindings/src/types/Transaction.ts index 93469996f..455f4fc45 100644 --- a/bindings/src/types/Transaction.ts +++ b/bindings/src/types/Transaction.ts @@ -1,17 +1,4 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { Epoch } from "./Epoch"; -import type { Instruction } from "./Instruction"; -import type { SubstateRequirement } from "./SubstateRequirement"; -import type { TransactionSignature } from "./TransactionSignature"; -import type { VersionedSubstateId } from "./VersionedSubstateId"; +import type { TransactionV1 } from "./TransactionV1"; -export interface Transaction { - id: string; - fee_instructions: Array; - instructions: Array; - inputs: Array; - min_epoch: Epoch | null; - max_epoch: Epoch | null; - signatures: Array; - filled_inputs: Array; -} +export type Transaction = { V1: TransactionV1 }; diff --git a/bindings/src/types/TransactionV1.ts b/bindings/src/types/TransactionV1.ts new file mode 100644 index 000000000..4461d2d04 --- /dev/null +++ b/bindings/src/types/TransactionV1.ts @@ -0,0 +1,17 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Epoch } from "./Epoch"; +import type { Instruction } from "./Instruction"; +import type { SubstateRequirement } from "./SubstateRequirement"; +import type { TransactionSignature } from "./TransactionSignature"; +import type { VersionedSubstateId } from "./VersionedSubstateId"; + +export interface TransactionV1 { + id: string; + fee_instructions: Array; + instructions: Array; + inputs: Array; + min_epoch: Epoch | null; + max_epoch: Epoch | null; + signatures: Array; + filled_inputs: Array; +} diff --git a/clients/javascript/wallet_daemon_client/package.json b/clients/javascript/wallet_daemon_client/package.json index 0d530ac53..8addf1cb0 100644 --- a/clients/javascript/wallet_daemon_client/package.json +++ b/clients/javascript/wallet_daemon_client/package.json @@ -1,6 +1,6 @@ { "name": "@tari-project/wallet_jrpc_client", - "version": "1.1.0", + "version": "1.2.0", "description": "Tari wallet JSON-RPC client library", "publishConfig": { "access": "public" @@ -17,7 +17,7 @@ "author": "", "license": "ISC", "dependencies": { - "@tari-project/typescript-bindings": "1.1.0" + "@tari-project/typescript-bindings": "1.2.0" }, "devDependencies": { "typescript": "^5.3.3" diff --git a/clients/javascript/wallet_daemon_client/tsconfig.json b/clients/javascript/wallet_daemon_client/tsconfig.json index a27fffd81..e423fa934 100644 --- a/clients/javascript/wallet_daemon_client/tsconfig.json +++ b/clients/javascript/wallet_daemon_client/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "ES2020", "target": "ESNext", - "moduleResolution": "Bundler", + "moduleResolution": "node", "declaration": true, "outDir": "./dist", }, diff --git a/dan_layer/common_types/src/committee.rs b/dan_layer/common_types/src/committee.rs index 7455a56d2..606e03e75 100644 --- a/dan_layer/common_types/src/committee.rs +++ b/dan_layer/common_types/src/committee.rs @@ -256,7 +256,7 @@ impl CommitteeInfo { .any(|substate_address| self.includes_substate_address(substate_address.borrow())) } - pub fn filter<'a, I, B>(&'a self, items: I) -> impl Iterator + '_ + pub fn filter<'a, I, B>(&'a self, items: I) -> impl Iterator + 'a where I: IntoIterator + 'a, B: Borrow, diff --git a/dan_layer/consensus/src/hotstuff/substate_store/shard_state_store.rs b/dan_layer/consensus/src/hotstuff/substate_store/shard_state_store.rs index 630aa732f..a0af500c8 100644 --- a/dan_layer/consensus/src/hotstuff/substate_store/shard_state_store.rs +++ b/dan_layer/consensus/src/hotstuff/substate_store/shard_state_store.rs @@ -20,7 +20,7 @@ impl<'a, TTx> ShardScopedTreeStoreReader<'a, TTx> { } } -impl<'a, TTx: StateStoreReadTransaction> TreeStoreReader for ShardScopedTreeStoreReader<'a, TTx> { +impl TreeStoreReader for ShardScopedTreeStoreReader<'_, TTx> { fn get_node(&self, key: &NodeKey) -> Result, tari_state_tree::JmtStorageError> { self.tx .state_tree_nodes_get(self.shard, key) @@ -52,7 +52,7 @@ impl<'a, TTx: StateStoreWriteTransaction> ShardScopedTreeStoreWriter<'a, TTx> { } } -impl<'a, TTx> TreeStoreReader for ShardScopedTreeStoreWriter<'a, TTx> +impl TreeStoreReader for ShardScopedTreeStoreWriter<'_, TTx> where TTx: StateStoreWriteTransaction + Deref, TTx::Target: StateStoreReadTransaction, @@ -66,7 +66,7 @@ where } } -impl<'a, TTx: StateStoreWriteTransaction> TreeStoreWriter for ShardScopedTreeStoreWriter<'a, TTx> { +impl TreeStoreWriter for ShardScopedTreeStoreWriter<'_, TTx> { fn insert_node(&mut self, key: NodeKey, node: Node) -> Result<(), tari_state_tree::JmtStorageError> { self.tx .state_tree_nodes_insert(self.shard, key, node) diff --git a/dan_layer/state_store_sqlite/migrations/2023-06-08-091819_create_state_store/up.sql b/dan_layer/state_store_sqlite/migrations/2023-06-08-091819_create_state_store/up.sql index 98e6ed7e1..ecf6d2a72 100644 --- a/dan_layer/state_store_sqlite/migrations/2023-06-08-091819_create_state_store/up.sql +++ b/dan_layer/state_store_sqlite/migrations/2023-06-08-091819_create_state_store/up.sql @@ -289,6 +289,7 @@ create table transactions abort_details text NULL, min_epoch BIGINT NULL, max_epoch BIGINT NULL, + schema_version BIGINT NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ); diff --git a/dan_layer/state_store_sqlite/src/schema.rs b/dan_layer/state_store_sqlite/src/schema.rs index 292aeaf39..d8d2d5199 100644 --- a/dan_layer/state_store_sqlite/src/schema.rs +++ b/dan_layer/state_store_sqlite/src/schema.rs @@ -521,6 +521,7 @@ diesel::table! { abort_details -> Nullable, min_epoch -> Nullable, max_epoch -> Nullable, + schema_version -> BigInt, created_at -> Timestamp, } } diff --git a/dan_layer/state_store_sqlite/src/sql_models/transaction.rs b/dan_layer/state_store_sqlite/src/sql_models/transaction.rs index 534a94cb8..574cd6cd7 100644 --- a/dan_layer/state_store_sqlite/src/sql_models/transaction.rs +++ b/dan_layer/state_store_sqlite/src/sql_models/transaction.rs @@ -30,6 +30,7 @@ pub struct Transaction { pub abort_details: Option, pub min_epoch: Option, pub max_epoch: Option, + pub schema_version: i64, pub created_at: PrimitiveDateTime, } @@ -37,6 +38,14 @@ impl TryFrom for tari_transaction::Transaction { type Error = StorageError; fn try_from(value: Transaction) -> Result { + if value.schema_version != 1 { + return Err(StorageError::DecodingError { + operation: "TryFrom for tari_transaction::Transaction", + item: "schema_version", + details: format!("Unsupported schema version: {}", value.schema_version), + }); + } + let fee_instructions = deserialize_json(&value.fee_instructions)?; let instructions = deserialize_json(&value.instructions)?; let signatures = deserialize_json(&value.signatures)?; diff --git a/dan_layer/state_store_sqlite/src/writer.rs b/dan_layer/state_store_sqlite/src/writer.rs index e70b3a05c..ddfe5e951 100644 --- a/dan_layer/state_store_sqlite/src/writer.rs +++ b/dan_layer/state_store_sqlite/src/writer.rs @@ -832,6 +832,7 @@ impl<'tx, TAddr: NodeAddressable + 'tx> StateStoreWriteTransaction for SqliteSta transactions::abort_details.eq(tx_rec.abort_reason().map(serialize_json).transpose()?), transactions::min_epoch.eq(transaction.min_epoch().map(|e| e.as_u64() as i64)), transactions::max_epoch.eq(transaction.max_epoch().map(|e| e.as_u64() as i64)), + transactions::schema_version.eq(transaction.schema_version() as i64), ); diesel::insert_into(transactions::table) diff --git a/dan_layer/state_tree/src/staged_store.rs b/dan_layer/state_tree/src/staged_store.rs index 4829994c8..1342150e7 100644 --- a/dan_layer/state_tree/src/staged_store.rs +++ b/dan_layer/state_tree/src/staged_store.rs @@ -51,7 +51,7 @@ impl<'s, S: TreeStoreReader

, P> StagedTreeStore<'s, S, P> { } } -impl<'s, S: TreeStoreReader

, P: Clone> TreeStoreReader

for StagedTreeStore<'s, S, P> { +impl, P: Clone> TreeStoreReader

for StagedTreeStore<'_, S, P> { fn get_node(&self, key: &NodeKey) -> Result, JmtStorageError> { if let Some(node) = self.new_tree_nodes.get(key).cloned() { return Ok(node); @@ -64,7 +64,7 @@ impl<'s, S: TreeStoreReader

, P: Clone> TreeStoreReader

for StagedTreeStore } } -impl<'s, S, P> TreeStoreWriter

for StagedTreeStore<'s, S, P> { +impl TreeStoreWriter

for StagedTreeStore<'_, S, P> { fn insert_node(&mut self, key: NodeKey, node: Node

) -> Result<(), JmtStorageError> { if self.new_tree_nodes.insert(key.clone(), node).is_some() { return Err(JmtStorageError::Conflict(key)); diff --git a/dan_layer/state_tree/src/tree.rs b/dan_layer/state_tree/src/tree.rs index fb3250d7e..cd01f2360 100644 --- a/dan_layer/state_tree/src/tree.rs +++ b/dan_layer/state_tree/src/tree.rs @@ -45,7 +45,7 @@ impl<'a, S, M> StateTree<'a, S, M> { } } -impl<'a, S: TreeStoreReader, M: DbKeyMapper> StateTree<'a, S, M> { +impl, M: DbKeyMapper> StateTree<'_, S, M> { pub fn get_proof( &self, version: Version, @@ -64,7 +64,7 @@ impl<'a, S: TreeStoreReader, M: DbKeyMapper> State } } -impl<'a, S: TreeStore, M: DbKeyMapper> StateTree<'a, S, M> { +impl, M: DbKeyMapper> StateTree<'_, S, M> { fn calculate_substate_changes>( &mut self, current_version: Option, @@ -103,7 +103,7 @@ impl<'a, S: TreeStore, M: DbKeyMapper> StateTree<' } } -impl<'a, S: TreeStore<()>, M: DbKeyMapper> StateTree<'a, S, M> { +impl, M: DbKeyMapper> StateTree<'_, S, M> { pub fn put_changes>( &mut self, current_version: Option, diff --git a/dan_layer/storage/src/consensus_models/block.rs b/dan_layer/storage/src/consensus_models/block.rs index 5e3164f06..1fd05860f 100644 --- a/dan_layer/storage/src/consensus_models/block.rs +++ b/dan_layer/storage/src/consensus_models/block.rs @@ -289,7 +289,7 @@ impl Block { pub fn all_transaction_ids_in_committee<'a>( &'a self, committee_info: &'a CommitteeInfo, - ) -> impl Iterator + 'a { + ) -> impl Iterator + 'a { self.commands .iter() .filter_map(|cmd| cmd.transaction()) diff --git a/dan_layer/storage/src/consensus_models/lock_intent.rs b/dan_layer/storage/src/consensus_models/lock_intent.rs index 2b7218d04..eb764fdba 100644 --- a/dan_layer/storage/src/consensus_models/lock_intent.rs +++ b/dan_layer/storage/src/consensus_models/lock_intent.rs @@ -121,7 +121,7 @@ impl LockIntent for VersionedSubstateIdLockIntent { } } -impl<'a> LockIntent for &'a VersionedSubstateIdLockIntent { +impl LockIntent for &VersionedSubstateIdLockIntent { fn substate_id(&self) -> &SubstateId { self.versioned_substate_id.substate_id() } @@ -204,7 +204,7 @@ impl SubstateRequirementLockIntent { } } -impl<'a> LockIntent for &'a SubstateRequirementLockIntent { +impl LockIntent for &SubstateRequirementLockIntent { fn substate_id(&self) -> &SubstateId { self.substate_requirement.substate_id() } diff --git a/dan_layer/tari_bor/src/json_encoding.rs b/dan_layer/tari_bor/src/json_encoding.rs index 031f0f506..0c2354d5d 100644 --- a/dan_layer/tari_bor/src/json_encoding.rs +++ b/dan_layer/tari_bor/src/json_encoding.rs @@ -75,7 +75,7 @@ impl<'de> serde::Deserialize<'de> for CborValueJsonDeserializeWrapper { } #[doc(hidden)] struct __FieldVisitor; - impl<'de> serde::de::Visitor<'de> for __FieldVisitor { + impl serde::de::Visitor<'_> for __FieldVisitor { type Value = __Field; fn expecting(&self, __formatter: &mut Formatter) -> fmt::Result { diff --git a/dan_layer/template_lib/src/panic_hook.rs b/dan_layer/template_lib/src/panic_hook.rs index 6ce16372c..3ee3e0dde 100644 --- a/dan_layer/template_lib/src/panic_hook.rs +++ b/dan_layer/template_lib/src/panic_hook.rs @@ -24,7 +24,7 @@ use tari_template_abi::on_panic; -fn hook(info: &std::panic::PanicInfo<'_>) { +fn hook(info: &std::panic::PanicHookInfo<'_>) { let error_msg = info .payload() .downcast_ref::() diff --git a/dan_layer/transaction/src/lib.rs b/dan_layer/transaction/src/lib.rs index 69b577137..f910774a7 100644 --- a/dan_layer/transaction/src/lib.rs +++ b/dan_layer/transaction/src/lib.rs @@ -25,6 +25,7 @@ mod signature; mod transaction; mod transaction_id; mod unsigned_transaction; +mod v1; pub use builder::TransactionBuilder; pub use signature::TransactionSignature; diff --git a/dan_layer/transaction/src/transaction.rs b/dan_layer/transaction/src/transaction.rs index 38ce5912b..277f265af 100644 --- a/dan_layer/transaction/src/transaction.rs +++ b/dan_layer/transaction/src/transaction.rs @@ -8,15 +8,16 @@ use serde::{Deserialize, Serialize}; use tari_common_types::types::PublicKey; use tari_crypto::ristretto::RistrettoSecretKey; use tari_dan_common_types::{committee::CommitteeInfo, Epoch, SubstateRequirement, VersionedSubstateId}; -use tari_engine_types::{ - hashing::{hasher32, EngineHashDomainLabel}, - indexed_value::{IndexedValue, IndexedValueError}, - instruction::Instruction, - substate::SubstateId, -}; +use tari_engine_types::{indexed_value::IndexedValueError, instruction::Instruction, substate::SubstateId}; use tari_template_lib::{models::ComponentAddress, Hash}; -use crate::{builder::TransactionBuilder, transaction_id::TransactionId, TransactionSignature, UnsignedTransaction}; +use crate::{ + builder::TransactionBuilder, + transaction_id::TransactionId, + v1::TransactionV1, + TransactionSignature, + UnsignedTransaction, +}; #[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr( @@ -24,14 +25,8 @@ use crate::{builder::TransactionBuilder, transaction_id::TransactionId, Transact derive(ts_rs::TS), ts(export, export_to = "../../bindings/src/types/") )] -pub struct Transaction { - #[cfg_attr(feature = "ts", ts(type = "string"))] - id: TransactionId, - #[serde(flatten)] - transaction: UnsignedTransaction, - signatures: Vec, - /// Inputs filled by some authority. These are not part of the transaction hash nor the signature - filled_inputs: IndexSet, +pub enum Transaction { + V1(TransactionV1), } impl Transaction { @@ -40,80 +35,80 @@ impl Transaction { } pub fn new(unsigned_transaction: UnsignedTransaction, signatures: Vec) -> Self { - let mut tx = Self { - id: TransactionId::default(), - transaction: unsigned_transaction, - filled_inputs: IndexSet::new(), - signatures, - }; - tx.id = tx.calculate_hash(); - tx + Self::V1(TransactionV1::new(unsigned_transaction, signatures)) } - pub fn sign(mut self, secret: &RistrettoSecretKey) -> Self { - let sig = TransactionSignature::sign(secret, &self.transaction); - self.signatures.push(sig); - self.id = self.calculate_hash(); - self + pub fn sign(self, secret: &RistrettoSecretKey) -> Self { + match self { + Self::V1(tx) => Self::V1(tx.sign(secret)), + } } pub fn with_filled_inputs(self, filled_inputs: IndexSet) -> Self { - Self { filled_inputs, ..self } - } - - fn calculate_hash(&self) -> TransactionId { - hasher32(EngineHashDomainLabel::Transaction) - .chain(&self.signatures) - .chain(&self.transaction) - .result() - .into_array() - .into() + match self { + Self::V1(tx) => Self::V1(tx.with_filled_inputs(filled_inputs)), + } } pub fn id(&self) -> &TransactionId { - &self.id + match self { + Self::V1(tx) => tx.id(), + } } pub fn check_id(&self) -> bool { - let id = self.calculate_hash(); - id == self.id + match self { + Self::V1(tx) => tx.check_id(), + } } pub fn unsigned_transaction(&self) -> &UnsignedTransaction { - &self.transaction + match self { + Self::V1(tx) => tx.unsigned_transaction(), + } } pub fn hash(&self) -> Hash { - self.id.into_array().into() + match self { + Self::V1(tx) => tx.hash(), + } } pub fn fee_instructions(&self) -> &[Instruction] { - &self.transaction.fee_instructions + match self { + Self::V1(tx) => tx.fee_instructions(), + } } pub fn instructions(&self) -> &[Instruction] { - &self.transaction.instructions + match self { + Self::V1(tx) => tx.instructions(), + } } pub fn signatures(&self) -> &[TransactionSignature] { - &self.signatures + match self { + Self::V1(tx) => tx.signatures(), + } } pub fn verify_all_signatures(&self) -> bool { - if self.signatures.is_empty() { - return false; + match self { + Self::V1(tx) => tx.verify_all_signatures(), } - - self.signatures().iter().all(|sig| sig.verify(&self.transaction)) } pub fn inputs(&self) -> &IndexSet { - &self.transaction.inputs + match self { + Self::V1(tx) => tx.inputs(), + } } /// Returns (fee instructions, instructions) pub fn into_instructions(self) -> (Vec, Vec) { - (self.transaction.fee_instructions, self.transaction.instructions) + match self { + Self::V1(tx) => tx.into_instructions(), + } } pub fn into_parts( @@ -123,16 +118,15 @@ impl Transaction { Vec, IndexSet, ) { - (self.transaction, self.signatures, self.filled_inputs) + match self { + Self::V1(tx) => tx.into_parts(), + } } pub fn all_inputs_iter(&self) -> impl Iterator + '_ { - self.inputs() - .iter() - // Filled inputs override other inputs as they are likely filled with versions - .filter(|i| self.filled_inputs().iter().all(|fi| fi.substate_id() != i.substate_id())) - .cloned() - .chain(self.filled_inputs().iter().cloned().map(Into::into)) + match self { + Self::V1(tx) => tx.all_inputs_iter(), + } } pub fn all_inputs_substate_ids_iter(&self) -> impl Iterator + '_ { @@ -155,100 +149,65 @@ impl Transaction { } pub fn filled_inputs(&self) -> &IndexSet { - &self.filled_inputs + match self { + Self::V1(tx) => tx.filled_inputs(), + } } pub fn filled_inputs_mut(&mut self) -> &mut IndexSet { - &mut self.filled_inputs + match self { + Self::V1(tx) => tx.filled_inputs_mut(), + } } pub fn fee_claims(&self) -> impl Iterator + '_ { - self.instructions() - .iter() - .chain(self.fee_instructions()) - .filter_map(|instruction| { - if let Instruction::ClaimValidatorFees { - epoch, - validator_public_key, - } = instruction - { - Some((Epoch(*epoch), validator_public_key.clone())) - } else { - None - } - }) + match self { + Self::V1(tx) => tx.fee_claims(), + } } pub fn min_epoch(&self) -> Option { - self.transaction.min_epoch + match self { + Self::V1(tx) => tx.min_epoch(), + } } pub fn max_epoch(&self) -> Option { - self.transaction.max_epoch + match self { + Self::V1(tx) => tx.max_epoch(), + } + } + + pub fn schema_version(&self) -> u64 { + match self { + Self::V1(_) => 1, + } } pub fn as_referenced_components(&self) -> impl Iterator + '_ { - self.instructions() - .iter() - .chain(self.fee_instructions()) - .filter_map(|instruction| { - if let Instruction::CallMethod { component_address, .. } = instruction { - Some(component_address) - } else { - None - } - }) + match self { + Self::V1(tx) => tx.as_referenced_components(), + } } /// Returns all substates addresses referenced by this transaction pub fn to_referenced_substates(&self) -> Result, IndexedValueError> { - let all_instructions = self.instructions().iter().chain(self.fee_instructions()); - - let mut substates = HashSet::new(); - for instruction in all_instructions { - match instruction { - Instruction::CallFunction { args, .. } => { - for arg in args.iter().filter_map(|a| a.as_literal_bytes()) { - let value = IndexedValue::from_raw(arg)?; - substates.extend(value.referenced_substates().filter(|id| !id.is_virtual())); - } - }, - Instruction::CallMethod { - component_address, - args, - .. - } => { - substates.insert(SubstateId::Component(*component_address)); - for arg in args.iter().filter_map(|a| a.as_literal_bytes()) { - let value = IndexedValue::from_raw(arg)?; - substates.extend(value.referenced_substates().filter(|id| !id.is_virtual())); - } - }, - Instruction::ClaimBurn { claim } => { - substates.insert(SubstateId::UnclaimedConfidentialOutput(claim.output_address)); - }, - _ => {}, - } - } - Ok(substates) + match self { + Self::V1(tx) => tx.to_referenced_substates(), + } } pub fn has_inputs_without_version(&self) -> bool { - self.inputs().iter().any(|i| i.version().is_none()) + match self { + Self::V1(tx) => tx.has_inputs_without_version(), + } } } impl Display for Transaction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "Transaction[{}, Inputs: {}, Fee Instructions: {}, Instructions: {}, Signatures: {}, Filled Inputs: {}]", - self.id, - self.transaction.inputs.len(), - self.transaction.fee_instructions.len(), - self.transaction.instructions.len(), - self.signatures.len(), - self.filled_inputs.len(), - ) + match self { + Transaction::V1(tx) => write!(f, "{tx}"), + } } } diff --git a/dan_layer/transaction/src/v1.rs b/dan_layer/transaction/src/v1.rs new file mode 100644 index 000000000..eb0e69e22 --- /dev/null +++ b/dan_layer/transaction/src/v1.rs @@ -0,0 +1,250 @@ +// Copyright 2024 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::{collections::HashSet, fmt::Display}; + +use indexmap::IndexSet; +use serde::{Deserialize, Serialize}; +use tari_common_types::types::PublicKey; +use tari_crypto::ristretto::RistrettoSecretKey; +use tari_dan_common_types::{committee::CommitteeInfo, Epoch, SubstateRequirement, VersionedSubstateId}; +use tari_engine_types::{ + hashing::{hasher32, EngineHashDomainLabel}, + indexed_value::{IndexedValue, IndexedValueError}, + instruction::Instruction, + substate::SubstateId, +}; +use tari_template_lib::{models::ComponentAddress, Hash}; + +use crate::{TransactionId, TransactionSignature, UnsignedTransaction}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr( + feature = "ts", + derive(ts_rs::TS), + ts(export, export_to = "../../bindings/src/types/") +)] +pub struct TransactionV1 { + #[cfg_attr(feature = "ts", ts(type = "string"))] + id: TransactionId, + #[serde(flatten)] + transaction: UnsignedTransaction, + signatures: Vec, + /// Inputs filled by some authority. These are not part of the transaction hash nor the signature + filled_inputs: IndexSet, +} + +impl TransactionV1 { + pub fn new(unsigned_transaction: UnsignedTransaction, signatures: Vec) -> Self { + let mut tx = Self { + id: TransactionId::default(), + transaction: unsigned_transaction, + filled_inputs: IndexSet::new(), + signatures, + }; + tx.id = tx.calculate_hash(); + tx + } + + pub fn sign(mut self, secret: &RistrettoSecretKey) -> Self { + let sig = TransactionSignature::sign(secret, &self.transaction); + self.signatures.push(sig); + self.id = self.calculate_hash(); + self + } + + pub fn with_filled_inputs(self, filled_inputs: IndexSet) -> Self { + Self { filled_inputs, ..self } + } + + fn calculate_hash(&self) -> TransactionId { + hasher32(EngineHashDomainLabel::Transaction) + .chain(&self.signatures) + .chain(&self.transaction) + .result() + .into_array() + .into() + } + + pub fn id(&self) -> &TransactionId { + &self.id + } + + pub fn check_id(&self) -> bool { + let id = self.calculate_hash(); + id == self.id + } + + pub fn unsigned_transaction(&self) -> &UnsignedTransaction { + &self.transaction + } + + pub fn hash(&self) -> Hash { + self.id.into_array().into() + } + + pub fn fee_instructions(&self) -> &[Instruction] { + &self.transaction.fee_instructions + } + + pub fn instructions(&self) -> &[Instruction] { + &self.transaction.instructions + } + + pub fn signatures(&self) -> &[TransactionSignature] { + &self.signatures + } + + pub fn verify_all_signatures(&self) -> bool { + if self.signatures.is_empty() { + return false; + } + + self.signatures().iter().all(|sig| sig.verify(&self.transaction)) + } + + pub fn inputs(&self) -> &IndexSet { + &self.transaction.inputs + } + + /// Returns (fee instructions, instructions) + pub fn into_instructions(self) -> (Vec, Vec) { + (self.transaction.fee_instructions, self.transaction.instructions) + } + + pub fn into_parts( + self, + ) -> ( + UnsignedTransaction, + Vec, + IndexSet, + ) { + (self.transaction, self.signatures, self.filled_inputs) + } + + pub fn all_inputs_iter(&self) -> impl Iterator + '_ { + self.inputs() + .iter() + // Filled inputs override other inputs as they are likely filled with versions + .filter(|i| self.filled_inputs().iter().all(|fi| fi.substate_id() != i.substate_id())) + .cloned() + .chain(self.filled_inputs().iter().cloned().map(Into::into)) + } + + pub fn all_inputs_substate_ids_iter(&self) -> impl Iterator + '_ { + self.inputs() + .iter() + // Filled inputs override other inputs as they are likely filled with versions + .filter(|i| self.filled_inputs().iter().all(|fi| fi.substate_id() != i.substate_id())) + .map(|i| i.substate_id()) + .chain(self.filled_inputs().iter().map(|fi| fi.substate_id())) + } + + /// Returns true if the provided committee is involved in at least one input of this transaction. + pub fn is_involved_inputs(&self, committee_info: &CommitteeInfo) -> bool { + self.all_inputs_iter() + .any(|id| committee_info.includes_substate_id(id.substate_id())) + } + + pub fn num_unique_inputs(&self) -> usize { + self.all_inputs_substate_ids_iter().count() + } + + pub fn filled_inputs(&self) -> &IndexSet { + &self.filled_inputs + } + + pub fn filled_inputs_mut(&mut self) -> &mut IndexSet { + &mut self.filled_inputs + } + + pub fn fee_claims(&self) -> impl Iterator + '_ { + self.instructions() + .iter() + .chain(self.fee_instructions()) + .filter_map(|instruction| { + if let Instruction::ClaimValidatorFees { + epoch, + validator_public_key, + } = instruction + { + Some((Epoch(*epoch), validator_public_key.clone())) + } else { + None + } + }) + } + + pub fn min_epoch(&self) -> Option { + self.transaction.min_epoch + } + + pub fn max_epoch(&self) -> Option { + self.transaction.max_epoch + } + + pub fn as_referenced_components(&self) -> impl Iterator + '_ { + self.instructions() + .iter() + .chain(self.fee_instructions()) + .filter_map(|instruction| { + if let Instruction::CallMethod { component_address, .. } = instruction { + Some(component_address) + } else { + None + } + }) + } + + /// Returns all substates addresses referenced by this transaction + pub fn to_referenced_substates(&self) -> Result, IndexedValueError> { + let all_instructions = self.instructions().iter().chain(self.fee_instructions()); + + let mut substates = HashSet::new(); + for instruction in all_instructions { + match instruction { + Instruction::CallFunction { args, .. } => { + for arg in args.iter().filter_map(|a| a.as_literal_bytes()) { + let value = IndexedValue::from_raw(arg)?; + substates.extend(value.referenced_substates().filter(|id| !id.is_virtual())); + } + }, + Instruction::CallMethod { + component_address, + args, + .. + } => { + substates.insert(SubstateId::Component(*component_address)); + for arg in args.iter().filter_map(|a| a.as_literal_bytes()) { + let value = IndexedValue::from_raw(arg)?; + substates.extend(value.referenced_substates().filter(|id| !id.is_virtual())); + } + }, + Instruction::ClaimBurn { claim } => { + substates.insert(SubstateId::UnclaimedConfidentialOutput(claim.output_address)); + }, + _ => {}, + } + } + Ok(substates) + } + + pub fn has_inputs_without_version(&self) -> bool { + self.inputs().iter().any(|i| i.version().is_none()) + } +} + +impl Display for TransactionV1 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "TransactionV1[{}, Inputs: {}, Fee Instructions: {}, Instructions: {}, Signatures: {}, Filled Inputs: {}]", + self.id, + self.transaction.inputs.len(), + self.transaction.fee_instructions.len(), + self.transaction.instructions.len(), + self.signatures.len(), + self.filled_inputs.len(), + ) + } +} diff --git a/dan_layer/wallet/crypto/src/value_lookup/io_reader_value_lookup.rs b/dan_layer/wallet/crypto/src/value_lookup/io_reader_value_lookup.rs index f3ad78349..ce07c89f7 100644 --- a/dan_layer/wallet/crypto/src/value_lookup/io_reader_value_lookup.rs +++ b/dan_layer/wallet/crypto/src/value_lookup/io_reader_value_lookup.rs @@ -77,7 +77,7 @@ impl<'a, R: Read + Seek> IoReaderValueLookup<'a, R> { } } -impl<'a, R: Read + Seek> ValueLookupTable for IoReaderValueLookup<'a, R> { +impl ValueLookupTable for IoReaderValueLookup<'_, R> { type Error = io::Error; fn lookup(&mut self, value: u64) -> Result, Self::Error> { diff --git a/dan_layer/wallet/storage_sqlite/src/writer.rs b/dan_layer/wallet/storage_sqlite/src/writer.rs index 0c76d3dd1..ec5fc6cc9 100644 --- a/dan_layer/wallet/storage_sqlite/src/writer.rs +++ b/dan_layer/wallet/storage_sqlite/src/writer.rs @@ -935,7 +935,7 @@ impl<'a> Deref for WriteTransaction<'a> { } } -impl<'a> DerefMut for WriteTransaction<'a> { +impl DerefMut for WriteTransaction<'_> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.transaction }