A function in a contract that is spawning a new contract executes fine from Remix but fails when called from my custom app, without giving any details except "transaction failed". I'm pretty sure the reason for this is that both contracts are written in the same file in Remix so it knows exactly how to define the child contract whereas my app only takes in the abi of the source/parent.
The simplified distributed code is something like this:
pragma solidity ^0.6.0;
contract Parent{
address[] public children;
function createChild (uint256[] memory distro)external payable{
children.push(address(new Child(msg.sender,distro)));
}
}
contract Child{
address payable owner;
uint256[] distribution;
constructor(address payable admin,uint256[] memory distro)public payable{
owner=admin;
distribution=distro;
}
}
in my Flutter app, I'm defining the Parent contract using a list of strings like so:
List<String> source = [
"function createChild(int256[]) payable",
]
And then proceed to get the user's wallet credentials and push the transaction like so:
String address = "0xbAF01C91b2d53cC9eeb0ED1A300783Cb74563010"; //address of deployed Parent
var contract = Contract(address, source, web3user);
contract.connect(web3user.getSigner()); // uses the connected wallet as signer
var ponse = await promiseToFuture(callMethod(contract, "createChild", [
[
[30, 70], //the array of int256 it takes as parameters
TxParams(
value: "1000000000000",
gasLimit: "1000000",
)
]));
How do I let my app know about the Child contract? I'm thinking it should be somehow included in the source list of functions, so that the EVM knows what to compile and deploy, but it's unclear how to specify that.
Whenever you want to interact with a contract on-chain, you need 4 things:
The ABI
The Address
The Blockchain
A wallet with funds to pay for the gas
And when you create your contract, yes, your application needs to know what the ABI of the child contract is. So when you create your child contract, you'll need to pass in the ABI.
Related
I used web3dart with flutter with Ganache and Truffle to run my Solidity contract, the contract is being read fine by my Flutter app but when I run functions that write to the contract it doesn't work (can't write to the contract from the app). I saw on the web3dart package it says you should use .sendTransaction() instead of .call() when running a function that writes to the contract
for the credential, I used WalletConnect I used the WalletConnectEthereumCredentials class that was written in the package example source code here
The transaction is successful from MetaMask wallet Address to the contract address(traceable with EtherScan), but still, contract data remains unchanged.
Solidity Code:
function update(string memory newMessage) public {
message = newMessage;
}
Flutter Code:
final cred = WalletConnectEthereumCredentials(provider: provider);
try {
var transactionId = await _web3client.sendTransaction(
cred,
Transaction.callContract(
contract: _deployedContract,
function: _updateFunction,
parameters: ["NEW_MESSAGE"],
from: EthereumAddress.fromHex(
cred.provider.connector.session.accounts[0]),
),
chainId: 4);
You can see what's on WalletConnectEthereumCredentials and WalletConnectEthereumCredentials on the walletConnect repository
Solved!
Just deploy the contract instead of running it locally on your machine.
I was basically trying to make a transaction to a contract that is running locally on Ganache. So I deployed the contract on truffle, this solved the issue and I can fully interact with the contract using my app.
I managed to publish a package to the PTE via resim publish.
Now I am stuck as I have the following problem:
How to send a signed manifest to the PTE (from my account as I need a badge that will be returned)?
In order to create a Manifest, and sign it, you must back an element which upon activation constructs a Manifest, sends it to the PTE Extension to be signed, and receives the results.
Here is some sample code, this is the Typescript part:
document.getElementById('instantiateMainComponent')!.onclick = async function () {
// Construct manifest
const manifest = new ManifestBuilder()
// Instantiates component
.callFunction(Package_Address, 'ComponentName', 'instantiate', [])
// Deposits returned resources to account
.callMethodWithAllResources(Account_Address, 'deposit_batch')
.build()
.toString();
// Send manifest to extension for signing
const receipt = await signTransaction(manifest);
// Add results here
}
And here is my associated HTML:
<h2>3. Instantiate Main Component</h2>
<p><button id="instantiateMainComponent">Instantiate</button></p>
This was one of the things I needed to do not too long ago. To clarify, for the public test environment (only the PTE, nothing else) not all transactions require signatures. Matter of fact, only transactions which withdraw funds from an account require a signature, nothing else requires one. This means the following:
For all transactions which do not withdraw funds from an account, you can continue using the PTE API to send your transactions and not sign them.
If signing transactions is necessary, then my recommendation is to construct and sign your transactions using Rust since it already has an SBOR implementation and you can very easily sign all of your transactions with Rust + the existing Scrypto libraries.
Regarding the Rust implementation, here is an example code I wrote in Rust which signs transactions and submits them to the PTE (PTE01 but you can change it to PTE02): https://github.com/0xOmarA/PTE-programmatic-interactions/blob/main/src/main.rs
Here is an example of this code being used in action: https://github.com/0xOmarA/RaDEX/tree/main/bootstrap
I'm using openZeppelin to make a crowdsale contract, all (30 of them) my tests pass with flying colours ;) and I can migrate on a locall ganache blockchain no problem.
When I try to deploy to rinkeby I start having issues. My config in truffle.js is
rinkeby: {
provider: rinkeybyProvider,
network_id: 3,
gas: 4712388,
gasPrice: web3.utils.toWei("40", "gwei"),
websockets: true,
from: "0x9793371e69ed67284a1xxxx"
}
When I deploy on rinkeby I get:
"SplitWallet" hit a require or revert statement somewhere in its
constructor. Try: * Verifying that your constructor params satisfy
all require conditions. * Adding reason strings to your require
statements.
I have gone through and put messages in every revert in the constructor hierachy, but I never see any of the messages. I thought it might be that my payees and shares were different lengths but, no, they are the same (only parameters that the constructor for a splitwallet take)
Things to note:
I have an infura api key
I am using truffle-wallet-provider provider, with just a private key (no mnemonic) to deploy
I am confused (due to the above), how my deploy script, can know multiple (10) wallets on deployment. Usually (in ganache) these are the 10 wallets ganache generates for you, but here, I am providing a private key, so it shouldn't be able to know 10 wallets, just one - the public key of the private key that is deploying the contract, no? (talking about here):
module.exports = async (
deployer,
network,
[owner, purchaser, investor, organisation, ...accounts] //how does it know these??
)
This last point, makes me wonder, because I printed out owner/purchaser and they dont match my public key wallet at all, so I have no idea where they are coming from. And if they dont match, and it defaults to the owner being accounts[0], then that wallet may not be able to pay for the gas.... perhaps??
Thanks
Rinkeby network id is 4, not 3.
The question assumes the use of Event Sourcing.
When rebuilding current state by replaying events, event handlers should be idempotent. For example, when a user successfully updates their username, a UsernameUpdated event might be emitted, the event containing a newUsername string property. When rebuilding current state, the appropriate event handler receives the UsernameUpdated event and sets the username property on the User object to the newUsername property of the UsernameUpdated event object. In other words, the handling of the same message multiple times always yields the same result.
However, how does such an event handler work when integrating with external services? For example, if the user wants to reset their password, the User object might emit a PasswordResetRequested event, which is handled by a portion of code that issues a 3rd party with a command to send an SMS. Now when the application is rebuilt, we do NOT want to re-send this SMS. How is this situation best avoided?
There are two messages involved in the interaction: commands and events.
I do not regard the system messages in a messaging infrastructure the same as domain events. Command message handling should be idempotent. Event handlers typically would not need to be.
In your scenario I could tell the aggregate root 100 times to update the user name:
public UserNameChanged ChangeUserName(string username, IServiceBus serviceBus)
{
if (_username.Equals(username))
{
return null;
}
serviceBus.Send(new SendEMailCommand(*data*));
return On(new UserNameChanged{ Username = userName});
}
public UserNameChanged On(UserNameChanged #event)
{
_username = #event.UserName;
return #event;
}
The above code would result in a single event so reconstituting it would not produce any duplicate processing. Even if we had 100 UserNameChanged events the result would still be the same as the On method does not perform any processing. I guess the point to remember is that the command side does all the real work and the event side is used only to change the state of the object.
The above isn't necessarily how I would implement the messaging but it does demonstrate the concept.
I think you are mixing two separate concepts here. The first is reconstructing an object where the handlers are all internal methods of the entity itself. Sample code from Axon framework
public class MyAggregateRoot extends AbstractAnnotatedAggregateRoot {
#AggregateIdentifier
private String aggregateIdentifier;
private String someProperty;
public MyAggregateRoot(String id) {
apply(new MyAggregateCreatedEvent(id));
}
// constructor needed for reconstruction
protected MyAggregateRoot() {
}
#EventSourcingHandler
private void handleMyAggregateCreatedEvent(MyAggregateCreatedEvent event) {
// make sure identifier is always initialized properly
this.aggregateIdentifier = event.getMyAggregateIdentifier();
// do something with someProperty
}
}
Surely you wouldn't put code that talks to an external API inside an aggregate's method.
The second is replaying events on a bounded context which could cause the problem you are talking about and depending on your case you may need to divide your event handlers into clusters.
See Axon frameworks documentation for this point to get a better understanding of the problem and the solution they went with.
Replaying Events on a Cluster
TLDR; store the SMS identifier within the event itself.
A core principle of event sourcing is "idempotency". Events are idempotent, meaning that processing them multiple times will have the same result as if they were processed once. Commands are "non-idempotent", meaning that the re-execution of a command may have a different result for each execution.
The fact that aggregates are identified by UUID (with a very low percentage of duplication) means that the client can generate the UUIDs of newly created aggregates. Process managers (a.k.a., "Sagas") coordinate actions across multiple aggregates by listening to events in order to issue commands, so in this sense, the process manager is also a "client". Cecause the process manager issues commands, it cannot be considered "idempotent".
One solution I came up with is to include the UUID of the soon-to-be-created SMS in the PasswordResetRequested event. This allows the process manager to only create the SMS if it does not yet already exist, hence achieving idempotency.
Sample code below (C++ pseudo-code):
// The event indicating a password reset was successfully requested.
class PasswordResetRequested : public Event {
public:
PasswordResetRequested(const Uuid& userUuid, const Uuid& smsUuid, const std::string& passwordResetCode);
const Uuid userUuid;
const Uuid smsUuid;
const std::string passwordResetCode;
};
// The user aggregate root.
class User {
public:
PasswordResetRequested requestPasswordReset() {
// Realistically, the password reset functionality would have it's own class
// with functionality like checking request timestamps, generationg of the random
// code, etc.
Uuid smsUuid = Uuid::random();
passwordResetCode_ = generateRandomString();
return PasswordResetRequested(userUuid_, smsUuid, passwordResetCode_);
}
private:
Uuid userUuid_;
string passwordResetCode_;
};
// The process manager (aka, "saga") for handling password resets.
class PasswordResetProcessManager {
public:
void on(const PasswordResetRequested& event) {
if (!smsRepository_.hasSms(event.smsUuid)) {
smsRepository_.queueSms(event.smsUuid, "Your password reset code is: " + event.passwordResetCode);
}
}
};
There are a few things to note about the above solution:
Firstly, while there is a (very) low possibility that the SMS UUIDs can conflict, it can actually happen, which could cause several issues.
Communication with the external service is prevented. For example, if user "bob" requests a password reset that generates an SMS UUID of "1234", then (perhaps 2 years later) user "frank" requests a password reset that generates the same SMS UUID of "1234", the process manager will not queue the SMS because it thinks it already exists, so frank will never see it.
Incorrect reporting in the read model. Because there is a duplicate UUID, the read side may display the SMS sent to "bob" when "frank" is viewing the list of SMSes the system sent him. If the duplicate UUIDs were generated in quick succession, it is possible that "frank" would be able to reset "bob"s password.
Secondly, moving the SMS UUID generation into the event means you must make the User aggregate aware of the PasswordResetProcessManager's functionality (but not the PasswordResetManager itself), which increases coupling. However, the coupling here is loose, in that the User is unaware of how to queue an SMS, only that an SMS should be queued. If the User class were to send the SMS itself, you could run into the situation in which the SmsQueued event is stored while the PasswordResetRequested event is not, meaning that the user will receive an SMS but the generated password reset code was not saved on the user, and so entering the code will not reset the password.
Thirdly, if a PasswordResetRequested event is generated but the system crashes before the PasswordResetProcessManager can create the SMS, then the SMS will eventually be sent, but only when the PasswordResetRequested event is re-played (which might be a long time in the future). E.g., the "eventual" part of eventual consistency could be a long time away.
The above approach works (and I can see that it should also work in more complicated scenarious, like the OrderProcessManager described here: https://msdn.microsoft.com/en-us/library/jj591569.aspx). However, I am very keen to hear what other people think about this approach.
I need to develop a pretty complicated Flash site based on the Facebook API, and if there's a way I can develop locally rather than having to upload it all the time I would be forever grateful.
I saw a post mentioning setting something to localhost but they never specified what exactly ( is it possible to use facebook API locally? )
Much appreciated.
Encapsulation is your friend in this case. When I use external / 3rd party APIs, I like to make a wrapper class of my own for the data. Let's say you only care about 'fbID' and 'userName'. Make a class of your own to hold this data once it is retrieved (private vars with getters, and 1 or more setters). Some skeleton code:
class MyUserClass{
//declare vars here (_fbID, _userName)
public function setData(userID:String, userName:String):void{
//set the values here.
}
//getters here (get fbID, get userName)
}
You can use 2 setter functions if you want to, but the point is that you will be able to call them with any data you want. When your entire application fetches this info from your class, and not the api directly you can work offline. When in offline mode, you can plug in some compatible 'fake' data to see it work.
Now you need to take this to the next level by making a wrapper type for every call you make to facebook. What I mean by this is that since you know what to expect from fb, you can pretend you actually got it, and proceed from there. Asking for a list of friend IDs? make a fake list that is reasonable, and have your application use it. Better still, generate as many fake offline users as you want, and make your server calls delay a random 'lag' time before returning the fake data to the event listener. This will also help test against possible race conditions.
One way to do this is by creating and extending a class to execute the api calls. Enjoy.
import flash.events.EventDispatcher;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
class MyApiCaller extends EventDispatcher{
//set up vars to hold call result data
protected var _someData:String;
//make sure to declare some event types for the callbacks
public static const SERVERCALL1_COMPLETE:String = "servercall1_complete";
function MyApiCaller(){
//init things....
}
public function doServerCall1(...args:*):void {
//create the ulrLoader etc...
//set up event listener to onServerCall1Complete
}
public function onServerCall1Complete(event:Event):void {
//parse results, save to vars
//fire event to notify the caller
dispatchEvent(new Event(SERVERCALL1_COMPLETE));
}
//getter to be used when the waiting object gets the SERVERCALL1_COMPLETE event
public function get someData():String {return _someData;}
}
class MyFakeApiCaller extends MyApiCaller{
//set up any additional types (random user data etc..) that would not be found in the base class
//no need to redeclare the event types
function MyFakeApiCaller(){
//init things....
}
override public function doServerCall1(...args:*):void {
//wait a random amount of time via Timer, set up event listener to onServerCall1Complete
}
override public function onServerCall1Complete(event:Event):void {
//event is a TimerEvent in this case
//generate data / choose random data
//save to vars: _someData = ...
//fire event to notify the caller
dispatchEvent(new Event(MyApiCaller.SERVERCALL1_COMPLETE));
}
//getter from base class will be used as usual
}
https://github.com/facebook/php-sdk plus http://www.apachefriends.org/en/xampp.html I believe is your best bet.