diff --git a/src/controllers/index.ts b/src/controllers/index.ts index ce46a3793..412debb68 100644 --- a/src/controllers/index.ts +++ b/src/controllers/index.ts @@ -4,5 +4,3 @@ export * from './blocks'; export * from './runtime'; export * from './pallets'; export * from './node'; - -export * as v0 from './v0'; diff --git a/src/controllers/v0/index.ts b/src/controllers/v0/index.ts deleted file mode 100644 index 872b6808e..000000000 --- a/src/controllers/v0/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './v0accounts'; -export * from './v0claims'; -export * from './v0blocks'; -export * from './v0pallets'; -export * from './v0transaction'; -export * from './v0runtime'; diff --git a/src/controllers/v0/v0accounts/AccountsBalanceInfoController.ts b/src/controllers/v0/v0accounts/AccountsBalanceInfoController.ts deleted file mode 100644 index 8a8296017..000000000 --- a/src/controllers/v0/v0accounts/AccountsBalanceInfoController.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; -import { RequestHandler } from 'express'; -import { IAddressNumberParams, IAddressParam } from 'src/types/requests'; - -import { validateAddress } from '../../../middleware'; -import { AccountsBalanceInfoService } from '../../../services/v0'; -import AbstractController from '../../AbstractController'; - -/** - * GET balance information for an address. - * - * Paths: - * - `address`: The address to query. - * - (Optional) `number`: Block hash or height at which to query. If not provided, queries - * finalized head. - * - * Returns: - * - `at`: Block number and hash at which the call was made. - * - `nonce`: Account nonce. - * - `free`: Free balance of the account. Not equivalent to _spendable_ balance. This is the only - * balance that matters in terms of most operations on tokens. - * - `reserved`: Reserved balance of the account. - * - `miscFrozen`: The amount that `free` may not drop below when withdrawing for anything except - * transaction fee payment. - * - `feeFrozen`: The amount that `free` may not drop below when withdrawing specifically for - * transaction fee payment. - * - `locks`: Array of locks on a balance. There can be many of these on an account and they - * "overlap", so the same balance is frozen by multiple locks. Contains: - * - `id`: An identifier for this lock. Only one lock may be in existence for each identifier. - * - `amount`: The amount below which the free balance may not drop with this lock in effect. - * - `reasons`: If true, then the lock remains in effect even for payment of transaction fees. - * - * Substrate Reference: - * - FRAME System: https://crates.parity.io/frame_system/index.html - * - Balances Pallet: https://crates.parity.io/pallet_balances/index.html - * - `AccountInfo`: https://crates.parity.io/frame_system/struct.AccountInfo.html - * - `AccountData`: https://crates.parity.io/pallet_balances/struct.AccountData.html - * - `BalanceLock`: https://crates.parity.io/pallet_balances/struct.BalanceLock.html - */ -export default class AccountsBalanceController extends AbstractController< - AccountsBalanceInfoService -> { - constructor(api: ApiPromise) { - super(api, '/balance/:address', new AccountsBalanceInfoService(api)); - this.initRoutes(); - } - - protected initRoutes(): void { - this.router.use(this.path, validateAddress); - - this.safeMountAsyncGetHandlers([ - ['', this.getAccountBalanceSummary], - ['/:number', this.getAccountBalanceSummaryAtBlock], - ]); - } - - /** - * Get the latest account balance summary of `address`. - * - * @param req Express Request - * @param res Express Response - */ - private getAccountBalanceSummary: RequestHandler = async ( - { params: { address } }, - res - ): Promise => { - const hash = await this.api.rpc.chain.getFinalizedHead(); - - AccountsBalanceController.sanitizedSend( - res, - await this.service.fetchAccountBalanceInfo(hash, address) - ); - }; - - /** - * Get the account balance summary of `address` at a block identified by its - * hash or number. - * - * @param req Express Request - * @param res Express Response - */ - private getAccountBalanceSummaryAtBlock: RequestHandler< - IAddressNumberParams - > = async ({ params: { number, address } }, res): Promise => { - const hash = await this.getHashForBlock(number); - - AccountsBalanceController.sanitizedSend( - res, - await this.service.fetchAccountBalanceInfo(hash, address) - ); - }; -} diff --git a/src/controllers/v0/v0accounts/AccountsStakingInfoController.ts b/src/controllers/v0/v0accounts/AccountsStakingInfoController.ts deleted file mode 100644 index 80879fa8b..000000000 --- a/src/controllers/v0/v0accounts/AccountsStakingInfoController.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; -import { RequestHandler } from 'express'; -import { IAddressNumberParams, IAddressParam } from 'src/types/requests'; - -import { validateAddress } from '../../../middleware/'; -import { AccountsStakingInfoService } from '../../../services/v0'; -import AbstractController from '../../AbstractController'; - -/** - * GET staking information for an address. - * - * Paths: - * - `address`: The _Stash_ address for staking. - * - (Optional) `number`: Block hash or height at which to query. If not provided, queries - * finalized head. - * - * Returns: - * - `at`: Block number and hash at which the call was made. - * - `rewardDestination`: The account to which rewards will be paid. Can be 'Staked' (Stash - * account, adding to the amount at stake), 'Stash' (Stash address, not adding to the amount at - * stake), 'Controller' (Controller address), or 'Account(AccountId)' (address identified by AccountId). - * - `controller`: Controller address for the given Stash. - * - `numSlashingSpans`: Number of slashing spans on Stash account; `null` if provided address is - * not a Controller. - * - `staking`: The staking ledger. Empty object if provided address is not a Controller. - * - `stash`: The stash account whose balance is actually locked and at stake. - * - `total`: The total amount of the stash's balance that we are currently accounting for. - * Simply `active + unlocking`. - * - `active`: The total amount of the stash's balance that will be at stake in any forthcoming - * eras. - * - `unlocking`: Any balance that is becoming free, which may eventually be transferred out of - * the stash (assuming it doesn't get slashed first). Represented as an array of objects, each - * with an `era` at which `value` will be unlocked. - * - `claimedRewards`: Array of eras for which the stakers behind a validator have claimed - * rewards. Only updated for _validators._ - * - * Note: Runtime versions of Kusama less than 1062 will either have `lastReward` in place of - * `claimedRewards`, or no field at all. This is related to changes in reward distribution. See: - * - Lazy Payouts: https://github.com/paritytech/substrate/pull/4474 - * - Simple Payouts: https://github.com/paritytech/substrate/pull/5406 - * - * Substrate Reference: - * - Staking Pallet: https://crates.parity.io/pallet_staking/index.html - * - `RewardDestination`: https://crates.parity.io/pallet_staking/enum.RewardDestination.html - * - `Bonded`: https://crates.parity.io/pallet_staking/struct.Bonded.html - * - `StakingLedger`: https://crates.parity.io/pallet_staking/struct.StakingLedger.html - */ -export default class AccountsStakingInfoController extends AbstractController< - AccountsStakingInfoService -> { - constructor(api: ApiPromise) { - super(api, '/staking/:address', new AccountsStakingInfoService(api)); - this.initRoutes(); - } - - protected initRoutes(): void { - this.router.use(this.path, validateAddress); - - this.safeMountAsyncGetHandlers([ - ['', this.getAccountStakingSummary], - ['/:number', this.getAccountStakingSummaryAtBlock], - ]); - } - - /** - * Get the latest account staking summary of `address`. - * - * @param req Express Request - * @param res Express Response - */ - private getAccountStakingSummary: RequestHandler = async ( - { params: { address } }, - res - ): Promise => { - const hash = await this.api.rpc.chain.getFinalizedHead(); - - AccountsStakingInfoController.sanitizedSend( - res, - await this.service.fetchAccountStakingInfo(hash, address) - ); - }; - - /** - * Get the account staking summary of `address` at a block identified by its - * hash or number. - * - * @param req Express Request - * @param res Express Response - */ - private getAccountStakingSummaryAtBlock: RequestHandler< - IAddressNumberParams - > = async (req, res): Promise => { - const { address, number } = req.params; - const hash = await this.getHashForBlock(number); - - AccountsStakingInfoController.sanitizedSend( - res, - await this.service.fetchAccountStakingInfo(hash, address) - ); - }; -} diff --git a/src/controllers/v0/v0accounts/AccountsVestingInfoController.ts b/src/controllers/v0/v0accounts/AccountsVestingInfoController.ts deleted file mode 100644 index 97d77bd7f..000000000 --- a/src/controllers/v0/v0accounts/AccountsVestingInfoController.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; -import { RequestHandler } from 'express'; -import { IAddressNumberParams, IAddressParam } from 'src/types/requests'; - -import { validateAddress } from '../../../middleware'; -import { AccountsVestingInfoService } from '../../../services/v0'; -import AbstractController from '../../AbstractController'; - -/** - * GET vesting information for an address. - * - * Paths: - * - `address`: Address to query. - * - (Optional) `number`: Block hash or height at which to query. If not provided, queries - * finalized head. - * - * Returns: - * - `at`: Block number and hash at which the call was made. - * - `vesting`: Vesting schedule for an account. - * - `locked`: Number of tokens locked at start. - * - `perBlock`: Number of tokens that gets unlocked every block after `startingBlock`. - * - `startingBlock`: Starting block for unlocking(vesting). - * - * Substrate Reference: - * - Vesting Pallet: https://crates.parity.io/pallet_vesting/index.html - * - `VestingInfo`: https://crates.parity.io/pallet_vesting/struct.VestingInfo.html - */ -export default class AccountsVestingInfoController extends AbstractController< - AccountsVestingInfoService -> { - constructor(api: ApiPromise) { - super(api, '/vesting/:address', new AccountsVestingInfoService(api)); - this.initRoutes(); - } - - protected initRoutes(): void { - this.router.use(this.path, validateAddress); - - this.safeMountAsyncGetHandlers([ - ['', this.getAccountVestingSummary], - ['/:number', this.getAccountVestingSummaryAtBlock], - ]); - } - - /** - * Get the latest account vesting summary of `address`. - * - * @param req Express Request - * @param res Express Response - */ - private getAccountVestingSummary: RequestHandler = async ( - { params: { address } }, - res - ): Promise => { - const hash = await this.api.rpc.chain.getFinalizedHead(); - - AccountsVestingInfoController.sanitizedSend( - res, - await this.service.fetchAccountVestingInfo(hash, address) - ); - }; - - /** - * Get the account vesting summary of `address` at a block identified by its - * hash or number. - * - * @param req Express Request - * @param res Express Response - */ - private getAccountVestingSummaryAtBlock: RequestHandler< - IAddressNumberParams - > = async (req, res): Promise => { - const { address, number } = req.params; - const hash = await this.getHashForBlock(number); - - AccountsVestingInfoController.sanitizedSend( - res, - await this.service.fetchAccountVestingInfo(hash, address) - ); - }; -} diff --git a/src/controllers/v0/v0accounts/index.ts b/src/controllers/v0/v0accounts/index.ts deleted file mode 100644 index 7af601abd..000000000 --- a/src/controllers/v0/v0accounts/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as v0AccountsBalanceInfo } from './AccountsBalanceInfoController'; -export { default as v0AccountsStakingInfo } from './AccountsStakingInfoController'; -export { default as v0AccountsVestingInfo } from './AccountsVestingInfoController'; diff --git a/src/controllers/v0/v0blocks/BlocksController.ts b/src/controllers/v0/v0blocks/BlocksController.ts deleted file mode 100644 index a9760f569..000000000 --- a/src/controllers/v0/v0blocks/BlocksController.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; -import { RequestHandler } from 'express'; - -import { BlocksService } from '../../../services/v0'; -import { INumberParam } from '../../../types/requests'; -import AbstractController from '../../AbstractController'; - -/** - * GET a block. - * - * Paths: - * - (Optional) `number`: Block hash or height at which to query. If not provided, queries - * finalized head. - * - * Returns: - * - `number`: Block height. - * - `hash`: The block's hash. - * - `parentHash`: The hash of the parent block. - * - `stateRoot`: The state root after executing this block. - * - `extrinsicsRoot`: The Merkle root of the extrinsics. - * - `authorId`: The account ID of the block author (may be undefined for some chains). - * - `logs`: Array of `DigestItem`s associated with the block. - * - `onInitialize`: Object with an array of `SanitizedEvent`s that occurred during block - * initialization with the `method` and `data` for each. - * - `extrinsics`: Array of extrinsics (inherents and transactions) within the block. Each - * contains: - * - `method`: Extrinsic method, `{module}.{function}`. - * - `signature`: Object with `signature` and `signer`, or `null` if unsigned. - * - `nonce`: Account nonce, if applicable. - * - `args`: Array of arguments. - * - `tip`: Any tip added to the transaction. - * - `hash`: The transaction's hash. - * - `info`: `RuntimeDispatchInfo` for the transaction. Includes the `partialFee`. - * - `events`: An array of `SanitizedEvent`s that occurred during extrinsic execution. - * - `success`: Whether or not the extrinsic succeeded. - * - `paysFee`: Whether the extrinsic requires a fee. Careful! This field relates to whether or - * not the extrinsic requires a fee if called as a transaction. Block authors could insert - * the extrinsic as an inherent in the block and not pay a fee. Always check that `paysFee` - * is `true` and that the extrinsic is signed when reconciling old blocks. - * - `onFinalize`: Object with an array of `SanitizedEvent`s that occurred during block - * finalization with the `method` and `data` for each. - * - * Note: Block finalization does not correspond to consensus, i.e. whether the block is in the - * canonical chain. It denotes the finalization of block _construction._ - * - * Substrate Reference: - * - `DigestItem`: https://crates.parity.io/sp_runtime/enum.DigestItem.html - * - `RawEvent`: https://crates.parity.io/frame_system/enum.RawEvent.html - * - Extrinsics: https://substrate.dev/docs/en/knowledgebase/learn-substrate/extrinsics - * - `Extrinsic`: https://crates.parity.io/sp_runtime/traits/trait.Extrinsic.html - * - `OnInitialize`: https://crates.parity.io/frame_support/traits/trait.OnInitialize.html - * - `OnFinalize`: https://crates.parity.io/frame_support/traits/trait.OnFinalize.html - */ -export default class BlocksController extends AbstractController< - BlocksService -> { - constructor(api: ApiPromise) { - super(api, '/block', new BlocksService(api)); - this.initRoutes(); - } - - protected initRoutes(): void { - this.safeMountAsyncGetHandlers([ - ['', this.getLatestBlock], - ['/:number', this.getBlockById], - ]); - } - - /** - * Get the latest block. - * - * @param _req Express Request - * @param res Express Response - */ - private getLatestBlock: RequestHandler = async (_req, res) => { - const hash = await this.api.rpc.chain.getFinalizedHead(); - - BlocksController.sanitizedSend( - res, - await this.service.fetchBlock(hash) - ); - }; - - /** - * Get a block by its hash or number identifier. - * - * @param req Express Request - * @param res Express Response - */ - private getBlockById: RequestHandler = async ( - { params: { number } }, - res - ): Promise => { - const hash = await this.getHashForBlock(number); - - BlocksController.sanitizedSend( - res, - await this.service.fetchBlock(hash) - ); - }; -} diff --git a/src/controllers/v0/v0blocks/index.ts b/src/controllers/v0/v0blocks/index.ts deleted file mode 100644 index e1f9074b5..000000000 --- a/src/controllers/v0/v0blocks/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as v0Blocks } from './BlocksController'; diff --git a/src/controllers/v0/v0claims/ClaimsController.ts b/src/controllers/v0/v0claims/ClaimsController.ts deleted file mode 100644 index 4d301d8ae..000000000 --- a/src/controllers/v0/v0claims/ClaimsController.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; -import { RequestHandler } from 'express'; -import { IAddressNumberParams, IAddressParam } from 'src/types/requests'; - -import { ClaimsService } from '../../../services/v0'; -import AbstractController from '../../AbstractController'; - -/** - * GET the claims type for an Ethereum address. - * - * Paths: - * - `ethAddress`: The _Ethereum_ address that holds a DOT claim. - * - (Optional) `number`: Block hash or height at which to query. If not provided, queries - * finalized head. - * - * Returns: - * - `type`: The type of claim. 'Regular' or 'Saft'. - * - * Reference: - * - Claims Guide: https://wiki.polkadot.network/docs/en/claims - */ -export default class ClaimsController extends AbstractController< - ClaimsService -> { - constructor(api: ApiPromise) { - super(api, '/claims/:address', new ClaimsService(api)); - this.initRoutes(); - } - - protected initRoutes(): void { - this.safeMountAsyncGetHandlers([ - ['', this.getClaim], - ['/:number', this.getClaimAtBlock], - ]); - } - - /** - * Get information on a claim by ethereum `address`. - * - * @param req Express Request - * @param res Express Response - */ - private getClaim: RequestHandler = async ( - req, - res - ): Promise => { - const { address } = req.params; - const hash = await this.api.rpc.chain.getFinalizedHead(); - - ClaimsController.sanitizedSend( - res, - await this.service.fetchClaimsInfo(hash, address) - ); - }; - - /** - * Get information on a claim by ethereum `address` at a block identified by - * its hash or number. - * - * @param req Express Request - * @param res Express Response - */ - private getClaimAtBlock: RequestHandler = async ( - { params: { number, address } }, - res - ): Promise => { - const hash = await this.getHashForBlock(number); - - ClaimsController.sanitizedSend( - res, - await this.service.fetchClaimsInfo(hash, address) - ); - }; -} diff --git a/src/controllers/v0/v0claims/index.ts b/src/controllers/v0/v0claims/index.ts deleted file mode 100644 index 038858979..000000000 --- a/src/controllers/v0/v0claims/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as v0Claims } from './ClaimsController'; diff --git a/src/controllers/v0/v0pallets/PalletsStakingProgressController.ts b/src/controllers/v0/v0pallets/PalletsStakingProgressController.ts deleted file mode 100644 index 747462eb6..000000000 --- a/src/controllers/v0/v0pallets/PalletsStakingProgressController.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; -import { RequestHandler } from 'express'; -import { INumberParam } from 'src/types/requests'; - -import { PalletsStakingProgressService } from '../../../services/v0'; -import AbstractController from '../../AbstractController'; - -/** - * GET generalized staking information. - * - * Paths: - * - (Optional) `number`: Block hash or height at which to query. If not provided, queries - * finalized head. - * - * Returns: - * - `at`: Block number and hash at which the call was made. - * - `activeEra`: `EraIndex` of the era being rewarded. - * - `forceEra`: Current status of era forcing. - * - `nextActiveEraEstimate`: **Upper bound estimate** of the block height at which the next - * active era will start. Not included in response when `forceEra.isForceNone`. - * - `nextSessionEstimate`: **Upper bound estimate** of the block height at which the next - * session will start. - * - `unappliedSlashes`: Array of upcoming `UnappliedSlash` indexed by era. Each `UnappliedSlash` - * contains: - * - `validator`: Stash account ID of the offending validator. - * - `own`: The amount the validator will be slashed. - * - `others`: Array of tuples of (accountId, amount) representing all the stashes of other - * slashed stakers and the amount they will be slashed. - * - `reporters`: Array of account IDs of the reporters of the offense. - * - `payout`: Amount of bounty payout to reporters. - * - `electionStatus`: Information about the off-chain election. Not included in response when - * `forceEra.isForceNone`. Response includes: - * - `status`: Era election status; either `Close: null` or `Open: `. A status of - * `Close` indicates that the submission window for solutions from off-chain Phragmen is not - * open. A status of `Open` indicates the submission window for off-chain Phragmen solutions - * has been open since BlockNumber. N.B. when the submission window is open, certain - * extrinsics are not allowed because they would mutate the state that the off-chain Phragmen - * calculation relies on for calculating results. - * - `toggleEstimate`: **Upper bound estimate** of the block height at which the `status` will - * switch. - * - `idealValidatorCount`: Upper bound of validator set size; considered the ideal size. Not - * included in response when `forceEra.isForceNone`. - * - `validatorSet`: Stash account IDs of the validators for the current session. Not included in - * response when `forceEra.isForceNone`. - * - * Note about 'active' vs. 'current' era: The _active_ era is the era currently being rewarded. - * That is, an elected validator set will be in place for an entire active era, as long as none - * are kicked out due to slashing. Elections take place at the end of each _current_ era, which - * is the latest planned era, and may not equal the active era. Normally, the current era index - * increments one session before the active era, in order to perform the election and queue the - * validator set for the next active era. For example: - * - * ``` - * Time: ---------> - * CurrentEra: 1 | 2 | - * ActiveEra: | 1 | 2 | - * SessionIdx: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | - * Elections: ^ ^ - * Set Changes: ^ ^ - * ``` - * - * Substrate Reference: - * - Staking Pallet: https://crates.parity.io/pallet_staking/index.html - * - Session Pallet: https://crates.parity.io/pallet_session/index.html - * - `Forcing`: https://crates.parity.io/pallet_staking/enum.Forcing.html - * - `ElectionStatus`: https://crates.parity.io/pallet_staking/enum.ElectionStatus.html - */ -export default class PalletsStakingProgressController extends AbstractController< - PalletsStakingProgressService -> { - constructor(api: ApiPromise) { - super(api, '/staking-info', new PalletsStakingProgressService(api)); - this.initRoutes(); - } - - protected initRoutes(): void { - this.safeMountAsyncGetHandlers([ - ['', this.getStakingInfo], - ['/:number', this.getStakingInfoAtBlock], - ]); - } - - /** - * Get staking information and progress summary. - * - * @param _req Express Request - * @param res Express Response - */ - private getStakingInfo: RequestHandler = async ( - _req, - res - ): Promise => { - const hash = await this.api.rpc.chain.getFinalizedHead(); - - PalletsStakingProgressController.sanitizedSend( - res, - await this.service.derivePalletStakingProgress(hash) - ); - }; - - /** - * Get staking information and progress summary at a block identified by its - * hash or number. - * - * @param req Express Request - * @param res Express Response - */ - private getStakingInfoAtBlock: RequestHandler = async ( - { params: { number } }, - res - ): Promise => { - const hash = await this.getHashForBlock(number); - - PalletsStakingProgressController.sanitizedSend( - res, - await this.service.derivePalletStakingProgress(hash) - ); - }; -} diff --git a/src/controllers/v0/v0pallets/index.ts b/src/controllers/v0/v0pallets/index.ts deleted file mode 100644 index c057aa32d..000000000 --- a/src/controllers/v0/v0pallets/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as v0PalletsStakingProgress } from './PalletsStakingProgressController'; diff --git a/src/controllers/v0/v0runtime/RuntimeMetadataController.ts b/src/controllers/v0/v0runtime/RuntimeMetadataController.ts deleted file mode 100644 index d8b72bf60..000000000 --- a/src/controllers/v0/v0runtime/RuntimeMetadataController.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; -import { RequestHandler } from 'express'; -import { INumberParam } from 'src/types/requests'; - -import { RuntimeMetadataService } from '../../../services/v0'; -import AbstractController from '../../AbstractController'; - -/** - * GET the chain's metadata. - * - * Paths: - * - (Optional) `number`: Block hash or height at which to query. If not provided, queries - * finalized head. - * - * Returns: - * - Metadata object. - * - * Substrate Reference: - * - FRAME Support: https://crates.parity.io/frame_support/metadata/index.html - * - Knowledge Base: https://substrate.dev/docs/en/knowledgebase/runtime/metadata - */ -export default class RuntimeMetadataController extends AbstractController< - RuntimeMetadataService -> { - constructor(api: ApiPromise) { - super(api, '/metadata', new RuntimeMetadataService(api)); - this.initRoutes(); - } - - protected initRoutes(): void { - this.safeMountAsyncGetHandlers([ - ['', this.getMetadata], - ['/:number', this.getMetadataAtBlock], - ]); - } - - /** - * Get the chain's latest metadata in a decoded, JSON format. - * - * @param _req Express Request - * @param res Express Response - */ - - private getMetadata: RequestHandler = async (_req, res): Promise => { - const hash = await this.api.rpc.chain.getFinalizedHead(); - - RuntimeMetadataController.sanitizedSend( - res, - await this.service.fetchMetadata(hash) - ); - }; - - /** - * Get the chain's metadata in a decoded, JSON format at a block identified - * by its hash or number. - * - * @param req Express Request - * @param res Express Response - */ - private getMetadataAtBlock: RequestHandler = async ( - { params: { number } }, - res - ): Promise => { - const hash = await this.getHashForBlock(number); - - RuntimeMetadataController.sanitizedSend( - res, - await this.service.fetchMetadata(hash) - ); - }; -} diff --git a/src/controllers/v0/v0runtime/index.ts b/src/controllers/v0/v0runtime/index.ts deleted file mode 100644 index 03457874d..000000000 --- a/src/controllers/v0/v0runtime/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as v0Metadata } from './RuntimeMetadataController'; diff --git a/src/controllers/v0/v0transaction/TransactionFeeEstimateController.ts b/src/controllers/v0/v0transaction/TransactionFeeEstimateController.ts deleted file mode 100644 index 72ea4582f..000000000 --- a/src/controllers/v0/v0transaction/TransactionFeeEstimateController.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; - -import { TransactionFeeEstimateService } from '../../../services/v0'; -import { IPostRequestHandler, ITx } from '../../../types/requests'; -import AbstractController from '../../AbstractController'; - -/** - * POST a serialized transaction and receive a fee estimate. - * - * Post info: - * - `data`: Expects a hex-encoded transaction, e.g. '{"tx": "0x..."}'. - * - `headers`: Expects 'Content-Type: application/json'. - * - * Returns: - * - Success: - * - `weight`: Extrinsic weight. - * - `class`: Extrinsic class, one of 'Normal', 'Operational', or 'Mandatory'. - * - `partialFee`: _Expected_ inclusion fee for the transaction. Note that the fee rate changes - * up to 30% in a 24 hour period and this will not be the exact fee. - * - Failure: - * - `error`: Error description. - * - `data`: The extrinsic and reference block hash. - * - `cause`: Error message from the client. - * - * Note: `partialFee` does not include any tips that you may add to increase a transaction's - * priority. See the reference on `compute_fee`. - * - * Substrate Reference: - * - `RuntimeDispatchInfo`: https://crates.parity.io/pallet_transaction_payment_rpc_runtime_api/struct.RuntimeDispatchInfo.html - * - `query_info`: https://crates.parity.io/pallet_transaction_payment/struct.Module.html#method.query_info - * - `compute_fee`: https://crates.parity.io/pallet_transaction_payment/struct.Module.html#method.compute_fee - */ -export default class TransactionFeeEstimateController extends AbstractController< - TransactionFeeEstimateService -> { - constructor(api: ApiPromise) { - super(api, '/tx/fee-estimate', new TransactionFeeEstimateService(api)); - this.initRoutes(); - } - - protected initRoutes(): void { - this.router.post( - this.path, - TransactionFeeEstimateController.catchWrap(this.txFeeEstimate) - ); - } - - /** - * Submit a serialized transaction in order to receive an estimate for its - * partial fees. - * - * @param req Sidecar TxRequest - * @param res Express Response - */ - private txFeeEstimate: IPostRequestHandler = async ( - { body: { tx } }, - res - ): Promise => { - if (!tx) { - throw { - error: 'Missing field `tx` on request body.', - }; - } - - const hash = await this.api.rpc.chain.getFinalizedHead(); - - TransactionFeeEstimateController.sanitizedSend( - res, - await this.service.fetchTransactionFeeEstimate(hash, tx) - ); - }; -} diff --git a/src/controllers/v0/v0transaction/TransactionMaterialController.ts b/src/controllers/v0/v0transaction/TransactionMaterialController.ts deleted file mode 100644 index 4ca9e4cf5..000000000 --- a/src/controllers/v0/v0transaction/TransactionMaterialController.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; -import { RequestHandler } from 'express'; -import { INumberParam } from 'src/types/requests'; - -import { TransactionMaterialService } from '../../../services/v0'; -// import ApiHandler from '../ApiHandler'; -import AbstractController from '../../AbstractController'; - -/** - * GET all the information needed to construct a transaction offline. - * - * Paths - * - (Optional) `number`: Block hash or number at which to query. If not provided, queries - * finalized head. - * - * Query - * - (Optional) `noMeta`: If true, does not return metadata hex. This is useful when metadata is not - * needed and response time is a concern. Defaults to false. - * - * Returns: - * - `at`: Block number and hash at which the call was made. - * - `genesisHash`: The hash of the chain's genesis block. - * - `chainName`: The chain's name. - * - `specName`: The chain's spec. - * - `specVersion`: The spec version. Always increased in a runtime upgrade. - * - `txversion`: The transaction version. Common `txVersion` numbers indicate that the - * transaction encoding format and method indices are the same. Needed for decoding in an - * offline environment. Adding new transactions does not change `txVersion`. - * - `metadata`: The chain's metadata in hex format. - * - * Note: `chainName`, `specName`, and `specVersion` are used to define a type registry with a set - * of signed extensions and types. For Polkadot and Kusama, `chainName` is not used in defining - * this registry, but in other Substrate-based chains that re-launch their network without - * changing the `specName`, the `chainName` would be needed to create the correct registry. - * - * Substrate Reference: - * - `RuntimeVersion`: https://crates.parity.io/sp_version/struct.RuntimeVersion.html - * - `SignedExtension`: https://crates.parity.io/sp_runtime/traits/trait.SignedExtension.html - * - FRAME Support: https://crates.parity.io/frame_support/metadata/index.html - */ -export default class TransactionMaterialController extends AbstractController< - TransactionMaterialService -> { - constructor(api: ApiPromise) { - super(api, '/tx/artifacts', new TransactionMaterialService(api)); - this.initRoutes(); - } - - protected initRoutes(): void { - this.safeMountAsyncGetHandlers([ - ['', this.getTxArtifacts], - ['/:number', this.getTxArtifactsAtBlock], - ]); - } - - /** - * Get generic offline transaction construction material. - * - * @param _req Express Request - * @param res Express Response - */ - private getTxArtifacts: RequestHandler = async ( - { query: { noMeta } }, - res - ): Promise => { - const hash = await this.api.rpc.chain.getFinalizedHead(); - - const noMetaArg = noMeta === 'true'; - - TransactionMaterialController.sanitizedSend( - res, - await this.service.fetchTransactionMaterial(hash, noMetaArg) - ); - }; - - /** - * Get generic offline transaction construction material at a block identified - * by its hash or number. - * - * @param req Express Request - * @param res Express Response - */ - private getTxArtifactsAtBlock: RequestHandler = async ( - { params: { number }, query: { noMeta } }, - res - ): Promise => { - const hash = await this.getHashForBlock(number); - - const noMetaArg = noMeta === 'true'; - - TransactionMaterialController.sanitizedSend( - res, - await this.service.fetchTransactionMaterial(hash, noMetaArg) - ); - }; -} diff --git a/src/controllers/v0/v0transaction/TransactionSubmitController.ts b/src/controllers/v0/v0transaction/TransactionSubmitController.ts deleted file mode 100644 index b0895bd8c..000000000 --- a/src/controllers/v0/v0transaction/TransactionSubmitController.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; - -import { TransactionSubmitService } from '../../../services/v0'; -import { IPostRequestHandler, ITx } from '../../../types/requests'; -import AbstractController from '../../AbstractController'; - -/** - * POST a serialized transaction to submit to the transaction queue. - * - * Post info: - * - `data`: Expects a hex-encoded transaction, e.g. '{"tx": "0x..."}'. - * - `headers`: Expects 'Content-Type: application/json'. - * - * Returns: - * - Success: - * - `hash`: The hash of the encoded transaction. - * - Failure: - * - `error`: 'Failed to parse a tx' or 'Failed to submit a tx'. In the case of the former, the - * Sidecar was unable to parse the transaction and never even submitted it to the client. In - * the case of the latter, the transaction queue rejected the transaction. - * - `data`: The hex-encoded extrinsic. Only present if Sidecar fails to parse a transaction. - * - `cause`: The error message from parsing or from the client. - */ -export default class TransactionSubmitController extends AbstractController< - TransactionSubmitService -> { - constructor(api: ApiPromise) { - super(api, '/tx', new TransactionSubmitService(api)); - this.initRoutes(); - } - - protected initRoutes(): void { - this.router.post( - this.path, - TransactionSubmitController.catchWrap(this.txSubmit) - ); - } - - /** - * Submit a serialized transaction to the transaction queue. - * - * @param req Sidecar TxRequest - * @param res Express Response - */ - private txSubmit: IPostRequestHandler = async ( - { body: { tx } }, - res - ): Promise => { - if (!tx) { - throw { - error: 'Missing field `tx` on request body.', - }; - } - - res.send(await this.service.submitTransaction(tx)); - }; -} diff --git a/src/controllers/v0/v0transaction/index.ts b/src/controllers/v0/v0transaction/index.ts deleted file mode 100644 index 1f2bcee7f..000000000 --- a/src/controllers/v0/v0transaction/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as v0TransactionFeeEstimate } from './TransactionFeeEstimateController'; -export { default as v0TransactionSubmit } from './TransactionSubmitController'; -export { default as v0TransactionMaterial } from './TransactionMaterialController'; diff --git a/src/main.ts b/src/main.ts index 809faf03a..37914a60e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -98,33 +98,6 @@ async function main() { ); } - // Instantiate v0 controllers (note these will be removed upon the release of v1.0.0) - const claimsController = new controllers.v0.v0Claims(api); - const txArtifactsController = new controllers.v0.v0TransactionMaterial(api); - const txFeeEstimateController = new controllers.v0.v0TransactionFeeEstimate( - api - ); - const txSubmitController = new controllers.v0.v0TransactionSubmit(api); - const vestingController = new controllers.v0.v0AccountsVestingInfo(api); - const balancesController = new controllers.v0.v0AccountsBalanceInfo(api); - const stakingInfoController = new controllers.v0.v0AccountsStakingInfo(api); - const v0blocksController = new controllers.v0.v0Blocks(api); - const stakingController = new controllers.v0.v0PalletsStakingProgress(api); - const metadataController = new controllers.v0.v0Metadata(api); - - const v0Controllers = [ - claimsController, - txArtifactsController, - txFeeEstimateController, - txSubmitController, - stakingInfoController, - vestingController, - balancesController, - v0blocksController, - stakingController, - metadataController, - ]; - // Create our App const app = new App({ preMiddleware: [json(), middleware.httpLoggerCreate(logger)], @@ -146,7 +119,6 @@ async function main() { new controllers.TransactionSubmit(api), new controllers.palletsStakingProgress(api), new controllers.palletsStorageItem(api), - ...v0Controllers, ], postMiddleware: [ middleware.txError, diff --git a/src/services/v0/index.ts b/src/services/v0/index.ts deleted file mode 100644 index 6266418b2..000000000 --- a/src/services/v0/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './v0accounts'; -export * from './v0claims'; -export * from './v0blocks'; -export * from './v0pallets'; -export * from './v0transaction'; -export * from './v0metadata'; diff --git a/src/services/v0/v0accounts/AccountsBalanceInfoService.spec.ts b/src/services/v0/v0accounts/AccountsBalanceInfoService.spec.ts deleted file mode 100644 index b46104729..000000000 --- a/src/services/v0/v0accounts/AccountsBalanceInfoService.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { sanitizeNumbers } from '../../../sanitize/sanitizeNumbers'; -import { blockHash789629, mockApi, testAddress } from '../../test-helpers/mock'; -import * as accountsBalanceInfo789629 from '../../test-helpers/responses/accounts/balanceInfo789629.json'; -import { AccountsBalanceInfoService } from './AccountsBalanceInfoService'; - -const accountsBalanceInfoService = new AccountsBalanceInfoService(mockApi); - -describe('AccountsBalanceInfoService', () => { - describe('fetchAccountBalanceInfo', () => { - it('works when ApiPromise works (block 789629)', async () => { - expect( - sanitizeNumbers( - await accountsBalanceInfoService.fetchAccountBalanceInfo( - blockHash789629, - testAddress - ) - ) - ).toStrictEqual(accountsBalanceInfo789629); - }); - }); -}); diff --git a/src/services/v0/v0accounts/AccountsBalanceInfoService.ts b/src/services/v0/v0accounts/AccountsBalanceInfoService.ts deleted file mode 100644 index 435308110..000000000 --- a/src/services/v0/v0accounts/AccountsBalanceInfoService.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { BlockHash } from '@polkadot/types/interfaces'; -import { IAccountBalanceInfo } from 'src/types/responses'; - -import { AbstractService } from '../../AbstractService'; - -export class AccountsBalanceInfoService extends AbstractService { - /** - * Fetch balance information for an account at a given block. - * - * @param hash `BlockHash` to make call at - * @param address address of the account to get the balance info of - */ - async fetchAccountBalanceInfo( - hash: BlockHash, - address: string - ): Promise { - const { api } = this; - - const [header, locks, sysAccount] = await Promise.all([ - api.rpc.chain.getHeader(hash), - api.query.balances.locks.at(hash, address), - api.query.system.account.at(hash, address), - ]); - - const account = - sysAccount.data != null - ? sysAccount.data - : await api.query.balances.account.at(hash, address); - - const at = { - hash, - height: header.number.toNumber().toString(10), - }; - - if (account && locks && sysAccount) { - const { free, reserved, miscFrozen, feeFrozen } = account; - const { nonce } = sysAccount; - - return { - at, - nonce, - free, - reserved, - miscFrozen, - feeFrozen, - locks, - }; - } else { - throw { - at, - error: 'Account not found', - }; - } - } -} diff --git a/src/services/v0/v0accounts/AccountsStakingInfoService.spec.ts b/src/services/v0/v0accounts/AccountsStakingInfoService.spec.ts deleted file mode 100644 index 2423f8386..000000000 --- a/src/services/v0/v0accounts/AccountsStakingInfoService.spec.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import { sanitizeNumbers } from '../../../sanitize/sanitizeNumbers'; -import { polkadotRegistry } from '../../../test-helpers/registries'; -import { - blockHash789629, - bondedAt, - ledgerAt, - mockApi, - testAddress, - testAddressController, -} from '../../test-helpers/mock'; -import * as response789629 from '../../test-helpers/responses/accounts/stakingInfo789629.json'; -import { AccountsStakingInfoService } from './AccountsStakingInfoService'; - -const accountStakingInfoService = new AccountsStakingInfoService(mockApi); - -describe('AccountsStakingInfoService', () => { - describe('fetchAccountStakingInfo', () => { - it('works with a valid stash address (block 789629)', async () => { - expect( - sanitizeNumbers( - await accountStakingInfoService.fetchAccountStakingInfo( - blockHash789629, - testAddress - ) - ) - ).toStrictEqual(response789629); - }); - - it('throws a 400 when the given address is not a stash', async () => { - (mockApi.query.staking.bonded as any).at = () => - Promise.resolve().then(() => - polkadotRegistry.createType('Option', null) - ); - - await expect( - accountStakingInfoService.fetchAccountStakingInfo( - blockHash789629, - 'NotStash' - ) - ).rejects.toStrictEqual({ - error: 'The address NotStash is not a stash address.', - statusCode: 400, - }); - - (mockApi.query.staking.bonded as any).at = bondedAt; - }); - - it('throws a 404 when the staking ledger cannot be found', async () => { - (mockApi.query.staking.ledger as any).at = () => - Promise.resolve().then(() => - polkadotRegistry.createType('Option', null) - ); - - await expect( - accountStakingInfoService.fetchAccountStakingInfo( - blockHash789629, - testAddress - ) - ).rejects.toStrictEqual({ - error: `Staking ledger could not be found for controller address "${testAddressController.toString()}"`, - statusCode: 404, - }); - - (mockApi.query.staking.ledger as any).at = ledgerAt; - }); - }); -}); diff --git a/src/services/v0/v0accounts/AccountsStakingInfoService.ts b/src/services/v0/v0accounts/AccountsStakingInfoService.ts deleted file mode 100644 index dfadc45dc..000000000 --- a/src/services/v0/v0accounts/AccountsStakingInfoService.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { BlockHash } from '@polkadot/types/interfaces'; -import { IAccountStakingInfo } from 'src/types/responses'; - -import { AbstractService } from '../../AbstractService'; - -export class AccountsStakingInfoService extends AbstractService { - /** - * Fetch staking information for a _Stash_ account at a given block. - * - * @param hash `BlockHash` to make call at - * @param stash address of the _Stash_ account to get the staking info of - */ - async fetchAccountStakingInfo( - hash: BlockHash, - stash: string - ): Promise { - const { api } = this; - - const [header, controllerOption] = await Promise.all([ - api.rpc.chain.getHeader(hash), - api.query.staking.bonded.at(hash, stash), // Option representing the controller - ]); - - const at = { - hash, - height: header.number.unwrap().toString(10), - }; - - if (controllerOption.isNone) { - throw { - // TODO convert to newer type error - error: `The address ${stash} is not a stash address.`, - statusCode: 400, - }; - } - - const controller = controllerOption.unwrap(); - - const [ - stakingLedgerOption, - rewardDestination, - slashingSpansOption, - ] = await Promise.all([ - api.query.staking.ledger.at(hash, controller), - api.query.staking.payee.at(hash, stash), - api.query.staking.slashingSpans.at(hash, stash), - ]); - - const stakingLedger = stakingLedgerOption.unwrapOr(null); - - if (stakingLedger === null) { - // TODO convert to newer type error - // should never throw because by time we get here we know we have a bonded pair - throw { - error: `Staking ledger could not be found for controller address "${controller.toString()}"`, - statusCode: 404, - }; - } - - const numSlashingSpans = slashingSpansOption.isSome - ? slashingSpansOption.unwrap().prior.length + 1 - : 0; - - return { - at, - controller, - rewardDestination, - numSlashingSpans, - staking: stakingLedger, - }; - } -} diff --git a/src/services/v0/v0accounts/AccountsVestingInfoService.spec.ts b/src/services/v0/v0accounts/AccountsVestingInfoService.spec.ts deleted file mode 100644 index 110eaa971..000000000 --- a/src/services/v0/v0accounts/AccountsVestingInfoService.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { sanitizeNumbers } from '../../../sanitize/sanitizeNumbers'; -import { blockHash789629, mockApi, testAddress } from '../../test-helpers/mock'; -import * as response789629 from '../../test-helpers/responses/accounts/vestingInfo789629.json'; -import { AccountsVestingInfoService } from './AccountsVestingInfoService'; - -const accountsVestingInfoService = new AccountsVestingInfoService(mockApi); - -describe('AccountVestingInfoService', () => { - describe('fetchAccountVestingInfo', () => { - it('works when ApiPromise works (block 789629)', async () => { - expect( - sanitizeNumbers( - await accountsVestingInfoService.fetchAccountVestingInfo( - blockHash789629, - testAddress - ) - ) - ).toStrictEqual(response789629); - }); - }); -}); diff --git a/src/services/v0/v0accounts/AccountsVestingInfoService.ts b/src/services/v0/v0accounts/AccountsVestingInfoService.ts deleted file mode 100644 index ee44bacb0..000000000 --- a/src/services/v0/v0accounts/AccountsVestingInfoService.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Metadata } from '@polkadot/types'; -import { BlockHash } from '@polkadot/types/interfaces'; -import { IAccountVestingInfo } from 'src/types/responses'; - -import { AbstractService } from '../../AbstractService'; - -export class AccountsVestingInfoService extends AbstractService { - /** - * Fetch vesting information for an account at a given block. - * - * @param hash `BlockHash` to make call at - * @param address address of the account to get the vesting info of - */ - async fetchAccountVestingInfo( - hash: BlockHash, - address: string - ): Promise { - const { api } = this; - - const [header, vesting] = await Promise.all([ - api.rpc.chain.getHeader(hash), - api.query.vesting.vesting.at(hash, address), - ]); - - const at = { - hash, - height: header.number.toNumber().toString(10), - }; - - return { - at, - vesting: vesting.isNone ? {} : vesting.unwrap(), - }; - } - - async fetchMetadata(hash: BlockHash): Promise { - const metadata = await this.api.rpc.state.getMetadata(hash); - - return metadata; - } -} diff --git a/src/services/v0/v0accounts/index.ts b/src/services/v0/v0accounts/index.ts deleted file mode 100644 index 2b08eda1a..000000000 --- a/src/services/v0/v0accounts/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './AccountsStakingInfoService'; -export * from './AccountsBalanceInfoService'; -export * from './AccountsVestingInfoService'; diff --git a/src/services/v0/v0blocks/BlocksService.ts b/src/services/v0/v0blocks/BlocksService.ts deleted file mode 100644 index 09c9b8d47..000000000 --- a/src/services/v0/v0blocks/BlocksService.ts +++ /dev/null @@ -1,461 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; -import { GenericCall, Struct } from '@polkadot/types'; -import { - AccountId, - Block, - BlockHash, - Digest, - DispatchInfo, - EventRecord, - Hash, -} from '@polkadot/types/interfaces'; -import { AnyJson, Codec, Registry } from '@polkadot/types/types'; -import { u8aToHex } from '@polkadot/util'; -import { blake2AsU8a } from '@polkadot/util-crypto'; -import { CalcFee } from '@substrate/calc'; - -import { - IBlock, - IExtrinsic, - ISanitizedCall, - ISanitizedEvent, -} from '../../../types/responses'; -import { isPaysFee } from '../../../types/util'; -import { AbstractService } from '../../AbstractService'; - -/** - * Event methods that we check for. - */ -enum Event { - success = 'system.ExtrinsicSuccess', - failure = 'system.ExtrinsicFailed', -} - -export class BlocksService extends AbstractService { - /** - * Fetch a block enhanced with augmented and derived values. - * - * @param hash `BlockHash` of the block to fetch. - */ - async fetchBlock(hash: BlockHash): Promise { - const { api } = this; - - const [{ block }, events, validators] = await Promise.all([ - api.rpc.chain.getBlock(hash), - this.fetchEvents(api, hash), - api.query.session.validators.at(hash), - ]); - - const { - parentHash, - number, - stateRoot, - extrinsicsRoot, - digest, - } = block.header; - - const authorId = this.extractAuthor(validators, digest); - - const logs = digest.logs.map((log) => { - const { type, index, value } = log; - - return { type, index, value }; - }); - - const nonSanitizedExtrinsics = this.extractExtrinsics(block, events); - - const { extrinsics, onInitialize, onFinalize } = this.sanitizeEvents( - events, - nonSanitizedExtrinsics, - hash - ); - - // The genesis block is a special case with little information associated with it. - if (parentHash.every((byte) => !byte)) { - return { - number, - hash, - parentHash, - stateRoot, - extrinsicsRoot, - authorId, - logs, - onInitialize, - extrinsics, - onFinalize, - }; - } - - const { calcFee, specName, specVersion } = await this.createCalcFee( - api, - parentHash, - block - ); - - for (let idx = 0; idx < block.extrinsics.length; ++idx) { - if (!extrinsics[idx].paysFee || !block.extrinsics[idx].isSigned) { - continue; - } - - if (calcFee === null || calcFee === undefined) { - extrinsics[idx].info = { - error: `Fee calculation not supported for ${specName}#${specVersion}`, - }; - continue; - } - - try { - const xtEvents = extrinsics[idx].events; - const completedEvent = xtEvents.find( - ({ method }) => - method === Event.success || method === Event.failure - ); - if (!completedEvent) { - extrinsics[idx].info = { - error: - 'Unable to find success or failure event for extrinsic', - }; - - continue; - } - - const completedData = completedEvent.data; - if (!completedData) { - extrinsics[idx].info = { - error: - 'Success or failure event for extrinsic does not contain expected data', - }; - - continue; - } - - // both ExtrinsicSuccess and ExtrinsicFailed events have DispatchInfo - // types as their final arg - const weightInfo = completedData[ - completedData.length - 1 - ] as DispatchInfo; - if (!weightInfo.weight) { - extrinsics[idx].info = { - error: - 'Success or failure event for extrinsic does not specify weight', - }; - - continue; - } - - const len = block.extrinsics[idx].encodedLength; - const weight = weightInfo.weight; - - const partialFee = calcFee.calc_fee( - BigInt(weight.toString()), - len - ); - - extrinsics[idx].info = api.createType('RuntimeDispatchInfo', { - weight, - class: weightInfo.class, - partialFee: partialFee, - }); - } catch (err) { - console.error(err); - extrinsics[idx].info = { error: 'Unable to fetch fee info' }; - } - } - - return { - number, - hash, - parentHash, - stateRoot, - extrinsicsRoot, - authorId, - logs, - onInitialize, - extrinsics, - onFinalize, - }; - } - - /** - * Extract extrinsics from a block. - * - * @param block Block - * @param events events fetched by `fetchEvents` - */ - private extractExtrinsics(block: Block, events: EventRecord[] | string) { - const defaultSuccess = typeof events === 'string' ? events : false; - - return block.extrinsics.map((extrinsic) => { - const { - method, - nonce, - signature, - signer, - isSigned, - tip, - } = extrinsic; - const hash = u8aToHex(blake2AsU8a(extrinsic.toU8a(), 256)); - - return { - method: `${method.sectionName}.${method.methodName}`, - signature: isSigned ? { signature, signer } : null, - nonce, - args: this.parseGenericCall(method, block.registry).args, - tip, - hash, - info: {}, - events: [] as ISanitizedEvent[], - success: defaultSuccess, - // paysFee overrides to bool if `system.ExtrinsicSuccess|ExtrinsicFailed` event is present - paysFee: null as null | boolean, - }; - }); - } - - /** - * Sanitize events and attribute them to an extrinsic, onInitialize, or - * onFinalize. - * - * @param events events from `fetchEvents` - * @param extrinsics extrinsics from - * @param hash hash of the block the events are from - */ - private sanitizeEvents( - events: EventRecord[] | string, - extrinsics: IExtrinsic[], - hash: BlockHash - ) { - const onInitialize = { events: [] as ISanitizedEvent[] }; - const onFinalize = { events: [] as ISanitizedEvent[] }; - - if (Array.isArray(events)) { - for (const record of events) { - const { event, phase } = record; - const sanitizedEvent = { - method: `${event.section}.${event.method}`, - data: event.data, - }; - - if (phase.isApplyExtrinsic) { - const extrinsicIdx = phase.asApplyExtrinsic.toNumber(); - const extrinsic = extrinsics[extrinsicIdx]; - - if (!extrinsic) { - throw new Error( - `Missing extrinsic ${extrinsicIdx} in block ${hash.toString()}` - ); - } - - const method = `${event.section}.${event.method}`; - - if (method === Event.success) { - extrinsic.success = true; - } - - if (method === Event.success || method === Event.failure) { - const sanitizedData = event.data.toJSON() as AnyJson[]; - - for (const data of sanitizedData) { - if (isPaysFee(data)) { - extrinsic.paysFee = - data.paysFee === true || - data.paysFee === 'Yes'; - - break; - } - } - } - - extrinsic.events.push(sanitizedEvent); - } else if (phase.isFinalization) { - onFinalize.events.push(sanitizedEvent); - } else if (phase.isInitialization) { - onInitialize.events.push(sanitizedEvent); - } - } - } - - return { - extrinsics, - onInitialize, - onFinalize, - }; - } - - /** - * Create calcFee from params. - * - * @param api ApiPromise - * @param parentHash Hash of the parent block - * @param block Block which the extrinsic is from - */ - private async createCalcFee( - api: ApiPromise, - parentHash: Hash, - block: Block - ) { - let parentParentHash: Hash; - if (block.header.number.toNumber() > 1) { - parentParentHash = (await api.rpc.chain.getHeader(parentHash)) - .parentHash; - } else { - parentParentHash = parentHash; - } - - const perByte = api.consts.transactionPayment.transactionByteFee; - const extrinsicBaseWeight = api.consts.system.extrinsicBaseWeight; - const multiplier = await api.query.transactionPayment.nextFeeMultiplier.at( - parentHash - ); - // The block where the runtime is deployed falsely proclaims it would - // be already using the new runtime. This workaround therefore uses the - // parent of the parent in order to determine the correct runtime under which - // this block was produced. - const version = await api.rpc.state.getRuntimeVersion(parentParentHash); - const specName = version.specName.toString(); - const specVersion = version.specVersion.toNumber(); - const coefficients = api.consts.transactionPayment.weightToFee.map( - (c) => { - return { - coeffInteger: c.coeffInteger.toString(), - coeffFrac: c.coeffFrac, - degree: c.degree, - negative: c.negative, - }; - } - ); - - return { - calcFee: CalcFee.from_params( - coefficients, - BigInt(extrinsicBaseWeight.toString()), - multiplier.toString(), - perByte.toString(), - specName, - specVersion - ), - specName, - specVersion, - }; - } - - /** - * Fetch events for the specified block. - * - * @param api ApiPromise to use for query - * @param hash `BlockHash` to make query at - */ - private async fetchEvents( - api: ApiPromise, - hash: BlockHash - ): Promise { - try { - return await api.query.system.events.at(hash); - } catch { - return 'Unable to fetch Events, cannot confirm extrinsic status. Check pruning settings on the node.'; - } - } - - /** - * Helper function for `parseGenericCall`. - * - * @param argsArray array of `Codec` values - * @param registry type registry of the block the call belongs to - */ - private parseArrayGenericCalls( - argsArray: Codec[], - registry: Registry - ): (Codec | ISanitizedCall)[] { - return argsArray.map((argument) => { - if (argument instanceof GenericCall) { - return this.parseGenericCall(argument, registry); - } - - return argument; - }); - } - - /** - * Recursively parse a `GenericCall` in order to label its arguments with - * their param names and give a human friendly method name (opposed to just a - * call index). Parses `GenericCall`s that are nested as arguments. - * - * @param genericCall `GenericCall` - * @param registry type registry of the block the call belongs to - */ - private parseGenericCall( - genericCall: GenericCall, - registry: Registry - ): ISanitizedCall { - const { sectionName, methodName, callIndex } = genericCall; - const newArgs = {}; - - // Pull out the struct of arguments to this call - const callArgs = genericCall.get('args') as Struct; - - // Make sure callArgs exists and we can access its keys - if (callArgs && callArgs.defKeys) { - // paramName is a string - for (const paramName of callArgs.defKeys) { - const argument = callArgs.get(paramName); - - if (Array.isArray(argument)) { - newArgs[paramName] = this.parseArrayGenericCalls( - argument, - registry - ); - } else if (argument instanceof GenericCall) { - newArgs[paramName] = this.parseGenericCall( - argument, - registry - ); - } else if ( - paramName === 'call' && - argument?.toRawType() === 'Bytes' - ) { - // multiSig.asMulti.args.call is an OpaqueCall (Vec) that we - // serialize to a polkadot-js Call and parse so it is not a hex blob. - const call = registry.createType('Call', argument.toHex()); - newArgs[paramName] = this.parseGenericCall(call, registry); - } else { - newArgs[paramName] = argument; - } - } - } - - return { - method: `${sectionName}.${methodName}`, - callIndex, - args: newArgs, - }; - } - - // Almost exact mimic of https://github.com/polkadot-js/api/blob/master/packages/api-derive/src/chain/getHeader.ts#L27 - // but we save a call to `getHeader` by hardcoding the logic here and using the digest from the blocks header. - private extractAuthor( - sessionValidators: AccountId[], - digest: Digest - ): AccountId | undefined { - const [pitem] = digest.logs.filter(({ type }) => type === 'PreRuntime'); - - // extract from the substrate 2.0 PreRuntime digest - if (pitem) { - const [engine, data] = pitem.asPreRuntime; - - return engine.extractAuthor(data, sessionValidators); - } else { - const [citem] = digest.logs.filter( - ({ type }) => type === 'Consensus' - ); - - // extract author from the consensus (substrate 1.0, digest) - if (citem) { - const [engine, data] = citem.asConsensus; - - return engine.extractAuthor(data, sessionValidators); - } - } - - return undefined; - } -} diff --git a/src/services/v0/v0blocks/index.ts b/src/services/v0/v0blocks/index.ts deleted file mode 100644 index 0525c9850..000000000 --- a/src/services/v0/v0blocks/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './BlocksService'; diff --git a/src/services/v0/v0claims/ClaimsService.ts b/src/services/v0/v0claims/ClaimsService.ts deleted file mode 100644 index 85f7efecd..000000000 --- a/src/services/v0/v0claims/ClaimsService.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { BlockHash } from '@polkadot/types/interfaces'; - -import { AbstractService } from '../../AbstractService'; - -export class ClaimsService extends AbstractService { - /** - * Fetch claims info for an Ethereum address at a given block. - * - * @param hash `BlockHash` to make query at - * @param ethAddress hex encoded public Ethereum address - */ - async fetchClaimsInfo( - hash: BlockHash, - ethAddress: string - ): Promise { - const { api } = this; - - const agreementType = await api.query.claims.signing.at( - hash, - ethAddress - ); - if (agreementType.isEmpty) { - return null; - } - - return { - type: agreementType.toString(), - }; - } -} diff --git a/src/services/v0/v0claims/index.ts b/src/services/v0/v0claims/index.ts deleted file mode 100644 index ae7854dd6..000000000 --- a/src/services/v0/v0claims/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ClaimsService'; diff --git a/src/services/v0/v0metadata/RuntimeMetadataService.spec.ts b/src/services/v0/v0metadata/RuntimeMetadataService.spec.ts deleted file mode 100644 index f3e6ed73c..000000000 --- a/src/services/v0/v0metadata/RuntimeMetadataService.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { sanitizeNumbers } from '../../../sanitize/sanitizeNumbers'; -import { blockHash789629, mockApi } from '../../test-helpers/mock'; -import * as response789629 from '../../test-helpers/responses/runtime/metadata789629.json'; -import { RuntimeMetadataService } from './RuntimeMetadataService'; - -const runtimeMetadataService = new RuntimeMetadataService(mockApi); - -describe('RuntimeMetadataService', () => { - describe('fetchMetadata', () => { - it('works when ApiPromise works (block 789629)', async () => { - expect( - sanitizeNumbers( - await runtimeMetadataService.fetchMetadata(blockHash789629) - ) - ).toStrictEqual(response789629); - }); - }); -}); diff --git a/src/services/v0/v0metadata/RuntimeMetadataService.ts b/src/services/v0/v0metadata/RuntimeMetadataService.ts deleted file mode 100644 index 4be9178df..000000000 --- a/src/services/v0/v0metadata/RuntimeMetadataService.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Metadata } from '@polkadot/types'; -import { BlockHash } from '@polkadot/types/interfaces'; - -import { AbstractService } from '../../AbstractService'; - -export class RuntimeMetadataService extends AbstractService { - /** - * Fetch `Metadata` in decoded JSON form. - * - * @param hash `BlockHash` to make call at - */ - async fetchMetadata(hash: BlockHash): Promise { - const { api } = this; - - const metadata = await api.rpc.state.getMetadata(hash); - - return metadata; - } -} diff --git a/src/services/v0/v0metadata/index.ts b/src/services/v0/v0metadata/index.ts deleted file mode 100644 index 015841544..000000000 --- a/src/services/v0/v0metadata/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './RuntimeMetadataService'; diff --git a/src/services/v0/v0pallets/PalletsStakingProgressService.spec.ts b/src/services/v0/v0pallets/PalletsStakingProgressService.spec.ts deleted file mode 100644 index cdfd0eac8..000000000 --- a/src/services/v0/v0pallets/PalletsStakingProgressService.spec.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import { sanitizeNumbers } from '../../../sanitize/sanitizeNumbers'; -import { polkadotRegistry } from '../../../test-helpers/registries'; -import { - activeEraAt, - blockHash789629, - erasStartSessionIndexAt, - mockApi, -} from '../../test-helpers/mock'; -import * as palletsStakingProgress789629SResponse from '../../test-helpers/responses/pallets/stakingProgress789629.json'; -import { PalletsStakingProgressService } from './PalletsStakingProgressService'; - -/** - * Mock PalletStakingProgressService instance. - */ -const palletStakingProgressService = new PalletsStakingProgressService(mockApi); - -describe('PalletStakingProgressService', () => { - describe('derivePalletStakingProgress', () => { - it('works when ApiPromise works (block 789629)', async () => { - expect( - sanitizeNumbers( - await palletStakingProgressService.derivePalletStakingProgress( - blockHash789629 - ) - ) - ).toStrictEqual(palletsStakingProgress789629SResponse); - }); - - it('throws when ErasStartSessionIndex.isNone', async () => { - (mockApi.query.staking.erasStartSessionIndex as any).at = () => - Promise.resolve().then(() => - polkadotRegistry.createType('Option', null) - ); - - await expect( - palletStakingProgressService.derivePalletStakingProgress( - blockHash789629 - ) - ).rejects.toStrictEqual({ - statusCode: 500, - error: - 'Unwrapping `await api.query.staking.erasStartSessionIndex.at(hash, activeEra)` returned None when Some was expected', - }); - - (mockApi.query.staking - .erasStartSessionIndex as any).at = erasStartSessionIndexAt; - }); - - it('throws when activeEra.isNone', async () => { - (mockApi.query.staking.activeEra as any).at = () => - Promise.resolve().then(() => - polkadotRegistry.createType('Option', null) - ); - - await expect( - palletStakingProgressService.derivePalletStakingProgress( - blockHash789629 - ) - ).rejects.toStrictEqual({ - statusCode: 500, - error: - 'Unwrapping the result of `await api.query.staking.activeEra.at(hash)` returned None when Some was expected.', - }); - - (mockApi.query.staking.activeEra as any).at = activeEraAt; - }); - }); -}); diff --git a/src/services/v0/v0pallets/PalletsStakingProgressService.ts b/src/services/v0/v0pallets/PalletsStakingProgressService.ts deleted file mode 100644 index c7dde1be6..000000000 --- a/src/services/v0/v0pallets/PalletsStakingProgressService.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { ApiPromise } from '@polkadot/api'; -import { BlockHash, EraIndex } from '@polkadot/types/interfaces'; -import * as BN from 'bn.js'; -import { IPalletStakingProgress } from 'src/types/responses'; - -import * as errors from '../../../../config/errors-en.json'; -import { AbstractService } from '../../AbstractService'; - -export class PalletsStakingProgressService extends AbstractService { - /** - * Fetch and derive generalized staking information at a given block. - * - * @param hash `BlockHash` to make call at - */ - async derivePalletStakingProgress( - hash: BlockHash - ): Promise { - const { api } = this; - - const [ - validatorCount, - forceEra, - eraElectionStatus, - validators, - { number }, - ] = await Promise.all([ - api.query.staking.validatorCount.at(hash), - api.query.staking.forceEra.at(hash), - api.query.staking.eraElectionStatus.at(hash), - api.query.session.validators.at(hash), - api.rpc.chain.getHeader(hash), - ]); - - const { - eraLength, - eraProgress, - sessionLength, - sessionProgress, - activeEra, - } = await this.deriveSessionAndEraProgress(api, hash); - - const unappliedSlashesAtActiveEra = await api.query.staking.unappliedSlashes.at( - hash, - activeEra - ); - - const currentBlockNumber = number.toBn(); - - const nextSession = sessionLength - .sub(sessionProgress) - .add(currentBlockNumber); - - const baseResponse = { - at: { - hash: hash.toJSON(), - height: currentBlockNumber.toString(10), - }, - activeEra: activeEra.toString(10), - forceEra: forceEra.toJSON(), - nextSessionEstimate: nextSession.toString(10), - unappliedSlashes: unappliedSlashesAtActiveEra.map((slash) => - slash.toJSON() - ), - }; - - if (forceEra.isForceNone) { - // Most likely we are in a PoA network with no elections. Things - // like `ValidatorCount` and `Validators` are hardcoded from genesis - // to support a transition into NPoS, but are irrelevant here and would be - // confusing to include. Thus, we craft a response excluding those values. - return baseResponse; - } - - const nextActiveEra = forceEra.isForceAlways - ? nextSession // there is a new era every session - : eraLength.sub(eraProgress).add(currentBlockNumber); // the nextActiveEra is at the end of this era - - const electionLookAhead = await this.deriveElectionLookAhead(api, hash); - - const nextCurrentEra = nextActiveEra - .sub(currentBlockNumber) - .sub(sessionLength) - .gt(new BN(0)) - ? nextActiveEra.sub(sessionLength) // current era simply one session before active era - : nextActiveEra.add(eraLength).sub(sessionLength); // we are in the last session of an active era - - let toggle; - if (electionLookAhead.eq(new BN(0))) { - // no offchain solutions accepted - toggle = null; - } else if (eraElectionStatus.isClose) { - // election window is yet to open - toggle = nextCurrentEra.sub(electionLookAhead); - } else { - // election window closes at the end of the current era - toggle = nextCurrentEra; - } - - return { - ...baseResponse, - nextActiveEraEstimate: nextActiveEra.toString(10), - electionStatus: { - status: eraElectionStatus.toJSON(), - toggleEstimate: toggle?.toString(10) ?? null, - }, - idealValidatorCount: validatorCount.toString(10), - validatorSet: validators.map((accountId) => accountId.toString()), - }; - } - - /** - * Derive information on the progress of the current session and era. - * - * @param api ApiPromise with ensured metadata - * @param hash `BlockHash` to make call at - */ - private async deriveSessionAndEraProgress( - api: ApiPromise, - hash: BlockHash - ): Promise<{ - eraLength: BN; - eraProgress: BN; - sessionLength: BN; - sessionProgress: BN; - activeEra: EraIndex; - }> { - const [ - currentSlot, - epochIndex, - genesisSlot, - currentIndex, - activeEraOption, - ] = await Promise.all([ - api.query.babe.currentSlot.at(hash), - api.query.babe.epochIndex.at(hash), - api.query.babe.genesisSlot.at(hash), - api.query.session.currentIndex.at(hash), - api.query.staking.activeEra.at(hash), - ]); - - if (activeEraOption.isNone) { - // TODO refactor to newer error type - throw errors.ActiveEra_IS_NONE; - } - const { index: activeEra } = activeEraOption.unwrap(); - - const activeEraStartSessionIndexOption = await api.query.staking.erasStartSessionIndex.at( - hash, - activeEra - ); - if (activeEraStartSessionIndexOption.isNone) { - // TODO refactor to newer error type - throw errors.ErasStartSessionIndex_IS_NONE; - } - const activeEraStartSessionIndex = activeEraStartSessionIndexOption.unwrap(); - - const { epochDuration: sessionLength } = api.consts.babe; - const eraLength = api.consts.staking.sessionsPerEra.mul(sessionLength); - const epochStartSlot = epochIndex.mul(sessionLength).add(genesisSlot); - const sessionProgress = currentSlot.sub(epochStartSlot); - const eraProgress = currentIndex - .sub(activeEraStartSessionIndex) - .mul(sessionLength) - .add(sessionProgress); - - return { - eraLength, - eraProgress, - sessionLength, - sessionProgress, - activeEra, - }; - } - - /** - * Get electionLookAhead as a const if available. Otherwise derive - * `electionLookAhead` based on the `specName` & `epochDuration`. - * N.B. Values are hardcoded based on `specName`s polkadot, kusama, and westend. - * There are no guarantees that this will return the expected values for - * other `specName`s. - * - * @param api ApiPromise with ensured metadata - * @param hash `BlockHash` to make call at - */ - private async deriveElectionLookAhead( - api: ApiPromise, - hash: BlockHash - ): Promise { - if (api.consts.staking.electionLookahead) { - return api.consts.staking.electionLookahead; - } - - const { specName } = await api.rpc.state.getRuntimeVersion(hash); - const { epochDuration } = api.consts.babe; - - // TODO - create a configurable epochDivisor env for a more generic solution - const epochDurationDivisor = - specName.toString() === 'polkadot' - ? new BN(16) // polkadot electionLookAhead = epochDuration / 16 - : new BN(4); // kusama, westend, `substrate/bin/node` electionLookAhead = epochDuration / 4 - - return epochDuration.div(epochDurationDivisor); - } -} diff --git a/src/services/v0/v0pallets/index.ts b/src/services/v0/v0pallets/index.ts deleted file mode 100644 index e7a3c6acb..000000000 --- a/src/services/v0/v0pallets/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './PalletsStakingProgressService'; diff --git a/src/services/v0/v0transaction/TransactionFeeEstimateService.ts b/src/services/v0/v0transaction/TransactionFeeEstimateService.ts deleted file mode 100644 index 4d5d5485d..000000000 --- a/src/services/v0/v0transaction/TransactionFeeEstimateService.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { BlockHash, RuntimeDispatchInfo } from '@polkadot/types/interfaces'; - -import { AbstractService } from '../../AbstractService'; -import { extractCauseAndStack } from './extractCauseAndStack'; - -export class TransactionFeeEstimateService extends AbstractService { - /** - * Fetch estimated fee information for a scale encoded extrinsic at a given - * block. - * - * @param hash `BlockHash` to make call at - * @param extrinsic scale encoded extrinsic to get a fee estimate for - */ - async fetchTransactionFeeEstimate( - hash: BlockHash, - extrinsic: string - ): Promise { - const { api } = this; - - try { - return await api.rpc.payment.queryInfo(extrinsic, hash); - } catch (err) { - const { cause, stack } = extractCauseAndStack(err); - - throw { - error: 'Unable to fetch fee info', - data: { - extrinsic, - block: hash.toString(), - }, - cause, - stack, - }; - } - } -} diff --git a/src/services/v0/v0transaction/TransactionMaterialService.spec.ts b/src/services/v0/v0transaction/TransactionMaterialService.spec.ts deleted file mode 100644 index a61b259c1..000000000 --- a/src/services/v0/v0transaction/TransactionMaterialService.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { sanitizeNumbers } from '../../../sanitize/sanitizeNumbers'; -import { blockHash789629, mockApi } from '../../test-helpers/mock'; -import * as response789629 from '../../test-helpers/responses/transaction/material789629.json'; -import { TransactionMaterialService } from './TransactionMaterialService'; - -const transactionMaterialService = new TransactionMaterialService(mockApi); - -describe('TransactionMaterialService', () => { - describe('getTransactionMaterial', () => { - it('works when ApiPromise works (block 789629)', async () => { - expect( - sanitizeNumbers( - await transactionMaterialService.fetchTransactionMaterial( - blockHash789629, - false - ) - ) - ).toStrictEqual(response789629); - }); - }); -}); diff --git a/src/services/v0/v0transaction/TransactionMaterialService.ts b/src/services/v0/v0transaction/TransactionMaterialService.ts deleted file mode 100644 index 41bcd3c46..000000000 --- a/src/services/v0/v0transaction/TransactionMaterialService.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { BlockHash } from '@polkadot/types/interfaces'; -import { ITransactionMaterial } from 'src/types/responses'; - -import { AbstractService } from '../../AbstractService'; - -export class TransactionMaterialService extends AbstractService { - /** - * Fetch the baseline "material" at a given block to construct a transaction - * offline. - * - * @param hash `BlockHash` to make call at - */ - async fetchTransactionMaterial( - hash: BlockHash, - noMeta: boolean - ): Promise { - const { api } = this; - - if (noMeta) { - const [header, genesisHash, name, version] = await Promise.all([ - api.rpc.chain.getHeader(hash), - api.rpc.chain.getBlockHash(0), - api.rpc.system.chain(), - api.rpc.state.getRuntimeVersion(hash), - ]); - - const at = { - hash, - height: header.number.toNumber().toString(10), - }; - - return { - at, - genesisHash, - chainName: name.toString(), - specName: version.specName.toString(), - specVersion: version.specVersion, - txVersion: version.transactionVersion, - }; - } - - const [ - header, - metadata, - genesisHash, - name, - version, - ] = await Promise.all([ - api.rpc.chain.getHeader(hash), - api.rpc.state.getMetadata(hash), - api.rpc.chain.getBlockHash(0), - api.rpc.system.chain(), - api.rpc.state.getRuntimeVersion(hash), - ]); - - const at = { - hash, - height: header.number.toNumber().toString(10), - }; - - return { - at, - genesisHash, - chainName: name.toString(), - specName: version.specName.toString(), - specVersion: version.specVersion, - txVersion: version.transactionVersion, - metadata: metadata.toHex(), - }; - } -} diff --git a/src/services/v0/v0transaction/TransactionSubmitService.ts b/src/services/v0/v0transaction/TransactionSubmitService.ts deleted file mode 100644 index 1e3088fa1..000000000 --- a/src/services/v0/v0transaction/TransactionSubmitService.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Hash } from '@polkadot/types/interfaces'; - -import { AbstractService } from '../../AbstractService'; -import { extractCauseAndStack } from '../../transaction/extractCauseAndStack'; - -export class TransactionSubmitService extends AbstractService { - /** - * Submit a fully formed scale encoded extrinsic for block inclusion. - * - * @param extrinsic scale encoded extrinsic to submit - */ - async submitTransaction(extrinsic: string): Promise<{ hash: Hash }> { - const { api } = this; - - let tx; - - try { - tx = api.tx(extrinsic); - } catch (err) { - const { cause, stack } = extractCauseAndStack(err); - - throw { - error: 'Failed to parse a tx', - data: extrinsic, - cause, - stack, - }; - } - - try { - const hash = await api.rpc.author.submitExtrinsic(tx); - - return { - hash, - }; - } catch (err) { - const { cause, stack } = extractCauseAndStack(err); - - throw { - error: 'Failed to submit a tx', - data: extrinsic, - cause, - stack, - }; - } - } -} diff --git a/src/services/v0/v0transaction/extractCauseAndStack.ts b/src/services/v0/v0transaction/extractCauseAndStack.ts deleted file mode 100644 index 0c7cf47ab..000000000 --- a/src/services/v0/v0transaction/extractCauseAndStack.ts +++ /dev/null @@ -1,18 +0,0 @@ -// TODO look into creating a base class for transactions and move this into that base class - -import { isToString } from '../../../types/util'; - -export function extractCauseAndStack( - err: unknown -): { cause: string | unknown; stack: string | undefined } { - const cause = - err instanceof Error - ? err.message - : isToString(err) - ? err.toString() - : err; - - const stack = err instanceof Error ? err.stack : ''; - - return { cause, stack }; -} diff --git a/src/services/v0/v0transaction/index.ts b/src/services/v0/v0transaction/index.ts deleted file mode 100644 index 9fb461ed7..000000000 --- a/src/services/v0/v0transaction/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './TransactionSubmitService'; -export * from './TransactionFeeEstimateService'; -export * from './TransactionMaterialService';