Can you call a Solidity contract method with only Metamask? - javascript

I’m wanting to use Metamask in my app to let users pay a fixed ETH fee (plus gas) to call a method from my Solidity contract. I looked at the Metamask documentation and the eth_sendTransaction method seems close to what I need; eth_sendTransaction would certainly allow me to request ETH from a user, but the “data” parameter is a bit confusing.
The Metamask docs say:
data is optional, but used for defining smart contract creation and interaction
and
also used for specifying contract methods and their parameters.
So “data” represents my method and its parameters, but how does Metamask (or window.ethereum, rather) know the contract whose methods I’m trying to call?
Don’t you normally have to provide a contract address and ABI/JSON in order to interact with a deployed contract? In short, is it possible to do what I’ve described with just Metamask alone? Or do you have to do other client-side setups in order to call a method with eth_sendTransaction?
Edit: by the way TylerH, the answer involved using web3.js. Maybe don't edit people's posts unless you know what the hell you're talking about. Just a thought...

Yes you will need the contract abi in order to get the information you need to include in the data that you're passing to the contract. There are also a few other things that you will need to accomplish this:
First you will need to make sure you download the ethers.js, and #alch/alchemy-web3 npm libraries into your application. Secondly you will need a provider API key from a platform like Alchemy in order to communicate with the contract abi. Lastly, you will need the contract abi which can be found at the bottom of the contract section of etherscan. There is plenty of information on how to obtain these things online, so I won't go over how to configure them here.
Once you have these, you are ready for the next step.
I suggest creating this in a utilities file somewhere in your applications file system, but the idea is this:
const alchemyKey = process.env.ALCHEMY_KEY;
const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS;
const { createAlchemyWeb3 } = require("#alch/alchemy-web3");
const web3 = createAlchemyWeb3(alchemyKey);
const contractABI = require('../contract-abi.json');
export const contract = new web3.eth.Contract(contractABI, CONTRACT_ADDRESS);
export const yourMethod = () => {
if(window.ethereum.request({method: 'eth_requestAccounts'})){
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const address = await signer.getAddress();
const tx = {
from: address,
to: CONTRACT_ADDRESS,
value: "some wei value", // this is the value in wei to send
data: contract.methods.YOUR_CONTRACT_METHOD_HERE().encodeABI()
}
const txHash = await window.ethereum.request({
method: 'eth_sendTransaction',
params: [tx]
});
// do something with your transaction hash here
console.log({txHash});
}else{
console.log('user must connect wallet');
}
}
So the value that is populated in the data field of our transaction comes from calling the method that we are trying to invoke in our contract. This is encoded, and then we pass this information along with the rest of our transaction data.
This is a very short and brief description as to what this does, and I hope this is what you're looking for. If you need any more help I'm always available to chat on Twitter #_syndk8.

Related

Error with AWS SDK-JS API when Retrieving Seller Partner Product Catalog Inventory

I need to retrieve the product catalog of my seller partner on Amazon. Although the API refers to this as "Inventory," I couldn't find this term in the SDK documentation. I assume that the "Catalog" namespace is the equivalent.
Update:
My custom application requires a list of the following product values:
ASINs
UPCs
SKUs
FNSKUs
I have read the documentation and found an API that returns what I need, which can be found here:
https://developer-docs.amazon.com/sp-api/docs/fba-inventory-api-v1-use-case-guide
According to the documentation, I need to create a signature in order to use the API. However, it is noted that if I use the AWS SDK, I do not need to calculate the signature myself. Therefore, I understand that the best practice is to use the AWS SDK.
I have the necessary IAM role permissions and the SP-API app has been published. I am currently attempting to use the AWS SDK.
I have made some changes based on recommendations, but I am not completely sure what else I need to do. Here is my current code:
```
export const /*bundle */ start = async () => {
const client = new MarketplaceCatalogClient({
region: REGION,
credentials: {
accessKeyId: ACCESS_KEY_ID,
secretAccessKey: ACCESS_SECRET_KEY,
},
});
const params = {
/** input parameters */
};
const answer = await client.send(
new ListEntitiesCommand({ Catalog: "AWSMarketplace", EntityType: "ContainerProduct" })
);
console.log(100, answer);
return answer;
};
```
I got the next answer with "AmiProduct" or "ContainerProduct":
{
'$metadata': {
httpStatusCode: 200,
requestId: '91fc5fed-6cdc-42d6-97ec-1ed3cc9d5796',
extendedRequestId: undefined,
cfId: undefined,
attempts: 1,
totalRetryDelay: 0
},
EntitySummaryList: []
}
I'm having difficulty understanding how to correctly implement this. Any guidance would be greatly appreciated.
The docs should be better. I spent a good 15 mins on the docs at https://docs.aws.amazon.com/marketplace-catalog/latest/api-reference/welcome.html and failed to find a full list of valid EntityType values.
Some EntityType values are documented here: https://docs.aws.amazon.com/marketplace-catalog/latest/api-reference/seller-products.html
AmiProduct
ContainerProduct
It looks like these types correspond to the product types in the index of the seller guide here -> https://docs.aws.amazon.com/marketplace/latest/userguide/machine-learning-products.html. It's not clear what the other valid values are.
Some other EntityType values are documented here: https://docs.aws.amazon.com/marketplace-catalog/latest/api-reference/private-marketplace.html
Experience
Procurement Policy
It looks the way to go for now is to scrounge these valid values from examples in the docs https://docs.aws.amazon.com/marketplace-catalog/latest/api-reference/welcome.html. Not the best developer experience :grimace:
Assuming you are a seller, that you have registered successfully with your AWS account. You can then use Marketplace APIs.
To use them, you have to create an IAM role or a user with policies to grant access to invoke the selected APIs like listEntities, describeEntity, etc.
Here I again assume you have the Cognito authorized credentials if using AWS SDK.
Now to view the list of products successfully published, you use listEntites command.
You can only view AMI or Containter product types. Read here.
It uses minimum two required parameters Catalog and EntityType. The former has a fixed value AWSMarketplace, and latter can have a value either AmiProduct or ContainerProduct.
To get a detailed information about a specific product, you use describeEntity command. It takes minimum 2 required parameters Catalog and EntityID.
The former again has a fixed value AWSMarketplace. For latter, you'll obtain it from the listEntites response.

Get the list of all Modules inside the Project on ThirdWeb

I was ultimately trying to get the list of all the modules I created inside my Project over the ThirdWeb.com dashboard and filter out the NFT collections out of it. So I asked on discord and someone told me to use the getAllModulesMetadata() to do so, I did something like this
const sdk = new ThirdwebSDK();
const NftModules = sdk
.getAppModule("<Project Address>")
.getAllModuleMetadata([ModuleType.NFT]);
I also did something like this but getting the same issue.
const sdk = new ThirdwebSDK();
async function getAllModules() {
const NftModules = await sdk
.getAppModule("<Project Address>")
.getAllModuleMetadata([ModuleType.NFT]);
}
getAllModules();
Now it gives this error
Unhandled Runtime Error
Error: call revert exception (method="getAllModulesOfType(uint256)", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.5.0)
Is something wrong? Any help will be appreciated :)
You need to pass in an RPC url or a signer in the ThirdwebSDK() constructor before you can use modules:
An RPC URL (which means the sdk is in read-only mode, you won't be able to change state of things on-chain, only fetch it). You can either use something like alchemy or use a public RPC for that particular chain.
A valid ethers signer (which could be connected from metamask, magiclink, coinbase wallet, etc)
A valid ethers.Wallet object, which can be initialised from a private key
const sdk = new ThirdwebSDK("your_rpc_url_or_signer");
Let me know if you still face any issues!

Add Meta Data To Solana Token with #solana/web3.js

I am trying to create an NFT using web3.js and spl-token.js.
However, i need to add meta data (like the name of the token or other attributes), otherwise it just shows up as "Unknown Token" in my wallet.
This is the relevant part of the code where I am minting the token:
let mint = await splToken.Token.createMint(
connection,
fromWallet,
fromWallet.publicKey,
null,
0,
splToken.TOKEN_PROGRAM_ID
);
Otherwise the code is similar to the answers on this question: I would like to mint a new token on solana. How can I do this using solana-web3.js?
There does not seem to be any documentation whatsoever, except for the structure of the meta data (which I found here: https://docs.phantom.app/integrating/tokens/on-chain-metadata).
If anyone could point me in the right direction with an example or documentation it would be really much appreciated. Thank you!
In order to add metadata to NFT you need to invoke this program spl_token_metadata::instruction::create_metadata_accounts. You can find the documentation here.
PS: The example above is in Rust. To do it in JavaScript is like that:
import { Metaplex, keypairIdentity } from "#metaplex-foundation/js";
const metaplex = new Metaplex(connection);
metaplex.use(keypairIdentity(keypair));
const mintNFTResponse = await metaplex.nfts().create({
uri: "https://ffaaqinzhkt4ukhbohixfliubnvpjgyedi3f2iccrq4efh3s.arweave.net/KUAIIbk6p8oo4XHRcq0U__C2r0mwQaNl0gQow4Qp9yk",
maxSupply: 1,
});
Like described here is another exemple.
Create a metadata for an NFT token in Solana is quite complicated. It is because in Solana SPL-token account would not carry the Metadata. Instead, you have to create another account to carry such data. So, I suggest you to use Metaplex's Candy Machine to make your own NFT with Metadata. You may get more information from their github:
https://github.com/metaplex-foundation/metaplex/

Stuck trying to write web3 RPC BalanceOf to get users metamask smartcontract token balance

I've been trying to use the new JSON RPC methods https://docs.metamask.io/guide/rpc-api.html#ethereum-json-rpc-methods to create a simple web page that can return the token balance of an ERC20 smart contract in metamask account.
I've only been able to successfully retrieve the balance of ethereum (with the following code)
try {
balance = await ethereum
.request({
method: 'eth_getBalance',
params: [address,"latest"],
})
// covert to readable format (account for decimals)
read = parseInt(balance) / 10**18; // will need change based on what token
console.log( "Smart Contract Token Balance:" + read.toFixed(5) );
} catch (error) {
console.log(error);
}
Of course, the above returns the ethereum amount for the address.
For the life of me, I haven't been able to figure version of this using the new JSON-RPC methods and don't see any examples of calling a smart contract method like "balanceOf":
var contract = new web3.eth.Contract(theAbi, theTokenAddress);
balance = await contract.methods.balanceOf(theTokenAddress).call().then(console.log);
I've been stuck on this for weeks on/off as a side project and well, any pointers as I'm sure what I'm trying to do is basic - I just setup an account on StackOverflow for the first time to post. Thank you
Also note, I'm linking this version of web3 https://cdn.jsdelivr.net/npm/web3#latest/dist/web3.min.js
Short answer is to get user account address from client side, and then retrieve balance of the account for whatever token you are interested in from server side.

Requesting 2 secrets from AWS Secrets Manager in One API Call with JavaScript

Background
I am using AWS Secrets Manager to store a few different passwords and secret values in AWS. The first entry is specifically for AWS RDS information.
To enter arbitrary secret data in Secrets Manager you must select a different entry than RDS.
I did this and then created a few key value pairs to be stored. Now that I have done this I have 2 sets of SecretIds. The SecretIds is what is used to return the correct secret from Secrets Manager. I have 2 different SecretIds and need to return 2 different sets of secrets. I am hoping I can do this without having to make 2 separate API calls.
Example
Originally this was the secretId for returning the RDS username and password.
const secretRds = 'some/thing/something';
I was able to return this data like this,
client.getSecretValue({ SecretId: secretRds }, {...}
Question
Now that I have a second secretId I have 2 sets that look like this,
const secretRds = 'some/thing/something';
const secretConfigs = 'some/thing/sopmethingElse';
Since the original secretId was passed into the SecretId key as the value in the getSecretValue params, how do I pass a second secretId in?
Looking at the documentation here, I can not seem to find anything explaining this.
Something like this is what I am trying to accomplish,
Obviously this wont work because the key is named twice.
I need to understand how to pass 2 secretIds in to the same secretId.
const secretRds = 'some/thing/something';
const secretConfigs = 'some/thing/sopmethingElse';
client.getSecretValue({ SecretId: secretRds: SecretId: secretConfigs }, {...}
Unfortunately, the Secrets Manager API does not support passing multiple SecretId's in a single GetSecretValue call.
There does not seem to be any way to retrieve more than 1 secret value in a single API call. You will have to issue 2 different API calls to GetSecretValue.
What are these values you are storing? If they are related, like the DB username, password, and connection string, you can just store them all in the same JSON blob in the secret. You could go back to the console and edit the secret to combine everything.
If they are not all related, you probably want to keep them in separate secrets so that you can manage the permissions to them separately.

Categories