Entities and Solana accounts - solana

I'm new to Solana/web3 and started learning about developing dApps for Solana. From my understanding, an "account" is essentially just a space allocated in memory in the decentralized "computer".
Does this mean that if I were to write a dApp for a bidding usecase for example, it would involve 1 account for each item being bid out, 1 account for each bidder, and 1 account for each bidder's bid?

You've understood the concept perfectly: account == data. It's all a matter of opinion after that, and you have the same tradeoffs as with any software system design.
For example, do you want to have one big global state? You could have all the items and their associated bids in one account. That would likely be a huge account that gets changed often, so it could create bottlenecks in the blockchain.
Then you may think, what about just one account per item being bid on? In that case, you could store all of the bids and bidders for the item in one place. In that case, you may not need 1 account for each bidder and 1 account for each bidder's bid.
If you go that route, and a user wants to know about all of their bids from the frontend, it may be tough to discover, since you'd have to iterate through all of the items being bid on to see if they have a bid. So in that case, maybe you do want 1 account per bidder.
So unfortunately, the answer is: it depends!

Related

Product price changed while creating order

What is the DDD way of handling the following scenario:
user enters Order Create screen and starts creatingnew Order with OrderItems
user chooses ProductX from products catalog and adds quantity
OrderItem for ProductX is created on Order and user goes on adding another product
in the meantime, before Order is saved, admin changes price for ProductX
Assuming Product and Order/OrderItem are separate aggregates, potentially even separate bounded contexts, how is this handled?
I can think of several options:
optimistic concurrency combined with db transactions, but then if we broaden the question to microservices where each microservice has its own db - what then?
joining everything into one giant AR but that doesn’t seem right.
introduce a business rule that no product prices are updated during the point of sales working hours but that is often not possible (time triggered discounts, e.g.)
What is the proper DDD/microservices way of solving this?
What is the proper DDD/microservices way of solving this?
The general answer is that you make time an explicit part of your pricing model. Price changes made to the product catalog have an effective date, which means that you can, by modeling time in the order, have complete agreement on what price the shopper saw at the time of the order.
This might introduce the concept of a QuotedPrice as something separate from the Catalog price, where the quote is a promise to hold a price for some amount of time.
To address this sort of problem in general, here are three important papers to review:
Memories, Guesses, and Apologies -- Pat Helland, 2007
Data on the Outside vs Data on the Inside -- Pat Helland, 2005
Race Conditions Don't Exist -- Udi Dahan, 2010
I think one way to solve this through is Events. As you said, Product and Order can are very least separate aggregates, I would keep them loosely coupled. Putting them into one single aggregate root would against Open/Close and Single Responsibility Principle.
If a Product changes it can raise a ProductChanged event and likewise of an Order.
Depending on whether these Domain-Objects are within the same service or different service you can create a Domain-Event or an Integration event. Read more about it here.
From the above link:
A domain event is, something that happened in the domain that you want other parts of the same domain (in-process) to be aware of. The notified parts usually react somehow to the events.
I think this fits perfectly to your scenario.

How to implement constraints that are external to a microservice?

Suppose we have two microservices, Customers and Orders, with no dependencies between them, i.e. they don't call each other, they don't know each other. Every order, though, has a reference to a customer by means of a customer id. In other words one customer may have zero or more orders, and one order belongs to exactly one customer.
For the sake of the example, it's totally fine to delete a customer unless there are orders belonging to that customer. What is the most appropriate way to implement a constraint on Customers that prevents a customer from being deleted if one or more orders have a reference to that customer? Analogous to referential integrity in a relational database.
These are the approaches I can think of:
Let Customers ask Orders if a given customer has any orders, e.g. via API call.
Let Customers keep track of which orders are assigned to every customer, e.g. by having each customer record maintain a list of order ids.
Merge Customers and Orders into a single microservice and manage it internally.
I'm not sure which approach is the best for the given example in a microservices context. I can see pros and cons in all three approaches but I won't list them here because I'd like to hear other people's thoughts on the problem, including approaches not listed above. Thanks.
Probably the second approach would help if you're going to decouple through events, either tracking a list of ids or a counter just telling how many orders are stored for such a Customer.
On the Order microservice you will emit an event when there is a creation/deletion that will be captured by the Customer (or any other microservice interested) who will take care of updating the list of order ids (or increment/reduce the counter).
If customer order counter is 0 then you may delete the customer.
Let's start with your third approach: This will not work in a Microservice world, because you will always have those constraints between some Services. And if you want to solve all of them this way, you'll end up with a Monolith - and that's the end of your Microservice story.
The first and second approach have both the same "problem": These are async operations, that may return false positive (or false negative) results: It's possible to make api requests for delete customer and create order (or delete order) at the same time.
Though this can happen:
For your first approach: Customer Service asks Order Service if there are any Orders for this Customer. Order Service returns 0. And at the same time Order Service creates a new Order for that Customer in another thread. So you end up with a deleted Customer and still created an Order.
The same applies for your second approach: The messaging between those services is async. Though it's possible that Customer Service knows of 0 Orders, and permits the delete. But at the same time the Order Service creates a new Order for this Customer. And the OrderCreated message will hit the Customer Service after the Customer has already been deleted.
If you try to do it the other way around, you'll end up with the same situation: Your Order Service could listen to CustomerDeleted messages, and then disallow creating new Orders for this Customer. But again: This message can arrive while there are still Orders in the database for this Customer.
Of course this is very unlikely to happen, but it still is possible and you cannot prevent it in an async Microservice world without transactions (which of course you want to avoid).
You should better ask yourself: How should the system handle Orders where the corresponding Customer has been deleted?
The answer to this question is most likely dependent on your business rules. For example: If the Order Service receives a CustomerDeleted message, it may be okay to simply delete all Orders from this Customer. Or maybe the behavior depends on the Order's state property: It's okay to delete all Orders with state = draft, but every other Order from this Customer should still be processed and shipped as usual.

Square payments: How to protect 'cards on file' from a data breach

I'm in the early stages of integrating Square payments. It makes sense in my application to allow users to save their card details, as we expect multiple small transactions. Square calls this feature 'cards on file'.
As part of this process you create a customer and a related card in Square's system; IDs for these will be held in my system and associated with my users; that way when they come to pay again they can select the option of using a card on file. The API to actually charge the card simply takes these two IDs and an amount.
What worries me is that my database is holding all the data necessary to charge a customer's card; I could write a script which just charges all of my customers an amount of money - naturally a hacker with access to my data could do the same thing.
I wasn't expecting to have this level of risk in my system - my assumption was that Square would have isolated me from this (via some sort of user challenge for missing data - e.g. the CCV number). It seems the safe option is to not use the 'card on file' feature and have the user re-enter every time.
Is this right, or have I completely misunderstood something here?
In order to charge a card, your Square access token is required along with the card ID. It's best practice to store that access token as an environment variable in order to limit the security risk. If someone gains access to the card IDs in your database, they won't be able to charge any of the cards without that access token that's associated with your developer account.
I did miss something - as any charge made on a customer's saved card is credited to my account (as configured in the Square portal), the only beneficiary of any fraudulent charge would be be me. A hacker could not get access to funds and therefore the risk is limited in scope.
Obviously if I was a fraudulent company there would be a risk to users - it seems the EU isn't happy with this and changes coming this year will require additional information to be captured from the user at the point of sale.
Strong Customer Authentication

Create subscription groups in Google Play?

In the iOS App Store, you can create subscription groups, which I believe allows the app to (if coded as such) display different subscription options to different groups of users. For example, grouping magazine subscriptions by genre.
Is there anything like this for the Google Play store, or would I need to do the groupings myself within the app?
Although I am not sure at this time, but I don't think Google Play provides the equivalent of a Subscription group. At the time of this writing, I am working on the same and new updates will publish edits here.
There is a catch here,
which I believe allows the app to (if coded as such) display different subscription options to different groups of users
Although, subscription groups can be used for the purpose described above, they are not inherently meant for the same. Subscription groups are meant to group different subscription products so that the user can purchase only one of them at the same time.
You can view a subscription group as a product/ service your app offers and the subscription products under them as the Plans under the same. For example, for a news app, you may offer a subscription product to your users with different plans like Single Category Monthly, All Monthly, Single Category Annual, All Annual. The single category app may provide news only in one single chosen category like sports, entertainment, politics etc. The user can choose to change between plans any time but can subscribe to only ONE plan at a time.
Also, as you would comprehend, some of these plans are higher levels of services than others. Based on your business definition, you can put these plans at different levels. That will determine if the user is upgrading/downgrading/cross grading while changing a plan. For example, in this case you may have two levels:
Level 1 may have All Monthly and All annual.
Level 2 may have both the single plans.
1 -> 2 will be downgrade, 2 -> 1 will be upgrade, 1 -> 1, 2 -> 2 will be cross grade.
In Google Play Billing, an upgrade or downgrade will be performed by setting the oldSku while making a purchase. If the oldSku is set, Google Play Store will consider it as an upgrade/downgrade.
However, I am not sure at this point how the App Store determines if it's a upgrade/ downgrade / crossgrade. May be based on the price (unlike Apple).
Grouping may not be required for Playstore. In Appstore, since all the subscription options are listed, we need to group a set of items together. For example, if user subscribes within a 10 days of registration, 10% reduction in monthly, annual cost can be provided. In such cases, if they cancel the subscription, they can re-subscribe from store. They will be listed with only those group to which they subscribed before (monthly, annually for within 10 day plan). So they continue to get 10% reduction if they re-subscribe to any plan (monthly, annually).
In Playstore, user can re-subscribe to the same subscription that user opted before. So such case won't arise.
Set update subscription param as specified here

what should I label this UI property group selection

In my application my users can generate statements, monthly and weekly. I've recently been
asked to allow the users the capability to associate a customer with either weekly or monthly
but not both, to a customer. This then leads to...if a user selects a weekly customer and runs a monthly
statement, he or she, should be prompted that customer's statement cannot be generated and why.
My question: In the UI of the customer screen when editing a customer, should I label the choice option(s) as
Select the customer Statement
Frequency [ monthly or weekly]?
Select the customer Statement Type [
monthly or weekly]?
What giudelines do you follow to assist you when making such decisions?
Thanks
I would suggest using Statement Frequency. Other choices might be cycle or period.
The rule of thumb should be to ask the user (product's business owner) what terms and wordings to use. It's not uncommon for business users to review all the terms and messages the application uses. That way the resulting product will speak the users' language.
The reason is that developer-invented terminology often leads to unintuitive UI. It may be perceived as clumsy, unfamiliar, or even incomprehensible by end-users. The worst case is bringing the software's internal terminology and mechanisms to the user interface.

Resources