diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx index e8fd0daf1..6f2d39d66 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx @@ -83,7 +83,10 @@ export const DealTicket = ({ const order = watch(); watch((orderData) => { - if (orderData.type === OrderType.TYPE_LIMIT && orderData.price === '') { + const persistable = !( + orderData.type === OrderType.TYPE_LIMIT && orderData.price === '' + ); + if (persistable) { setPersistedOrder(orderData as DealTicketFormFields); } }); diff --git a/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx b/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx index 49aaec2da..38583bdcb 100644 --- a/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx +++ b/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx @@ -22,7 +22,11 @@ import { normalizeOrderAmendment, useVegaTransactionStore, } from '@vegaprotocol/wallet'; -import type { VegaTxState, TransactionResult } from '@vegaprotocol/wallet'; +import type { + VegaTxState, + TransactionResult, + OrderTxUpdateFieldsFragment, +} from '@vegaprotocol/wallet'; import { OrderEditDialog } from '../order-list/order-edit-dialog'; import type { OrderSubFieldsFragment } from '../../order-hooks'; import * as Schema from '@vegaprotocol/types'; @@ -203,7 +207,19 @@ export const OrderListManager = ({ fields.limitPrice, fields.size ); - create({ orderAmendment }); + const originalOrder: OrderTxUpdateFieldsFragment = { + type: editOrder.type, + id: editOrder.id, + status: editOrder.status, + createdAt: editOrder.createdAt, + size: editOrder.size, + price: editOrder.price, + timeInForce: editOrder.timeInForce, + expiresAt: editOrder.expiresAt, + side: editOrder.side, + marketId: editOrder.market.id, + }; + create({ orderAmendment }, originalOrder); setEditOrder(null); }} /> diff --git a/libs/wallet/src/use-vega-transaction-store.spec.tsx b/libs/wallet/src/use-vega-transaction-store.spec.tsx index 7d8fa8cfe..bfdcfd3b1 100644 --- a/libs/wallet/src/use-vega-transaction-store.spec.tsx +++ b/libs/wallet/src/use-vega-transaction-store.spec.tsx @@ -2,9 +2,16 @@ import { useVegaTransactionStore } from './use-vega-transaction-store'; import { VegaTxStatus } from './use-vega-transaction'; import type { VegaStoredTxState } from './use-vega-transaction-store'; import type { + OrderAmendmentBody, OrderCancellationBody, WithdrawSubmissionBody, } from './connectors/vega-connector'; +import { + OrderStatus, + OrderTimeInForce, + OrderType, + Side, +} from '@vegaprotocol/types'; jest.mock('./utils', () => ({ ...jest.requireActual('./utils'), @@ -24,6 +31,33 @@ describe('useVegaTransactionStore', () => { }, }, }; + + const orderAmendment: OrderAmendmentBody = { + orderAmendment: { + orderId: + '6a4fcd0ba478df2f284ef5f6d3c64a478cb8043d3afe36f66f92c0ed92631e64', + marketId: + '3aa2a828687cc3d59e92445d294891cbbd40e2165bbfb15674158ef5d4e8848d', + price: '1122', + timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTC, + sizeDelta: 0, + }, + }; + + const originalOrder = { + type: OrderType.TYPE_LIMIT, + id: '6902dea1fa01f0b98cceb382cb9c95df244747fa27ba591de084cdd876d2f7c2', + status: OrderStatus.STATUS_ACTIVE, + createdAt: '2023-03-01T14:08:13.48478Z', + size: '12', + price: '1125', + timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTC, + expiresAt: null, + side: Side.SIDE_BUY, + marketId: + '3aa2a828687cc3d59e92445d294891cbbd40e2165bbfb15674158ef5d4e8848d', + }; + const processedTransactionUpdate = { status: VegaTxStatus.Pending, txHash: 'txHash', @@ -63,6 +97,45 @@ describe('useVegaTransactionStore', () => { VegaTxStatus.Requested, ]); }); + + it('updates an order with order amendment', () => { + useVegaTransactionStore.getState().create(orderAmendment, originalOrder); + useVegaTransactionStore.getState().create(orderAmendment, originalOrder); + useVegaTransactionStore.getState().create(orderAmendment, originalOrder); + const transaction = useVegaTransactionStore.getState().transactions[1]; + useVegaTransactionStore + .getState() + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + .update(transaction!.id, { status: VegaTxStatus.Pending }); + expect( + useVegaTransactionStore.getState().transactions.map((t) => t?.status) + ).toEqual([ + VegaTxStatus.Requested, + VegaTxStatus.Pending, + VegaTxStatus.Requested, + ]); + expect( + useVegaTransactionStore + .getState() + .transactions.map((t) => t?.order?.price) + ).toEqual(['1125', '1125', '1125']); + + const result = { + orderAmendment: { + marketId: + '3aa2a828687cc3d59e92445d294891cbbd40e2165bbfb15674158ef5d4e8848d', + orderId: + '6a4fcd0ba478df2f284ef5f6d3c64a478cb8043d3afe36f66f92c0ed92631e64', + price: '1122', + sizeDelta: 0, + timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTC, + }, + }; + expect( + useVegaTransactionStore.getState().transactions.map((t) => t?.body) + ).toStrictEqual([result, result, result]); + }); + it('sets dialogOpen to false on dismiss', () => { useVegaTransactionStore.getState().create(orderCancellation); useVegaTransactionStore.getState().dismiss(0); @@ -70,6 +143,7 @@ describe('useVegaTransactionStore', () => { useVegaTransactionStore.getState().transactions[0]?.dialogOpen ).toEqual(false); }); + it('updates transaction result', () => { useVegaTransactionStore.getState().create(withdrawSubmission); useVegaTransactionStore.getState().update(0, processedTransactionUpdate); @@ -80,6 +154,7 @@ describe('useVegaTransactionStore', () => { useVegaTransactionStore.getState().transactions[0]?.transactionResult ).toEqual(transactionResult); }); + it('updates withdrawal', () => { useVegaTransactionStore.getState().create(withdrawSubmission); useVegaTransactionStore.getState().update(0, processedTransactionUpdate); diff --git a/libs/wallet/src/use-vega-transaction-store.tsx b/libs/wallet/src/use-vega-transaction-store.tsx index 76014e5b8..bb2a38134 100644 --- a/libs/wallet/src/use-vega-transaction-store.tsx +++ b/libs/wallet/src/use-vega-transaction-store.tsx @@ -33,7 +33,7 @@ export interface VegaStoredTxState extends VegaTxState { } export interface VegaTransactionStore { transactions: (VegaStoredTxState | undefined)[]; - create: (tx: Transaction) => number; + create: (tx: Transaction, order?: OrderTxUpdateFieldsFragment) => number; update: ( index: number, update: Partial< @@ -55,7 +55,7 @@ export interface VegaTransactionStore { export const useVegaTransactionStore = create( subscribeWithSelector((set, get) => ({ transactions: [] as VegaStoredTxState[], - create: (body: Transaction) => { + create: (body: Transaction, order?: OrderTxUpdateFieldsFragment) => { const transactions = get().transactions; const now = new Date(); const transaction: VegaStoredTxState = { @@ -68,6 +68,7 @@ export const useVegaTransactionStore = create( signature: null, status: VegaTxStatus.Requested, dialogOpen: true, + order, }; set({ transactions: transactions.concat(transaction) }); return transaction.id; @@ -165,7 +166,11 @@ export const useVegaTransactionStore = create( // TODO: handle multiple orders from batch market instructions // Note: If multiple orders are submitted the first order ID is determined by hashing the signature of the transaction // (see determineId function). For each subsequent order's ID, a hash of the previous orders ID is used - transaction.order = order; + transaction.order = + isOrderAmendmentTransaction(transaction?.body) && + transaction.order + ? transaction.order // the transaction.order would be the original order amended + : order; transaction.status = VegaTxStatus.Complete; transaction.dialogOpen = true; transaction.updatedAt = new Date();