diff --git a/packages/api-observable/package.json b/packages/api-observable/package.json index 4d4f6128ff..01ea780082 100644 --- a/packages/api-observable/package.json +++ b/packages/api-observable/package.json @@ -32,6 +32,8 @@ "@babel/runtime": "^7.0.0", "@polkadot/api": "^0.30.21", "@polkadot/api-provider": "^0.30.21", + "@polkadot/extrinsics": "^0.30.21", + "@polkadot/storage": "^0.30.21", "@types/rx": "^4.1.1", "rxjs": "^6.3.2" } diff --git a/packages/api-observable/src/Base.ts b/packages/api-observable/src/Base.ts index 048bd54e11..533a417b34 100644 --- a/packages/api-observable/src/Base.ts +++ b/packages/api-observable/src/Base.ts @@ -5,12 +5,13 @@ import { RxApiInterface, RxApiInterface$Method, RxApiInterface$Section } from '@polkadot/api-rx/types'; import { Method } from '@polkadot/jsonrpc/types'; -import { Observable, combineLatest, from } from 'rxjs'; +import { EMPTY, Observable, combineLatest, from } from 'rxjs'; import { defaultIfEmpty, map } from 'rxjs/operators'; import extrinsicsFromMeta from '@polkadot/extrinsics/fromMetadata'; import extrinsicsStatic from '@polkadot/extrinsics/static'; import storageFromMeta from '@polkadot/storage/fromMetadata'; import storageStatic from '@polkadot/storage/static'; +import { Vector } from '@polkadot/types/codec'; import { Hash } from '@polkadot/types/index'; import { StorageFunction } from '@polkadot/types/StorageKey'; import assert from '@polkadot/util/assert'; @@ -69,7 +70,6 @@ export default class ApiBase { protected combine = (observables: Array>, mapfn: MapFn = defaultMapFn): Observable => { return combineLatest(...observables).pipe( - // FIXME There are a couple of places now where this casting happens after rxjs 6.3.2 defaultIfEmpty([] as any), map(mapfn) ); @@ -95,26 +95,35 @@ export default class ApiBase { return fn.apply(null, params); } - rawStorage = (key: StorageFunction, ...params: Array): Observable => { + rawStorage = (key: StorageFunction, ...params: Array): Observable => { return this .rawStorageMulti([key, ...params] as [StorageFunction, any]) .pipe( - // @ts-ignore After upgrade to 6.3.2 - map(([result]: Array): T => + map((result: Array): T | undefined => result + ? result[0] + : undefined ) ); } - rawStorageMulti = (...keys: Array<[StorageFunction] | [StorageFunction, any]>): Observable => { - return this._api.state - .storage(keys) - .pipe( - map((result?: any) => - isUndefined(result) - ? [] - : result - ) - ); + rawStorageMulti = (...keys: Array<[StorageFunction] | [StorageFunction, any]>): Observable => { + let observable; + + try { + observable = this._api.state.storage(keys); + } catch (error) { + observable = EMPTY; + } + + return observable.pipe( + defaultIfEmpty(), + map((result?: Vector): T => + isUndefined(result) + ? [] as T + // FIXME When Vector extends Array, this mapping can be removed + : result.map((item: any) => item) as T + ) + ); } } diff --git a/packages/api-observable/src/Calls.ts b/packages/api-observable/src/Calls.ts index 11fda12810..a7209d855e 100644 --- a/packages/api-observable/src/Calls.ts +++ b/packages/api-observable/src/Calls.ts @@ -4,7 +4,7 @@ import { Observable } from 'rxjs'; import { defaultIfEmpty, map } from 'rxjs/operators'; -import { BlockNumber, Header, SignedBlock } from '@polkadot/types/index'; +import { BlockNumber, Hash, Header, SignedBlock, UncheckedMortalExtrinsic } from '@polkadot/types/index'; import ApiQueries from './Queries'; @@ -12,7 +12,7 @@ import ApiQueries from './Queries'; export default class ApiCalls extends ApiQueries { bestNumber = (): Observable => { return this - .chainNewHead() + .newHead() .pipe( map((header?: Header): BlockNumber | undefined => header && header.blockNumber @@ -22,13 +22,29 @@ export default class ApiCalls extends ApiQueries { ); } - chainGetBlock = (hash: Uint8Array): Observable => { + chain = (): Observable => { + return this._api.system.chain(); + } + + getBlock = (hash: Uint8Array): Observable => { return this._api.chain.getBlock(hash); } - chainNewHead = (): Observable
=> { + newHead = (): Observable
=> { return this._api.chain.newHead().pipe( defaultIfEmpty() ); } + + systemName = (): Observable => { + return this._api.system.name(); + } + + systemVersion = (): Observable => { + return this._api.system.version(); + } + + submitExtrinsic = (extrinsic: UncheckedMortalExtrinsic): Observable => { + return this._api.author.submitExtrinsic(extrinsic); + } } diff --git a/packages/api-observable/src/Combined.ts b/packages/api-observable/src/Combined.ts index 0499b52d97..229b2fb4dd 100644 --- a/packages/api-observable/src/Combined.ts +++ b/packages/api-observable/src/Combined.ts @@ -17,9 +17,9 @@ import { RxProposal, RxReferendum } from './classes'; // useful extensions, i.e. queries can be made that returns the results from multiple observables, // make the noise for the API users significantly less export default class ApiCombined extends ApiCalls { - democracyProposalCount = (): Observable => { + publicProposalCount = (): Observable => { return this - .democracyPublicProposals() + .publicProposals() .pipe( map((proposals: Array) => proposals.length @@ -27,10 +27,10 @@ export default class ApiCombined extends ApiCalls { ); } - democracyReferendumInfos = (referendumIds: Array): Observable> => { + referendumsInfo = (referendumIds: Array): Observable> => { return this.combine( referendumIds.map((referendumId) => - this.democracyReferendumInfoOf(referendumId) + this.referendumInfo(referendumId) ), (referendums: Array = []): Array => referendums.filter((referendum) => @@ -42,7 +42,7 @@ export default class ApiCombined extends ApiCalls { democracyReferendumVoters = (referendumId: ReferendumIndex | BN | number): Observable> => { return this.combine( [ - this.democacyVotersFor(referendumId), + this.referendumVoters(referendumId), this.democracyVotersBalancesOf(referendumId), this.democracyVotersVotesOf(referendumId) ], @@ -55,17 +55,17 @@ export default class ApiCombined extends ApiCalls { ); } - democracyReferendums = (): Observable> => { + referendums = (): Observable> => { return this.combine( [ - this.democracyReferendumCount(), + this.referendumCount(), this.democracyNextTally() ] ).pipe( // @ts-ignore After upgrade to 6.3.2 switchMap(([referendumCount, nextTally]: [ReferendumIndex | undefined, ReferendumIndex | undefined]): Observable> => referendumCount && nextTally && referendumCount.gt(nextTally) && referendumCount.gt(0) - ? this.democracyReferendumInfos( + ? this.referendumsInfo( [...Array(referendumCount.toBn().sub(nextTally.toBn()).toNumber())].map((_, i) => nextTally.add(i).toNumber() ) @@ -76,17 +76,17 @@ export default class ApiCombined extends ApiCalls { ); } - democracyVotesOf = (index: ReferendumIndex | BN | number, addresses: Array): Observable => { + referendumVotes = (index: ReferendumIndex | BN | number, addresses: Array): Observable => { return this.combine( addresses.map((address) => - this.democacyVoteOf(index, address) + this.referendumVote(index, address) ) ); } democracyVotersBalancesOf = (referendumId: ReferendumIndex | BN | number): Observable> => { return this - .democacyVotersFor(referendumId) + .referendumVoters(referendumId) .pipe( switchMap((voters: Array = []) => this.votingBalances(...voters) @@ -102,10 +102,10 @@ export default class ApiCombined extends ApiCalls { democracyVotersVotesOf = (referendumId: ReferendumIndex | BN | number): Observable> => { return this - .democacyVotersFor(referendumId) + .referendumVoters(referendumId) .pipe( switchMap((voters: Array = []) => - this.democracyVotesOf(referendumId, voters) + this.referendumVotes(referendumId, voters) ), defaultIfEmpty([] as any) ); @@ -200,7 +200,7 @@ export default class ApiCombined extends ApiCalls { sessionBrokenValue = (): Observable => { return this.combine( [ - this.timestampNow(), + this.blockNow(), this.sessionTimeExpected(), this.sessionTimeRemaining(), this.sessionCurrentStart() @@ -220,7 +220,7 @@ export default class ApiCombined extends ApiCalls { return this.combine( [ this.sessionLength(), - this.timestampBlockPeriod() + this.blockPeriod() ], ([sessionLength, blockPeriod]: [BlockNumber | undefined, Moment | undefined]): Moment | undefined => sessionLength && blockPeriod @@ -235,7 +235,7 @@ export default class ApiCombined extends ApiCalls { return this.combine( [ this.sessionBlockRemaining(), - this.timestampBlockPeriod() + this.blockPeriod() ], ([sessionBlockRemaining, blockPeriod]: [BlockNumber | undefined, Moment | undefined]): Moment | undefined => blockPeriod && sessionBlockRemaining @@ -292,8 +292,8 @@ export default class ApiCombined extends ApiCalls { return this.combine( [ - this.stakingFreeBalanceOf(address), - this.stakingReservedBalanceOf(address) + this.balanceFree(address), + this.balanceReserved(address) ], ([freeBalance = new Balance(0), reservedBalance = new Balance(0)]: [Balance | undefined, Balance | undefined]): RxBalance => ({ address, diff --git a/packages/api-observable/src/Queries.ts b/packages/api-observable/src/Queries.ts index 7fd1855c17..1d99a4b2d3 100644 --- a/packages/api-observable/src/Queries.ts +++ b/packages/api-observable/src/Queries.ts @@ -16,6 +16,26 @@ import { RxProposal, RxProposalDeposits, RxReferendum } from './classes'; // Perform storage queries to the API endpoints. export default class ApiQueries extends ApiBase { + accountNonce = (address: AccountId | string): Observable => { + return this.rawStorage(storage.system.accountNonce, address); + } + + balanceFree = (address: AccountId | string): Observable => { + return this.rawStorage(storage.balances.freeBalance, address); + } + + balanceReserved = (address: AccountId | string): Observable => { + return this.rawStorage(storage.balances.reservedBalance, address); + } + + blockPeriod = (): Observable => { + return this.rawStorage(storage.timestamp.blockPeriod); + } + + blockNow = (): Observable => { + return this.rawStorage(storage.timestamp.now); + } + democracyLaunchPeriod = (): Observable => { return this.rawStorage(storage.democracy.launchPeriod); } @@ -24,7 +44,7 @@ export default class ApiQueries extends ApiBase { return this.rawStorage(storage.democracy.nextTally); } - democracyProposalDeposits = (proposalId: PropIndex | BN | number): Observable => { + proposalDeposits = (proposalId: PropIndex | BN | number): Observable => { return this .rawStorage(storage.democracy.depositOf, proposalId) .pipe( @@ -37,7 +57,7 @@ export default class ApiQueries extends ApiBase { ); } - democracyPublicProposals = (): Observable> => { + publicProposals = (): Observable> => { return this .rawStorage(storage.democracy.publicProps) .pipe( @@ -56,11 +76,11 @@ export default class ApiQueries extends ApiBase { ); } - democracyReferendumCount = (): Observable => { + referendumCount = (): Observable => { return this.rawStorage(storage.democracy.referendumCount); } - democracyReferendumInfoOf = (referendumId: ReferendumIndex | BN | number): Observable => { + referendumInfo = (referendumId: ReferendumIndex | BN | number): Observable => { return this .rawStorage(storage.democracy.referendumInfoOf, referendumId) .pipe( @@ -73,11 +93,11 @@ export default class ApiQueries extends ApiBase { ); } - democacyVoteOf = (index: ReferendumIndex | BN | number, address: AccountId | string): Observable => { + referendumVote = (index: ReferendumIndex | BN | number, address: AccountId | string): Observable => { return this.rawStorage(storage.democracy.voteOf, index, address); } - democacyVotersFor = (index: ReferendumIndex | BN | number): Observable> => { + referendumVoters = (index: ReferendumIndex | BN | number): Observable> => { return this .rawStorage(storage.democracy.votersFor, index) .pipe( @@ -167,11 +187,6 @@ export default class ApiQueries extends ApiBase { ); } - // FIXME -> freeBalance - stakingFreeBalanceOf = (address: AccountId | string): Observable => { - return this.rawStorage(storage.balances.freeBalance, address); - } - stakingNominatorsFor = (address: AccountId | string): Observable> => { return this .rawStorage(storage.staking.nominatorsFor, address) @@ -187,24 +202,7 @@ export default class ApiQueries extends ApiBase { return this.rawStorage(storage.staking.nominating, address); } - // FIXME -> reservedBalance - stakingReservedBalanceOf = (address: AccountId | string): Observable => { - return this.rawStorage(storage.balances.reservedBalance, address); - } - - timestampBlockPeriod = (): Observable => { - return this.rawStorage(storage.timestamp.blockPeriod); - } - - timestampNow = (): Observable => { - return this.rawStorage(storage.timestamp.now); - } - - systemAccountIndexOf = (address: AccountId | string): Observable => { - return this.rawStorage(storage.system.accountNonce, address); - } - - validatorCount = (): Observable => { + validatorCount = (): Observable => { return this.rawStorage(storage.staking.validatorCount); } }