I have successfully deployed and verified an ERC721 smart contract on BSC's testnet. Also successfully minted and awarded new ERC721 tokens. Next up is transferring tokens between wallets. So far so good, except that I'd like to add transfer comments to the transfer transactions.
My contract supports the standard safeTransferFrom(senderWaller, receiverWallet, tokenId, data) function, and I can see the data (i.e. - the transfer comment) being sent out. But it doesn't appear when I view the successful transaction in the BSC testnet explorer.
Here is an example transaction --> https://testnet.bscscan.com/tx/0x1f3bf69da66cff66bbeeb6ce6f7505be8a78729685162811cb29c9dc30a347d6. Decoding the data in the BSC testnet explorer I can see the trailing data in hex form and it translates back to readable text when I convert it back. See trailing value starting with 205363... below. Here is a screen shot of the hex converting back to the intended text value.
Function: safeTransferFrom(address from, address to, uint256 tokenId, bytes _data)
MethodID: 0xb88d4fde
[0]: 0000000000000000000000008175f3b00af0b775136b918a78298aaf4e1ea137
[1]: 000000000000000000000000ba3662af7c0cecd20cd97ef8072c30f4449b16b1
[2]: 0000000000000000000000000000000000000000000000000000000000000005
[3]: 0000000000000000000000000000000000000000000000000000000000000080
[4]: 0000000000000000000000000000000000000000000000000000000000000020
[5]: 5363686564756c656420736572766963696e6700000000000000000000000000
Here is my code that is used to encode the web3 method call.
const soygaToken = new web3.eth.Contract(soygaABI, contractAddress);
var byteComments = Buffer.from(comments.padEnd(32, "\0"), 'utf-8');
var myData = soygaToken.methods.safeTransferFrom(senderAddress, recipientAddress, tokenId, byteComments).encodeABI();
Any ideas as to what's causing this data to be missing from the transaction when I look on the BSC testnet explorer? Reviewing the ERC721 specs (https://ethereum.org/en/developers/docs/standards/tokens/erc-721/) the data parameter should be a 32-byte value. Which it appears I'm passing along.
Bounced this off the core Nethereum developer. He verified the user data is present, but it's likely just an issue where the Etherscan web client isn't decoding it. So the user data should be accessible.
Related
does anyone know how to create a secure in-game NFT mint? I think if we gave permission to users to create an NFT (this is the idea of the game - to assemble an NFT from different parts), it would be vulnerable because you can insert your own image URL into the function. I thought a mint function that can be used only by a game contract with the require(somePartsAmount), would it be secure?
Something like this:
function awardItem(address player, string memory tokenURI)
public
onlyGame
returns (uint256)
{
require(somePartsAmount);
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(player, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
How to be with the presale mint, because we can't check parts here and creating by owner is too expensive?
Usually, you won't want to give users the opportunity to set a custom token URI to an nft. Thus, I would suggest making all the URI things in another function maybe. For you to have, let's say, 1000 minteable random nfts, you would first need 1000 tokenURIs for those nfts to have information attached to, and then you would have to use the default getTokenURI function which returns the base token URI you specify when creating the smart contract and just adds the nft id to the end of it.
I'm trying to generate the channel ID of my private channel in Telegram.
I use the following:
link = input("Please provide channel invite link: ")
print(utils.resolve_invite_link(link))
My output looks like the following (I've scrambled the numbers):
(0, 0123456789, 1234567891234567891)
When I view the private channel in the web browser, I get the channel ID as https://web.telegram.org/z/#-9876543210
So the channel ID should be -1009876543210, which I confirmed with IDBot.
Why isn't 9876543210 appearing when I call variable link within utils.resolve_invite_link()? That's the value I expected to see, not 0123456789.
utils.resolve_invite_link(link) no longer works with the new links.
Old links used to pack the channel/group ID inside the links themselves but this is no longer the case. The function will possibly be removed as well in future updates of the library https://github.com/LonamiWebs/Telethon/issues/1723
The most reliable way now is to use CheckChatInviteRequest https://tl.telethon.dev/methods/messages/check_chat_invite.html
So in the documentation, it says if you want to get tasks with immutable id instead of normal one just add a header 'Prefer: IdType="ImmutableId"'. I've done that but it still returns tasks with normal ID.
It works fine when I try it with outlook events and if I try to get outlook task by ID (get single task instead of listing all). But as soon as I try getting all tasks with immutable id it doesn't work. It doesn't say any error it just returns the data but with the normal id.
Also, I know that outlook tasks API is getting deprecated but todo list API is not going to cut it right now and I've already tried it - there is no way to retrieve any form of immutable ids, just normal ones.
This is the code I use to retrieve all tasks (list all tasks) in NodeJS:
let response = await client
.api('/me/outlook/tasks?$top=25000')
.header("Prefer", "IdType=\"ImmutableId\"")
.header('Prefer', `outlook.timezone="${timeZone}"`)
.version('beta')
.get();
It is very weird because when trying to get one specific task by ID and setting prefer id type header, it works.
Anyway here is how requests look:
LIST OUTLOOK TASKS (GET ALL OUTLOOK TASKS)
GET https://graph.microsoft.com/beta/me/outlook/tasks
GET ONE SPECIFIC TASK VIA ID
GET /me/outlook/tasks/{id}
HEADER FOR GETTING IMMUTABLE IDS INSTEAD OF NORMAL ONES
Prefer: IdType="ImmutableId"
POTENTIONALLY HELPFUL
This is the code I use to retrieve all events with Immutable ID's (this works compared to tasks)
let response = await client.
api('/me/calendar/events?$top=25000')
.header('Prefer', `outlook.timezone="${timeZone}"`)
.header("Prefer", "IdType='ImmutableId'")
.get();
MS Graph official documentation: How to retrieve a list of outlookTasks
MS Graph official documentation: outlookTask resource type
MS Graph official documentation: event resource type
MS Graph official documentation: Get immutable identifiers for Outlook resources
Okay, so I've found the solution and it's just ridiculous. If any MS Graph SDK developers see this please fix it.
Instead of this:
let response = await client
.api('/me/outlook/tasks?$top=25000')
.header("Prefer", "IdType=\"ImmutableId\"")
.header('Prefer', `outlook.timezone="${timeZone}"`)
.version('beta')
.get();
You MUST do this:
let response = await client
.api('/me/outlook/tasks?$top=25000')
.header("Prefer", `IdType="ImmutableId", outlook.timezone="${timeZone}"`)
.version('beta')
.get();
I guess setting the second Prefer header overrides the first one and consequentially only the second one is sent. Unfortunately, I've discovered this right after I implemented the solution via OpenTypeExtension.
I have upgraded the Stripe.net to the latest version which is 20.3.0 and now I don't seem to find the .Last4 for the credit card. I had the following method:
public void CreateLocalCustomer(Stripe.Customer stipeCustomer)
{
var newCustomer = new Data.Models.Customer
{
Email = stipeCustomer.Email,
StripeCustomerId = stipeCustomer.Id,
CardLast4 = stipeCustomer.Sources.Data[0].Card.Last4
};
_dbService.Add(newCustomer);
_dbService.Save();
}
But now the stipeCustomer.Sources.Data[0].Card.Last4 says 'IPaymentSource' does not contain a definition for 'Card'. Does anyone know how I can get the card details now? The flow is that I create the customer by passing the Stripe token to Stripe, then I get the above stripeCustomer. So I expect it to be somewhere in that object. But I can't find it. The release notes can be found here.
Thank you.
In the old world of Stripe, there only used to be one type of payment method you could attach to a Customer; specifically, Card-objects. You would create a Card-object by using Stripe.js/v2 or the Create Token API Endpoint to first create a Token-object and then attach that token to a Customer-object with the Create Card API Endpoint.
Once Stripe expanded to support a number of other payment methods though, Stripe built support for a new object type that encapsulated a number of payment methods (including credit cards) called Source-objects. A Source-object is created either by using Stripe.js/v3 or the Create Source API Endpoint. It can also be attached to a Customer-object in much the same way as the Card-objects mentioned above, except they retain their object type. They're still a Source. You use the Attach Source API Endpoint to do this (that is notably identical to the Create Card API Endpoint mentioned above).
What I'm getting at here, is there are now two different object types (or more) that you can expect to see returned in the sources-array (or Sources in .NET). All of these methods though inherit from the IPaymentSource-interface. So if you know you have a Card-object getting returned, you can simply cast the returned object to the Card-class.
Something like this should get you going:
CardLast4 = ((Card) stipeCustomer.Sources.Data[0]).Last4
You can see what I mean by inheritance by looking at this line in the Card-class file:
https://github.com/stripe/stripe-dotnet/blob/master/src/Stripe.net/Entities/Cards/Card.cs#L7
Good luck!
As of Stripe.net.21.4.1, this is what works:
var chargeService = new ChargeService();
var charge = chargeService.Get(id);
CardLast4 = ((Card)charge.Source).Last4;
It's getting hard not to panic when code breaks because of all the micro-changes Stripe makes.
So after debugging, it looks like the Data[0] needs to be cast as Card to get the card.
So it will be CardLast4 = ((Card)stipeCustomer.Sources.Data[0]).Last4.
After I created an address, a webhook (on that address [address-transactions]), and sent BTC to that address, I am getting a callback.
How can I get the address, which was the purpose of payment (receive address)?
How can I be sure?
Callback below:
{"network":"tBTC","event_type":"address-transactions","data":{"raw":"010000000106b42c1327a982269aba7fe648efd85af636f95929bf9c7753db1874989ddfca00000000fdfd0000483045022100b244d43adb41687aa1382a8839e5ed71ead23b85e0080f19eb00842bfddf183b022052c48e9345a060224b6b73066556b1e7af8e6304e9aab4b580477ec6b5ea50d501473044022065b019ba879a361082990e466c74adce23dbe04f73bf5f8b24e68740a39779c6022023d3e0170a420032d25e84c02d4c37f14f83f644ef46f3d3fc71aa86cc937da8014c69522102e395f291278488ba971b94ce7ddef42020c351e7e6066ae0d031215fdaa20a6521035966e7947541ccd494bef89f2035bdddb9ecd74c7865fa5180acbeefedc151e62103820f089836a6a19d1a1c3a9e4a1d6532d2721ffad373fcf8093926c01097945253aeffffffff02801a06000000000017a91402994d31fb6c69f0a0399b879a7713130c75b894877ee43d000000000017a914415e211a35874aad3561c72f79d36655bf1829fa8700000000","hash":"f7e57a938f1e1cb0edf3f32d3af1aeb5d97b6fed2cbcd13f72f31e3c49f9c299","first_seen_at":"2016-06-13T19:15:45+0000","last_seen_at":"2016-06-13T19:15:45+0000","block_height":870128,"block_time":"2016-06-13T20:41:54+0000","block_hash":"00000000002fc98e5a4b655daef4d609ecc64f3f4bd74220cc516e83e2359d30","confirmations":1,"is_coinbase":false,"estimated_value":400000,"total_input_value":4460000,"total_output_value":4456190,"total_fee":3810,"estimated_change":4056190,"estimated_change_address":"2MyCrfyKKb7LMsx5F4mmDVbwQSfEMspaopx","high_priority":false,"enough_fee":false,"contains_dust":false,"inputs":[{"index":0,"output_hash":"cadf9d987418db53779cbf2959f936f65ad8ef48e67fba9a2682a927132cb406","output_index":0,"value":4460000,"address":"2N4ufH2284xz1BEFnpi4rU2KZk9YUmtzTtT","type":"scripthash","multisig":null,"multisig_addresses":null,"script_signature":"00483045022100b244d43adb41687aa1382a8839e5ed71ead23b85e0080f19eb00842bfddf183b022052c48e9345a060224b6b73066556b1e7af8e6304e9aab4b580477ec6b5ea50d501473044022065b019ba879a361082990e466c74adce23dbe04f73bf5f8b24e68740a39779c6022023d3e0170a420032d25e84c02d4c37f14f83f644ef46f3d3fc71aa86cc937da8014c69522102e395f291278488ba971b94ce7ddef42020c351e7e6066ae0d031215fdaa20a6521035966e7947541ccd494bef89f2035bdddb9ecd74c7865fa5180acbeefedc151e62103820f089836a6a19d1a1c3a9e4a1d6532d2721ffad373fcf8093926c01097945253ae"}],"outputs":[{"index":0,"value":400000,"address":"2MsUxzFCWuiJJSouCHko2BkV9u3Md5q9D8T","type":"scripthash","multisig":null,"multisig_addresses":null,"script":"OP_HASH160
02994d31fb6c69f0a0399b879a7713130c75b894
OP_EQUAL","script_hex":"a91402994d31fb6c69f0a0399b879a7713130c75b89487","spent_hash":null,"spent_index":0},{"index":1,"value":4056190,"address":"2MyCrfyKKb7LMsx5F4mmDVbwQSfEMspaopx","type":"scripthash","multisig":null,"multisig_addresses":null,"script":"OP_HASH160
415e211a35874aad3561c72f79d36655bf1829fa
OP_EQUAL","script_hex":"a914415e211a35874aad3561c72f79d36655bf1829fa87","spent_hash":null,"spent_index":0}]},"retry_count":"6","addresses":{"2N4ufH2284xz1BEFnpi4rU2KZk9YUmtzTtT":-4460000}}
Thank you very much for your help.
The addresses portion in the last line (in your example) has the address. It is a key so you can use .keys() and select the first one. Here is an example of how I parsed it using python:
data = json.loads(request.body)
address = data['addresses'].keys()[0]
amount = data['addresses'][address]
confirmations = data['data']['confirmations']