How to call a function of a smart contract with Ethers.rs? - rust

I'm using ethers.rs & want to call a function of a deployed smart contract. I don't to use the ABI of smart contract for this.
Based on my research so far I've found a way of using the function selector. This has to be encoded along with the function arguments in the data field of the transaction.
How can I do so using ethers.rs if I just know the contract address & the function that I want to call?

First you need to parse your contract abi with abigen:
abigen!(ERC20Token, "./erc20.json",);
more information here
next you create your contract object:
let contract = ERC20Token::new(address, client);
and finally you call it:
contract.total_supply().call().await
contract.transfer(to, amount).call().await
you can check the full example here

Related

How to get the hash from a transaction with web3

I am trying to do a Dapp with Nodejs and truffle. I have a solidity contract that works fine and I would like to use the method getTransactionReceipt() from the web3 library to print in console the result, but I dont know how.
The thing is that I have different functions in the nodejs app that call the functions in the solidity contract, and just after I call those contract function and the transaction is finished, I want to print that transaction info, but to use the method getTransactionReceipt() I need the transaction hash, ¿how can I get it?
as per web3.js documentation
web3.eth.getTransaction(transactionHash [, callback])
above line returns a transaction matching the given transaction hash.
also
web3.eth.getTransactionReceipt(hash [, callback])
above line returns the receipt of a transaction by transaction hash.
Note: The receipt is not available for pending transactions and returns null.

How can I call one chaincode function inside another chaincode? [nodejs specific]

I'm using NodeJs to write the Hyperledger Fabric chaincode v2.x and using const { Contract } = require('fabric-contract-api')
I have 2 sets of chaincode, one to maintain the user and its wallet amount, and 2nd contract has the information about the asset e.g. quantity, price, name, etc.
I wanted to transfer the asset some quantity from user1 to user2 and wanted to deduct money from user1's account and transfer it to user2's account.
How can I call the function of transfer from the user contract inside the asset contract?
Yes, you can call one chain code function in another chain code .
You can find a few more information in the below link:
https://hyperledger.github.io/fabric-chaincode-node/release-2.2/api/fabric-shim.ChaincodeStub.html#invokeChaincode__anchor
As there is nothing like a piece of code to explain how the SDK works, I would like to offer the following which may help. The exchangeAsset is a method signature on the current contract. It receives as parameters, the AssetId and the buyerId.
async exchangeAsset(ctx, assetId, buyerId) {
Further down in this contract method, there is a need to make a cross contract call to the client contract, which contains information on buyers and sellers. First create an array containing the name of the function to call and the number of parameters required e.g.
let values = new Array("readKeyValue", buyerId);
Then make the call using the following
let buyer = await this.crossChannelRead(
ctx,
"client",
[...values],
"channelname"
);
The "client" string is the name of the other contract to call.
The values array is spread and will read as readKeyValue, buyerId, which means use the readKeyValue function and use buyerId as the parameter.
The "channelname" as shown above will actually be the name of the channel where the contract can be found.

Security in in-game NFT mint

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.

Stripe: Getting Credit Card's Last 4 Digits

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.

Where to put outside-aggregate validation?

I've got a question regarding outside-aggregate validation.
In our domain partner can place orders that contain certain products (1).
Once order is placed (2) he can mark it as paid (3) in our system.
Once order is marked as paid (4) we assign licences to products in external library service (5).
Once we know licences are assigned (6) we close entire saga.
Here's a small drawing illustrating the process:
At this moment besides commands, command handlers and events there are two domain classes that are involved in entire process:
Order aggregate containing business logic
Order saga coordinating entire process and assigning licences
Now, there is one invariant that is not modelled in this process yet - before we mark order as paid we have to check if user does not already have particular licence assigned. We get this from library service as well.
Where would you put this validation? Command handler? Wrap Order in some domain service? Pass some validator to Order constructor?
class Order
{
public function __construct(OrderValidator $validator)
{
if (!$validator->isValid($this)) {
throw new \DomainException();
}
// else proceed
}
}
class OrderValidator
{
private $libraryServiceClient;
public function isValid(Order $order)
{
// check licence using $libraryServiceClient
}
}
As far as I understood the problem is in step 3 (Mark order as payed). In this step we need a user (let's call it payer) that marks the order as payed. So when creating this payer object (using factory maybe) we need to know if he is allowed to mark an order as payed. In order to get this information a call should be made to the external library.
What I suggest is to have an application service that have ->markOrderAsPayed($orderId, $payerUserId)
This method will make a call to 2 domain services. One for getting the payer and one for marking the order as payed.
$payer = $this->payerService->getPayer($payerUserId);
$this->orderService->payOrder($orderId, $payer);
In the getPayer() function you should make a call to the external library to know how many licences the payer have.
I hope this will be helpful, it is just based on what I understood from the questions and comments.

Resources