From 6568fe124a4089ae2b6c91b8c2cb8ce33592bdd0 Mon Sep 17 00:00:00 2001 From: karczuRF Date: Thu, 21 Nov 2024 08:42:51 +0100 Subject: [PATCH 1/5] refactor store --- src/store/provider/provider.action.ts | 80 +++++++++++++++++----- src/store/simulation/simulation.slice.ts | 23 ++++++- src/store/simulation/simulation.types.ts | 10 +++ src/store/transaction/transaction.types.ts | 4 +- 4 files changed, 95 insertions(+), 22 deletions(-) diff --git a/src/store/provider/provider.action.ts b/src/store/provider/provider.action.ts index 688ab16..f92d199 100644 --- a/src/store/provider/provider.action.ts +++ b/src/store/provider/provider.action.ts @@ -7,7 +7,7 @@ import { Transaction, TUProviderMethod } from "../transaction/transaction.types" import { errorActions } from "../error/error.slice" import { RootState } from "../store" import { providerSelector } from "./provider.selector" -import { SubmitTransactionRequest } from "@tari-project/tarijs" +import { SubmitTransactionRequest, TransactionStatus } from "@tari-project/tarijs" import { invoke } from "@tauri-apps/api/core" import { SubstateDiff, @@ -20,9 +20,10 @@ import { ResourceContainer, ResourceAddress, Amount, + RejectReason, } from "@tari-project/typescript-bindings" import { AccountsGetBalancesResponse } from "@tari-project/wallet_jrpc_client" -import { BalanceUpdate } from "../simulation/simulation.types" +import { BalanceUpdate, TxSimulation } from "../simulation/simulation.types" import { ErrorSource } from "../error/error.types" let handleMessage: typeof window.postMessage @@ -31,6 +32,10 @@ const isAccept = (result: TransactionResult): result is { Accept: SubstateDiff } return "Accept" in result } +const isReject = (result: TransactionResult): result is { Reject: RejectReason } => { + return "Reject" in result +} + const isVaultId = (substateId: SubstateId): substateId is { Vault: VaultId } => { return "Vault" in substateId } @@ -66,31 +71,68 @@ export const initializeAction = () => ({ } const { methodName, args, id } = event.data - const _method = methodName as TUProviderMethod - const runSimulation = async () => { + const method = methodName as TUProviderMethod + // tx simulation + const runSimulation = async (): Promise<{ balanceUpdates: BalanceUpdate[]; txSimulation: TxSimulation }> => { if (methodName !== "submitTransaction") { - return [] + return { + balanceUpdates: [], + txSimulation: { + status: TransactionStatus.InvalidTransaction, + errorMsg: `Simulation for ${methodName} not supported`, + }, + } } const transactionReq: SubmitTransactionRequest = { ...args[0], is_dry_run: true } - const tx = await provider.runOne(_method, [transactionReq]) + const tx = await provider.runOne(method, [transactionReq]) + const txReq = await provider.client.waitForTransactionResult({ + transaction_id: tx.transaction_id, + timeout_secs: 10, + }) + console.log("SIMULATION R", txReq) const txReceipt = await provider.getTransactionResult(tx.transaction_id) + const result = txReceipt.status + + console.log("SIMULATION S", result) + console.log("SIMULATION T", txReceipt) + const txResult = txReceipt.result as FinalizeResult | null + if (!txResult?.result) + return { + balanceUpdates: [], + txSimulation: { + status: TransactionStatus.InvalidTransaction, + errorMsg: "Transaction result undefined", + }, + } + + const txSimulation: TxSimulation = { + status: txReceipt.status, + errorMsg: isReject(txResult?.result) ? (txResult.result.Reject as string) : "", + } - const walletBalances: AccountsGetBalancesResponse = await invoke("get_balances", {}) - const txResult = txReceipt.result as FinalizeResult - if (!isAccept(txResult.result)) return [] + if (!isAccept(txResult.result)) return { balanceUpdates: [], txSimulation } - const { up_substates } = txResult.result.Accept + let walletBalances: AccountsGetBalancesResponse + try { + walletBalances = await invoke("get_balances", {}) //TODO + } catch (error) { + console.error(error) + const e = typeof error === "string" ? error : "Get balances error" + dispatch(errorActions.showError({ message: e, errorSource: ErrorSource.FRONTEND })) + } + + const { up_substates } = txResult.result.Accept const balanceUpdates: BalanceUpdate[] = up_substates .map((upSubstate) => { const [substateId, { substate }] = upSubstate - if (!isVaultId(substateId) || !isVaultSubstate(substate)) return - if (!isFungible(substate.Vault.resource_container)) return + if (!isVaultId(substateId) || !isVaultSubstate(substate)) return undefined + if (!isFungible(substate.Vault.resource_container)) return undefined const userBalance = walletBalances.balances.find((balance) => { if (!isVaultId(balance.vault_address)) return false return balance.vault_address.Vault === substateId.Vault }) - if (!userBalance) return + if (!userBalance) return undefined return { vaultAddress: substateId.Vault, tokenSymbol: userBalance.token_symbol || "", @@ -98,12 +140,13 @@ export const initializeAction = () => ({ newBalance: substate.Vault.resource_container.Fungible.amount, } }) - .filter((vault) => vault !== undefined) - return balanceUpdates + .filter((vault): vault is BalanceUpdate => vault !== undefined) + return { balanceUpdates, txSimulation } } + // tx submit const submit = async () => { try { - const result = await provider.runOne(_method, args) + const result = await provider.runOne(method, args) if (event.source) { event.source.postMessage({ id, result, type: "provider-call" }, { targetOrigin: event.origin }) } @@ -113,6 +156,7 @@ export const initializeAction = () => ({ dispatch(errorActions.showError({ message: e, errorSource: ErrorSource.FRONTEND })) } } + // tx cancel const cancel = async () => { if (event.source) { event.source.postMessage( @@ -126,11 +170,11 @@ export const initializeAction = () => ({ cancel, runSimulation, status: "pending", - methodName: _method, + methodName: method, args, id, } - if (_method === "submitTransaction") { + if (method === "submitTransaction") { dispatch(transactionActions.addTransaction({ transaction })) } else { dispatch(transactionActions.sendTransactionRequest({ transaction })) diff --git a/src/store/simulation/simulation.slice.ts b/src/store/simulation/simulation.slice.ts index 22f158e..c058460 100644 --- a/src/store/simulation/simulation.slice.ts +++ b/src/store/simulation/simulation.slice.ts @@ -7,6 +7,7 @@ import { } from "./simulation.types" import { listenerMiddleware } from "../store.listener" import { runTransactionSimulationAction } from "./simulation.action" +import { TransactionStatus } from "@tari-project/tarijs" export const simulationAdapter = createEntityAdapter({ selectId: (simulation: Simulation) => simulation.transactionId, @@ -23,18 +24,36 @@ const simulationSlice = createSlice({ status: "pending", balanceUpdates: [], errorMsg: "", + transaction: { + status: TransactionStatus.DryRun, + errorMsg: "", + }, }) }, runSimulationSuccess: (state, action: PayloadAction) => { simulationAdapter.updateOne(state, { id: action.payload.transactionId, - changes: { status: "success", balanceUpdates: action.payload.balanceUpdates }, + changes: { + status: "success", + balanceUpdates: action.payload.balanceUpdates, + transaction: { + errorMsg: action.payload.transaction.errorMsg, + status: action.payload.transaction.status, + }, + }, }) }, runSimulationFailure: (state, action: PayloadAction) => { simulationAdapter.updateOne(state, { id: action.payload.transactionId, - changes: { status: "failure", errorMsg: action.payload.errorMsg }, + changes: { + status: "failure", + errorMsg: action.payload.errorMsg, + transaction: { + errorMsg: action.payload.transaction.errorMsg, + status: action.payload.transaction.status, + }, + }, }) }, }, diff --git a/src/store/simulation/simulation.types.ts b/src/store/simulation/simulation.types.ts index 4dd7f5f..9bac7e8 100644 --- a/src/store/simulation/simulation.types.ts +++ b/src/store/simulation/simulation.types.ts @@ -1,3 +1,5 @@ +import { TransactionStatus } from "@tari-project/tarijs" + export type SimulationStatus = "pending" | "success" | "failure" export type Simulation = { @@ -5,6 +7,7 @@ export type Simulation = { status: SimulationStatus balanceUpdates: BalanceUpdate[] errorMsg: string + transaction: TxSimulation } export type BalanceUpdate = { @@ -20,8 +23,15 @@ export type SimulationRequestPayload = { export type SimulationSuccessPayload = { transactionId: number balanceUpdates: BalanceUpdate[] + transaction: TxSimulation } export type SimulationFailurePayload = { transactionId: number errorMsg: string + transaction: TxSimulation +} + +export type TxSimulation = { + status: TransactionStatus + errorMsg: string } diff --git a/src/store/transaction/transaction.types.ts b/src/store/transaction/transaction.types.ts index 064637f..06efd02 100644 --- a/src/store/transaction/transaction.types.ts +++ b/src/store/transaction/transaction.types.ts @@ -1,5 +1,5 @@ import { TUInternalProvider } from "@provider/TUInternalProvider" -import { BalanceUpdate } from "../simulation/simulation.types" +import { BalanceUpdate, TxSimulation } from "../simulation/simulation.types" import { SubmitTransactionRequest } from "@tari-project/tarijs" export type TransactionStatus = "pending" | "success" | "failure" | "cancelled" @@ -11,7 +11,7 @@ export type Transaction = { id: number submit: () => void cancel: () => void - runSimulation: () => Promise + runSimulation: () => Promise<{ balanceUpdates: BalanceUpdate[]; txSimulation: TxSimulation }> status: TransactionStatus } From f32fe07f256574cd2ecaf1805d9fa437e584127b Mon Sep 17 00:00:00 2001 From: karczuRF Date: Thu, 21 Nov 2024 08:43:31 +0100 Subject: [PATCH 2/5] improve confirmation dialog --- src/components/TransactionConfirmationModal.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/TransactionConfirmationModal.tsx b/src/components/TransactionConfirmationModal.tsx index 145b6ca..1958ee1 100644 --- a/src/components/TransactionConfirmationModal.tsx +++ b/src/components/TransactionConfirmationModal.tsx @@ -103,9 +103,17 @@ export const TransactionConfirmationModal: React.FC = () => { )} {t("balance-updates", { ns: "components" })}: - {simulation?.balanceUpdates?.map((update) => ( - - ))} + {Array.isArray(simulation?.balanceUpdates) && simulation.balanceUpdates.length > 0 ? ( + simulation.balanceUpdates.map((update) => ) + ) : ( + No balance updates available. // Optional: Provide feedback if there are no updates + )} + + + {t("tx-simulation-status", { ns: "components" })}: {simulation?.transaction?.status ?? "-"} + + + {t("tx-simulation-error-msg", { ns: "components" })}: {simulation?.transaction?.errorMsg ?? "-"} From d4bfc2149948e4384165e5672b43198bcae3bfc1 Mon Sep 17 00:00:00 2001 From: karczuRF Date: Thu, 21 Nov 2024 08:43:40 +0100 Subject: [PATCH 3/5] add translations --- locales/en/components.json | 4 +++- locales/pl/components.json | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/locales/en/components.json b/locales/en/components.json index cb5fd8c..15e4839 100644 --- a/locales/en/components.json +++ b/locales/en/components.json @@ -18,5 +18,7 @@ "create-account": "New account", "open-logs-directory": "Logs", "simulation-status": "Simulation status", - "simulation-error-msg": "Simulation error" + "simulation-error-msg": "Simulation error message", + "tx-simulation-status": "Simulated transaction error", + "tx-simulation-error-msg": "Simulated tx error message" } diff --git a/locales/pl/components.json b/locales/pl/components.json index e9c7946..b0d816d 100644 --- a/locales/pl/components.json +++ b/locales/pl/components.json @@ -18,5 +18,7 @@ "create-account": "Dodaj nowe konto", "open-logs-directory": "Logi", "simulation-status": "Status symulacji", - "simulation-error-msg": "Błąd symulacji" + "simulation-error-msg": "Błąd symulacji", + "tx-simulation-status": "Status symulowanej transakcji", + "tx-simulation-error-msg": "Błąd symulowanej transakcji" } From 71f4cca93a27055df8298621d7697a0714bbbabc Mon Sep 17 00:00:00 2001 From: karczuRF Date: Thu, 21 Nov 2024 10:48:24 +0100 Subject: [PATCH 4/5] fix front bugs --- locales/en/components.json | 5 +- locales/pl/components.json | 3 +- .../TransactionConfirmationModal.tsx | 46 ++++++------------- src/helpers/transaction.ts | 31 +++++++++++++ src/store/simulation/simulation.action.ts | 27 +++++++++-- 5 files changed, 72 insertions(+), 40 deletions(-) create mode 100644 src/helpers/transaction.ts diff --git a/locales/en/components.json b/locales/en/components.json index 15e4839..607901e 100644 --- a/locales/en/components.json +++ b/locales/en/components.json @@ -19,6 +19,7 @@ "open-logs-directory": "Logs", "simulation-status": "Simulation status", "simulation-error-msg": "Simulation error message", - "tx-simulation-status": "Simulated transaction error", - "tx-simulation-error-msg": "Simulated tx error message" + "tx-simulation-status": "Simulated transaction status", + "tx-simulation-error-msg": "Simulated tx error message", + "no-balance-update": "No balance updates available." } diff --git a/locales/pl/components.json b/locales/pl/components.json index b0d816d..0b80289 100644 --- a/locales/pl/components.json +++ b/locales/pl/components.json @@ -20,5 +20,6 @@ "simulation-status": "Status symulacji", "simulation-error-msg": "Błąd symulacji", "tx-simulation-status": "Status symulowanej transakcji", - "tx-simulation-error-msg": "Błąd symulowanej transakcji" + "tx-simulation-error-msg": "Błąd symulowanej transakcji", + "no-balance-update": "Aktualizacja balansów niedostępna" } diff --git a/src/components/TransactionConfirmationModal.tsx b/src/components/TransactionConfirmationModal.tsx index 1958ee1..9ae8a9a 100644 --- a/src/components/TransactionConfirmationModal.tsx +++ b/src/components/TransactionConfirmationModal.tsx @@ -10,9 +10,9 @@ import { simulationActions } from "../store/simulation/simulation.slice" import { BalanceUpdateView } from "./BalanceUpdate" import { useTranslation } from "react-i18next" import { ErrorSource } from "../store/error/error.types" -import { CallFunction, CallMethod } from "@tari-project/tarijs/dist/builders/types/Instruction" import { resolveBackendErrorMessage } from "./ErrorSnackBar" import { metadataSelector } from "../store/metadata/metadata.selector" +import { getFunctionOrMethod, getTransactionStatusName } from "../helpers/transaction" const selectSimulationById = (state: RootState, id?: number) => (id ? simulationsSelectors.selectById(state, id) : null) @@ -50,31 +50,6 @@ export const TransactionConfirmationModal: React.FC = () => { ) } - interface InstructionWithArgs { - instructionName: string - args: any[] - } - // Function to get function or method fields - function getFunctionOrMethod(instructions: object[]): InstructionWithArgs[] { - let functionNames: InstructionWithArgs[] = [] - instructions.forEach((instruction) => { - // Check if the instruction is an object and not a string - if (typeof instruction === "object" && instruction !== null) { - if ("CallFunction" in instruction) { - const callFunction = instruction as CallFunction - functionNames.push({ - instructionName: callFunction.CallFunction.function, - args: callFunction.CallFunction.args, - }) - } else if ("CallMethod" in instruction) { - const callMethod = instruction as CallMethod - functionNames.push({ instructionName: callMethod.CallMethod.method, args: callMethod.CallMethod.args }) - } - } - }) - return functionNames - } - return ( {t("transaction-confirmation", { ns: "components" })}: @@ -88,7 +63,7 @@ export const TransactionConfirmationModal: React.FC = () => { {getFunctionOrMethod(arg.instructions) .flatMap((i) => i.instructionName + " with args: " + i.args) .map((instruction, index) => ( -
{instruction}
// Using
or to wrap each instruction +
{instruction}
))} ))} @@ -102,19 +77,24 @@ export const TransactionConfirmationModal: React.FC = () => { )} - {t("balance-updates", { ns: "components" })}: + {t("balance-updates", { ns: "components" })}:{" "} {Array.isArray(simulation?.balanceUpdates) && simulation.balanceUpdates.length > 0 ? ( simulation.balanceUpdates.map((update) => ) ) : ( - No balance updates available. // Optional: Provide feedback if there are no updates + {t("no-balance-update", { ns: "components" })} )} - {t("tx-simulation-status", { ns: "components" })}: {simulation?.transaction?.status ?? "-"} - - - {t("tx-simulation-error-msg", { ns: "components" })}: {simulation?.transaction?.errorMsg ?? "-"} + {t("tx-simulation-status", { ns: "components" })}: {getTransactionStatusName(simulation?.transaction?.status)} + {simulation?.transaction.errorMsg && ( + + {t("tx-simulation-error-msg", { ns: "components" })}:{" "} + {typeof simulation?.transaction?.errorMsg === "string" + ? simulation.transaction.errorMsg + : JSON.stringify(simulation?.transaction?.errorMsg)} + + )}