Gotta Set That Gas!

It’s never a dull moment here at the Bearmint Minin’ Company, friends! Yep, we’re always busy workin’ on makin’ improvements and using the best tech available to make things easier fer developers all over the world. We also understand that without sharin’ our vast knowledge with others, it’ll be mighty hard for most of ‘em to figure out how to get what we’ve made to work!

This is exactly why our last few blogs have covered how to build and implement several different components fer yer application. Blockchains ain’t just made from one thing but many different interconnected parts that allow fer different transactions to take place. If even one of these parts doesn’t do its job properly, well, you may just be in fer a world of hurt! This is one of the many reasons why we’ve done our best to take care of all the hard work fer you so that buildin’ and launchin’ yer own application is far less stressful, expensive and time-consumin’!

Now nothin’ in this life is free, and fer the pleasure of harnessin’ the power of an extensive decentralized network, people need to pay a fee (usually a pretty small one, but this might depend on several different factors). In blockchains, we refer to the network fee as “gas.” But just how do you go about figurin’ out exactly how much folks should pay fer the privilege of havin’ their transactions securely handled?

This is why a gas meter, which basically calculates gas accordin’ to a particular strategy (fer example, fixed or dynamic) is non-negotiable. You obviously don’t want to have to perform this task manually, and with blockchains that handle thousands and thousands of transactions, it goes without sayin’ that the whole process needs to be automated, accurate and consistent. It’s just that simple!

So in today’s (relatively short) guide, we’ll show you just how to build and implement a gas meter of yer own. If you follow our lead and exercise a little care, you’ll be done in no time at all! However, as always, before we get into the details, we ask that you familiarize yerself (or refresh yer memory) by takin’ a look at some important definitions before proceedin’ to read the guide itself…

Could You Help Me Figure This Out, Partner?

  • @bearmint/bep9 is an NPM package that offers an implementation of BEP-009 which contains a set of utilities to deal with particularly tedious tasks that do not fall within a single domain
  • @bearmint/bep13 is an NPM package that offers an implementation of BEP-013 which allows for the sharing of a set of types between all the modules that exist within Bearmint
  • @bearmint/bep16 is an NPM package that offers an implementation of BEP-016 which contains a standardized method of bootstrapping the plugins and application via service providers
  • @bearmint/bep109 is an NPM package that offers an implementation of BEP-109 which provides a single module that exposes various exceptions and allows for sharing between modules without circular dependencies arising

Meter

To begin, you will simply use the following code to set up a gas meter.

import type { Cradle, GasMeter } from '@bearmint/bep13';
import {
TransactionGasTooHighException,
TransactionGasTooLowException,
TransactionHandlerHasNoGasException,
} from '@bearmint/bep109';
import { denom, getModuleMilestone } from '@bearmint/bep21';
import { readPackageJson } from '@bearmint/bep9';
const packageJSON = readPackageJson(__dirname);
export function makeGasMeter(cradle: Cradle): GasMeter {
return {
async measure({ checksum, data, type }) {
const milestone = getModuleMilestone({
handler: packageJSON.name,
state: cradle.DeliverTxState,
version: packageJSON.version,
}).messages[checksum.handler];
const expected = milestone[checksum.version] ?? milestone['*'];
if (expected === undefined) {
throw new TransactionHandlerHasNoGasException(type);
}
if (data.gas.isEqualTo(expected)) {
return data.gas;
}
if (data.gas.isLessThan(expected)) {
throw new TransactionGasTooLowException({
actual: data.gas,
denomination: denom({ state: cradle.DeliverTxState, type: 'gas' }),
expected,
hash: data.hash,
});
}
throw new TransactionGasTooHighException({
actual: data.gas,
denomination: denom({ state: cradle.DeliverTxState, type: 'gas' }),
expected,
hash: data.hash,
});
},
};
}

Registering With the Application

To finish, we simply bind our newly-created function to the container as ContainerType.GasMeter. Bearmint will now use our gas meter whenever it needs to calculate transaction fees.

import { ContainerType, Cradle, ServiceProvider } from '@bearmint/bep13';
import { makeServiceProviderSkeleton } from '@bearmint/bep16';
import { makeGasMeter } from './meter';
function makeServiceProvider(cradle: Cradle): ServiceProvider {
return {
...makeServiceProviderSkeleton(__dirname),
async register() {
cradle.Container.bind(ContainerType.GasMeter).toFunctionSingleton(makeGasMeter);
},
};
}

Couldn’t Be Any Simpler, Could It?

Were you maybe expectin’ a little more, Pilgrims? Well, this particular process couldn’t have been much simpler if we do say so ourselves. Of course, if fer some reason this ain’t what yer lookin’ fer or have a unique question, please feel free to get in touch with us so that we can help you figure out a solution to yer issue. We would never want to leave anyone high and dry, and we know fer a fact that Buckley simply wouldn’t allow it! So as always, give us a holler if you need a helpin’ hand, and we guarantee you that we’ll come runnin’!