How to allow NFTs to show up in the NEAR Wallet - nearprotocol

I've created an NFT contract and it seems as though none of the NFTs that I've minted show up in the collectibles tab. I was wondering what the criteria were for having NFTs in the wallet and how an arbitrary NFT contract could achieve this?

The way NFTs are displayed is that the wallet keeps track of a list of "likely" NFT contracts that you might own NFTs on. When you navigate to the collectibles tab, the wallet will then call the nft_tokens_for_owner enumeration method to display your NFTs. This means that in order to have your NFTs show up, you need two things:
Your contract should implement the nft_tokens_for_owner function as per the enumeration standard.
Your contract should be able to be flagged as a "likely" NFT contract.
Let's go through the first requirement. Your NFT contract should implement the nft_tokens_for_owner function and when called, it should return an object that contains a metadata field as per the metadata standard. An example response of the Token object that should be returned is shown below:
{
token_id: 'token-1',
owner_id: 'eth-denver-testing2.testnet',
metadata: {
title: 'My Non Fungible Team Token',
description: 'The Team Most Certainly Goes :)',
media: 'https://bafybeiftczwrtyr3k7a2k4vutd3amkwsmaqyhrdzlhvpt33dyjivufqusq.ipfs.dweb.link/goteam-gif.gif',
media_hash: null,
copies: null,
issued_at: null,
expires_at: null,
starts_at: null,
updated_at: null,
extra: null,
reference: null,
reference_hash: null
},
approved_account_ids: {},
royalty: {}
}
Your token object should contain some metadata which includes the media field. If your contract doesn't implement the nft_tokens_for_owner function properly, it will result in something that looks like the following, where the NEAR wallet has correctly flagged your contract but it doesn't know how to display your NFT. This is explained in the NFT zero to hero tutorial's minting section.
Let's now go through the second requirement. Up until late 2021, the NEAR wallet used a hacky solution to flag NFT contracts. Basically, it looked for any method starting with nft_ where the receiver_id parameter was your account. This code can be found here (please ping me if this code changes places). This was a hacky solution since there isn't any standard for minting NFTs and so people could mint NFTs by calling a function that didn't start with nft_ or where the receiver ID wasn't in the parameter and the NFT was simply minted to the predecessor.
After late 2021, we introduced a new standard for NEP-171 tokens known as the events standard. This dictated that your smart contract should emit an event whenever an NFT is minted, burnt, or transferred. This allowed NFT contracts to have one source of truth as to when things happened and the wallet didn't need to rely on hacky "guesses" as to what contracts were considered likely NFT contracts.
TLDR:
With this in mind, your contract should either implement the events standard (recommended) or your mint function should start with nft_ and have the receiver_id parameter set to your account in order for your contract to be flagged as likely (or both).
Secondly, your contract should correctly implement the nft_tokens_for_owner function which returns a token object containing metadata that has a valid media field.

Related

How to specify Metaplex NFT collection image in Phantom wallet

I've created a Solana NFT through metaplex. 1 out of 1.
It's showing up in my Phantom wallet on mobile however it's different from the NFTs purchased on solanart.
On the NFT screen, it says "Collection NFT" and shows the actual image only if I tap into the collection (last one).
What should I do to make it look like the purchased ones?
Also somehow another unspecified and empty (no metadata) NFT is also there and I'm not sure what it is (third one in the list).
Quite new to this, so probably missing something simple...
Thank you!
regarding the "Collection NFT" - You have to manually add metadata to the NFT:
Upload a new JSON + PNG pair (e.g. with arloader, sol-nft.tools arkb). It should can look like any other NFT metadata but should contain the collection data that will be shown.
use cli-nft.ts create-metadata or metaboss to add the uri (from the step 1) to the collection nft mint
Update June 2022: There is now a way better method to updating single NFTs:
Search your collection adress (Open a NFT on solscan, look into the metadata tab. There is a "collection" value which is your collection address). Copy it.
go to https://sol-tools.tonyboyle.io/update-nft and connect your wallet
enter the collection address
Modify whatever you need
Regarding the third NFT in your list: It looks like that you did not verify the upload and therefore the data was not on chain when the token was minted. Have a look here: https://docs.metaplex.com/candy-machine-v2/verify-upload

What view function can I call to determine if a user owns an nft minted on paras

I know from the zero to hero nft tutorial if I know the contract account id that minted it I should be able to call:
near view example-nft.testnet nft_tokens_for_owner '{"account_id": "'$NEARID'"}'
But what is the account id for a nft that was minted using paras? Do I need to search through a list of all paras tokens or is there a way to simply check for a single collection?
I'm thinking about making a fan game for an nft I like only accessible to users with that nft.
Currently reading these docs, but if anyone wants to answer might speed things up for me.
https://docs.paras.id/getting-started
If you want to see which NFTs a user owns on Paras, you can call the view-function from the near-cli like this:
export NEAR_ENV=mainnet # make sure you switch from testnet to mainnet
near view x.paras.near nft_tokens_for_owner '{"account_id": "'$NEARID'"}'
Paras.id also has a method called nft_tokens_by_series (found it on their GitHub repo), which takes one (string) argument, token_series_id. You can use the near-cli to get all NFTs for your series, and then see if the user owns one of your tokens.
near view x.paras.near nft_tokens_by_series '{"token_series_id": "id"}' # try id 49585 to get my own Mirror Crystals series
You can find the token_series_id in the URL when you inspect the details of an NFT on Paras.id (e.g. my own series https://paras.id/token/x.paras.near::49585/49585:2).
You can also do something similar with the near-api-js if you need to call the API from a browser or a Node.js application.
I'm not sure of understand completely your question, but you can list all the stores of any account with a simple "http get" call:
https://helper.mainnet.near.org/account/jeph.near/likelynfts
*Just change my account below for the user account.
And then knowing that the user has (or not) paras NFT you can make the next "http post":
To: https://rpc.mainnet.near.org/
Body:
{
"method": "query",
"params": {
"request_type": "call_function",
"account_id": "x.paras.near",
"method_name": "nft_tokens_for_owner",
"args_base64": "eyJhY2NvdW50X2lkIjoiamVwaC5uZWFyIn0=",
"finality": "optimistic"
},
"id": 158,
"jsonrpc": "2.0"
}
*Below "args_base64" are: {"account_id":"jeph.near"} , again, change my account and encode to base64.
It will return the info from all the NFTs that the user has from Paras.
The first get is not 100% necessary, but better be sure the user has or not NFTs from Paras, and then make the post.

Google Classroom API: Courses list returning unavailable classes

I am trying to fetch a list of classes which the current user has access to, and I am getting classes returned which the user cannot access.
Using the ruby client I can call
service.list_courses(course_states: "ACTIVE")
# I have 7 courses returned
OR
service.list_courses(course_states: "ACTIVE", teacher_id: "me")
# I have 3 courses returned (just mine)
The issue is that in the first call there are 4 courses returned which the current user cannot see/access. This seems like it shouldn't be happening as the docs say Returns a list of courses that the requesting user is permitted to view, restricted to those that match the request.
Is this a bug which I should report in the issue tracker or am I misunderstanding what results can be returned in the courses list?
My use case is that I want to create a course work item in a course, but I only want to do this for courses that the teacher can access. I thought that the list courses should return exactly that list, but, it doesn't seem to (unless I specify teacher_id: "me", but then I'm worried I'll miss courses which the teacher is collaborating on (if that's even possible))
Is this a bug or am I misunderstanding something?
Edited to add
Thanks to #ziganotschka for the API details. After further testing, calling service.list_courses(course_states: "ACTIVE", teacher_id: "me") will return courses that the requesting user has created or courses that the requesting user is collaborating on. This wasn't obvious to me as the course object has an owner_id field which is a single user, so, I thought the teacher_id might be referencing that.
The issue I had been running into was that I was logged in as the super admin which according to the answer below allows me to see all the courses. However, I wasn't actually able to access the weblink of any of those courses which is what was confusing me.
The behavior of the API is following:
service.list_courses(course_states: "ACTIVE") returns for anyone all the courses in which he/she is participating - be it as teacher or student.
If an admin calls service.list_courses(course_states: "ACTIVE") he can see all the classes of the domain - this is intended behavior.
service.list_courses(course_states: "ACTIVE", teacher_id: "me") will return only the classes owned by me.

Correct way to handle entities anytime in middle of conversation

I have started working with the LUIS and bot framework recently, after having some experience also with API AI / Google home development.
In the sample below that, I will use an example (from https://learn.microsoft.com/en-us/bot-framework/nodejs/bot-builder-nodejs-dialog-waterfall) is exemplified a step by step interaction with a user. First, it asks for a date, then a number, then a name for the reserve, and so on.
var bot = new builder.UniversalBot(connector, [
function (session) {
session.send("Welcome to the dinner reservation.");
builder.Prompts.time(session, "Please provide a reservation date and time (e.g.: June 6th at 5pm)");
},
function (session, results) {
session.dialogData.reservationDate = builder.EntityRecognizer.resolveTime([results.response]);
builder.Prompts.text(session, "How many people are in your party?");
},
function (session, results) {
session.dialogData.partySize = results.response;
builder.Prompts.text(session, "Who's name will this reservation be under?");
},
function (session, results) {
session.dialogData.reservationName = results.response;
// Process request and display reservation details
session.send("Reservation confirmed. Reservation details: <br/>Date/Time: %s <br/>Party size: %s <br/>Reservation name: %s",
session.dialogData.reservationDate, session.dialogData.partySize, session.dialogData.reservationName);
session.endDialog();
}]);
In my code, I have a similar multi-parameter dialog, but I want to allow the user to answer with multiple information at the same time in any of the responses it have. For example, after providing the reservation date the user can say "a reserve for Robert for 10 people", so both numbers of people and reservation name are giving at the same time.
To identify these text entities I suppose I have to call LUIS and get the entities resolved from the session context. I notice that the bot object has a recognized method that I think can work for that.
My question is how do I organize the structure of the code and the LUIS utterances and entities? Right now I have an intent with some entities and several utterances samples, but if I send this 'partial' user sentence I think it will not be mapped to the same intent and may not identify the entities with a small sentence like that.
How should I handle this? Do I need to provide samples for the intent with these partial sentences, that may contain only some of the entities?
Thanks
Yes, you should provide samples for all those utterances that you want to your intent to recognize. Not a million of samples, but just as few to get everything trained.
Then, the other problem that you might want to solve next, is asking for the information for those entities missing in the utterance. You can do that manually or you could go one step further and explore the LUIS Action Binding library.

Attach shipping information to Stripe Charge using Go

I'm trying to create a new charge via the Go API. I have a shipping address and a payment token. But the Go API doesn't seem to support sending the shipping address. The documentation indicates that it should support it but there isn't a direct mapping between the arguments described in the docs and the Go ChargeParams arguments and some are missing.
type ChargeParams struct {
Params
Amount uint64
Currency Currency
Customer, Token string
Desc, Statement, Email string
NoCapture bool
Fee uint64
Fraud FraudReport
Source *SourceParams
}
Is there some other way that I'm supposed to add the address that I'm missing?
I know nothing about Stripe's API but if you follow the fields of the struct, you find Charge ➜ Source ➜ Card ➜ Address1, Address2, City, State, Zip, Country. Is that what you are after?
Answer from Stripe support.
Thanks for writing in about this, I'm happy to help! Unfortunately our
go bindings don't support that parameter at the moment which is why
you couldn't find it in the source. The temporary solution would be to
create the POST request yourself when you need to send the shipping
details along with the charge.
I've forwarded this internally to make sure it gets addressed in the
future but unfortunately I don't have any timeline to share with you
at the moment. We are definitely open to a Pull Request from one of
our users so if that's something you'd feel comfortable building
yourself that would be awesome!
Here's how to use ChargeParams to include shipping infomation https://github.com/stripe/stripe-go/blob/master/charge/client_test.go
charge, err := New(&stripe.ChargeParams{
Amount: stripe.Int64(11700),
Currency: stripe.String(string(stripe.CurrencyUSD)),
Source: &stripe.SourceParams{Token: stripe.String("src_123")},
Shipping: &stripe.ShippingDetailsParams{
Address: &stripe.AddressParams{
Line1: stripe.String("line1"),
City: stripe.String("city"),
},
Carrier: stripe.String("carrier"),
Name: stripe.String("name"),
}
})

Resources