NFT drop marketplace Smart Contract and show collections by type - smartcontracts

New to NFT and solidity, and want to know how we can get NFTs grouped by collection type.
e.g.
collections =>
[
art => [nft1, nft2, ...],
music => [nft1, nft2, ...]
]
So that users can see collections and buy a random NFT from it.
My question is, where to put that logic ?
in smart contract or we have to save nfts in other database (MySql, MongoDb) where can query and categorise them on the basis of collection type ?
If I have to do this in other database e.g. MySql, MongoDb then I will listen to transfer event when an NFT is minted and save all details on database and then query to list collections on the basis of types.
Or If I add that logic in Smart Contract then I can create Collection struct and add functions to add/remove/move NFT to that collection.
What do you think one is better option to do this ?
If smart contract is better then, how I can get collections along with NFTs added in them ?
should I create mapping of collections and then each Collection struct will have mapping of NFT struct ?

Related

NFT Collections and Supply - ERC721 vs ERC 1155

I'm building an NFT marketplace, say a copycat of OpenSea.
I need to make my users able to mint their own tokens. That's ok, that would be an ERC721 contract. But I want to allow my users to mint different collections (as OpenSea does) with different supplies as follows:
(1) Have a single collection
(2) Have multiple collections
(A) Mint 1/1 NFTs
(B) Mint 1/N NFTs (say, for instance, 100 in total of the same NFT)
That makes a set of combinations:
Single collections (1) of 1/1 NFTs (A)
Single collections (1) of 1/N NFTs (B)
Multiple collections (2) of 1/1 NFTs (A)
Multiple collections (2) of 1/N NFTs (B)
Single or multiple collections (1 or 2) of both 1/1 and 1/N NFTS (A and B)
When using ERC721 I would be able to make (A) and (B), yet for every collection I would have to deploy a new contract. I want to avoid this.
Is this covered by ERC1155?
(A) Mint 1/1 NFTs
(B) Mint 1/N NFTs (say, for instance, 100 in total of the same NFT)
Both options are in accordance with the ERC-1155 standard.
The ERC-1155 defines a collection of tokens, where each token has an ID and an amount (specified as a value in the standard). Which means, you can have for example:
Token ID 1 that has amount of 1. At any point in time, it's always owned by just one address. (Case A)
Token ID 2 that has amount of 10. Five of these tokens ID 2 is owned by Alice, and other five tokens ID 2 is owned by Bob. (Case B)

DDD - Entity vs ValueObject

I was reading about DDD and I realize that sometimes an entity might be a VO or VO might be an entity. You can know which one is better depends on the context. I was checking different examples. For example, shopping cart DDD example. Product is an aggregate root, Cart is an aggregate root and items is a entity of Cart, so if you want to add a product to the cart you would do something like this:
$cart->addProduct(id $id, $name, $price)
class Cart
{
private items;
function addProduct(ProductId $id, ProductName $name, ProductPrice $price) {
this->items[] = new Item(
new ItemProductId($id->ToString()),
new ItemName($name->ToString()),
new ItemPrice($price->ToString()),
new ItemCartId(this->id->ToString())
);
}
}
There are two reasons why I think it is a VO:
You cannot modify the value's item ( only if the product's
price has been modify there is a event that would modify its price).
The item doesn't have id, it's has a reference of the
product(ItemProductId) and a reference of the cart (ItemCartId)
I was reading about DDD and I realize that sometimes an entity might be a VO or VO might be an entity. You can know which one is better depends on the context.
Usually its pretty clear whats entity and whats an value object. If it contains data that's fixed at the time of assignation, its a value object. For example "order address" on the order aggregate. When the order is placed, the address is set. "Addresses" may be an entity in user aggregate (i.e. a list of his common addresses), but for an order its an value object since its not supposed to change when the user edits or deletes one of his addresses.
cart->addProduct(id $id, $name, $price)
class Cart
{
private items;
function addProduct(ProductId $id, ProductName $name, ProductPrice $price) {
this->items[] = new Item(
new ItemProductId($id->ToString()),
new ItemName($name->ToString()),
new ItemPrice($price->ToString()),
new ItemCartId(this->id->ToString())
);
}
}
That's a pretty bad example. Why would or should the value object be ItemPrice? Does that makes it any special? Why string? A price is usually just a numeric value but also involves a currency, passing it as string kinda beats that.
On top of that, having ItemCartId in the it does
a) leak data persistence knowledge into your domain. The fact, it's contained inside this->items[] already establishes a relationship between the entity (or aggregate) and the value object. ItemCartId as no meaning in the domain, other than that it's required for relational database engines (=persistence knowledge)
There are two reasons why I think it is a VO:
You cannot modify the value's item ( only if the product's price has been modify there is a event that would modify its price).
You sure? Why would a eCommerce business want to have the prices in the card anyways?
Prices are informational only, they could change before the order is placed. Same as availability.
A lot of users put stuff in their cart and check on next day. In that time, the price could change.
No company would want to sell a product for the price when it was put into the shopping cart, if the price increased in the time since it was put in there. That would mean a financial loss.
Prices in the shopping carts are informational, not compulsory. You need know the exact process of the company.
The item doesn't have id, it's has a reference of the product(ItemProductId) and a reference of the cart (ItemCartId)
Again. Why do you think ItemCartId belongs to the Item object? That's leaked persistence knowledge, since its only important for relational database systems.
All you really need in a shopping cart is
* product or article number (not necessary the id, that's typically db knowledge)
* quantity
Nothing else. If you may want to change the user when the price changed and show the old and new price, the take the price (=currency value object, not ItemPrice) to it too as a value to compare to an old state.
Finally and probably most importantly: Consider if the shopping cart is an aggregate at all (or does fit into ddd).
After all, most shopping carts are only a value bag w/o a lot of business logic into it. The real logic (checking the real price, product availability, asking for shipping location, calculation of taxes and shipping costs) happens during the checkout process, not while putting stuff into the cart.
For example you can check out eShops on Containers demo project showing an example shopping service based on microservices and ddd.
Some microservices apply DDD (such as Ordering microservice), where others don't (Catalog microservice or the Basket (cart) Microservice).
Applying DDD doesn't mean everything needs to be done with DDD. If its simple crud based services, then you don't need DDD for these. DDD adds a value where you have complex systems and complex business logic.
A catalog has neither, it just presents data which come from a different system (i.e. ERP which on other side may be built on using DDD).
I don't understand what are you asking exactly, but the code you are providing could be improved.
First of all I suggest you to read the red book by Vaughn Vernon https://www.amazon.co.uk/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577: you can find 3 chapters describing how to define entities, value objects and aggregates, with some rules of thumbs.
One of those advices, is to keep your aggregates as small as possible, in order to improve your performance and keep the code easy to read and maintain. Imagine that you have a Blog aggregate that contains a list of Post entities: if you manage all of them in a single aggregate, when you want to modify the blog Author, for example, you are forced to retrieve all of the blog's post, without any reason, and that means that you are doing a join and slowing down your application. The more your aggregates grows, the slower those queries with their joins.
So, in the case of the Cart, I suggest you to build the cart without any item or product, instead you can add the CartId to the Item. Cart does not know which items it contains, but items know in which cart they are.
About value objects: is a tool that allows you to wrap some validation and business logic inside a class that is represented by its state and not by its id (like entities), so in the case of the cart, if you put two identical bottles of water inside it, how can you know that they are different? Do you need to know that they are different? Are they different if they are physically (or logically different) or are they different if some of their attribute is different?
In my opinion an item or a product, in your case, are entities because they are not measuring anything, and when you put an item twice, you actually have two different items (and you use an id to recognize them).
This is not necessary like this, sometime you can use a value object and sometimes an entity, it depends on your context. A good example to understand that difference is with money:
if you want to measure an amount, for example 10 dollars, probably a value object will work for you, because you don't care if it a bill or another, you just want to measure 10 dollars; in this case if you have 10 dollars, is not important if you have a bill or another, the important thing is that is 10 and not 5
in the case that you need to recognize different physical bills, for any reason (you need to track money for the police), you should use an entity, because any printed bill has a unique serial number, and a 10 dollar bill, in this context, is actually different from another 10 dollar bill
Hope this can help you.
Goodbye!

Empty all accounts in a smartcontract for a banking application

I am working on a sample banking code in solidity. I wanted to use a so called "TakeAllTheMoney" and run function (just to give you an idea about the role of the function).
This function should only be executable by the deployer of the contract and should give him the possibility to take all the money on the bank and transfer it to his account.
Problem: How can I empty also the account of the other user of the bank? Meaning that when a different user - not the deployer of the contract and of the function - uses the contract after the "TakeAllTheMoney" function is employed, he also sees 0 on his account.
Many thanks in advance
function TakeTheMoneyAndRun() public{
require (msg.sender==Owner);
balance[msg.sender] -= balance[msg.sender];
(msg.sender).transfer( address(this).balance );
Expected results after employing this function:
Balance Bank = 0
Balance person that employed contract and function = 0 (since it went on his metamask account or similar)
Balance of every other user = 0
Again, thanks!
You are mixing two things. User's amount in metamask and user sent amount to Bank in your case is Smart Contract and stored in some variable. So the amount you see in the metamask is the amount User own and has no link with the Smart Contract until and unless you send the money to the Smart Contract.
The Smart Contract in your case "Bank" the money sent by the user is store in the Smart Contract and the tracking of money recieve is stored in the array. Smart Contract itself does not holds the record of the previous transaction. So if you want to delete the Smart contract balance tracks of the User you have to empty that particular array. Although it sounds fishy if you want to implement it and wants to make the user accounts to zero in the Smart Contract.

Retrieve customer related to payment

Anyone know if it's possible to retrieve the customer name related to a transaction from the API?
I see it under "Paid by" if I follow the "payment_url" in the connect v1 https://connect.squareup.com/v1/{{location_id}}/payments/{{payment_id}} endpoint but can't see to find it anywhere else
Background: I'm working on a ticketing system that breaks out items by item_category so a kitchen gets only food items and the bar gets only drink items.
I have queues and itemized tickets by category BUT I can't seem to find the customer's name anywhere
You'll need to utilize the V2 Transactions API. When you call ListTransactions or RetrieveTransaction (ListTransactions), the Transaction object will have an array of Tenders, tenders, which has a field called customer_id. With this id, you will be able to pass it to RetrieveCustomer (RetrieveCustomer) to find out their name. Note that if you're not explicitly filling out their name, the name might not be available (an "instant profile" (Instant Profiles) will be created with whatever information can be retrieve from the card used to pay).
Update: Alternatively, as suggested by #Dan, would be to strip the payment_url from a V1 RetrievePayment (RetrievePayment) which includes the transaction_id at the end of the URL: https://squareup.com/dashboard/sales/transactions/TRANSACTION_ID. This is more efficient as you won't need to loop through transactions, and allow you to send it straight to RetrieveTransaction.

Cannot find Yodlee DAG fields in API

In the Yodlee DAG templates, there are fields for ISIN and SEDOL and some other fields that we do not see in the API. Are these fields able to be pulled via the Yodlee API?
If you have downloaded the complete Yodlee SDK folder contents and search the Javadoc/index-all.html for sedol and ISIN you will find multiple properties with these names all in Investment/SEcurities related structures/classes.
A warning, just because the property is there does not mean it's populated. Just because it's populated doesn't mean it's populated with all information (e.g often times sensitive information is obsecured to the last 4 digits such as Account #s).
The fact that I see it as a property in the SecuritiesSearchCriteria however might lend hope to the fact that it is populated with usable info.
ISIN is an unique identifier of a holding in India and SEDOL is a unique identifier used in UK and Ireland. Hence they will be populated for investment account of users from those parts. Also their population is dependent on the availability at the end site(The website from where we are scraping the data)
You can get these details through Yodlee's DataService API.
This API will return the itemSummary which contains ItemData object.
This ItemData object contains the list of accounts and then each account will have Investment data and this investment data contains Holding details which contains all the details for a holding. In the Holding details you can find the method to retrieve ISIN , SEDOL etc.