diff --git a/.gitignore b/.gitignore
index b8e5e2b8..1725614d 100755
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,3 @@ yarn-error.log
.env
generated/
result*
-schema.graphql
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b4c64b4..ebc3c008 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,23 @@
Changelog
=========
+## 1.2.0
+
+### Compatible with:
+
+- [`cardano-graphql`: `2.2.0`](https://github.com/input-output-hk/cardano-graphql/releases/tag/2.2.0)
+
+### Features
+- [show deposits and reclaims when present in transaction](https://github.com/input-output-hk/cardano-explorer-app/pull/361)
+- [add withdrawals to TransactionInfo](https://github.com/input-output-hk/cardano-explorer-app/pull/363)
+- [resolve stake address searches based on withdrawals](https://github.com/input-output-hk/cardano-explorer-app/pull/363)
+- [use stake pool hash over slot leader reference](https://github.com/input-output-hk/cardano-explorer-app/pull/364)
+### Chores
+- [use new combined cardano-graphql schema from client package, removing local build step](https://github.com/input-output-hk/cardano-explorer-app/pull/362)
+
## 1.1.0
### Features
-- [Split slots & blocks into separate columns](https://github.com/input-output-hk/cardano-explorer-app/pull/338)
+- [Split slots & blocks into separate columns](https://github.com/input-output-hk/cardano-explorer-app/pull/347)
- [Add package.json version to footer](https://github.com/input-output-hk/cardano-explorer-app/pull/348)
### Chores
- [Dynamically calc Byron epochs length](https://github.com/input-output-hk/cardano-explorer-app/pull/334)
diff --git a/codegen.yml b/codegen.yml
index ee1c1d5a..cbb645d7 100644
--- a/codegen.yml
+++ b/codegen.yml
@@ -1,5 +1,5 @@
overwrite: true
-schema: schema.graphql
+schema: node_modules/@cardano-graphql/client-ts/api/schema.graphql
documents: "source/**/*.graphql"
generates:
generated/typings/graphql-schema.d.ts:
diff --git a/package.json b/package.json
index 118edd15..d77f5c69 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cardano-explorer-app",
- "version": "1.1.0",
+ "version": "1.2.0",
"description": "Cardano Explorer App",
"author": "Daedalus Team @ Input Output HK",
"license": "Apache-2.0",
@@ -13,8 +13,7 @@
"test": "jest",
"test:e2e": "cypress run",
"test:e2e:dev": "cypress open",
- "generate:graphql-schema": "node source/utils/generateGraphQLSchema.js",
- "generate:graphql-typings": "yarn generate:graphql-schema && graphql-codegen",
+ "generate:graphql-typings": "graphql-codegen",
"export": "next export source --outdir build/static",
"static:build": "NODE_ENV=production yarn build && yarn export",
"static:serve": "serve ./build/static",
@@ -72,7 +71,7 @@
"@babel/plugin-transform-react-display-name": "7.8.3",
"@babel/plugin-transform-react-jsx-self": "7.9.0",
"@babel/plugin-transform-react-jsx-source": "7.9.0",
- "@cardano-graphql/client-ts": "2.1.0",
+ "@cardano-graphql/client-ts": "2.2.0",
"@cypress/webpack-preprocessor": "4.1.1",
"@graphql-codegen/cli": "1.2.0",
"@graphql-codegen/typescript": "1.2.0",
diff --git a/packages-cache/@cardano-graphql-client-ts-2.1.0.tgz b/packages-cache/@cardano-graphql-client-ts-2.1.0.tgz
deleted file mode 100644
index 6a83cb66..00000000
Binary files a/packages-cache/@cardano-graphql-client-ts-2.1.0.tgz and /dev/null differ
diff --git a/packages-cache/@cardano-graphql-client-ts-2.2.0.tgz b/packages-cache/@cardano-graphql-client-ts-2.2.0.tgz
new file mode 100644
index 00000000..6ce23253
Binary files /dev/null and b/packages-cache/@cardano-graphql-client-ts-2.2.0.tgz differ
diff --git a/source/features/address/api/transformers.ts b/source/features/address/api/transformers.ts
index 538f3872..e1e6afbf 100644
--- a/source/features/address/api/transformers.ts
+++ b/source/features/address/api/transformers.ts
@@ -1,15 +1,36 @@
import { Currency } from 'cardano-js';
-import { SearchForAddressQuery } from '../../../../generated/typings/graphql-schema';
-import { IAddressSummary } from '../types';
+import {
+ SearchForPaymentAddressQuery,
+ SearchForStakeAddressQuery,
+} from '../../../../generated/typings/graphql-schema';
+import { IPaymentAddressSummary, IStakeAddressSummary } from '../types';
-export const addressDetailTransformer = (
+export const paymentAddressDetailTransformer = (
address: string,
- s: SearchForAddressQuery
-): IAddressSummary => ({
- address,
- finalBalance: Currency.Util.lovelacesToAda(
- s.utxos_aggregate?.aggregate?.sum?.value || '0'
- ),
- transactionsCount:
- s.transactions_aggregate?.aggregate?.count.toString() || '0',
-});
+ s: SearchForPaymentAddressQuery
+): IPaymentAddressSummary => {
+ return {
+ address,
+ finalBalance: Currency.Util.lovelacesToAda(
+ s.utxos_aggregate?.aggregate?.sum?.value || '0'
+ ),
+ transactionsCount:
+ s.transactions_aggregate?.aggregate?.count.toString() || '0'
+ }
+};
+
+export const stakeAddressDetailTransformer = (
+ address: string,
+ s: SearchForStakeAddressQuery
+): IStakeAddressSummary => {
+ return {
+ address,
+ totalWithdrawals:
+ s.withdrawals_aggregate?.aggregate?.count.toString() || '0',
+ totalWithdrawn: Currency.Util.lovelacesToAda(
+ s.withdrawals_aggregate?.aggregate?.sum?.amount || '0'
+ ),
+ transactionsCount:
+ s.transactions_aggregate?.aggregate?.count.toString() || '0'
+ }
+};
diff --git a/source/features/address/types.ts b/source/features/address/types.ts
index 2cf26c3a..5789f357 100644
--- a/source/features/address/types.ts
+++ b/source/features/address/types.ts
@@ -1,5 +1,13 @@
export interface IAddressSummary {
address: string;
- finalBalance: string;
transactionsCount: string;
}
+
+export interface IPaymentAddressSummary extends IAddressSummary {
+ finalBalance: string;
+}
+
+export interface IStakeAddressSummary extends IAddressSummary {
+ totalWithdrawals: string;
+ totalWithdrawn: string;
+}
diff --git a/source/features/address/ui/AddressSummary.tsx b/source/features/address/ui/AddressSummary.tsx
index b8936e0b..6b7953a6 100644
--- a/source/features/address/ui/AddressSummary.tsx
+++ b/source/features/address/ui/AddressSummary.tsx
@@ -6,12 +6,30 @@ import styles from './AddressSummary.module.scss';
export interface IAddressSummaryProps {
address: string;
- finalBalance: string;
title: string;
transactionsCount: string;
}
-const AddressSummary = (props: IAddressSummaryProps) => {
+export interface IPaymentAddressSummaryProps extends IAddressSummaryProps {
+ finalBalance: string;
+}
+
+export interface IStakeAddressSummaryProps extends IAddressSummaryProps {
+ totalWithdrawn: string;
+ totalWithdrawals: string;
+}
+
+type AddressSummaryProps = IPaymentAddressSummaryProps | IStakeAddressSummaryProps
+
+function isPaymentAddress (props: AddressSummaryProps): props is IPaymentAddressSummaryProps {
+ return (props as IPaymentAddressSummaryProps).finalBalance !== undefined;
+}
+
+function isStakeAddress (props: AddressSummaryProps): props is IStakeAddressSummaryProps {
+ return (props as IStakeAddressSummaryProps).totalWithdrawn !== undefined;
+}
+
+const AddressSummary = (props: AddressSummaryProps) => {
const { translate } = useI18nFeature().store;
return (
@@ -32,12 +50,30 @@ const AddressSummary = (props: IAddressSummaryProps) => {
{props.transactionsCount}
-
-
- {translate('address.summaryBalanceLabel')}
+ {isPaymentAddress(props) && (
+
+
+ {translate('address.summaryBalanceLabel')}
+
+
{props.finalBalance} ADA
-
{props.finalBalance} ADA
-
+ )}
+ {isStakeAddress(props) && (
+ <>
+
+
+ {translate('withdrawals')}
+
+
{props.totalWithdrawals}
+
+
+
+ {translate('address.totalWithdrawn')}
+
+
{props.totalWithdrawn} ADA
+
+ >
+ )}
;
+
+ public searchForStakeAddressQuery: GraphQLRequest<
+ SearchForStakeAddressQuery,
+ SearchForStakeAddressQueryVariables
>;
public searchByIdQuery: GraphQLRequest<
@@ -37,9 +45,13 @@ export class SearchApi {
>;
constructor(client: GraphQLClient) {
- this.searchForAddressQuery = new GraphQLRequest(
+ this.searchForPaymentAddressQuery = new GraphQLRequest(
+ client,
+ searchForPaymentAddressQuery
+ );
+ this.searchForStakeAddressQuery = new GraphQLRequest(
client,
- searchForAddressQuery
+ searchForStakeAddressQuery
);
this.searchByIdQuery = new GraphQLRequest(client, searchByIdQuery);
this.searchForBlockByNumberQuery = new GraphQLRequest(
diff --git a/source/features/search/api/searchForAddress.graphql b/source/features/search/api/searchForPaymentAddress.graphql
similarity index 95%
rename from source/features/search/api/searchForAddress.graphql
rename to source/features/search/api/searchForPaymentAddress.graphql
index bcb06fc8..0b03e242 100644
--- a/source/features/search/api/searchForAddress.graphql
+++ b/source/features/search/api/searchForPaymentAddress.graphql
@@ -1,4 +1,4 @@
-query searchForAddress(
+query searchForPaymentAddress(
$address: String!
) {
utxos_aggregate (
diff --git a/source/features/search/api/searchForStakeAddress.graphql b/source/features/search/api/searchForStakeAddress.graphql
new file mode 100644
index 00000000..e479bb4a
--- /dev/null
+++ b/source/features/search/api/searchForStakeAddress.graphql
@@ -0,0 +1,38 @@
+#import "../../transactions/api/TransactionDetails.graphql"
+
+query searchForStakeAddress(
+ $address: String!
+) {
+ transactions_aggregate (
+ where: {
+ withdrawals: {
+ address: {
+ _eq: $address
+ }
+ }
+ }
+ ) {
+ aggregate {
+ count
+ }
+ }
+ withdrawals {
+ transaction {
+ ...TransactionDetails
+ }
+ }
+ withdrawals_aggregate (
+ where: {
+ address: {
+ _eq: $address
+ }
+ }
+ ) {
+ aggregate {
+ count
+ sum {
+ amount
+ }
+ }
+ }
+}
diff --git a/source/features/search/index.ts b/source/features/search/index.ts
index 410338f0..623e8027 100644
--- a/source/features/search/index.ts
+++ b/source/features/search/index.ts
@@ -10,16 +10,18 @@ import { SearchStore } from './store';
* Defines the actions that are supported by this feature
*/
export class SearchActions {
+ public addressNotFound: Action<{ address: string }> = new Action();
public addressSearchRequested: Action<{ address: string }> = new Action();
public blockNumberSearchRequested: Action<{ number: number }> = new Action();
public epochNumberSearchRequested: Action<{ number: number }> = new Action();
public idSearchRequested: Action<{ id: string }> = new Action();
- public unknownSearchRequested: Action<{ query: string }> = new Action();
public searchById: Action<{ id: string }> = new Action();
- public searchForAddress: Action<{ address: string }> = new Action();
+ public searchForPaymentAddress: Action<{ address: string }> = new Action();
+ public searchForStakeAddress: Action<{ address: string }> = new Action();
public searchForBlockByNumber: Action<{ number: number }> = new Action();
public searchForEpochByNumber: Action<{ number: number }> = new Action();
public subscribeToEpoch: Action<{ number: number }> = new Action();
+ public unknownSearchRequested: Action<{ query: string }> = new Action();
public unsubscribeFromEpoch: Action = new Action();
}
diff --git a/source/features/search/specs/helpers/exampleAddressData.ts b/source/features/search/specs/helpers/exampleAddressData.ts
index 77521578..330afe6c 100644
--- a/source/features/search/specs/helpers/exampleAddressData.ts
+++ b/source/features/search/specs/helpers/exampleAddressData.ts
@@ -1,4 +1,4 @@
-export const exampleAddressData = {
+export const examplePaymentAddressData = {
address: 'Ae2tdPwUPEZBZTsRj7nGvvWQDTkqD9KLpCPpuZvjA1roL7KLDDVgkPU5S8j',
finalBalance: '0',
transactions: [
@@ -25,3 +25,9 @@ export const exampleAddressData = {
],
transactionsCount: '2',
};
+
+export const exampleStakeAddressData = {
+ address: 'stake1u8gu2vzsk2nc6hsphudhl3p6aum7nd59ajqjg9zp00uvxcqwsdray',
+ totalWithdrawn: '1563.774139',
+ transactionsCount: '1',
+};
diff --git a/source/features/search/specs/searchForAddress.spec.ts b/source/features/search/specs/searchForAddress.spec.ts
deleted file mode 100644
index 940f2ac2..00000000
--- a/source/features/search/specs/searchForAddress.spec.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import waitForExpect from 'wait-for-expect';
-import { ISearchFeature } from '../index';
-import { exampleAddressData } from './helpers/exampleAddressData';
-import { setupSearchFeature } from './helpers/setup';
-
-describe('Searching for an address summary', () => {
- let search: ISearchFeature;
- beforeEach(() => {
- search = setupSearchFeature();
- search.start();
- });
- afterEach(() => {
- search.stop();
- });
- it('searches for a summary related to the provided address', async () => {
- // 1. Trigger action
- search.actions.searchForAddress.trigger({
- address: exampleAddressData.address,
- });
-
- // 2. Check the API query status
- expect(search.api.searchForAddressQuery.isExecuting).toBe(true);
-
- // 3. Access the observable search result provided by the store
- await waitForExpect(() => {
- expect(search.store?.addressSearchResult?.finalBalance).toBe(
- exampleAddressData.finalBalance
- );
- expect(search.store?.addressSearchResult?.transactionsCount).toBe(
- exampleAddressData.transactionsCount
- );
- });
- });
-});
diff --git a/source/features/search/specs/searchForPaymentAddress.spec.ts b/source/features/search/specs/searchForPaymentAddress.spec.ts
new file mode 100644
index 00000000..3529f2b1
--- /dev/null
+++ b/source/features/search/specs/searchForPaymentAddress.spec.ts
@@ -0,0 +1,34 @@
+import waitForExpect from 'wait-for-expect';
+import { ISearchFeature } from '../index';
+import { examplePaymentAddressData } from './helpers/exampleAddressData';
+import { setupSearchFeature } from './helpers/setup';
+
+describe('Searching for a payment address summary', () => {
+ let search: ISearchFeature;
+ beforeEach(() => {
+ search = setupSearchFeature();
+ search.start();
+ });
+ afterEach(() => {
+ search.stop();
+ });
+ it('searches for a summary related to the provided payment address', async () => {
+ // 1. Trigger action
+ search.actions.searchForPaymentAddress.trigger({
+ address: examplePaymentAddressData.address,
+ });
+
+ // 2. Check the API query status
+ expect(search.api.searchForPaymentAddressQuery.isExecuting).toBe(true);
+
+ // 3. Access the observable search result provided by the store
+ await waitForExpect(() => {
+ expect(search.store?.paymentAddressSearchResult?.finalBalance).toBe(
+ examplePaymentAddressData.finalBalance
+ );
+ expect(search.store?.paymentAddressSearchResult?.transactionsCount).toBe(
+ examplePaymentAddressData.transactionsCount
+ );
+ });
+ });
+});
diff --git a/source/features/search/specs/searchForStakeAddress.spec.ts b/source/features/search/specs/searchForStakeAddress.spec.ts
new file mode 100644
index 00000000..123de9f7
--- /dev/null
+++ b/source/features/search/specs/searchForStakeAddress.spec.ts
@@ -0,0 +1,34 @@
+import waitForExpect from 'wait-for-expect';
+import { ISearchFeature } from '../index';
+import { exampleStakeAddressData } from './helpers/exampleAddressData';
+import { setupSearchFeature } from './helpers/setup';
+
+describe('Searching for a stake address summary', () => {
+ let search: ISearchFeature;
+ beforeEach(() => {
+ search = setupSearchFeature();
+ search.start();
+ });
+ afterEach(() => {
+ search.stop();
+ });
+ it('searches for a summary related to the provided stake address', async () => {
+ // 1. Trigger action
+ search.actions.searchForStakeAddress.trigger({
+ address: exampleStakeAddressData.address,
+ });
+
+ // 2. Check the API query status
+ expect(search.api.searchForStakeAddressQuery.isExecuting).toBe(true);
+
+ // 3. Access the observable search result provided by the store
+ await waitForExpect(() => {
+ expect(search.store?.stakeAddressSearchResult?.totalWithdrawn).toBe(
+ exampleStakeAddressData.totalWithdrawn
+ );
+ expect(search.store?.stakeAddressSearchResult?.transactionsCount).toBe(
+ exampleStakeAddressData.transactionsCount
+ );
+ });
+ });
+});
diff --git a/source/features/search/store.ts b/source/features/search/store.ts
index 20774556..19e0c0a2 100644
--- a/source/features/search/store.ts
+++ b/source/features/search/store.ts
@@ -3,9 +3,12 @@ import { ActionProps, createActionBindings } from '../../lib/ActionBinding';
import Reaction, { createReactions } from '../../lib/mobx/Reaction';
import { Store } from '../../lib/Store';
import { isDefined } from '../../lib/types';
-import { addressDetailTransformer } from '../address/api/transformers';
+import {
+ paymentAddressDetailTransformer,
+ stakeAddressDetailTransformer
+} from '../address/api/transformers';
import { ADDRESS_SEARCH_RESULT_PATH } from '../address/config';
-import { IAddressSummary } from '../address/types';
+import { IAddressSummary, IPaymentAddressSummary, IStakeAddressSummary } from '../address/types';
import { blockDetailsTransformer } from '../blocks/api/transformers';
import { BLOCK_SEARCH_RESULT_PATH } from '../blocks/config';
import { IBlockDetailed } from '../blocks/types';
@@ -31,9 +34,10 @@ export enum SearchType {
}
export class SearchStore extends Store {
- @observable public addressSearchResult: IAddressSummary | null = null;
@observable public blockSearchResult: IBlockDetailed | null = null;
@observable public epochSearchResult: IEpochOverview | null = null;
+ @observable public paymentAddressSearchResult: IPaymentAddressSummary | null = null;
+ @observable public stakeAddressSearchResult: IStakeAddressSummary | null = null;
@observable public transactionSearchResult: ITransactionDetails | null = null;
private readonly searchApi: SearchApi;
@@ -71,7 +75,8 @@ export class SearchStore extends Store {
this.onSearchByEpochNumberRequested,
],
[this.searchActions.searchById, this.searchById],
- [this.searchActions.searchForAddress, this.searchForAddress],
+ [this.searchActions.searchForPaymentAddress, this.searchForPaymentAddress],
+ [this.searchActions.searchForStakeAddress, this.searchForStakeAddress],
[
this.searchActions.searchForBlockByNumber,
this.searchForBlockByNumber,
@@ -98,11 +103,12 @@ export class SearchStore extends Store {
@computed get isSearching() {
return (
- this.searchApi.searchForAddressQuery.isExecuting ||
- this.searchApi.searchForBlockByNumberQuery.isExecuting ||
this.searchApi.searchByIdQuery.isExecuting ||
this.searchApi.searchForBlockByNumberQuery.isExecuting ||
- this.searchApi.searchForEpochByNumberQuery.isExecuting
+ this.searchApi.searchForBlockByNumberQuery.isExecuting ||
+ this.searchApi.searchForEpochByNumberQuery.isExecuting ||
+ this.searchApi.searchForPaymentAddressQuery.isExecuting ||
+ this.searchApi.searchForStakeAddressQuery.isExecuting
);
}
@@ -189,20 +195,21 @@ export class SearchStore extends Store {
});
};
- @action private searchForAddress = async ({
- address,
+ @action private searchForPaymentAddress = async ({
+ address
}: {
address: string;
}) => {
// Do not execute queries more than necessary!
if (
- this.searchApi.searchForAddressQuery.isExecuting ||
- this.addressSearchResult?.address === address
+ this.searchApi.searchForPaymentAddressQuery.isExecuting ||
+ this.paymentAddressSearchResult?.address === address
) {
return;
}
- this.addressSearchResult = null;
- const result = await this.searchApi.searchForAddressQuery.execute({
+ this.paymentAddressSearchResult = null;
+ this.stakeAddressSearchResult = null;
+ const result = await this.searchApi.searchForPaymentAddressQuery.execute({
address,
});
if (isDefined(result)) {
@@ -215,7 +222,36 @@ export class SearchStore extends Store {
});
}
runInAction(() => {
- this.addressSearchResult = addressDetailTransformer(address, result);
+ this.paymentAddressSearchResult = paymentAddressDetailTransformer(address, result);
+ });
+ }
+ };
+
+ @action private searchForStakeAddress = async ({
+ address,
+ }: {
+ address: string;
+ }) => {
+ // Do not execute queries more than necessary!
+ if (
+ this.searchApi.searchForStakeAddressQuery.isExecuting ||
+ this.stakeAddressSearchResult?.address === address
+ ) {
+ return;
+ }
+ this.stakeAddressSearchResult = null;
+ this.paymentAddressSearchResult = null;
+ const result = await this.searchApi.searchForStakeAddressQuery.execute({
+ address,
+ });
+ if (isDefined(result)) {
+ if (result.withdrawals_aggregate?.aggregate?.count === '0') {
+ return this.searchActions.unknownSearchRequested.trigger({
+ query: address,
+ });
+ }
+ runInAction(() => {
+ this.stakeAddressSearchResult = stakeAddressDetailTransformer(address, result);
});
}
};
diff --git a/source/features/search/ui/AddressSearchResult.tsx b/source/features/search/ui/AddressSearchResult.tsx
index 963ff88f..64fab89c 100644
--- a/source/features/search/ui/AddressSearchResult.tsx
+++ b/source/features/search/ui/AddressSearchResult.tsx
@@ -25,36 +25,49 @@ export const AddressSearchResult = () => {
const { query } = navigation.store;
const { address } = query;
if (isString(address)) {
- actions.searchForAddress.trigger({ address });
+ if (address.substring(0, 5) === 'stake') {
+ actions.searchForStakeAddress.trigger({ address });
+ } else {
+ actions.searchForPaymentAddress.trigger({ address });
+ }
}
});
return (
{() => {
- const { addressSearchResult } = store;
+ const { paymentAddressSearchResult, stakeAddressSearchResult } = store;
+ const address = paymentAddressSearchResult?.address || stakeAddressSearchResult?.address || null;
+ const transactionsCount = paymentAddressSearchResult?.transactionsCount || stakeAddressSearchResult?.transactionsCount;
if (
- !api.searchForAddressQuery.hasBeenExecutedAtLeastOnce ||
+ ( paymentAddressSearchResult && !api.searchForPaymentAddressQuery.hasBeenExecutedAtLeastOnce ) ||
+ ( stakeAddressSearchResult && !api.searchForStakeAddressQuery.hasBeenExecutedAtLeastOnce ) ||
store.isSearching
) {
return ;
- } else if (addressSearchResult) {
- const {
- address,
- finalBalance,
- transactionsCount,
- } = addressSearchResult;
+ } else if (address !== null && transactionsCount !== null) {
return (
<>
-
+ { paymentAddressSearchResult && (
+
+ )}
+ { stakeAddressSearchResult && (
+
+ )}
- {
}}
perPage={navigation.store.query.perPage as string}
currentPage={(navigation.store.query.page as string) ?? 1}
- total={parseInt(transactionsCount, 10)}
+ total={parseInt(paymentAddressSearchResult?.transactionsCount || stakeAddressSearchResult?.transactionsCount || '0', 10)}
transactions={transactions.store.browsedAddressTransactions}
- />
+ />}
>
);
diff --git a/source/features/transactions/api/TransactionDetails.graphql b/source/features/transactions/api/TransactionDetails.graphql
index 2be03a9d..218fae75 100644
--- a/source/features/transactions/api/TransactionDetails.graphql
+++ b/source/features/transactions/api/TransactionDetails.graphql
@@ -5,6 +5,7 @@ fragment TransactionDetails on Transaction {
number,
slotNo,
}
+ deposit,
fee,
hash,
includedAt,
@@ -20,4 +21,8 @@ fragment TransactionDetails on Transaction {
value
},
totalOutput
+ withdrawals {
+ address
+ amount
+ }
}
diff --git a/source/features/transactions/api/getAddressTransactions.graphql b/source/features/transactions/api/getAddressTransactions.graphql
index 387bff5e..5aaf7cb5 100644
--- a/source/features/transactions/api/getAddressTransactions.graphql
+++ b/source/features/transactions/api/getAddressTransactions.graphql
@@ -8,6 +8,12 @@ query getAddressTransactions(
transactions(
where: {
_or: [{
+ withdrawals: {
+ address: {
+ _eq: $address
+ }
+ }
+ }, {
inputs: {
address: {
_eq: $address
diff --git a/source/features/transactions/api/transformers.ts b/source/features/transactions/api/transformers.ts
index 68c7c07d..5628976c 100644
--- a/source/features/transactions/api/transformers.ts
+++ b/source/features/transactions/api/transformers.ts
@@ -11,6 +11,7 @@ export const transactionDetailsTransformer = (
id: tx.block?.hash,
number: tx.block?.number,
},
+ deposit: Currency.Util.lovelacesToAda(tx.deposit),
fee: Currency.Util.lovelacesToAda(tx.fee),
id: tx.hash,
includedAt: new Date(tx.includedAt),
@@ -24,4 +25,8 @@ export const transactionDetailsTransformer = (
value: Currency.Util.lovelacesToAda(i.value),
})),
totalOutput: Currency.Util.lovelacesToAda(tx.totalOutput),
+ withdrawals: tx.withdrawals?.filter(isDefined).map((i) => ({
+ address: i.address,
+ value: Currency.Util.lovelacesToAda(i.amount)
+ })) || []
});
diff --git a/source/features/transactions/components/TransactionInfo.tsx b/source/features/transactions/components/TransactionInfo.tsx
index 7f5fe465..55f2d898 100644
--- a/source/features/transactions/components/TransactionInfo.tsx
+++ b/source/features/transactions/components/TransactionInfo.tsx
@@ -18,6 +18,7 @@ import {
ITransactionDetails,
ITransactionInput,
ITransactionOutput,
+ IWithdrawal,
} from '../types';
import styles from './TransactionInfo.module.scss';
@@ -48,7 +49,7 @@ const TransactionAddressMobile = (props: { address: string }) =>
>
);
-type AddressInputOutput = ITransactionInput | ITransactionOutput;
+type AddressInputOutput = ITransactionInput | IWithdrawal | ITransactionOutput;
interface IAddressesRowProps {
addresses?: Array;
@@ -119,7 +120,7 @@ const TransactionInfo = (props: ITransactionInfoProps) => {
});
};
const epoch = props.block.epoch === '-' ? 0 : props.block.epoch;
-
+ const depositLabel = parseInt(props.deposit) >= 0 ? 'transaction.deposit' : 'transaction.depositReclaim'
return (
{props.title && (
@@ -203,7 +204,7 @@ const TransactionInfo = (props: ITransactionInfoProps) => {
@@ -227,6 +228,16 @@ const TransactionInfo = (props: ITransactionInfoProps) => {
+ {/* ===== DEPOSIT ===== */}
+ {props.deposit !== '0' && (
+
+
+ {translate(depositLabel)}
+
+
{Math.abs(parseInt(props.deposit))} ADA
+
+ )}
+
{/* ===== TOTAL OUTPUT ===== */}
diff --git a/source/features/transactions/types.ts b/source/features/transactions/types.ts
index 63148484..2a29265c 100644
--- a/source/features/transactions/types.ts
+++ b/source/features/transactions/types.ts
@@ -13,6 +13,10 @@ export interface ITransactionOutput extends ICoin {
index: number;
}
+export interface IWithdrawal extends ICoin {
+ address: string;
+}
+
export interface ITransactionDetails {
block: {
epoch?: number | '-';
@@ -20,10 +24,12 @@ export interface ITransactionDetails {
number?: number | null;
slot?: number | null;
};
+ deposit: string;
fee: string;
id: string;
includedAt: Date;
inputs: ITransactionInput[];
outputs?: ITransactionOutput[];
totalOutput: string;
+ withdrawals: IWithdrawal[];
}
diff --git a/source/utils/generateGraphQLSchema.js b/source/utils/generateGraphQLSchema.js
deleted file mode 100644
index 94f1a144..00000000
--- a/source/utils/generateGraphQLSchema.js
+++ /dev/null
@@ -1,17 +0,0 @@
-const fs = require('fs');
-const path = require('path');
-const { loadFilesSync } = require('@graphql-tools/load-files');
-const { mergeTypeDefs } = require('@graphql-tools/merge');
-const { printSchemaWithDirectives } = require('@graphql-tools/utils');
-const { makeExecutableSchema } = require('@graphql-tools/schema');
-
-const cardanoDbHasuraSchema = loadFilesSync('./node_modules/@cardano-graphql/client-ts/api/cardano-db-hasura/schema.graphql');
-const genesisSchema = loadFilesSync('./node_modules/@cardano-graphql/client-ts/api/genesis/schema.graphql');
-const mergedTypes = mergeTypeDefs([cardanoDbHasuraSchema, genesisSchema], {
- throwOnConflict: true
-});
-
-const executableSchema = makeExecutableSchema({ typeDefs: [mergedTypes] });
-const schema = printSchemaWithDirectives(executableSchema);
-
-fs.writeFileSync(path.join(__dirname, '../../schema.graphql'), schema);
diff --git a/yarn.lock b/yarn.lock
index b19022f1..9d6fa36c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1443,10 +1443,10 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
-"@cardano-graphql/client-ts@2.1.0":
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/@cardano-graphql/client-ts/-/client-ts-2.1.0.tgz#f93ddbe4cb88c7b4f5048bc0692e575bd81d9993"
- integrity sha512-OnvlWkMxSoH2NFfSLPTNRGnzqg4efZmXc34wBUefTfPvmGaNO1NxYVP1wW2nS5/lfkNxwSyFPKX3yNu+MNKh2Q==
+"@cardano-graphql/client-ts@2.2.0":
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/@cardano-graphql/client-ts/-/client-ts-2.2.0.tgz#a8f725ab642a9605f9c4aee3b78d2a637f568675"
+ integrity sha512-1ob9UboUijZxXllSlaYtsoOWM4EXcmPlKyhm1o5+kY2qkD7lRzOs6TBpJegrU4xQX+TGhLALawP+l6lNiHIsTg==
"@cnakazawa/watch@^1.0.3":
version "1.0.4"