How to update deployed Ethereum smart contract with ABI only through console (Truffle) - solidity

I need to update value on deployed contract ( I dont have sol neither it has been deployed on my platform )
I want to update param with setter in contract and call getter to see changed value .. always default value comes back!
here is the code Im using :
new web3.eth.Contract(HelloWorld.abi,'0x085Ab4C596535FFCE5B520D277f1C01236a656CB').methods.setMessage('Hi').call()
=> Result {}
then call :
new web3.eth.Contract(HelloWorld.abi,'0x085Ab4C596535FFCE5B520D277f1C01236a656CB').methods.getMessage().call()
=>
'hello world10' 🤔
Im using Truffle console:
truffle console --network ropsten
one comment if I use :
HelloWorld.deployed().then(instance => instance.setMessage('new Hi').call())
then call:
HelloWorld.deployed().then(instance => instance.getMessage.call()).then(result => message = result)
then I got expected value .. but I don't have deployed contract. neither sol. all what I have part ABI
Is it wrong with my calls that should be async .. or I need to redeploy contract ?
Im still new in this crypto-world 🙂

welcome to the "crypto-world" as you named it.
I've got a bit lost on your question but what you want is to deploy a contract with an initial message and then change that message using setMessage method, all through the console.
First thing you are doing wrong is calling the "setMessage" method using .call(). When you want to change something in the blockchain, you will send a transaction, and to send a transaction you need to specify an account. The correct method should be .send({ from: "you-account-address" }).
In order to simplify a bit, let me just show a few lines that you can use and then explain
$ > truffle console --network ropsten
$ (truffle) > helloInstance = await HelloWorld.deployed()
$ (truffle) > await helloInstance.getMessage()
$ (truffle) > await helloInstance.setMessage("new Hi", { from: "you-account-address" })
So, basically, all calls are async. First, you call HelloWorld.deployed() because when you deployed the contracts with truffle, truffle created a folder named "build" where it saved the contracts with all the necessary data, that's why you don't need to specify the address neither the abi. This is totally different from using web3.js in which you need to specify both.
Then, you can just call the methods.
You can find more detailed information here https://www.trufflesuite.com/docs/truffle/getting-started/interacting-with-your-contracts

Related

what is the difference between these two ethers.js functions [duplicate]

Can somebody please point me to the documentation (official or otherwise ) that explains the function ethers.getContractAt():
the original context of this is as follows:
vrfCoordinator = await ethers.getContractAt('VRFCoordinatorMock', VRFCoordinatorMock.address, signer)
and the full code can be found here...
https://github.com/PatrickAlphaC/all-on-chain-generated-nft/blob/main/deploy/02_Deploy_RandomSVG.js
In the absence of such documentation, an explanation would be much appreciated. Thank you!
The getContractAt() function is part of the hardhat-ethers plugin for Hardhat, expanding the ethers object.
It's not a part of the core Ethers package, so it's not included in their documentation.
Hardhat docs mentioning the plugin: https://hardhat.org/plugins/nomiclabs-hardhat-ethers.html#helpers
Basically, it is doing the same thing, that attach do but in one line. i.e you can actually interact with an already deployed contract.
For reference below is the code if you are using attach
let xyzContract = await hre.ethers.getContractFactory("Name of the contract");
let xyzContractInstance = xyzContract.attach('Address of the contract');
You can accomplish the same thing in one line via getContractAt() when using hardhat
let xyzContractInstance = await hre.ethers.getContractAt(
"Contract Address",
deployed contract address
);

Raku Cro service subscribing to data "in the background" general guidance

I am attempting to put together a Cro service that has a react/whenever block consuming data "in the background" So unlike many examples of websocket usage with Cro, this has nothing to do with routes that may be accessed via the browser.
My use case is to consume message received via an MQTT topic and do some processing with them. At a later stage in development I might create a supply out of this data, but for now, when data is received it will be stored in a variable and dependant on certain conditions, be sent to another service via a http post.
My thought was to include a provider() in the Cro::HTTP::Server setup like so:
use Cro::HTTP::Log::File;
use Cro::HTTP::Server;
use Routes;
use DataProvider; # Here
my Cro::Service $http = Cro::HTTP::Server.new(
http => <1.1>,
host => ...,
port => ...,
application => [routes(), provider()], # Made this into an array of subs?
after => [
Cro::HTTP::Log::File.new(logs => $*OUT, errors => $*ERR)
]
);
And in the DataProvider.pm6:
use MQTT::Client;
sub provider() is export {
my $mqtt = MQTT::Client.new: server => 'localhost';
react {
whenever $mqtt.subscribe('some/mqtt/topic') {
say "+ topic: { .<topic> } => { .<message>.decode("utf8-c8") }";
}
}
}
This throws a bunch of errors:
A react block:
in sub provider at DataProvider.pm6 (DataProvider) line 5
in block <unit> at service.p6 line 26
Died because of the exception:
Invocant of method 'write' must be an object instance of type
'IO::Socket::Async', not a type object of type 'IO::Socket::Async'. Did
you forget a '.new'?
in method subscribe at /home/cam/raku/share/perl6/site/sources/42C762836A951A1C11586214B78AD34262EC465F (MQTT::Client) line 133
in sub provider at DataProvider.pm6 (DataProvider) line 6
in block <unit> at service.p6 line 26
To be perfectly honest, I am totally guessing that this is how I would approach the need to subscribe to data in the background of a Cro service, but I was not able to find any information on what might be considered the recommended approach.
Initially I had my react/whenever block in the main service.pm6 file, but that did not seem right. And needed to be wrapped in a start{} block because as I have just learned, react is blocking :) and cro was not able to actually start.
But following the pattern of how Routes are implemented seemed logical, but I am missing something. The error speaks about setting up a new method, but I'm not convinced that is the root cause. Routes.pm6 does not have a constructor.
Can anyone point me in the right direction please?
Thanks to all who have provided information, this has been a very valuable learning exercise.
The approach of passing additional sub routines, along side router() in the application parameter to Cro::HTTP::Server.new gave further trouble. (an array is not allowed, and broke routing)
Instead, I have moved the background work into a class of it's own, and given it a start and stop method more akin to Cro::HTTP::Server.
My new approach:
service.pm6
use Cro::HTTP::Log::File;
use Cro::HTTP::Server;
use Routes;
use KlineDataSubscriber; # Moved mqtt functionality here
use Database;
my $dsn = "host=localhost port=5432 dbname=act user=.. password=..";
my $dbh = Database.new :$dsn;
my $mqtt-host = 'localhost';
my $subscriber = KlineDataSubscriber.new :$mqtt-host;
$subscriber.start; # Inspired by $http.start below
my Cro::Service $http = Cro::HTTP::Server.new(
http => <1.1>,
host => ...,
port => ...,
application => routes($dbh), # Basically back the way it was originally
after => [
Cro::HTTP::Log::File.new(logs => $*OUT, errors => $*ERR)
]
);
$http.start;
say "Listening at...";
react {
whenever signal(SIGINT) {
say "Shutting down...";
$subscriber.stop;
$http.stop;
done;
}
}
And in KlineDataSubscriber.pm6
use MQTT::Client;
class KlineDataSubscriber {
has Str $.mqtt-host is required;
has MQTT::Client $.mqtt = Nil;
submethod TWEAK() {
$!mqtt = MQTT::Client.new: server => $!mqtt-host;
await $!mqtt.connect;
}
method start(Str $topic = 'act/feed/exchange/binance/kline-closed/+/json') {
start {
react {
whenever $!mqtt.subscribe($topic) {
say "+ topic: { .<topic> } => { .<message>.decode("utf8-c8") }";
}
}
}
}
method stop() {
# TODO Figure how to unsubscribe and cleanup nicely
}
}
This feels much more "Cro idiomatic" to me, but I would be happy to be corrected.
More importantly, it works as expected and I feel is somewhat future proof. I should be able to create a supply to make real-time data available to the router, and push data to any connected web clients.
I also intend to have a http GET endpoint /status with various checks to ensure everything healthy
The root cause
The error speaks about setting up a new method, but I'm not convinced that is the root cause.
It's not about setting up a new method. It's about a value that should be defined instead being undefined. That typically means a failure to attempt to initialize it, which typically means a failure to call .new.
Can anyone point me in the right direction please?
Hopefully this question helps.
Finding information on a recommended approach
I am totally guessing that this is how I would approach the need to subscribe to data in the background of a Cro service, but I was not able to find any information on what might be considered the recommended approach.
It might be helpful for you to list which of the get-up-to-speed steps you've followed from Getting started with Cro, including the basics but also the "Learn about" steps at the end.
The error message
A react block:
in sub provider ...
Died because of the exception:
...
in method subscribe ...
The error message begins with the built in react construct reporting that it caught an exception (and handled it by throwing its own exception in response). A "backtrace" corresponding to where the react appeared in your code is provided indented from the initial "A react block:".
The error message continues with the react construct summarizing its own exception (Died because ...) and explains itself by reporting the original exception, further indented, in subsequent lines. This includes another backtrace, this time one corresponding to the original exception, which will likely have occurred on a different thread with a different callstack.
(All of Raku's structured multithreading constructs[1] use this two part error reporting approach for exceptions they catch and handle by throwing another exception.)
The first backtrace indicates the react line:
in sub provider at DataProvider.pm6 (DataProvider) line 5
use MQTT::Client;
sub provider() is export {
my $mqtt = MQTT::Client.new: server => 'localhost';
react {
The second backtrace is about the original exception:
Invocant of method 'write' must be an object instance of type
'IO::Socket::Async', not a type object of type 'IO::Socket::Async'. ...
in method subscribe at ... (MQTT::Client) line 133
This reports that the write method called on line 133 of MQTT::Client requires its invocant is an instance of type 'IO::Socket::Async'. The value it got was of that type but was not an instance, but instead a "type object". (All values of non-native types are either type objects or instances of their type.).
The error message concludes with:
Did you forget a '.new'?
This is a succinct hint based on the reality that 99 times out of a hundred the reason a type object is encountered when an instance is required is that code has failed to initialize a variable. (One of the things type objects are used for is to serve the role of "undefined" in languages like Perl.)
So, can you see why something that should have been an initialized instance of 'IO::Socket::Async' is instead an uninitialized one?
Footnotes
[1] Raku's constructs for parallelism, concurrency, and asynchrony follow the structured programming paradigm. See Parallelism, Concurrency, and Asynchrony in Raku for Jonathan Worthington's video presentation of this overall approach. Structured constructs like react can cleanly observe, contain, and manage events that occur anywhere within their execution scope, including errors such as error exceptions, even if they happen on other threads.
You seem to be fine now but when I first saw this I made this https://github.com/jonathanstowe/Cro-MQTT which turns the MQTT client into a first class Cro service.
I haven't released it yet but it may be instructive.

How to share a variable between two routers module in cro?

I try to use Cro to create a Rest API that will publish messages in rabbitMQ. I would like to split my routes in different modules and compose them with an "include". But I would like to be able to share the same connection to rabbitMQ in each of those modules too. I try with "our" but it does not work :
File 1:
unit module XXX::YYY;
use Cro::HTTP::Router;
use Cro::HTTP::Server;
use Cro::HTTP::Log::File;
use XXX::YYY::Route1;
use Net::AMQP;
our $rabbitConnection is export = Net::AMQP.new;
await $rabbitConnection.connect;
my $application = route {
include <api v1 run> => run-routes;
}
...
File 2:
unit module XXX::YYY::Route1;
use UUID;
use Cro::HTTP::Router;
use JSON::Fast;
use Net::AMQP;
my $channel = $XXX::YYY::rabbitConnection.open-channel().result;
$channel.declare-queue("test_task", durable=> True );
sub run-routes() is export { ... }
Error message:
===SORRY!===
No such method 'open-channel' for invocant of type 'Any'
Thanks!
When you define your exportable route function you can specify arguments then in your composing module you can create the shared objects and pass them to the routes. For example in your router module :
sub run-routes ($rmq) is export{
route {
... $rmq is available in here
}
}
Then in your main router you can create your Queue and pass it in when including
my $rmq = # Insert queue creation code here
include product => run-routes( $rmq );
I've not tried this but I can't see any reason why it shouldn't work.
The answer by #Scimon is certainly correct, but it does not addresses the OP. On the other hand, the two comments by #ugexe and #raiph are spot-on, so I'll try to summarize them here and explain what's going on.
The error itself
This is the error:
Error message:
===SORRY!=== No such method 'open-channel' for invocant of type 'Any'
It indicates the invocant ($XXX::YYY::rabbitConnection) is of type Any, which is the type usually assigned to variables when they don't have a defined value; that is, basically, $XXX::YYY::rabbitConnection is not defined. It certainly is not since XXX::YYY is not included among the imported modules, as indicated by #ugexe.
The additioal problem indicated by the OP
That module was eliminated from the imported list because, as indicated by the OP
I certainly code it the wrong way because if i try to add use
XXX::YYY;, i get a Circular module loading detected error
But of course. since use XXX::YYY::Route1; which is file 2, is included in File 1.
The final solution is to reorganize files
That circular dependence probably points out to the fact that they should be in the same file, or else common code should be factored out to a third file, which would be eventually be included by both. So you should have something like
unit module XXX::YYY::Common;
use Net::AMQP;
our $rabbitConnection is export = Net::AMQP.new;
await $rabbitConnection.connect;
And then
use XXX::YYY::Common;
in both modules.

How to log correctly with Mocha/Velocity (Meteor testing)?

What's the correct way to go about logging out information about tests using the velocity framework with Meteor?
I have some mocha tests that I'd like to output some values from, I guess it'd be good if the output could end up in the logs section of the velocity window... but there doesn't seem to be any documentation anywhere?
I haven't seen it documented either.
I don't know how to log messages into the Velocity window, though I don't like the idea of logging into the UI.
What I've done is created a simple Logger object that wraps all of my console.{{method}} calls and prevents logging if process.env.IS_MIRROR. That will only output test framework messages on the terminal. If I need to debug an specific test, I activate logging output for a while on Logger.
This is a terrible hack. It will expose an unprotected method that writes to your DB.
But it works.
I was really annoyed to lack this feature so I digged into the Velocity code to find out that they have a VelocityLogs collection that is globally accessible. But you need to access it from your production, not testing, instance to see it in the web reporter.
So it then took me a good while to get Meteor CORS enabled, but I finally managed - even for Firefox - to create a new route within IronRouter to POST log messages to. (CORS could be nicer with this suggestion - but you really shouldn't expose this anyway.)
You'll need to meteor add http for this.
Place outside of /tests:
if Meteor.isServer
Router.route 'log', ->
if #request.method is 'OPTIONS'
#response.setHeader 'Access-Control-Allow-Origin', '*'
#response.setHeader 'Access-Control-Allow-Methods', 'POST, OPTIONS'
#response.setHeader 'Access-Control-Max-Age', 1000
#response.setHeader 'Access-Control-Allow-Headers', 'origin, x-csrftoken, content-type, accept'
#response.end()
return
if #request.method is 'POST'
logEntry = #request.body
logEntry.level ?= 'unspecified'
logEntry.framework ?= 'log hack'
logEntry.timestamp ?= moment().format("HH:mm:ss.SSS")
_id = VelocityLogs.insert(logEntry)
#response.setHeader 'Access-Control-Allow-Origin', '*'
#response.end(_id)
return
, where: 'server'
Within tests/mocha/lib or similar, as a utility function:
#log = (message, framework, level) ->
HTTP.post "http://localhost:3000/log",
data: { message: message, framework: framework, level: level}
(error) -> console.dir error
For coffee haters: coffeescript.org > TRY NOW > Paste the code to convert > Get your good old JavaScript.

Google Apps Script ScriptDb permissions issue

I am having an issue trying to query the ScriptDb of a resource file in Google Apps Script. I create a script file (file1), add it as a resource to another script file (file2). I call file1 from file2 to return a handle to its ScriptDb. This works fine. I then try to query the ScriptDb but have a permissions error returned.
Both files owned by same user and in same google environment
See code below:
file 1:
function getMyDb() {
return ScriptDb.getMyDb;
}
file 2 (references file1):
function getDataFromFile1() {
var db = file1.getMyDb(); // This works
var result = db.query({..............}); // This results in a permissions error!
}
I am at a loss to understand why I can access file1 and get back a handle on the ScriptDb, but then am not able to query it, due to an permissions issue.
I have tried to force file1 to require re-authorization, but have not yet been successful. I tried adding a new function and running it, so any suggestions there would be gratefully received.
Thanks in advance
Chris
There appears to be an error in file1/line2. It says "return ScriptDb.getMyDb;" but it should say "return ScriptDb.getMyDb();"
If you leave out the ()s then when you call file1 as a library, file1.getMyDb() will return a function which you store in var db. Then the line var result = db.query({..............}) results in an error because there is no method "query" in the function.
Is that what's causing your error?
I have figured out what the problem was, a misunderstanding on my part regarding authorisation. I was thinking of it in terms of file permissions, when in fact that problem was that my code was not authorised to run the DbScript service. As my code calls a different file and receives back a pointer to a ScriptDb database it is not using the ScriptDb service, so then when it calls the db.query() it invokes the ScriptDb service, for which it is not authorised.
To resolve this I just had to create a dummy function and make a ScriptDb.getMyDb() call, which triggered authorisation for the service. The code then worked fine.
Thanks for the input though.
Chris