diff --git a/src/app/account/account.converter.ts b/src/app/account/account.converter.ts index b63c9831db66448241967b5463605c387f0ab728..77dfc8adac45cc93896517c7c325f3fa935661b5 100644 --- a/src/app/account/account.converter.ts +++ b/src/app/account/account.converter.ts @@ -1,6 +1,5 @@ import { LightAccountConnectionFragment, LightAccountFragment, LightIdentityFragment } from '@app/network/indexer-types.generated'; import { Account, parseAddressSquid } from '@app/account/account.model'; -import { isNotNil } from '@app/shared/functions'; export class AccountConverter { static connectionToAccounts(accountConnection: LightAccountConnectionFragment, debug?: boolean): Account[] { @@ -19,13 +18,16 @@ export class AccountConverter { static toAccount(input: LightAccountFragment): Account { if (!input) return undefined; const addressSquid = parseAddressSquid(input.id); + const identity = input.identity; return <Account>{ address: addressSquid.address, meta: { - id: input.identity?.id, - index: input.identity?.index, - uid: input.identity?.name, - isMember: input.identity?.membershipHistory?.some((h) => isNotNil(h.id)) || false, + id: identity?.id, + index: identity?.index, + uid: identity?.name, + status: identity?.status, + isMember: identity?.isMember || false, + createdOn: identity?.createdOn, }, }; } @@ -46,7 +48,8 @@ export class IdentityConverter { id: input.id, index: input.index, uid: input.name, - isMember: input.membershipHistory?.some((h) => isNotNil(h.id)) || false, + status: input?.status, + isMember: input.isMember || false, }, }; } diff --git a/src/app/account/account.model.ts b/src/app/account/account.model.ts index 36eec9ceb0b44f0f321001cbdd6fa590a34b8f49..3d24135440e1e2873952bc1e403fa8b5ac063ed1 100644 --- a/src/app/account/account.model.ts +++ b/src/app/account/account.model.ts @@ -1,6 +1,7 @@ import { HexString } from '@polkadot/util/types'; import { ListItem } from '@app/shared/popover/list.popover'; import { formatAddress } from '@app/shared/currencies'; +import { IdentityStatusEnum } from '@app/network/indexer-types.generated'; export interface AddressSquid { index: number; @@ -16,6 +17,8 @@ export interface Account { data?: AccountData; } +//export declare type IdentityStatus = 'CREATION'; + export interface AccountMeta { // Polkadot properties name: string; @@ -26,6 +29,7 @@ export interface AccountMeta { id?: string; index?: number; // member index uid?: string; + createdOn?: number; // Cesium properties self?: boolean; @@ -34,6 +38,7 @@ export interface AccountMeta { avatar?: string; email?: string; isMember?: boolean; + status?: IdentityStatusEnum; [key: string]: unknown; } diff --git a/src/app/account/account.queries.graphql b/src/app/account/account.queries.graphql index 862e9fb9108aa6880fffe654a1723034fd81f0df..fced4b5d137376f8e621b7b14ecdefb8ece17571 100644 --- a/src/app/account/account.queries.graphql +++ b/src/app/account/account.queries.graphql @@ -2,11 +2,14 @@ fragment LightIdentity on Identity { id index name - isMember accountId + status + isMember + createdOn membershipHistory { __typename id + eventType } } diff --git a/src/app/account/accounts.service.ts b/src/app/account/accounts.service.ts index 5abc77ede5ed92bdea9eeb3574b671eadc3b21ba..0a3bfa24e284a28091edfa48ef00cbe1fe181795 100644 --- a/src/app/account/accounts.service.ts +++ b/src/app/account/accounts.service.ts @@ -660,6 +660,8 @@ export class AccountsService extends RxStartableService<AccountsState> { ...account.meta, uid: indexedAccount.meta?.uid, isMember: indexedAccount.meta?.isMember, + status: indexedAccount.meta?.status, + createdOn: indexedAccount.meta?.createdOn, }; changed = true; } diff --git a/src/app/account/wallet/wallet.page.html b/src/app/account/wallet/wallet.page.html index 2814df74911054a240a1b459c9d9627985e5fa08..a5a37ef459053e1b3a0b9c5707fe408c0880e70c 100644 --- a/src/app/account/wallet/wallet.page.html +++ b/src/app/account/wallet/wallet.page.html @@ -58,7 +58,7 @@ <ion-label class="ion-text-end"> <p translate>ACCOUNT.BALANCE</p> <h2> - <b *rxIf="account$; let account">{{ account | balance | amountFormat }}</b> + <b *rxIf="account$; let account" [innerHtml]="account | balance | amountFormat"></b> </h2> </ion-label> </div> @@ -123,9 +123,14 @@ <ion-icon aria-hidden="true" slot="start" name="calendar-clear-outline"></ion-icon> <ion-label> <h3 translate>COMMON.UID</h3> - <p>{{ 'WOT.REGISTERED_SINCE' | translate }}</p> + <p> + {{ 'WOT.REGISTERED_SINCE' | translate }} {{ account.meta.createdOn | blockTime | dateFormat }} - + {{ 'WOT.REGISTERED_SINCE_BLOCK' | translate }} {{ account.meta.createdOn | blockNumber }} + </p> </ion-label> - <ion-badge color="warning" slot="end">{{ account.meta?.uid }}</ion-badge> + <ion-badge [color]="account.meta.isMember ? 'warning' : 'medium'" slot="end"> + {{ account.meta.uid }} ({{ account.meta.status }}) + </ion-badge> </ion-item> <!-- Received cert count --> diff --git a/src/app/certification/history/cert-history.page.html b/src/app/certification/history/cert-history.page.html index 82c8782f876698680c85fd0db11410bc363d46fa..1130238d4be2f92062ce5ce0a9562e1cbb15908a 100644 --- a/src/app/certification/history/cert-history.page.html +++ b/src/app/certification/history/cert-history.page.html @@ -62,7 +62,7 @@ <ion-icon name="key"></ion-icon> {{ item.account.address | addressToPubkeyV1 | pubkeyFormat: true }} | <a [routerLink]="['/block', item.createdOn]" routerDirection="forward" (click)="$event.preventDefault()" class="tx-timestamp"> - {{ 'COMMON.BLOCK' | translate }} #{{ item.updatedOn | blockNumber }} + {{ item.updatedOn | blockTime | dateFormat }} | {{ 'COMMON.BLOCK' | translate }} #{{ item.updatedOn | blockNumber }} </a> </p> </ion-label> diff --git a/src/app/network/indexer-types.generated.ts b/src/app/network/indexer-types.generated.ts index dac9ca201751bda7393683b8f492318ab512ff09..a5510cdb899b41b3eef37464d7f65607141665fe 100644 --- a/src/app/network/indexer-types.generated.ts +++ b/src/app/network/indexer-types.generated.ts @@ -4687,11 +4687,11 @@ export type TransferAggregateBoolExpCount = { predicate: IntComparisonExp; }; -export type LightIdentityFragment = { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> }; +export type LightIdentityFragment = { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> }; -export type LightAccountFragment = { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null }; +export type LightAccountFragment = { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null }; -export type LightAccountConnectionFragment = { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } }> }; +export type LightAccountConnectionFragment = { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }> }; export type LightBlockFragment = { __typename: 'Block', id: string, height: number, hash: any, timestamp: any, callsCount: number, eventsCount: number, extrinsicsCount: number }; @@ -4716,13 +4716,13 @@ export type BlocksQuery = { __typename?: 'query_root', blockConnection: { __type export type LightCertFragment = { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number }; -export type CertFragment = { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null }; +export type CertFragment = { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null }; -export type CertConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; +export type CertConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; -export type CertReceivedConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; +export type CertReceivedConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; -export type CertIssuedConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; +export type CertIssuedConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; export type CertsConnectionByIssuerQueryVariables = Exact<{ address: Scalars['String']['input']; @@ -4732,7 +4732,7 @@ export type CertsConnectionByIssuerQueryVariables = Exact<{ }>; -export type CertsConnectionByIssuerQuery = { __typename?: 'query_root', identityConnection: { __typename?: 'IdentityConnection', edges: Array<{ __typename?: 'IdentityEdge', node: { __typename?: 'Identity', aggregate: { __typename?: 'CertAggregate', aggregate?: { __typename?: 'CertAggregateFields', count: number } | null }, connection: { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } } } }> } }; +export type CertsConnectionByIssuerQuery = { __typename?: 'query_root', identityConnection: { __typename?: 'IdentityConnection', edges: Array<{ __typename?: 'IdentityEdge', node: { __typename?: 'Identity', aggregate: { __typename?: 'CertAggregate', aggregate?: { __typename?: 'CertAggregateFields', count: number } | null }, connection: { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } } } }> } }; export type CertsConnectionByReceiverQueryVariables = Exact<{ address: Scalars['String']['input']; @@ -4742,11 +4742,11 @@ export type CertsConnectionByReceiverQueryVariables = Exact<{ }>; -export type CertsConnectionByReceiverQuery = { __typename?: 'query_root', identityConnection: { __typename?: 'IdentityConnection', edges: Array<{ __typename?: 'IdentityEdge', node: { __typename?: 'Identity', aggregate: { __typename?: 'CertAggregate', aggregate?: { __typename?: 'CertAggregateFields', count: number } | null }, connection: { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } } } }> } }; +export type CertsConnectionByReceiverQuery = { __typename?: 'query_root', identityConnection: { __typename?: 'IdentityConnection', edges: Array<{ __typename?: 'IdentityEdge', node: { __typename?: 'Identity', aggregate: { __typename?: 'CertAggregate', aggregate?: { __typename?: 'CertAggregateFields', count: number } | null }, connection: { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } } } }> } }; -export type TransferFragment = { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } | null }; +export type TransferFragment = { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null }; -export type TransferConnectionFragment = { __typename?: 'TransferConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'TransferEdge', node: { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } | null } }> }; +export type TransferConnectionFragment = { __typename?: 'TransferConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'TransferEdge', node: { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null } }> }; export type TransferConnectionByAddressQueryVariables = Exact<{ address: Scalars['String']['input']; @@ -4756,7 +4756,7 @@ export type TransferConnectionByAddressQueryVariables = Exact<{ }>; -export type TransferConnectionByAddressQuery = { __typename?: 'query_root', transferConnection: { __typename?: 'TransferConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'TransferEdge', node: { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } | null } }> } }; +export type TransferConnectionByAddressQuery = { __typename?: 'query_root', transferConnection: { __typename?: 'TransferConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'TransferEdge', node: { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null } }> } }; export type WotSearchByTextQueryVariables = Exact<{ searchText: Scalars['String']['input']; @@ -4766,7 +4766,7 @@ export type WotSearchByTextQueryVariables = Exact<{ }>; -export type WotSearchByTextQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } }> } }; +export type WotSearchByTextQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }> } }; export type WotSearchByAddressQueryVariables = Exact<{ address: Scalars['String']['input']; @@ -4776,7 +4776,7 @@ export type WotSearchByAddressQueryVariables = Exact<{ }>; -export type WotSearchByAddressQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } }> } }; +export type WotSearchByAddressQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }> } }; export type WotSearchLastQueryVariables = Exact<{ first: Scalars['Int']['input']; @@ -4786,18 +4786,21 @@ export type WotSearchLastQueryVariables = Exact<{ }>; -export type WotSearchLastQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, isMember: boolean, accountId?: string | null, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string }> } | null } }> } }; +export type WotSearchLastQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }> } }; export const LightIdentityFragmentDoc = gql` fragment LightIdentity on Identity { id index name - isMember accountId + status + isMember + createdOn membershipHistory { __typename id + eventType } } `; diff --git a/src/app/settings/settings.service.ts b/src/app/settings/settings.service.ts index d9a5ec053c321607a7f7a46b21c1361a33f8bc23..0afe7c674456df332ed53aff92394a38637fb8cc 100644 --- a/src/app/settings/settings.service.ts +++ b/src/app/settings/settings.service.ts @@ -60,13 +60,14 @@ export class SettingsService extends RxStartableService<Settings> { } clone(): Settings { + const data = this.get(); return <Settings>{ locale: environment.defaultLocale, - defaultPeers: environment.defaultPeers || [], - peer: environment.defaultPeers?.[0], - defaultIndexers: environment.defaultIndexers || [], - indexer: environment.defaultIndexers?.[0], + peer: environment.dev?.peer || environment.defaultPeers?.[0], + indexer: environment.dev?.indexer || environment.defaultIndexers?.[0], ...this.get(), + preferredPeers: arrayDistinct([...environment.defaultPeers, ...(data?.preferredPeers || [])]), + preferredIndexers: arrayDistinct([...environment.defaultIndexers, ...(data?.preferredIndexers || [])]), }; } @@ -74,12 +75,13 @@ export class SettingsService extends RxStartableService<Settings> { const data = await this.storage.get(SETTINGS_STORAGE_KEY); return <Settings>{ // Default values - preferredPeers: arrayDistinct([...environment.defaultPeers, ...(data?.preferredPeers || [])]), - preferredIndexers: arrayDistinct([...environment.defaultIndexers, ...(data?.preferredIndexers || [])]), unAuthDelayMs: 15 * 60_000, // 15 min darkMode: window.matchMedia('(prefers-color-scheme: dark)').matches, // Restored data ...data, + // Merge default and restored data + preferredPeers: arrayDistinct([...environment.defaultPeers, ...(data?.preferredPeers || [])]), + preferredIndexers: arrayDistinct([...environment.defaultIndexers, ...(data?.preferredIndexers || [])]), }; } diff --git a/src/app/shared/pipes/amount.pipe.ts b/src/app/shared/pipes/amount.pipe.ts index 71ada7a2b6dfb48c6ede219aa3f61f827d85c769..d91c857f23c156f4f5d0410e9e464e039457f771 100644 --- a/src/app/shared/pipes/amount.pipe.ts +++ b/src/app/shared/pipes/amount.pipe.ts @@ -2,6 +2,10 @@ import { Pipe, PipeTransform } from '@angular/core'; import { NumberFormatPipe } from '@app/shared/pipes/number-format.pipe'; import { NetworkService } from '@app/network/network.service'; import { isNil } from '@app/shared/functions'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { SettingsService } from '@app/settings/settings.service'; +import { u64 } from '@polkadot/types'; +import { TranslateService } from '@ngx-translate/core'; @Pipe({ name: 'amountFormat', @@ -10,13 +14,34 @@ export class AmountFormatPipe extends NumberFormatPipe implements PipeTransform private currencySymbol = this.networkService.currency?.symbol; private powBase = this.networkService.currency?.powBase; private decimals = this.networkService.currency?.decimals; - - constructor(private networkService: NetworkService) { + private udValue: number; + constructor( + private networkService: NetworkService, + private settings: SettingsService, + private translate: TranslateService, + private sanitizer: DomSanitizer + ) { super(); + this.udValue = (networkService.api.consts.universalDividend.unitsPerUd as u64).toNumber(); } - transform(val: number, opts?: Intl.NumberFormatOptions & { fixedDecimals?: number }): string { + transform(val: number, opts?: Intl.NumberFormatOptions & { fixedDecimals?: number; html?: boolean }): SafeHtml { if (isNil(val)) return ''; - return super.transform(val / this.powBase, { fixedDecimals: this.decimals, ...opts }) + (' ' + this.currencySymbol); + switch (this.settings.displayUnit) { + case 'du': { + if (opts?.html === false) { + return ( + super.transform(val / this.udValue / this.powBase, { fixedDecimals: this.decimals, ...opts }) + + ` ${this.translate.instant('COMMON.UD')}(${this.currencySymbol})` + ); + } + return this.sanitizer.bypassSecurityTrustHtml( + super.transform(val / this.udValue / this.powBase, { fixedDecimals: this.decimals, ...opts }) + + ` ${this.translate.instant('COMMON.UD')}<sub>${this.currencySymbol}</sub>` + ); + } + default: + return super.transform(val / this.powBase, { fixedDecimals: this.decimals, ...opts }) + (' ' + this.currencySymbol); + } } } diff --git a/src/app/shared/pipes/block-number.pipe.ts b/src/app/shared/pipes/block-number.pipe.ts index 96f6536bf84454a7218d6060846f0ee5cabcddf3..e2a910482bf7432c73e48ecbe857c45d8b96b7ad 100644 --- a/src/app/shared/pipes/block-number.pipe.ts +++ b/src/app/shared/pipes/block-number.pipe.ts @@ -1,5 +1,6 @@ import { Pipe, PipeTransform } from '@angular/core'; import { IndexerService } from '@app/network/indexer.service'; +import { isNil } from '@app/shared/functions'; @Pipe({ name: 'blockNumber', @@ -8,16 +9,16 @@ export class BlockNumberPipe implements PipeTransform { constructor(private indexer: IndexerService) {} transform(blockNumber: number, suffixV1 = true): string { - if (!blockNumber) return null; + if (isNil(blockNumber)) return null; // Convert V1 block number (cf CRR https://pad.p2p.legal/Visio_2024-04-29) if (blockNumber < 0 && this.indexer.minBlockHeight) { blockNumber = -1 * this.indexer.minBlockHeight + blockNumber; if (suffixV1) { - return `${blockNumber.toLocaleString()} (v1)`; + return `${blockNumber.toString()} (v1)`; } } - return blockNumber.toLocaleString(); + return blockNumber.toString(); } } diff --git a/src/app/shared/pipes/block-timestamp.pipe.ts b/src/app/shared/pipes/block-timestamp.pipe.ts index ce09f80d96dd5c649b028874c950eced1a884828..0465eba94461b52072d9f94f22867a2872e40330 100644 --- a/src/app/shared/pipes/block-timestamp.pipe.ts +++ b/src/app/shared/pipes/block-timestamp.pipe.ts @@ -2,22 +2,39 @@ import { Pipe, PipeTransform } from '@angular/core'; import { Moment } from 'moment'; import { DateUtils } from '@app/shared/dates'; import { NetworkService } from '@app/network/network.service'; +import { isNil } from '@app/shared/functions'; +import { IndexerService } from '@app/network/indexer.service'; @Pipe({ name: 'blockTime', }) export class BlockTimePipe implements PipeTransform { - constructor(private networkService: NetworkService) {} + constructor( + private networkService: NetworkService, + private indexer: IndexerService + ) {} transform(blockNumber: number): Moment { - if (!blockNumber) return null; + if (isNil(blockNumber)) return null; - const blockDate = (this.networkService.currency.startTime as Moment).clone(); - const blockDuration = 6; + const startTime = DateUtils.fromDateISOString(this.networkService.currency.startTime); + + // block V1 + if (blockNumber < 0 && this.indexer.minBlockHeight) { + // FIXME BLA: find a better way to get V1 block time + /*blockNumber = -1 * this.indexer.minBlockHeight + blockNumber; + const blockDuration = 5; + + const duration = DateUtils.toDuration(blockNumber * blockDuration, 'minute'); + return startTime.clone().subtract(duration);*/ - const duration = DateUtils.toDuration(blockNumber * blockDuration, 'seconds'); - blockDate.add(duration); - return blockDate; + return null; + } else { + // TODO: get from network service + const blockDuration = 6; + const duration = DateUtils.toDuration(blockNumber * blockDuration, 'seconds'); + return startTime.clone().add(duration); + } } } diff --git a/src/app/shared/pipes/number-format.pipe.ts b/src/app/shared/pipes/number-format.pipe.ts index 8ce2cc9540072dc51668b17d5f941a9b187ebe64..0c32054d106acb28953c11e92f9e7a1b0ceb127e 100644 --- a/src/app/shared/pipes/number-format.pipe.ts +++ b/src/app/shared/pipes/number-format.pipe.ts @@ -1,10 +1,11 @@ import { Pipe, PipeTransform } from '@angular/core'; +import { SafeHtml } from '@angular/platform-browser'; @Pipe({ name: 'numberFormat', }) export class NumberFormatPipe implements PipeTransform { - transform(val: number, opts?: Intl.NumberFormatOptions & { fixedDecimals?: number }): string { + transform(val: number, opts?: Intl.NumberFormatOptions & { fixedDecimals?: number }): string | SafeHtml { // Format the output to display any way you want here. // For instance: if (val !== undefined && val !== null) { diff --git a/src/app/transfer/history/transfer-history.page.html b/src/app/transfer/history/transfer-history.page.html index 3e269f7539dcacabc498c0e83cea15c46be93e19..d66823d551b1fb3bb571441869b91fd76d0d30ed 100644 --- a/src/app/transfer/history/transfer-history.page.html +++ b/src/app/transfer/history/transfer-history.page.html @@ -47,7 +47,7 @@ <ion-label class="ion-text-end"> <p translate>ACCOUNT.BALANCE</p> <h2> - <b *rxIf="account$; let account">{{ account | balance | amountFormat }}</b> + <b *rxIf="account$; let account" [innerHtml]="account | balance | amountFormat"></b> </h2> </ion-label> </div> @@ -108,7 +108,7 @@ </p> </ion-label> - <ion-badge [color]="item.amount > 0 ? 'secondary' : 'light'" slot="end">{{ item.amount | amountFormat }}</ion-badge> + <ion-badge [color]="item.amount > 0 ? 'secondary' : 'light'" slot="end" [innerHtml]="item.amount | amountFormat"></ion-badge> </ion-item> <!-- loading spinner --> diff --git a/src/app/wot/wot-details.page.html b/src/app/wot/wot-details.page.html index 399cb1b14352a4de28af6ee459d6df48d7bee206..d0c735d5dbe1fe173a4b0eee71aca3c26cf9281b 100644 --- a/src/app/wot/wot-details.page.html +++ b/src/app/wot/wot-details.page.html @@ -27,7 +27,7 @@ <ion-label class="ion-text-end"> <p translate>ACCOUNT.BALANCE</p> <h2 *rxIf="loaded$; else loadingText"> - <b>{{ account$ | push | balance | amountFormat }}</b> + <b [innerHtml]="account$ | push | balance | amountFormat"></b> </h2> <ng-template #loadingText> <p translate>COMMON.LOADING</p> diff --git a/src/environments/environment.class.ts b/src/environments/environment.class.ts index 9621bf2bbd45b397d74d7c36a1f7a28fe778a59b..3e7b41824932984bfa4af1fcd9f6086d319e0022 100644 --- a/src/environments/environment.class.ts +++ b/src/environments/environment.class.ts @@ -36,6 +36,7 @@ export interface Environment { dev?: { // Default peer peer?: string; + indexer?: string; // Load polkadot default account (alice, etc.) testingAccounts?: boolean; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 0e4011296fac40520526ecf659b0ca595fd4be17..49f97e23f36169184492d967e202e314361b0bc6 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -35,6 +35,7 @@ export const environment = <Environment>{ //peer: 'ws://127.0.0.1:9944', peer: 'wss://gdev.coinduf.eu/ws', //peer: 'wss://gdev.cgeek.fr/ws', + indexer: 'https://squid.gdev.coinduf.eu/v1beta1/relay', auth: <AuthData>{ v1: { @@ -61,6 +62,7 @@ export const environment = <Environment>{ defaultIndexers: [ 'https://gdev-squid.axiom-team.fr/v1beta1/relay', + 'https://squid.gdev.coinduf.eu/v1beta1/relay', //'https://gdev-squid.axiom-team.fr/graphql' ], };