diff --git a/android/app/build.gradle b/android/app/build.gradle index 03a99bc41dc61ca0910f23c85d68bb84e8f6bf60..55679eb9bead8a9808f3b2109ad4144b2a484a26 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -13,8 +13,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion compileSdkVersion rootProject.ext.compileSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 2000040 - versionName "2.0.0-alpha40" + versionCode 2000041 + versionName "2.0.0-alpha41" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/electron/package.json b/electron/package.json index 49a5f0acec2b2c4527d4b226689e341e668f14c8..0c00bc51b4842aa869bc215e80645799c7c1237d 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,6 +1,6 @@ { "name": "cesium2s", - "version": "2.0.0-alpha40", + "version": "2.0.0-alpha41", "description": "Cesium², running on Duniter v2s (Substrate).", "author": { "name": "Benoit Lavenier", diff --git a/install.sh b/install.sh index 187b22066c4bc0d5b75a17dc4e36eb61f52cbbd2..065a2833d6c3c1284de1674825275580a560e4ee 100755 --- a/install.sh +++ b/install.sh @@ -14,7 +14,7 @@ INSTALL_DIR=${1:-$(pwd)/${PROJECT_NAME}} INSTALL_ENV=testing latest_version() { - echo "2.0.0-alpha40" #lastest + echo "2.0.0-alpha41" #lastest } api_release_url() { diff --git a/package-lock.json b/package-lock.json index 7aaa57f97844f92d4001ee2177db12a0d709c24d..55b3a68194c4ec9f4c9c61c950aed63be814ac9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cesium", - "version": "2.0.0-alpha38", + "version": "2.0.0-alpha40", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cesium", - "version": "2.0.0-alpha38", + "version": "2.0.0-alpha40", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.5", diff --git a/package.json b/package.json index 2d804ba8d3523f9c8a4e09afbe30b006efbf17fd..c85c93a858ca74d72e5d875372c26a9666670979 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cesium", - "version": "2.0.0-alpha40", + "version": "2.0.0-alpha41", "description": "Manage G1 wallet", "author": "Benoit Lavenier <benoit.lavenier@e-is.pro>", "homepage": "https://cesium.app", @@ -196,7 +196,7 @@ "shelljs": "~0.8.5", "stdio": "^2.1.3", "ts-node": "^8.10.2", - "typescript": "~5.2.2" + "typescript": "~5.4.5" }, "engines": { "node": ">= 18.18.2", diff --git a/resources/webext/manifest.json b/resources/webext/manifest.json index 2fe51a67a78073865c08e0c7524ba8b5b1a9589c..ffa142a0474b58b73eb243c127f0f8541b4f59aa 100644 --- a/resources/webext/manifest.json +++ b/resources/webext/manifest.json @@ -1,8 +1,8 @@ { "manifest_version": 2, "name": "cesium2s", - "version": "2.0.0.40", - "version_name": "2.0.0-alpha40", + "version": "2.0.0.41", + "version_name": "2.0.0-alpha41", "short_name": "Cesium²", "description": "Manage G1 wallet", "author": "Benoit Lavenier <benoit.lavenier@e-is.pro>", diff --git a/src/app/account/accounts.service.ts b/src/app/account/accounts.service.ts index cc840a14fae497fd55b6fd080f964b2a82a3db60..441412fee193bf43b9ad8e68750c0996e10e55a2 100644 --- a/src/app/account/accounts.service.ts +++ b/src/app/account/accounts.service.ts @@ -32,6 +32,17 @@ import { IndexerService } from '@app/network/indexer/indexer.service'; import { AppEvent } from '@app/shared/types'; import { APP_AUTH_CONTROLLER, AuthData, IAuthController } from '@app/account/auth/auth.model'; import { ExtrinsicError, ExtrinsicUtils } from '@app/shared/substrate/extrinsic.utils'; +import { IdentityStatusEnum } from '@app/network/indexer/indexer-types.generated'; + +// kind of certify action +enum CertType { + // first certification is actually an identity creation + IdentityCreation, + // normal cert creation + CertCreation, + // cert renewal + CertRenewal, +} export interface LoadAccountDataOptions { reload?: boolean; @@ -528,7 +539,6 @@ export class AccountsService extends RxStartableService<AccountsState> { try { // Sign and send a transfer from Alice to Bob - console.log(Object.keys(this.api.tx)); const txHash = await this.api.tx.balances.transferKeepAlive(to.address, amount).signAndSend(issuerPair, async ({ status, events }) => { if (status.isInBlock) { console.info(`${this._logPrefix}Extrinsic status`, status.toHuman()); @@ -568,9 +578,9 @@ export class AccountsService extends RxStartableService<AccountsState> { * @param from * @param to */ - async cert(from: Partial<Account>, to: Partial<Account>): Promise<string> { + async cert(from: Partial<Account>, to: Partial<Account>, opts = { allowCreation: true, confirmBeforeCreation: true }): Promise<string> { if (!from || !to) throw new Error("Missing argument 'from' or 'to' !"); - if (isNil(to.meta?.index)) throw new Error("Missing argument 'to.meta.index' !"); + if (isNil(to.meta)) throw new Error("Missing 'to.meta' argument"); // Check currency const currency = this.network.currency; @@ -582,7 +592,7 @@ export class AccountsService extends RxStartableService<AccountsState> { } // Get issuer account - const issuerAccount = await this.getByAddress(from.address); + const issuerAccount = await this.getByAddress(from.address, { withMembership: true }); // Check enough credit const fee = currency.fees.cert; @@ -595,16 +605,62 @@ export class AccountsService extends RxStartableService<AccountsState> { // Get pair, and unlock it const issuerPair = keyring.getPair(issuerAccount.address); if (issuerPair.isLocked) { - console.debug(`[account-service] Unlocking address ${from.address} ...`); + console.debug(`${this._logPrefix}Unlocking address ${from.address} ...`); const isAuth = await this.auth(); if (!isAuth) throw new Error('ERROR.AUTH_REQUIRED'); issuerPair.unlock(this._password); } + // Detect certification type + let certType: CertType = null; + if (isNil(to.meta?.status) || isNil(to.meta?.index)) { + if (opts.allowCreation === false) throw new Error('ERROR.SEND_TX_FAILED'); + + if (opts?.confirmBeforeCreation !== false) { + // TODO ask user confirmation to create identity ? + } + + console.debug(this._logPrefix + 'Target identity not exists: creating...'); + certType = CertType.IdentityCreation; + } else { + // check if target has identity index (identity already created) + switch (to.meta.status) { + case IdentityStatusEnum.Revoked: + console.log('can not certify revoked identity'); + break; + case IdentityStatusEnum.Unconfirmed: + console.log('can not certify unconfirmed identity'); + break; + case IdentityStatusEnum.Unvalidated: + // TODO special case for last certification: request distance evaluation + break; + case IdentityStatusEnum.Notmember: + // TODO prevent certifying if lost membership for membership non renewal + break; + default: + // ok to certify + // TODO check if certification already exists (renewal) + certType = CertType.CertCreation; + break; + } + } + await this.ready(); try { - const { status } = await ExtrinsicUtils.submit(this.api.tx.certification.addCert(to.meta?.index), issuerPair); + let tx = null; + switch (certType) { + case CertType.IdentityCreation: + tx = this.api.tx.identity.createIdentity(to.address); + break; + case CertType.CertCreation: + tx = this.api.tx.certification.addCert(to.meta.index); + break; + case CertType.CertRenewal: + tx = this.api.tx.certification.renewCert(to.meta.index); + break; + } + const status = (await ExtrinsicUtils.submit(tx, issuerPair)).status; console.info(`${this._logPrefix}Extrinsic status`, status.toHuman()); console.info(`${this._logPrefix}Certifying completed at block hash #${status.hash.toHuman()}`); @@ -659,6 +715,7 @@ export class AccountsService extends RxStartableService<AccountsState> { account.meta = { ...account.meta, uid: indexedAccount.meta?.uid, + index: indexedAccount.meta?.index, isMember: indexedAccount.meta?.isMember, status: indexedAccount.meta?.status, createdOn: indexedAccount.meta?.createdOn, diff --git a/src/app/account/wallet/wallet.page.html b/src/app/account/wallet/wallet.page.html index a5a37ef459053e1b3a0b9c5707fe408c0880e70c..53128d3b1eaf536ff365a1a32e7eee15fe9114fa 100644 --- a/src/app/account/wallet/wallet.page.html +++ b/src/app/account/wallet/wallet.page.html @@ -117,8 +117,8 @@ </ion-button> </ion-item> - @if (account.meta?.uid) { - <!-- UID --> + <!-- UID --> + @if (account.meta?.index) { <ion-item> <ion-icon aria-hidden="true" slot="start" name="calendar-clear-outline"></ion-icon> <ion-label> diff --git a/src/app/account/wallet/wallet.page.ts b/src/app/account/wallet/wallet.page.ts index 4a6ce6900e831615a213613e7d0e059dc819aed9..2e0f39f9709a9bc7048a4025098605976fe49838 100644 --- a/src/app/account/wallet/wallet.page.ts +++ b/src/app/account/wallet/wallet.page.ts @@ -106,23 +106,29 @@ export class WalletPage extends AppPage<WalletState> implements OnInit { 'account', this._state.$.pipe( filter((s) => isNotEmptyArray(s.accounts) && isNil(s.account) && isNotNilOrBlank(s.address)), + // TODO find a way to avoid multiple call, on address='default' + //distinctUntilKeyChanged('address'), mergeMap(async (s) => { console.debug(this._logPrefix + 'Loading account from address: ' + s.address); let account: Account; if (s.address === 'default') { - account = await this.accountService.getDefault(); + account = await this.accountService.getDefault({ withMembership: true }); + console.debug(this._logPrefix + 'Loaded account by default', account); return account; } // Load by address const exists = await this.accountService.isAvailable(s.address); if (exists) { - return this.accountService.getByAddress(s.address); + account = await this.accountService.getByAddress(s.address, { withMembership: true }); + console.debug(this._logPrefix + 'Loaded account by address', account); + return account; } // Try by name - account = await this.accountService.getByName(s.address); + account = await this.accountService.getByName(s.address, { withMembership: true }); + console.debug(this._logPrefix + 'Loaded account by name', account); return account; }) ) diff --git a/src/app/network/indexer/indexer-block.gql b/src/app/network/indexer/indexer-block.gql index 63f2a82caaca499c603e0415738e5c3eb16215a1..ad8e4e34ae3434a1a744d222990bea3ad6187d8f 100644 --- a/src/app/network/indexer/indexer-block.gql +++ b/src/app/network/indexer/indexer-block.gql @@ -31,3 +31,9 @@ query Blocks($where: BlockBoolExp, $first: Int!, $after: String, $orderBy: [Bloc ...LightBlockConnection } } + +query LastBlock { + blockConnection(first: 1, orderBy: { height: DESC }) { + ...LightBlockConnection + } +} diff --git a/src/app/wot/wot-details.page.html b/src/app/wot/wot-details.page.html index d0c735d5dbe1fe173a4b0eee71aca3c26cf9281b..cd7b8a9ce2265f0ae78bd48e0afa0c5c0f0b72c6 100644 --- a/src/app/wot/wot-details.page.html +++ b/src/app/wot/wot-details.page.html @@ -88,7 +88,7 @@ </ion-item> <!-- UID --> - @if (account.meta?.uid) { + @if (account.meta?.index) { <ion-item> <ion-icon aria-hidden="true" slot="start" name="calendar-clear-outline"></ion-icon> <ion-label> diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index a91d3220d21a05fe941a469e39924592833526f4..a484450d94fd753e925cef630101b9a1607aa4c2 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -4,6 +4,7 @@ "APP_VERSION": "v{{version}}", "APP_BUILD": "build {{build}}", "PUBKEY": "Public key", + "ADDRESS": "SS58 Address", "MEMBER": "Member", "BLOCK": "Block", "BTN_OK": "OK", diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 7b72aa070c0fbb7eed114f044212a8e992deaa0d..be0ed973300aec30d99c9a3ce57329f7269493b0 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -65,9 +65,9 @@ export const environment = <Environment>{ /* Local endpoint */ //'http://localhost:8080/v1/graphql', /* GDev endpoints */ - 'https://gdev-squid.axiom-team.fr/v1beta1/relay', 'https://squid.gdev.coinduf.eu/v1beta1/relay', //'https://gdev-squid.axiom-team.fr/graphql' + // 'https://gdev-squid.axiom-team.fr/v1beta1/relay', ], defaultPods: [ diff --git a/src/interfaces/augment-api-consts.ts b/src/interfaces/augment-api-consts.ts index 3c614617f99470889a81dbb2db85440d7ed94982..4859308d658f9874a74e728553a76944ca921160 100644 --- a/src/interfaces/augment-api-consts.ts +++ b/src/interfaces/augment-api-consts.ts @@ -9,6 +9,7 @@ import type { ApiTypes, AugmentedConst } from '@polkadot/api-base/types'; import type { Option, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { Codec } from '@polkadot/types-codec/types'; import type { AccountId32, Perbill, Permill } from '@polkadot/types/interfaces/runtime'; +import { SpWeightsWeightV2Weight, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpWeightsRuntimeDbWeight, SpVersionRuntimeVersion, FrameSupportPalletId } from '@polkadot/types/lookup'; export type __AugmentedConst<ApiType extends ApiTypes> = AugmentedConst<ApiType>; diff --git a/src/interfaces/augment-api-events.ts b/src/interfaces/augment-api-events.ts index 0ce0746229683bd813c9ad5ad02d84aa41bafccb..c6852451d43366c2de1d1b04219edc68feeae4a8 100644 --- a/src/interfaces/augment-api-events.ts +++ b/src/interfaces/augment-api-events.ts @@ -9,6 +9,7 @@ import type { ApiTypes, AugmentedEvent } from '@polkadot/api-base/types'; import type { Bytes, Null, Option, Result, U8aFixed, Vec, bool, u16, u32, u64 } from '@polkadot/types-codec'; import type { ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, H256 } from '@polkadot/types/interfaces/runtime'; +import { PalletAtomicSwapPendingSwap, FrameSupportTokensMiscBalanceStatus, SpConsensusGrandpaAppPublic, PalletIdentityRemovalReason, PalletIdentityRevocationReason, PalletImOnlineSr25519AppSr25519Public, CommonRuntimeEntitiesValidatorFullIdentification, PalletMembershipMembershipRemovalReason, PalletMultisigTimepoint, SpRuntimeDispatchError, PalletProvideRandomnessRandomnessType, GdevRuntimeProxyType, FrameSupportDispatchDispatchInfo } from '@polkadot/types/lookup'; export type __AugmentedEvent<ApiType extends ApiTypes> = AugmentedEvent<ApiType>; diff --git a/src/interfaces/augment-api-query.ts b/src/interfaces/augment-api-query.ts index 51912425e67e01f58e8a5158670c9e4e9538c93e..f26dfe00a926996a08ecc9c224b3072f33506fba 100644 --- a/src/interfaces/augment-api-query.ts +++ b/src/interfaces/augment-api-query.ts @@ -10,6 +10,7 @@ import type { Bytes, Null, Option, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 import type { AnyNumber, ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, Call, H256 } from '@polkadot/types/interfaces/runtime'; import type { Observable } from '@polkadot/types/types'; +import { PalletAtomicSwapPendingSwap, SpAuthorityDiscoveryAppPublic, PalletAuthorityMembersMemberData, SpConsensusBabeAppPublic, SpConsensusBabeBabeEpochConfiguration, SpConsensusBabeDigestsPreDigest, SpConsensusBabeDigestsNextConfigDescriptor, PalletBalancesAccountData, PalletBalancesIdAmount, PalletBalancesBalanceLock, PalletBalancesReserveData, PalletCertificationIdtyCertMeta, PalletDistanceEvaluationPool, SpConsensusGrandpaAppPublic, PalletGrandpaStoredPendingChange, PalletGrandpaStoredState, PalletIdentityIdtyValue, PalletImOnlineSr25519AppSr25519Public, SpMembershipMembershipData, PalletMultisigMultisig, SpStakingOffenceOffenceDetails, PalletDuniterTestParametersParameters, PalletPreimageRequestStatus, PalletPreimageOldRequestStatus, PalletProvideRandomnessRequest, PalletProxyAnnouncement, PalletProxyProxyDefinition, PalletQuotaQuota, PalletQuotaRefund, PalletSchedulerScheduled, SpCoreCryptoKeyTypeId, GdevRuntimeOpaqueSessionKeys, PalletSmithMembersSmithMeta, FrameSystemAccountInfo, FrameSystemCodeUpgradeAuthorization, FrameSupportDispatchPerDispatchClassWeight, SpRuntimeDigest, FrameSystemEventRecord, FrameSystemPhase, FrameSystemLastRuntimeUpgradeInfo, PalletCollectiveVotes, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletTreasurySpendStatus } from '@polkadot/types/lookup'; export type __AugmentedQuery<ApiType extends ApiTypes> = AugmentedQuery<ApiType, () => unknown>; export type __QueryableStorageEntry<ApiType extends ApiTypes> = QueryableStorageEntry<ApiType>; diff --git a/src/interfaces/augment-api-tx.ts b/src/interfaces/augment-api-tx.ts index 4e5968b755940306aadf0b8761764fca042e0bdd..ad1d642b9eddd2a1fa23586c69893f9776add723 100644 --- a/src/interfaces/augment-api-tx.ts +++ b/src/interfaces/augment-api-tx.ts @@ -9,6 +9,7 @@ import type { ApiTypes, AugmentedSubmittable, SubmittableExtrinsic, SubmittableE import type { Bytes, Compact, Null, Option, U8aFixed, Vec, bool, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { AnyNumber, IMethod, ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, Call, H256, MultiAddress } from '@polkadot/types/interfaces/runtime'; +import { PalletAtomicSwapBalanceSwapAction, GdevRuntimeOpaqueSessionKeys, SpConsensusBabeDigestsNextConfigDescriptor, SpConsensusSlotsEquivocationProof, SpSessionMembershipProof, SpDistanceComputationResult, SpConsensusGrandpaEquivocationProof, SpRuntimeMultiSignature, PalletImOnlineHeartbeat, PalletImOnlineSr25519AppSr25519Signature, PalletMultisigTimepoint, SpWeightsWeightV2Weight, PalletOneshotAccountAccount, PalletProvideRandomnessRandomnessType, GdevRuntimeProxyType, GdevRuntimeOriginCaller } from '@polkadot/types/lookup'; export type __AugmentedSubmittable = AugmentedSubmittable<() => unknown>; export type __SubmittableExtrinsic<ApiType extends ApiTypes> = SubmittableExtrinsic<ApiType>; diff --git a/src/interfaces/augment-api.ts b/src/interfaces/augment-api.ts index 53c9c7701712e9820e6e0f5d2f0af83167c8e9dd..7cafd228bdb509a26dd817b7dec4bcb832ca9790 100644 --- a/src/interfaces/augment-api.ts +++ b/src/interfaces/augment-api.ts @@ -1,10 +1,10 @@ // Auto-generated via `yarn polkadot-types-from-chain`, do not edit /* eslint-disable */ -import './augment-api-consts.js'; -import './augment-api-errors.js'; -import './augment-api-events.js'; -import './augment-api-query.js'; -import './augment-api-tx.js'; -import './augment-api-rpc.js'; -import './augment-api-runtime.js'; +import './augment-api-consts'; +import './augment-api-errors'; +import './augment-api-events'; +import './augment-api-query'; +import './augment-api-tx'; +import './augment-api-rpc'; +import './augment-api-runtime'; diff --git a/src/interfaces/types.ts b/src/interfaces/types.ts index dfecb1f8d957ef3e9b28f4d2ee72b5aef82d1e84..6d635c7bd2518f7779cd8970965baae50eed9845 100644 --- a/src/interfaces/types.ts +++ b/src/interfaces/types.ts @@ -1,3 +1,5 @@ // Auto-generated via `yarn polkadot-types-from-defs`, do not edit /* eslint-disable */ +// hack to get detected as a module +export const HACK = 'HACK' \ No newline at end of file diff --git a/src/manifest.json b/src/manifest.json index daf6d7fd13fa6f7b6115e8775d09c8bdb34690bb..a3ef3272675f80add0293f65ff4054c39b7cadc1 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -2,7 +2,7 @@ "short_name": "Cesium", "name": "Cesium2", "manifest_version": 2, - "version": "2.0.0-alpha40", + "version": "2.0.0-alpha41", "default_locale": "fr", "description": "Cesium Wallet for Ğ1 libre currency", "icons": [ diff --git a/src/polyfills.ts b/src/polyfills.ts index d74918a1a2c542abfead545fe3475cd93aca9021..af27ea39d82f2303a3fff4e8fdd383e6999af7f9 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -60,7 +60,9 @@ if ((window as any).__Zone_disable_ZoneAwarePromise === true) { * APPLICATION IMPORTS */ // Polkadot API augment -import '@polkadot/api-augment'; +// import '@polkadot/api-augment'; +import '@polkadot/api/augment'; +import '@polkadot/types/lookup'; // eslint-disable-next-line @typescript-eslint/no-explicit-any (window as any).global = window; diff --git a/tsconfig.json b/tsconfig.json index 4549e30f0bc482b65f3caa01473b59f5fed63af7..4f19daadafb4545aef067f58c7494eb7f178cf2e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,7 @@ "module": "es2020", "lib": ["es2020","dom"], "allowSyntheticDefaultImports": true, + "skipLibCheck": true, "typeRoots": [ "node_modules/@types" ], @@ -29,13 +30,12 @@ "rxjs/*": ["node_modules/rxjs/*"], // Local types - "@duniter/interfaces": ["src/interfaces/types-lookup.ts"], + "@polkadot/types/lookup": ["src/interfaces/types-lookup.ts"], // here we replace the @polkadot/api augmentation with our own, generated from chain "@polkadot/api/augment": ["src/interfaces/augment-api.ts"], // replace the augmented types with our own, as generated from definitions "@polkadot/types/augment": ["src/interfaces/augment-types.ts"], - "@polkadot/types": ["./node_modules/@polkadot/types"], // Node JS lib "stream": ["node_modules/stream-browserify"],