Compare commits

...
Author SHA1 Message Date
Dariusz Majcherczyk bd1d5f1e2b test: lint fix 2023-07-11 22:40:29 +02:00
Dariusz Majcherczyk aca72f075a test: fix lint 2023-07-11 22:36:37 +02:00
Dariusz Majcherczyk dce766a036 test: fix capsule place order 2023-07-11 22:28:05 +02:00
Matthew Russell 981c8649a2 fix(trading): replace oracle details and deal ticket pink with red (#4284) 2023-07-11 14:26:24 +01:00
Bartłomiej Głownia 501ffbfc80 chore(trading): ignore parse source map warnings, fix trading readme (#4252) 2023-07-11 10:41:54 +01:00
Mikołaj Młodzikowski f391e8c351 fix(ci): add different settings to curl and print preview link 2023-07-10 15:53:38 +02:00
Edd 0e10b2108e chore(explorer): update block explorer types for 72 (#4275) 2023-07-10 14:12:12 +01:00
Bartłomiej Głownia 162a934408 feat(trading): amend market red and green colors (#4226) 2023-07-07 14:52:38 +02:00
Joe Tsang 4581e117c4 test(cypress): clean up nx todos (#4273) 2023-07-07 09:23:27 +01:00
Bartłomiej Głownia e89b818e4c feat(orders): reduce number of columns in orders table (#4238) 2023-07-06 17:57:29 +02:00
daro-maj 0665ac85db test(trading): add withdrawal delayed (#4268) 2023-07-06 15:49:02 +02:00
Joe Tsang 3c71a86b48 chore(governance): skip test (#4263) 2023-07-06 09:40:57 +01:00
Art b381f16ace fix(announcements): remember dismissed announcement (#4255) 2023-07-05 16:59:22 +02:00
Matthew Russellandsam-keen fc6ce9e99b fix(governance,trading): proposals not showing (#4222)
Co-authored-by: sam-keen <samuel.kleinmann@gmail.com>
2023-07-05 14:09:13 +01:00
Art f6fc4df1c5 chore(trading): dropdown alignments, account history default asset, transfer dialog asset selector (#4239) 2023-07-05 13:02:02 +02:00
Art fc8f12d6fc fix(proposals): truncated text in network param toast (#4249) 2023-07-05 12:50:42 +02:00
Gordsport 26f4c1c983 feat(governance,explorer,trading): add env config for mainnet-mirror apps (#4253) 2023-07-04 16:20:40 +00:00
Maciek efd632f5c6 chore(orders): get rid of unnecessary stores (#4231) 2023-07-04 17:47:04 +02:00
100 changed files with 1240 additions and 1211 deletions
+8 -8
View File
@@ -241,26 +241,26 @@ jobs:
# https://stackoverflow.com/questions/3183444/check-for-valid-link-url
regex='(https?|ftp|file)://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
if [[ "${{ needs.lint-test-build.outputs.preview_governance }}" =~ $regex ]]; then
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_governance }}"; do
echo "waiting for governance preview"
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_governance }}"; do
echo "waiting for governance preview: ${{ needs.lint-test-build.outputs.preview_governance }}"
sleep 5
done
fi
if [[ "${{ needs.lint-test-build.outputs.preview_explorer }}" =~ $regex ]]; then
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_explorer }}"; do
echo "waiting for explorer preview"
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_explorer }}"; do
echo "waiting for explorer preview: ${{ needs.lint-test-build.outputs.preview_explorer }}"
sleep 5
done
fi
if [[ "${{ needs.lint-test-build.outputs.preview_trading }}" =~ $regex ]]; then
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_trading }}"; do
echo "waiting for trading preview"
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_trading }}"; do
echo "waiting for trading preview: ${{ needs.lint-test-build.outputs.preview_trading }}"
sleep 5
done
fi
if [[ "${{ needs.lint-test-build.outputs.preview_tools }}" =~ $regex ]]; then
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_tools }}"; do
echo "waiting for tools preview"
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_tools }}"; do
echo "waiting for tools preview: ${{ needs.lint-test-build.outputs.preview_tools }}"
sleep 5
done
fi
@@ -31,7 +31,7 @@ context('Asset page', { tags: '@regression' }, () => {
});
});
it('should open details page when clicked on "View details"', () => {
it.skip('should open details page when clicked on "View details"', () => {
cy.getAssets().then((assets) => {
assets.forEach((asset) => {
cy.get(`[row-id="${asset.id}"] [col-id="actions"] button`)
@@ -27,11 +27,6 @@ context('Home Page', function () {
16: 'Chain ID',
};
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('[data-testid="stats-title"]')
.each(($list, index) => {
cy.wrap($list).should('contain.text', statTitles[index]);
@@ -34,11 +34,6 @@ context('Network parameters page', { tags: '@smoke' }, function () {
const parameterName = network_parameter[0];
const parameterValue = network_parameter[1];
if (this.networkParameterFormat.json.includes(parameterName)) {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(tableRows)
.contains(parameterName)
.should('be.visible')
@@ -70,11 +65,6 @@ context('Network parameters page', { tags: '@smoke' }, function () {
if (this.networkParameterFormat.percentage.includes(parameterName)) {
const formattedPercentageParameter =
(parseFloat(parameterValue) * 100).toFixed(0) + '%';
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(tableRows)
.contains(parameterName)
.should('be.visible')
@@ -158,11 +148,6 @@ context('Network parameters page', { tags: '@smoke' }, function () {
cy.convert_number_to_max_four_decimal(parameterValue)
.add_commas_to_number_if_large_enough()
.then((parameterValueFormatted) => {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(tableRows)
.contains(parameterName)
.should('be.visible')
@@ -194,11 +179,6 @@ context('Network parameters page', { tags: '@smoke' }, function () {
cy.convert_number_to_max_eighteen_decimal(parameterValue)
.add_commas_to_number_if_large_enough()
.then((parameterValueFormatted) => {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(tableRows)
.contains(parameterName)
.should('be.visible')
@@ -169,12 +169,6 @@ context.skip('Parties page', { tags: '@regression' }, function () {
const jsonFields = '.hljs';
const sideMenuBackground = '.absolute';
// Engage dark mode if not allready set
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(sideMenuBackground)
.should('have.css', 'background-color')
.then((background_color) => {
@@ -60,31 +60,16 @@ context.skip('Transactions page', function () {
});
cy.get('block').should('not.be.empty');
cy.get('encoded-tnx').should('not.be.empty');
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('tx-type')
.should('not.be.empty')
.invoke('text')
.then((txTypeTxt) => {
if (txTypeTxt == 'Order Submission') {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('.hljs-attr')
.should('have.length.at.least', 8)
.each(($propertyName) => {
cy.wrap($propertyName).should('not.be.empty');
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('.hljs-string')
.should('have.length.at.least', 8)
.each(($propertyValue) => {
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/tm
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_ENV=DEVNET
+13
View File
@@ -0,0 +1,13 @@
# App configuration variables
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_URL=https://api.mainnet-mirror.vega.rocks/graphql
NX_VEGA_ENV=MAINNET-MIRROR
NX_BLOCK_EXPLORER=https://be.mainnet-mirror.vega.rocks/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://governance.mainnet-mirror.vega.rocks
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks/
NX_VEGA_CONSOLE_URL=https://console.mainnet-mirror.vega.rocks
+1
View File
@@ -32,6 +32,7 @@ yarn nx serve explorer
Example configurations are provided here:
- [Mainnet](./.env.mainnet)
- [Mainnet-mirror](./.env.mainnet-mirror)
- [Devnet](./.env.devnet)
- [Capsule](./.env.capsule)
- [Testnet](./.env.testnet)
+1 -1
View File
@@ -77,7 +77,7 @@
"executor": "nx:run-commands",
"options": {
"commands": [
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.71.4/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/spec-update-v0.72.0-preview.2/specs/v0.72.0-preview.2/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
]
}
},
@@ -6,10 +6,32 @@ import {
SPECIAL_CASE_NETWORK_ID,
} from '../../../../links/party-link/party-link';
import SizeInAsset from '../../../../size-in-asset/size-in-asset';
import { AccountTypeMapping } from '@vegaprotocol/types';
import { AccountType } from '@vegaprotocol/types';
import { headerClasses, wrapperClasses } from '../transfer-details';
import type { Transfer } from '../transfer-details';
import type { components } from '../../../../../../types/explorer';
type Transfer = components['schemas']['commandsv1Transfer'];
type AccountTypes = components['schemas']['vegaAccountType'];
const AccountType: Record<AccountTypes, string> = {
ACCOUNT_TYPE_UNSPECIFIED: 'Unspecified',
ACCOUNT_TYPE_INSURANCE: 'Insurance',
ACCOUNT_TYPE_SETTLEMENT: 'Settlement',
ACCOUNT_TYPE_MARGIN: 'Margin',
ACCOUNT_TYPE_GENERAL: 'General',
ACCOUNT_TYPE_FEES_INFRASTRUCTURE: 'Infrastructure',
ACCOUNT_TYPE_FEES_LIQUIDITY: 'Liquidity',
ACCOUNT_TYPE_FEES_MAKER: 'Maker',
ACCOUNT_TYPE_BOND: 'Bond',
ACCOUNT_TYPE_EXTERNAL: 'External',
ACCOUNT_TYPE_GLOBAL_INSURANCE: 'Global Insurance',
ACCOUNT_TYPE_GLOBAL_REWARD: 'Global Reward',
ACCOUNT_TYPE_PENDING_TRANSFERS: 'Pending Transfers',
ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES: 'Maker Paid Fees',
ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES: 'Maker Received Fees',
ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES: 'LP Received Fees',
ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS: 'Market Proposers',
ACCOUNT_TYPE_HOLDING: 'Holding',
};
interface TransferParticipantsProps {
transfer: Transfer;
@@ -30,22 +52,22 @@ export function TransferParticipants({
}: TransferParticipantsProps) {
// This mapping is required as the global account types require a type to be set, while
// the underlying protobufs allow for every field to be undefined.
const fromAcct =
const fromAcct: AccountTypes =
transfer.fromAccountType &&
transfer.fromAccountType !== 'ACCOUNT_TYPE_UNSPECIFIED'
? AccountType[transfer.fromAccountType]
: AccountType.ACCOUNT_TYPE_GENERAL;
const fromAccountTypeLabel = transfer.fromAccountType
? AccountTypeMapping[fromAcct]
? transfer.fromAccountType
: 'ACCOUNT_TYPE_GENERAL';
const fromAccountTypeLabel: string = transfer.fromAccountType
? AccountType[fromAcct]
: 'Unknown';
const toAcct =
const toAcct: AccountTypes =
transfer.toAccountType &&
transfer.toAccountType !== 'ACCOUNT_TYPE_UNSPECIFIED'
? AccountType[transfer.toAccountType]
: AccountType.ACCOUNT_TYPE_GENERAL;
? transfer.toAccountType
: 'ACCOUNT_TYPE_GENERAL';
const toAccountTypeLabel = transfer.fromAccountType
? AccountTypeMapping[toAcct]
? AccountType[toAcct]
: 'Unknown';
return (
@@ -27,9 +27,9 @@ export function TransferRepeat({ recurring }: TransferRepeatProps) {
<div className={wrapperClasses}>
<h2 className={headerClasses}>{t('Active epochs')}</h2>
<div className="relative block rounded-lg py-6 text-center p-6">
<p>
<div>
<EpochOverview id={recurring.startEpoch} />
</p>
</div>
<p className="leading-10 my-2">
<IconForEpoch
start={recurring.startEpoch}
@@ -37,13 +37,13 @@ export function TransferRepeat({ recurring }: TransferRepeatProps) {
current={data?.epoch.id}
/>
</p>
<p>
<div>
{recurring.endEpoch ? (
<EpochOverview id={recurring.endEpoch} />
) : (
<span>{t('Forever')}</span>
)}
</p>
</div>
</div>
</div>
);
@@ -8,7 +8,7 @@ import { DispatchMetricLabels } from '@vegaprotocol/types';
export type Metric = components['schemas']['vegaDispatchMetric'];
export type Strategy = components['schemas']['vegaDispatchStrategy'];
const metricLabels = {
const metricLabels: Record<Metric, string> = {
DISPATCH_METRIC_UNSPECIFIED: 'Unknown metric',
...DispatchMetricLabels,
};
@@ -3,7 +3,7 @@ import { TransferRepeat } from './blocks/transfer-repeat';
import { TransferRewards } from './blocks/transfer-rewards';
import { TransferParticipants } from './blocks/transfer-participants';
export type Recurring = components['schemas']['v1RecurringTransfer'];
export type Recurring = components['schemas']['commandsv1RecurringTransfer'];
export type Metric = components['schemas']['vegaDispatchMetric'];
export const wrapperClasses =
@@ -16,7 +16,7 @@ interface StringMap {
const displayString: StringMap = {
OrderSubmission: 'Order Submission',
'Submit Order': 'Order',
OrderCancellation: 'Order Cancellation',
OrderCancellation: 'Cancel order',
OrderAmendment: 'Order Amendment',
VoteSubmission: 'Vote Submission',
WithdrawSubmission: 'Withdraw Submission',
@@ -44,8 +44,27 @@ const displayString: StringMap = {
ValidatorHeartbeat: 'Heartbeat',
'Validator Heartbeat': 'Heartbeat',
'Batch Market Instructions': 'Batch',
'Stop Orders Submission': 'Stop',
StopOrdersSubmission: 'Stop',
StopOrdersCancellation: 'Cancel stop',
'Stop Orders Cancellation': 'Cancel stop',
};
export function getLabelForOrderType(
orderType: string,
command: components['schemas']['v1InputData']
): string {
if (command.orderSubmission) {
if (command.orderSubmission.peggedOrder) {
return 'Peg';
}
if (command.orderSubmission.icebergOpts) {
return 'Iceberg';
}
}
return 'Order';
}
/**
* Given a proposal, will return a specific label
* @param chainEvent
@@ -117,6 +136,8 @@ export function getLabelForChainEvent(
return t('Signer threshold');
}
return t('Multisig update');
} else if (chainEvent.contractCall) {
return t('Contract call');
}
return t('Chain Event');
}
+398 -72
View File
@@ -3,7 +3,7 @@
* Do not make direct changes to the file.
*/
/** Type helpers */
/** OneOf type helpers */
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
type XOR<T, U> = T | U extends object
? (Without<T, U> & U) | (Without<U, T> & T)
@@ -41,6 +41,8 @@ export interface paths {
};
}
export type webhooks = Record<string, never>;
export interface components {
schemas: {
/**
@@ -101,6 +103,17 @@ export interface components {
| 'TIME_IN_FORCE_FOK'
| 'TIME_IN_FORCE_GFA'
| 'TIME_IN_FORCE_GFN';
/**
* @description - EXPIRY_STRATEGY_UNSPECIFIED: Never valid
* - EXPIRY_STRATEGY_CANCELS: Stop order should be cancelled if the expiry time is reached.
* - EXPIRY_STRATEGY_SUBMIT: Order should be submitted if the expiry time is reached.
* @default EXPIRY_STRATEGY_UNSPECIFIED
* @enum {string}
*/
readonly StopOrderExpiryStrategy:
| 'EXPIRY_STRATEGY_UNSPECIFIED'
| 'EXPIRY_STRATEGY_CANCELS'
| 'EXPIRY_STRATEGY_SUBMIT';
/**
* @default METHOD_UNSPECIFIED
* @enum {string}
@@ -143,6 +156,36 @@ export interface components {
/** Type of transaction */
readonly type?: string;
};
/** Request for cancelling a recurring transfer */
readonly commandsv1CancelTransfer: {
/** @description Transfer ID of the transfer to cancel. */
readonly transferId?: string;
};
/** Specific details for a one off transfer */
readonly commandsv1OneOffTransfer: {
/**
* Format: int64
* @description Timestamp in Unix nanoseconds for when the transfer should be delivered into the receiver's account.
*/
readonly deliverOn?: string;
};
/** Specific details for a recurring transfer */
readonly commandsv1RecurringTransfer: {
/** @description Optional parameter defining how a transfer is dispatched. */
readonly dispatchStrategy?: components['schemas']['vegaDispatchStrategy'];
/**
* Format: uint64
* @description Last epoch at which this transfer shall be paid.
*/
readonly endEpoch?: string;
/** @description Factor needs to be > 0. */
readonly factor?: string;
/**
* Format: uint64
* @description First epoch from which this transfer shall be paid.
*/
readonly startEpoch?: string;
};
/** Transfer initiated by a party */
readonly commandsv1Transfer: {
/** @description Amount to be taken from the source account. This field is an unsigned integer scaled to the asset's decimal places. */
@@ -154,8 +197,8 @@ export interface components {
* should be taken.
*/
readonly fromAccountType?: components['schemas']['vegaAccountType'];
readonly oneOff?: components['schemas']['v1OneOffTransfer'];
readonly recurring?: components['schemas']['v1RecurringTransfer'];
readonly oneOff?: components['schemas']['commandsv1OneOffTransfer'];
readonly recurring?: components['schemas']['commandsv1RecurringTransfer'];
/** @description Reference to be attached to the transfer. */
readonly reference?: string;
/** @description Public key of the destination account. */
@@ -171,8 +214,19 @@ export interface components {
};
readonly protobufAny: {
readonly '@type'?: string;
[key: string]: unknown | undefined;
[key: string]: unknown;
};
/**
* @description `NullValue` is a singleton enumeration to represent the null value for the
* `Value` type union.
*
* The JSON representation for `NullValue` is JSON `null`.
*
* - NULL_VALUE: Null value.
* @default NULL_VALUE
* @enum {string}
*/
readonly protobufNullValue: 'NULL_VALUE';
/** Used to announce a node as a new pending validator */
readonly v1AnnounceNode: {
/** @description AvatarURL of the validator. */
@@ -225,18 +279,19 @@ export interface components {
readonly amendments?: readonly components['schemas']['v1OrderAmendment'][];
/** @description List of order cancellations to be processed sequentially. */
readonly cancellations?: readonly components['schemas']['v1OrderCancellation'][];
/** @description List of stop order cancellations to be processed sequentially. */
readonly stopOrdersCancellation?: readonly components['schemas']['v1StopOrdersCancellation'][];
/** @description List of stop order submissions to be processed sequentially. */
readonly stopOrdersSubmission?: readonly components['schemas']['v1StopOrdersSubmission'][];
/** @description List of order submissions to be processed sequentially. */
readonly submissions?: readonly components['schemas']['v1OrderSubmission'][];
};
/** Request for cancelling a recurring transfer */
readonly v1CancelTransfer: {
/** @description Transfer ID of the transfer to cancel. */
readonly transferId?: string;
};
/** Event forwarded to the Vega network to provide information on events happening on other networks */
readonly v1ChainEvent: {
/** @description Built-in asset event. */
readonly builtin?: components['schemas']['vegaBuiltinAssetEvent'];
/** Arbitrary contract call */
readonly contractCall?: components['schemas']['vegaEthContractCallEvent'];
/** @description Ethereum ERC20 event. */
readonly erc20?: components['schemas']['vegaERC20Event'];
/** @description Ethereum ERC20 multisig event. */
@@ -301,6 +356,19 @@ export interface components {
/** Transaction corresponding to the hash */
readonly transaction?: components['schemas']['blockexplorerapiv1Transaction'];
};
/** Iceberg order options */
readonly v1IcebergOpts: {
/**
* Format: uint64
* @description Minimum allowed remaining size of the order before it is replenished back to its peak size.
*/
readonly minimumVisibleSize?: string;
/**
* Format: uint64
* @description Size of the order that is made visible and can be traded with during the execution of a single order.
*/
readonly peakSize?: string;
};
readonly v1InfoResponse: {
/** Commit hash from which the data node was built */
readonly commitHash?: string;
@@ -325,7 +393,7 @@ export interface components {
*/
readonly blockHeight?: string;
/** @description Command to request cancelling a recurring transfer. */
readonly cancelTransfer?: components['schemas']['v1CancelTransfer'];
readonly cancelTransfer?: components['schemas']['commandsv1CancelTransfer'];
/**
* @description Command used by a validator to submit an event forwarded to the Vega network to provide information
* on events happening on other networks, to be used by a foreign chain
@@ -381,6 +449,10 @@ export interface components {
readonly protocolUpgradeProposal?: components['schemas']['v1ProtocolUpgradeProposal'];
/** @description Command used by a validator to submit a floating point value. */
readonly stateVariableProposal?: components['schemas']['v1StateVariableProposal'];
/** @description Command to cancel stop orders. */
readonly stopOrdersCancellation?: components['schemas']['v1StopOrdersCancellation'];
/** @description Command to submit a pair of stop orders. */
readonly stopOrdersSubmission?: components['schemas']['v1StopOrdersSubmission'];
/** @description Command to submit a transfer. */
readonly transfer?: components['schemas']['commandsv1Transfer'];
/** @description Command to remove tokens delegated to a validator. */
@@ -448,9 +520,9 @@ export interface components {
readonly commitmentAmount?: string;
/** @description Nominated liquidity fee factor, which is an input to the calculation of taker fees on the market, as per setting fees and rewarding liquidity providers. */
readonly fee?: string;
/** @description Market ID for the order, required field. */
/** @description Market ID for the order. */
readonly marketId?: string;
/** @description Reference to be added to every order created out of this liquidityProvisionSubmission. */
/** @description Reference to be added to every order created out of this liquidity provision submission. */
readonly reference?: string;
/** @description Set of liquidity sell orders to meet the liquidity provision obligation. */
readonly sells?: readonly components['schemas']['vegaLiquidityOrder'][];
@@ -530,15 +602,6 @@ export interface components {
| 'TYPE_STAKE_TOTAL_SUPPLY'
| 'TYPE_SIGNER_THRESHOLD_SET'
| 'TYPE_GOVERNANCE_VALIDATE_ASSET';
/** Specific details for a one off transfer */
readonly v1OneOffTransfer: {
/**
* Format: int64
* @description Unix timestamp in nanoseconds. Time at which the
* transfer should be delivered into the To account.
*/
readonly deliverOn?: string;
};
/** Command to submit new Oracle data from third party providers */
readonly v1OracleDataSubmission: {
/**
@@ -596,10 +659,12 @@ export interface components {
readonly v1OrderSubmission: {
/**
* Format: int64
* @description Timestamp for when the order will expire, in nanoseconds,
* @description Timestamp in Unix nanoseconds for when the order will expire,
* required field only for `Order.TimeInForce`.TIME_IN_FORCE_GTT`.
*/
readonly expiresAt?: string;
/** @description Parameters used to specify an iceberg order. */
readonly icebergOpts?: components['schemas']['v1IcebergOpts'];
/** @description Market ID for the order, required field. */
readonly marketId?: string;
/** @description Used to specify the details for a pegged order. */
@@ -699,23 +764,6 @@ export interface components {
readonly v1PubKey: {
readonly key?: string;
};
/** Specific details for a recurring transfer */
readonly v1RecurringTransfer: {
/** @description Optional parameter defining how a transfer is dispatched. */
readonly dispatchStrategy?: components['schemas']['vegaDispatchStrategy'];
/**
* Format: uint64
* @description Last epoch at which this transfer shall be paid.
*/
readonly endEpoch?: string;
/** @description Factor needs to be > 0. */
readonly factor?: string;
/**
* Format: uint64
* @description First epoch from which this transfer shall be paid.
*/
readonly startEpoch?: string;
};
/**
* @description Signature to authenticate a transaction and to be verified by the Vega
* network.
@@ -732,7 +780,7 @@ export interface components {
readonly version?: number;
};
readonly v1Signer: {
/** In case of an open oracle - Ethereum address will be submitted */
/** @description In case of an open oracle - Ethereum address will be submitted. */
readonly ethAddress?: components['schemas']['v1ETHAddress'];
/**
* @description List of authorized public keys that signed the data for this
@@ -746,6 +794,55 @@ export interface components {
/** @description State value proposal details. */
readonly proposal?: components['schemas']['vegaStateValueProposal'];
};
/** Price and expiry configuration for a stop order */
readonly v1StopOrderSetup: {
/**
* Format: int64
* @description Optional expiry timestamp.
*/
readonly expiresAt?: string;
/** @description Strategy to adopt if the expiry time is reached. */
readonly expiryStrategy?: components['schemas']['StopOrderExpiryStrategy'];
/** @description Order to be submitted once the trigger is breached. */
readonly orderSubmission?: components['schemas']['v1OrderSubmission'];
/** @description Fixed price at which the order will be submitted. */
readonly price?: string;
/** @description Trailing percentage at which the order will be submitted. */
readonly trailingPercentOffset?: string;
};
/**
* Cancel a stop order.
* The following combinations are available:
* Empty object will cancel all stop orders for the party
* Market ID alone will cancel all stop orders in a market
* Market ID and order ID will cancel a specific stop order in a market
* If the stop order is part of an OCO, both stop orders will be cancelled
*/
readonly v1StopOrdersCancellation: {
/** @description Optional market ID. */
readonly marketId?: string;
/** @description Optional order ID. */
readonly stopOrderId?: string;
};
/**
* Stop order submission submits stops orders.
* It is possible to make a single stop order submission by
* specifying a single direction,
* or an OCO (One Cancels the Other) stop order submission
* by specifying a configuration for both directions
*/
readonly v1StopOrdersSubmission: {
/**
* @description Stop order that will be triggered
* if the price falls below a given trigger price.
*/
readonly fallsBelow?: components['schemas']['v1StopOrderSetup'];
/**
* @description Stop order that will be triggered
* if the price rises above a given trigger price.
*/
readonly risesAbove?: components['schemas']['v1StopOrderSetup'];
};
readonly v1UndelegateSubmission: {
/**
* @description Optional, if not specified = ALL.
@@ -822,6 +919,7 @@ export interface components {
* - ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES: Per asset reward account for fees received by makers
* - ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES: Per asset reward account for fees received by liquidity providers
* - ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS: Per asset reward account for market proposers when the market goes above some trading threshold
* - ACCOUNT_TYPE_HOLDING: Per asset account for holding in-flight unfilled orders' funds
* @default ACCOUNT_TYPE_UNSPECIFIED
* @enum {string}
*/
@@ -842,7 +940,8 @@ export interface components {
| 'ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES'
| 'ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES'
| 'ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES'
| 'ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS';
| 'ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS'
| 'ACCOUNT_TYPE_HOLDING';
/** Vega representation of an external asset */
readonly vegaAssetDetails: {
/** @description Vega built-in asset. */
@@ -898,6 +997,14 @@ export interface components {
/** @description Vega network internal asset ID. */
readonly vegaAssetId?: string;
};
readonly vegaCancelTransfer: {
/** Configuration for cancellation of a governance-initiated transfer */
readonly changes?: components['schemas']['vegaCancelTransferConfiguration'];
};
readonly vegaCancelTransferConfiguration: {
/** @description ID of the governance transfer proposal. */
readonly transferId?: string;
};
/**
* @description DataSourceDefinition represents the top level object that deals with data sources.
* DataSourceDefinition can be external or internal, with whatever number of data sources are defined
@@ -912,6 +1019,7 @@ export interface components {
* It contains one of any of the defined `SourceType` variants.
*/
readonly vegaDataSourceDefinitionExternal: {
readonly ethCall?: components['schemas']['vegaEthCallSpec'];
readonly oracle?: components['schemas']['vegaDataSourceSpecConfiguration'];
};
/**
@@ -1147,6 +1255,64 @@ export interface components {
/** @description Address into which the bridge will release the funds. */
readonly receiverAddress?: string;
};
/** @description Specifies a data source that derives its content from calling a read method on an Ethereum contract. */
readonly vegaEthCallSpec: {
/** @description The ABI of that contract. */
readonly abi?: readonly Record<string, never>[];
/** @description Ethereum address of the contract to call. */
readonly address?: string;
/**
* @description List of arguments to pass to method call.
* Protobuf 'Value' wraps an arbitrary JSON type that is mapped to an Ethereum type according to the ABI.
*/
readonly args?: readonly Record<string, never>[];
/** @description Name of the method on the contract to call. */
readonly method?: string;
/** @description Conditions for determining when to call the contract method. */
readonly trigger?: components['schemas']['vegaEthCallTrigger'];
};
/** @description Determines when the contract method should be called. */
readonly vegaEthCallTrigger: {
readonly timeTrigger?: components['schemas']['vegaEthTimeTrigger'];
};
/** Result of calling an arbitrary Ethereum contract method */
readonly vegaEthContractCallEvent: {
/**
* Format: uint64
* @description Ethereum block height.
*/
readonly blockHeight?: string;
/**
* Format: uint64
* @description Ethereum block time in Unix seconds.
*/
readonly blockTime?: string;
/**
* Format: byte
* @description Result of contract call, packed according to the ABI stored in the associated data source spec.
*/
readonly result?: string;
/** @description ID of the data source spec that triggered this contract call. */
readonly specId?: string;
};
/** @description Trigger for an Ethereum call based on the Ethereum block timestamp. Can be one-off or repeating. */
readonly vegaEthTimeTrigger: {
/**
* Format: uint64
* @description Repeat the call every n seconds after the inital call. If no time for initial call was specified, begin repeating immediately.
*/
readonly every?: string;
/**
* Format: uint64
* @description Trigger when the Ethereum time is greater or equal to this time, in Unix seconds.
*/
readonly initial?: string;
/**
* Format: uint64
* @description If repeating, stop once Ethereum time is greater than this time, in Unix seconds. If not set, then repeat indefinitely.
*/
readonly until?: string;
};
/** Future product configuration */
readonly vegaFutureProduct: {
/** @description Binding between the data source spec and the settlement data. */
@@ -1160,6 +1326,14 @@ export interface components {
/** @description Asset ID for the product's settlement asset. */
readonly settlementAsset?: string;
};
/**
* @default GOVERNANCE_TRANSFER_TYPE_UNSPECIFIED
* @enum {string}
*/
readonly vegaGovernanceTransferType:
| 'GOVERNANCE_TRANSFER_TYPE_UNSPECIFIED'
| 'GOVERNANCE_TRANSFER_TYPE_ALL_OR_NOTHING'
| 'GOVERNANCE_TRANSFER_TYPE_BEST_EFFORT';
/** Instrument configuration */
readonly vegaInstrumentConfiguration: {
/** @description Instrument code, human-readable shortcode used to describe the instrument. */
@@ -1168,6 +1342,8 @@ export interface components {
readonly future?: components['schemas']['vegaFutureProduct'];
/** @description Instrument name. */
readonly name?: string;
/** @description Spot. */
readonly spot?: components['schemas']['vegaSpotProduct'];
};
readonly vegaKeyValueBundle: {
readonly key?: string;
@@ -1258,14 +1434,14 @@ export interface components {
/** @description Configuration of the new market. */
readonly changes?: components['schemas']['vegaNewMarketConfiguration'];
};
/** Configuration for a new market on Vega */
/** Configuration for a new futures market on Vega */
readonly vegaNewMarketConfiguration: {
/**
* Format: uint64
* @description Decimal places used for the new market, sets the smallest price increment on the book.
* @description Decimal places used for the new futures market, sets the smallest price increment on the book.
*/
readonly decimalPlaces?: string;
/** @description New market instrument configuration. */
/** @description New futures market instrument configuration. */
readonly instrument?: components['schemas']['vegaInstrumentConfiguration'];
/** @description Linear slippage factor is used to cap the slippage component of maintenance margin - it is applied to the slippage volume. */
readonly linearSlippageFactor?: string;
@@ -1278,11 +1454,11 @@ export interface components {
* price levels over which automated liquidity provision orders will be deployed.
*/
readonly lpPriceRange?: string;
/** @description Optional new market metadata, tags. */
/** @description Optional new futures market metadata, tags. */
readonly metadata?: readonly string[];
/**
* Format: int64
* @description Decimal places for order sizes, sets what size the smallest order / position on the market can be.
* @description Decimal places for order sizes, sets what size the smallest order / position on the futures market can be.
*/
readonly positionDecimalPlaces?: string;
/** @description Price monitoring parameters. */
@@ -1291,6 +1467,80 @@ export interface components {
readonly quadraticSlippageFactor?: string;
/** @description Simple risk model parameters, valid only if MODEL_SIMPLE is selected. */
readonly simple?: components['schemas']['vegaSimpleModelParams'];
/** @description Successor configuration. If this proposal is meant to succeed a given market, then this should be set. */
readonly successor?: components['schemas']['vegaSuccessorConfiguration'];
};
/** New spot market on Vega */
readonly vegaNewSpotMarket: {
/** @description Configuration of the new spot market. */
readonly changes?: components['schemas']['vegaNewSpotMarketConfiguration'];
};
/** Configuration for a new spot market on Vega */
readonly vegaNewSpotMarketConfiguration: {
/**
* Format: uint64
* @description Decimal places used for the new spot market, sets the smallest price increment on the book.
*/
readonly decimalPlaces?: string;
/** @description New spot market instrument configuration. */
readonly instrument?: components['schemas']['vegaInstrumentConfiguration'];
/** @description Log normal risk model parameters, valid only if MODEL_LOG_NORMAL is selected. */
readonly logNormal?: components['schemas']['vegaLogNormalRiskModel'];
/** @description Optional new spot market metadata, tags. */
readonly metadata?: readonly string[];
/**
* Format: int64
* @description Decimal places for order sizes, sets what size the smallest order / position on the spot market can be.
*/
readonly positionDecimalPlaces?: string;
/** @description Price monitoring parameters. */
readonly priceMonitoringParameters?: components['schemas']['vegaPriceMonitoringParameters'];
/** @description Simple risk model parameters, valid only if MODEL_SIMPLE is selected. */
readonly simple?: components['schemas']['vegaSimpleModelParams'];
/** @description Specifies parameters related to target stake calculation. */
readonly targetStakeParameters?: components['schemas']['vegaTargetStakeParameters'];
};
/** New governance transfer */
readonly vegaNewTransfer: {
/** @description Configuration for a new transfer. */
readonly changes?: components['schemas']['vegaNewTransferConfiguration'];
};
readonly vegaNewTransferConfiguration: {
/** Maximum amount to transfer */
readonly amount?: string;
/** ID of asset to transfer */
readonly asset?: string;
/**
* Specifies the account to transfer to, depending on the account type:
* Network treasury: leave empty
* Party: party's public key
* Market insurance pool: market ID
*/
readonly destination?: string;
/** Specifies the account type to transfer to: reward pool, party, network insurance pool, market insurance pool */
readonly destinationType?: components['schemas']['vegaAccountType'];
/** Maximum fraction of the source account's balance to transfer as a decimal - i.e. 0.1 = 10% of the balance */
readonly fractionOfBalance?: string;
readonly oneOff?: components['schemas']['vegaOneOffTransfer'];
readonly recurring?: components['schemas']['vegaRecurringTransfer'];
/** If network treasury, field is empty, otherwise uses the market ID */
readonly source?: string;
/** Source account type, such as network treasury, market insurance pool */
readonly sourceType?: components['schemas']['vegaAccountType'];
/**
* "All or nothing" or "best effort":
* All or nothing: Transfers the specified amount or does not transfer anything
* Best effort: Transfers the specified amount or the max allowable amount if this is less than the specified amount
*/
readonly transferType?: components['schemas']['vegaGovernanceTransferType'];
};
/** Specific details for a one off transfer */
readonly vegaOneOffTransfer: {
/**
* Format: int64
* @description Timestamp in Unix nanoseconds for when the transfer should be delivered into the receiver's account.
*/
readonly deliverOn?: string;
};
/**
* Type values for an order
@@ -1369,6 +1619,8 @@ export interface components {
};
/** Terms for a governance proposal on Vega */
readonly vegaProposalTerms: {
/** @description Cancel a governance transfer. */
readonly cancelTransfer?: components['schemas']['vegaCancelTransfer'];
/**
* Format: int64
* @description Timestamp as Unix time in seconds when voting closes for this proposal,
@@ -1388,20 +1640,39 @@ export interface components {
* and can be used to gauge community sentiment.
*/
readonly newFreeform?: components['schemas']['vegaNewFreeform'];
/** @description Proposal change for creating new market on Vega. */
/** @description Proposal change for creating new futures market on Vega. */
readonly newMarket?: components['schemas']['vegaNewMarket'];
/** @description Proposal change for creating new spot market on Vega. */
readonly newSpotMarket?: components['schemas']['vegaNewSpotMarket'];
/** @description Proposal change for a governance transfer. */
readonly newTransfer?: components['schemas']['vegaNewTransfer'];
/** @description Proposal change for updating an asset. */
readonly updateAsset?: components['schemas']['vegaUpdateAsset'];
/** @description Proposal change for modifying an existing market on Vega. */
/** @description Proposal change for modifying an existing futures market on Vega. */
readonly updateMarket?: components['schemas']['vegaUpdateMarket'];
/** @description Proposal change for updating Vega network parameters. */
readonly updateNetworkParameter?: components['schemas']['vegaUpdateNetworkParameter'];
/** @description Proposal change for modifying an existing spot market on Vega. */
readonly updateSpotMarket?: components['schemas']['vegaUpdateSpotMarket'];
/**
* Format: int64
* @description Validation timestamp as Unix time in seconds.
*/
readonly validationTimestamp?: string;
};
/** Specific details for a recurring transfer */
readonly vegaRecurringTransfer: {
/**
* Format: uint64
* @description Last epoch at which this transfer shall be paid.
*/
readonly endEpoch?: string;
/**
* Format: uint64
* @description First epoch from which this transfer shall be paid.
*/
readonly startEpoch?: string;
};
readonly vegaScalarValue: {
readonly value?: string;
};
@@ -1442,6 +1713,15 @@ export interface components {
*/
readonly probabilityOfTrading?: number;
};
/** Spot product configuration */
readonly vegaSpotProduct: {
/** @description Base asset ID. */
readonly baseAsset?: string;
/** @description Product name. */
readonly name?: string;
/** @description Quote asset ID. */
readonly quoteAsset?: string;
};
readonly vegaStakeDeposited: {
/** @description Amount deposited as an unsigned base 10 integer scaled to the asset's decimal places. */
readonly amount?: string;
@@ -1507,6 +1787,13 @@ export interface components {
readonly scalarVal?: components['schemas']['vegaScalarValue'];
readonly vectorVal?: components['schemas']['vegaVectorValue'];
};
/** @description Configuration required to turn a new market proposal in to a successor market proposal. */
readonly vegaSuccessorConfiguration: {
/** @description A decimal value between or equal to 0 and 1, specifying the fraction of the insurance pool balance that is carried over from the parent market to the successor. */
readonly insurancePoolFraction?: string;
/** @description ID of the market that the successor should take over from. */
readonly parentMarketId?: string;
};
/** TargetStakeParameters contains parameters used in target stake calculation */
readonly vegaTargetStakeParameters: {
/**
@@ -1547,14 +1834,14 @@ export interface components {
};
/** Update an existing market on Vega */
readonly vegaUpdateMarket: {
/** @description Updated configuration of the market. */
/** @description Updated configuration of the futures market. */
readonly changes?: components['schemas']['vegaUpdateMarketConfiguration'];
/** @description Market ID the update is for. */
readonly marketId?: string;
};
/** Configuration to update a market on Vega */
/** Configuration to update a futures market on Vega */
readonly vegaUpdateMarketConfiguration: {
/** @description Updated market instrument configuration. */
/** @description Updated futures market instrument configuration. */
readonly instrument?: components['schemas']['vegaUpdateInstrumentConfiguration'];
/** @description Linear slippage factor is used to cap the slippage component of maintenance margin - it is applied to the slippage volume. */
readonly linearSlippageFactor?: string;
@@ -1567,7 +1854,7 @@ export interface components {
* price levels over which automated liquidity provision orders will be deployed.
*/
readonly lpPriceRange?: string;
/** @description Optional market metadata, tags. */
/** @description Optional futures market metadata, tags. */
readonly metadata?: readonly string[];
/** @description Price monitoring parameters. */
readonly priceMonitoringParameters?: components['schemas']['vegaPriceMonitoringParameters'];
@@ -1581,6 +1868,26 @@ export interface components {
/** @description The network parameter to update. */
readonly changes?: components['schemas']['vegaNetworkParameter'];
};
/** Update an existing spot market on Vega */
readonly vegaUpdateSpotMarket: {
/** @description Updated configuration of the spot market. */
readonly changes?: components['schemas']['vegaUpdateSpotMarketConfiguration'];
/** @description Market ID the update is for. */
readonly marketId?: string;
};
/** Configuration to update a spot market on Vega */
readonly vegaUpdateSpotMarketConfiguration: {
/** @description Log normal risk model parameters, valid only if MODEL_LOG_NORMAL is selected. */
readonly logNormal?: components['schemas']['vegaLogNormalRiskModel'];
/** @description Optional spot market metadata, tags. */
readonly metadata?: readonly string[];
/** @description Price monitoring parameters. */
readonly priceMonitoringParameters?: components['schemas']['vegaPriceMonitoringParameters'];
/** @description Simple risk model parameters, valid only if MODEL_SIMPLE is selected. */
readonly simple?: components['schemas']['vegaSimpleModelParams'];
/** @description Specifies parameters related to target stake calculation. */
readonly targetStakeParameters?: components['schemas']['vegaTargetStakeParameters'];
};
readonly vegaVectorValue: {
readonly value?: readonly string[];
};
@@ -1609,12 +1916,12 @@ export interface components {
export type external = Record<string, never>;
export interface operations {
/**
* Info
* @description Get information about the block explorer.
* Response contains a semver formatted version of the data node and the commit hash, from which the block explorer was built
*/
BlockExplorer_Info: {
/**
* Info
* @description Get information about the block explorer.
* Response contains a semver formatted version of the data node and the commit hash, from which the block explorer was built
*/
responses: {
/** @description A successful response. */
200: {
@@ -1630,19 +1937,38 @@ export interface operations {
};
};
};
/**
* List transactions
* @description List transactions from the Vega blockchain
*/
BlockExplorer_ListTransactions: {
/**
* List transactions
* @description List transactions from the Vega blockchain
*/
parameters?: {
/** @description Number of transactions to be returned from the blockchain. */
/** @description Optional cursor to paginate the request. */
/** @description Optional cursor to paginate the request. */
readonly query?: {
parameters: {
query?: {
/**
* @description Number of transactions to be returned from the blockchain.
* This is deprecated, use first and last instead.
*/
limit?: number;
/** @description Optional cursor to paginate the request. */
before?: string;
/** @description Optional cursor to paginate the request. */
after?: string;
/** @description Transaction command types filter, for listing transactions with specified command types. */
cmdTypes?: readonly string[];
/** @description Transaction command types exclusion filter, for listing all the transactions except the ones with specified command types. */
excludeCmdTypes?: readonly string[];
/** @description Party IDs filter, can be sender or receiver. */
parties?: readonly string[];
/**
* @description Number of transactions to be returned from the blockchain. Use in conjunction with the `after` cursor to paginate forwards.
* On its own, this will return the first `first` transactions.
*/
first?: number;
/**
* @description Number of transactions to be returned from the blockchain. Use in conjunction with the `before` cursor to paginate backwards.
* On its own, this will return the last `last` transactions.
*/
last?: number;
};
};
responses: {
@@ -1660,14 +1986,14 @@ export interface operations {
};
};
};
/**
* Get transaction
* @description Get a transaction from the Vega blockchain
*/
BlockExplorer_GetTransaction: {
/**
* Get transaction
* @description Get a transaction from the Vega blockchain
*/
parameters: {
/** @description Hash of the transaction */
readonly path: {
path: {
/** @description Hash of the transaction */
hash: string;
};
};
+1
View File
@@ -15,5 +15,6 @@ module.exports = composePlugins(withNx(), withReact(), (config) => {
return {
...config,
plugins: [...additionalPlugins, ...config.plugins],
ignoreWarnings: [/Failed to parse source map/],
};
});
@@ -98,11 +98,6 @@ describe(
.and('have.length', 64);
cy.getByTestId(proposalTermsToggle).click();
// 3001-VOTE-052 3001-VOTE-010
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('code.language-json')
.should('exist')
.within(() => {
@@ -295,7 +295,7 @@ context(
// Will fail if run after 'Able to submit update market proposal and vote for proposal'
// 3002-PROP-022
it('Unable to submit update market proposal without equity-like share in the market', function () {
it.skip('Unable to submit update market proposal without equity-like share in the market', function () {
switchVegaWalletPubKey();
stakingPageAssociateTokens('1');
goToMakeNewProposal(governanceProposalType.UPDATE_MARKET);
@@ -116,12 +116,6 @@ context(
cy.getByTestId(amountInput).click().type('120');
cy.getByTestId(submitWithdrawalButton).click();
});
// assert withdrawal request
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(toast)
.first(txTimeout)
.should('contain.text', 'Funds unlocked')
@@ -135,11 +129,6 @@ context(
cy.getByTestId(toastClose).click();
});
// withdrawal complete
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(toast)
.first(txTimeout)
.should('contain.text', 'The withdrawal has been approved.')
@@ -149,11 +138,6 @@ context(
'Withdraw 120.00 tUSDC'
);
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(toast)
.last(txTimeout)
.should('contain.text', 'Transaction confirmed')
@@ -161,11 +145,6 @@ context(
cy.getByTestId('external-link').should('exist');
});
// withdrawal history for complete withdrawal displayed
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(tableWithdrawnStatus)
.eq(1, txTimeout)
.should('have.text', 'Completed')
@@ -207,11 +186,6 @@ context(
cy.getByTestId(submitWithdrawalButton).click();
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(toast)
.first(txTimeout)
.should('contain.text', 'Funds unlocked')
@@ -223,11 +197,6 @@ context(
);
cy.getByTestId(toastClose).click();
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(tableTxHash)
.eq(1)
.should('have.text', 'Complete withdrawal')
@@ -243,33 +212,18 @@ context(
});
ethereumWalletConnect();
cy.getByTestId(completeWithdrawalButton).first().click();
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(toast)
.last(txTimeout)
.should('contain.text', 'Awaiting confirmation')
.within(() => {
cy.getByTestId('external-link').should('exist');
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(toast)
.first(txTimeout)
.should('contain.text', 'The withdrawal has been approved.')
.within(() => {
cy.getByTestId(toastPanel).should('contain.text', '110.00', 'tUSDC');
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(toast)
.last(txTimeout)
.should('contain.text', 'Transaction confirmed')
@@ -293,11 +247,6 @@ context(
cy.getByTestId(amountInput).click().type('50');
cy.getByTestId(submitWithdrawalButton).click();
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(toast)
.first(txTimeout)
.should('contain.text', 'Funds unlocked')
@@ -16,11 +16,6 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
});
it('should display announcement banner', function () {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('app-announcement')
.should('contain.text', 'TEST ANNOUNCEMENT!')
.within(() => {
@@ -40,11 +35,6 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
waitForSpinner();
}
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('proposals-list-item')
.should('have.length.at.least', 1)
.first()
@@ -104,11 +94,6 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
});
it('should contain link to specific validators', function () {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('validators')
.should('have.length', '2')
.each(($validator) => {
@@ -135,11 +120,6 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
});
it('should display network data', function () {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('git-network-data')
.should('contain.text', 'Reading network data from')
.within(() => {
@@ -151,11 +131,6 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
});
it('should display eth data', function () {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('git-eth-data')
.should('contain.text', 'Reading Ethereum data from')
.within(() => {
@@ -142,11 +142,6 @@ context(
mockNetworkUpgradeProposal();
navigateTo(navigation.proposals);
cy.getByTestId('open-proposals').within(() => {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('li')
.eq(0)
.should('have.attr', 'data-testid', networkUpgradeProposalListItem)
@@ -205,11 +200,6 @@ context(
.should('contain.text', '99.98% approval (% validator voting power)')
.and('contain.text', '(67% voting power required)');
cy.get('h2').should('contain.text', 'Approvers (4/4 validators)');
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('validator-name')
.should('have.length', 4)
.each(($validator) => {
@@ -42,11 +42,6 @@ context(
// Skipping due to bug #3471 causing flaky failuress
it.skip('should have option to view go to next and previous page', function () {
waitForBeginningOfEpoch();
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('page-info')
.should('contain.text', 'Page ')
.invoke('text')
@@ -21,11 +21,6 @@ context(
// 1005-VEST-001
// 1005-VEST-002
it('Able to view tranches', function () {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('tranche-item')
.should('have.length', 2)
.first()
@@ -56,11 +51,6 @@ context(
cy.get('span').eq(1).should('have.text', 0);
});
cy.getByTestId('key-value-table').within(() => {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('link')
.should('have.length', 8)
.each((ethLink) => {
@@ -68,11 +58,6 @@ context(
.should('have.attr', 'href')
.and('contain', 'https://sepolia.etherscan.io/address/');
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('redeem-link')
.should('have.length', 8)
.each((redeemLink) => {
@@ -86,11 +71,6 @@ context(
it('Able to view tranches with less than 10 vega', function () {
navigateTo(navigation.supply);
cy.getByTestId('show-all-tranches').click();
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('tranche-item')
.should('have.length', 8)
.first()
@@ -74,11 +74,6 @@ context('Validators Page - verify elements on page', function () {
function () {
// 1002-STKE-050
it('Should be able to see validator names', function () {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('[col-id="validator"] > div > span')
.should('have.length.at.least', 1)
.each(($name) => {
@@ -87,11 +82,6 @@ context('Validators Page - verify elements on page', function () {
});
it('Should be able to see validator stake', function () {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('total-stake')
.should('have.length.at.least', 1)
.each(($stake) => {
@@ -115,11 +105,6 @@ context('Validators Page - verify elements on page', function () {
});
it('Should be able to see validator normalised voting power', function () {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('normalised-voting-power')
.should('have.length.at.least', 1)
.each(($vPower) => {
@@ -141,11 +126,6 @@ context('Validators Page - verify elements on page', function () {
// 2002-SINC-018
it('Should be able to see validator total penalties', function () {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('total-penalty')
.should('have.length.at.least', 1)
.each(($penalties) => {
@@ -166,11 +146,6 @@ context('Validators Page - verify elements on page', function () {
});
it('Should be able to see validator pending stake', function () {
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('total-pending-stake')
.should('have.length.at.least', 1)
.each(($pendingStake) => {
@@ -340,7 +340,7 @@ context(
.contains(name)
.parent()
.siblings()
.then((elementAmount) => {
.should((elementAmount) => {
const displayedAmount = parseFloat(elementAmount.text());
expect(displayedAmount).be.gte(expectedAmount);
});
+15
View File
@@ -0,0 +1,15 @@
# App configuration variables
NX_VEGA_ENV=MAINNET-MIRROR
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_URL=https://api.mainnet-mirror.vega.rocks/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz","MAINNET-MIRROR":"https://governance.mainnet-mirror.vega.rocks","STAGNET1":"https://trading.stagnet1.vega.rocks"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-mirror-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_REST_URL=https://api.mainnet-mirror.vega.rocks/api/v2/
+1
View File
@@ -25,6 +25,7 @@ yarn nx serve governance
Example configurations are provided here:
- [Mainnet](./.env.mainnet)
- [Mainnet-mirror](./.env.mainnet-mirror)
- [Devnet](./.env.devnet)
- [Testnet](./.env.testnet)
@@ -91,46 +91,46 @@ query Proposal($proposalId: ID!) {
}
}
}
dataSourceSpecForTradingTermination {
sourceType {
... on DataSourceDefinitionInternal {
sourceType {
... on DataSourceSpecConfigurationTime {
conditions {
operator
value
}
}
}
}
... on DataSourceDefinitionExternal {
sourceType {
... on DataSourceSpecConfiguration {
signers {
signer {
... on PubKey {
key
}
... on ETHAddress {
address
}
}
}
filters {
key {
name
type
}
conditions {
operator
value
}
}
}
}
}
}
}
# dataSourceSpecForTradingTermination {
# sourceType {
# ... on DataSourceDefinitionInternal {
# sourceType {
# ... on DataSourceSpecConfigurationTime {
# conditions {
# operator
# value
# }
# }
# }
# }
# ... on DataSourceDefinitionExternal {
# sourceType {
# ... on DataSourceSpecConfiguration {
# signers {
# signer {
# ... on PubKey {
# key
# }
# ... on ETHAddress {
# address
# }
# }
# }
# filters {
# key {
# name
# type
# }
# conditions {
# operator
# value
# }
# }
# }
# }
# }
# }
# }
dataSourceSpecBinding {
settlementDataProperty
tradingTerminationProperty
@@ -203,46 +203,46 @@ query Proposal($proposalId: ID!) {
}
}
}
dataSourceSpecForTradingTermination {
sourceType {
... on DataSourceDefinitionInternal {
sourceType {
... on DataSourceSpecConfigurationTime {
conditions {
operator
value
}
}
}
}
... on DataSourceDefinitionExternal {
sourceType {
... on DataSourceSpecConfiguration {
signers {
signer {
... on PubKey {
key
}
... on ETHAddress {
address
}
}
}
filters {
key {
name
type
}
conditions {
operator
value
}
}
}
}
}
}
}
# dataSourceSpecForTradingTermination {
# sourceType {
# ... on DataSourceDefinitionInternal {
# sourceType {
# ... on DataSourceSpecConfigurationTime {
# conditions {
# operator
# value
# }
# }
# }
# }
# ... on DataSourceDefinitionExternal {
# sourceType {
# ... on DataSourceSpecConfiguration {
# signers {
# signer {
# ... on PubKey {
# key
# }
# ... on ETHAddress {
# address
# }
# }
# }
# filters {
# key {
# name
# type
# }
# conditions {
# operator
# value
# }
# }
# }
# }
# }
# }
# }
dataSourceSpecBinding {
settlementDataProperty
tradingTerminationProperty
File diff suppressed because one or more lines are too long
+1
View File
@@ -14,5 +14,6 @@ module.exports = composePlugins(withNx(), withReact(), (config, context) => {
return {
...config,
plugins: [...additionalPlugins, ...config.plugins],
ignoreWarnings: [/Failed to parse source map/],
};
});
+35 -50
View File
@@ -2,7 +2,6 @@ import { removeDecimal } from '@vegaprotocol/cypress';
import * as Schema from '@vegaprotocol/types';
import {
OrderStatusMapping,
OrderTimeInForceMapping,
OrderTypeMapping,
Side,
} from '@vegaprotocol/types';
@@ -17,7 +16,6 @@ const orderStatus = 'status';
const orderRemaining = 'remaining';
const orderPrice = 'price';
const orderTimeInForce = 'timeInForce';
const orderCreatedAt = 'createdAt';
const orderUpdatedAt = 'updatedAt';
const assetSelectField = 'select[name="asset"]';
const amountField = 'input[name="amount"]';
@@ -92,16 +90,14 @@ describe('capsule - without MultiSign', { tags: '@slow' }, () => {
cy.highlight('deposit verification');
cy.getByTestId('asset', txTimeout).should('contain.text', btcSymbol);
cy.get('[col-id="asset.symbol"]', txTimeout).should(
'contain.text',
btcSymbol
);
cy.getByTestId(depositsTab).click();
cy.get('.ag-cell-value', txTimeout).should('contain.text', btcSymbol);
cy.get('[col-id="status"]').should('not.have.text', 'Open', txTimeout);
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('[col-id="txHash"]')
.should('have.length.above', 2)
.eq(1)
@@ -149,7 +145,6 @@ describe('capsule - without MultiSign', { tags: '@slow' }, () => {
// 1002-WITH-022
// 1002-WITH-023
// 0003-WTXN-011
cy.getByTestId('Withdrawals').click();
cy.getByTestId('withdraw-dialog-button').click();
selectAsset(0);
@@ -160,18 +155,9 @@ describe('capsule - without MultiSign', { tags: '@slow' }, () => {
'contain.text',
'Funds unlocked'
);
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId('tab-withdrawals').within(() => {
cy.get('.ag-center-cols-container')
.children()
.first()
.within(() => {
cy.get('[col-id="status"]').should('contain.text', 'Pending');
});
});
// cy.getByTestId(toastCloseBtn).click();
cy.highlight('withdrawals verification');
cy.getByTestId('toast-complete-withdrawal').click();
cy.getByTestId('toast-complete-withdrawal').last().click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
@@ -228,9 +214,12 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
};
const rawPrice = removeDecimal(order.price, market.decimalPlaces);
cy.getByTestId(toastCloseBtn, txTimeout).click();
cy.getByTestId('Collateral').click();
cy.getByTestId('asset', txTimeout).should('contain.text', usdcSymbol);
cy.get('[col-id="asset.symbol"]', txTimeout).should(
'contain.text',
usdcSymbol
);
createOrder(order);
@@ -269,10 +258,7 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
OrderStatusMapping.STATUS_ACTIVE
);
cy.get(`[col-id='${orderRemaining}']`).should(
'contain.text',
`0.00/${order.size}`
);
cy.get(`[col-id='${orderRemaining}']`).should('contain.text', '0.00');
cy.get(`[col-id='${orderPrice}']`).then(($price) => {
expect(parseFloat($price.text())).to.equal(parseFloat(order.price));
@@ -280,17 +266,19 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
cy.get(`[col-id='${orderTimeInForce}']`).should(
'contain.text',
OrderTimeInForceMapping[order.timeInForce]
'GTC'
);
checkIfDataAndTimeOfCreationAndUpdateIsEqual(orderCreatedAt);
checkIfDataAndTimeOfCreationAndUpdateIsEqual(orderUpdatedAt);
});
});
});
it('can edit order', function () {
const market = this.market;
cy.visit(`/#/markets/${market.id}`);
cy.getByTestId(toastCloseBtn, txTimeout).click();
cy.getByTestId(openOrdersTab).click();
cy.getByTestId('edit', txTimeout).should('be.visible');
cy.getByTestId('edit').first().should('be.visible').click();
cy.getByTestId('dialog-title').should('contain.text', 'Edit order');
cy.get('#limitPrice').focus().clear().type(newPrice);
@@ -318,6 +306,7 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
it('can cancel order', function () {
const market = this.market;
cy.visit(`/#/markets/${market.id}`);
cy.getByTestId(toastCloseBtn, txTimeout).click();
cy.getByTestId(openOrdersTab).click();
cy.getByTestId('cancel').first().click();
cy.getByTestId(toastContent).should(
@@ -354,7 +343,7 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
cy.getByTestId(toastCloseBtn, txTimeout).click();
cy.getByTestId('Withdrawals').click();
cy.getByTestId('withdraw-dialog-button').click();
connectEthereumWallet('Unknown');
@@ -365,14 +354,6 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
'contain.text',
'Funds unlocked'
);
cy.getByTestId('tab-withdrawals').within(() => {
cy.get('.ag-center-cols-container')
.children()
.first()
.within(() => {
cy.get('[col-id="status"]').should('contain.text', 'Pending');
});
});
cy.highlight('withdrawals verification');
cy.getByTestId('toast-complete-withdrawal').click();
@@ -420,11 +401,6 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
.eq(0, txTimeout)
.should('contain.text', 'Completed');
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('[col-id="txHash"]', txTimeout)
.should('have.length.above', 1)
.eq(1)
@@ -454,6 +430,7 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
// 1001-DEPO-007
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
cy.getByTestId(toastCloseBtn, txTimeout).click();
cy.getByTestId(depositsTab).click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('Unknown');
@@ -474,8 +451,8 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
// 1002-WITH-007
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
cy.get('main[data-testid="/portfolio"]', txTimeout).should('exist');
cy.getByTestId(toastCloseBtn, txTimeout).click();
cy.getByTestId(depositsTab).click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('Unknown');
@@ -497,16 +474,14 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
cy.highlight('deposit verification');
cy.getByTestId('asset', txTimeout).should('contain.text', vegaSymbol);
cy.get('[col-id="asset.symbol"]', txTimeout).should(
'contain.text',
vegaSymbol
);
cy.getByTestId(depositsTab).click();
cy.get('.ag-cell-value', txTimeout).should('contain.text', vegaSymbol);
cy.get('[col-id="status"]').should('not.have.text', 'Open', txTimeout);
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('[col-id="txHash"]')
.should('have.length.above', 2)
.eq(1)
@@ -535,6 +510,16 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId(completeWithdrawalBtn).first().should('be.visible').click();
cy.getByTestId(toastContent, txTimeout).should('contain.text', 'Delayed');
cy.getByTestId('tab-withdrawals').within(() => {
cy.get('.ag-center-cols-container')
.children()
.first()
.within(() => {
cy.get('[col-id="status"]').contains(
/Delayed \(ready in (\d{1,2}:\d{2}:\d{2}:\d{2})\)/
);
});
});
});
});
@@ -153,7 +153,7 @@ describe('markets all table', { tags: '@smoke' }, () => {
cy.get(dropdownContent)
.find(dropdownContentItem)
.eq(2)
.should('have.text', 'View asset');
.should('have.text', 'View settlement asset details');
cy.getByTestId('market-actions-content').click();
});
@@ -137,11 +137,6 @@ describe('Market trading page', () => {
.realHover();
});
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(expirtyTooltip)
.eq(0)
.should(
@@ -175,11 +170,6 @@ describe('Market trading page', () => {
.realHover();
});
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(tradingModeTooltip)
.should(
'contain.text',
@@ -206,11 +196,6 @@ describe('Market trading page', () => {
cy.getByTestId(itemValue).realHover();
});
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId(liquiditySuppliedTooltip)
.should('contain.text', 'Supplied stake')
.and('contain.text', 'Target stake')
@@ -16,7 +16,7 @@ const orderStatus = 'status';
const orderRemaining = 'remaining';
const orderPrice = 'price';
const orderTimeInForce = 'timeInForce';
const orderCreatedAt = 'createdAt';
const orderUpdatedAt = 'updatedAt';
const cancelOrderBtn = 'cancel';
const cancelAllOrdersBtn = 'cancelAll';
const editOrderBtn = 'edit';
@@ -46,6 +46,10 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.wrap($symbol).invoke('text').should('not.be.empty');
});
cy.get(`[col-id='${orderRemaining}']`).each(($remaining) => {
cy.wrap($remaining).invoke('text').should('not.be.empty');
});
cy.get(`[col-id='${orderSize}']`).each(($size) => {
cy.wrap($size).invoke('text').should('not.be.empty');
});
@@ -58,10 +62,6 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.wrap($status).invoke('text').should('not.be.empty');
});
cy.get(`[col-id='${orderRemaining}']`).each(($remaining) => {
cy.wrap($remaining).invoke('text').should('not.be.empty');
});
cy.get(`[col-id='${orderPrice}']`).each(($price) => {
cy.wrap($price).invoke('text').should('not.be.empty');
});
@@ -70,7 +70,7 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.wrap($timeInForce).invoke('text').should('not.be.empty');
});
cy.get(`[col-id='${orderCreatedAt}']`).each(($dateTime) => {
cy.get(`[col-id='${orderUpdatedAt}']`).each(($dateTime) => {
cy.wrap($dateTime).invoke('text').should('not.be.empty');
});
});
@@ -96,7 +96,8 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
'have.text',
'Partially Filled'
);
cy.get(`[col-id='${orderRemaining}']`).should('have.text', '7/10');
cy.get(`[col-id='${orderRemaining}']`).should('have.text', '7');
cy.get(`[col-id='${orderSize}']`).should('have.text', '-10');
cy.getByTestId(cancelOrderBtn).should('not.exist');
cy.getByTestId(editOrderBtn).should('not.exist');
});
@@ -118,11 +119,6 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.contains('Reset').click();
cy.getByTestId('All').click();
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.getByTestId('tab-orders')
.get(`.ag-center-cols-container [col-id='${orderSymbol}']`)
.should('have.length.at.least', expectedOrderList.length)
@@ -219,7 +215,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
cy.getByTestId(`order-status-${orderId}`)
.parentsUntil(`.ag-row`)
.siblings(`[col-id=${orderRemaining}]`)
.should('have.text', '4/5');
.should('have.text', '4');
});
it('must see a filled order', () => {
@@ -267,7 +263,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
status: Schema.OrderStatus.STATUS_ACTIVE,
});
cy.get(`[row-id=${orderId}]`)
.find('[col-id="size"]')
.find(`[col-id="${orderSize}"]`)
.should('have.text', '-15');
});
@@ -281,7 +277,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
status: Schema.OrderStatus.STATUS_ACTIVE,
});
cy.get(`[row-id=${orderId}]`)
.find('[col-id="size"]')
.find(`[col-id="${orderSize}"]`)
.should('have.text', '+5');
});
@@ -364,7 +360,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
});
cy.get(`[row-id=${orderId}]`)
.find(`[col-id='${orderTimeInForce}']`)
.should('have.text', "Good 'til Cancelled (GTC)");
.should('have.text', 'GTC');
});
it('for Active order when is part of a liquidity or peg shape, must not see an option to amend the individual order ', () => {
@@ -446,11 +442,6 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
peggedOrder: null,
liquidityProvisionId: null,
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(`[row-id=${orderId}]`)
.find('[data-testid="edit"]')
.should('have.text', 'Edit')
@@ -480,11 +471,6 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
peggedOrder: null,
liquidityProvisionId: null,
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(`[row-id=${orderId}]`)
.find(`[data-testid="cancel"]`)
.should('have.text', 'Cancel')
@@ -507,11 +493,6 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
peggedOrder: null,
liquidityProvisionId: null,
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(`[data-testid="cancelAll"]`)
.should('have.text', 'Cancel all')
.then(($btn) => {
@@ -528,11 +509,6 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
peggedOrder: null,
liquidityProvisionId: null,
});
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get(`[row-id=${orderId}]`)
.find('[data-testid="edit"]')
.should('have.text', 'Edit')
@@ -47,11 +47,6 @@ describe('Portfolio page', { tags: '@smoke' }, () => {
cy.get(
'[role="columnheader"][col-id="fromAccountType"] .ag-header-cell-menu-button'
).click();
/**
* TODO(@nx/cypress): Nesting Cypress commands in a should assertion now throws.
* You should use .then() to chain commands instead.
* More Info: https://docs.cypress.io/guides/references/migration-guide#-should
**/
cy.get('fieldset.ag-simple-filter-body-wrapper')
.should('be.visible')
.within((fields) => {
@@ -267,22 +267,22 @@ describe('positions', { tags: '@regression', testIsolation: true }, () => {
cy.get('.ag-center-cols-container').within(() => {
assertPNLColor(
'[col-id="realisedPNL"]',
'text-vega-green',
'text-vega-pink'
'text-market-green-600',
'text-market-red'
);
});
cy.get('.ag-center-cols-container').within(() => {
assertPNLColor(
'[col-id="unrealisedPNL"]',
'text-vega-green',
'text-vega-pink'
'text-market-green-600',
'text-market-red'
);
});
cy.get('.ag-center-cols-container').within(() => {
assertPNLColor(
'[col-id="openVolume"]',
'text-vega-green',
'text-vega-pink'
'text-market-green-600',
'text-market-red'
);
});
});
+17
View File
@@ -0,0 +1,17 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_SENTRY_DSN=https://2ffce43721964aafa78277c50654ece4@o286262.ingest.sentry.io/6300613
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_ENV=MAINNET-MIRROR
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks
NX_VEGA_NETWORKS={\"MAINNET\":\"https://console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://trading.stagnet1.vega.rocks\",\"MAINNET-MIRROR\":\"https://trading.mainnet-mirror.vega.rocks\"}
NX_VEGA_TOKEN_URL=https://governance.mainnet-mirror.vega.rocks
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
NX_VEGA_CONSOLE_URL=https://console.mainnet-mirror.vega.rocks
# TAG name of the current app version - TODO: bump to the latest upon release
NX_APP_VERSION=v0.20.19-core-0.71.6
+3 -2
View File
@@ -11,7 +11,7 @@ cp .env.[environment] .env.local
Starting the app:
```bash
yarn nx serve explorer
yarn nx serve trading
```
### Configuration
@@ -19,13 +19,14 @@ yarn nx serve explorer
Example configurations are provided here:
- [Mainnet](./.env.mainnet)
- [Mainnet-mirror](./.env.mainnet-mirror)
- [Devnet](./.env.devnet)
- [Testnet](./.env.testnet)
For convenience, you can boot the app injecting one of the configurations above by running:
```bash
yarn env-cmd -f .\apps\token\.env.{env} yarn nx run token:serve # e.g. stagnet1
yarn env-cmd -f .\apps\trading\.env.{env} yarn nx run trading:serve # e.g. stagnet1
```
There are a few different configuration options offered for this app:
@@ -160,8 +160,9 @@ const DataRow = ({
const PriceChange = ({ candles }: { candles: string[] }) => {
const priceChange = candles ? priceChangePercentage(candles) : undefined;
const priceChangeClasses = classNames('text-xs', {
'text-vega-pink': priceChange && priceChange < 0,
'text-vega-green': priceChange && priceChange > 0,
'text-market-red': priceChange && priceChange < 0,
'text-market-green-600 dark:text-market-green':
priceChange && priceChange > 0,
});
let prefix = '';
if (priceChange && priceChange > 0) {
@@ -9,10 +9,7 @@ import { t } from '@vegaprotocol/i18n';
import { OracleBanner } from '@vegaprotocol/markets';
import type { Market } from '@vegaprotocol/markets';
import { Filter } from '@vegaprotocol/orders';
import {
usePaneLayout,
useScreenDimensions,
} from '@vegaprotocol/react-helpers';
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
import {
Tab,
LocalStoragePersistTabs as Tabs,
@@ -25,6 +22,7 @@ import { HeaderTitle } from '../../components/header';
import {
ResizableGrid,
ResizableGridPanel,
usePaneLayout,
} from '../../components/resizable-grid';
import { TradingViews } from './trade-views';
import { MarketSelector } from './market-selector';
@@ -318,7 +316,7 @@ export const TradeGrid = ({ market, pinnedAsset }: TradeGridProps) => {
<div className="border-b border-default min-w-0">
<HeaderStats market={market} />
</div>
<div className="col-span-2 bg-vega-green">
<div className="col-span-2">
<OracleBanner marketId={market?.id || ''} />
</div>
{sidebarOpen && (
+2 -2
View File
@@ -18,7 +18,7 @@ import type {
MarketMaybeWithData,
} from '@vegaprotocol/markets';
import {
MarketTableActions,
MarketActionsDropdown,
closedMarketsWithDataProvider,
} from '@vegaprotocol/markets';
import { useVegaWallet } from '@vegaprotocol/wallet';
@@ -291,7 +291,7 @@ const ClosedMarketsDataGrid = ({
cellRenderer: ({ data }: VegaICellRendererParams<Row>) => {
if (!data) return null;
return (
<MarketTableActions
<MarketActionsDropdown
marketId={data.id}
assetId={data.settlementAsset.id}
/>
@@ -24,7 +24,10 @@ import { PriceChart } from 'pennant';
import 'pennant/dist/style.css';
import type { Account } from '@vegaprotocol/accounts';
import { accountsDataProvider } from '@vegaprotocol/accounts';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
import {
useLocalStorageSnapshot,
useThemeSwitcher,
} from '@vegaprotocol/react-helpers';
import { useDataProvider } from '@vegaprotocol/data-provider';
import type { Market } from '@vegaprotocol/markets';
@@ -68,7 +71,7 @@ export const AccountHistoryContainer = () => {
const { data: assets } = useAssetsDataProvider();
if (!pubKey) {
return <Splash>Connect wallet</Splash>;
return <Splash>{t('Connect wallet')}</Splash>;
}
return (
@@ -114,7 +117,15 @@ const AccountHistoryManager = ({
.sort((a, b) => a.name.localeCompare(b.name)),
[assetData, assetIds]
);
const [asset, setAsset] = useState<AssetFieldsFragment>(assets[0]);
const [assetId, setAssetId] = useLocalStorageSnapshot(
'account-history-active-asset-id'
);
const asset = useMemo(
() => assets.find((a) => a.id === assetId) || assets[0],
[assetId, assets]
);
const [range, setRange] = useState<typeof DateRange[keyof typeof DateRange]>(
DateRange.RANGE_1M
);
@@ -146,10 +157,10 @@ const AccountHistoryManager = ({
m.tradableInstrument.instrument.product.settlementAsset.id;
const newAsset = assets.find((item) => item.id === newAssetId);
if ((!asset || (assets && newAssetId !== asset.id)) && newAsset) {
setAsset(newAsset);
setAssetId(newAsset.id);
}
},
[asset, assets]
[asset, assets, setAssetId]
);
const variables = useMemo(
@@ -211,14 +222,14 @@ const AccountHistoryManager = ({
>
<DropdownMenuContent>
{assets.map((a) => (
<DropdownMenuItem key={a.id} onClick={() => setAsset(a)}>
<DropdownMenuItem key={a.id} onClick={() => setAssetId(a.id)}>
{a.symbol}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
}, [assets, asset]);
}, [asset, assets, setAssetId]);
const marketsMenu = useMemo(() => {
return accountType === Schema.AccountType.ACCOUNT_TYPE_MARGIN &&
markets?.length ? (
@@ -4,7 +4,6 @@ import { LayoutPriority } from 'allotment';
import { titlefy } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { useIncompleteWithdrawals } from '@vegaprotocol/withdraws';
import { usePaneLayout } from '@vegaprotocol/react-helpers';
import { Tab, LocalStoragePersistTabs as Tabs } from '@vegaprotocol/ui-toolkit';
import { usePageTitleStore } from '../../stores';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
@@ -20,6 +19,7 @@ import { AccountHistoryContainer } from './account-history-container';
import {
ResizableGrid,
ResizableGridPanel,
usePaneLayout,
} from '../../components/resizable-grid';
const WithdrawalsIndicator = () => {
@@ -1 +1,2 @@
export * from './resizable-grid';
export * from './use-pane-layout';
+37 -31
View File
@@ -29,51 +29,57 @@ html.dark {
/* PENNANT */
html [data-theme='dark'] {
--pennant-color-danger: theme('colors.vega.pink.DEFAULT');
/* candles */
--pennant-color-buy-fill: theme('colors.vega.green.650');
--pennant-color-buy-stroke: theme('colors.vega.green.500');
html [data-theme='dark'],
html [data-theme='light'] {
/* sell candles only use stroke as the candle is solid (without border) */
--pennant-color-sell-stroke: theme('colors.vega.pink.500');
--pennant-color-sell-stroke: theme('colors.market.red.500');
/* studies */
--pennant-color-eldar-ray-bear-power: theme('colors.vega.pink.500');
--pennant-color-eldar-ray-bull-power: theme('colors.vega.green.650');
--pennant-color-eldar-ray-bear-power: theme('colors.market.red.500');
--pennant-color-eldar-ray-bull-power: theme('colors.market.green.600');
--pennant-color-macd-divergence-buy: theme('colors.vega.green.650');
--pennant-color-macd-divergence-sell: theme('colors.vega.pink.500');
--pennant-color-macd-divergence-buy: theme('colors.market.green.600');
--pennant-color-macd-divergence-sell: theme('colors.market.red.500');
--pennant-color-macd-signal: theme('colors.vega.blue.500');
--pennant-color-macd-macd: theme('colors.vega.yellow.500');
--pennant-color-volume-buy: theme('colors.vega.green.650');
--pennant-color-volume-sell: theme('colors.vega.pink.500');
/* depth chart */
--pennant-color-depth-buy-fill: theme('colors.vega.green.650');
--pennant-color-depth-buy-stroke: theme('colors.vega.green.500');
--pennant-color-depth-sell-fill: theme('colors.vega.pink.650');
--pennant-color-depth-sell-stroke: theme('colors.vega.pink.500');
--pennant-color-volume-sell: theme('colors.market.red.500');
}
html [data-theme='light'] {
--pennant-color-danger: theme('colors.vega.pink.500');
/* candles */
--pennant-color-buy-fill: theme('colors.vega.green.400');
--pennant-color-buy-stroke: theme('colors.vega.green.550');
/* sell candles only use stroke as the candle is solid (without border) */
--pennant-color-sell-stroke: theme('colors.vega.pink.400');
--pennant-color-buy-fill: theme(colors.market.green.500);
--pennant-color-buy-stroke: theme(colors.market.green.600);
--pennant-color-volume-buy: theme('colors.vega.green.400');
--pennant-color-volume-sell: theme('colors.vega.pink.400');
/* sell uses stroke for fill and stroke */
--pennant-color-sell-stroke: theme(colors.market.red.500);
/* depth chart */
--pennant-color-depth-buy-fill: theme('colors.vega.green.400');
--pennant-color-depth-buy-stroke: theme('colors.vega.green.550');
--pennant-color-depth-sell-fill: theme('colors.vega.pink.400');
--pennant-color-depth-sell-stroke: theme('colors.vega.pink.550');
--pennant-color-depth-buy-fill: theme(colors.market.green.500);
--pennant-color-depth-buy-stroke: theme(colors.market.green.600);
--pennant-color-depth-sell-fill: theme(colors.market.red.500);
--pennant-color-depth-sell-stroke: theme(colors.market.red.600);
--pennant-color-volume-buy: theme(colors.market.green.400);
--pennant-color-volume-sell: theme(colors.market.red.400);
}
html [data-theme='dark'] {
/* candles */
--pennant-color-buy-fill: theme(colors.market.green.600);
--pennant-color-buy-stroke: theme(colors.market.green.500);
/* sell uses stroke for fill and stroke */
--pennant-color-sell-stroke: theme(colors.market.red.500);
/* depth chart */
--pennant-color-depth-buy-fill: theme(colors.market.green.600);
--pennant-color-depth-buy-stroke: theme(colors.market.green.500);
--pennant-color-depth-sell-fill: theme(colors.market.red.600);
--pennant-color-depth-sell-stroke: theme(colors.market.red.500);
--pennant-color-volume-buy: theme(colors.market.green.600);
--pennant-color-volume-sell: theme(colors.market.red.600);
}
/* AG GRID - Do not edit without updating other global stylesheets for each app */
@@ -1,11 +1,9 @@
import { ETHERSCAN_ADDRESS, useEtherscanLink } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import {
DropdownMenu,
DropdownMenuContent,
ActionsDropdown,
DropdownMenuCopyItem,
DropdownMenuItem,
DropdownMenuTrigger,
Link,
VegaIcon,
VegaIconNames,
@@ -29,75 +27,65 @@ export const AccountsActionsDropdown = ({
const etherscanLink = useEtherscanLink();
const openTransferDialog = useTransferDialog((store) => store.open);
const openAssetDialog = useAssetDetailsDialogStore((store) => store.open);
return (
<DropdownMenu
trigger={
<DropdownMenuTrigger
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
data-testid="dropdown-menu"
>
<VegaIcon name={VegaIconNames.KEBAB} />
</DropdownMenuTrigger>
}
>
<DropdownMenuContent>
<DropdownMenuItem
key={'deposit'}
data-testid="deposit"
onClick={onClickDeposit}
>
<VegaIcon name={VegaIconNames.DEPOSIT} size={16} />
{t('Deposit')}
<ActionsDropdown>
<DropdownMenuItem
key={'deposit'}
data-testid="deposit"
onClick={onClickDeposit}
>
<VegaIcon name={VegaIconNames.DEPOSIT} size={16} />
{t('Deposit')}
</DropdownMenuItem>
<DropdownMenuItem
key={'withdraw'}
data-testid="withdraw"
onClick={onClickWithdraw}
>
<VegaIcon name={VegaIconNames.WITHDRAW} size={16} />
{t('Withdraw')}
</DropdownMenuItem>
<DropdownMenuItem
key={'transfer'}
data-testid="transfer"
onClick={() => openTransferDialog(true, assetId)}
>
<VegaIcon name={VegaIconNames.TRANSFER} size={16} />
{t('Transfer')}
</DropdownMenuItem>
<DropdownMenuItem
key={'breakdown'}
data-testid="breakdown"
onClick={onClickBreakdown}
>
<VegaIcon name={VegaIconNames.BREAKDOWN} size={16} />
{t('View usage breakdown')}
</DropdownMenuItem>
<DropdownMenuItem
onClick={(e) => {
openAssetDialog(assetId, e.target as HTMLElement);
}}
>
<VegaIcon name={VegaIconNames.INFO} size={16} />
{t('View asset details')}
</DropdownMenuItem>
<DropdownMenuCopyItem value={assetId} text={t('Copy asset ID')} />
{assetContractAddress && (
<DropdownMenuItem>
<Link
href={etherscanLink(
ETHERSCAN_ADDRESS.replace(':hash', assetContractAddress)
)}
target="_blank"
>
<span className="flex gap-2">
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
{t('View on Etherscan')}
</span>
</Link>
</DropdownMenuItem>
<DropdownMenuItem
key={'withdraw'}
data-testid="withdraw"
onClick={onClickWithdraw}
>
<VegaIcon name={VegaIconNames.WITHDRAW} size={16} />
{t('Withdraw')}
</DropdownMenuItem>
<DropdownMenuItem
key={'transfer'}
data-testid="transfer"
onClick={() => openTransferDialog(true, assetId)}
>
<VegaIcon name={VegaIconNames.TRANSFER} size={16} />
{t('Transfer')}
</DropdownMenuItem>
<DropdownMenuItem
key={'breakdown'}
data-testid="breakdown"
onClick={onClickBreakdown}
>
<VegaIcon name={VegaIconNames.BREAKDOWN} size={16} />
{t('Breakdown')}
</DropdownMenuItem>
<DropdownMenuItem
onClick={(e) => {
openAssetDialog(assetId, e.target as HTMLElement);
}}
>
<VegaIcon name={VegaIconNames.BREAKDOWN} size={16} />
{t('View asset')}
</DropdownMenuItem>
<DropdownMenuCopyItem value={assetId} text={t('Copy asset ID')} />
{assetContractAddress && (
<DropdownMenuItem>
<Link
href={etherscanLink(
ETHERSCAN_ADDRESS.replace(':hash', assetContractAddress)
)}
target="_blank"
>
<span className="flex gap-2">
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
{t('View on Etherscan')}
</span>
</Link>
</DropdownMenuItem>
)}
</DropdownMenuContent>
</DropdownMenu>
)}
</ActionsDropdown>
);
};
+1 -1
View File
@@ -33,7 +33,7 @@ const colorClass = (percentageUsed: number, neutral = false) => {
return classNames('text-right', {
'text-neutral-500 dark:text-neutral-400': percentageUsed < 75 && !neutral,
'text-vega-orange': percentageUsed >= 75 && percentageUsed < 90,
'text-vega-pink': percentageUsed >= 90,
'text-vega-red': percentageUsed >= 90,
});
};
@@ -189,7 +189,7 @@ export const MarginHealthChart = ({
>
<div
data-testid="margin-health-chart-red"
className="bg-vega-pink-550"
className="bg-vega-red-550"
style={{
height: '100%',
width: `${red * 100}%`,
+2 -1
View File
@@ -13,6 +13,7 @@ import { accountsDataProvider } from './accounts-data-provider';
import { TransferForm } from './transfer-form';
import { useTransferDialog } from './transfer-dialog';
import { Lozenge } from '@vegaprotocol/ui-toolkit';
import sortBy from 'lodash/sortBy';
export const TransferContainer = ({ assetId }: { assetId?: string }) => {
const { pubKey, pubKeys } = useVegaWallet();
@@ -58,7 +59,7 @@ export const TransferContainer = ({ assetId }: { assetId?: string }) => {
<TransferForm
pubKey={pubKey}
pubKeys={pubKeys ? pubKeys?.map((pk) => pk.publicKey) : null}
assets={assets}
assets={sortBy(assets, 'name')}
assetId={assetId}
feeFactor={param}
submitTransfer={transfer}
+8 -8
View File
@@ -8,7 +8,7 @@ import {
import BigNumber from 'bignumber.js';
import { AddressField, TransferFee, TransferForm } from './transfer-form';
import { AccountType } from '@vegaprotocol/types';
import { formatNumber, removeDecimal } from '@vegaprotocol/utils';
import { addDecimal, formatNumber, removeDecimal } from '@vegaprotocol/utils';
describe('TransferForm', () => {
const submit = () => fireEvent.submit(screen.getByTestId('transfer-form'));
@@ -16,11 +16,11 @@ describe('TransferForm', () => {
const pubKey =
'70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680';
const asset = {
id: 'asset-0',
symbol: 'ASSET 0',
name: 'Asset 0',
id: 'eur',
symbol: '',
name: 'EUR',
decimals: 2,
balance: '1000',
balance: addDecimal(100000, 2), // 1000
};
const props = {
pubKey,
@@ -92,7 +92,7 @@ describe('TransferForm', () => {
expect(await screen.findByTestId('select-asset')).toHaveTextContent(
asset.name
);
expect(screen.getByTestId('asset-balance')).toHaveTextContent(
expect(await screen.findByTestId('asset-balance')).toHaveTextContent(
formatNumber(asset.balance, asset.decimals)
);
@@ -168,7 +168,7 @@ describe('TransferForm', () => {
expect(await screen.findByTestId('select-asset')).toHaveTextContent(
asset.name
);
expect(screen.getByTestId('asset-balance')).toHaveTextContent(
expect(await screen.findByTestId('asset-balance')).toHaveTextContent(
formatNumber(asset.balance, asset.decimals)
);
@@ -244,7 +244,7 @@ describe('TransferForm', () => {
expect(await screen.findByTestId('select-asset')).toHaveTextContent(
asset.name
);
expect(screen.getByTestId('asset-balance')).toHaveTextContent(
expect(await screen.findByTestId('asset-balance')).toHaveTextContent(
formatNumber(asset.balance, asset.decimals)
);
+12 -13
View File
@@ -12,7 +12,6 @@ import {
FormGroup,
Input,
InputError,
Option,
RichSelect,
Select,
Tooltip,
@@ -24,6 +23,7 @@ import BigNumber from 'bignumber.js';
import type { ReactNode } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { AssetOption, Balance } from '@vegaprotocol/assets';
interface FormFields {
toAddress: string;
@@ -193,21 +193,20 @@ export const TransferForm = ({
onValueChange={(value) => {
field.onChange(value);
}}
placeholder={t('Please select')}
placeholder={t('Please select an asset')}
value={field.value}
>
{assets.map((a) => (
<Option key={a.id} value={a.id}>
<div className="text-left" data-testid={`asset-${a.id}`}>
<div>{a.name}</div>
<div className="text-xs">
<span className="font-mono" data-testid="asset-balance">
{formatNumber(a.balance, a.decimals)}
</span>{' '}
<span>{a.symbol}</span>
</div>
</div>
</Option>
<AssetOption
key={a.id}
asset={a}
balance={
<Balance
balance={formatNumber(a.balance, a.decimals)}
symbol={a.symbol}
/>
}
/>
))}
</RichSelect>
)}
+9 -2
View File
@@ -1,6 +1,9 @@
import { useEffect, useState } from 'react';
import type { AppNameType, Announcement } from './schema';
import { useAnnouncement } from './hooks/use-announcement';
import {
useAnnouncement,
useDismissedAnnouncement,
} from './hooks/use-announcement';
import {
AnnouncementBanner as Banner,
ExternalLink,
@@ -36,6 +39,7 @@ export const AnnouncementBanner = ({
}: AnnouncementBannerProps) => {
const [isVisible, setVisible] = useState(false);
const { data, reload } = useAnnouncement(app, configUrl);
const [, setDismissed] = useDismissedAnnouncement();
useEffect(() => {
const now = new Date();
@@ -88,7 +92,10 @@ export const AnnouncementBanner = ({
<button
className="absolute right-0 top-0 p-4 w-10 h-full flex items-center justify-center text-white"
data-testid="app-announcement-close"
onClick={() => setVisible(false)}
onClick={() => {
setVisible(false);
setDismissed(data);
}}
>
<VegaIcon name={VegaIconNames.CROSS} size={24} />
</button>
@@ -1,6 +1,8 @@
import { useCallback, useEffect, useState } from 'react';
import type { AppNameType, Announcement } from '../schema';
import { AnnouncementsSchema } from '../schema';
import { sha256 } from 'ethers/lib/utils';
import { useLocalStorageSnapshot } from '@vegaprotocol/react-helpers';
const getData = async (name: AppNameType, url: string) => {
const now = new Date();
@@ -31,6 +33,22 @@ type State = {
error: null | string;
};
const checksum = (data: object) => sha256(Buffer.from(JSON.stringify(data)));
export const useDismissedAnnouncement = (): [
string | null | undefined,
(data: object) => void
] => {
const [dismissed, setDismissedInStorage] = useLocalStorageSnapshot(
'dismissed-announcement'
);
const setDismissed = useCallback(
(data: object) => setDismissedInStorage(checksum(data)),
[setDismissedInStorage]
);
return [dismissed, setDismissed];
};
export const useAnnouncement = (name: AppNameType, url: string) => {
const [state, setState] = useState<State>({
loading: true,
@@ -38,12 +56,14 @@ export const useAnnouncement = (name: AppNameType, url: string) => {
error: null,
});
const [dismissed] = useDismissedAnnouncement();
const fetchData = useCallback(() => {
let mounted = true;
getData(name, url)
.then((data) => {
if (mounted) {
if (mounted && dismissed !== checksum(data)) {
setState({
loading: false,
data,
@@ -64,7 +84,7 @@ export const useAnnouncement = (name: AppNameType, url: string) => {
return () => {
mounted = false;
};
}, [name, url, setState]);
}, [name, url, dismissed]);
useEffect(() => {
fetchData();
+5 -3
View File
@@ -5,7 +5,7 @@ import { t } from '@vegaprotocol/i18n';
import type { ReactNode } from 'react';
type AssetOptionProps = {
asset: AssetFieldsFragment;
asset: Pick<AssetFieldsFragment, 'id' | 'name' | 'symbol'>;
balance?: ReactNode;
};
@@ -17,11 +17,13 @@ export const Balance = ({
symbol: string;
}) =>
balance ? (
<div className="mt-1 font-alpha">
<div className="mt-1 font-alpha" data-testid="asset-balance">
{balance} {symbol}
</div>
) : (
<div className="text-vega-orange-500">{t('Fetching balance…')}</div>
<div className="text-vega-orange-500" data-testid="asset-balance">
{t('Fetching balance…')}
</div>
);
export const AssetOption = ({ asset, balance }: AssetOptionProps) => {
+3 -2
View File
@@ -1,5 +1,6 @@
export const positiveClassNames = 'text-vega-green-550 dark:text-vega-green';
export const negativeClassNames = 'text-vega-pink dark:text-vega-pink';
export const positiveClassNames =
'text-market-green-600 dark:text-market-green';
export const negativeClassNames = 'text-market-red dark:text-market-red';
const isPositive = ({ value }: { value: string | bigint | number }) =>
!!value &&
+4 -4
View File
@@ -71,8 +71,8 @@ export const FlashCell = memo(({ children, value }: FlashCellProps) => {
if (value < previousValue) {
ref.current?.animate(
[
{ color: theme.colors.vega.pink.DEFAULT },
{ color: theme.colors.vega.pink.DEFAULT, offset: 0.8 },
{ color: theme.colors.market.red.DEFAULT },
{ color: theme.colors.market.red.DEFAULT, offset: 0.8 },
{ color: 'inherit' },
],
FLASH_DURATION
@@ -80,8 +80,8 @@ export const FlashCell = memo(({ children, value }: FlashCellProps) => {
} else if (value > previousValue) {
ref.current?.animate(
[
{ color: theme.colors.vega.green.DEFAULT },
{ color: theme.colors.vega.green.DEFAULT, offset: 0.8 },
{ color: theme.colors.market.green.DEFAULT },
{ color: theme.colors.market.green.DEFAULT, offset: 0.8 },
{ color: 'inherit' },
],
FLASH_DURATION
+4 -9
View File
@@ -19,19 +19,14 @@ export const Size = ({
data-testid="size"
className={classNames('text-right', {
// BUY
'text-vega-green-550 dark:text-vega-green':
'text-market-green-600 dark:text-market-green':
side === Schema.Side.SIDE_BUY && !forceTheme,
'text-vega-green-550':
'text-market-green-600':
side === Schema.Side.SIDE_BUY && forceTheme === 'light',
'text-vega-green':
'text-market-green':
side === Schema.Side.SIDE_BUY && forceTheme === 'dark',
// SELL
'text-vega-pink-550 dark:text-vega-pink':
side === Schema.Side.SIDE_SELL && !forceTheme,
'text-vega-pink-550':
side === Schema.Side.SIDE_SELL && forceTheme === 'light',
'text-vega-pink':
side === Schema.Side.SIDE_SELL && forceTheme === 'dark',
'text-market-red': side === Schema.Side.SIDE_SELL,
})}
>
{side === Schema.Side.SIDE_BUY
@@ -1,17 +1,24 @@
import { t } from '@vegaprotocol/i18n';
import type { ButtonVariant } from '@vegaprotocol/ui-toolkit';
import { Button } from '@vegaprotocol/ui-toolkit';
import { Side } from '@vegaprotocol/types';
import classNames from 'classnames';
interface Props {
variant: ButtonVariant;
side: Side;
}
export const DealTicketButton = ({ variant }: Props) => {
export const DealTicketButton = ({ side }: Props) => {
const buttonClasses = classNames(
'px-10 py-2 uppercase rounded-md text-white w-full',
{
'bg-market-red-500': side === Side.SIDE_SELL,
'bg-market-green-550': side === Side.SIDE_BUY,
}
);
return (
<div className="mb-2">
<Button variant={variant} fill type="submit" data-testid="place-order">
<button type="submit" data-testid="place-order" className={buttonClasses}>
{t('Place order')}
</Button>
</button>
</div>
);
};
@@ -1,13 +1,13 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { VegaWalletContext } from '@vegaprotocol/wallet';
import { act, render, screen } from '@testing-library/react';
import { act, render, renderHook, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { generateMarket, generateMarketData } from '../../test-helpers';
import { DealTicket } from './deal-ticket';
import * as Schema from '@vegaprotocol/types';
import { MockedProvider } from '@apollo/client/testing';
import { addDecimal } from '@vegaprotocol/utils';
import { useOrderStore } from '@vegaprotocol/orders';
import { useCreateOrderStore } from '@vegaprotocol/orders';
jest.mock('zustand');
jest.mock('./deal-ticket-fee-details', () => ({
@@ -30,6 +30,9 @@ function generateJsx() {
}
describe('DealTicket', () => {
const { result } = renderHook(() => useCreateOrderStore());
const useOrderStore = result.current;
beforeEach(() => {
localStorage.clear();
});
@@ -138,7 +141,6 @@ describe('DealTicket', () => {
reduceOnly: true,
postOnly: false,
};
useOrderStore.setState({
orders: {
[expectedOrder.marketId]: expectedOrder,
@@ -476,11 +476,7 @@ export const DealTicket = ({
pubKey={pubKey}
onClickCollateral={onClickCollateral}
/>
<DealTicketButton
variant={
order.side === Schema.Side.SIDE_BUY ? 'ternary' : 'secondary'
}
/>
<DealTicketButton side={order.side} />
<DealTicketFeeDetails
onMarketClick={onMarketClick}
feeEstimate={feeEstimate}
@@ -1,6 +1,6 @@
import omit from 'lodash/omit';
import { act, renderHook } from '@testing-library/react';
import { getDefaultOrder, useOrderStore } from '@vegaprotocol/orders';
import { getDefaultOrder, useCreateOrderStore } from '@vegaprotocol/orders';
import { useOrderForm } from './use-order-form';
jest.mock('zustand');
@@ -10,6 +10,8 @@ describe('useOrderForm', () => {
const setup = (marketId: string) => {
return renderHook(() => useOrderForm(marketId));
};
const { result } = renderHook(() => useCreateOrderStore());
const useOrderStore = result.current;
it('updates form fields when the order changes', async () => {
const order = getDefaultOrder(marketId);
+9 -27
View File
@@ -1,10 +1,6 @@
import {
DropdownMenu,
DropdownMenuContent,
ActionsDropdown,
DropdownMenuCopyItem,
DropdownMenuTrigger,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
@@ -18,27 +14,13 @@ export const FillActionsDropdown = ({
sellOrderId: string;
}) => {
return (
<DropdownMenu
trigger={
<DropdownMenuTrigger
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
data-testid="dropdown-menu"
>
<VegaIcon name={VegaIconNames.KEBAB} />
</DropdownMenuTrigger>
}
>
<DropdownMenuContent data-testid="market-actions-content">
<DropdownMenuCopyItem value={tradeId} text={t('Copy trade ID')} />
<DropdownMenuCopyItem
value={buyOrderId}
text={t('Copy buy order ID')}
/>
<DropdownMenuCopyItem
value={sellOrderId}
text={t('Copy sell order ID')}
/>
</DropdownMenuContent>
</DropdownMenu>
<ActionsDropdown data-testid="market-actions-content">
<DropdownMenuCopyItem value={tradeId} text={t('Copy trade ID')} />
<DropdownMenuCopyItem value={buyOrderId} text={t('Copy buy order ID')} />
<DropdownMenuCopyItem
value={sellOrderId}
text={t('Copy sell order ID')}
/>
</ActionsDropdown>
);
};
+3 -3
View File
@@ -85,7 +85,7 @@ describe('FillsTable', () => {
});
const amountCell = cells.find((c) => c.getAttribute('col-id') === 'size');
expect(amountCell).toHaveClass('text-vega-green-550');
expect(amountCell).toHaveClass('text-market-green-600');
});
it('should format cells correctly for seller fill', async () => {
@@ -120,7 +120,7 @@ describe('FillsTable', () => {
});
const amountCell = cells.find((c) => c.getAttribute('col-id') === 'size');
expect(amountCell).toHaveClass('text-vega-pink');
expect(amountCell).toHaveClass('text-market-red');
});
it('should format cells correctly for side unspecified', async () => {
@@ -155,7 +155,7 @@ describe('FillsTable', () => {
});
const amountCell = cells.find((c) => c.getAttribute('col-id') === 'size');
expect(amountCell).toHaveClass('text-vega-pink');
expect(amountCell).toHaveClass('text-market-red');
});
it('should render correct maker or taker role', async () => {
@@ -9,7 +9,7 @@ import type {
MarketDepthUpdateSubscription,
PriceLevelFieldsFragment,
} from './__generated__/MarketDepth';
import { useOrderStore } from '@vegaprotocol/orders';
import { useCreateOrderStore } from '@vegaprotocol/orders';
export type OrderbookData = {
asks: PriceLevelFieldsFragment[];
@@ -50,8 +50,8 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
dataProvider: marketDataProvider,
variables,
});
const updateOrder = useOrderStore((store) => store.update);
const useOrderStoreRef = useCreateOrderStore();
const updateOrder = useOrderStoreRef((store) => store.update);
return (
<AsyncRenderer
+4 -4
View File
@@ -28,8 +28,8 @@ const CumulationBar = ({
className={classNames(
'absolute top-0 left-0 h-full transition-all',
type === VolumeType.bid
? 'bg-vega-green/20 dark:bg-vega-green/50'
: 'bg-vega-pink/20 dark:bg-vega-pink/30'
? 'bg-market-green-300 dark:bg-market-green/50'
: 'bg-market-red-300 dark:bg-market-red/30'
)}
style={{
width: `${cumulativeValue}%`,
@@ -93,8 +93,8 @@ export const OrderbookRow = React.memo(
valueFormatted={addDecimalsFixedFormatNumber(price, decimalPlaces)}
className={
type === VolumeType.ask
? '!text-vega-pink dark:text-vega-pink'
: 'text-vega-green-550 dark:text-vega-green'
? 'text-market-red dark:text-market-red'
: 'text-market-green-600 dark:text-market-green'
}
/>
<NumericCell
@@ -1,18 +1,16 @@
import { t } from '@vegaprotocol/i18n';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
DropdownMenuCopyItem,
Link,
VegaIcon,
VegaIconNames,
ActionsDropdown,
} from '@vegaprotocol/ui-toolkit';
import { DApp, EXPLORER_MARKET, useLinks } from '@vegaprotocol/environment';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
export const MarketTableActions = ({
export const MarketActionsDropdown = ({
marketId,
assetId,
}: {
@@ -21,39 +19,29 @@ export const MarketTableActions = ({
}) => {
const open = useAssetDetailsDialogStore((store) => store.open);
const linkCreator = useLinks(DApp.Explorer);
return (
<DropdownMenu
trigger={
<DropdownMenuTrigger
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
data-testid="dropdown-menu"
<ActionsDropdown data-testid="market-actions-content">
<DropdownMenuCopyItem value={marketId} text={t('Copy Market ID')} />
<DropdownMenuItem>
<Link
href={linkCreator(EXPLORER_MARKET.replace(':id', marketId))}
target="_blank"
>
<VegaIcon name={VegaIconNames.KEBAB} />
</DropdownMenuTrigger>
}
>
<DropdownMenuContent data-testid="market-actions-content">
<DropdownMenuCopyItem value={marketId} text={t('Copy Market ID')} />
<DropdownMenuItem>
<Link
href={linkCreator(EXPLORER_MARKET.replace(':id', marketId))}
target="_blank"
>
<span className="flex gap-2">
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
{t('View on Explorer')}
</span>
</Link>
</DropdownMenuItem>
<DropdownMenuItem
onClick={(e) => {
open(assetId, e.target as HTMLElement);
}}
>
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
{t('View asset')}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<span className="flex gap-2">
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
{t('View on Explorer')}
</span>
</Link>
</DropdownMenuItem>
<DropdownMenuItem
onClick={(e) => {
open(assetId, e.target as HTMLElement);
}}
>
<VegaIcon name={VegaIconNames.INFO} size={16} />
{t('View settlement asset details')}
</DropdownMenuItem>
</ActionsDropdown>
);
};
@@ -12,7 +12,7 @@ import { addDecimalsFormatNumber, toBigNum } from '@vegaprotocol/utils';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import type { MarketMaybeWithData } from '../../markets-provider';
import { MarketTableActions } from './market-table-actions';
import { MarketActionsDropdown } from './market-table-actions';
interface Props {
onMarketClick: (marketId: string, metaKey?: boolean) => void;
@@ -172,7 +172,7 @@ export const useColumnDefs = ({ onMarketClick }: Props) => {
}: VegaICellRendererParams<MarketMaybeWithData>) => {
if (!data) return null;
return (
<MarketTableActions
<MarketActionsDropdown
marketId={data.id}
assetId={
data.tradableInstrument.instrument.product.settlementAsset.id
@@ -104,7 +104,7 @@ export const OracleBasicProfile = ({
'text-vega-blue': intent === Intent.Primary,
'text-vega-green dark:text-vega-green': intent === Intent.Success,
'text-yellow-600 dark:text-yellow': intent === Intent.Warning,
'text-vega-pink': intent === Intent.Danger,
'text-vega-red': intent === Intent.Danger,
},
'flex items-start align-text-bottom p-1'
)}
@@ -40,7 +40,7 @@ export const OracleProfileTitle = ({ provider }: { provider: Provider }) => {
'text-vega-blue': intent === Intent.Primary,
'text-vega-green dark:text-vega-green': intent === Intent.Success,
'text-yellow-600 dark:text-yellow': intent === Intent.Warning,
'text-vega-pink': intent === Intent.Danger,
'text-vega-red': intent === Intent.Danger,
},
'flex items-start align-text-bottom p-1'
)}
@@ -1,28 +1,13 @@
import {
DropdownMenu,
DropdownMenuContent,
ActionsDropdown,
DropdownMenuCopyItem,
DropdownMenuTrigger,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
export const OrderActionsDropdown = ({ id }: { id: string }) => {
return (
<DropdownMenu
trigger={
<DropdownMenuTrigger
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
data-testid="dropdown-menu"
>
<VegaIcon name={VegaIconNames.KEBAB} />
</DropdownMenuTrigger>
}
>
<DropdownMenuContent data-testid="market-actions-content">
<DropdownMenuCopyItem value={id} text={t('Copy order ID')} />
</DropdownMenuContent>
</DropdownMenu>
<ActionsDropdown data-testid="market-actions-content">
<DropdownMenuCopyItem value={id} text={t('Copy order ID')} />
</ActionsDropdown>
);
};
@@ -76,54 +76,4 @@ describe('order data provider', () => {
)?.length
).toEqual(5);
});
it('add only data matching date range filter', () => {
const data = [
{
id: '1',
createdAt: new Date('2022-01-29').toISOString(),
},
{
id: '2',
createdAt: new Date('2022-01-30').toISOString(),
},
] as OrderFieldsFragment[];
const delta = [
// this one should be ignored because it does not match date range
{
id: '0',
createdAt: new Date('2022-02-02').toISOString(),
},
// this one should be updated
{
id: '2',
updatedAt: new Date('2022-01-31').toISOString(),
createdAt: new Date('2022-01-30').toISOString(),
},
// this should be added
{
id: '4',
createdAt: new Date('2022-01-31').toISOString(),
},
] as OrderUpdateFieldsFragment[];
const updatedData = update(
data,
filterOrderUpdates(delta),
{
partyId: '0x123',
filter: {
dateRange: { end: new Date('2022-02-01').toISOString() },
},
},
mapOrderUpdateToOrder
);
expect(updatedData?.findIndex((node) => node.id === delta[0].id)).toEqual(
-1
);
expect(updatedData && updatedData[0].id).toEqual(delta[2].id);
expect(updatedData && updatedData[0].updatedAt).toEqual(delta[2].updatedAt);
expect(updatedData && updatedData[2].id).toEqual(delta[1].id);
expect(updatedData && updatedData[2].updatedAt).toEqual(delta[1].updatedAt);
});
});
@@ -39,13 +39,6 @@ const orderMatchFilters = (
return true;
}
if (
variables?.filter?.status &&
!(order.status && variables.filter.status.includes(order.status))
) {
return false;
}
if (
variables?.filter?.liveOnly &&
!(order.status && liveOnlyOrderStatuses.includes(order.status))
@@ -53,34 +46,6 @@ const orderMatchFilters = (
return false;
}
if (
variables?.filter?.types &&
!(order.type && variables.filter.types.includes(order.type))
) {
return false;
}
if (
variables?.filter?.timeInForce &&
!variables.filter.timeInForce.includes(order.timeInForce)
) {
return false;
}
if (variables?.filter?.excludeLiquidity && order.liquidityProvisionId) {
return false;
}
if (
variables?.filter?.dateRange?.start &&
!(order.createdAt && variables.filter.dateRange.start < order.createdAt)
) {
return false;
}
if (
variables?.filter?.dateRange?.end &&
!(order.createdAt && variables.filter.dateRange.end > order.createdAt)
) {
return false;
}
return true;
};
@@ -50,13 +50,12 @@ describe('OrderListTable', () => {
});
const expectedHeaders = [
'Market',
'Filled',
'Size',
'Type',
'Status',
'Filled',
'Price',
'Time In Force',
'Created At',
'Updated At',
'', // no cell header for edit/cancel
];
@@ -73,14 +72,13 @@ describe('OrderListTable', () => {
const cells = screen.getAllByRole('gridcell');
const expectedValues: string[] = [
marketOrder.market?.tradableInstrument.instrument.code || '',
'+0.10',
'0.05',
'0.10',
Schema.OrderTypeMapping[marketOrder.type as Schema.OrderType] || '',
Schema.OrderStatusMapping[marketOrder.status],
'5',
'-',
Schema.OrderTimeInForceMapping[marketOrder.timeInForce],
Schema.OrderTimeInForceCode[marketOrder.timeInForce],
getDateTimeFormat().format(new Date(marketOrder.createdAt)),
'-',
'Edit',
];
expectedValues.forEach((expectedValue, i) =>
@@ -96,16 +94,15 @@ describe('OrderListTable', () => {
const expectedValues: string[] = [
limitOrder.market?.tradableInstrument.instrument.code || '',
'+0.10',
'0.05',
'0.10',
Schema.OrderTypeMapping[limitOrder.type || Schema.OrderType.TYPE_LIMIT],
Schema.OrderStatusMapping[limitOrder.status],
'5',
'-',
`${
Schema.OrderTimeInForceMapping[limitOrder.timeInForce]
Schema.OrderTimeInForceCode[limitOrder.timeInForce]
}: ${getDateTimeFormat().format(new Date(limitOrder.expiresAt ?? ''))}`,
getDateTimeFormat().format(new Date(limitOrder.createdAt)),
'-',
'Edit',
];
expectedValues.forEach((expectedValue, i) =>
@@ -124,7 +121,7 @@ describe('OrderListTable', () => {
render(generateJsx({ rowData: [rejectedOrder] }));
});
const cells = screen.getAllByRole('gridcell');
expect(cells[3]).toHaveTextContent(
expect(cells[4]).toHaveTextContent(
`${Schema.OrderStatusMapping[rejectedOrder.status]}: ${
Schema.OrderRejectionReasonMapping[rejectedOrder.rejectionReason]
}`
@@ -193,7 +190,7 @@ describe('OrderListTable', () => {
});
const amendCell = getAmendCell();
const typeCell = screen.getAllByRole('gridcell')[2];
const typeCell = screen.getAllByRole('gridcell')[3];
expect(typeCell).toHaveTextContent('Liquidity provision');
expect(amendCell.queryByTestId('edit')).not.toBeInTheDocument();
expect(amendCell.queryByTestId('cancel')).not.toBeInTheDocument();
@@ -215,7 +212,7 @@ describe('OrderListTable', () => {
});
const amendCell = getAmendCell();
const typeCell = screen.getAllByRole('gridcell')[2];
const typeCell = screen.getAllByRole('gridcell')[3];
expect(typeCell).toHaveTextContent('Mid - 10.0 Peg limit');
expect(amendCell.queryByTestId('edit')).toBeInTheDocument();
expect(amendCell.queryByTestId('cancel')).toBeInTheDocument();
@@ -63,6 +63,38 @@ export const OrderListTable = memo<
cellRendererParams: { idPath: 'market.id', onMarketClick },
minWidth: 150,
},
{
headerName: t('Filled'),
field: 'remaining',
cellClass: 'font-mono text-right',
type: 'rightAligned',
valueGetter: ({ data }: VegaValueGetterParams<Order>) => {
return data?.size && data.market
? toBigNum(
(BigInt(data.size) - BigInt(data.remaining)).toString(),
data.market.positionDecimalPlaces ?? 0
).toNumber()
: undefined;
},
valueFormatter: ({
data,
value,
}: VegaValueFormatterParams<Order, 'remaining'>): string => {
if (!data) {
return '';
}
if (!data?.market || !isNumeric(value) || !isNumeric(data.size)) {
return '-';
}
return addDecimalsFormatNumber(
(BigInt(data.size) - BigInt(data.remaining)).toString(),
data.market.positionDecimalPlaces
);
},
minWidth: 50,
width: 90,
flex: 0,
},
{
headerName: t('Size'),
field: 'size',
@@ -103,7 +135,9 @@ export const OrderListTable = memo<
)
);
},
minWidth: 80,
minWidth: 50,
width: 80,
flex: 0,
},
{
field: 'type',
@@ -150,38 +184,6 @@ export const OrderListTable = memo<
),
minWidth: 100,
},
{
headerName: t('Filled'),
field: 'remaining',
cellClass: 'font-mono text-right',
type: 'rightAligned',
valueGetter: ({ data }: VegaValueGetterParams<Order>) => {
return data?.size && data.market
? toBigNum(
(BigInt(data.size) - BigInt(data.remaining)).toString(),
data.market.positionDecimalPlaces ?? 0
).toNumber()
: undefined;
},
valueFormatter: ({
data,
value,
}: VegaValueFormatterParams<Order, 'remaining'>): string => {
if (!data) {
return '';
}
if (!data?.market || !isNumeric(value) || !isNumeric(data.size)) {
return '-';
}
const { positionDecimalPlaces } = data.market;
const filled = BigInt(data.size) - BigInt(data.remaining);
return `${addDecimalsFormatNumber(
filled.toString(),
positionDecimalPlaces
)}/${addDecimalsFormatNumber(data.size, positionDecimalPlaces)}`;
},
minWidth: 100,
},
{
field: 'price',
type: 'rightAligned',
@@ -221,12 +223,10 @@ export const OrderListTable = memo<
const expiry = getDateTimeFormat().format(
new Date(data.expiresAt)
);
return `${Schema.OrderTimeInForceMapping[value]}: ${expiry}`;
return `${Schema.OrderTimeInForceCode[value]}: ${expiry}`;
}
const tifLabel = value
? Schema.OrderTimeInForceMapping[value]
: '';
const tifLabel = value ? Schema.OrderTimeInForceCode[value] : '';
const label = `${tifLabel}${
data?.postOnly ? t('. Post Only') : ''
}${data?.reduceOnly ? t('. Reduce only') : ''}`;
@@ -235,29 +235,18 @@ export const OrderListTable = memo<
},
minWidth: 150,
},
{
field: 'createdAt',
filter: DateRangeFilter,
cellRenderer: ({
value,
}: VegaICellRendererParams<Order, 'createdAt'>) => {
return (
<span data-value={value}>
{value ? getDateTimeFormat().format(new Date(value)) : value}
</span>
);
},
minWidth: 150,
},
{
field: 'updatedAt',
filter: DateRangeFilter,
valueGetter: ({ data }: VegaValueGetterParams<Order>) =>
data?.updatedAt || data?.createdAt,
cellRenderer: ({
data,
value,
}: VegaICellRendererParams<Order, 'updatedAt'>) => {
if (!data) {
return undefined;
}
const value = data.updatedAt || data.createdAt;
return (
<span data-value={value}>
{value ? getDateTimeFormat().format(new Date(value)) : '-'}
@@ -2,16 +2,17 @@ import {
getDefaultOrder,
STORAGE_KEY,
useOrder,
useOrderStore,
useCreateOrderStore,
} from './use-order-store';
import { act, renderHook } from '@testing-library/react';
import { OrderType } from '@vegaprotocol/types';
jest.mock('zustand');
describe('useOrderStore', () => {
describe('useCreateOrderStore', () => {
const setup = () => {
return renderHook(() => useOrderStore());
const { result } = renderHook(() => useCreateOrderStore());
return renderHook(() => result.current());
};
afterEach(() => {
@@ -1,6 +1,7 @@
import { OrderTimeInForce, Side } from '@vegaprotocol/types';
import { OrderType } from '@vegaprotocol/types';
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useRef } from 'react';
import type { StateCreator, UseBoundStore, Mutate, StoreApi } from 'zustand';
import { create } from 'zustand';
import { persist, subscribeWithSelector } from 'zustand/middleware';
@@ -31,58 +32,69 @@ interface Store {
export const STORAGE_KEY = 'vega_order_store';
export const useOrderStore = create<Store>()(
persist(
subscribeWithSelector((set) => ({
orders: {},
update: (marketId, order, persist = true) => {
set((state) => {
const curr = state.orders[marketId];
const defaultOrder = getDefaultOrder(marketId);
const orderStateCreator: StateCreator<Store> = (set) => ({
orders: {},
update: (marketId, order, persist = true) => {
set((state) => {
const curr = state.orders[marketId];
const defaultOrder = getDefaultOrder(marketId);
return {
orders: {
...state.orders,
[marketId]: {
...defaultOrder,
...curr,
...order,
persist,
},
},
};
});
},
});
let store: UseBoundStore<Mutate<StoreApi<Store>, []>> | null = null;
const getOrderStore = () => {
if (!store) {
store = create<Store>()(
persist(subscribeWithSelector(orderStateCreator), {
name: STORAGE_KEY,
partialize: (state) => {
// only store the order in localStorage if user has edited, this avoids
// bloating localStorage if a user just visits the page but does not
// edit the ticket
const partializedOrders: OrderMap = {};
for (const o in state.orders) {
const order = state.orders[o];
if (order && order.persist) {
partializedOrders[order.marketId] = order;
}
}
return {
orders: {
...state.orders,
[marketId]: {
...defaultOrder,
...curr,
...order,
persist,
},
},
...state,
orders: partializedOrders,
};
});
},
})),
{
name: STORAGE_KEY,
partialize: (state) => {
// only store the order in localStorage if user has edited, this avoids
// bloating localStorage if a user just visits the page but does not
// edit the ticket
const partializedOrders: OrderMap = {};
for (const o in state.orders) {
const order = state.orders[o];
if (order && order.persist) {
partializedOrders[order.marketId] = order;
}
}
},
})
);
}
return store as UseBoundStore<Mutate<StoreApi<Store>, []>>;
};
return {
...state,
orders: partializedOrders,
};
},
}
)
);
export const useCreateOrderStore = () => {
const useOrderStoreRef = useRef(getOrderStore());
return useOrderStoreRef.current;
};
/**
* Retrieves an order from the store for a market and
* creates one if it doesn't already exist
*/
export const useOrder = (marketId: string) => {
const [order, _update] = useOrderStore((store) => {
const useOrderStoreRef = useCreateOrderStore();
const [order, _update] = useOrderStoreRef((store) => {
return [store.orders[marketId], store.update];
});
@@ -1,37 +1,25 @@
import { t } from '@vegaprotocol/i18n';
import {
DropdownMenu,
DropdownMenuContent,
ActionsDropdown,
DropdownMenuItem,
DropdownMenuTrigger,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
export const PositionTableActions = ({ assetId }: { assetId: string }) => {
export const PositionActionsDropdown = ({ assetId }: { assetId: string }) => {
const open = useAssetDetailsDialogStore((store) => store.open);
return (
<DropdownMenu
trigger={
<DropdownMenuTrigger
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
data-testid="dropdown-menu"
>
<VegaIcon name={VegaIconNames.KEBAB} />
</DropdownMenuTrigger>
}
>
<DropdownMenuContent data-testid="market-actions-content">
<DropdownMenuItem
onClick={(e) => {
open(assetId, e.target as HTMLElement);
}}
>
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
{t('View asset')}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<ActionsDropdown data-testid="market-actions-content">
<DropdownMenuItem
onClick={(e) => {
open(assetId, e.target as HTMLElement);
}}
>
<VegaIcon name={VegaIconNames.INFO} size={16} />
{t('View settlement asset details')}
</DropdownMenuItem>
</ActionsDropdown>
);
};
@@ -102,8 +102,8 @@ it('add color and sign to amount, displays positive notional value', async () =>
});
let cells = screen.getAllByRole('gridcell');
expect(cells[2].classList.contains('text-vega-green-550')).toBeTruthy();
expect(cells[2].classList.contains('text-vega-pink')).toBeFalsy();
expect(cells[2].classList.contains('text-market-green-600')).toBeTruthy();
expect(cells[2].classList.contains('text-market-red')).toBeFalsy();
expect(cells[2].textContent).toEqual('+100');
expect(cells[1].textContent).toEqual('1,230.0');
await act(async () => {
@@ -115,8 +115,8 @@ it('add color and sign to amount, displays positive notional value', async () =>
);
});
cells = screen.getAllByRole('gridcell');
expect(cells[2].classList.contains('text-vega-green-550')).toBeFalsy();
expect(cells[2].classList.contains('text-vega-pink')).toBeTruthy();
expect(cells[2].classList.contains('text-market-green-600')).toBeFalsy();
expect(cells[2].classList.contains('text-market-red')).toBeTruthy();
expect(cells[2].textContent?.startsWith('-100')).toBeTruthy();
expect(cells[1].textContent).toEqual('1,230.0');
});
+3 -2
View File
@@ -38,7 +38,7 @@ import type { Position } from './positions-data-providers';
import * as Schema from '@vegaprotocol/types';
import { PositionStatus, PositionStatusMapping } from '@vegaprotocol/types';
import { DocsLinks } from '@vegaprotocol/environment';
import { PositionTableActions } from './position-actions-dropdown';
import { PositionActionsDropdown } from './position-actions-dropdown';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { LiquidationPrice } from './liquidation-price';
@@ -264,6 +264,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
if (!data) return null;
return (
<ButtonLink
title={t('View settlement asset details')}
onClick={(e) => {
openAssetDetailsDialog(
data.assetId,
@@ -449,7 +450,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
</ButtonLink>
) : null}
{data?.assetId && (
<PositionTableActions assetId={data?.assetId} />
<PositionActionsDropdown assetId={data?.assetId} />
)}
</div>
);
@@ -1,39 +1,27 @@
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
VegaIcon,
VegaIconNames,
Link,
ActionsDropdown,
} from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment';
export const ProposalActionsDropdown = ({ id }: { id: string }) => {
const linkCreator = useLinks(DApp.Token);
return (
<DropdownMenu
trigger={
<DropdownMenuTrigger
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
data-testid="dropdown-menu"
<ActionsDropdown data-testid="market-actions-content">
<DropdownMenuItem>
<Link
href={linkCreator(TOKEN_PROPOSAL.replace(':id', id))}
target="_blank"
>
<VegaIcon name={VegaIconNames.KEBAB} />
</DropdownMenuTrigger>
}
>
<DropdownMenuContent data-testid="market-actions-content">
<DropdownMenuItem>
<Link
href={linkCreator(TOKEN_PROPOSAL.replace(':id', id))}
target="_blank"
>
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
{t('View proposal')}
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
{t('View proposal')}
</Link>
</DropdownMenuItem>
</ActionsDropdown>
);
};
@@ -19,7 +19,7 @@ export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
export const ProposalsList = () => {
const gridRef = useRef<AgGridReact | null>(null);
const { data, error } = useProposalsListQuery({
const { data } = useProposalsListQuery({
variables: {
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
},
@@ -40,7 +40,7 @@ export const ProposalsList = () => {
defaultColDef={defaultColDef}
getRowId={({ data }) => data.id}
style={{ width: '100%', height: '100%' }}
overlayNoRowsTemplate={error ? error.message : t('No markets')}
overlayNoRowsTemplate={t('No markets')}
/>
</div>
);
@@ -37,11 +37,10 @@ const UpdateNetworkParameterToastContent = ({
<div>
<ToastHeading>{title}</ToastHeading>
<p className="italic">
'
{t(
`Update ${change.networkParameter.key} to ${change.networkParameter.value}`
)}
'
'{t('Update ')}
<span className="break-all">{change.networkParameter.key}</span>
{t(' to ')}
<span>{change.networkParameter.value}</span>'
</p>
{!isNaN(enactment) && (
<p>
-1
View File
@@ -11,5 +11,4 @@ export * from './use-theme-switcher';
export * from './use-storybook-theme-observer';
export * from './use-yesterday';
export * from './use-previous';
export * from './use-pane-layout';
export * from './use-copy-timeout';
+37 -1
View File
@@ -13,6 +13,28 @@ module.exports = {
current: 'currentColor',
black: '#000000',
white: '#FFFFFF',
market: {
red: {
// same as vega-red
700: '#2F000C',
600: '#7B001F',
550: '#B3002E',
DEFAULT: '#EC003C',
500: '#EC003C',
400: '#F57382',
300: '#FDD9DC',
},
green: {
// same as vega-green
700: '#012915',
600: '#01914B',
550: '#01C566',
DEFAULT: '#00F780',
500: '#00F780',
400: '#74BE8E',
300: '#DDFEE8',
},
},
vega: {
// YELLOW
yellow: {
@@ -32,7 +54,7 @@ module.exports = {
green: {
700: '#012915',
650: '#015D30',
600: '#01914B',
600: '#008545',
550: '#01C566',
DEFAULT: '#00F780',
500: '#00F780',
@@ -84,6 +106,20 @@ module.exports = {
300: '#FFD7EA',
},
// RED
red: {
700: '#2F000C',
650: '#550016',
600: '#7B001F',
550: '#B3002E',
DEFAULT: '#EC003C',
500: '#EC003C',
450: '#F03D6B',
400: '#F4668A',
350: '#F78FA9',
300: '#F8A3B9',
},
// ORANGE
orange: {
700: '#2A1701',
+3 -2
View File
@@ -3,7 +3,7 @@ import type { AgGridReact } from 'ag-grid-react';
import { useRef } from 'react';
import { tradesWithMarketProvider } from './trades-data-provider';
import { TradesTable } from './trades-table';
import { useOrderStore } from '@vegaprotocol/orders';
import { useCreateOrderStore } from '@vegaprotocol/orders';
import { t } from '@vegaprotocol/i18n';
interface TradesContainerProps {
@@ -12,7 +12,8 @@ interface TradesContainerProps {
export const TradesContainer = ({ marketId }: TradesContainerProps) => {
const gridRef = useRef<AgGridReact | null>(null);
const updateOrder = useOrderStore((store) => store.update);
const useOrderStoreRef = useCreateOrderStore();
const updateOrder = useOrderStoreRef((store) => store.update);
const { data, error } = useDataProvider({
dataProvider: tradesWithMarketProvider,
+2 -2
View File
@@ -19,8 +19,8 @@ import type { AgGridReactProps } from 'ag-grid-react';
import type { Trade } from './trades-data-provider';
import { Side } from '@vegaprotocol/types';
export const BUY_CLASS = 'text-vega-green dark:text-vega-green';
export const SELL_CLASS = 'text-vega-pink dark:text-vega-pink';
export const BUY_CLASS = 'text-market-green-600 dark:text-market-green';
export const SELL_CLASS = 'text-market-red dark:text-market-red';
const changeCellClass = ({ node }: CellClassParams) => {
let colorClass = '';
@@ -0,0 +1,26 @@
import { VegaIcon, VegaIconNames } from '../icon';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from './dropdown-menu';
export const ActionsDropdownTrigger = () => {
return (
<DropdownMenuTrigger
className='hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 [&[aria-expanded="true"]]:bg-vega-light-200 dark:[&[aria-expanded="true"]]:bg-vega-dark-200 p-0.5 rounded-full'
data-testid="dropdown-menu"
>
<VegaIcon name={VegaIconNames.KEBAB} />
</DropdownMenuTrigger>
);
};
type ActionMenuContentProps = React.ComponentProps<typeof DropdownMenuContent>;
export const ActionsDropdown = (props: ActionMenuContentProps) => {
return (
<DropdownMenu trigger={<ActionsDropdownTrigger />}>
<DropdownMenuContent {...props}></DropdownMenuContent>
</DropdownMenu>
);
};
@@ -1 +1,2 @@
export * from './dropdown-menu';
export * from './actions-dropdown';
@@ -0,0 +1,12 @@
export const IconInfo = ({ size = 14 }: { size: number }) => {
return (
<svg
width={size}
height={size}
viewBox="0 0 14 14"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M7 0C3.13 0 0 3.13 0 7C0 10.87 3.13 14 7 14C10.87 14 14 10.87 14 7C14 3.13 10.87 0 7 0ZM7.75 10.75H6.25V5.75H7.75V10.75ZM7.75 4.75H6.25V3.25H7.75V4.75Z" />
</svg>
);
};
@@ -1,72 +1,75 @@
import { IconBreakdown } from './svg-icons/icon-breakdown';
import { IconCopy } from './svg-icons/icon-copy';
import { IconDeposit } from './svg-icons/icon-deposit';
import { IconWithdraw } from './svg-icons/icon-withdraw';
import { IconTransfer } from './svg-icons/icon-transfer';
import { IconEdit } from './svg-icons/icon-edit';
import { IconMoon } from './svg-icons/icon-moon';
import { IconGlobe } from './svg-icons/icon-globe';
import { IconLinkedIn } from './svg-icons/icon-linkedin';
import { IconTwitter } from './svg-icons/icon-twitter';
import { IconQuestionMark } from './svg-icons/icon-question-mark';
import { IconForum } from './svg-icons/icon-forum';
import { IconOpenExternal } from './svg-icons/icon-open-external';
import { IconArrowRight } from './svg-icons/icon-arrow-right';
import { IconChevronUp } from './svg-icons/icon-chevron-up';
import { IconTrendUp } from './svg-icons/icon-trend-up';
import { IconCross } from './svg-icons/icon-cross';
import { IconKebab } from './svg-icons/icon-kebab';
import { IconArrowDown } from './svg-icons/icon-arrow-down';
import { IconArrowRight } from './svg-icons/icon-arrow-right';
import { IconBreakdown } from './svg-icons/icon-breakdown';
import { IconChevronDown } from './svg-icons/icon-chevron-down';
import { IconChevronUp } from './svg-icons/icon-chevron-up';
import { IconCopy } from './svg-icons/icon-copy';
import { IconCross } from './svg-icons/icon-cross';
import { IconDeposit } from './svg-icons/icon-deposit';
import { IconEdit } from './svg-icons/icon-edit';
import { IconForum } from './svg-icons/icon-forum';
import { IconGlobe } from './svg-icons/icon-globe';
import { IconInfo } from './svg-icons/icon-info';
import { IconKebab } from './svg-icons/icon-kebab';
import { IconLinkedIn } from './svg-icons/icon-linkedin';
import { IconMoon } from './svg-icons/icon-moon';
import { IconOpenExternal } from './svg-icons/icon-open-external';
import { IconQuestionMark } from './svg-icons/icon-question-mark';
import { IconTick } from './svg-icons/icon-tick';
import { IconTransfer } from './svg-icons/icon-transfer';
import { IconTrendUp } from './svg-icons/icon-trend-up';
import { IconTwitter } from './svg-icons/icon-twitter';
import { IconWithdraw } from './svg-icons/icon-withdraw';
export enum VegaIconNames {
ARROW_DOWN = 'arrow-down',
ARROW_RIGHT = 'arrow-right',
BREAKDOWN = 'breakdown',
CHEVRON_DOWN = 'chevron-down',
CHEVRON_UP = 'chevron-up',
COPY = 'copy',
CROSS = 'cross',
DEPOSIT = 'deposit',
WITHDRAW = 'withdraw',
EDIT = 'edit',
TRANSFER = 'transfer',
FORUM = 'forum',
GLOBE = 'globe',
INFO = 'info',
KEBAB = 'kebab',
LINKEDIN = 'linkedin',
TWITTER = 'twitter',
MOON = 'moon',
OPEN_EXTERNAL = 'open-external',
QUESTION_MARK = 'question-mark',
ARROW_RIGHT = 'arrow-right',
ARROW_DOWN = 'arrow-down',
CHEVRON_UP = 'chevron-up',
CHEVRON_DOWN = 'chevron-down',
TREND_UP = 'trend-up',
CROSS = 'cross',
KEBAB = 'kebab',
TICK = 'tick',
TRANSFER = 'transfer',
TREND_UP = 'trend-up',
TWITTER = 'twitter',
WITHDRAW = 'withdraw',
}
export const VegaIconNameMap: Record<
VegaIconNames,
({ size }: { size: number }) => JSX.Element
> = {
'arrow-down': IconArrowDown,
'arrow-right': IconArrowRight,
'chevron-down': IconChevronDown,
'chevron-up': IconChevronUp,
'open-external': IconOpenExternal,
'question-mark': IconQuestionMark,
'trend-up': IconTrendUp,
breakdown: IconBreakdown,
copy: IconCopy,
deposit: IconDeposit,
withdraw: IconWithdraw,
transfer: IconTransfer,
edit: IconEdit,
moon: IconMoon,
globe: IconGlobe,
linkedin: IconLinkedIn,
twitter: IconTwitter,
'question-mark': IconQuestionMark,
forum: IconForum,
'open-external': IconOpenExternal,
'arrow-right': IconArrowRight,
'arrow-down': IconArrowDown,
'chevron-up': IconChevronUp,
'chevron-down': IconChevronDown,
'trend-up': IconTrendUp,
cross: IconCross,
deposit: IconDeposit,
edit: IconEdit,
forum: IconForum,
globe: IconGlobe,
info: IconInfo,
kebab: IconKebab,
linkedin: IconLinkedIn,
moon: IconMoon,
tick: IconTick,
transfer: IconTransfer,
twitter: IconTwitter,
withdraw: IconWithdraw,
};
@@ -25,7 +25,7 @@ export const NotificationBanner = ({
'bg-vega-green-300 dark:bg-vega-green-700': intent === Intent.Success,
'bg-vega-orange-300 dark:bg-vega-orange-700':
intent === Intent.Warning,
'bg-vega-pink-300 dark:bg-vega-pink-700': intent === Intent.Danger,
'bg-vega-red-300 dark:bg-vega-red-700': intent === Intent.Danger,
},
{
'border-b-vega-light-200 dark:border-b-vega-dark-200 ':
@@ -40,7 +40,7 @@ export const NotificationBanner = ({
'border-b-vega-orange-500 dark:border-b-vega-orange-500':
intent === Intent.Warning,
'border-b-vega-pink-500 dark:border-b-vega-pink-500':
'border-b-vega-red-500 dark:border-b-vega-red-500':
intent === Intent.Danger,
}
)}
@@ -59,7 +59,7 @@ export const NotificationBanner = ({
'text-vega-orange-500 dark:text-vega-orange-500':
intent === Intent.Warning,
'text-vega-pink-500 dark:text-vega-pink-500':
'text-vega-red-500 dark:text-vega-red-500':
intent === Intent.Danger,
})}
/>
@@ -48,24 +48,12 @@ export const RichSelect = forwardRef<
const containerRef = useRef<HTMLDivElement>();
const contentRef = useRef<HTMLDivElement>();
const setWidth = () => {
if (contentRef.current) {
contentRef.current.style.width = containerRef.current ? `450px` : 'auto';
}
};
return (
<div
ref={containerRef as Ref<HTMLDivElement>}
className="flex items-center relative"
>
<SelectPrimitive.Root
{...props}
onOpenChange={() => {
setWidth();
}}
defaultOpen={false}
>
<SelectPrimitive.Root {...props} defaultOpen={false}>
<SelectPrimitive.Trigger
data-testid={props['data-testid'] || 'rich-select-trigger'}
className={classNames(
@@ -85,9 +73,10 @@ export const RichSelect = forwardRef<
<SelectPrimitive.Content
ref={contentRef as Ref<HTMLDivElement>}
className={classNames(
'relative',
'z-20',
'bg-white dark:bg-black',
'border border-neutral-500 focus:border-black dark:focus:border-white',
'border border-neutral-500 focus:border-black dark:focus:border-white rounded',
'overflow-hidden',
'shadow-lg'
)}
@@ -95,11 +84,11 @@ export const RichSelect = forwardRef<
side={'bottom'}
align={'center'}
>
<SelectPrimitive.ScrollUpButton className="flex items-center justify-center p-1 absolute w-full h-6 z-20 bg-gradient-to-t from-transparent to-neutral-50 dark:to-neutral-900">
<SelectPrimitive.ScrollUpButton className="flex items-center justify-center py-1 absolute w-full h-6 z-20 bg-gradient-to-t from-transparent to-neutral-50 dark:to-neutral-900">
<Icon name="chevron-up" />
</SelectPrimitive.ScrollUpButton>
<SelectPrimitive.Viewport>{children}</SelectPrimitive.Viewport>
<SelectPrimitive.ScrollDownButton className="flex items-center justify-center p-1 absolute bottom-0 w-full h-6 z-20 bg-gradient-to-b from-transparent to-neutral-50 dark:to-neutral-900">
<SelectPrimitive.ScrollDownButton className="flex items-center justify-center py-1 absolute bottom-0 w-full h-6 z-20 bg-gradient-to-b from-transparent to-neutral-50 dark:to-neutral-900">
<Icon name="chevron-down" />
</SelectPrimitive.ScrollDownButton>
</SelectPrimitive.Content>
@@ -36,7 +36,7 @@ it('Renders a red line if the last value is less than the first', () => {
const paths = screen.getAllByTestId('sparkline-path');
const path = paths[0];
expect(path).toHaveClass(
'[vector-effect:non-scaling-stroke] stroke-vega-pink dark:stroke-vega-pink'
'[vector-effect:non-scaling-stroke] stroke-market-red dark:stroke-market-red'
);
});
@@ -48,7 +48,7 @@ it('Renders a green line if the last value is greater than the first', () => {
const paths = screen.getAllByTestId('sparkline-path');
const path = paths[0];
expect(path).toHaveClass(
'[vector-effect:non-scaling-stroke] stroke-vega-green dark:stroke-vega-green'
'[vector-effect:non-scaling-stroke] stroke-market-green-600 dark:stroke-market-green'
);
});
@@ -9,8 +9,8 @@ function colorByChange(a: number, b: number) {
return a === b
? 'stroke-black/40 dark:stroke-white/40'
: a < b
? 'stroke-vega-green dark:stroke-vega-green'
: 'stroke-vega-pink dark:stroke-vega-pink';
? 'stroke-market-green-600 dark:stroke-market-green'
: 'stroke-market-red dark:stroke-market-red';
}
export interface SparklineProps {
@@ -38,14 +38,12 @@ export const Toggle = ({
'relative inline-flex w-full h-full text-center items-center justify-center',
'peer-checked:rounded-full',
{
'peer-checked:bg-neutral-400 dark:peer-checked:bg-white dark:peer-checked:text-black':
'peer-checked:bg-neutral-400 dark:peer-checked:bg-white peer-checked:text-white dark:peer-checked:text-black':
type === 'primary',
'dark:peer-checked:bg-vega-green peer-checked:bg-vega-green-550':
'peer-checked:bg-market-green-550 peer-checked:text-white':
type === 'buy',
'dark:peer-checked:bg-vega-pink peer-checked:bg-vega-pink-550':
type === 'sell',
'peer-checked:bg-market-red-500 peer-checked:text-white': type === 'sell',
},
'peer-checked:text-white dark:peer-checked:text-black',
'cursor-pointer peer-checked:cursor-auto select-none',
{
'px-10 py-2': size === 'lg',
+5 -2
View File
@@ -2,7 +2,7 @@ import { useAccountBalance } from '@vegaprotocol/accounts';
import type { AssetFieldsFragment } from '@vegaprotocol/assets';
import { useBalancesStore } from '@vegaprotocol/assets';
import { Balance } from '@vegaprotocol/assets';
import { addDecimal } from '@vegaprotocol/utils';
import { addDecimal, formatNumber } from '@vegaprotocol/utils';
import BigNumber from 'bignumber.js';
import { useEffect } from 'react';
@@ -23,7 +23,10 @@ export const AssetBalance = ({ asset }: { asset: AssetFieldsFragment }) => {
return (
<Balance
balance={getBalance(asset.id)?.balanceOnVega?.toString()}
balance={formatNumber(
getBalance(asset.id)?.balanceOnVega || 0,
accountDecimals || 0
)}
symbol={asset.symbol}
/>
);
+16 -30
View File
@@ -10,11 +10,9 @@ import {
} from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import {
ActionsDropdown,
ButtonLink,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
@@ -160,7 +158,7 @@ export type CompleteCellProps = {
};
export const CompleteCell = ({ data, complete }: CompleteCellProps) => {
const open = useWithdrawalApprovalDialog((state) => state.open);
const ref = useRef<HTMLDivElement>(null);
const ref = useRef<HTMLButtonElement>(null);
if (!data) {
return null;
@@ -176,32 +174,20 @@ export const CompleteCell = ({ data, complete }: CompleteCellProps) => {
{t('Complete withdrawal')}
</ButtonLink>
<DropdownMenu
trigger={
<DropdownMenuTrigger
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
data-testid="dropdown-menu"
>
<VegaIcon name={VegaIconNames.KEBAB} />
</DropdownMenuTrigger>
}
>
<DropdownMenuContent>
<DropdownMenuItem
key={'withdrawal-approval'}
data-testid="withdrawal-approval"
ref={ref}
onClick={() => {
if (data.id) {
open(data.id, ref.current, false);
}
}}
>
<VegaIcon name={VegaIconNames.BREAKDOWN} size={16} />
{t('View withdrawal details')}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<ActionsDropdown>
<DropdownMenuItem
key={'withdrawal-approval'}
data-testid="withdrawal-approval"
onClick={() => {
if (data.id) {
open(data.id, ref.current, false);
}
}}
>
<VegaIcon name={VegaIconNames.BREAKDOWN} size={16} />
{t('View withdrawal details')}
</DropdownMenuItem>
</ActionsDropdown>
</div>
);
};