eco-stake / restake Goto Github PK
View Code? Open in Web Editor NEWAuto-compounder script for Cosmos Validators using REStake
Home Page: https://restake.app
License: MIT License
Auto-compounder script for Cosmos Validators using REStake
Home Page: https://restake.app
License: MIT License
Currently restake ignores withdraw addresses
Detect the presence of a withdraw address, and error on enable.
Add a feature to calculate APY and show them in the UI
I'm learning that when you send a TX you can provide it in two structures; Amino (legacy) and Protobuf. Keplr uses Protobuf if the wallet supports it, otherwise falls back to Amino. Typically transactions are sent in Protobuf format, and the blockchain (or Keplr, CosmJS..?) automatically converts them to Amino if it knows how to do so.
Authz transactions aren't supported for this conversion currently and REStake only send the Protobuf version. More importantly though, it doesn't seem like it's possible to send the right message structure based on the discussion in the below issues.
I need to spend a bit of time working out if it's possible to work around this, or if we have to wait for a chain upgrade to an unreleased SDK version.
Related:
in the cosmos-sdk a tx can contain many messages. A message is a claimreward or delegate message. This would allow for operators to have less fees per tx for now.
If a chain is not authz enable, the script try to query the authz module.
this create an error and the script stop
Juno shows APY fetch warning even though disabled
Cosmos node is stalled - need to show latest block time + warning
Kava APY is off, needs disabling for now
Since everyone is known to have a different way of programming, I suggest adding a linter to the Github CI. This way we get consistent code quality.
Looking to disable networks that we don't use + remove other operators from our bot script, and not have to update this every time we pull latest.
Thanks!
Setup a networks.local.json file which is .gitignore'd but can be used to override any needed attributes from networks.json locally.
Would be useful for validators to add their own nodes so they don't rely on public for autocompounding. Also useful for overriding gas prices, adding extra networks. Whatever.
Easy to achieve with a deep merge too. Will sort ASAP
Fee-grant enables one to use fees from other accounts. Here instead of using hot wallet for fees, let delegators pay fees for their transactions. If there are 100k delegators, fees for a validator would be very high. It's a benefit for delegators, and competely optional for them. So they can pay fees
Really awesome tech being built here! ๐
Going thru the readme and i had a question about the following sentence.
REStake specifically lets you grant a validator permission to send WithdrawDelegatorReward and Delegate transactions for their validator only (note WithdrawDelegatorReward is technically not restricted to a single validator)
I'm very curious about the authority that users are handing over to validators by using restake so was wondering if someone add more clarity on the text in parenthesis? What are (if any) the implications of WithdrawDelegatorReward
not being restricted to a single validator?
Generally need some unit tests, and ideally some kind of integration test too.
Also need validate networks.json submission. At least prefix etc. See #185
e.g. rest.stargaze-apis.com blocks the delegations lookup for a validator, which impacts autostake.
Because we load balance the nodes, these errors would come up intermittently.
Need to keep an eye, and potentially blacklist nodes from cosmos.directory as required.
Some people have redelegated to validators through Keplr. In REStake, most of the chains shows this change but for the "Cosmos HUB" doesn't.
I've tried deleting the cache of my browser as sometimes it helps but it keeps showing that the delegation is still in the old validator. It also throws some errors if you try any other action through REStake.
P.D: I have not seen a similar issue related to this, sorry if this is a known issue
Allow user to set the grant expiry and maximum delegation limits. Show this in a modal when granting and use the space to explain grant process further
Show countdown to runtime in delegations and validator listing
Show runtimes on validator profile
Show operator address, contact details, commission, rank on validator profile
Deep link to validator profile
Currently validator image URLs are thrown into local storage keyed by the validator address. We have to query the keybase API to get the URL which is why we cache it like this.
Naturally.. these images will expire and local storage does not. I'm seeing a broken image for Frens and I suspect this is related. Need to store a bit of JSON instead including the image URL and a timestamp so we can expire images older than 24h(?).
Script to add operator, shouldn't be as manual as it is.
Maybe with eco-stake/restake-ui#48, script could probably convert an address into pub key
Might be a dump question. With the same mnemonic, I was able to set up the restake for osmosis chain, but was not able to set up on desmos chain.
By placing the corresponding osmo...
address in the "botAddress" field in networks.json, It seems to give me a correct output:
Osmosis bot address is osmo145a2r0yurzkv43p2arhrwsqcy80pxg7guhadh2
Using REST URL https://lcd-osmosis.blockapsis.com
Using RPC URL https://osmosis.validator.network
You are using public nodes, script may fail with many delegations. Check the README to use your own
Running autostake
Bot balance is 0 uosmo
Bot balance is too low
But then when I did the same for desmos (of course using the corresponding desmos...
address), it fails:
Desmos bot address is desmos145a2r0yurzkv43p2arhrwsqcy80pxg7gq5rdkq
Not an operator
Skipping
Any ideas why that would be the case? Thank you
Keplr only supports a few chains out of the box. I get an error There is no chain info for cheqd-mainnet-1
for Cheqd for example. We need to use the Suggest Chain feature to hook this up. Info can come from Chain Registry, and cosmos.directory APIs.
Adding issue for my tracking but this will hold up #76 and others for now. @Galadrin I think we chatted about this too.
Allow npm run autostake osmosis cerberus
. Currently only accepts a single network.
Also allow excludes?
https://vinorodrigues.github.io/bootstrap-dark-5/
Handle auto-switch based on OS preference, but want a button too
hi, thanks again for this!! what i encountered running the autostake script on cosmoshub:
the script fails because at a point the node is not able to broadcast txs:
Found 7 delegators with valid grants...
cosmos... uatom reward is too low, skipping
cosmos... 892 uatom reward is too low, skipping
cosmos... 576 uatom reward is too low, skipping
cosmos... Autostaking 297743 uatom
cosmos... Successfully broadcasted
cosmos... 980 uatom reward is too low, skipping
cosmos... Autostaking 94897 uatom
cosmos... Successfully broadcasted
cosmos... Autostaking 14823 uatom
cosmos... Failed to broadcast: TimeoutError: Transaction with ID 3B1E27CF726851E2918ABEFB3D5FCAA4FF34F12AD35C618FB40F324AF7EA2E8D was submitted but was not yet found on the chain. You might want to check later.
at pollForTx (/home/osmo/restake/node_modules/@cosmjs/stargate/build/stargateclient.js:213:23)
at pollForTx (/home/osmo/restake/node_modules/@cosmjs/stargate/build/stargateclient.js:226:19)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
txId: '3B1E27CF726851E2918ABEFB3D5FCAA4FF34F12AD35C618FB40F324AF7EA2E8D'
}
this is common behaviour of heavy chain nodes, if RPC load is high the node will start lagging and fall out of sync, to catch up as soon as the load lowers significantly. We're experiencing this regularly on our relayer endpoints on various chains, but cosmoshub is the most prone to that error.
transactions "stuck" in this way will eventually be broadcasted to the mempool and confirm on-chain, but only if the node is able to reach the tip
proposed solution: batch txs (?); make broadcast TimeoutError non critical
workaround: repeatedly run script with chain argument until there are no errors anymore
the current connected public lcd hits some limit and times out:
path: '/cosmos/staking/v1beta1/validators/cosmosvaloper14qazscc80zgzx3m0m0aa30ths0p9hg8vdglqrc/delegations?pagination.limit=1000',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'lcd-cosmoshub.blockapsis.com',
protocol: 'https:',
_redirectable: [Writable],
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype]
},
data: '<html>\r\n' +
'<head><title>504 Gateway Time-out</title></head>\r\n' +
'<body>\r\n' +
'<center><h1>504 Gateway Time-out</h1></center>\r\n' +
'</body>\r\n' +
'</html>\r\n'
},
isAxiosError: true
proposed solution: validators providing the service could use private REST endpoints without rate limits
while these errors turned up during tests on cosmoshub it doesn't mean they are limited to the hub, it can be assumed that the bigger the number of total delegators, the worse the load issues will be
Need to factor in actual block time.
if you have 6sec block time and 5sec theoric, you have 0.83% less APR than theory
you can calculate over 100 block to get ~ 1h mean
take time of latest heigh
take time of height - 100
divide per 100=> you have the average block time
Just for readability in the file. Will write a script to do this automatically
Node requirements: indexing on, min gas prices, use your own node
Bit more info on key management for operators. Be clear about mnemonic being for hot wallet etc.
I'll add more as they come up
Sifchain has 18 decimals and Cosmjs seems to have issues processing integers, e.g. errors in console when delegating. Unsure if Sifchain is usable at all right now with REStake. Needs some more investigation.
Separating from #125
Include validator voting power/rank in UI and encourage delegators in the right direction to improve health of network.
I'm not sure if entirely disabling delegation functions is a good idea but could be some upper limits that make sense to do this
Doesn't merge well, don't know who the operators are at a glance.
Slightly improved now the chain-registry data is dynamic but could still be better.
Relates to #129
Accidentally re-enabled it when I switched to chain registry integration. Not a big deal but should probably be disabled for now.
Maybe should switch to explicit enabled: true
option in networks.json, instead of disabled: true
.
Hi, I am trying to become an operator of restake but I am not able to run the docker image successsfully.
I already have latest docker and docker-compose installed on an Ubuntu machine.
When I run sudo docker-compose run --rm app npm run autostake
, the following error occurs:
`
[email protected] autostake
node scripts/autostake.mjs
node:internal/errors:465
ErrorCaptureStackTrace(err);
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@cosmjs/proto-signing' imported from /usr/src/app/scripts/autostake.mjs
at new NodeError (node:internal/errors:372:5)
at packageResolve (node:internal/modules/esm/resolve:907:9)
at moduleResolve (node:internal/modules/esm/resolve:956:20)
at defaultResolve (node:internal/modules/esm/resolve:1172:11)
at ESMLoader.resolve (node:internal/modules/esm/loader:580:30)
at ESMLoader.getModuleJob (node:internal/modules/esm/loader:294:18)
at ModuleWrap. (node:internal/modules/esm/module_job:80:40)
at link (node:internal/modules/esm/module_job:78:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
Node.js v17.7.1
ERROR: 1
`
May I know how to resolve this problem? Thank you.
line 61 of /scripts/autostake.mjs:
let grantedAddresses = await this.getGrantedAddresses(addresses)
passes addresses
as the only parameter, which doesn't match the function definition
on line 137 (same file):
async getGrantedAddresses(client, addresses){
Results in the following error:
file:///usr/src/app/scripts/autostake.mjs:138
let grantCalls = addresses.map(item => {
^
TypeError: Cannot read properties of undefined (reading 'map')
at Autostake.getGrantedAddresses (file:///usr/src/app/scripts/autostake.mjs:138:32)
at file:///usr/src/app/scripts/autostake.mjs:61:43
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Promise.all (index 0)
at async executeSync (file:///usr/src/app/src/utils/Helpers.mjs:44:5)
at async Autostake.run (file:///usr/src/app/scripts/autostake.mjs:76:5)
I'll work on a pull request to fix this later, just wanted to make people aware in the meantime.
Currently the first network in the array is the default, i.e. redirecting from the root page.
Make this flexible, much like ownerAddress. Allows validators with their own UI to focus on their preferred network.
Add support for withdraw addresses
Upon detecting a withdraw address,
the grant for /cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward
needs to come from the delegate address
the grant for AUTHORIZATION_TYPE_DELEGATE
needs to come from the withdraw address.
So that means the user needs to sign from two different addresses ... I'm not sure how to make Keplr handle this gracefully.
Presumably the user with the withdraw address is slightly advanced and will be able to manage switching from one person to the other.
(Of course, this means the Revokes need to follow the same two address tango)
Refresh balance after delegate, on schedule. Clear after network change before new network loads
since this commit 237c3c1
file:///root/restake/scripts/autostake.mjs:113
return client.queryClient.getBalance(client.operator.botAddress, client.network.denom)
^
TypeError: Cannot read properties of undefined (reading 'botAddress')
at Autostake.checkBalance (file:///root/restake/scripts/autostake.mjs:113:58)
at file:///root/restake/scripts/autostake.mjs:47:20
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Promise.all (index 0)
at async executeSync (file:///root/restake/src/utils/Helpers.mjs:44:5)
at async Autostake.run (file:///root/restake/scripts/autostake.mjs:75:5)
Finding delegators...
Checking 313 delegators for grants...
...batch 1
...batch 2
ERROR: Error: connect ETIMEDOUT 54.183.249.236:443
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1158:16) {
errno: -110,
code: 'ETIMEDOUT',
syscall: 'connect',
address: '54.183.249.236',
port: 443,
config: {
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false
},
adapter: [Function: httpAdapter],
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
validateStatus: [Function: validateStatus],
headers: {
Accept: 'application/json, text/plain, /',
'User-Agent': 'axios/0.26.0'
},
method: 'get',
url: 'https://lcd-osmosis.blockapsis.com/cosmos/authz/v1beta1/grants?grantee=osmo194ytn50yhh67rdha8akhs7c6zulnz4n2pv6n63&granter=osmo159d5k2aaeepvxs3f7cv8uapeveh9a5shhu9amj',
data: undefined
},
request: <ref *1> Writable {
_writableState: WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: true,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
afterWriteTickInfo: null,
buffered: [],
bufferedIndex: 0,
allBuffers: true,
allNoop: true,
pendingcb: 0,
constructed: true,
prefinished: false,
errorEmitted: false,
emitClose: true,
autoDestroy: true,
errored: null,
closed: false,
closeEmitted: false,
[Symbol(kOnFinished)]: []
},
_events: [Object: null prototype] {
response: [Function: handleResponse],
error: [Function: handleRequestError],
socket: [Function: handleRequestSocket]
},
_eventsCount: 3,
_maxListeners: undefined,
_options: {
maxRedirects: 21,
maxBodyLength: 10485760,
protocol: 'https:',
path: '/cosmos/authz/v1beta1/grants?grantee=osmo194ytn50yhh67rdha8akhs7c6zulnz4n2pv6n63&granter=osmo159d5k2aaeepvxs3f7cv8uapeveh9a5shhu9amj',
method: 'GET',
headers: [Object],
agent: undefined,
agents: [Object],
auth: undefined,
hostname: 'lcd-osmosis.blockapsis.com',
port: null,
nativeProtocols: [Object],
pathname: '/cosmos/authz/v1beta1/grants',
search: '?grantee=osmo194ytn50yhh67rdha8akhs7c6zulnz4n2pv6n63&granter=osmo159d5k2aaeepvxs3f7cv8uapeveh9a5shhu9amj'
},
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 0,
_requestBodyBuffers: [],
_onNativeResponse: [Function (anonymous)],
_currentRequest: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
socket: [TLSSocket],
_header: 'GET /cosmos/authz/v1beta1/grants?grantee=osmo194ytn50yhh67rdha8akhs7c6zulnz4n2pv6n63&granter=osmo159d5k2aaeepvxs3f7cv8uapeveh9a5shhu9amj HTTP/1.1\r\n' +
'Accept: application/json, text/plain, /\r\n' +
'User-Agent: axios/0.26.0\r\n' +
'Host: lcd-osmosis.blockapsis.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: [Agent],
socketPath: undefined,
method: 'GET',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/cosmos/authz/v1beta1/grants?grantee=osmo194ytn50yhh67rdha8akhs7c6zulnz4n2pv6n63&granter=osmo159d5k2aaeepvxs3f7cv8uapeveh9a5shhu9amj',
_ended: false,
res: null,
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'lcd-osmosis.blockapsis.com',
protocol: 'https:',
_redirectable: [Circular *1],
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype]
},
_currentUrl: 'https://lcd-osmosis.blockapsis.com/cosmos/authz/v1beta1/grants?grantee=osmo194ytn50yhh67rdha8akhs7c6zulnz4n2pv6n63&granter=osmo159d5k2aaeepvxs3f7cv8uapeveh9a5shhu9amj',
[Symbol(kCapture)]: false
},
response: undefined,
isAxiosError: true,
toJSON: [Function: toJSON]
}
Mebbe add an optional Pro mode where a validator can grant restake
/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission
and then autostake can issue those....
See initial comment and discussion on #67 for detail.
Restake is able to pick up the list of supported validators and my own delegation, however when attempting any action (delegate, manual compound, claim, enable restake), the following error is thrown:
Failed to broadcast: Unsupported type: '/desmos.profiles.v1beta1.Profile'
Currently limited to batch size of 100 for delegators and grant lookup. Reduced delegator batch size from 250 to 100 recently.
CosmosHub can still struggle with 100 batch size, and it really depends on node resources too. Might as well make this configurable per network so operators can override in their local networks json.
Run times are assumed to be UTC but this isn't clear. Also mention around cron and systemd timers docs
Show operator when it started/finished/duration
Some validators will likely want to offer multiple runtimes per day. It could make sense for most validators to offer this if they set their minimum reward a bit higher.
Allow multiple runtimes, which feeds into the future APY feature (#80). Show full runtimes on the validator profile, and adapt the countdown to handle multiple times per day (#125)
Had reports of this for Desmos, maybe others. When your autostaking mnemonic is imported into Keplr, the address matches for most networks but some it does not. E.g. Desmos.
For the purpose of running the script, the address spat out by npm run autostake
is the correct one. This is the one you should fund and the script will send TXs from. I'm not sure how to actually access this in Keplr as of writing but it's probably derivation path related.
If you see this on any other networks, please add to this issue. I'll put a note in the README asap.
Hi mates,
My restake was working nicely for cosmoshub until today. I just pulled repo changes and rebuilt as usually.
What info would help to debug this?
This are the logs:
/usr/local/bin/docker-compose run --rm app npm run autostake cosmoshub
Creating restake_app_run ... done
> [email protected] autostake
> node scripts/autostake.mjs "cosmoshub"
[11:59:47.011] Cosmos Hub bot address is cosmos1dg8u5qll7fjm9nnwqns0ullhtc6g552ugd0eqj
[11:59:47.137] Failed to connect All promises were rejected
Before that it worked like this:
19-03-22/10:01:01
Creating restake_app_run ...
Creating restake_app_run ... done
> [email protected] autostake
> node scripts/autostake.mjs "cosmoshub"
Cosmos Hub bot address is cosmos1dg8u5qll7fjm9nnwqns0ullhtc6g552ugd0eqj
Using REST URL http://127.0.0.1:1317
Using RPC URL http://127.0.0.1:26657
Running autostake
Bot balance is 72024 uatom
Finding delegators...
...batch 1
...batch 2
...batch 3
...batch 4
Checking 356 delegators for grants...
...batch 1
...batch 2
...batch 3
...batch 4
Currently we send one TX per delegator, which includes a single MsgExec
TX with the two messages inside to withdraw and delegate.
There's no reason we can't send multiple MsgExec in a single transaction. Just need to work out how many is reasonable to include in a single batch
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.