diff --git a/packages/extension-base/package.json b/packages/extension-base/package.json index a117a487fb..741c5acfe5 100644 --- a/packages/extension-base/package.json +++ b/packages/extension-base/package.json @@ -71,6 +71,7 @@ "browser-passworder": "^2.0.3", "buffer": "^6.0.3", "cross-fetch": "^3.1.5", + "dedot": "0.0.1-alpha.36", "dexie": "^3.2.2", "dexie-export-import": "^4.0.7", "eth-simple-keyring": "^4.2.0", diff --git a/packages/extension-base/src/services/chain-service/handler/SubstrateApi.ts b/packages/extension-base/src/services/chain-service/handler/SubstrateApi.ts index 219f78b7ac..0950a113e4 100644 --- a/packages/extension-base/src/services/chain-service/handler/SubstrateApi.ts +++ b/packages/extension-base/src/services/chain-service/handler/SubstrateApi.ts @@ -1,8 +1,6 @@ // Copyright 2019-2022 @subwallet/extension-base authors & contributors // SPDX-License-Identifier: Apache-2.0 -import '@polkadot/types-augment'; - import { options as acalaOptions } from '@acala-network/api'; import { GearApi } from '@gear-js/api'; import { rpc as oakRpc, types as oakTypes } from '@oak-foundation/types'; @@ -10,10 +8,11 @@ import { MetadataItem } from '@subwallet/extension-base/background/KoniTypes'; import { _API_OPTIONS_CHAIN_GROUP, API_AUTO_CONNECT_MS, API_CONNECT_TIMEOUT } from '@subwallet/extension-base/services/chain-service/constants'; import { getSubstrateConnectProvider } from '@subwallet/extension-base/services/chain-service/handler/light-client'; import { DEFAULT_AUX } from '@subwallet/extension-base/services/chain-service/handler/SubstrateChainHandler'; -import { _ApiOptions } from '@subwallet/extension-base/services/chain-service/handler/types'; +import { _ApiOptions, _SubstrateApiMode } from '@subwallet/extension-base/services/chain-service/handler/types'; import { _ChainConnectionStatus, _SubstrateApi, _SubstrateDefaultFormatBalance } from '@subwallet/extension-base/services/chain-service/types'; import { createPromiseHandler, PromiseHandler } from '@subwallet/extension-base/utils/promise'; import { goldbergRpc, goldbergTypes, spec as availSpec } from 'avail-js-sdk'; +import { DedotClient, WsProvider as DedotWsProvider } from 'dedot'; import { BehaviorSubject } from 'rxjs'; import { ApiPromise, WsProvider } from '@polkadot/api'; @@ -28,7 +27,7 @@ import { defaults as addressDefaults } from '@polkadot/util-crypto/address/defau export class SubstrateApi implements _SubstrateApi { chainSlug: string; - api: ApiPromise; + _api: ApiPromise | DedotClient; providerName?: string; provider: ProviderInterface; apiUrl: string; @@ -41,6 +40,11 @@ export class SubstrateApi implements _SubstrateApi { private handleApiReady: PromiseHandler<_SubstrateApi>; public readonly isApiConnectedSubject = new BehaviorSubject(false); public readonly connectionStatusSubject = new BehaviorSubject(_ChainConnectionStatus.DISCONNECTED); + + get api (): ApiPromise { + return this._api as ApiPromise; + } + get isApiConnected (): boolean { return this.isApiConnectedSubject.getValue(); } @@ -86,7 +90,7 @@ export class SubstrateApi implements _SubstrateApi { } } - private createApi (provider: ProviderInterface, externalApiPromise?: ApiPromise): ApiPromise { + private createApiPromise (provider: ProviderInterface, externalApiPromise?: ApiPromise): ApiPromise { const apiOption: ApiOptions = { provider, typesBundle, @@ -150,14 +154,41 @@ export class SubstrateApi implements _SubstrateApi { return api; } - constructor (chainSlug: string, apiUrl: string, { externalApiPromise, metadata, providerName }: _ApiOptions = {}) { + private createDedotClient (providerUrl: string): DedotClient { + const wsProvider = new DedotWsProvider(providerUrl); + const dedot = new DedotClient(wsProvider); + + dedot.on('ready', this.onReady.bind(this)); + dedot.on('connected', this.onConnect.bind(this)); + dedot.on('disconnected', this.onDisconnect.bind(this)); + dedot.on('error', this.onError.bind(this)); + + return dedot; + } + + private createApiByMode (mode: _SubstrateApiMode, apiUrl: string, externalApiPromise?: ApiPromise) { + switch (mode) { + case _SubstrateApiMode.DEDOT: { + this._api = this.createDedotClient(apiUrl); + + break; + } + + default: { + this.provider = this.createProvider(apiUrl); + this._api = this.createApiPromise(this.provider, externalApiPromise); + } + } + } + + constructor (chainSlug: string, apiUrl: string, { externalApiPromise, metadata, mode, providerName }: _ApiOptions = {}) { this.chainSlug = chainSlug; this.apiUrl = apiUrl; this.providerName = providerName; this.registry = new TypeRegistry(); this.metadata = metadata; this.provider = this.createProvider(apiUrl); - this.api = this.createApi(this.provider, externalApiPromise); + this._api = this.createApiPromise(this.provider, externalApiPromise); this.handleApiReady = createPromiseHandler<_SubstrateApi>(); } @@ -182,7 +213,7 @@ export class SubstrateApi implements _SubstrateApi { // Create new provider and api this.apiUrl = apiUrl; this.provider = this.createProvider(apiUrl); - this.api = this.createApi(this.provider); + this._api = this.createApiPromise(this.provider); } connect (): void { diff --git a/packages/extension-base/src/services/chain-service/handler/types.ts b/packages/extension-base/src/services/chain-service/handler/types.ts index 8f95d2b622..0d76d53f8b 100644 --- a/packages/extension-base/src/services/chain-service/handler/types.ts +++ b/packages/extension-base/src/services/chain-service/handler/types.ts @@ -28,7 +28,14 @@ export interface _ApiOptions { providerName?: string, metadata?: MetadataItem, onUpdateStatus?: (status: _ChainConnectionStatus) => void, - externalApiPromise?: ApiPromise + externalApiPromise?: ApiPromise, + mode?: _SubstrateApiMode +} + +export enum _SubstrateApiMode { + POLKADOT_JS = 'POLKADOT_JS', + DEDOT = 'DEDOT', + PAPI = 'PAPI' } export enum _CHAIN_VALIDATION_ERROR { diff --git a/packages/extension-base/src/services/chain-service/types.ts b/packages/extension-base/src/services/chain-service/types.ts index 2ea0def934..ac9d799dae 100644 --- a/packages/extension-base/src/services/chain-service/types.ts +++ b/packages/extension-base/src/services/chain-service/types.ts @@ -5,6 +5,7 @@ import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _CrowdloanFund } from '@subwallet/chain-list/types'; import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chain-service/handler/types'; +import { DedotClient } from 'dedot'; import { BehaviorSubject } from 'rxjs'; import Web3 from 'web3'; @@ -81,6 +82,7 @@ export interface _SubstrateApiState { } export interface _SubstrateApi extends _SubstrateApiState, _ChainBaseApi { + _api: ApiPromise | DedotClient; api: ApiPromise; isReady: Promise<_SubstrateApi>; diff --git a/yarn.lock b/yarn.lock index 11dce506db..4a1d22efc9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1882,6 +1882,136 @@ __metadata: languageName: node linkType: hard +"@dedot/api@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/api@npm:0.0.1-alpha.36" + dependencies: + "@dedot/codecs": 0.0.1-alpha.36 + "@dedot/providers": 0.0.1-alpha.36 + "@dedot/runtime-specs": 0.0.1-alpha.36 + "@dedot/shape": 0.0.1-alpha.36 + "@dedot/storage": 0.0.1-alpha.36 + "@dedot/types": 0.0.1-alpha.36 + "@dedot/utils": 0.0.1-alpha.36 + checksum: fe5fae1576aa1a19c3f5bf22ad810b71f4e77594abff8135224deaa539f834b692ba7ee1cc5d2886970c044d016fc2e9d500e037c9d7688dc664c33b368dd3cc + languageName: node + linkType: hard + +"@dedot/cli@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/cli@npm:0.0.1-alpha.36" + dependencies: + "@dedot/api": 0.0.1-alpha.36 + "@dedot/codecs": 0.0.1-alpha.36 + "@dedot/codegen": 0.0.1-alpha.36 + "@polkadot/types-support": ^12.0.1 + yargs: ^17.7.2 + bin: + dedot: bin/dedot + djs: bin/dedot + checksum: e1c4f1b90f232efcb923fa7e22f2fdb0a58c7e41932b13ed476a1743b80300e4f598a4ff8250f55ab298a2e98d69852a0e5769857b1cb0db9c18fc060e1ca72c + languageName: node + linkType: hard + +"@dedot/codecs@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/codecs@npm:0.0.1-alpha.36" + dependencies: + "@dedot/shape": 0.0.1-alpha.36 + "@dedot/utils": 0.0.1-alpha.36 + checksum: f408d324cbd7ea23f284e10e0c42b355acbdcaca29b612c73b82de3fe5d876be4c60bea5011f118874dee3f7dd3e1645fce2ef23553bafc77f193c4fc5417e1f + languageName: node + linkType: hard + +"@dedot/codegen@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/codegen@npm:0.0.1-alpha.36" + dependencies: + "@dedot/api": 0.0.1-alpha.36 + "@dedot/codecs": 0.0.1-alpha.36 + "@dedot/providers": 0.0.1-alpha.36 + "@dedot/runtime-specs": 0.0.1-alpha.36 + "@dedot/shape": 0.0.1-alpha.36 + "@dedot/types": 0.0.1-alpha.36 + "@dedot/utils": 0.0.1-alpha.36 + handlebars: ^4.7.8 + prettier: ^3.3.2 + checksum: d0bffe2481bcf1254e3524affaea1c0d6aee90cf64a68d91fd6f31dbbd0bd3e2661e562821605bf250dcd6e4b868047ff5e7a427ad3052368f3cef823b718c5d + languageName: node + linkType: hard + +"@dedot/contracts@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/contracts@npm:0.0.1-alpha.36" + dependencies: + "@dedot/api": 0.0.1-alpha.36 + "@dedot/codecs": 0.0.1-alpha.36 + "@dedot/types": 0.0.1-alpha.36 + "@dedot/utils": 0.0.1-alpha.36 + checksum: 36840222ee01ab88f9b41853e833b8721348adf05885c33bc34b9c98c1229810fa9fbcfa14b8a0b1790882b83e7156bf3e1f4f0d789caa74285c4e55882c9147 + languageName: node + linkType: hard + +"@dedot/providers@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/providers@npm:0.0.1-alpha.36" + dependencies: + "@dedot/utils": 0.0.1-alpha.36 + "@polkadot/x-ws": ^12.6.2 + checksum: 881739ed84a6460c28c268888f25bbfe89c8a4027bb8eaeca8ac94216506261a5d381aa7bbe96e0927e88b03d95fabc1cdd0ea6a94a7be234234ee7b761b93de + languageName: node + linkType: hard + +"@dedot/runtime-specs@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/runtime-specs@npm:0.0.1-alpha.36" + dependencies: + "@dedot/codecs": 0.0.1-alpha.36 + "@dedot/shape": 0.0.1-alpha.36 + "@dedot/types": 0.0.1-alpha.36 + checksum: 07e8823976a87e066232ee9ed863e0a039e04101a94ea492ef49d3c2db3441178119b60945850c3b19cfb44846644e295b3bd7e89fb35e3cc446ea57f9e346bd + languageName: node + linkType: hard + +"@dedot/shape@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/shape@npm:0.0.1-alpha.36" + dependencies: + "@dedot/utils": 0.0.1-alpha.36 + subshape: ^0.14.0 + checksum: 1407eb09d8be56281abb53bf6e028ee7618d258868c4341b7d1bd343c8e589c8db703eed609eda0bd262ffc1db70126e58a9e0caedf2b7a1de58dfb0996dcf8d + languageName: node + linkType: hard + +"@dedot/storage@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/storage@npm:0.0.1-alpha.36" + checksum: fe7411cd836f5879a104a662d530f5d4fa77f792d7a46ae9919c02bed07f13adc6af4d047233694af7f7723c2aed72f57ed89d9a5ed397cdb3803ea89a3efa62 + languageName: node + linkType: hard + +"@dedot/types@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/types@npm:0.0.1-alpha.36" + dependencies: + "@dedot/codecs": 0.0.1-alpha.36 + "@dedot/shape": 0.0.1-alpha.36 + "@dedot/utils": 0.0.1-alpha.36 + checksum: a31e33360fdbc20dfc313d452a8be3e0630fdd40e9d621e6be2f31dc39f9c35f1a7d38bd035fd5479c038c074d4e6353d7ad94a8f5a9582706be6096e139b5af + languageName: node + linkType: hard + +"@dedot/utils@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "@dedot/utils@npm:0.0.1-alpha.36" + dependencies: + "@noble/hashes": ^1.4.0 + "@scure/base": ^1.1.7 + eventemitter3: ^5.0.1 + checksum: 5caba2a981df484a3b853557800490336159053c83ccfcdcdd7631ba4d7fece41b6f9fbf9bf9e1426e6c9b5e6c2ecc51d383566892723955790fafd7c33a44fa + languageName: node + linkType: hard + "@digitalnative/type-definitions@npm:1.1.27": version: 1.1.27 resolution: "@digitalnative/type-definitions@npm:1.1.27" @@ -3739,7 +3869,7 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:^1.3.1": +"@noble/hashes@npm:^1.3.1, @noble/hashes@npm:^1.4.0": version: 1.4.0 resolution: "@noble/hashes@npm:1.4.0" checksum: 8ba816ae26c90764b8c42493eea383716396096c5f7ba6bea559993194f49d80a73c081f315f4c367e51bd2d5891700bcdfa816b421d24ab45b41cb03e4f3342 @@ -5572,6 +5702,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:^1.1.7": + version: 1.1.7 + resolution: "@scure/base@npm:1.1.7" + checksum: d9084be9a2f27971df1684af9e40bb750e86f549345e1bb3227fb61673c0c83569c92c1cb0a4ddccb32650b39d3cd3c145603b926ba751c9bc60c27317549b20 + languageName: node + linkType: hard + "@scure/bip32@npm:1.3.3": version: 1.3.3 resolution: "@scure/bip32@npm:1.3.3" @@ -6034,6 +6171,7 @@ __metadata: browser-passworder: ^2.0.3 buffer: ^6.0.3 cross-fetch: ^3.1.5 + dedot: 0.0.1-alpha.36 dexie: ^3.2.2 dexie-export-import: ^4.0.7 eth-simple-keyring: ^4.2.0 @@ -12278,6 +12416,26 @@ __metadata: languageName: node linkType: hard +"dedot@npm:0.0.1-alpha.36": + version: 0.0.1-alpha.36 + resolution: "dedot@npm:0.0.1-alpha.36" + dependencies: + "@dedot/api": 0.0.1-alpha.36 + "@dedot/cli": 0.0.1-alpha.36 + "@dedot/codecs": 0.0.1-alpha.36 + "@dedot/contracts": 0.0.1-alpha.36 + "@dedot/providers": 0.0.1-alpha.36 + "@dedot/runtime-specs": 0.0.1-alpha.36 + "@dedot/shape": 0.0.1-alpha.36 + "@dedot/types": 0.0.1-alpha.36 + "@dedot/utils": 0.0.1-alpha.36 + bin: + dedot: bin/dedot + djs: bin/dedot + checksum: 5c0c966de82833d0f3d80633507af6efdf1242dd12f54d070d5d146b668538b4e713981e6438e6c9bff8cec0a1d721b47e96eb8f49e194d44c47b525a0426616 + languageName: node + linkType: hard + "deep-extend@npm:^0.6.0": version: 0.6.0 resolution: "deep-extend@npm:0.6.0" @@ -15590,6 +15748,24 @@ __metadata: languageName: node linkType: hard +"handlebars@npm:^4.7.8": + version: 4.7.8 + resolution: "handlebars@npm:4.7.8" + dependencies: + minimist: ^1.2.5 + neo-async: ^2.6.2 + source-map: ^0.6.1 + uglify-js: ^3.1.4 + wordwrap: ^1.0.0 + dependenciesMeta: + uglify-js: + optional: true + bin: + handlebars: bin/handlebars + checksum: 00e68bb5c183fd7b8b63322e6234b5ac8fbb960d712cb3f25587d559c2951d9642df83c04a1172c918c41bcfc81bfbd7a7718bbce93b893e0135fc99edea93ff + languageName: node + linkType: hard + "har-schema@npm:^2.0.0": version: 2.0.0 resolution: "har-schema@npm:2.0.0" @@ -22199,6 +22375,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:^3.3.2": + version: 3.3.2 + resolution: "prettier@npm:3.3.2" + bin: + prettier: bin/prettier.cjs + checksum: 5557d8caed0b182f68123c2e1e370ef105251d1dd75800fadaece3d061daf96b1389141634febf776050f9d732c7ae8fd444ff0b4a61b20535e7610552f32c69 + languageName: node + linkType: hard + "pretty-error@npm:^4.0.0": version: 4.0.0 resolution: "pretty-error@npm:4.0.0" @@ -25791,6 +25976,13 @@ __metadata: languageName: node linkType: hard +"subshape@npm:^0.14.0": + version: 0.14.0 + resolution: "subshape@npm:0.14.0" + checksum: 171a2d55db431917e1206b3cd9b4df976406fb12358f4932aff77d8d67f5564aec6909803ab3b95374876dcfc55c5a9582d0f2c164903e9996289cfcac8dfbd9 + languageName: node + linkType: hard + "superellipsejs@npm:^0.0.6": version: 0.0.6 resolution: "superellipsejs@npm:0.0.6" @@ -26542,6 +26734,15 @@ __metadata: languageName: node linkType: hard +"uglify-js@npm:^3.1.4": + version: 3.18.0 + resolution: "uglify-js@npm:3.18.0" + bin: + uglifyjs: bin/uglifyjs + checksum: 887733d05d4139a94dffd04a5f07ee7d8be70201c016ea48cb82703778b5c48fadbe6e5e7ac956425522f72e657d3eade23f06ae8a0e2eeed2d684bf6cc25e36 + languageName: node + linkType: hard + "uint8arrays@npm:3.1.0": version: 3.1.0 resolution: "uint8arrays@npm:3.1.0" @@ -28158,6 +28359,13 @@ __metadata: languageName: node linkType: hard +"wordwrap@npm:^1.0.0": + version: 1.0.0 + resolution: "wordwrap@npm:1.0.0" + checksum: 2a44b2788165d0a3de71fd517d4880a8e20ea3a82c080ce46e294f0b68b69a2e49cff5f99c600e275c698a90d12c5ea32aff06c311f0db2eb3f1201f3e7b2a04 + languageName: node + linkType: hard + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0" @@ -28451,6 +28659,21 @@ __metadata: languageName: node linkType: hard +"yargs@npm:^17.7.2": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: ^8.0.1 + escalade: ^3.1.1 + get-caller-file: ^2.0.5 + require-directory: ^2.1.1 + string-width: ^4.2.3 + y18n: ^5.0.5 + yargs-parser: ^21.1.1 + checksum: 73b572e863aa4a8cbef323dd911d79d193b772defd5a51aab0aca2d446655216f5002c42c5306033968193bdbf892a7a4c110b0d77954a7fdf563e653967b56a + languageName: node + linkType: hard + "yocto-queue@npm:^0.1.0": version: 0.1.0 resolution: "yocto-queue@npm:0.1.0"