Skip to content

Commit

Permalink
added bool to calc fees
Browse files Browse the repository at this point in the history
  • Loading branch information
bee344 committed Dec 21, 2023
1 parent eece4aa commit 979830b
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 96 deletions.
1 change: 1 addition & 0 deletions src/SidecarConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export class SidecarConfig {
TYPES_CHAIN: config.Get(MODULES.SUBSTRATE, CONFIG.TYPES_CHAIN) as string,
TYPES_SPEC: config.Get(MODULES.SUBSTRATE, CONFIG.TYPES_SPEC) as string,
TYPES: config.Get(MODULES.SUBSTRATE, CONFIG.TYPES) as string,
CALC_FEE: config.Get(MODULES.SUBSTRATE, CONFIG.CALC_FEE) as boolean,
},
LOG: {
LEVEL: config.Get(MODULES.LOG, CONFIG.LEVEL) as string,
Expand Down
13 changes: 13 additions & 0 deletions src/Specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ export class Specs {
mandatory: false,
}),
);
// CALC_FEE
this._specs.appendSpec(
MODULES.SUBSTRATE,
this._specs.getSpec(

Check failure on line 157 in src/Specs.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `⏎↹↹↹↹CONFIG.CALC_FEE,⏎↹↹↹↹'boolean·to·calculate·or·not·partial·fees',⏎↹↹↹↹` with `CONFIG.CALC_FEE,·'boolean·to·calculate·or·not·partial·fees',·`
CONFIG.CALC_FEE,
'boolean to calculate or not partial fees',
{
default: 'true',

Check failure on line 161 in src/Specs.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `↹`
type: 'boolean',

Check failure on line 162 in src/Specs.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `↹`
mandatory: false,

Check failure on line 163 in src/Specs.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `↹`
},

Check failure on line 164 in src/Specs.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `↹},⏎↹↹↹` with `}`
),
);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/chains-config/polkadotControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import { ControllerConfig } from '../types/chains-config';

Check failure on line 17 in src/chains-config/polkadotControllers.ts

View workflow job for this annotation

GitHub Actions / lint

Run autofix to sort these imports!
import { SidecarConfig } from '../../src/SidecarConfig'

Check failure on line 18 in src/chains-config/polkadotControllers.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `;`
import { initLRUCache, QueryFeeDetailsCache } from './cache';

/**
Expand Down Expand Up @@ -57,5 +58,6 @@ export const polkadotControllers: ControllerConfig = {
minCalcFeeRuntime: 0,
blockStore: initLRUCache(),
hasQueryFeeApi: new QueryFeeDetailsCache(27, 28),
calcFee: SidecarConfig.config.SUBSTRATE.CALC_FEE,
},
};
2 changes: 1 addition & 1 deletion src/controllers/blocks/BlocksController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default class BlocksController extends AbstractController<BlocksService>
super(
api,
'/blocks',
new BlocksService(api, options.minCalcFeeRuntime, options.blockStore, options.hasQueryFeeApi),
new BlocksService(api, options.minCalcFeeRuntime, options.blockStore, options.hasQueryFeeApi, options.calcFee),
);
this.initRoutes();
}
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/blocks/BlocksExtrinsicsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default class BlocksExtrinsicsController extends AbstractController<Block
super(
api,
'/blocks/:blockId/extrinsics',
new BlocksService(api, options.minCalcFeeRuntime, options.blockStore, options.hasQueryFeeApi),
new BlocksService(api, options.minCalcFeeRuntime, options.blockStore, options.hasQueryFeeApi, options.calcFee),
);
this.initRoutes();
}
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/blocks/BlocksRawExtrinsicsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default class BlocksRawExtrinsicsController extends AbstractController<Bl
super(
api,
'/blocks/:blockId/extrinsics-raw',
new BlocksService(api, options.minCalcFeeRuntime, options.blockStore, options.hasQueryFeeApi),
new BlocksService(api, options.minCalcFeeRuntime, options.blockStore, options.hasQueryFeeApi, options.calcFee),
);
this.initRoutes();
}
Expand Down
195 changes: 102 additions & 93 deletions src/services/blocks/BlocksService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export class BlocksService extends AbstractService {
private minCalcFeeRuntime: IOption<number>,
private blockStore: LRU<string, IBlock>,
private hasQueryFeeApi: QueryFeeDetailsCache,
private calcFee?: boolean,
) {
super(api);
}
Expand Down Expand Up @@ -168,124 +169,132 @@ export class BlocksService extends AbstractService {
const previousBlockHash = await this.fetchPreviousBlockHash(number);

for (let idx = 0; idx < block.extrinsics.length; ++idx) {
if (!extrinsics[idx].paysFee || !block.extrinsics[idx].isSigned) {
continue;
}
if (this.calcFee) {
console.log("Calc fee true", this.calcFee)

Check failure on line 173 in src/services/blocks/BlocksService.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `"Calc·fee·true",·this.calcFee)` with `'Calc·fee·true',·this.calcFee);`

if (this.minCalcFeeRuntime === null) {
extrinsics[idx].info = {
error: `Fee calculation not supported for this network`,
};
continue;
}
if (!extrinsics[idx].paysFee || !block.extrinsics[idx].isSigned) {
continue;
}

if (this.minCalcFeeRuntime > specVersion.toNumber()) {
extrinsics[idx].info = {
error: `Fee calculation not supported for ${specVersion.toString()}#${specName.toString()}`,
};
continue;
}
if (this.minCalcFeeRuntime === null) {
extrinsics[idx].info = {
error: `Fee calculation not supported for this network`,
};
continue;
}

const xtEvents = extrinsics[idx].events;
const completedEvent = xtEvents.find(
({ method }) => isFrameMethod(method) && (method.method === Event.success || method.method === Event.failure),
);
if (this.minCalcFeeRuntime > specVersion.toNumber()) {
extrinsics[idx].info = {
error: `Fee calculation not supported for ${specVersion.toString()}#${specName.toString()}`,
};
continue;
}

if (!completedEvent) {
extrinsics[idx].info = {
error: 'Unable to find success or failure event for extrinsic',
};
const xtEvents = extrinsics[idx].events;
const completedEvent = xtEvents.find(
({ method }) => isFrameMethod(method) && (method.method === Event.success || method.method === Event.failure),
);

continue;
}
if (!completedEvent) {
extrinsics[idx].info = {
error: 'Unable to find success or failure event for extrinsic',
};

const completedData = completedEvent.data;
if (!completedData) {
extrinsics[idx].info = {
error: 'Success or failure event for extrinsic does not contain expected data',
};
continue;
}

continue;
}
const completedData = completedEvent.data;
if (!completedData) {
extrinsics[idx].info = {
error: 'Success or failure event for extrinsic does not contain expected data',
};

// 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;
}

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',
};

if (!api.rpc.payment?.queryInfo && !api.call.transactionPaymentApi?.queryInfo) {
extrinsics[idx].info = {
error: 'Rpc method payment::queryInfo is not available',
};
continue;
}

continue;
}
if (!api.rpc.payment?.queryInfo && !api.call.transactionPaymentApi?.queryInfo) {
extrinsics[idx].info = {
error: 'Rpc method payment::queryInfo is not available',
};

/**
* Grab the initial partialFee, and information required for calculating a partialFee
* if queryFeeDetails is available in the runtime.
*/
const {
class: dispatchClass,
partialFee,
weight,
} = await this.fetchQueryInfo(block.extrinsics[idx], previousBlockHash);
const versionedWeight = (weight as Weight).refTime ? (weight as Weight).refTime.unwrap() : (weight as WeightV1);

const transactionPaidFeeEvent = xtEvents.find(
({ method }) => isFrameMethod(method) && method.method === Event.transactionPaidFee,
);
continue;
}

let finalPartialFee = partialFee.toString(),
dispatchFeeType = 'preDispatch';
if (transactionPaidFeeEvent) {
finalPartialFee = transactionPaidFeeEvent.data[1].toString();
dispatchFeeType = 'fromEvent';
} else {
/**
* Call queryFeeDetails. It may not be available in the runtime and will
* error automatically when we try to call it. We cache the runtimes it will error so we
* don't try to call it again given a specVersion.
* Grab the initial partialFee, and information required for calculating a partialFee
* if queryFeeDetails is available in the runtime.
*/
const doesQueryFeeDetailsExist = this.hasQueryFeeApi.hasQueryFeeDetails(specVersion.toNumber());
if (doesQueryFeeDetailsExist === 'available') {
finalPartialFee = await this.fetchQueryFeeDetails(
block.extrinsics[idx],
previousBlockHash,
weightInfo.weight,
versionedWeight.toString(),
);

dispatchFeeType = 'postDispatch';
} else if (doesQueryFeeDetailsExist === 'unknown') {
try {
const {
class: dispatchClass,
partialFee,
weight,
} = await this.fetchQueryInfo(block.extrinsics[idx], previousBlockHash);
const versionedWeight = (weight as Weight).refTime ? (weight as Weight).refTime.unwrap() : (weight as WeightV1);

const transactionPaidFeeEvent = xtEvents.find(
({ method }) => isFrameMethod(method) && method.method === Event.transactionPaidFee,
);

let finalPartialFee = partialFee.toString(),
dispatchFeeType = 'preDispatch';
if (transactionPaidFeeEvent) {
finalPartialFee = transactionPaidFeeEvent.data[1].toString();
dispatchFeeType = 'fromEvent';
} else {
/**
* Call queryFeeDetails. It may not be available in the runtime and will
* error automatically when we try to call it. We cache the runtimes it will error so we
* don't try to call it again given a specVersion.
*/
const doesQueryFeeDetailsExist = this.hasQueryFeeApi.hasQueryFeeDetails(specVersion.toNumber());
if (doesQueryFeeDetailsExist === 'available') {
finalPartialFee = await this.fetchQueryFeeDetails(
block.extrinsics[idx],
previousBlockHash,
weightInfo.weight,
versionedWeight.toString(),
);

dispatchFeeType = 'postDispatch';
this.hasQueryFeeApi.setRegisterWithCall(specVersion.toNumber());
} catch {
this.hasQueryFeeApi.setRegisterWithoutCall(specVersion.toNumber());
console.warn('The error above is automatically emitted from polkadot-js, and can be ignored.');
} else if (doesQueryFeeDetailsExist === 'unknown') {
try {
finalPartialFee = await this.fetchQueryFeeDetails(
block.extrinsics[idx],
previousBlockHash,
weightInfo.weight,
versionedWeight.toString(),
);
dispatchFeeType = 'postDispatch';
this.hasQueryFeeApi.setRegisterWithCall(specVersion.toNumber());
} catch {
this.hasQueryFeeApi.setRegisterWithoutCall(specVersion.toNumber());
console.warn('The error above is automatically emitted from polkadot-js, and can be ignored.');
}
}
}
}

extrinsics[idx].info = {
weight: weightInfo.weight,
class: dispatchClass,
partialFee: api.registry.createType('Balance', finalPartialFee),
kind: dispatchFeeType,
};
extrinsics[idx].info = {
weight: weightInfo.weight,
class: dispatchClass,
partialFee: api.registry.createType('Balance', finalPartialFee),
kind: dispatchFeeType,
};
} else {
console.log("Calc fee false", this.calcFee)

Check failure on line 294 in src/services/blocks/BlocksService.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `"Calc·fee·false",·this.calcFee)` with `'Calc·fee·false',·this.calcFee);`

extrinsics[idx].info = {}

Check failure on line 296 in src/services/blocks/BlocksService.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `;`
}
}

const response = {
Expand Down
4 changes: 4 additions & 0 deletions src/types/chains-config/ControllerConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,8 @@ export interface ControllerOptions {
* Cache for storing runtime versions that either have queryFeeDetails, or dont.
*/
hasQueryFeeApi: QueryFeeDetailsCache;
/**
* @default = true
*/
calcFee?: boolean;
}
1 change: 1 addition & 0 deletions src/types/sidecar-config/CONFIG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ export enum CONFIG {
WRITE_PATH = 'WRITE_PATH',
WRITE_MAX_FILE_SIZE = 'WRITE_MAX_FILE_SIZE',
WRITE_MAX_FILES = 'WRITE_MAX_FILES',
CALC_FEE = 'CALC_FEE'
}
1 change: 1 addition & 0 deletions src/types/sidecar-config/SidecarConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface ISidecarConfigSubstrate {
TYPES_CHAIN: string;
TYPES_SPEC: string;
TYPES: string;
CALC_FEE: boolean;
}

interface ISidecarConfigExpress {
Expand Down

0 comments on commit 979830b

Please sign in to comment.