NEAR Marketplace - Timed Auction Functionality - nearprotocol

We're building a marketplace in NEAR. We have two smart contracts for token and marketplace. Same as NEAR example.
In our platform, we have successfully implemented below features:
Token mint (used contract method: nft_mint)
Token listing for sale at Fixed Price in marketplace (used contract methods: storage_deposit nft_approve)
Token purchase (used contract method: offer)
Apply creator royalty at mint time.
Apply service fee (Transaction fee of Marketplace) on each sale.
Everything is working fine.
Now, we would like to implement the Timed Auction Functionality
Creator can create NFT’s to be sold as an auction so that buyers can bid on them to get a higher price.
Method:- Sell to the highest bidder: where the highest bid wins at the end.
Making a bid on this kind of auction is like making an offer on a fixed-price listing. The seller can choose to accept it at any time, but the buyer will near of the amount of bid to create a bid.
Questions:
How we can implement the Timed Auction Functionality with Marketplace
Contract?
Do we have any documentation or example for the
Timed Auction Functionality?
Example of OpenSea's Timed Auction Functionality:

You can't do that directly from within a contract since the contract does not run all the time you will have to call function trough something like https://cron.cat/ or your own.
Contracts perceive time trough current execution so when a function is called env::block_timestamp_ms() within said fn would give us the current time of execution, you can subtract time from it to get some time in the past. We can do manual checks like is the time stamp past this than do that or the less accurate is the blockheight above certain threshold but all this will have to be executed within a function that needs to be called.

I will preface this post by saying that this is how I would go about solving this in a simple way. There are more complex solutions out there but I'll try and keep it relatively simple. (scroll to the bottom for a TLDR).
Here's a solution to the timed auction functionality. In the marketplace example that you posted, what you'll want to do is store two extra fields in the sale object indicating the desired length of the auction as well as the time when the sale was listed.
Whenever NFTs are put for sale (in the nft_on_approve function), you'll need to add the current block_timestamp (which will give you the number of nanoseconds since the Unix epoch). You'll also need to store the desired length of the auction which is up to you as to how you would like to implement that. It can be time in nanoseconds, milliseconds, seconds, days, either since the Unix epoch or the actual desired duration of the auction.
Once your sale object contains both these new fields, all you would need to do is whenever an offer is made, check if the current block timestamp is within the desired auction length. If it is, proceed, if it's not panic. Since the marketplace can't constantly be polling to see if the auction is finished, a common approach is to use the functionality I described above:
You either bid on the NFT before the timestamp or you didn't. If you did, your bid is accepted, if you don't, it panics.
At this point, there is no way for the marketplace to automatically transfer the NFT to the highest bidder the second the auction closes (due to the marketplace's inability to poll). My suggestion here would be to have a claim function that the highest bidder must call if they want the NFT transferred to them. You can get spicy with this and have timeouts whereby if it isn't claimed within 5 days, the original owner can claim it back but for the sake of simplicity, let's not get into that.
As for the bidding mechanic, there's many different ways you can do this. I'll go over one of the more simple approaches. Currently, when a sale is listed with sale conditions, the NFT can only be purchased for more than or equal to the price as shown here. What you'll want to do is store active bids in the sale object.
You'll need to store both the current highest bidder as well as their bid amount. This will be initialized to empty when the NFT is listed and then once an offer is made for less than the desired list price, it's considered a bid. Bids will only be added if they are less than the desired price and greater than the highest current bid. If the offer is more than the list price, the NFT is automatically sold and the purchase is processed.
Combining everything I've outlined so far in a TLDR:
What you would need to add as a minimum PoC to the sales object:
Store desired length of auction (in whatever format you want)
Store date of listing
Store current highest bidder
Store current highest bid
Listing mechanics:
When a sale is listed, set the date of listing and the desired length of the auction.
Offer mechanics:
make sure the attached deposit is greater than the current highest bid (if none, make sure it's >= 0).
If the attached deposit is greater than the list price, process the purchase. If it's not, add it as the current highest bid.
Make sure that the any offers are made within the desired length of the auction. If they aren't panic, if they are, you're good to go.
If somebody is outbid, make sure you refund them for their deposit!
Claim mechanics:
Claims can only be made if the auction time has passed. Only the highest bidder can claim the NFT. Once claimed, the purchase is processed.

Related

I want to prevent user to make payout request from his wallet for specific time

I'm working on e-learning academy system like udemy every instructor have wallets and wallets have three type of balance
1- total balance and it present total earning
2- available balance and it present earning that he can make payout or transfer it to his bank account
3- hold balance and it present earning that is not available for specific time then will be available to transfer it.
Project build by Laravel my issue how can I hold money for 14 days and after that make this money available without any action from my side I need logical idea to make it
can use cron job, or is anyone have this experience before ?
Let me break down the issue as per my understanding so we make sure I'm answering the correct question;
You have a system that has a wallet feature.
This wallet needs to hold some money and make the money unavailable to be paid out (hold status)
Then after 14 days, the money gets paid automatically without any interaction.
If I'm correct, then keep reading the answer below. If i'm not, correct me with a comment and I'll update my answer accordingly.
Answer:
We will create a new table. Let's call it pending_payments. It'll have the following information: user_id, payment_amount, pay_at
That table will hold information about pending payments and to which user they should be paid as well as the amount and the date it should be paid at.
We'll have a Laravel job that can be automated ( read this for more information: https://laravel.com/docs/9.x/scheduling) which will do the following:
a. Run daily on a specific time. Let's say at 13:00 daily for ease.
b. It'll check the pending_payments table for payments that should be paid today.
c. Pay them ( which means run whatever function/task you have to run in order to process the payment).
d. On a successful payment, remove the row from pending_payments table. And on a failure payment, log the error and insert the row again with a later date to be retried again later.
That's it.

Laravel Cashier incrementQuantity() tidy invoicing

Has anybody here dealt with incrementing subscriptions for "admin" users? Also, how do you handle invoicing and first/second-month charges in a neat manner?
I have a use case where users can sign up other subscribers and pay for these subscriptions from their card on file. The "admin" user signs up for the first subscription, and I keep incrementing the original sub every time a new sub is added.
When I send these through Cashier, the user only seems to get charged once, and then the second, third, etc., the first-month cost gets added onto the next month's invoice, and a new line item of unused time every time the admin user adds a new sub. So I first do:
$request->user()->newSubscription()->create();
Then I do:
$request->user()->subscription()->incrementQuantity();
The user only gets charged one monthly charge at newSubscription()->create(), And the next month's invoice has the following math.
(# of Subscriptions x Monthly Charge) - (Monthly Charge)
And the invoice has a ton of line items saying "Unused Time ..." which looks OK if that admin user only has one or two additions to their subscription but gets messy real quick beyond that. This seems super unprofessional and annoying to explain to the admin users. How do you/would you guys go about making this smoother? I understand that the invoicing for the incrementQuantity() method is enforced by the Stripe API, but it doesn't make sense to have so many prorating adjustments in a first invoice.
What is your goal/desired behavior here? Laravel cashier does allow you to change how you want the prorations to behave. By default prorations will be created and pulled into the next invoice, but you can also choose to disable prorations entirely or create prorations and have them immediately invoiced so that the difference is price is paid for immediately.
If you don't want any prorations generated at all when you update the quantity of a Subscription you can use noProrate() (see laravel's docs). Disabling prorations entirely may not be what you want though, since it won't allow you to charge a customer for the difference in price when they update mid-cycle. As an example, if you start off with a quantity: 1 Subscription they'll be charge for just 1 unit at the start of the month. If prorations are turned off and you update to quantity: 5, the customer won't have to pay for the new price until the subscription is renewed. If this is still what you want to do, you'd use it like this: $request->user()->subscription()->noProrate()-> incrementQuantity().
Another option would be to keep generating prorations, but have them immediately invoiced so that they aren't reflected in the renewal invoice at the end of the month. This will result in the customer being invoiced more often, but would solve your issue where the renewal invoice looks cluttered because of all the prorations. You would get this behavior by using alwaysInvoice() like this: $request->user()->subscription()->alwaysInvoice()-> incrementQuantity().

Retrieving Card details from Square Customer

I'm trying to create a recurring payment on Square, ala Stripe subscriptions. However, I am having trouble retrieving a customer's card information (specifically customer_card_id) to pass into Charge.
Our flow is such:
A customer visits to our store and subscribes to a membership, which we process via the point of sale app.
We continuously poll Square to retrieve payment information, and create membership records appropriately.
When the user's membership period expires, charge them for the next month's membership.
When researching RetrieveCustomer, I find that there is a cards property under Customer, but iterating through all the Customers under our account, they all have cards = None despite us having taken card payments via the point of sale app.
Also, looking at ListTransactions, there doesn't seem to be anything that might be customer_card_id. The IDs I see there are tender ID, location ID, and transaction ID. The card_fingerprint also looks promising but that doesn't seem right either, since a card can have both an ID and a fingerprint.
Am I missing something? Where might I find customer_card_id?
EDIT
Looks like I was dumb and my local instance of our application was just out of date with transactions from Square. After updating my data with customers we've processed since the last time I updated, customers with a non-None card property now show up. tristansokol's answer below is still valid however.
How do you process the first charge? You need to explicitly add the card on file, it won't be added by default from processing a transaction from a customer. See: https://squareup.com/help/us/en/article/5770-use-card-on-file-with-the-square-point-of-sale-app

Event Before the Record is changed in MS Access

I have an MS Access Form where I have two subforms. I need to be able to run a code/query before the record is discarded.
This DB is for tracking a hotel's sales and payments. The bounded form has the following layout:
First we have the main form with global fields like, ClientID, client name, address, bill date, restaurant bill, spa charges, etc.
Then I have the rooms subform (Datasheet view). This form has all rooms allotted to the guest. It also has the number of days charged and Rate fields.
Lastly I have a payments sub form (DataSheet View). It has all payments received from the guest. Last Tab index is for the payments Subform. I need to find the total amount the customer was billed. (sum of all room rate X number of days + Money Spent in Spa + Restaurant Bill). I also need to find the sum of all payments. If the total payment is different from total bill then I need to prompt the Operator to confirm the addition.
I know the VBA codes and queries to process the above. But what I do not know is how to trigger this event. I tried AfterUpdate, but it is fired the moment I move to any Sub Form. I need the code to run after the Operator has made all changes and is ready to move to the next record. I am at a loss on how to accomplish this.
You could just place the function in the after update of the last field in the operator's workflow on the last subform?
Alternatively, place a check to run the code on your move next/prev buttons to ensure the operator has completed the entirety of the workflow?
Could you post a ss of the form(s) so I can get a visual picture :)?

how can i decrease the product price on cart page?

If the user has an existing account balance, I'd like to give him the option to specify how much of his previous balance to apply to the item and sync this info with the cart and order. I have already implemented the user's account balance, both on the front and back end.
Would a coupon-like system work best, or should I try something else?
Thanks in advance.
I would let the customer decrease its cart total with the balance would be more simple / logic for the customer also (?)
What E-commerce solution do you use? Magento(?) If so there are coupon extensions that can handle this.
You could also build a simple balance system where users would see there balance in there account ( if such feature is implemented) or just mail them a message with a unique code that you save in DB + the value of balance then use this code as a coupon on checkout.
We have created quite a few e-commerce solutions up to date. Usually, when user balance is involved, then what you do is create two transactions referred to one invoice. In the first transaction specify the amount taken from balance, where as leave the other transaction for whatever checkout method you use. Upon callback from the checkout, see if the balance paid matches the invoice to mark it as paid respectfully.
Alternatively, you can use discount - decrease user balance and add "discount" to the order. It all depends on your accounting needs and preferences.
On Amazon they allow you to apply any unused balance to the existing order. Its when you checkout that they say you have $150 credit on your account, would you like to apply this to your order, it defaults to yes in a tick box.
Its quite neat and simple, it doesn't allow you to apply a part amount from what I've seen.
Then when you go to payment you pay $total - balance.
So if you have $200 total, the payment via credit card would be for the $50.

Resources