Return a whole struct in solidity? - ethereum

Let's say I have a struct & a mapping like this:
struct myStruct {
address addr;
uint256 price;
bool approved;
}
mapping(string => myStruct) mappy;
How can I retrieve all the keys?
I know solidity will generate getters so if I have the key I can retrieve the info from inside the struct. But the keys are unknown to me and I need to retrieve the complete struct.
Maybe a better solution would be to have a public variable which would be the size of the struct and an index has key and store the key in the struct?
That way I will know the size and I suppose I can iterate it

First thing is that you shouldn't use string as key, better declare bytes32 as string is just an alias for it.
you can make a call to the mapping giving the string key as reference.
However it will retrieve only an iterative array without the internal keynames.
let's say for example you have :
mappy['a'] that contains the following information
{
'0x000...000',
1,
true
}
the call will retrieve an simple array like this : ['0x000...000',1,true]
If you want to make it an object you'll have to rebuild it on your own.

Related

Use Validator/Dive to enter an array and validate nested structs in go

type myType struct {
value int `json:"value"`
Name string `json:"name" validate:"required"`
URL string `json:"URL" validate:"required"`
args []otherType `json:"args" validate:"dive", "required"`
}
type otherType struct {
name string `validate:"required"`
origin string `validate:"required"`
}
err := paramsValidator.Validate(someInstantiationOfThisStruct)
Hello there! I'm a tad bit stumped on using validator's dive feature. This specific combination of validation scheme isn't present in the documentation for the validator, and I was unable to get it working with a little bit of tweaking.
I would like to simply enter the args array in the primary struct, and validate each of two sets of otherType. However I don't quite understand how this is supposed to transpire.
I understand dive incorrectly and it's not working of course, as the validator is unable to determine incorrect validations using Validate().
Is there any particular thing I'm doing wrong? In general how should I approach evaluating and validating args that are in an array?
I was able to figure it out. I am so sorry for even posting! I was stumped for thirty minutes, but the solution was not that particularly bad.
type myType struct {
value int `json:"value"`
Name string `json:"name" validate:"required"`
URL string `json:"URL" validate:"required"`
args []otherType `json:"args" validate:"dive", "required"`
}
type otherType struct {
name string `validate:"required"`
origin string `validate:"required"`
}
is the updated code. There was a missing , between "dive" and "required", and I had posted code that read
`validate: "dive, required"
dyslexia sorry! :(
I came searching for the answer here but the solution didn't work for me.
In order to validate nested struct using go-playground/validator add dive.
So add below code to the nested struct at top level
`validate:"required,dive,required"`
Note: add without spaces, also make sure the fields are exposed (use PascalCase) to package incase u importing the struct
type myType struct {
value int `json:"value"`
Name string `json:"name" validate:"required"`
URL string `json:"URL" validate:"required"`
Args []OtherType `json:"args" validate:"required,dive,required"`
}
type OtherType struct {
Name string `validate:"required"`
Origin string `validate:"required"`
}
Note: This validation is as per my use case where i want Args to be required and also want it to be exposed to other packages. Just trying to help other who come searching for the same issue as "Dive" is not documented properly in go/playground documentation

use mappings inside structs in solidity

After including a mapping inside a struct, when trying to pass the struct into a function, it has to be "storage" instead of "memory". (the "checkBalance" function is just an example here)
Is it a good practice to store mapping inside struct?
Any alternatives to the mapping type inside the struct? Thought of using array but it has to do the iteration to find the item.
library MappingLib {
struct Balance {
uint256 value;
mapping(string => uint256) positions;
}
function checkBalance(Balance storage balance, string memory key) public returns (uint256) {
return balance.positions[key];
}
}
First of all mappings and any other data structures that need to be persisted in-between contract calls are always stored in storage, whether they are part of any struct or not. Now answering your questions:
Yes, it's perfectly fine to have mappings inside structs
In your particular case mapping seems to be the most natural option as you want to access values by keys
You could put the mapping outside the struct
`mapping(string => uint256) positions;`
Pass in the string and get the value or you could just create the key in the mapping
`mapping(uint256 => Balance) positions;`

Solidity storage struct not compiling

I'm new to solidity and I'm just experiencing with some simple code.
Basically I just want to create a struct that will store data permenantly inside a contract. According to the doc I need storage for that.
But the following code is not compiling except if I use memory instead. Why?
pragma solidity ^0.4.11;
contract test {
struct Selling {
address addr;
string name;
uint price;
}
mapping(string => Selling) selling;
function sellName() constant returns (bool ok)
{
address a = 0x4c3032756d5884D4cAeb2F1eba52cDb79235C2CA;
Selling storage myStruct = Selling(a,"hey",12);
}
}
The error I get is this:
ERROR:
browser/test.sol:16:9: TypeError: Type struct test.Selling memory is not implicitly convertible to expected type struct test.Selling storage pointer.
Selling storage myStruct = Selling(a,"hey",12);
^--------------------------------------------^
When you first create the myStruct instance, it will be created in memory and then written out to storage (assuming you put the object into your selling map and don't declare your method constant) when the function returns. If you were to retrieve the item from your map in another function, then you would declare it as a storage variable.
See this explanation on Ethereum StackExchange for more details. The Solidity documentation also has a very good explanation of how variables are stored and when to use memory vs storage.
I had similiar situation, the fix for this was:
function sellName() constant returns (bool ok)
{
address a = 0x4c3032756d5884D4cAeb2F1eba52cDb79235C2CA;
Selling memory myStruct = Selling(a,"hey",12);
// insert 'myStruct' to the mapping:
selling[a] = myStruct;
}

One to One relation mapping using GORM for Golang

I am trying to understand how GORM works for one to one relational mapping with MySQL. I have 2 structs like so:
type User struct {
Id uint `gorm:"AUTO_INCREMENT"`
FirstName string `gorm:"column:first_name"`
LastName string `gorm:"column:last_name"`
EncryptedUserId string `gorm:"size:255"`
Email string `gorm:"not null;unique"`
Password string `gorm:"not null;unique"`
CreatedAt int64 `gorm:"type(timestamp)"`
}
type UserSession struct {
Id uint `gorm:"AUTO_INCREMENT"`
UserId User
SessionToken string `gorm:"column:session_token"`
CreatedAt int64 `gorm:"type(timestamp)"`
}
User and UserSession share one to one relation. But when code above is run, the column UserId for UserSession table is not created. Even after specifying the foreign key constraint gorm:"ForeignKey:Id"
the result is same. Why isn't the above code working? Is anything missing in the struct definition?
I can't comment your questions so I would ask it here:
Do you migrate your schema in any way like:
db.AutoMigrate(&User{}, &UserSession{})
?
If you do, you should get some detailed errors in log, which might be useful for you.
The way I have managed to get something similar to work is this.
type UserSession struct {
Id uint `gorm:"AUTO_INCREMENT"`
UserId uint
User User
SessionToken string `gorm:"column:session_token"`
CreatedAt int64 `gorm:"type(timestamp)"`
}

In AS3, where do you draw the line between Dictionary and ArrayCollection?

Basically I have been using a Dictionary object in my program that basically took ints as its keys and stored RTMFP peer IDs in the appropriate locations. Each int was unique and represented one user.
Now I'm needing to expand on this where users are identified by a combination of the int and a Boolean value, kind of like this:
private var m_iUID:int;
private var m_blnIsCurrent:Boolean;
Only the combination between those two really uniquely identifies the user. That being said I was just about to use a new class made out of this for the Dictionary keys; but then it occurred to me that instead of doing it this way, I could just add the peer ID to the class definition and turn the Dictionary object into an ArrayCollection:
private var m_iUID:int;
private var m_blnIsCurrent:Boolean;
public var m_strNearID:String;
So now I'm wondering which is really better in this scenario. And that question has led to a bigger question: where do you really draw the line between these two collection types in general? They're suddenly starting to not seem all that different after all, except where you're trying to avoid messing with class definitions. I guess I'm really asking for advice about both the specific scenario and the general question. Thanks!
ArrayCollection is just a wrapper for an Array, and is only available in Flex.
In AS3 you really have 3 fundamental hash table types: Array, Object, and Dictionary. You choose which one to use based on the type of key you want to use: an integer, a string, or an object reference. Arrays will convert any key to an int, Object will convert any key to a string. Dictionary works like Object for string keys (and will convert primitives to a string) but what it is really good at is using object references as keys.
It you want to use a single int as the unique key, use an array. If you want to use a single string as the unique key, use an object. If you want to use object references as the unique key, use a Dictionary.
In your case you should probably use an Object, and a custom toString() method on your "key" class. This is because you want to use a composite of primitive values (NOT an object reference) as your unique key. There is no way to do this natively, so you'll have to mash the values together as a single string. Objects are the best (fastest) hash table for string keys, so that is the collection you should use.
Example:
class User {
private var m_iUID:int;
private var m_blnIsCurrent:Boolean;
public var m_strNearID:String;
public function User(UID:int, IsCurrent:Boolean) {
m_iUID = UID;
m_blnIsCurrent = IsCurrent;
}
// Custom toString to mash together primitives
public function toString() {
return m_iUID.toString() + "-" + (m_blnIsCurrent ? "1" : "0");
}
}
// Later:
var allUsers:Object = {}
var user1:User = new User(231049, true);
var user2:User = new User(0x2309, false);
// Implicitly calls toString():
allUsers[user1] = "User 1";
allUsers[user2] = "User 2";
// All of the following will successfully retrieve the value for user1 ("User 1"):
// ONLY the first would work if allUsers was a Dictionary
trace(allUsers[user1]);
trace(allUsers[user1.toString()]);
trace(allUsers["231049-1"]);
trace(allUsers[new User(231049, true)]);
Dictionary and ArrayCollection have some important differences:
Dictionary maps objects to other objects, while ArrayCollection is just a list of objects.
ArrayCollection is Flex only, so unusable in a generic AS3 project.
Which one you should use really depends on what you need in your app:
Will you be using the "identity" object (with user id and "is current") somewhere else, without an associated peer id? In that case, make it a separate Identity class or so and use a Dictionary to map Identity instances to peer ids.
Do you need to perform lookups based on identities? In other words, do you need to ask "which peer id is associated with this identity?". If so, go for Dictionary + Identity once more, to avoid looping through a list instead.
I'm sure there are more considerations, but these should get you started.