mirror of
https://github.com/cerc-io/watcher-ts
synced 2024-11-19 20:36:19 +00:00
Handle BigNumber event params and customize Decimal (#63)
* Handle BigNumber event params in watchers * Customize decimal according to limits of IEEE-754 decimal128 * Add definition for custom scalar BigDecimal
This commit is contained in:
parent
238ad21189
commit
94e9182dd3
@ -591,7 +591,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
eventInfo = {
|
eventInfo = {
|
||||||
{{#each event.params}}
|
{{#each event.params}}
|
||||||
{{#if (compare this.type 'bigint')}}
|
{{#if (compare this.type 'bigint')}}
|
||||||
{{this.name}}: BigInt(ethers.BigNumber.from({{this.name}}).toString())
|
{{this.name}}: BigInt({{this.name}}.toString())
|
||||||
{{~else}}
|
{{~else}}
|
||||||
{{this.name}}
|
{{this.name}}
|
||||||
{{~/if}}
|
{{~/if}}
|
||||||
|
@ -624,7 +624,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
eventInfo = {
|
eventInfo = {
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
value: BigInt(ethers.BigNumber.from(value).toString())
|
value: BigInt(value.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -635,7 +635,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
eventInfo = {
|
eventInfo = {
|
||||||
owner,
|
owner,
|
||||||
spender,
|
spender,
|
||||||
value: BigInt(ethers.BigNumber.from(value).toString())
|
value: BigInt(value.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -679,8 +679,8 @@ export class Indexer implements IndexerInterface {
|
|||||||
slot,
|
slot,
|
||||||
owner,
|
owner,
|
||||||
delegate,
|
delegate,
|
||||||
newBidAmount,
|
newBidAmount: BigInt(newBidAmount.toString()),
|
||||||
oldBidAmount,
|
oldBidAmount: BigInt(oldBidAmount.toString()),
|
||||||
taxNumerator,
|
taxNumerator,
|
||||||
taxDenominator
|
taxDenominator
|
||||||
};
|
};
|
||||||
@ -704,7 +704,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
const { staker, stakeAmount } = logDescription.args;
|
const { staker, stakeAmount } = logDescription.args;
|
||||||
eventInfo = {
|
eventInfo = {
|
||||||
staker,
|
staker,
|
||||||
stakeAmount: BigInt(ethers.BigNumber.from(stakeAmount).toString())
|
stakeAmount: BigInt(stakeAmount.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -714,7 +714,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
const { staker, unstakedAmount } = logDescription.args;
|
const { staker, unstakedAmount } = logDescription.args;
|
||||||
eventInfo = {
|
eventInfo = {
|
||||||
staker,
|
staker,
|
||||||
unstakedAmount: BigInt(ethers.BigNumber.from(unstakedAmount).toString())
|
unstakedAmount: BigInt(unstakedAmount.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -724,7 +724,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
const { withdrawer, withdrawalAmount } = logDescription.args;
|
const { withdrawer, withdrawalAmount } = logDescription.args;
|
||||||
eventInfo = {
|
eventInfo = {
|
||||||
withdrawer,
|
withdrawer,
|
||||||
withdrawalAmount: BigInt(ethers.BigNumber.from(withdrawalAmount).toString())
|
withdrawalAmount: BigInt(withdrawalAmount.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -748,7 +748,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
eventInfo = {
|
eventInfo = {
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
tokenId: BigInt(ethers.BigNumber.from(tokenId).toString())
|
tokenId: BigInt(tokenId.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -759,7 +759,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
eventInfo = {
|
eventInfo = {
|
||||||
owner,
|
owner,
|
||||||
approved,
|
approved,
|
||||||
tokenId: BigInt(ethers.BigNumber.from(tokenId).toString())
|
tokenId: BigInt(tokenId.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -813,10 +813,10 @@ export class Indexer implements IndexerInterface {
|
|||||||
eventName = logDescription.name;
|
eventName = logDescription.name;
|
||||||
const { index, totalEarned, account, claimed } = logDescription.args;
|
const { index, totalEarned, account, claimed } = logDescription.args;
|
||||||
eventInfo = {
|
eventInfo = {
|
||||||
index: BigInt(ethers.BigNumber.from(index).toString()),
|
index: BigInt(index.toString()),
|
||||||
totalEarned: BigInt(ethers.BigNumber.from(totalEarned).toString()),
|
totalEarned: BigInt(totalEarned.toString()),
|
||||||
account,
|
account,
|
||||||
claimed: BigInt(ethers.BigNumber.from(claimed).toString())
|
claimed: BigInt(claimed.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -826,7 +826,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
const { account, slashed } = logDescription.args;
|
const { account, slashed } = logDescription.args;
|
||||||
eventInfo = {
|
eventInfo = {
|
||||||
account,
|
account,
|
||||||
slashed: BigInt(ethers.BigNumber.from(slashed).toString())
|
slashed: BigInt(slashed.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -836,7 +836,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
const { merkleRoot, distributionNumber, metadataURI } = logDescription.args;
|
const { merkleRoot, distributionNumber, metadataURI } = logDescription.args;
|
||||||
eventInfo = {
|
eventInfo = {
|
||||||
merkleRoot,
|
merkleRoot,
|
||||||
distributionNumber: BigInt(ethers.BigNumber.from(distributionNumber).toString()),
|
distributionNumber: BigInt(distributionNumber.toString()),
|
||||||
metadataURI
|
metadataURI
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -847,8 +847,8 @@ export class Indexer implements IndexerInterface {
|
|||||||
const { account, totalClaimed, totalSlashed } = logDescription.args;
|
const { account, totalClaimed, totalSlashed } = logDescription.args;
|
||||||
eventInfo = {
|
eventInfo = {
|
||||||
account,
|
account,
|
||||||
totalClaimed: BigInt(ethers.BigNumber.from(totalClaimed).toString()),
|
totalClaimed: BigInt(totalClaimed.toString()),
|
||||||
totalSlashed: BigInt(ethers.BigNumber.from(totalSlashed).toString())
|
totalSlashed: BigInt(totalSlashed.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -858,7 +858,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
const { value, id } = logDescription.args;
|
const { value, id } = logDescription.args;
|
||||||
eventInfo = {
|
eventInfo = {
|
||||||
value,
|
value,
|
||||||
id: BigInt(ethers.BigNumber.from(id).toString())
|
id: BigInt(id.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -877,7 +877,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
eventName = logDescription.name;
|
eventName = logDescription.name;
|
||||||
const { updateThreshold } = logDescription.args;
|
const { updateThreshold } = logDescription.args;
|
||||||
eventInfo = {
|
eventInfo = {
|
||||||
updateThreshold: BigInt(ethers.BigNumber.from(updateThreshold).toString())
|
updateThreshold: BigInt(updateThreshold.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import BigInt from 'apollo-type-bigint';
|
import BigInt from 'apollo-type-bigint';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
|
import Decimal from 'decimal.js';
|
||||||
|
import { GraphQLScalarType } from 'graphql';
|
||||||
|
|
||||||
import { BlockHeight } from '@vulcanize/util';
|
import { BlockHeight } from '@vulcanize/util';
|
||||||
|
|
||||||
@ -38,6 +40,19 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
return {
|
return {
|
||||||
BigInt: new BigInt('bigInt'),
|
BigInt: new BigInt('bigInt'),
|
||||||
|
|
||||||
|
BigDecimal: new GraphQLScalarType({
|
||||||
|
name: 'BigDecimal',
|
||||||
|
description: 'BigDecimal custom scalar type',
|
||||||
|
parseValue (value) {
|
||||||
|
// value from the client
|
||||||
|
return new Decimal(value);
|
||||||
|
},
|
||||||
|
serialize (value: Decimal) {
|
||||||
|
// value sent to the client
|
||||||
|
return value.toFixed();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
Event: {
|
Event: {
|
||||||
__resolveType: (obj: any) => {
|
__resolveType: (obj: any) => {
|
||||||
assert(obj.__typename);
|
assert(obj.__typename);
|
||||||
|
@ -35,11 +35,16 @@ describe('call handler in mapping code', () => {
|
|||||||
|
|
||||||
sandbox.on(db, 'fromGraphEntity', async (instanceExports: any, block: Block, entity: string, entityInstance: any) => {
|
sandbox.on(db, 'fromGraphEntity', async (instanceExports: any, block: Block, entity: string, entityInstance: any) => {
|
||||||
const entityFields = [
|
const entityFields = [
|
||||||
{ type: 'varchar', propertyName: 'blockHash' },
|
{ type: 'varchar', propertyName: 'id' },
|
||||||
{ type: 'integer', propertyName: 'blockNumber' },
|
|
||||||
{ type: 'bigint', propertyName: 'count' },
|
{ type: 'bigint', propertyName: 'count' },
|
||||||
{ type: 'varchar', propertyName: 'param1' },
|
{ type: 'varchar', propertyName: 'paramString' },
|
||||||
{ type: 'integer', propertyName: 'param2' }
|
{ type: 'integer', propertyName: 'paramInt' },
|
||||||
|
{ type: 'bigint', propertyName: 'paramBigInt' },
|
||||||
|
{ type: 'boolean', propertyName: 'paramBoolean' },
|
||||||
|
{ type: 'varchar', propertyName: 'paramBytes' },
|
||||||
|
{ type: 'numeric', propertyName: 'paramBigDecimal' },
|
||||||
|
{ type: 'varchar', propertyName: 'related' },
|
||||||
|
{ type: 'varchar', propertyName: 'manyRelated' }
|
||||||
];
|
];
|
||||||
|
|
||||||
return db.getEntityValues(instanceExports, block, entityInstance, entityFields);
|
return db.getEntityValues(instanceExports, block, entityInstance, entityFields);
|
||||||
@ -69,12 +74,13 @@ describe('call handler in mapping code', () => {
|
|||||||
|
|
||||||
// Create event params data.
|
// Create event params data.
|
||||||
const contractInterface = new utils.Interface(abi);
|
const contractInterface = new utils.Interface(abi);
|
||||||
const eventFragment = contractInterface.getEvent('Test(string,uint8)');
|
const eventFragment = contractInterface.getEvent('Test(string,uint8,uint256)');
|
||||||
dummyEventData.inputs = eventFragment.inputs;
|
dummyEventData.inputs = eventFragment.inputs;
|
||||||
|
|
||||||
dummyEventData.event = {
|
dummyEventData.event = {
|
||||||
param1: 'abc',
|
param1: 'abc',
|
||||||
param2: BigInt(123)
|
param2: BigInt(150),
|
||||||
|
param3: BigInt(564894232132154)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dummy contract address string.
|
// Dummy contract address string.
|
||||||
|
@ -11,7 +11,6 @@ import {
|
|||||||
Contract,
|
Contract,
|
||||||
ContractInterface
|
ContractInterface
|
||||||
} from 'ethers';
|
} from 'ethers';
|
||||||
import Decimal from 'decimal.js';
|
|
||||||
import JSONbig from 'json-bigint';
|
import JSONbig from 'json-bigint';
|
||||||
import BN from 'bn.js';
|
import BN from 'bn.js';
|
||||||
|
|
||||||
@ -19,7 +18,7 @@ import loader from '@vulcanize/assemblyscript/lib/loader';
|
|||||||
import { IndexerInterface } from '@vulcanize/util';
|
import { IndexerInterface } from '@vulcanize/util';
|
||||||
|
|
||||||
import { TypeId } from './types';
|
import { TypeId } from './types';
|
||||||
import { Block, fromEthereumValue, toEthereumValue, resolveEntityFieldConflicts } from './utils';
|
import { Block, fromEthereumValue, toEthereumValue, resolveEntityFieldConflicts, GraphDecimal, digitsToString } from './utils';
|
||||||
import { Database } from './database';
|
import { Database } from './database';
|
||||||
|
|
||||||
const NETWORK_URL = 'http://127.0.0.1:8081';
|
const NETWORK_URL = 'http://127.0.0.1:8081';
|
||||||
@ -238,12 +237,12 @@ export const instantiate = async (
|
|||||||
// Creating decimal x.
|
// Creating decimal x.
|
||||||
const xBigDecimal = await BigDecimal.wrap(x);
|
const xBigDecimal = await BigDecimal.wrap(x);
|
||||||
const xStringPtr = await xBigDecimal.toString();
|
const xStringPtr = await xBigDecimal.toString();
|
||||||
const xDecimal = new Decimal(__getString(xStringPtr));
|
const xDecimal = new GraphDecimal(__getString(xStringPtr));
|
||||||
|
|
||||||
// Create decimal y.
|
// Create decimal y.
|
||||||
const yBigDecimal = await BigDecimal.wrap(y);
|
const yBigDecimal = await BigDecimal.wrap(y);
|
||||||
const yStringPtr = await yBigDecimal.toString();
|
const yStringPtr = await yBigDecimal.toString();
|
||||||
const yDecimal = new Decimal(__getString(yStringPtr));
|
const yDecimal = new GraphDecimal(__getString(yStringPtr));
|
||||||
|
|
||||||
// Performing the decimal division operation.
|
// Performing the decimal division operation.
|
||||||
const divResult = xDecimal.dividedBy(yDecimal);
|
const divResult = xDecimal.dividedBy(yDecimal);
|
||||||
@ -267,17 +266,19 @@ export const instantiate = async (
|
|||||||
const expStringPtr = await expBigInt.toString();
|
const expStringPtr = await expBigInt.toString();
|
||||||
const exp = __getString(expStringPtr);
|
const exp = __getString(expStringPtr);
|
||||||
|
|
||||||
const decimal = new Decimal(`${digits}e${exp}`);
|
const decimal = new GraphDecimal(`${digits}e${exp}`);
|
||||||
const ptr = __newString(decimal.toFixed());
|
const ptr = __newString(decimal.toFixed());
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
},
|
},
|
||||||
'bigDecimal.fromString': async (s: number) => {
|
'bigDecimal.fromString': async (s: number) => {
|
||||||
const string = __getString(s);
|
const string = __getString(s);
|
||||||
const decimal = new Decimal(string);
|
|
||||||
|
// Creating a decimal with the configured precision applied.
|
||||||
|
const decimal = new GraphDecimal(string).toSignificantDigits();
|
||||||
|
|
||||||
// Convert from digits array to BigInt.
|
// Convert from digits array to BigInt.
|
||||||
const digits = decimal.d.join('');
|
const digits = digitsToString(decimal.d);
|
||||||
const digitsBigNumber = BigNumber.from(digits);
|
const digitsBigNumber = BigNumber.from(digits);
|
||||||
const signBigNumber = BigNumber.from(decimal.s);
|
const signBigNumber = BigNumber.from(decimal.s);
|
||||||
const digitsStringPtr = await __newString(digitsBigNumber.mul(signBigNumber).toString());
|
const digitsStringPtr = await __newString(digitsBigNumber.mul(signBigNumber).toString());
|
||||||
@ -305,7 +306,7 @@ export const instantiate = async (
|
|||||||
const yDecimalString = __getString(yStringPtr);
|
const yDecimalString = __getString(yStringPtr);
|
||||||
|
|
||||||
// Perform the decimal sum operation.
|
// Perform the decimal sum operation.
|
||||||
const sumResult = Decimal.sum(xDecimalString, yDecimalString);
|
const sumResult = GraphDecimal.sum(xDecimalString, yDecimalString);
|
||||||
const ptr = await __newString(sumResult.toString());
|
const ptr = await __newString(sumResult.toString());
|
||||||
const sumResultBigDecimal = await BigDecimal.fromString(ptr);
|
const sumResultBigDecimal = await BigDecimal.fromString(ptr);
|
||||||
|
|
||||||
@ -323,7 +324,7 @@ export const instantiate = async (
|
|||||||
const yDecimalString = __getString(yStringPtr);
|
const yDecimalString = __getString(yStringPtr);
|
||||||
|
|
||||||
// Perform the decimal sub operation.
|
// Perform the decimal sub operation.
|
||||||
const subResult = Decimal.sub(xDecimalString, yDecimalString);
|
const subResult = GraphDecimal.sub(xDecimalString, yDecimalString);
|
||||||
const ptr = await __newString(subResult.toString());
|
const ptr = await __newString(subResult.toString());
|
||||||
const subResultBigDecimal = await BigDecimal.fromString(ptr);
|
const subResultBigDecimal = await BigDecimal.fromString(ptr);
|
||||||
|
|
||||||
@ -341,7 +342,7 @@ export const instantiate = async (
|
|||||||
const yDecimalString = __getString(yStringPtr);
|
const yDecimalString = __getString(yStringPtr);
|
||||||
|
|
||||||
// Perform the decimal mul operation.
|
// Perform the decimal mul operation.
|
||||||
const mulResult = Decimal.mul(xDecimalString, yDecimalString);
|
const mulResult = GraphDecimal.mul(xDecimalString, yDecimalString);
|
||||||
const ptr = await __newString(mulResult.toString());
|
const ptr = await __newString(mulResult.toString());
|
||||||
const mulResultBigDecimal = await BigDecimal.fromString(ptr);
|
const mulResultBigDecimal = await BigDecimal.fromString(ptr);
|
||||||
|
|
||||||
@ -431,12 +432,12 @@ export const instantiate = async (
|
|||||||
// Create a decimal out of bigInt x.
|
// Create a decimal out of bigInt x.
|
||||||
const xBigInt = await BigInt.wrap(x);
|
const xBigInt = await BigInt.wrap(x);
|
||||||
const xStringPtr = await xBigInt.toString();
|
const xStringPtr = await xBigInt.toString();
|
||||||
const xDecimal = new Decimal(__getString(xStringPtr));
|
const xDecimal = new GraphDecimal(__getString(xStringPtr));
|
||||||
|
|
||||||
// Create decimal y.
|
// Create decimal y.
|
||||||
const yBigDecimal = await BigDecimal.wrap(y);
|
const yBigDecimal = await BigDecimal.wrap(y);
|
||||||
const yStringPtr = await yBigDecimal.toString();
|
const yStringPtr = await yBigDecimal.toString();
|
||||||
const yDecimal = new Decimal(__getString(yStringPtr));
|
const yDecimal = new GraphDecimal(__getString(yStringPtr));
|
||||||
|
|
||||||
// Perform the decimal division operation.
|
// Perform the decimal division operation.
|
||||||
const divResult = xDecimal.dividedBy(yDecimal);
|
const divResult = xDecimal.dividedBy(yDecimal);
|
||||||
|
@ -90,23 +90,23 @@ describe('numbers wasm tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should execute bigInt dividedByDecimal for positive dividend and positive divisor', async () => {
|
it('should execute bigInt dividedByDecimal for positive dividend and positive divisor', async () => {
|
||||||
const ptr = await testBigIntDividedByDecimal(await __newString('2315432122132354'), await __newString('54652.65645'));
|
const ptr = await testBigIntDividedByDecimal(await __newString('231543212213235645154'), await __newString('552.65645'));
|
||||||
expect(__getString(ptr)).to.equal('42366323478.725506672');
|
expect(__getString(ptr)).to.equal('418964100053904455.7500414588484401');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should execute bigInt dividedByDecimal for negative dividend and positive divisor', async () => {
|
it('should execute bigInt dividedByDecimal for negative dividend and positive divisor', async () => {
|
||||||
const ptr = await testBigIntDividedByDecimal(await __newString('-2315432122132354'), await __newString('54652.65645'));
|
const ptr = await testBigIntDividedByDecimal(await __newString('-231543212213235645154'), await __newString('552.65645'));
|
||||||
expect(__getString(ptr)).to.equal('-42366323478.725506672');
|
expect(__getString(ptr)).to.equal('-418964100053904455.7500414588484401');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should execute bigInt dividedByDecimal for positive dividend and negative divisor', async () => {
|
it('should execute bigInt dividedByDecimal for positive dividend and negative divisor', async () => {
|
||||||
const ptr = await testBigIntDividedByDecimal(await __newString('2315432122132354'), await __newString('-54652.65645'));
|
const ptr = await testBigIntDividedByDecimal(await __newString('231543212213235645154'), await __newString('-552.65645'));
|
||||||
expect(__getString(ptr)).to.equal('-42366323478.725506672');
|
expect(__getString(ptr)).to.equal('-418964100053904455.7500414588484401');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should execute bigInt dividedByDecimal for negative dividend and negative divisor', async () => {
|
it('should execute bigInt dividedByDecimal for negative dividend and negative divisor', async () => {
|
||||||
const ptr = await testBigIntDividedByDecimal(await __newString('-2315432122132354'), await __newString('-54652.65645'));
|
const ptr = await testBigIntDividedByDecimal(await __newString('-231543212213235645154'), await __newString('-552.65645'));
|
||||||
expect(__getString(ptr)).to.equal('42366323478.725506672');
|
expect(__getString(ptr)).to.equal('418964100053904455.7500414588484401');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ describe('numbers wasm tests', () => {
|
|||||||
const { testBigDecimalToString, __newString, __getString } = exports;
|
const { testBigDecimalToString, __newString, __getString } = exports;
|
||||||
|
|
||||||
const ptr = await testBigDecimalToString(await __newString('-5032485723458348569331745849735.3343434634691214453454356561'));
|
const ptr = await testBigDecimalToString(await __newString('-5032485723458348569331745849735.3343434634691214453454356561'));
|
||||||
expect(__getString(ptr)).to.equal('-5032485723458348569331745849735.3343434634691214453454356561');
|
expect(__getString(ptr)).to.equal('-5032485723458348569331745849735.334');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('should execute bigDecimal fromString API', () => {
|
describe('should execute bigDecimal fromString API', () => {
|
||||||
@ -138,7 +138,7 @@ describe('numbers wasm tests', () => {
|
|||||||
|
|
||||||
it('should get bigDecimal for numbers with decimals', async () => {
|
it('should get bigDecimal for numbers with decimals', async () => {
|
||||||
const ptr = await testBigDecimalFromString(await __newString('-5032485723458348569331745849735.3343434634691214453454356561'));
|
const ptr = await testBigDecimalFromString(await __newString('-5032485723458348569331745849735.3343434634691214453454356561'));
|
||||||
expect(__getString(ptr)).to.equal('-5032485723458348569331745849735.3343434634691214453454356561');
|
expect(__getString(ptr)).to.equal('-5032485723458348569331745849735.334');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -160,13 +160,13 @@ describe('numbers wasm tests', () => {
|
|||||||
const { testBigDecimalTimes, __getString, __newString } = exports;
|
const { testBigDecimalTimes, __getString, __newString } = exports;
|
||||||
|
|
||||||
const ptr = await testBigDecimalTimes(await __newString('231543212.2132354'), await __newString('54652.65645'));
|
const ptr = await testBigDecimalTimes(await __newString('231543212.2132354'), await __newString('54652.65645'));
|
||||||
expect(__getString(ptr)).to.equal('12654451630419.398459');
|
expect(__getString(ptr)).to.equal('12654451630419.39845917833');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should execute bigDecimal dividedBy API', async () => {
|
it('should execute bigDecimal dividedBy API', async () => {
|
||||||
const { testBigDecimalDividedBy, __getString, __newString } = exports;
|
const { testBigDecimalDividedBy, __getString, __newString } = exports;
|
||||||
|
|
||||||
const ptr = await testBigDecimalDividedBy(await __newString('231543212.2132354'), await __newString('54652.65645'));
|
const ptr = await testBigDecimalDividedBy(await __newString('231543212.2132354'), await __newString('54652.65645'));
|
||||||
expect(__getString(ptr)).to.equal('4236.6323478725506672');
|
expect(__getString(ptr)).to.equal('4236.632347872550667205491344419362');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,13 @@ import { TypeId, EthereumValueKind, ValueKind } from './types';
|
|||||||
|
|
||||||
const log = debug('vulcanize:utils');
|
const log = debug('vulcanize:utils');
|
||||||
|
|
||||||
|
// Customize Decimal according the limits of IEEE-754 decimal128.
|
||||||
|
// Reference: https://github.com/graphprotocol/graph-node/blob/v0.24.2/graph/src/data/store/scalar.rs#L42
|
||||||
|
export const GraphDecimal = Decimal.clone({ minE: -6143, maxE: 6144, precision: 34 });
|
||||||
|
|
||||||
|
// Constant used in function digitsToString.
|
||||||
|
const LOG_BASE = 7;
|
||||||
|
|
||||||
interface Transaction {
|
interface Transaction {
|
||||||
hash: string;
|
hash: string;
|
||||||
index: number;
|
index: number;
|
||||||
@ -436,7 +443,7 @@ const parseEntityValue = async (instanceExports: any, valuePtr: number) => {
|
|||||||
const bigDecimal = BigDecimal.wrap(bigDecimalPtr);
|
const bigDecimal = BigDecimal.wrap(bigDecimalPtr);
|
||||||
const bigDecimalStringPtr = await bigDecimal.toString();
|
const bigDecimalStringPtr = await bigDecimal.toString();
|
||||||
|
|
||||||
return new Decimal(__getString(bigDecimalStringPtr));
|
return new GraphDecimal(__getString(bigDecimalStringPtr)).toFixed();
|
||||||
}
|
}
|
||||||
|
|
||||||
case ValueKind.ARRAY: {
|
case ValueKind.ARRAY: {
|
||||||
@ -542,3 +549,40 @@ export const resolveEntityFieldConflicts = (entity: any): any => {
|
|||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get digits in a string from an array of digit numbers (Decimal().d)
|
||||||
|
// https://github.com/MikeMcl/decimal.js/blob/master/decimal.mjs#L2516
|
||||||
|
export function digitsToString (d: any) {
|
||||||
|
let i, k, ws;
|
||||||
|
const indexOfLastWord = d.length - 1;
|
||||||
|
let str = '';
|
||||||
|
let w = d[0];
|
||||||
|
|
||||||
|
if (indexOfLastWord > 0) {
|
||||||
|
str += w;
|
||||||
|
for (i = 1; i < indexOfLastWord; i++) {
|
||||||
|
ws = d[i] + '';
|
||||||
|
k = LOG_BASE - ws.length;
|
||||||
|
if (k) str += getZeroString(k);
|
||||||
|
str += ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
w = d[i];
|
||||||
|
ws = w + '';
|
||||||
|
k = LOG_BASE - ws.length;
|
||||||
|
if (k) str += getZeroString(k);
|
||||||
|
} else if (w === 0) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove trailing zeros of last w.
|
||||||
|
for (; w % 10 === 0;) w /= 10;
|
||||||
|
|
||||||
|
return str + w;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getZeroString (k: any) {
|
||||||
|
let zs = '';
|
||||||
|
for (; k--;) zs += '0';
|
||||||
|
return zs;
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@ contract Example {
|
|||||||
uint128 bidAmount2;
|
uint128 bidAmount2;
|
||||||
}
|
}
|
||||||
|
|
||||||
event Test(string param1, uint8 param2);
|
event Test(string param1, uint8 param2, uint256 param3);
|
||||||
|
|
||||||
function getMethod() public view virtual returns (string memory)
|
function getMethod() public view virtual returns (string memory)
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@ contract Example {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function emitEvent() public virtual returns (bool) {
|
function emitEvent() public virtual returns (bool) {
|
||||||
emit Test('abc', 123);
|
emit Test('abc', 150, 564894232132154);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,12 @@
|
|||||||
"internalType": "uint8",
|
"internalType": "uint8",
|
||||||
"name": "param2",
|
"name": "param2",
|
||||||
"type": "uint8"
|
"type": "uint8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "param3",
|
||||||
|
"type": "uint256"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "Test",
|
"name": "Test",
|
||||||
|
@ -30,6 +30,10 @@ export class Test__Params {
|
|||||||
get param2(): i32 {
|
get param2(): i32 {
|
||||||
return this._event.parameters[1].value.toI32();
|
return this._event.parameters[1].value.toI32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get param3(): BigInt {
|
||||||
|
return this._event.parameters[2].value.toBigInt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Example1__structMethodResultValue0Struct extends ethereum.Tuple {
|
export class Example1__structMethodResultValue0Struct extends ethereum.Tuple {
|
||||||
|
@ -105,6 +105,7 @@ export class Author extends Entity {
|
|||||||
this.set("name", Value.fromString(""));
|
this.set("name", Value.fromString(""));
|
||||||
this.set("rating", Value.fromBigDecimal(BigDecimal.zero()));
|
this.set("rating", Value.fromBigDecimal(BigDecimal.zero()));
|
||||||
this.set("paramInt", Value.fromI32(0));
|
this.set("paramInt", Value.fromI32(0));
|
||||||
|
this.set("paramBigInt", Value.fromBigInt(BigInt.zero()));
|
||||||
this.set("paramBytes", Value.fromBytes(Bytes.empty()));
|
this.set("paramBytes", Value.fromBytes(Bytes.empty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,6 +171,15 @@ export class Author extends Entity {
|
|||||||
this.set("paramInt", Value.fromI32(value));
|
this.set("paramInt", Value.fromI32(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get paramBigInt(): BigInt {
|
||||||
|
let value = this.get("paramBigInt");
|
||||||
|
return value!.toBigInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
set paramBigInt(value: BigInt) {
|
||||||
|
this.set("paramBigInt", Value.fromBigInt(value));
|
||||||
|
}
|
||||||
|
|
||||||
get paramBytes(): Bytes {
|
get paramBytes(): Bytes {
|
||||||
let value = this.get("paramBytes");
|
let value = this.get("paramBytes");
|
||||||
return value!.toBytes();
|
return value!.toBytes();
|
||||||
|
@ -18,6 +18,7 @@ type Author @entity {
|
|||||||
name: String! # string
|
name: String! # string
|
||||||
rating: BigDecimal!
|
rating: BigDecimal!
|
||||||
paramInt: Int! # uint8
|
paramInt: Int! # uint8
|
||||||
|
paramBigInt: BigInt! # uint256
|
||||||
paramBytes: Bytes!
|
paramBytes: Bytes!
|
||||||
blogs: [Blog!]! @derivedFrom(field: "author")
|
blogs: [Blog!]! @derivedFrom(field: "author")
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ export function handleTest (event: Test): void {
|
|||||||
log.debug('event.address: {}', [event.address.toHexString()]);
|
log.debug('event.address: {}', [event.address.toHexString()]);
|
||||||
log.debug('event.params.param1: {}', [event.params.param1]);
|
log.debug('event.params.param1: {}', [event.params.param1]);
|
||||||
log.debug('event.params.param2: {}', [event.params.param2.toString()]);
|
log.debug('event.params.param2: {}', [event.params.param2.toString()]);
|
||||||
|
log.debug('event.params.param3: {}', [event.params.param3.toString()]);
|
||||||
log.debug('event.block.hash: {}', [event.block.hash.toHexString()]);
|
log.debug('event.block.hash: {}', [event.block.hash.toHexString()]);
|
||||||
log.debug('event.block.stateRoot: {}', [event.block.stateRoot.toHexString()]);
|
log.debug('event.block.stateRoot: {}', [event.block.stateRoot.toHexString()]);
|
||||||
|
|
||||||
@ -32,8 +33,9 @@ export function handleTest (event: Test): void {
|
|||||||
// Entity fields can be set based on event parameters
|
// Entity fields can be set based on event parameters
|
||||||
author.name = event.params.param1;
|
author.name = event.params.param1;
|
||||||
author.paramInt = event.params.param2;
|
author.paramInt = event.params.param2;
|
||||||
|
author.paramBigInt = event.params.param3;
|
||||||
author.paramBytes = event.address;
|
author.paramBytes = event.address;
|
||||||
author.rating = BigDecimal.fromString('4');
|
author.rating = BigDecimal.fromString('3.2132354');
|
||||||
|
|
||||||
// Entities can be written to the store with `.save()`
|
// Entities can be written to the store with `.save()`
|
||||||
author.save();
|
author.save();
|
||||||
|
@ -19,7 +19,7 @@ dataSources:
|
|||||||
- name: Example1
|
- name: Example1
|
||||||
file: ./abis/Example1.json
|
file: ./abis/Example1.json
|
||||||
eventHandlers:
|
eventHandlers:
|
||||||
- event: Test(string,uint8)
|
- event: Test(string,uint8,uint256)
|
||||||
handler: handleTest
|
handler: handleTest
|
||||||
blockHandlers:
|
blockHandlers:
|
||||||
- handler: handleBlock
|
- handler: handleBlock
|
||||||
|
@ -14,11 +14,41 @@
|
|||||||
"internalType": "uint8",
|
"internalType": "uint8",
|
||||||
"name": "param2",
|
"name": "param2",
|
||||||
"type": "uint8"
|
"type": "uint8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "param3",
|
||||||
|
"type": "uint256"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "Test",
|
"name": "Test",
|
||||||
"type": "event"
|
"type": "event"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint128",
|
||||||
|
"name": "bidAmount1",
|
||||||
|
"type": "uint128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint128",
|
||||||
|
"name": "bidAmount2",
|
||||||
|
"type": "uint128"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "addMethod",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"inputs": [],
|
"inputs": [],
|
||||||
"name": "emitEvent",
|
"name": "emitEvent",
|
||||||
@ -44,6 +74,42 @@
|
|||||||
],
|
],
|
||||||
"stateMutability": "view",
|
"stateMutability": "view",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint128",
|
||||||
|
"name": "bidAmount1",
|
||||||
|
"type": "uint128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint128",
|
||||||
|
"name": "bidAmount2",
|
||||||
|
"type": "uint128"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "structMethod",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "uint128",
|
||||||
|
"name": "bidAmount1",
|
||||||
|
"type": "uint128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint128",
|
||||||
|
"name": "bidAmount2",
|
||||||
|
"type": "uint128"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Example.Bid",
|
||||||
|
"name": "",
|
||||||
|
"type": "tuple"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"storageLayout": {
|
"storageLayout": {
|
||||||
|
@ -27,6 +27,9 @@ export class Author {
|
|||||||
@Column('integer')
|
@Column('integer')
|
||||||
paramInt!: number
|
paramInt!: number
|
||||||
|
|
||||||
|
@Column('bigint', { transformer: bigintTransformer })
|
||||||
|
paramBigInt!: number
|
||||||
|
|
||||||
@Column('varchar')
|
@Column('varchar')
|
||||||
paramBytes!: string
|
paramBytes!: string
|
||||||
|
|
||||||
|
@ -584,10 +584,11 @@ export class Indexer implements IndexerInterface {
|
|||||||
switch (logDescription.name) {
|
switch (logDescription.name) {
|
||||||
case TEST_EVENT: {
|
case TEST_EVENT: {
|
||||||
eventName = logDescription.name;
|
eventName = logDescription.name;
|
||||||
const { param1, param2 } = logDescription.args;
|
const { param1, param2, param3 } = logDescription.args;
|
||||||
eventInfo = {
|
eventInfo = {
|
||||||
param1,
|
param1,
|
||||||
param2
|
param2,
|
||||||
|
param3: BigInt(param3.toString())
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import BigInt from 'apollo-type-bigint';
|
import BigInt from 'apollo-type-bigint';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
|
import Decimal from 'decimal.js';
|
||||||
|
import { GraphQLScalarType } from 'graphql';
|
||||||
|
|
||||||
import { ValueResult, BlockHeight } from '@vulcanize/util';
|
import { ValueResult, BlockHeight } from '@vulcanize/util';
|
||||||
|
|
||||||
@ -23,6 +25,19 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
return {
|
return {
|
||||||
BigInt: new BigInt('bigInt'),
|
BigInt: new BigInt('bigInt'),
|
||||||
|
|
||||||
|
BigDecimal: new GraphQLScalarType({
|
||||||
|
name: 'BigDecimal',
|
||||||
|
description: 'BigDecimal custom scalar type',
|
||||||
|
parseValue (value) {
|
||||||
|
// value from the client
|
||||||
|
return new Decimal(value);
|
||||||
|
},
|
||||||
|
serialize (value: Decimal) {
|
||||||
|
// value sent to the client
|
||||||
|
return value.toFixed();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
Event: {
|
Event: {
|
||||||
__resolveType: (obj: any) => {
|
__resolveType: (obj: any) => {
|
||||||
assert(obj.__typename);
|
assert(obj.__typename);
|
||||||
|
@ -62,6 +62,7 @@ union Event = TestEvent
|
|||||||
type TestEvent {
|
type TestEvent {
|
||||||
param1: String!
|
param1: String!
|
||||||
param2: Int!
|
param2: Int!
|
||||||
|
param3: BigInt!
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResultIPLDBlock {
|
type ResultIPLDBlock {
|
||||||
@ -110,6 +111,7 @@ type Author {
|
|||||||
name: String!
|
name: String!
|
||||||
rating: BigDecimal!
|
rating: BigDecimal!
|
||||||
paramInt: Int!
|
paramInt: Int!
|
||||||
|
paramBigInt: BigInt!
|
||||||
paramBytes: Bytes!
|
paramBytes: Bytes!
|
||||||
blogs: [Blog!]!
|
blogs: [Blog!]!
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user