I am trying to sign typed data via MetaMask "eth_signTypedData_v4". Recovering signer via recoverTypedSignature_v4 returns correct address that I signed my data with. But smart contract returns wrong address every time as ecrecover output. Can't understand what is wrong with the code.
js:
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();// 签名
const signerAddress = (await signer.getAddress()).toLowerCase();
const originalMessage = {
types: {
EIP712Domain: [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chainId", type: "uint256" },
{ name: "verifyingContract", type: "address" }
],
Greeting: [
{ name: 'contents', type: 'string' },
{ name: "sender", type: "address" },
{ name: "x", type: "uint256" }
],
},
primaryType: 'Greeting',
domain: {
name: 'SignatureVerifyTest',
version: '1',
chainId: 31337,
verifyingContract: "0x5fbdb2315678afecb367f032d93f642f64180aa3"
},
message: {
contents: 'Hello',
sender: signerAddress,
x: 123
}
};
const signedMessage = await signer.provider.send("eth_signTypedData_v4", [signerAddress, JSON.stringify(originalMessage)]);
const { v, r, s } = ethers.utils.splitSignature(signedMessage);
console.log('signerAddress:', signerAddress)
console.log("r:", r);
console.log("s:", s);
console.log("v:", v);
bytes32 eip712DomainHash = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes("SignatureVerifyTest")),
keccak256(bytes("1")),
block.chainid,
address(this)
)
);
bytes32 hashStruct = keccak256(
abi.encode(keccak256("Greeting(string contents,address sender,uint256 x)"), contents, sender, x)
);
bytes32 hash = ECDSA.toTypedDataHash(eip712DomainHash, hashStruct);
address signer = ECDSA.recover(hash, v, r, s);
console.log("sender", sender);
console.log("signer", signer);
Related
I was doing a test in truffle. But i encountered this error, "ReferenceError: halalMeatInstance is not defined". I am pretty new in this truffle test thingy, actually this is my first time playing around with smart contracts and truffle test realm. It will be really helpful if anyone can point me out the mistake i made and give a solution. Thank you so much! the test file code is added below.
const { expectedEvent, BN } = require("#openzeppelin/test-helpers");
const HDWalletProvider = require("#truffle/hdwallet-provider");
const Web3 = require("Web3");
const HalalMeat = artifacts.require("HalalMeat");
contract("HalalMeat", (accounts) => {
before(async () => {
this.owner = accounts[0];
this.MEAT_BRANDS = {
GHagro: "Golden Harvest Agro Industries",
Kazifood: "Kazi Food Industries",
AGagro: "Ahsan Group Agro Foods",
Bengalmeat: "Bengal Meat ltd",
Sagro: "Sadek Agro ltd"
};
//enums
this.ModeEnums = {
ISSUER: { val: "ISSUER", pos: 0 },
VERIFIER: { val: "VERIFIER", pos: 1 },
PROVER: { val: "PROVER", pos: 2 }
};
this.StatusEnums = {
//MANUFACTURED, DELIVERING_INTERNATIONAL, STORED, DELIVERING_LOCAL, DELIVERED
manufactured: { val: "IMANUFACTURED", pos: 0 },
delivering1: { val: "DELIVERING_INTERNATIONAL", pos: 1 },
stored: { val: "STORED", pos: 2 },
delivering2: { val: "DELIVERING_LOCAL", pos: 3 },
delivered: { val: "DELIVERED", pos: 4 }
};
this.defaultEntities = {
farmA: { id: accounts[1], mode: this.ModeEnums.PROVER.val },
farmB: { id: accounts[2], mode: this.ModeEnums.PROVER.val },
inspector: { id: accounts[3], mode: this.ModeEnums.ISSUER.val },
distributorGlobal: { id: accounts[4], mode: this.ModeEnums.VERIFIER.val },
distributorLocal: { id: accounts[5], mode: this.ModeEnums.VERIFIER.val },
seller: { id: accounts[6], mode: this.ModeEnums.ISSUER.val },
customer: { id: accounts[7], mode: this.ModeEnums.PROVER.val }
};
this.defaultMeatBatches ={
0: { brand: this.MEAT_BRANDS.Bengalmeat, farm: this.defaultEntities.farmA.id },
1: { brand: this.MEAT_BRANDS.Sagro, farm: this.defaultEntities.farmA.id },
2: { brand: this.MEAT_BRANDS.Kazifood, farm: this.defaultEntities.farmA.id },
3: { brand: this.MEAT_BRANDS.GHagro, farm: this.defaultEntities.farmA.id },
4: { brand: this.MEAT_BRANDS.AGagro, farm: this.defaultEntities.farmA.id },
5: { brand: this.MEAT_BRANDS.Bengalmeat, farm: this.defaultEntities.farmB.id },
6: { brand: this.MEAT_BRANDS.Sagro, farm: this.defaultEntities.farmB.id },
7: { brand: this.MEAT_BRANDS.Kazifood, farm: this.defaultEntities.farmB.id },
8: { brand: this.MEAT_BRANDS.GHagro, farm: this.defaultEntities.farmB.id },
9: { brand: this.MEAT_BRANDS.AGagro, farm: this.defaultEntities.farmB.id }
};
this.halalMeatInstance = await HalalMeat.deployed();
this.providerOrUrl = "http://localhost:8545";
});
it('should add entities successfully', async () => {
for(const entity in this.defaultEntities){
const { id, mode } = this.defaultEntities[entity];
const result = await halalMeatInstance.addEntity(
id,
mode,
{ from: this.owner}
);
console.log(result);
expectedEvent(result.receipt, "AddEntity", {
entityId: id,
entityMode: mode
});
//assert.equal(actual, expected, errorMessage);
}
});
});
i tried truffle test. got reference error but was expecting an emit event.
Contract: HalalMeaton list from solc-bin. Attempt #1
1) should add entities successfullybin. Attempt #1
> No events were emitted
0 passing (99ms)
1 failing
Contract: HalalMeat
should add entities successfully:
ReferenceError: halalMeatInstance is not defined
at Context. (test\halalmeat.js:74:22)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
this is the error message i got when i used truffle test
Getting error unknown top level operator $regex
search.vue `
let questDocuments = await conversation
.find({ query: { $limit: 100, $search: q, skippop: true } })
.then(response => {`
q is the string being passed
service hook
before: {
all: [],
find: [
hookBeforeFind,
search({
fields: ["label"],
deep: true
})
],
Model
const conversation = new Schema(
{
label: { type: String, required: true },
nodeId: { type: String, required: true },
details: { type: String },
url: { type: String },
creator: { type: String },
handle: { type: String },
date: { type: String },
From search bar add expression to search. E.g "the"
Add $regex to the whitelist option of the Mongoose service:
app.use('/messages', service({
Model,
whitelist: [ '$regex' ]
}));
try this
// regex to find records that start with letter any name , example "e"
Model.aggregate([
{
$match: {
field_name: {
$regex: "^" + searchName,
$options: "i"
}
}
}]).exec(function(err, result) {
if (err) { // handle here }
if (result) { // do something }
}
I've been having troubles with Elastic Search (ES) dynamic mappings. Seems like I'm in a catch-22. https://www.elastic.co/guide/en/elasticsearch/guide/current/custom-dynamic-mapping.html
The main goal is to store everything as a string that comes into ES.
What I've tried:
In ES you can't create a dynamic mapping until the index has been
created. Okay, makes sense.
I can't create an empty index, so if
the first item sent into the index is not a string, I can't
re-assign it... I won't know what type of object with be the first
item in the index, it could be any type, due to how the the app accepts a variety of objects/events.
So if I can't create the mapping ahead of time, and I can't insert an empty index to create the mapping, and I can't change the mapping after the fact, how do I deal with the first item if its NOT a string???
Here's what I'm currently doing (using the Javascript Client).
createESIndex = function (esClient){
esClient.index({
index: 'timeline-2015-11-21',
type: 'event',
body: event
},function (error, response) {
if (error) {
logger.log(logger.SEVERITY.ERROR, 'acceptEvent elasticsearch create failed with: '+ error + " req:" + JSON.stringify(event));
console.log(logger.SEVERITY.ERROR, 'acceptEvent elasticsearch create failed with: '+ error + " req:" + JSON.stringify(event));
res.status(500).send('Error saving document');
} else {
res.status(200).send('Accepted');
}
});
}
esClientLookup.getClient( function(esClient) {
esClient.indices.putTemplate({
name: "timeline-mapping-template",
body:{
"template": "timeline-*",
"mappings": {
"event": {
"dynamic_templates": [
{ "timestamp-only": {
"match": "#timestamp",
"match_mapping_type": "date",
"mapping": {
"type": "date",
}
}},
{ "all-others": {
"match": "*",
"match_mapping_type": "string",
"mapping": {
"type": "string",
}
}
}
]
}
}
}
}).then(function(res){
console.log("put template response: " + JSON.stringify(res));
createESIndex(esClient);
}, function(error){
console.log(error);
res.status(500).send('Error saving document');
});
});
Index templates to the rescue !! That's exactly what you need, the idea is to create a template of your index and as soon as you wish to store a document in that index, ES will create it for you with the mapping you gave (even dynamic ones)
curl -XPUT localhost:9200/_template/my_template -d '{
"template": "index_name_*",
"settings": {
"number_of_shards": 1
},
"mappings": {
"type_name": {
"dynamic_templates": [
{
"strings": {
"match": "*",
"match_mapping_type": "*",
"mapping": {
"type": "string"
}
}
}
],
"properties": {}
}
}
}'
Then when you index anything in an index whose name matches index_name_*, the index will be created with the dynamic mapping above.
For instance:
curl -XPUT localhost:9200/index_name_1/type_name/1 -d '{
"one": 1,
"two": "two",
"three": true
}'
That will create a new index called index_name_1 with a mapping type for type_name where all properties are string. You can verify that with
curl -XGET localhost:9200/index_name_1/_mapping/type_name
Response:
{
"index_name_1" : {
"mappings" : {
"type_name" : {
"dynamic_templates" : [ {
"strings" : {
"mapping" : {
"type" : "string"
},
"match" : "*",
"match_mapping_type" : "*"
}
} ],
"properties" : {
"one" : {
"type" : "string"
},
"three" : {
"type" : "string"
},
"two" : {
"type" : "string"
}
}
}
}
}
}
Note that if you're willing to do this via the Javascript API, you can use the indices.putTemplate call.
export const user = {
email: {
type: 'text',
},
};
export const activity = {
date: {
type: 'text',
},
};
export const common = {
name: {
type: 'text',
},
};
import { Client } from '#elastic/elasticsearch';
import { user } from './user';
import { activity } from './activity';
import { common } from './common';
export class UserDataFactory {
private schema = {
...user,
...activity,
...common,
relation_type: {
type: 'join',
eager_global_ordinals: true,
relations: {
parent: ['activity'],
},
},
};
constructor(private client: Client) {
Object.setPrototypeOf(this, UserDataFactory.prototype);
}
async create() {
const settings = {
settings: {
analysis: {
normalizer: {
useLowercase: {
filter: ['lowercase'],
},
},
},
},
mappings: {
properties: this.schema,
},
};
const { body } = await this.client.indices.exists({
index: ElasticIndex.UserDataFactory,
});
await Promise.all([
await (async (client) => {
await new Promise(async function (resolve, reject) {
if (!body) {
await client.indices.create({
index: ElasticIndex.UserDataFactory,
});
}
resolve({ body });
});
})(this.client),
]);
await this.client.indices.close({ index: ElasticIndex.UserDataFactory });
await this.client.indices.putSettings({
index: ElasticIndex.UserDataFactory,
body: settings,
});
await this.client.indices.open({
index: ElasticIndex.UserDataFactory,
});
await this.client.indices.putMapping({
index: ElasticIndex.UserDataFactory,
body: {
dynamic: 'strict',
properties: {
...this.schema,
},
},
});
}
}
wrapper.ts
class ElasticWrapper {
private _client: Client = new Client({
node: process.env.elasticsearch_node,
auth: {
username: 'elastic',
password: process.env.elasticsearch_password || 'changeme',
},
ssl: {
ca: process.env.elasticsearch_certificate,
rejectUnauthorized: false,
},
});
get client() {
return this._client;
}
}
export const elasticWrapper = new ElasticWrapper();
index.ts
new UserDataFactory(elasticWrapper.client).create();
This is my code in backend controller in MEAN JS:
exports.list = function(req, res) {
// configure the filter using req params
var filters = {
filters : {
optional : {
contains : req.query.filter
}
}
};
var sort = {
asc : {
desc: 'name'
}
};
Province
.find()
.filter(filters)
.order(sort)
.exec(function (err, provinces) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(provinces);
}
});
};
The request:
http://localhost:3000/provinces?filter[name]=provincia de Barcelona
Returns a filtered result, as expected:
[
{
"_id": "54ba72903f51d73c4aff6da6",
"community": "54ba689f5fdfbdea292b8737",
"location": "{lat: '41.386290', lng: '2.184988', zoom: '11'}",
"__v": 0,
"name": "provincia de Barcelona"
}
]
When I use a different attribute, the filter stops working. Example:
http://localhost:3000/provinces?filters[community]=54ba69755fdfbdea292b8738
Return this:
{
"message": ""
}
And console.log(err) return this:
[CastError: Cast to ObjectId failed for value "/54ba689f5fdfbdea292b8737/i" at path "community"]
message: 'Cast to ObjectId failed for value "/54ba689f5fdfbdea292b8737/i" at path "community"',
name: 'CastError',
type: 'ObjectId',
value: /54ba689f5fdfbdea292b8737/i,
path: 'community' }
The original document:
[
{
"_id": "54ba72903f51d73c4aff6da6",
"community": "54ba689f5fdfbdea292b8737",
"location": "{lat: '41.386290', lng: '2.184988', zoom: '11'}",
"__v": 0,
"name": "provincia de Barcelona"
},
{
"_id": "54ba73c33f51d73c4aff6da7",
"community": "54ba69755fdfbdea292b8738",
"location": "{lat: '42.4298846', lng: '-8.644620199999963', zoom: '11'}",
"__v": 0,
"name": "provincia de Pontevedra"
}
]
Maybe is not the best way, but works :)
exports.list = function(req, res) {
var community = {community: ''};
community.community = mongoose.Types.ObjectId(req.query.filter.community);
console.log(community);
var filters = {
filters : {
optional : {
contains : community
}
}
};
var sort = {
asc : {
desc: 'name'
}
};
Province
.find()
.filter(filters)
.order(sort)
.exec(function (err, provinces) {
console.log(err);
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(provinces);
}
});
};
The request:
http://localhost:3000/provinces?filter[community]=54ba689f5fdfbdea292b8737
The result:
[
{
"_id": "54ba72903f51d73c4aff6da6",
"community": "54ba689f5fdfbdea292b8737",
"location": "{lat: '41.386290', lng: '2.184988', zoom: '11'}",
"__v": 0,
"name": "provincia de Barcelona"
}
]
I've trying to get the sencha touch 2 data management examples to work but with no use. Here is the code of a simple model and store that are not working (getCount returns 0).
Ext.define('MyClient.model.Product', {
extend:'Ext.data.Model',
config:{
fields:['name', 'image'],
proxy:{
type:'ajax',
url:'http://localhost/st2/Projets/my-client-sencha/data/products.json',
reader:{
type:'json',
rootProperty:'products',
successProperty:'success'
}
}
}
});
Ext.define('MyClient.store.ProductsStore', {
extend:'Ext.data.Store',
config:{
model:'MyClient.model.Product',
autoLoad:true,
autoSync:true
}
});
In the launch function I have these lines:
var prod = Ext.create('MyClient.store.ProductsStore');
prod.load();
alert(prod.getCount());
And finally here's my products.json:
[
{
"name":"test"
}
]
I'm not getting any errors in the console but still the getCount always returns 0. Can use some help here please.
EDIT: wrong JSON, not working with this neither:
{
"success":true,
"products": [
{
"name":"test"
}
]
}
Because of your setting rootProperty:'products', your json has to be like
{
products: [
{
"name":"test"
}
]
}
if you do not want to change server response remover rootProperty from config.
have a look at Json Reader doc
Ahh... you forgot about asyn nature of the load()....
var prod = Ext.create('MyClient.store.ProductsStore');
prod.load(function ( ){
alert(prod.getCount());
});
Notice that it prod.load() is using only for testing purposes, as far you have set property autoLoad: true.
In your snippet the loader would make 2 similar calls.
Cheers, Oleg
Ext.define('MyBizilinkms.model.Customer', {
extend: 'Ext.data.Model',
config: {
identifier:'uuid',
fields: [
'CustId',
'EMail',
'Title',
'FName',
'MdInitial',
'LName',
'PhnNum',
'SecondPhnNo',
'DOB',
'Address',
'SecondAddress',
'City',
'State',
'Zip',
'Country',
'RecieveEmail',
'IsSaveonServer',
{
name: 'Full_Name',
type:'string',
convert:function(v, rec) {
return rec.data.FName + " " + rec.data.LName;
}
}],
validations: [
{
type: 'format',
name: 'EMail',
matcher: /^[a-zA-Z0-9._-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/,
message:"Valid Email Required"
},
{
name: 'PhnNum',
type : 'custom',
message : "Valid Phone required",
validator : function(config, value, model) {
var reg = /^[0-9]{3}-[0-9]{3}-[0-9]{4}$/;
return reg.test(value);
}
},
{
name: 'SecondPhnNum',
type : 'custom',
message : "Valid 2nd Phone required",
validator : function(config, value, model) {
if (!Ext.isEmpty(value)) {
var reg = /^[0-9]{3}-[0-9]{3}-[0-9]{4}$/;
return reg.test(value)
}
return true;
}
},
{
type: 'presence',
name: 'FName',
message : "First Name is required"
},
{
type: 'presence',
name: 'LName',
message : "Last Name is required"
},
{
type: 'presence',
name: 'Address',
message : "Address is required"
},
{
type: 'presence',
name: 'City',
message : "City is required"
},
{
name: 'State',
type : 'custom',
message : "Valid State required",
validator : function(config, value, model) {
var reg = /^(AK|AL|AR|AZ|CA|CO|CT|DC|DE|FL|GA|HI|IA|ID|IL|IN|KS|KY|LA|MA|MD|ME|MI|MN|MO|MS|MT|NB|NC|ND|NH|NJ|NM|NV|NY|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VA|VT|WA|WI|WV|WY)$/i;
if(Ext.isEmpty(value))
value = '00'
var state = value.replace(/^\s+|\s+$/g, "");
return reg.test(state)
}
},
{
name: 'Zip',
type : 'custom',
message : "Valid Zip required",
validator : function(config, value, model) {
var reg = /(^\d{5}$)|(^\d{5}-\d{4}$)/;
return reg.test(value)
}
},
{
type: 'presence',
name: 'Country',
message : "Country is required"
}
]
},
getFullName: function() {
return this.get('FName') + '' + this.get( 'LName');
}
});