Compare commits

...
Author SHA1 Message Date
Edd cf6d6e70bc fix(explorer): cache more appropriately 2022-11-25 19:19:36 +00:00
Edd 9e2dc19426 fix(explorer): fix wss urls 2022-11-25 18:54:46 +00:00
Edd 344971d5a9 fix(explorer): remove old urls from default env 2022-11-25 16:57:08 +00:00
macqbatandMadalina Raicu de1f8b5895 chore(2170): console update ledger entries columns (#2221)
* chore: update ledger entries columns

* chore: update ledger entries columns - remove labels from sender and receiver

* chore: update ledger entries columns - remove labels from sender and receiver

* chore: update ledger entries columns - remove labels from sender and receiver

Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2022-11-25 17:17:21 +01:00
Joe Tsang 5b826f89d8 chore: tests passing (#2231) 2022-11-25 15:10:57 +00:00
Art 246c07f355 feat: view proposed market change (#2189) 2022-11-25 15:10:22 +00:00
macqbat 642bc8072b chore: fix removing closed positions (#2230) 2022-11-25 14:56:59 +00:00
m.ray de8e543bf4 fix(#2171): remove user's pubkey from LP query (#2188)
* fix(#2171): remove user's pubkey from LP query

* fix(#2171): add LP partyID in account events

* fix(#2171): add LP partyID in account events

* fix(#2200): handle NotFound GraphQL errors in async renderer

* fix(#2200): data provider filter apollo graphQL not found error

* fix(#2200): update apollo-client to not report not found error link

* fix(#2200): fix log on not found error link

* fix(#2200): fix set error in data provider

* fix(#2200): extensions type access via index signature

* fix: accounts-data-provider.spec.ts had missing partyId

* fix: revert not found error commit

* fix: revert and set error in data prov
2022-11-25 14:38:02 +00:00
m.ray 787a8ea1b3 fix: deal ticket set market price (#2228) 2022-11-25 08:39:14 -05:00
mattrussell36 d28ff4cfe7 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-25 12:07:00 +00:00
mattrussell36 71e1a116c7 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-25 06:06:10 +00:00
mattrussell36 f0fc737e58 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-25 00:10:25 +00:00
m.ray fe447167ca fix(#2200): handle NotFound GraphQL errors in async renderer (#2204)
* fix(#2200): handle NotFound GraphQL errors in async renderer

* fix(#2200): data provider filter apollo graphQL not found error

* fix(#2200): update apollo-client to not report not found error link

* fix(#2200): fix log on not found error link

* fix(#2200): fix set error in data provider

* fix(#2200): extensions type access via index signature

* fix(#2200): log gql errors that are not NotFound and still throw error in data provider

* fix: remove unused import
2022-11-24 15:52:46 -08:00
m.ray 02a8a8d9ec chore: update explorer stagnet3 links (#2227) 2022-11-24 15:48:39 -08:00
mattrussell36 f7bee22ba6 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-24 18:06:14 +00:00
70 changed files with 3093 additions and 1452 deletions
@@ -70,11 +70,6 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
const step = toDecimal(market.positionDecimalPlaces);
const order = watch();
const { pubKey } = useVegaWallet();
const estMargin = useOrderMargin({
order,
market,
partyId: pubKey || '',
});
const { message: invalidText, isDisabled } = useOrderValidation({
market,
order,
@@ -127,11 +122,18 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
);
return new BigNumber(market?.depth?.lastTrade?.price)
.multipliedBy(multiplier)
.toNumber();
.toString();
}
return null;
return undefined;
}, [market?.depth?.lastTrade?.price, order.side, slippage]);
const estMargin = useOrderMargin({
order,
market,
partyId: pubKey || '',
derivedPrice: price,
});
const formattedPrice =
price && addDecimalsFormatNumber(price, market.decimalPlaces);
+4 -3
View File
@@ -1,13 +1,14 @@
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n01.stagnet3.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n01.stagnet3.vega.xyz/tm/websocket
NX_TENDERMINT_URL=https://tm.be.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=STAGNET3
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_BLOCK_EXPLORER=
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
# App flags
NX_EXPLORER_ASSETS=1
+1 -1
View File
@@ -1,6 +1,6 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://be.explorer.vega.xyz
NX_TENDERMINT_URL=https://be.explorer.vega.xyz/websocket
NX_TENDERMINT_WEBSOCKET_URL=wss://be.explorer.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
+2 -2
View File
@@ -7,7 +7,7 @@ NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
NX_TENDERMINT_URL=https://tm.be.stagnet1.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.stagnet1.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+2 -4
View File
@@ -1,10 +1,8 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=STAGNET3
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_ETHERSCAN_URL=https://be.stagnet3.vega.xyz/rest
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
+1 -1
View File
@@ -1,8 +1,8 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.testnet.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.testnet.vega.xyz/
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=TESTNET
@@ -26,7 +26,8 @@ export const TxDetailsWrapper = ({
const {
state: { data: blockData },
} = useFetch<TendermintBlocksResponse>(
`${DATA_SOURCES.tendermintUrl}/block?height=${height}`
`${DATA_SOURCES.tendermintUrl}/block?height=${height}`,
{ cache: 'force-cache' }
);
const child = useMemo(() => getTransactionComponent(txData), [txData]);
@@ -44,7 +44,7 @@ const Blocks = () => {
refetch,
} = useFetch<TendermintBlockchainResponse>(
`${DATA_SOURCES.tendermintUrl}/blockchain`,
undefined,
{ cache: 'no-cache' },
false
);
@@ -23,7 +23,8 @@ const Block = () => {
const {
state: { data: blockData, loading, error },
} = useFetch<TendermintBlocksResponse>(
`${DATA_SOURCES.tendermintUrl}/block?height=${block}`
`${DATA_SOURCES.tendermintUrl}/block?height=${block}`,
{ cache: 'force-cache' }
);
return (
+622 -118
View File
@@ -351,7 +351,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "129999.45",
"total_removed": "0",
"locked_amount": "89077.06065926284600326",
"locked_amount": "88839.711830710158224655",
"deposits": [
{
"amount": "129999.45",
@@ -417,7 +417,7 @@
"tranche_end": "2023-09-03T00:00:00.000Z",
"total_added": "52600",
"total_removed": "0",
"locked_amount": "40710.3334284627032",
"locked_amount": "40566.14878234398856",
"deposits": [
{
"amount": "2600",
@@ -590,7 +590,7 @@
"tranche_end": "2023-09-17T00:00:00.000Z",
"total_added": "5000",
"total_removed": "0",
"locked_amount": "4061.584379756469",
"locked_amount": "4047.878614916286",
"deposits": [
{
"amount": "5000",
@@ -801,7 +801,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "97499.58",
"total_removed": "0",
"locked_amount": "30598.500226108789835724",
"locked_amount": "30365.683135342087052892",
"deposits": [
{
"amount": "97499.58",
@@ -834,7 +834,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "135173.4239508",
"total_removed": "0",
"locked_amount": "41822.86719840489469619178036",
"locked_amount": "41504.64642952072194908217954",
"deposits": [
{
"amount": "135173.4239508",
@@ -867,7 +867,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "32499.86",
"total_removed": "0",
"locked_amount": "12872.2606372887369764782",
"locked_amount": "12774.31850773929295347",
"deposits": [
{
"amount": "32499.86",
@@ -900,7 +900,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "10833.29",
"total_removed": "0",
"locked_amount": "4189.7959279769199976577",
"locked_amount": "4157.916715216503367102",
"deposits": [
{
"amount": "10833.29",
@@ -933,7 +933,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "22749.93",
"total_removed": "0",
"locked_amount": "15662.392952797776307689",
"locked_amount": "15543.221335405760330901",
"deposits": [
{
"amount": "6500",
@@ -1072,7 +1072,7 @@
"tranche_end": "2023-05-01T00:00:00.000Z",
"total_added": "22500",
"total_removed": "0",
"locked_amount": "19578.18974447513925",
"locked_amount": "19453.81560773480775",
"deposits": [
{
"amount": "7500",
@@ -1125,7 +1125,7 @@
"tranche_end": "2023-06-02T00:00:00.000Z",
"total_added": "1939928.38",
"total_removed": "928642.9598472029154",
"locked_amount": "1007145.227895785748862222",
"locked_amount": "1001827.587459170315643514",
"deposits": [
{
"amount": "1852091.69",
@@ -1477,7 +1477,7 @@
"tranche_end": "2023-02-01T00:00:00.000Z",
"total_added": "42500",
"total_removed": "18381.5424969",
"locked_amount": "15821.008359752413375",
"locked_amount": "15589.90979770531325",
"deposits": [
{
"amount": "12500",
@@ -6303,8 +6303,8 @@
"tranche_id": 11,
"tranche_start": "2021-09-03T00:00:00.000Z",
"tranche_end": "2022-09-03T00:00:00.000Z",
"total_added": "45481.000000000000000003",
"total_removed": "27913.75324099301",
"total_added": "46610.000000000000000003",
"total_removed": "28274.75324099301",
"locked_amount": "0",
"deposits": [
{
@@ -6357,6 +6357,201 @@
"user": "0xDFc4B2D40D12F0eFf04b5F13D32c847f0a9ba7dD",
"tx": "0xa81022fd31ef7c0dc0e50121a8a99a2fd0c7b14a4f99e3f77ebbf8283da4e37d"
},
{
"amount": "10",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"tx": "0x20746dd7898e20747d4d7331c65d3ba443ce71c99e7ab2cb8332d5e708050dd0"
},
{
"amount": "50",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x04f0af4557ef852e5132a139f9f9c45315c86cfab2b9147cb279f6a4fb120146"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0xd2fc5b073a66634f75d80de216d4ee83de510a767e44d2a74bce25f66caf3890"
},
{
"amount": "50",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x24addf02f8ce6aa54a601359d7400e0c4f99aae8fbca961ccc7f5c155984da37"
},
{
"amount": "46",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x69b7fedbd011b574f6541eae53a4d39212f72a5c9707e244f2b56b14bda40663"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0xb3fc83a99518e3d17281c6a2f26eb9ce68e21b3a97796e6cfb6601355a58e6d1"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x0c10322e4ac684a17359fe5bff7acb6ad6ac90b0b35fd31068d6254e298f6d06"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x13e769680c99022af2fe734eda617c638b8bfb6035ca027eba47f20cb4a07a49"
},
{
"amount": "15",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x8b933a7aaa3b1ea891c4392ec290df935e0ebcd433713df4c07d8583a123b125"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x0e722eedc0d2c4cca2b38bbe54b914f0833ed77db8e068b4e0580fcc63d05fcf"
},
{
"amount": "15",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0xcfe1c973d4d73770bff8defed041187f405bfdd24835bd08294be8065deed3d5"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x3a437dda1289198f485de1dce66eda37aaec0d4d2f157a2e8e155962616f9056"
},
{
"amount": "20",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"tx": "0x71e4e558ceb26dc02a6d69dce9852a0379c07054aa9db12f7edef34ee20743ea"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0xd5cc8fd70dcd8ef2e902032c17b0284387a4032f1ecda509d8da1a87faa430de"
},
{
"amount": "20",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"tx": "0x6153b89191f8988680a2fa7cd44965e6fdfe15701b2d1973307d6e2dd3ef93d2"
},
{
"amount": "26",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0xa61b2f4a7962db3e1b3bd008949a45fca273d919236582fac2837fe9338bf09d"
},
{
"amount": "15",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"tx": "0x1cb55bafcb2c889ae684c764145e4378e029dbb6d395e9cf8670fd82b0aa6a71"
},
{
"amount": "15",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x3d5e00f458e04b8869a5a800948b27a681babcc008fad092b0cea92bd77ce4d4"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x4aa20102d2e76f332a83555ee29892be1972fd41a6a647c5dafd0aed9ac08da2"
},
{
"amount": "15",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x5c94d762403f8c1af0513f22578e4839d191f72230a4bc5e88292294056dc7b1"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x470364c533cc37371644ceec17d2ecb8efc123ae2a48a67538f1e7a551d87507"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0x005a58c1e9c52919d16b4033924a1d20c8ece3ea8b4ef31c18dc22063b6f0e37"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tx": "0xe84e0f602076c3cbbe1fce4a807cd77b7edc0a5402a60a632fa7210fcf45e519"
},
{
"amount": "60",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tx": "0x1610a45e4e6cf254dd2344a4f03b81ee4be04e3b4c46b9f1fa5460a500b86c5f"
},
{
"amount": "20",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tx": "0x973127e641cf01314a44e7560be0b54b1b139bad731e1379358e169f31b606e0"
},
{
"amount": "100",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tx": "0x03ebb823c4a3aa2794b9f9dae9b9fb75e19f518cb8fbd1c245fd07144c2a2760"
},
{
"amount": "46",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tx": "0xd5bf21ff59df324ce1fadc9acd3edf649904a0be184e91994b6f59255a98170f"
},
{
"amount": "30",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tx": "0x38ac7e75b875453765de7759023d75161f210354cdb09932a60d8e16277e1d92"
},
{
"amount": "20",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tx": "0x676bbb8223541f0527e33572dac4641a527d4719e7958bca495950c4ddc25dab"
},
{
"amount": "20",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tx": "0x8beb66b4f217717342943d8e4ec6f896a5ac4f092f948e3b2dabeaea6269814e"
},
{
"amount": "20",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tx": "0xbd37ca2a89da18ae711e2fcd7b6b41ed83b2bbdc11e0d704776f9673d7449ecf"
},
{
"amount": "60",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tx": "0x6c01fda718564da41840d86464a32afd9640b7d599d7fed2a1ff61d7c9d47193"
},
{
"amount": "20",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tx": "0xe41c66b0f4a6dd290909324fd048ff348f33c59a60974bd231920e00d4e4288d"
},
{
"amount": "30",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tx": "0xb755c0264b6b31a3aa767b0683da02d9881e7c762587621c5031ce6b4ff8f54f"
},
{
"amount": "26",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tx": "0xdcd2e1e9f393809c80283575d200a6d87096bb108a0c357a08c5e8e4f1c98de6"
},
{
"amount": "40",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tx": "0x6cd1e72f959033edd31958e6de7a44f6a1413a3bf98cd44db00c574603a06ea2"
},
{
"amount": "30",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tx": "0xc70308ea7193419a02d35ee0a39fe47f613bec25e9f681013b64b508f97aa679"
},
{
"amount": "30",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tx": "0xfd21b34d23162d743a1db14bb2072d88fd50a320c052646667de1bda6124c06c"
},
{
"amount": "10",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tx": "0x49b6f2f5f8239d2029dda62147d53666e2bae003272cd49de4ee9ffa872d9696"
},
{
"amount": "20",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
@@ -14674,6 +14869,16 @@
"user": "0xA11f6613272763Dde1F3c139c5bD1c585293c2ec",
"tx": "0xf520e07c453a758bba834b04607c7be251d39e69ce510534fdc7e68d8f738775"
},
{
"amount": "65",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"tx": "0x679502e8d24eb2c2476f3e1976f8b686639ce46358a28119894e75c8e418923b"
},
{
"amount": "296",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tx": "0xc0fbcdeac8ee69ea6a6be21a7c2865efcc37d5c70d82fc14898aae3651ca3eb7"
},
{
"amount": "565",
"user": "0xF488F160Df1975F9D032568f0f60c485f46E744f",
@@ -15693,6 +15898,30 @@
{
"address": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"deposits": [
{
"amount": "10",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"tranche_id": 11,
"tx": "0x20746dd7898e20747d4d7331c65d3ba443ce71c99e7ab2cb8332d5e708050dd0"
},
{
"amount": "20",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"tranche_id": 11,
"tx": "0x71e4e558ceb26dc02a6d69dce9852a0379c07054aa9db12f7edef34ee20743ea"
},
{
"amount": "20",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"tranche_id": 11,
"tx": "0x6153b89191f8988680a2fa7cd44965e6fdfe15701b2d1973307d6e2dd3ef93d2"
},
{
"amount": "15",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"tranche_id": 11,
"tx": "0x1cb55bafcb2c889ae684c764145e4378e029dbb6d395e9cf8670fd82b0aa6a71"
},
{
"amount": "20",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
@@ -16073,6 +16302,12 @@
}
],
"withdrawals": [
{
"amount": "65",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
"tranche_id": 11,
"tx": "0x679502e8d24eb2c2476f3e1976f8b686639ce46358a28119894e75c8e418923b"
},
{
"amount": "445",
"user": "0xB12Cdb63E38f9a6ff2C0F68aBC3CA9beFCb7148c",
@@ -16092,10 +16327,333 @@
"tx": "0x6940787f6ceaac0846e69f1bc93ad9efee8c39774b91ea29f84328ae64fc9969"
}
],
"total_tokens": "1165",
"withdrawn_tokens": "1165",
"total_tokens": "1230",
"withdrawn_tokens": "1230",
"remaining_tokens": "0"
},
{
"address": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"deposits": [
{
"amount": "50",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x04f0af4557ef852e5132a139f9f9c45315c86cfab2b9147cb279f6a4fb120146"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xd2fc5b073a66634f75d80de216d4ee83de510a767e44d2a74bce25f66caf3890"
},
{
"amount": "50",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x24addf02f8ce6aa54a601359d7400e0c4f99aae8fbca961ccc7f5c155984da37"
},
{
"amount": "46",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x69b7fedbd011b574f6541eae53a4d39212f72a5c9707e244f2b56b14bda40663"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xb3fc83a99518e3d17281c6a2f26eb9ce68e21b3a97796e6cfb6601355a58e6d1"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x0c10322e4ac684a17359fe5bff7acb6ad6ac90b0b35fd31068d6254e298f6d06"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x13e769680c99022af2fe734eda617c638b8bfb6035ca027eba47f20cb4a07a49"
},
{
"amount": "15",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x8b933a7aaa3b1ea891c4392ec290df935e0ebcd433713df4c07d8583a123b125"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x0e722eedc0d2c4cca2b38bbe54b914f0833ed77db8e068b4e0580fcc63d05fcf"
},
{
"amount": "15",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xcfe1c973d4d73770bff8defed041187f405bfdd24835bd08294be8065deed3d5"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x3a437dda1289198f485de1dce66eda37aaec0d4d2f157a2e8e155962616f9056"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xd5cc8fd70dcd8ef2e902032c17b0284387a4032f1ecda509d8da1a87faa430de"
},
{
"amount": "26",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xa61b2f4a7962db3e1b3bd008949a45fca273d919236582fac2837fe9338bf09d"
},
{
"amount": "15",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x3d5e00f458e04b8869a5a800948b27a681babcc008fad092b0cea92bd77ce4d4"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x4aa20102d2e76f332a83555ee29892be1972fd41a6a647c5dafd0aed9ac08da2"
},
{
"amount": "15",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x5c94d762403f8c1af0513f22578e4839d191f72230a4bc5e88292294056dc7b1"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x470364c533cc37371644ceec17d2ecb8efc123ae2a48a67538f1e7a551d87507"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x005a58c1e9c52919d16b4033924a1d20c8ece3ea8b4ef31c18dc22063b6f0e37"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xe84e0f602076c3cbbe1fce4a807cd77b7edc0a5402a60a632fa7210fcf45e519"
},
{
"amount": "65",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xdea46047ed750a8a035be101bb66dc68e57f08b4c7d674a3e7c5fa72aa186b2b"
},
{
"amount": "120",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x08bbc1418fc1a08ff06ec298c205eb40496e98f9c63636dd750d00c36d4c4852"
},
{
"amount": "10",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x502c6357954fe005d8d26aeb91cc519e2d23b233aeb90a9fe180bfd8087a630c"
},
{
"amount": "15",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x699de41fd489c72412a07eac668a95e676433a8a483e4c94340d9f5ea4e5883a"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xfd7e7aad721f06dc963d1e91401e33051c42740740419c2d89ec4b005d4426af"
},
{
"amount": "26",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x8c0f6f0f3362beecd8ffac3df842e61dbb8634c088871c819473ce7c1f61638f"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x0b1e9eac4f1ad30ec826525769115b4200f0d67a11039eacc7dec254cae4e6ae"
},
{
"amount": "40",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x6fec302369b6cc50b5fdd03f14a8ca5f8dc86d30b6f6695916c442d822c64464"
},
{
"amount": "100",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x51f3812a13b40b8da14240c9e1467b5193302cb45fd99524330c46b561526918"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x1196cc3f61afe969673421c6a00edaf82b48dda42986b98a4edfdb737a7fc18d"
},
{
"amount": "25",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xaa794c4025996e859a907009a44d39eb46f1485042ace3e6f0353f2ab397471a"
},
{
"amount": "10",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x2cc9394dd362b6834b700c6b5c43dd61e6c07aa6f7e0d5c3e3f3a0b5ca54b01d"
}
],
"withdrawals": [
{
"amount": "481",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x536705dd5d8f7944cd5e3414dbd374bef0d96ba8209ba93c9c19da6a0d4d4a9a"
}
],
"total_tokens": "983",
"withdrawn_tokens": "481",
"remaining_tokens": "502"
},
{
"address": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"deposits": [
{
"amount": "60",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tranche_id": 11,
"tx": "0x1610a45e4e6cf254dd2344a4f03b81ee4be04e3b4c46b9f1fa5460a500b86c5f"
},
{
"amount": "20",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tranche_id": 11,
"tx": "0x973127e641cf01314a44e7560be0b54b1b139bad731e1379358e169f31b606e0"
},
{
"amount": "100",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tranche_id": 11,
"tx": "0x03ebb823c4a3aa2794b9f9dae9b9fb75e19f518cb8fbd1c245fd07144c2a2760"
},
{
"amount": "46",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tranche_id": 11,
"tx": "0xd5bf21ff59df324ce1fadc9acd3edf649904a0be184e91994b6f59255a98170f"
},
{
"amount": "30",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tranche_id": 11,
"tx": "0x38ac7e75b875453765de7759023d75161f210354cdb09932a60d8e16277e1d92"
},
{
"amount": "20",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tranche_id": 11,
"tx": "0x676bbb8223541f0527e33572dac4641a527d4719e7958bca495950c4ddc25dab"
},
{
"amount": "20",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tranche_id": 11,
"tx": "0x8beb66b4f217717342943d8e4ec6f896a5ac4f092f948e3b2dabeaea6269814e"
}
],
"withdrawals": [
{
"amount": "296",
"user": "0xc7eC0d77a1417C97fb455f404c4B425A69a0004d",
"tranche_id": 11,
"tx": "0xc0fbcdeac8ee69ea6a6be21a7c2865efcc37d5c70d82fc14898aae3651ca3eb7"
}
],
"total_tokens": "296",
"withdrawn_tokens": "296",
"remaining_tokens": "0"
},
{
"address": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"deposits": [
{
"amount": "20",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tranche_id": 11,
"tx": "0xbd37ca2a89da18ae711e2fcd7b6b41ed83b2bbdc11e0d704776f9673d7449ecf"
},
{
"amount": "60",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tranche_id": 11,
"tx": "0x6c01fda718564da41840d86464a32afd9640b7d599d7fed2a1ff61d7c9d47193"
},
{
"amount": "20",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tranche_id": 11,
"tx": "0xe41c66b0f4a6dd290909324fd048ff348f33c59a60974bd231920e00d4e4288d"
},
{
"amount": "30",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tranche_id": 11,
"tx": "0xb755c0264b6b31a3aa767b0683da02d9881e7c762587621c5031ce6b4ff8f54f"
},
{
"amount": "26",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tranche_id": 11,
"tx": "0xdcd2e1e9f393809c80283575d200a6d87096bb108a0c357a08c5e8e4f1c98de6"
},
{
"amount": "40",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tranche_id": 11,
"tx": "0x6cd1e72f959033edd31958e6de7a44f6a1413a3bf98cd44db00c574603a06ea2"
},
{
"amount": "30",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tranche_id": 11,
"tx": "0xc70308ea7193419a02d35ee0a39fe47f613bec25e9f681013b64b508f97aa679"
},
{
"amount": "30",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tranche_id": 11,
"tx": "0xfd21b34d23162d743a1db14bb2072d88fd50a320c052646667de1bda6124c06c"
},
{
"amount": "10",
"user": "0xBF623fEe9460C1a97e0dA2eDe0e5246B45813b6a",
"tranche_id": 11,
"tx": "0x49b6f2f5f8239d2029dda62147d53666e2bae003272cd49de4ee9ffa872d9696"
}
],
"withdrawals": [],
"total_tokens": "266",
"withdrawn_tokens": "0",
"remaining_tokens": "266"
},
{
"address": "0x4cf8879dC68ebe9F003E6231CB8B704FAbEA8d9c",
"deposits": [
@@ -18359,94 +18917,6 @@
"withdrawn_tokens": "50",
"remaining_tokens": "0"
},
{
"address": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"deposits": [
{
"amount": "65",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xdea46047ed750a8a035be101bb66dc68e57f08b4c7d674a3e7c5fa72aa186b2b"
},
{
"amount": "120",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x08bbc1418fc1a08ff06ec298c205eb40496e98f9c63636dd750d00c36d4c4852"
},
{
"amount": "10",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x502c6357954fe005d8d26aeb91cc519e2d23b233aeb90a9fe180bfd8087a630c"
},
{
"amount": "15",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x699de41fd489c72412a07eac668a95e676433a8a483e4c94340d9f5ea4e5883a"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xfd7e7aad721f06dc963d1e91401e33051c42740740419c2d89ec4b005d4426af"
},
{
"amount": "26",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x8c0f6f0f3362beecd8ffac3df842e61dbb8634c088871c819473ce7c1f61638f"
},
{
"amount": "20",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x0b1e9eac4f1ad30ec826525769115b4200f0d67a11039eacc7dec254cae4e6ae"
},
{
"amount": "40",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x6fec302369b6cc50b5fdd03f14a8ca5f8dc86d30b6f6695916c442d822c64464"
},
{
"amount": "100",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x51f3812a13b40b8da14240c9e1467b5193302cb45fd99524330c46b561526918"
},
{
"amount": "30",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x1196cc3f61afe969673421c6a00edaf82b48dda42986b98a4edfdb737a7fc18d"
},
{
"amount": "25",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0xaa794c4025996e859a907009a44d39eb46f1485042ace3e6f0353f2ab397471a"
},
{
"amount": "10",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x2cc9394dd362b6834b700c6b5c43dd61e6c07aa6f7e0d5c3e3f3a0b5ca54b01d"
}
],
"withdrawals": [
{
"amount": "481",
"user": "0xf83aaA5786516F7016DF9ead2CD9F14616dA0A13",
"tranche_id": 11,
"tx": "0x536705dd5d8f7944cd5e3414dbd374bef0d96ba8209ba93c9c19da6a0d4d4a9a"
}
],
"total_tokens": "481",
"withdrawn_tokens": "481",
"remaining_tokens": "0"
},
{
"address": "0x57a018724a4518ccA397f2897BD8CB43731899a4",
"deposits": [
@@ -28928,8 +29398,8 @@
"tranche_start": "2022-03-05T00:00:00.000Z",
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "3732368.4671",
"total_removed": "409007.9945382030589",
"locked_amount": "1572132.889279723713611887036",
"total_removed": "409964.5466205507569",
"locked_amount": "1563961.5273344066896779797",
"deposits": [
{
"amount": "1998.95815",
@@ -29108,6 +29578,11 @@
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tx": "0x7310ed23baf953c36f8c7f71edfde3edb3745ce1f00b73999c56204e3784e7da"
},
{
"amount": "956.552082347698",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tx": "0xff76825dfd0803f4b17a7498793fed74ad31094cc4150867d2f25493852a369c"
},
{
"amount": "2893.9492727166165",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
@@ -29369,6 +29844,12 @@
"tranche_id": 1,
"tx": "0x7310ed23baf953c36f8c7f71edfde3edb3745ce1f00b73999c56204e3784e7da"
},
{
"amount": "956.552082347698",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tranche_id": 1,
"tx": "0xff76825dfd0803f4b17a7498793fed74ad31094cc4150867d2f25493852a369c"
},
{
"amount": "2893.9492727166165",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
@@ -29521,8 +30002,8 @@
}
],
"total_tokens": "187637.95",
"withdrawn_tokens": "107964.3534144730895",
"remaining_tokens": "79673.5965855269105"
"withdrawn_tokens": "108920.9054968207875",
"remaining_tokens": "78717.0445031792125"
},
{
"address": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
@@ -30022,8 +30503,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "15870102.715470999700000001",
"total_removed": "466274.5051748354452444",
"locked_amount": "10874369.8704474692093109479818310178872668",
"total_removed": "466327.0633126899537444",
"locked_amount": "10845394.7456409575582014225413169199432279",
"deposits": [
{
"amount": "16249.93",
@@ -30562,6 +31043,11 @@
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
"tx": "0xdddf8c03e0672650ca634d16fede3ac80ce6962708da5ac75ac67bd105ff34d8"
},
{
"amount": "52.5581378545085",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tx": "0x56c7bc1180a45c44004fe214cbecdc94d390ea780465e5ec067b268b4af7979d"
},
{
"amount": "858.1623848394685",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -33481,6 +33967,12 @@
"tranche_id": 2,
"tx": "0x2f1edcbd2367384aa1fcefb07035f54b60a5ed9716937f6f3fc3c70603c9ea27"
},
{
"amount": "52.5581378545085",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tranche_id": 2,
"tx": "0x56c7bc1180a45c44004fe214cbecdc94d390ea780465e5ec067b268b4af7979d"
},
{
"amount": "158.9965914292145",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
@@ -33615,8 +34107,8 @@
}
],
"total_tokens": "12362.05",
"withdrawn_tokens": "3856.419815042606",
"remaining_tokens": "8505.630184957394"
"withdrawn_tokens": "3908.9779528971145",
"remaining_tokens": "8453.0720471028855"
},
{
"address": "0xb091D456d0dFCB94dcba6f355379056C5bb995fC",
@@ -34241,7 +34733,7 @@
"tranche_end": "2023-05-05T00:00:00.000Z",
"total_added": "14597706.0446472999",
"total_removed": "3354105.892527157234161157",
"locked_amount": "4317703.60459960867008212228336535",
"locked_amount": "4290953.95438615584003845285762592",
"deposits": [
{
"amount": "129284.449",
@@ -40215,7 +40707,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "5778205.3912159303",
"total_removed": "2339432.642165343526844507",
"locked_amount": "1389047.40389111510815702616078974",
"locked_amount": "1378478.45531124214410403158534039",
"deposits": [
{
"amount": "552496.6455",
@@ -41934,7 +42426,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "472355.6199999996",
"total_removed": "16069.665777422296",
"locked_amount": "249113.44300109382834670835920848",
"locked_amount": "247818.64399136206106747754642312",
"deposits": [
{
"amount": "3000",
@@ -90415,7 +90907,7 @@
"tranche_start": "2021-09-03T00:00:00.000Z",
"tranche_end": "2021-09-03T00:00:00.000Z",
"total_added": "539489.4799999985",
"total_removed": "531366.1399999988",
"total_removed": "531432.8099999988",
"locked_amount": "0",
"deposits": [
{
@@ -95640,6 +96132,11 @@
}
],
"withdrawals": [
{
"amount": "66.67",
"user": "0x63ccc85135edF1EB2F559c4106aBD3B2e96107C3",
"tx": "0xc613319b71aa10ffadd89ae92e126339b01bf5a76f2e72e920e0ec6012551610"
},
{
"amount": "66.67",
"user": "0x82CEDEAd8B2D52565c157c9f209C4D9659eA8990",
@@ -102209,10 +102706,17 @@
"tx": "0xee02e72ef8e0755982704385da512cc12c8ff0ea7b58056fa3d5a5932394e9ca"
}
],
"withdrawals": [],
"withdrawals": [
{
"amount": "66.67",
"user": "0x63ccc85135edF1EB2F559c4106aBD3B2e96107C3",
"tranche_id": 7,
"tx": "0xc613319b71aa10ffadd89ae92e126339b01bf5a76f2e72e920e0ec6012551610"
}
],
"total_tokens": "66.67",
"withdrawn_tokens": "0",
"remaining_tokens": "66.67"
"withdrawn_tokens": "66.67",
"remaining_tokens": "0"
},
{
"address": "0x055c22a4e4b5751bb0B2617F8872DC00278C90F8",
@@ -116,7 +116,7 @@ context(
cy.get(newProposalSubmitButton).click();
cy.get(feedbackError).should(
'have.text',
'proposal_submission.terms.closing_timestamp: cannot be after enactment time'
'Invalid params: proposal_submission.terms.closing_timestamp (cannot be after enactment time)'
);
cy.get(dialogCloseButton).click();
cy.get(minVoteDeadline).click();
@@ -157,7 +157,7 @@ context(
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should(
'have.text',
'*: unknown field "signers" in vega.DataSourceDefinition'
'Invalid params: the transaction is malformed'
);
});
@@ -28,7 +28,6 @@ context(
before('visit staking tab and connect vega wallet', function () {
cy.visit('/');
cy.verify_page_header('The $VEGA token');
cy.vega_wallet_connect();
cy.vega_wallet_set_specified_approval_amount('1000');
});
@@ -43,10 +43,6 @@ context(
it('Able to open withdrawal form with vega wallet connected', function () {
// needs to reload page for withdrawal form to be displayed in ci - not reproducible outside of ci
cy.getByTestId(withdraw).should('be.visible').click();
cy.visit('/');
cy.navigate_to('withdrawals');
cy.ethereum_wallet_connect();
cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(selectAsset)
.find('option')
.should('have.length.at.least', 2);
@@ -93,6 +93,7 @@ Cypress.Commands.add('faucet_asset', function (assetEthAddress) {
Cypress.Commands.add('vega_wallet_teardown', function () {
cy.get(vegaWalletContainer).within(() => {
cy.get(vegaWalletAssociatedBalance)
.first()
.invoke('text')
.then((balance) => {
if (balance != '0.00') {
@@ -100,6 +101,10 @@ Cypress.Commands.add('vega_wallet_teardown', function () {
cy.vega_wallet_teardown_staking(this.stakingBridgeContract);
}
});
cy.get('[data-test-id="associated-amount"]', { timeout: 30000 }).should(
'contain.text',
'0.00'
);
});
cy.get(vegaWalletContainer).within(() => {
+1 -1
View File
@@ -3,6 +3,6 @@ NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_EXPLORER_URL=https://staging3.explorer.vega.xyz
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
+2 -2
View File
@@ -4,11 +4,11 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://staging3.explorer.vega.xyz
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
CYPRESS_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
CYPRESS_EXPLORER_URL=https://staging3.explorer.vega.xyz
CYPRESS_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
@@ -1,4 +1,9 @@
import { aliasQuery } from '@vegaprotocol/cypress';
import { Schema } from '@vegaprotocol/types';
import {
generateProposals,
marketUpdateProposal,
} from '../support/mocks/generate-proposals';
const marketSummaryBlock = 'header-summary';
const marketExpiry = 'market-expiry';
@@ -12,6 +17,42 @@ const priceChangeValue = 'price-change';
const itemHeader = 'item-header';
const itemValue = 'item-value';
describe('Market proposal notification', { tags: '@smoke' }, () => {
before(() => {
cy.mockTradingPage(
Schema.MarketState.STATE_ACTIVE,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY
);
cy.mockGQL((req) => {
aliasQuery(
req,
'ProposalsList',
generateProposals([marketUpdateProposal])
);
});
cy.mockGQLSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@MarketData');
cy.getByTestId(marketSummaryBlock).should('be.visible');
});
it('should display market proposal notification if proposal found', () => {
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId('market-proposal-notification').should(
'contain.text',
'Changes have been proposed for this market'
);
cy.getByTestId('market-proposal-notification').within(() => {
cy.getByTestId('external-link').should(
'have.attr',
'href',
'https://stagnet3.token.vega.xyz/governance/123'
);
});
});
});
});
describe('Market trading page', () => {
before(() => {
cy.mockTradingPage(
@@ -0,0 +1,42 @@
import { aliasQuery } from '@vegaprotocol/cypress';
import { generateLedgerEntries } from '../support/mocks/generate-ledger-entries';
import { connectVegaWallet } from '../support/vega-wallet';
import { generateAssets } from '../support/mocks/generate-assets';
import { generateMarkets } from '../support/mocks/generate-markets';
describe('Portfolio page', { tags: '@regression' }, () => {
beforeEach(() => {
cy.mockGQL((req) => {
aliasQuery(req, 'LedgerEntries', generateLedgerEntries());
aliasQuery(req, 'Assets', generateAssets());
aliasQuery(req, 'Markets', generateMarkets());
});
cy.mockGQLSubscription();
});
describe('Ledger entries', () => {
it('List should be properly rendered', () => {
cy.visit('/#/portfolio');
connectVegaWallet();
cy.get('[data-testid="Ledger entries"]').click();
const headers = [
'Sender',
'Receiver',
'Transfer Type',
'Quantity',
'Asset',
'Vega Time',
];
cy.get('.ag-header-row.ag-header-row-column').within(($headers) => {
cy.wrap($headers)
.get('.ag-header-cell-text')
.each(($header, i) => {
cy.wrap($header).should('have.text', headers[i]);
});
});
cy.get('.ag-center-cols-container .ag-row').should(
'have.length',
generateLedgerEntries().ledgerEntries.edges.length
);
});
});
});
@@ -0,0 +1,258 @@
import type { LedgerEntriesQuery } from '@vegaprotocol/ledger';
import { Schema as Types } from '@vegaprotocol/types';
const ledgerEntries: LedgerEntriesQuery = {
ledgerEntries: {
edges: [
{
node: {
vegaTime: '1669224476734364000',
quantity: '0',
assetId: 'asset-id',
transferType: Types.TransferType.TRANSFER_TYPE_MARGIN_HIGH,
receiverAccountType: Types.AccountType.ACCOUNT_TYPE_EXTERNAL,
receiverMarketId: 'market-1',
receiverPartyId: 'network',
senderAccountType: Types.AccountType.ACCOUNT_TYPE_GENERAL,
senderMarketId: 'market-0',
senderPartyId:
'2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '1669221452175594000',
quantity: '0',
assetId: 'asset-id-2',
transferType: Types.TransferType.TRANSFER_TYPE_MARGIN_HIGH,
receiverAccountType: Types.AccountType.ACCOUNT_TYPE_EXTERNAL,
receiverMarketId: 'market-0',
receiverPartyId: 'network',
senderAccountType: Types.AccountType.ACCOUNT_TYPE_GENERAL,
senderMarketId: 'market-2',
senderPartyId:
'2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '1669209347054198000',
quantity: '0',
assetId: 'asset-id',
transferType: Types.TransferType.TRANSFER_TYPE_MARGIN_HIGH,
receiverAccountType: Types.AccountType.ACCOUNT_TYPE_EXTERNAL,
receiverMarketId: 'market-3',
receiverPartyId: 'network',
senderAccountType: Types.AccountType.ACCOUNT_TYPE_GENERAL,
senderMarketId: 'market-2',
senderPartyId: 'sender party id',
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '1669209345512806000',
quantity: '0',
assetId: 'asset-id',
transferType: Types.TransferType.TRANSFER_TYPE_MARGIN_HIGH,
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '1669209316163397000',
quantity: '0',
assetId: 'asset-id-2',
transferType: Types.TransferType.TRANSFER_TYPE_MARGIN_HIGH,
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '1669209299051286000',
quantity: '1326783',
assetId: 'asset-id-2',
transferType: Types.TransferType.TRANSFER_TYPE_MTM_WIN,
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '1669209151328614000',
quantity: '0',
assetId:
'5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
transferType: Types.TransferType.TRANSFER_TYPE_MARGIN_HIGH,
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '1669209117655380000',
quantity: '0',
assetId:
'5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
transferType: Types.TransferType.TRANSFER_TYPE_MARGIN_HIGH,
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '1669209082788024000',
quantity: '1326783',
assetId:
'5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
transferType: Types.TransferType.TRANSFER_TYPE_MTM_WIN,
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '1669209076546363000',
quantity: '0',
assetId:
'cee709223217281d7893b650850ae8ee8a18b7539b5658f9b4cc24de95dd18ad',
transferType: Types.TransferType.TRANSFER_TYPE_MARGIN_HIGH,
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '2022-11-24T13:36:42.13989Z',
quantity: '9078407730948615',
assetId:
'cee709223217281d7893b650850ae8ee8a18b7539b5658f9b4cc24de95dd18ad',
transferType: Types.TransferType.TRANSFER_TYPE_MARGIN_LOW,
receiverAccountType: Types.AccountType.ACCOUNT_TYPE_GENERAL,
receiverMarketId: null,
receiverPartyId:
'2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
senderAccountType: Types.AccountType.ACCOUNT_TYPE_MARGIN,
senderMarketId:
'0942d767cb2cb5a795e14216e8e53c2b6f75e46dc1732c5aeda8a5aba4ad193d',
senderPartyId:
'2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '2022-11-24T13:35:49.257039Z',
quantity: '263142253070974',
assetId:
'cee709223217281d7893b650850ae8ee8a18b7539b5658f9b4cc24de95dd18ad',
transferType: Types.TransferType.TRANSFER_TYPE_MARGIN_LOW,
receiverAccountType: Types.AccountType.ACCOUNT_TYPE_GENERAL,
receiverMarketId: null,
receiverPartyId:
'2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
senderAccountType: Types.AccountType.ACCOUNT_TYPE_MARGIN,
senderMarketId:
'0942d767cb2cb5a795e14216e8e53c2b6f75e46dc1732c5aeda8a5aba4ad193d',
senderPartyId:
'2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '2022-11-24T12:41:22.054428Z',
quantity: '1000000000',
assetId:
'4e4e80abff30cab933b8c4ac6befc618372eb76b2cbddc337eff0b4a3a4d25b8',
transferType: Types.TransferType.TRANSFER_TYPE_DEPOSIT,
receiverAccountType: Types.AccountType.ACCOUNT_TYPE_EXTERNAL,
receiverMarketId: null,
receiverPartyId: 'network',
senderAccountType: Types.AccountType.ACCOUNT_TYPE_GENERAL,
senderMarketId: null,
senderPartyId:
'2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '2022-11-24T12:39:11.516154Z',
quantity: '1000000000000',
assetId:
'c9fe6fc24fce121b2cc72680543a886055abb560043fda394ba5376203b7527d',
transferType: Types.TransferType.TRANSFER_TYPE_DEPOSIT,
receiverAccountType: Types.AccountType.ACCOUNT_TYPE_EXTERNAL,
receiverMarketId: null,
receiverPartyId: 'network',
senderAccountType: Types.AccountType.ACCOUNT_TYPE_GENERAL,
senderMarketId: null,
senderPartyId:
'2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '2022-11-24T12:37:26.832226Z',
quantity: '10000000000000000000000',
assetId:
'c9fe6fc24fce121b2cc72680543a886055abb560043fda394ba5376203b7527d',
transferType: Types.TransferType.TRANSFER_TYPE_DEPOSIT,
receiverAccountType: Types.AccountType.ACCOUNT_TYPE_EXTERNAL,
receiverMarketId: null,
receiverPartyId: 'network',
senderAccountType: Types.AccountType.ACCOUNT_TYPE_GENERAL,
senderMarketId: null,
senderPartyId:
'2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
{
node: {
vegaTime: '2022-11-24T12:24:52.844901Z',
quantity: '49390000000000000000000',
assetId:
'c9fe6fc24fce121b2cc72680543a886055abb560043fda394ba5376203b7527d',
transferType: Types.TransferType.TRANSFER_TYPE_DEPOSIT,
receiverAccountType: Types.AccountType.ACCOUNT_TYPE_EXTERNAL,
receiverMarketId: null,
receiverPartyId: 'network',
senderAccountType: Types.AccountType.ACCOUNT_TYPE_GENERAL,
senderMarketId: null,
senderPartyId:
'2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
__typename: 'AggregatedLedgerEntry',
},
__typename: 'AggregatedLedgerEntriesEdge',
},
],
pageInfo: {
startCursor:
'eyJ2ZWdhX3RpbWUiOiIyMDIyLTExLTIzVDE3OjI3OjU2LjczNDM2NFoifQ==',
endCursor: 'eyJ2ZWdhX3RpbWUiOiIyMDIyLTExLTIzVDEzOjExOjE2LjU0NjM2M1oifQ==',
hasNextPage: true,
hasPreviousPage: false,
__typename: 'PageInfo',
},
__typename: 'AggregatedLedgerEntriesConnection',
},
};
export const generateLedgerEntries = () => {
return { ...ledgerEntries };
};
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -3,7 +3,7 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://staging3.explorer.vega.xyz
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
+1 -1
View File
@@ -3,7 +3,7 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://staging3.explorer.vega.xyz
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
@@ -69,10 +69,7 @@ export const Liquidity = () => {
} = useDataProvider({
dataProvider: lpAggregatedDataProvider,
update,
variables: useMemo(
() => ({ marketId, partyId: pubKey }),
[marketId, pubKey]
),
variables: useMemo(() => ({ marketId }), [marketId]),
});
// To be removed when liquidityProvision subscriptions are working
@@ -36,6 +36,7 @@ import { Last24hPriceChange } from '../../components/last-24h-price-change';
import { MarketMarkPrice } from '../../components/market-mark-price';
import { MarketTradingModeComponent } from '../../components/market-trading-mode';
import { Last24hVolume } from '../../components/last-24h-volume';
import { MarketProposalNotification } from '@vegaprotocol/governance';
const NO_MARKET = t('No market');
@@ -177,6 +178,7 @@ export const TradeMarketHeader = ({
</div>
</HeaderStat>
) : null}
<MarketProposalNotification marketId={market?.id} />
</Header>
);
};
+2 -2
View File
@@ -10,7 +10,7 @@ interface TradeMarketHeaderProps {
export const Header = ({ title, children }: TradeMarketHeaderProps) => {
return (
<header className="w-screen xl:px-4 pt-4 border-b border-default">
<header className="w-screen xl:px-4 pt-3 border-b border-default">
<div className="xl:flex xl:gap-4 items-start">
<div className="mb-4 xl:mb-0 px-4 xl:px-0">{title}</div>
<div
@@ -43,7 +43,7 @@ export const HeaderStat = ({
testId?: string;
}) => {
const itemClass =
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-default';
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-default mt-1';
const itemHeading = 'text-neutral-500 dark:text-neutral-400';
return (
@@ -144,7 +144,7 @@ export const SelectMarketPopover = ({
onCellClick: OnCellClickHandler;
}) => {
const triggerClasses =
'sm:text-lg md:text-xl lg:text-2xl flex items-center gap-2 whitespace-nowrap hover:text-neutral-500 dark:hover:text-neutral-300';
'sm:text-lg md:text-xl lg:text-2xl flex items-center gap-2 whitespace-nowrap hover:text-neutral-500 dark:hover:text-neutral-300 mt-1';
const { pubKey } = useVegaWallet();
const [open, setOpen] = useState(false);
const { data, loading: marketsLoading } = useMarketList();
+5 -1
View File
@@ -7,6 +7,9 @@ fragment AccountFields on AccountBalance {
asset {
id
}
party {
id
}
}
query Accounts($partyId: ID!) {
@@ -22,11 +25,12 @@ query Accounts($partyId: ID!) {
}
}
subscription AccountEvents($partyId: ID!) {
subscription AccountEvents($partyId: ID) {
accounts(partyId: $partyId) {
type
balance
assetId
marketId
partyId
}
}
+10 -6
View File
@@ -3,21 +3,21 @@ import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type AccountFieldsFragment = { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, market?: { __typename?: 'Market', id: string } | null, asset: { __typename?: 'Asset', id: string } };
export type AccountFieldsFragment = { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, market?: { __typename?: 'Market', id: string } | null, asset: { __typename?: 'Asset', id: string }, party?: { __typename?: 'Party', id: string } | null };
export type AccountsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type AccountsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, market?: { __typename?: 'Market', id: string } | null, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null } | null };
export type AccountsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, market?: { __typename?: 'Market', id: string } | null, asset: { __typename?: 'Asset', id: string }, party?: { __typename?: 'Party', id: string } | null } } | null> | null } | null } | null };
export type AccountEventsSubscriptionVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
partyId?: Types.InputMaybe<Types.Scalars['ID']>;
}>;
export type AccountEventsSubscription = { __typename?: 'Subscription', accounts: Array<{ __typename?: 'AccountUpdate', type: Types.AccountType, balance: string, assetId: string, marketId?: string | null }> };
export type AccountEventsSubscription = { __typename?: 'Subscription', accounts: Array<{ __typename?: 'AccountUpdate', type: Types.AccountType, balance: string, assetId: string, marketId?: string | null, partyId: string }> };
export const AccountFieldsFragmentDoc = gql`
fragment AccountFields on AccountBalance {
@@ -29,6 +29,9 @@ export const AccountFieldsFragmentDoc = gql`
asset {
id
}
party {
id
}
}
`;
export const AccountsDocument = gql`
@@ -74,12 +77,13 @@ export type AccountsQueryHookResult = ReturnType<typeof useAccountsQuery>;
export type AccountsLazyQueryHookResult = ReturnType<typeof useAccountsLazyQuery>;
export type AccountsQueryResult = Apollo.QueryResult<AccountsQuery, AccountsQueryVariables>;
export const AccountEventsDocument = gql`
subscription AccountEvents($partyId: ID!) {
subscription AccountEvents($partyId: ID) {
accounts(partyId: $partyId) {
type
balance
assetId
marketId
partyId
}
}
`;
@@ -100,7 +104,7 @@ export const AccountEventsDocument = gql`
* },
* });
*/
export function useAccountEventsSubscription(baseOptions: Apollo.SubscriptionHookOptions<AccountEventsSubscription, AccountEventsSubscriptionVariables>) {
export function useAccountEventsSubscription(baseOptions?: Apollo.SubscriptionHookOptions<AccountEventsSubscription, AccountEventsSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<AccountEventsSubscription, AccountEventsSubscriptionVariables>(AccountEventsDocument, options);
}
@@ -26,6 +26,7 @@ describe('getId', () => {
balance: '1',
assetId: 'assetId',
marketId: '',
partyId: 'partyId',
})
);
expect(
@@ -41,6 +42,7 @@ describe('getId', () => {
balance: '1',
assetId: 'assetId',
marketId: 'testId',
partyId: 'partyId',
})
);
});
+32 -3
View File
@@ -1,4 +1,4 @@
import type { InMemoryCacheConfig } from '@apollo/client';
import type { ApolloError, InMemoryCacheConfig } from '@apollo/client';
import {
ApolloClient,
from,
@@ -13,9 +13,12 @@ import { createClient as createWSClient } from 'graphql-ws';
import { onError } from '@apollo/client/link/error';
import { RetryLink } from '@apollo/client/link/retry';
import ApolloLinkTimeout from 'apollo-link-timeout';
import type { GraphQLErrors } from '@apollo/client/errors';
const isBrowser = typeof window !== 'undefined';
const NOT_FOUND = 'NotFound';
export function createClient(base?: string, cacheConfig?: InMemoryCacheConfig) {
if (!base) {
throw new Error('Base must be passed into createClient!');
@@ -61,8 +64,16 @@ export function createClient(base?: string, cacheConfig?: InMemoryCacheConfig) {
: httpLink;
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) console.log(graphQLErrors);
if (networkError) console.log(networkError);
if (graphQLErrors) {
graphQLErrors.forEach((e) => {
if (e.extensions && e.extensions['type'] !== NOT_FOUND) {
console.log(e);
}
});
}
if (networkError) {
console.log(networkError);
}
});
return new ApolloClient({
@@ -70,3 +81,21 @@ export function createClient(base?: string, cacheConfig?: InMemoryCacheConfig) {
cache: new InMemoryCache(cacheConfig),
});
}
const isApolloGraphQLError = (
error: ApolloError | Error | undefined
): error is ApolloError => {
return !!error && !!(error as ApolloError).graphQLErrors;
};
const hasNotFoundGraphQLErrors = (errors: GraphQLErrors) => {
return errors.some((e) => e.extensions && e.extensions['type'] === NOT_FOUND);
};
export const isNotFoundGraphQLError = (
error: Error | ApolloError | undefined
) => {
return (
isApolloGraphQLError(error) && hasNotFoundGraphQLErrors(error.graphQLErrors)
);
};
@@ -3,6 +3,7 @@ import { useAssetsDataProvider } from './assets-data-provider';
import { Button, Dialog, Icon, Splash } from '@vegaprotocol/ui-toolkit';
import create from 'zustand';
import { AssetDetailsTable } from './asset-details-table';
import { AssetProposalNotification } from '@vegaprotocol/governance';
export type AssetDetailsDialogStore = {
isOpen: boolean;
@@ -49,6 +50,7 @@ export const AssetDetailsDialog = ({
const content = asset ? (
<div className="my-2">
<AssetProposalNotification assetId={asset.id} />
<AssetDetailsTable asset={asset} />
</div>
) : (
@@ -17,7 +17,7 @@ export const MarginWarning = ({ margin, balance, asset }: Props) => {
return (
<>
<div
className="text-sm text-vega-orange mb-4"
className="text-xs text-vega-orange mb-4"
data-testid="dealticket-warning-margin"
>
<p className="mb-2">
@@ -5,8 +5,8 @@ import {
} from '@vegaprotocol/react-helpers';
import { Input, InputError, Tooltip } from '@vegaprotocol/ui-toolkit';
import { isMarketInAuction, validateAmount } from '../../utils';
import type { DealTicketAmountProps } from './deal-ticket-amount';
import { getMarketPrice } from '../../utils/get-price';
export type DealTicketMarketAmountProps = Omit<
DealTicketAmountProps,
@@ -21,21 +21,7 @@ export const DealTicketMarketAmount = ({
const quoteName =
market.tradableInstrument.instrument.product.settlementAsset.symbol;
const sizeStep = toDecimal(market?.positionDecimalPlaces);
let price;
if (isMarketInAuction(market)) {
// 0 can never be a valid uncrossing price
// as it would require there being orders on the book at that price.
if (
market.data?.indicativePrice &&
market.data.indicativePrice !== '0' &&
BigInt(market.data?.indicativePrice) !== BigInt(0)
) {
price = market.data.indicativePrice;
}
} else {
price = market.depth?.lastTrade?.price;
}
const price = getMarketPrice(market);
const priceFormatted = price
? addDecimalsFormatNumber(price, market.decimalPlaces)
@@ -46,7 +32,7 @@ export const DealTicketMarketAmount = ({
<div className="flex items-end gap-4 mb-2">
<div className="flex-1 text-sm">Size</div>
<div />
<div className="flex-1 text-sm text-right">
<div className="flex-2 text-sm text-right">
{isMarketInAuction(market) && (
<Tooltip
description={t(
@@ -69,7 +69,7 @@ describe('DealTicket', () => {
// Assert last price is shown
expect(screen.getByTestId('last-price')).toHaveTextContent(
// eslint-disable-next-line
`~${addDecimal(market!.depth!.lastTrade!.price, market.decimalPlaces)} ${
`~${addDecimal(market!.data.markPrice, market.decimalPlaces)} ${
market.tradableInstrument.instrument.product.settlementAsset.symbol
}`
);
@@ -63,9 +63,11 @@ export const DealTicket = ({
const order = watch();
// When order state changes persist it in local storage
useEffect(() => setPersistedOrder(order), [order, setPersistedOrder]);
const hasNoBalance = useHasNoBalance(
market.tradableInstrument.instrument.product.settlementAsset.id
);
const onSubmit = useCallback(
(order: OrderSubmissionBody['orderSubmission']) => {
if (!pubKey) {
@@ -1,5 +1,6 @@
import { FeesBreakdown } from '@vegaprotocol/market-info';
import {
addDecimal,
addDecimalsFormatNumber,
formatNumber,
t,
@@ -20,34 +21,39 @@ import { useCalculateSlippage } from './use-calculate-slippage';
import { useOrderCloseOut } from './use-order-closeout';
import { useOrderMargin } from './use-order-margin';
import type { OrderMargin } from './use-order-margin';
import { getDerivedPrice } from '../utils/get-price';
export const useFeeDealTicketDetails = (
order: OrderSubmissionBody['orderSubmission'],
market: MarketDealTicket
) => {
const { pubKey } = useVegaWallet();
const slippage = useCalculateSlippage({ marketId: market.id, order });
const price = useMemo(() => {
const estPrice = order.price || market.data.markPrice;
if (estPrice) {
const derivedPrice = useMemo(() => {
return getDerivedPrice(order, market);
}, [order, market]);
// Note this isn't currently used anywhere
const slippageAdjustedPrice = useMemo(() => {
if (derivedPrice) {
if (slippage && parseFloat(slippage) !== 0) {
const isLong = order.side === Schema.Side.SIDE_BUY;
const multiplier = new BigNumber(1)[isLong ? 'plus' : 'minus'](
parseFloat(slippage) / 100
);
return new BigNumber(estPrice).multipliedBy(multiplier).toNumber();
return new BigNumber(derivedPrice).multipliedBy(multiplier).toNumber();
}
return order.price;
return derivedPrice;
}
return null;
}, [market.data.markPrice, order.price, order.side, slippage]);
}, [derivedPrice, order.side, slippage]);
const estMargin: OrderMargin | null = useOrderMargin({
order,
market,
partyId: pubKey || '',
derivedPrice,
});
const { data: partyBalance } = usePartyBalanceQuery({
@@ -62,11 +68,13 @@ export const useFeeDealTicketDetails = (
});
const notionalSize = useMemo(() => {
if (order.price && order.size) {
return new BigNumber(order.size).multipliedBy(order.price).toString();
if (derivedPrice && order.size) {
return new BigNumber(order.size)
.multipliedBy(addDecimal(derivedPrice, market.decimalPlaces))
.toString();
}
return null;
}, [order.price, order.size]);
}, [derivedPrice, order.size, market.decimalPlaces]);
const quoteName = market.tradableInstrument.instrument.product.quoteName;
@@ -78,7 +86,7 @@ export const useFeeDealTicketDetails = (
estMargin,
estCloseOut,
slippage,
price,
slippageAdjustedPrice,
partyData: partyBalance,
};
}, [
@@ -88,7 +96,7 @@ export const useFeeDealTicketDetails = (
estMargin,
estCloseOut,
slippage,
price,
slippageAdjustedPrice,
partyBalance,
]);
};
@@ -100,7 +108,6 @@ export interface FeeDetails {
estMargin: OrderMargin | null;
estCloseOut: string | null;
slippage: string | null;
price?: string | number | null;
}
export const getFeeDetailsValues = ({
@@ -5,6 +5,7 @@ import type { PositionMargin } from './use-market-positions';
import type { Props } from './use-order-margin';
import { useOrderMargin } from './use-order-margin';
import { Schema } from '@vegaprotocol/types';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
let mockEstimateData = {
estimateOrder: {
@@ -58,7 +59,7 @@ describe('useOrderMargin', () => {
indicativePrice: '100',
markPrice: '200',
},
},
} as MarketDealTicket,
partyId: 'partyId',
};
+6 -46
View File
@@ -1,27 +1,16 @@
import { BigNumber } from 'bignumber.js';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { Schema } from '@vegaprotocol/types';
import { removeDecimal } from '@vegaprotocol/react-helpers';
import { useMarketPositions } from './use-market-positions';
import type { EstimateOrderQuery } from './__generated__/EstimateOrder';
import { useEstimateOrderQuery } from './__generated__/EstimateOrder';
import { isMarketInAuction } from '../utils';
interface Market {
id: string;
decimalPlaces: number;
positionDecimalPlaces: number;
tradingMode: Schema.MarketTradingMode;
data: {
indicativePrice: string;
markPrice: string;
};
}
import type { MarketDealTicket } from '@vegaprotocol/market-list';
export interface Props {
order: OrderSubmissionBody['orderSubmission'];
market: Market;
market: MarketDealTicket;
partyId: string;
derivedPrice?: string;
}
const addFees = (feeObj: EstimateOrderQuery['estimateOrder']['fee']) => {
@@ -44,21 +33,21 @@ export const useOrderMargin = ({
order,
market,
partyId,
derivedPrice,
}: Props): OrderMargin | null => {
const marketPositions = useMarketPositions({ marketId: market.id, partyId });
const priceForEstimate = getPriceForEstimate(order, market);
const { data } = useEstimateOrderQuery({
variables: {
marketId: market.id,
partyId,
price: priceForEstimate,
price: derivedPrice,
size: removeDecimal(order.size, market.positionDecimalPlaces),
side: order.side,
timeInForce: order.timeInForce,
type: order.type,
},
skip: !partyId || !market.id || !order.size || !priceForEstimate,
skip: !partyId || !market.id || !order.size || !derivedPrice,
});
if (data?.estimateOrder.marginLevels.initialLevel) {
@@ -86,32 +75,3 @@ export const useOrderMargin = ({
}
return null;
};
/**
* Gets a price to use for estimating order margin and fees.
* Market orders should use the markPrice or if in auction mode
* the indicative price. If its a limit order use user input price.
*/
const getPriceForEstimate = (
order: {
type: Schema.OrderType;
price?: string | undefined;
},
market: Market
) => {
// If order type is market we should use either the mark price
// or the uncrossing price. If order type is limit use the price
// the user has input
let price;
if (order.type === Schema.OrderType.TYPE_LIMIT && order.price) {
price = removeDecimal(order.price, market.decimalPlaces);
} else {
if (isMarketInAuction(market)) {
price = market.data.indicativePrice;
} else {
price = market.data.markPrice;
}
}
return price === '0' ? undefined : price;
};
+51
View File
@@ -0,0 +1,51 @@
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import { removeDecimal } from '@vegaprotocol/react-helpers';
import { Schema } from '@vegaprotocol/types';
import { isMarketInAuction } from './is-market-in-auction';
/**
* Get the market price based on market mode (auction or not auction)
*/
export const getMarketPrice = (market: MarketDealTicket) => {
if (isMarketInAuction(market)) {
// 0 can never be a valid uncrossing price
// as it would require there being orders on the book at that price.
if (
market.data?.indicativePrice &&
market.data.indicativePrice !== '0' &&
BigInt(market.data?.indicativePrice) !== BigInt(0)
) {
return market.data.indicativePrice;
}
} else {
return market.data.markPrice;
}
return undefined;
};
/**
* Gets the price for an order, order limit this is the user
* entered value, for market this will be the mark price or
* if in auction the indicative uncrossing price
*/
export const getDerivedPrice = (
order: {
type: Schema.OrderType;
price?: string | undefined;
},
market: MarketDealTicket
) => {
// If order type is market we should use either the mark price
// or the uncrossing price. If order type is limit use the price
// the user has input
// Use the market price if order is a market order
let price;
if (order.type === Schema.OrderType.TYPE_LIMIT && order.price) {
price = removeDecimal(order.price, market.decimalPlaces);
} else {
price = getMarketPrice(market);
}
return price === '0' ? undefined : price;
};
+6 -1
View File
@@ -29,7 +29,12 @@ export const FillsManager = ({ partyId }: FillsManagerProps) => {
};
return (
<AsyncRenderer loading={loading} error={error} data={data}>
<AsyncRenderer
loading={loading}
error={error}
data={data}
noDataCondition={() => false}
>
<FillsTable
ref={gridRef}
partyId={partyId}
@@ -0,0 +1,35 @@
import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/react-helpers';
import { Schema } from '@vegaprotocol/types';
import { ExternalLink, Intent, Notification } from '@vegaprotocol/ui-toolkit';
import { useUpdateProposal } from '../lib';
type AssetProposalNotificationProps = {
assetId?: string;
};
export const AssetProposalNotification = ({
assetId,
}: AssetProposalNotificationProps) => {
const tokenLink = useLinks(DApp.Token);
const { data: proposal } = useUpdateProposal({
id: assetId,
proposalType: Schema.ProposalType.TYPE_UPDATE_ASSET,
});
if (proposal) {
const proposalLink = tokenLink(
TOKEN_PROPOSAL.replace(':id', proposal.id || '')
);
return (
<Notification
intent={Intent.Warning}
message={t('Changes have been proposed for this asset')}
testId="asset-proposal-notification"
>
<ExternalLink href={proposalLink}>{t('View proposal')}</ExternalLink>
</Notification>
);
}
return null;
};
+2
View File
@@ -0,0 +1,2 @@
export * from './asset-proposal-notification';
export * from './market-proposal-notification';
@@ -0,0 +1,35 @@
import { t } from '@vegaprotocol/react-helpers';
import { Schema } from '@vegaprotocol/types';
import { ExternalLink, Intent, Notification } from '@vegaprotocol/ui-toolkit';
import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment';
import { useUpdateProposal } from '../lib';
type MarketProposalNotificationProps = {
marketId?: string;
};
export const MarketProposalNotification = ({
marketId,
}: MarketProposalNotificationProps) => {
const tokenLink = useLinks(DApp.Token);
const { data: proposal } = useUpdateProposal({
id: marketId,
proposalType: Schema.ProposalType.TYPE_UPDATE_MARKET,
});
if (proposal) {
const proposalLink = tokenLink(
TOKEN_PROPOSAL.replace(':id', proposal.id || '')
);
return (
<Notification
intent={Intent.Warning}
message={t('Changes have been proposed for this market')}
testId="market-proposal-notification"
>
<ExternalLink href={proposalLink}>{t('View proposal')}</ExternalLink>
</Notification>
);
}
return null;
};
+1
View File
@@ -1,2 +1,3 @@
export * from './lib';
export * from './utils';
export * from './components';
@@ -12,6 +12,63 @@ fragment NewMarketFields on NewMarket {
}
}
fragment UpdateMarketFields on UpdateMarket {
marketId
updateMarketConfiguration {
instrument {
code
product {
quoteName
}
}
priceMonitoringParameters {
triggers {
horizonSecs
probability
auctionExtensionSecs
}
}
liquidityMonitoringParameters {
targetStakeParameters {
timeWindow
scalingFactor
}
triggeringRatio
}
riskParameters {
__typename
... on UpdateMarketSimpleRiskModel {
simple {
factorLong
factorShort
}
}
... on UpdateMarketLogNormalRiskModel {
logNormal {
riskAversionParameter
tau
params {
mu
r
sigma
}
}
}
}
}
}
fragment UpdateAssetFields on UpdateAsset {
assetId
quantum
source {
... on UpdateERC20 {
lifetimeLimit
withdrawThreshold
}
}
}
fragment ProposalListFields on Proposal {
id
reference
@@ -36,6 +93,12 @@ fragment ProposalListFields on Proposal {
... on NewMarket {
...NewMarketFields
}
... on UpdateMarket {
...UpdateMarketFields
}
... on UpdateAsset {
...UpdateAssetFields
}
}
}
}
@@ -5,7 +5,11 @@ import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type NewMarketFieldsFragment = { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', code: string, name: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', id: string, name: string, symbol: string } } | null } };
export type ProposalListFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalWeight: string } }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', code: string, name: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', id: string, name: string, symbol: string } } | null } } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateNetworkParameter' } } };
export type UpdateMarketFieldsFragment = { __typename?: 'UpdateMarket', marketId: string, updateMarketConfiguration: { __typename?: 'UpdateMarketConfiguration', instrument: { __typename?: 'UpdateInstrumentConfiguration', code: string, product: { __typename?: 'UpdateFutureProduct', quoteName: string } }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: number, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, riskParameters: { __typename: 'UpdateMarketLogNormalRiskModel', logNormal?: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', mu: number, r: number, sigma: number } } | null } | { __typename: 'UpdateMarketSimpleRiskModel', simple?: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } | null } } };
export type UpdateAssetFieldsFragment = { __typename?: 'UpdateAsset', assetId: string, quantum: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } };
export type ProposalListFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalWeight: string } }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', code: string, name: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', id: string, name: string, symbol: string } } | null } } | { __typename?: 'UpdateAsset', assetId: string, quantum: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string, updateMarketConfiguration: { __typename?: 'UpdateMarketConfiguration', instrument: { __typename?: 'UpdateInstrumentConfiguration', code: string, product: { __typename?: 'UpdateFutureProduct', quoteName: string } }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: number, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, riskParameters: { __typename: 'UpdateMarketLogNormalRiskModel', logNormal?: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', mu: number, r: number, sigma: number } } | null } | { __typename: 'UpdateMarketSimpleRiskModel', simple?: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } | null } } } | { __typename?: 'UpdateNetworkParameter' } } };
export type ProposalsListQueryVariables = Types.Exact<{
proposalType?: Types.InputMaybe<Types.ProposalType>;
@@ -13,7 +17,7 @@ export type ProposalsListQueryVariables = Types.Exact<{
}>;
export type ProposalsListQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalWeight: string } }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', code: string, name: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', id: string, name: string, symbol: string } } | null } } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateNetworkParameter' } } } } | null> | null } | null };
export type ProposalsListQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalWeight: string } }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', code: string, name: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', id: string, name: string, symbol: string } } | null } } | { __typename?: 'UpdateAsset', assetId: string, quantum: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string, updateMarketConfiguration: { __typename?: 'UpdateMarketConfiguration', instrument: { __typename?: 'UpdateInstrumentConfiguration', code: string, product: { __typename?: 'UpdateFutureProduct', quoteName: string } }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: number, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, riskParameters: { __typename: 'UpdateMarketLogNormalRiskModel', logNormal?: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', mu: number, r: number, sigma: number } } | null } | { __typename: 'UpdateMarketSimpleRiskModel', simple?: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } | null } } } | { __typename?: 'UpdateNetworkParameter' } } } } | null> | null } | null };
export const NewMarketFieldsFragmentDoc = gql`
fragment NewMarketFields on NewMarket {
@@ -30,6 +34,65 @@ export const NewMarketFieldsFragmentDoc = gql`
}
}
`;
export const UpdateMarketFieldsFragmentDoc = gql`
fragment UpdateMarketFields on UpdateMarket {
marketId
updateMarketConfiguration {
instrument {
code
product {
quoteName
}
}
priceMonitoringParameters {
triggers {
horizonSecs
probability
auctionExtensionSecs
}
}
liquidityMonitoringParameters {
targetStakeParameters {
timeWindow
scalingFactor
}
triggeringRatio
}
riskParameters {
__typename
... on UpdateMarketSimpleRiskModel {
simple {
factorLong
factorShort
}
}
... on UpdateMarketLogNormalRiskModel {
logNormal {
riskAversionParameter
tau
params {
mu
r
sigma
}
}
}
}
}
}
`;
export const UpdateAssetFieldsFragmentDoc = gql`
fragment UpdateAssetFields on UpdateAsset {
assetId
quantum
source {
... on UpdateERC20 {
lifetimeLimit
withdrawThreshold
}
}
}
`;
export const ProposalListFieldsFragmentDoc = gql`
fragment ProposalListFields on Proposal {
id
@@ -55,10 +118,18 @@ export const ProposalListFieldsFragmentDoc = gql`
... on NewMarket {
...NewMarketFields
}
... on UpdateMarket {
...UpdateMarketFields
}
... on UpdateAsset {
...UpdateAssetFields
}
}
}
}
${NewMarketFieldsFragmentDoc}`;
${NewMarketFieldsFragmentDoc}
${UpdateMarketFieldsFragmentDoc}
${UpdateAssetFieldsFragmentDoc}`;
export const ProposalsListDocument = gql`
query ProposalsList($proposalType: ProposalType, $inState: ProposalState) {
proposalsConnection(proposalType: $proposalType, inState: $inState) {
@@ -1,3 +1,4 @@
export * from './__generated__/Proposal';
export * from './use-proposal-event';
export * from './use-proposal-submit';
export * from './use-update-proposal';
@@ -0,0 +1,319 @@
/* eslint-disable jest/no-conditional-expect */
import { renderHook } from '@testing-library/react';
import { Schema } from '@vegaprotocol/types';
import type {
ProposalListFieldsFragment,
UpdateAssetFieldsFragment,
UpdateMarketFieldsFragment,
} from '../proposals-data-provider';
import {
isChangeProposed,
UpdateAssetFields,
UpdateMarketFields,
useUpdateProposal,
} from './use-update-proposal';
const generateUpdateAssetProposal = (
id: string,
quantum = '',
lifetimeLimit = '',
withdrawThreshold = ''
): ProposalListFieldsFragment => ({
reference: '',
state: Schema.ProposalState.STATE_OPEN,
datetime: '',
votes: {
__typename: undefined,
yes: {
__typename: undefined,
totalTokens: '',
totalNumber: '',
totalWeight: '',
},
no: {
__typename: undefined,
totalTokens: '',
totalNumber: '',
totalWeight: '',
},
},
terms: {
__typename: 'ProposalTerms',
closingDatetime: '',
enactmentDatetime: undefined,
change: {
__typename: 'UpdateAsset',
assetId: id,
quantum,
source: {
__typename: 'UpdateERC20',
lifetimeLimit,
withdrawThreshold,
},
},
},
});
type RiskParameters =
| {
__typename: 'UpdateMarketLogNormalRiskModel';
logNormal?: {
__typename?: 'LogNormalRiskModel';
riskAversionParameter: number;
tau: number;
params: {
__typename?: 'LogNormalModelParams';
mu: number;
r: number;
sigma: number;
};
} | null;
}
| {
__typename: 'UpdateMarketSimpleRiskModel';
simple?: {
__typename?: 'SimpleRiskModelParams';
factorLong: number;
factorShort: number;
} | null;
};
const generateRiskParameters = (
type:
| 'UpdateMarketLogNormalRiskModel'
| 'UpdateMarketSimpleRiskModel' = 'UpdateMarketLogNormalRiskModel'
): RiskParameters => {
if (type === 'UpdateMarketSimpleRiskModel')
return {
__typename: 'UpdateMarketSimpleRiskModel',
simple: {
__typename: 'SimpleRiskModelParams',
factorLong: 0,
factorShort: 0,
},
};
return {
__typename: 'UpdateMarketLogNormalRiskModel',
logNormal: {
__typename: 'LogNormalRiskModel',
params: {
__typename: 'LogNormalModelParams',
mu: 0,
r: 0,
sigma: 0,
},
riskAversionParameter: 0,
tau: 0,
},
};
};
const generateUpdateMarketProposal = (
id: string,
code = '',
quoteName = '',
priceMonitoring = false,
liquidityMonitoring = false,
riskParameters = false,
riskParametersType:
| 'UpdateMarketLogNormalRiskModel'
| 'UpdateMarketSimpleRiskModel' = 'UpdateMarketLogNormalRiskModel'
): ProposalListFieldsFragment => ({
reference: '',
state: Schema.ProposalState.STATE_OPEN,
datetime: '',
votes: {
__typename: undefined,
yes: {
__typename: undefined,
totalTokens: '',
totalNumber: '',
totalWeight: '',
},
no: {
__typename: undefined,
totalTokens: '',
totalNumber: '',
totalWeight: '',
},
},
terms: {
__typename: 'ProposalTerms',
closingDatetime: '',
enactmentDatetime: undefined,
change: {
__typename: 'UpdateMarket',
marketId: id,
updateMarketConfiguration: {
__typename: undefined,
instrument: {
__typename:
code.length > 0 || quoteName.length > 0
? 'UpdateInstrumentConfiguration'
: undefined,
code,
product: {
__typename:
quoteName.length > 0 ? 'UpdateFutureProduct' : undefined,
quoteName,
},
},
priceMonitoringParameters: {
__typename: priceMonitoring ? 'PriceMonitoringParameters' : undefined,
triggers: priceMonitoring
? [
{
auctionExtensionSecs: 1,
horizonSecs: 2,
probability: 3,
__typename: 'PriceMonitoringTrigger',
},
]
: [],
},
liquidityMonitoringParameters: {
__typename: liquidityMonitoring
? 'LiquidityMonitoringParameters'
: undefined,
triggeringRatio: 0,
targetStakeParameters: {
__typename: undefined,
scalingFactor: 0,
timeWindow: 0,
},
},
riskParameters: riskParameters
? generateRiskParameters(riskParametersType)
: {
__typename: riskParametersType,
},
},
},
},
});
const mockDataProviderData: {
data: ProposalListFieldsFragment[];
error: Error | undefined;
loading: boolean;
} = {
data: [
generateUpdateMarketProposal('123'),
generateUpdateAssetProposal('456'),
],
error: undefined,
loading: false,
};
const mockDataProvider = jest.fn(() => {
return mockDataProviderData;
});
jest.mock('@vegaprotocol/react-helpers', () => ({
...jest.requireActual('@vegaprotocol/react-helpers'),
useDataProvider: jest.fn((args) => mockDataProvider()),
}));
describe('useUpdateProposal', () => {
it('returns update proposal for a given asset', () => {
const { result } = renderHook(() =>
useUpdateProposal({
id: '456',
proposalType: Schema.ProposalType.TYPE_UPDATE_ASSET,
})
);
const change = result.current.data?.terms
.change as UpdateAssetFieldsFragment;
expect(change.__typename).toEqual('UpdateAsset');
expect(change.assetId).toEqual('456');
});
it('returns update proposal for a given market', () => {
const { result } = renderHook(() =>
useUpdateProposal({
id: '123',
proposalType: Schema.ProposalType.TYPE_UPDATE_MARKET,
})
);
const change = result.current.data?.terms
.change as UpdateMarketFieldsFragment;
expect(change.__typename).toEqual('UpdateMarket');
expect(change.marketId).toEqual('123');
});
it('does not return a proposal if not found', () => {
const { result } = renderHook(() =>
useUpdateProposal({
id: '789',
proposalType: Schema.ProposalType.TYPE_UPDATE_MARKET,
})
);
expect(result.current.data).toBeFalsy();
});
});
describe('isChangeProposed', () => {
it('returns false if a change for the specified asset field is not proposed', () => {
const proposal = generateUpdateAssetProposal('123');
expect(isChangeProposed(proposal, UpdateAssetFields.Quantum)).toBeFalsy();
expect(
isChangeProposed(proposal, UpdateAssetFields.LifetimeLimit)
).toBeFalsy();
expect(
isChangeProposed(proposal, UpdateAssetFields.WithdrawThreshold)
).toBeFalsy();
});
it('returns true if a change for the specified asset field is proposed', () => {
const proposal = generateUpdateAssetProposal('123', '100', '100', '100');
expect(isChangeProposed(proposal, UpdateAssetFields.Quantum)).toBeTruthy();
expect(
isChangeProposed(proposal, UpdateAssetFields.LifetimeLimit)
).toBeTruthy();
expect(
isChangeProposed(proposal, UpdateAssetFields.WithdrawThreshold)
).toBeTruthy();
});
it('returns false if a change for the specified market field is not proposed', () => {
const proposal = generateUpdateMarketProposal('123');
expect(isChangeProposed(proposal, UpdateMarketFields.Code)).toBeFalsy();
expect(
isChangeProposed(proposal, UpdateMarketFields.QuoteName)
).toBeFalsy();
expect(
isChangeProposed(proposal, UpdateMarketFields.PriceMonitoring)
).toBeFalsy();
expect(
isChangeProposed(proposal, UpdateMarketFields.LiquidityMonitoring)
).toBeFalsy();
expect(
isChangeProposed(proposal, UpdateMarketFields.RiskParameters)
).toBeFalsy();
});
it('returns true if a change for the specified market field is proposed', () => {
const proposal = generateUpdateMarketProposal(
'123',
'ABCDEF',
'qABCDEFq',
true,
true,
true
);
expect(isChangeProposed(proposal, UpdateMarketFields.Code)).toBeFalsy();
expect(
isChangeProposed(proposal, UpdateMarketFields.QuoteName)
).toBeFalsy();
expect(
isChangeProposed(proposal, UpdateMarketFields.PriceMonitoring)
).toBeFalsy();
expect(
isChangeProposed(proposal, UpdateMarketFields.LiquidityMonitoring)
).toBeFalsy();
expect(
isChangeProposed(proposal, UpdateMarketFields.RiskParameters)
).toBeFalsy();
});
});
@@ -0,0 +1,203 @@
import { proposalsListDataProvider } from '..';
import { Schema } from '@vegaprotocol/types';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { useMemo } from 'react';
import first from 'lodash/first';
import type { ProposalListFieldsFragment } from '..';
type UseUpdateProposalProps = {
id?: string;
proposalType:
| Schema.ProposalType.TYPE_UPDATE_ASSET
| Schema.ProposalType.TYPE_UPDATE_MARKET;
};
type UseUpdateProposal = {
data: ProposalListFieldsFragment | undefined;
loading: boolean;
error: Error | undefined;
};
const changeCondition = {
[Schema.ProposalType.TYPE_UPDATE_ASSET]: (
id: string,
change: ProposalListFieldsFragment['terms']['change']
) => change.__typename === 'UpdateAsset' && change.assetId === id,
[Schema.ProposalType.TYPE_UPDATE_MARKET]: (
id: string,
change: ProposalListFieldsFragment['terms']['change']
) => change.__typename === 'UpdateMarket' && change.marketId === id,
};
export const useUpdateProposal = ({
id,
proposalType,
}: UseUpdateProposalProps): UseUpdateProposal => {
const variables = useMemo(
() => ({
proposalType,
skipUpdates: true,
}),
[proposalType]
);
const { data, loading, error } = useDataProvider({
dataProvider: proposalsListDataProvider,
variables,
});
const proposal = id
? first(
(data || []).filter(
(proposal) =>
[
Schema.ProposalState.STATE_OPEN,
Schema.ProposalState.STATE_PASSED,
Schema.ProposalState.STATE_WAITING_FOR_NODE_VOTE,
].includes(proposal.state) &&
changeCondition[proposalType](id, proposal.terms.change)
)
)
: undefined;
return { data: proposal, loading, error };
};
export enum UpdateMarketFields {
Code,
QuoteName,
PriceMonitoring,
LiquidityMonitoring,
RiskParameters,
}
export enum UpdateAssetFields {
Quantum,
LifetimeLimit,
WithdrawThreshold,
}
export type UpdateProposalField = UpdateAssetFields | UpdateMarketFields;
const fieldGetters = {
[UpdateMarketFields.Code]: (
change: ProposalListFieldsFragment['terms']['change']
) => {
if (change.__typename === 'UpdateMarket') {
const proposed =
change.updateMarketConfiguration.__typename !== undefined &&
change.updateMarketConfiguration.instrument.__typename !== undefined;
return (
proposed && change.updateMarketConfiguration.instrument.code.length > 0
);
}
return false;
},
[UpdateMarketFields.QuoteName]: (
change: ProposalListFieldsFragment['terms']['change']
) => {
if (change.__typename === 'UpdateMarket') {
const proposed =
change.updateMarketConfiguration.__typename !== undefined &&
change.updateMarketConfiguration.instrument.__typename !== undefined &&
change.updateMarketConfiguration.instrument.product.__typename !==
undefined;
return (
proposed &&
change.updateMarketConfiguration.instrument.product.quoteName.length > 0
);
}
return false;
},
[UpdateMarketFields.PriceMonitoring]: (
change: ProposalListFieldsFragment['terms']['change']
) => {
if (change.__typename === 'UpdateMarket') {
const proposed =
change.updateMarketConfiguration.__typename !== undefined &&
change.updateMarketConfiguration.priceMonitoringParameters
.__typename !== undefined &&
change.updateMarketConfiguration.priceMonitoringParameters.triggers
?.length;
return proposed;
}
return false;
},
[UpdateMarketFields.LiquidityMonitoring]: (
change: ProposalListFieldsFragment['terms']['change']
) => {
if (change.__typename === 'UpdateMarket') {
const proposed =
change.updateMarketConfiguration.__typename !== undefined &&
change.updateMarketConfiguration.liquidityMonitoringParameters
.__typename !== undefined;
return proposed;
}
return false;
},
[UpdateMarketFields.RiskParameters]: (
change: ProposalListFieldsFragment['terms']['change']
) => {
if (change.__typename === 'UpdateMarket') {
const proposed =
change.updateMarketConfiguration.__typename !== undefined &&
change.updateMarketConfiguration.riskParameters.__typename !==
undefined;
const log =
change.updateMarketConfiguration.riskParameters.__typename ===
'UpdateMarketLogNormalRiskModel' &&
change.updateMarketConfiguration.riskParameters.logNormal !== undefined;
const simple =
change.updateMarketConfiguration.riskParameters.__typename ===
'UpdateMarketSimpleRiskModel' &&
change.updateMarketConfiguration.riskParameters.simple !== undefined;
return proposed && (log || simple);
}
return false;
},
[UpdateAssetFields.Quantum]: (
change: ProposalListFieldsFragment['terms']['change']
) => {
if (change.__typename === 'UpdateAsset') {
const proposed = change.quantum.length > 0;
return proposed;
}
return false;
},
[UpdateAssetFields.LifetimeLimit]: (
change: ProposalListFieldsFragment['terms']['change']
) => {
if (change.__typename === 'UpdateAsset') {
const proposed =
change.source.__typename === 'UpdateERC20' &&
change.source.lifetimeLimit.length > 0;
return proposed;
}
return false;
},
[UpdateAssetFields.WithdrawThreshold]: (
change: ProposalListFieldsFragment['terms']['change']
) => {
if (change.__typename === 'UpdateAsset') {
const proposed =
change.source.__typename === 'UpdateERC20' &&
change.source.withdrawThreshold.length > 0;
return proposed;
}
return false;
},
};
export const isChangeProposed = (
proposal: ProposalListFieldsFragment | undefined,
field: UpdateProposalField
) => {
if (proposal) {
return (
(proposal.terms.change.__typename === 'UpdateAsset' ||
proposal.terms.change.__typename === 'UpdateMarket') &&
fieldGetters[field](proposal.terms.change)
);
}
return false;
};
+1
View File
@@ -1,2 +1,3 @@
export * from './lib/ledger-container';
export * from './lib/ledger-manager';
export * from './lib/__generated__/LedgerEntries';
+18 -10
View File
@@ -1,26 +1,34 @@
fragment LedgerEntry on AggregatedLedgerEntries {
fragment LedgerEntry on AggregatedLedgerEntry {
vegaTime
quantity
partyId
assetId
marketId
accountType
transferType
receiverAccountType
receiverMarketId
receiverPartyId
senderAccountType
senderMarketId
senderPartyId
}
query LedgerEntries($partyId: ID!) {
query LedgerEntries($partyId: ID!, $pagination: Pagination) {
ledgerEntries(
filter: { AccountFromFilter: { partyIds: [$partyId] } }
groupOptions: {
ByAccountField: [PartyId, AccountType, AssetId, MarketId]
ByLedgerEntryField: [TransferType]
filter: {
SenderAccountFilter: { partyIds: [$partyId] }
ReceiverAccountFilter: { partyIds: [$partyId] }
}
pagination: { first: 500 }
pagination: $pagination
) {
edges {
node {
...LedgerEntry
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
+20 -10
View File
@@ -3,38 +3,47 @@ import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type LedgerEntryFragment = { __typename?: 'AggregatedLedgerEntries', vegaTime: string, quantity: string, partyId?: string | null, assetId?: string | null, marketId?: string | null, accountType?: Types.AccountType | null, transferType?: string | null };
export type LedgerEntryFragment = { __typename?: 'AggregatedLedgerEntry', vegaTime: any, quantity: string, assetId?: string | null, transferType?: Types.TransferType | null, receiverAccountType?: Types.AccountType | null, receiverMarketId?: string | null, receiverPartyId?: string | null, senderAccountType?: Types.AccountType | null, senderMarketId?: string | null, senderPartyId?: string | null };
export type LedgerEntriesQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
pagination?: Types.InputMaybe<Types.Pagination>;
}>;
export type LedgerEntriesQuery = { __typename?: 'Query', ledgerEntries: { __typename?: 'AggregatedLedgerEntriesConnection', edges: Array<{ __typename?: 'AggregatedLedgerEntriesEdge', node: { __typename?: 'AggregatedLedgerEntries', vegaTime: string, quantity: string, partyId?: string | null, assetId?: string | null, marketId?: string | null, accountType?: Types.AccountType | null, transferType?: string | null } } | null> } };
export type LedgerEntriesQuery = { __typename?: 'Query', ledgerEntries: { __typename?: 'AggregatedLedgerEntriesConnection', edges: Array<{ __typename?: 'AggregatedLedgerEntriesEdge', node: { __typename?: 'AggregatedLedgerEntry', vegaTime: any, quantity: string, assetId?: string | null, transferType?: Types.TransferType | null, receiverAccountType?: Types.AccountType | null, receiverMarketId?: string | null, receiverPartyId?: string | null, senderAccountType?: Types.AccountType | null, senderMarketId?: string | null, senderPartyId?: string | null } } | null>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } };
export const LedgerEntryFragmentDoc = gql`
fragment LedgerEntry on AggregatedLedgerEntries {
fragment LedgerEntry on AggregatedLedgerEntry {
vegaTime
quantity
partyId
assetId
marketId
accountType
transferType
receiverAccountType
receiverMarketId
receiverPartyId
senderAccountType
senderMarketId
senderPartyId
}
`;
export const LedgerEntriesDocument = gql`
query LedgerEntries($partyId: ID!) {
query LedgerEntries($partyId: ID!, $pagination: Pagination) {
ledgerEntries(
filter: {AccountFromFilter: {partyIds: [$partyId]}}
groupOptions: {ByAccountField: [PartyId, AccountType, AssetId, MarketId], ByLedgerEntryField: [TransferType]}
pagination: {first: 500}
filter: {SenderAccountFilter: {partyIds: [$partyId]}, ReceiverAccountFilter: {partyIds: [$partyId]}}
pagination: $pagination
) {
edges {
node {
...LedgerEntry
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
${LedgerEntryFragmentDoc}`;
@@ -52,6 +61,7 @@ export const LedgerEntriesDocument = gql`
* const { data, loading, error } = useLedgerEntriesQuery({
* variables: {
* partyId: // value for 'partyId'
* pagination: // value for 'pagination'
* },
* });
*/
@@ -2,7 +2,9 @@ import type { Asset } from '@vegaprotocol/assets';
import { assetsProvider } from '@vegaprotocol/assets';
import type { Market } from '@vegaprotocol/market-list';
import { marketsProvider } from '@vegaprotocol/market-list';
import type { PageInfo } from '@vegaprotocol/react-helpers';
import {
defaultAppend as append,
makeDataProvider,
makeDerivedDataProvider,
useDataProvider,
@@ -17,20 +19,36 @@ import { LedgerEntriesDocument } from './__generated__/LedgerEntries';
export type LedgerEntry = LedgerEntryFragment & {
id: number;
asset: Asset | null | undefined;
market: Market | null | undefined;
marketSender: Market | null | undefined;
marketReceiver: Market | null | undefined;
};
const getData = (responseData: LedgerEntriesQuery): LedgerEntry[] =>
responseData.ledgerEntries?.edges
?.filter((e) => Boolean(e?.node))
.map((e, i) => ({ id: i, ...e?.node } as LedgerEntry)) ?? [];
const getData = (responseData: LedgerEntriesQuery): LedgerEntry[] => {
console.log('responseData', responseData);
return (
responseData.ledgerEntries?.edges
?.filter((e) => Boolean(e?.node))
.map((e, i) => ({ id: i, ...e?.node } as LedgerEntry)) ?? []
);
};
const getPageInfo = (responseData: LedgerEntriesQuery): PageInfo | null =>
responseData.ledgerEntries?.pageInfo || null;
const ledgerEntriesOnlyProvider = makeDataProvider<
LedgerEntriesQuery,
LedgerEntry[] | null,
never,
never
>({ query: LedgerEntriesDocument, getData });
>({
query: LedgerEntriesDocument,
getData,
pagination: {
getPageInfo,
append,
first: 100,
},
});
export const ledgerEntriesProvider = makeDerivedDataProvider<
LedgerEntry[],
@@ -40,10 +58,13 @@ export const ledgerEntriesProvider = makeDerivedDataProvider<
([entries, assets, markets]): LedgerEntry[] =>
entries.map((entry: LedgerEntry) => {
const asset = assets.find((asset: Asset) => asset.id === entry.assetId);
const market = markets.find(
(market: Market) => market.id === entry.marketId
const marketSender = markets.find(
(market: Market) => market.id === entry.senderMarketId
);
return { ...entry, asset, market };
const marketReceiver = markets.find(
(market: Market) => market.id === entry.receiverMarketId
);
return { ...entry, asset, marketSender, marketReceiver };
})
);
+1
View File
@@ -5,6 +5,7 @@ import { LedgerTable } from './ledger-table';
// '3ac37999796c2be3546e0c1d87daa8ec7e99d8c423969be44c2f63256c415004'
type LedgerManagerProps = { partyId: string };
export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
console.log('partyId', partyId);
const { data, error, loading } = useLedgerEntriesDataProvider(partyId);
return (
+71 -23
View File
@@ -3,11 +3,15 @@ import {
fromNanoSeconds,
getDateTimeFormat,
t,
truncateByChars,
} from '@vegaprotocol/react-helpers';
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
import type {
VegaValueFormatterParams,
VegaICellRendererParams,
} from '@vegaprotocol/ui-toolkit';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import { AgGridColumn } from 'ag-grid-react';
import type { Schema } from '@vegaprotocol/types';
import type { Schema as Types } from '@vegaprotocol/types';
import {
AccountTypeMapping,
DescriptionTransferTypeMapping,
@@ -18,7 +22,7 @@ import type { LedgerEntry } from './ledger-entries-data-provider';
export const TransferTooltipCellComponent = ({
value,
}: {
value: Schema.TransferType;
value: Types.TransferType;
}) => {
return (
<p className="max-w-sm bg-neutral-200 px-4 py-2 z-20 rounded text-sm break-word text-black">
@@ -27,11 +31,63 @@ export const TransferTooltipCellComponent = ({
);
};
type LedgerCellRendererProps = {
accountType?: Types.AccountType | null;
partyId?: string | null;
marketName?: string;
};
const LedgerCellRenderer = ({
accountType,
partyId,
marketName,
}: LedgerCellRendererProps) => {
return (
<div className="flex flex-col justify-around leading-5 h-full">
<div
className="flex"
title={`${t('ID')}: ${truncateByChars(partyId || '-')}`}
>
{truncateByChars(partyId || '')}
</div>
<div
className="flex"
title={`${t('Account type')}: ${
accountType ? AccountTypeMapping[accountType] : '-'
}`}
>
{accountType && AccountTypeMapping[accountType]}
</div>
<div className="flex" title={`${t('Market')}: ${marketName || '-'}`}>
{marketName}
</div>
</div>
);
};
const SenderCellRenderer = ({ data }: VegaICellRendererParams<LedgerEntry>) => {
const props = {
accountType: data?.senderAccountType,
partyId: data?.senderPartyId,
marketName: data?.marketSender?.tradableInstrument?.instrument?.code,
};
return <LedgerCellRenderer {...props} />;
};
const ReceiverCellRenderer = ({
data,
}: VegaICellRendererParams<LedgerEntry>) => {
const props = {
accountType: data?.receiverAccountType,
partyId: data?.receiverPartyId,
marketName: data?.marketReceiver?.tradableInstrument?.instrument?.code,
};
return <LedgerCellRenderer {...props} />;
};
export const LedgerTable = ({ ...props }) => (
<AgGrid
style={{ width: '100%', height: '100%' }}
overlayNoRowsTemplate={t('No entries')}
rowHeight={34}
rowHeight={70}
getRowId={({ data }) => data.id}
tooltipShowDelay={500}
defaultColDef={{
@@ -43,13 +99,14 @@ export const LedgerTable = ({ ...props }) => (
{...props}
>
<AgGridColumn
headerName={t('Account Type')}
field="accountType"
valueFormatter={({
value,
}: VegaValueFormatterParams<LedgerEntry, 'accountType'>) =>
value ? AccountTypeMapping[value] : ''
}
headerName={t('Sender')}
field="senderAccountType"
cellRenderer={SenderCellRenderer}
/>
<AgGridColumn
headerName={t('Receiver')}
field="receiverAccountType"
cellRenderer={ReceiverCellRenderer}
/>
<AgGridColumn
headerName={t('Transfer Type')}
@@ -70,7 +127,7 @@ export const LedgerTable = ({ ...props }) => (
value,
data,
}: VegaValueFormatterParams<LedgerEntry, 'quantity'>) => {
const marketDecimalPlaces = data?.market?.decimalPlaces;
const marketDecimalPlaces = data?.marketSender?.decimalPlaces;
const assetDecimalPlaces = data?.asset?.decimals || 0;
return value
? addDecimalsFormatNumber(
@@ -91,20 +148,11 @@ export const LedgerTable = ({ ...props }) => (
data?.asset?.symbol || value
}
/>
<AgGridColumn
headerName={t('Market')}
field="marketId"
valueFormatter={({
data,
}: VegaValueFormatterParams<LedgerEntry, 'market'>) =>
data?.market?.tradableInstrument.instrument.code || '-'
}
/>
<AgGridColumn
headerName={t('Vega Time')}
field="vegaTime"
valueFormatter={({ value }: { value: string }) =>
getDateTimeFormat().format(fromNanoSeconds(value))
valueFormatter={({ value }: { value?: string }) =>
value ? getDateTimeFormat().format(fromNanoSeconds(value)) : '-'
}
filter="agDateColumnFilter"
filterParams={{
+3 -3
View File
@@ -10,14 +10,14 @@ export type MarketLpQueryVariables = Types.Exact<{
export type MarketLpQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', code: string, name: string, product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', id: string, symbol: string, decimals: number } } } }, data?: { __typename?: 'MarketData', marketTradingMode: Types.MarketTradingMode, suppliedStake?: string | null, openInterest: string, targetStake?: string | null, trigger: Types.AuctionTrigger, marketValueProxy: string, market: { __typename?: 'Market', id: string } } | null } | null };
export type LiquidityProvisionFieldsFragment = { __typename?: 'LiquidityProvision', createdAt: string, updatedAt?: string | null, commitmentAmount: string, fee: string, status: Types.LiquidityProvisionStatus, party: { __typename?: 'Party', id: string, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string } } | null> | null } | null } };
export type LiquidityProvisionFieldsFragment = { __typename?: 'LiquidityProvision', createdAt: any, updatedAt?: any | null, commitmentAmount: string, fee: string, status: Types.LiquidityProvisionStatus, party: { __typename?: 'Party', id: string, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string } } | null> | null } | null } };
export type LiquidityProvisionsQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
}>;
export type LiquidityProvisionsQuery = { __typename?: 'Query', market?: { __typename?: 'Market', liquidityProvisionsConnection?: { __typename?: 'LiquidityProvisionsConnection', edges?: Array<{ __typename?: 'LiquidityProvisionsEdge', node: { __typename?: 'LiquidityProvision', createdAt: string, updatedAt?: string | null, commitmentAmount: string, fee: string, status: Types.LiquidityProvisionStatus, party: { __typename?: 'Party', id: string, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string } } | null> | null } | null } } } | null> | null } | null } | null };
export type LiquidityProvisionsQuery = { __typename?: 'Query', market?: { __typename?: 'Market', liquidityProvisionsConnection?: { __typename?: 'LiquidityProvisionsConnection', edges?: Array<{ __typename?: 'LiquidityProvisionsEdge', node: { __typename?: 'LiquidityProvision', createdAt: any, updatedAt?: any | null, commitmentAmount: string, fee: string, status: Types.LiquidityProvisionStatus, party: { __typename?: 'Party', id: string, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string } } | null> | null } | null } } } | null> | null } | null } | null };
export type LiquidityProvisionsUpdateSubscriptionVariables = Types.Exact<{
partyId?: Types.InputMaybe<Types.Scalars['ID']>;
@@ -25,7 +25,7 @@ export type LiquidityProvisionsUpdateSubscriptionVariables = Types.Exact<{
}>;
export type LiquidityProvisionsUpdateSubscription = { __typename?: 'Subscription', liquidityProvisions?: Array<{ __typename?: 'LiquidityProvisionUpdate', id?: string | null, partyID: string, createdAt: string, updatedAt?: string | null, marketID: string, commitmentAmount: string, fee: string, status: Types.LiquidityProvisionStatus }> | null };
export type LiquidityProvisionsUpdateSubscription = { __typename?: 'Subscription', liquidityProvisions?: Array<{ __typename?: 'LiquidityProvisionUpdate', id?: string | null, partyID: string, createdAt: any, updatedAt?: any | null, marketID: string, commitmentAmount: string, fee: string, status: Types.LiquidityProvisionStatus }> | null };
export type LiquidityProviderFeeShareFieldsFragment = { __typename?: 'LiquidityProviderFeeShare', equityLikeShare: string, averageEntryValuation: string, party: { __typename?: 'Party', id: string } };
@@ -189,6 +189,11 @@ export const getLiquidityProvision = (
const market = marketLiquidity?.market;
const feeShare = liquidityFeeShare.find((f) => f.party.id === lp.party.id);
if (!feeShare) return lp;
const bondAccounts = accounts?.filter(
(a) =>
a?.type === Schema.AccountType.ACCOUNT_TYPE_BOND &&
(!a.party?.id || a.party?.id === lp.party.id)
);
const lpData: LiquidityProvisionData = {
...lp,
averageEntryValuation: feeShare?.averageEntryValuation,
@@ -196,8 +201,7 @@ export const getLiquidityProvision = (
assetDecimalPlaces:
market?.tradableInstrument.instrument.product.settlementAsset.decimals,
balance:
accounts
?.filter((a) => a?.type === Schema.AccountType.ACCOUNT_TYPE_BOND)
bondAccounts
?.reduce(
(acc, a) => acc.plus(new BigNumber(a.balance ?? 0)),
new BigNumber(0)
@@ -31,6 +31,7 @@ import { marketInfoDataProvider } from './market-info-data-provider';
import { TokenLinks } from '@vegaprotocol/react-helpers';
import type { MarketInfoQuery } from './__generated___/MarketInfo';
import { MarketProposalNotification } from '@vegaprotocol/governance';
export interface InfoProps {
market: MarketInfoQuery['market'];
@@ -405,6 +406,7 @@ export const Info = ({ market, onSelect }: InfoProps) => {
<Accordion panels={marketDataPanels} />
</div>
<div className="mb-8">
<MarketProposalNotification marketId={market.id} />
<p className={headerClassName}>{t('Market specification')}</p>
<Accordion panels={marketSpecPanels} />
</div>
+7 -1
View File
@@ -25,7 +25,13 @@ export const PositionsManager = ({ partyId }: PositionsManagerProps) => {
return (
<>
<AsyncRenderer loading={loading} error={error} data={data}>
<AsyncRenderer
loading={loading}
error={error}
data={data}
noDataMessage={t('No positions')}
noDataCondition={(data) => !(data && data.length)}
>
<PositionsTable
ref={gridRef}
rowData={data}
@@ -0,0 +1,138 @@
import type { AgGridReact } from 'ag-grid-react';
import { MockedProvider } from '@apollo/client/testing';
import { renderHook, waitFor } from '@testing-library/react';
import { usePositionsData } from './use-positions-data';
import type { Position } from './positions-data-providers';
let mockData: Position[] = [
{
marketName: 'M1',
marketId: 'market-0',
openVolume: '1',
},
{
marketName: 'M2',
marketId: 'market-1',
openVolume: '-1985',
},
{
marketName: 'M3',
marketId: 'market-2',
openVolume: '0',
},
{
marketName: 'M4',
marketId: 'market-3',
openVolume: '0',
},
{
marketName: 'M5',
marketId: 'market-4',
openVolume: '3',
},
] as Position[];
let mockDataProviderData = {
data: mockData,
error: undefined,
loading: false,
totalCount: undefined,
};
let updateMock: jest.Mock;
const mockDataProvider = jest.fn((args) => {
updateMock = args.update;
return mockDataProviderData;
});
jest.mock('@vegaprotocol/react-helpers', () => ({
...jest.requireActual('@vegaprotocol/react-helpers'),
useDataProvider: jest.fn((args) => mockDataProvider(args)),
}));
describe('usePositionData Hook', () => {
afterEach(() => {
jest.clearAllMocks();
});
const mockApplyTransactions = jest.fn();
const mockApplyTransactionsAsync = jest.fn();
const mockGetRowNode = jest
.fn()
.mockImplementation((id: string) =>
mockData.find((position) => position.marketId === id)
);
const partyId = 'partyId';
const aNewOne = {
marketId: 'market-5',
openVolume: '1',
};
const toRemoveOne = {
marketId: 'market-0',
openVolume: '0',
};
const anUpdatedOne = {
marketId: 'market-1',
openVolume: '1',
};
const gridRef = {
current: {
api: {
applyTransaction: mockApplyTransactions,
applyTransactionAsync: mockApplyTransactionsAsync,
getRowNode: mockGetRowNode,
},
} as unknown as AgGridReact,
};
it('should return proper data', async () => {
const { result } = renderHook(() => usePositionsData(partyId, gridRef), {
wrapper: MockedProvider,
});
expect(result.current.data?.length ?? 0).toEqual(3);
});
it('should append by sync', async () => {
renderHook(() => usePositionsData(partyId, gridRef), {
wrapper: MockedProvider,
});
await waitFor(() => {
updateMock({ delta: [aNewOne, toRemoveOne, anUpdatedOne] as Position[] });
});
expect(mockApplyTransactions).toHaveBeenCalledWith({
update: [anUpdatedOne],
add: [aNewOne],
remove: [toRemoveOne],
addIndex: 0,
});
});
it('should append by async', async () => {
renderHook(() => usePositionsData(partyId, gridRef), {
wrapper: MockedProvider,
});
await waitFor(() => {
updateMock({ delta: [anUpdatedOne] as Position[] });
});
expect(mockApplyTransactionsAsync).toHaveBeenCalledWith({
update: [anUpdatedOne],
add: [],
remove: [],
addIndex: 0,
});
});
it('no data should return null', () => {
mockData = [];
mockDataProviderData = {
...mockDataProviderData,
data: mockData,
loading: false,
};
const { result } = renderHook(() => usePositionsData(partyId, gridRef), {
wrapper: MockedProvider,
});
expect(result.current.data).toEqual([]);
});
});
+11 -5
View File
@@ -29,6 +29,7 @@ export const usePositionsData = (
const update: Position[] = [];
const add: Position[] = [];
const remove: Position[] = [];
if (!gridRef.current?.api) {
return false;
}
@@ -37,18 +38,23 @@ export const usePositionsData = (
getRowId({ data: position })
);
if (rowNode) {
update.push(position);
} else {
if (position.openVolume === '0') {
remove.push(position);
} else {
update.push(position);
}
} else if (position.openVolume !== '0') {
add.push(position);
}
});
if (update.length || add.length) {
if (update.length || add.length || remove.length) {
const rowDataTransaction = {
update,
add,
remove,
addIndex: 0,
};
if (add.length) {
if (add.length || remove.length) {
gridRef.current.api.applyTransaction(rowDataTransaction);
} else {
gridRef.current.api.applyTransactionAsync(rowDataTransaction);
@@ -64,7 +70,7 @@ export const usePositionsData = (
variables,
});
return {
data,
data: data?.filter((position) => position.openVolume !== '0'),
error,
loading,
};
@@ -136,7 +136,15 @@ export const useDataProvider = <
return unsubscribe();
};
}, [client, initialized, dataProvider, callback, variables, skip, update]);
return { data, loading, error, flush, reload, load, totalCount };
return {
data,
loading,
error,
flush,
reload,
load,
totalCount,
};
};
export const useThrottledDataProvider = <Data, Delta>(
+4 -3
View File
@@ -1,9 +1,10 @@
import { parseISO, isValid } from 'date-fns';
export const toNanoSeconds = (date: Date | string) => {
return new Date(date).getTime().toString() + '000000';
};
export const fromNanoSeconds = (ts: string) => {
if (typeof ts !== 'string') return new Date(0);
const validTs = ts.substring(0, ts.length - 6);
return new Date(Number(validTs));
const val = parseISO(ts);
return new Date(isValid(val) ? val : 0);
};
+117 -519
View File
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,7 @@
import { Splash } from '../splash';
import type { ReactNode } from 'react';
import { t } from '@vegaprotocol/react-helpers';
import { isNotFoundGraphQLError } from '@vegaprotocol/apollo-client';
interface AsyncRendererProps<T> {
loading: boolean;
@@ -25,7 +26,7 @@ export function AsyncRenderer<T = object>({
children,
render,
}: AsyncRendererProps<T>) {
if (error) {
if (error && !isNotFoundGraphQLError(error)) {
return (
<Splash>
{errorMessage
+1
View File
@@ -38,3 +38,4 @@ export * from './vega-icons';
export * from './vega-logo';
export * from './traffic-light';
export * from './toast';
export * from './notification';
@@ -0,0 +1 @@
export * from './notification';
@@ -0,0 +1,57 @@
import type { Meta, Story } from '@storybook/react';
import { Intent } from '../../utils/intent';
import { ExternalLink, Link } from '../link';
import { Notification } from './notification';
export default {
component: Notification,
title: 'Notification',
} as Meta;
const Template: Story = ({ intent, message, children }) => (
<div className="flex">
<Notification intent={intent} message={message}>
{children}
</Notification>
</div>
);
const props = {
message: 'Exercitationem doloremque neque laborum incidunt consectetur amet',
children: (
<div className="flex space-x-1">
<Link>Action</Link>
<ExternalLink>External action</ExternalLink>
</div>
),
};
export const Default = Template.bind({});
Default.args = {
...props,
intent: Intent.None,
};
export const Primary = Template.bind({});
Primary.args = {
...props,
intent: Intent.Primary,
};
export const Success = Template.bind({});
Success.args = {
...props,
intent: Intent.Success,
};
export const Warning = Template.bind({});
Warning.args = {
...props,
intent: Intent.Warning,
};
export const Danger = Template.bind({});
Danger.args = {
...props,
intent: Intent.Danger,
};
@@ -0,0 +1,71 @@
import { IconNames } from '@blueprintjs/icons';
import type { IconName } from '@blueprintjs/icons';
import classNames from 'classnames';
import type { ReactNode } from 'react';
import { Intent } from '../../utils/intent';
import { Icon } from '../icon';
type NotificationProps = {
intent: Intent;
message: string;
testId?: string;
children?: ReactNode;
};
const getIcon = (intent: Intent): IconName => {
const mapping = {
[Intent.None]: IconNames.HELP,
[Intent.Primary]: IconNames.INFO_SIGN,
[Intent.Success]: IconNames.TICK_CIRCLE,
[Intent.Warning]: IconNames.WARNING_SIGN,
[Intent.Danger]: IconNames.ERROR,
};
return mapping[intent] as IconName;
};
export const Notification = ({
intent,
message,
testId,
children,
}: NotificationProps) => {
return (
<div
data-testid={testId || 'notification'}
className={classNames(
{
'border-gray-700 dark:border-gray-300': intent === Intent.None,
'border-vega-blue': intent === Intent.Primary,
'border-vega-green-dark dark:border-vega-green':
intent === Intent.Success,
'border-yellow-500': intent === Intent.Warning,
'border-vega-pink': intent === Intent.Danger,
},
'border rounded px-3 py-1 text-xs mb-1 mr-1'
)}
>
<div
className={classNames(
{
'text-gray-700 dark:text-gray-300': intent === Intent.None,
'text-vega-blue': intent === Intent.Primary,
'text-vega-green-dark dark:text-vega-green':
intent === Intent.Success,
'text-yellow-600 dark:text-yellow-500': intent === Intent.Warning,
'text-vega-pink': intent === Intent.Danger,
},
'flex items-start'
)}
>
<Icon size={3} className="mr-1 mt-[2px]" name={getIcon(intent)} />
<span
title={message}
className="whitespace-nowrap overflow-hidden text-ellipsis"
>
{message}
</span>
</div>
{children}
</div>
);
};
@@ -7,7 +7,7 @@ export interface SplashProps {
export const Splash = ({ children }: SplashProps) => {
const splashClasses = classNames(
'w-full h-full',
'w-full h-full text-xs text-center text-gray-200',
'flex items-center justify-center'
);
return <div className={splashClasses}>{children}</div>;