Automates the task for a Jupiter DAO representative to vote on-behalf of their constituents.
If a GLAM is observed to cast their own vote the service will NOT override the users vote for that proposal.
Needed to access dependencies hosted on GitHub Package Repository.
Create a gradle.properties
file in this directory or under $HOME/.gradle/
.
Generate a classic token with the read:packages
scope.
gpr.user=GITHUB_USERNAME
gpr.token=GITHUB_TOKEN
With dry run enabled all code paths will still be hit, excluding only publishing transactions.
- dryRun="false"
- jvmArgs="-server -XX:+UseZGC -Xms128M -Xmx896M"
- logLevel="INFO"
Builds an Alpine based image with a custom runtime image using Java jlink.
If your gradle properties file is not local you can pass your GitHub access token via environment variables.
export GITHUB_ACTOR="GITHUB_USERNAME"
export GITHUB_TOKEN="GITHUB_TOKEN"
docker build \
--secret type=env,id=GITHUB_ACTOR,env=GITHUB_ACTOR \
--secret type=env,id=GITHUB_TOKEN,env=GITHUB_TOKEN \
-t glam-systems/jupiter-vote-service:latest .
configDirectory
must be absolute.
- configFileName=""
- configDirectory="$(pwd)/.config"
- dockerImageName="glam-systems/jupiter-vote-service:latest"
- dockerRunFlags="--detach --name jupiter_vote_service --memory 1g"
./runDockerImage.sh --configFileName=vote_service.json
Java JDK 23 or later is required.
Compiles a custom runtime image using Java jlink, that can be found at
jupiter_vote_service/build/jupiter_vote_service/bin/java
.
./compile.sh
- configFile=""
- screen=[0|1]
./runService.sh --configFile=.config/vote_service.json
-Dsystems.glam.jupiter_vote_service.config=.config/vote_service.json -Dsystems.glam.jupiter_vote_service.dry_run=false
Durations/windows/delays are ISO-8601 duration formatted
PnDTnHnMn.nS
, PT
may be omitted.
Request capacity limits for constrained resources.
maxCapacity
: Maximum requests that can be made withinresetDuration
resetDuration
:maxCapacity
is added over the course of this duration.minCapacityDuration
: Maximum time before capacity should recover to a positive value, given that no additional failures happen.
Backoff strategy in response to errors.
type
: single, linear, fibonacci, exponentialinitialRetryDelay
maxRetryDelay
See context below.
{
"signingService": {
"factoryClass": "software.sava.kms.core.signing.MemorySignerFromFilePointerFactory",
"config": {
"filePath": ".config/service_key.json"
}
},
"workDir": ".vote",
"ballotFilePath": ".config/glam_ballot.json",
"formatter": {
"sig": "https://solscan.io/tx/%s",
"address": "https://solscan.io/account/%s"
},
"api": {
"basePath": "/api/v0/",
"port": 7073
},
"notificationHooks": [
{
"endpoint": "https://hooks.slack.com/<URL_PATH_PROVIDED_BY_SLACK>",
"provider": "SLACK",
"capacity": {
"maxCapacity": 2,
"resetDuration": "1S",
"minCapacityDuration": "8S"
}
}
],
"rpcCallWeights": {
"getProgramAccounts": 2,
"getTransaction": 5,
"sendTransaction": 10
},
"rpc": {
"defaultCapacity": {
"minCapacityDuration": "PT8S",
"maxCapacity": 4,
"resetDuration": "PT1S"
},
"endpoints": [
{
"url": "https://mainnet.helius-rpc.com/?api-key=",
"capacity": {
"minCapacityDuration": "PT5S",
"maxCapacity": 50,
"resetDuration": "PT1S"
}
},
{
"url": "https://solana-mainnet.rpc.extrnode.com/"
}
]
},
"sendRPC": {
"defaultCapacity": {
"maxCapacity": 1,
"resetDuration": "1S",
"minCapacityDuration": "8S"
},
"endpoints": [
{
"url": "https://staked.helius-rpc.com/?api-key="
}
]
},
"websocket": {
"endpoint": "wss://mainnet.helius-rpc.com/?api-key="
},
"helius": {
"url": "https://mainnet.helius-rpc.com/?api-key=",
"capacity": {
"maxCapacity": 2,
"resetDuration": "1S",
"minCapacityDuration": "8S"
}
},
"schedule": {
"initialDelay": 0,
"delay": 1,
"timeUnit": "HOURS"
},
"minLockedToVote": 1,
"stopVotingBeforeEndDuration": "42S",
"newVoteBatchSize": 3,
"changeVoteBatchSize": 6,
"maxSOLPriorityFee": 0.00042
}
- signingService
- workDir
- ballotFilePath
- formatter
- notificationHooks
- rpcCallWeights
- rpc
- sendRPC
- helius
- websocket
- minLockedToVote
- stopVotingBeforeEndDuration
- newVoteBatchSize
- changeVoteBatchSize
- maxSOLPriorityFee
Service key used to pay for transactions.
See Sava KMS for some example options and configuration.
Each GLAM that delegates to this service key must have the following minimum configuration.
- JupiterVote
- VoteOnProposal
Used to cache run time state and track the proposal vote state for each delegated GLAM.
Holds the representatives vote side for each proposal they wish to vote on.
The proposal
key can be found in the URL for each proposal page hosted by vote.jup.ag,
e.g., https://vote.jup.ag/proposal/ByQ21v3hqdQVwPHsfwurrtEAH8pB3DYuLdp9jU2Hwnd4.
The representative may change their vote by updating this file and restarting the service.
TODO: Map text based side to int.
[
{
"proposal": "ByQ21v3hqdQVwPHsfwurrtEAH8pB3DYuLdp9jU2Hwnd4",
"side": 3
}
]
Detailed JSON messages will be POSTed to each webhook endpoint.
Local webserver to provide service information.
{
"basePath": "/api/v0/",
"port": 7073
}
Define call weights per RPC call to help match your providers API limits. See the CallWeights class for which are supported.
{
"getProgramAccounts": 2,
"getTransaction": 5,
"sendTransaction": 10
}
defaultCapacity
defaultBackoff
endpoints
: Array of RPC node configurations.url
capacity
: OverridesdefaultCapacity
backoff
: OverridesdefaultBackoff
{
"defaultCapacity": {
"maxCapacity": 10,
"resetDuration": "1S",
"minCapacityDuration": "13S"
}
}
Same as rpc
but only used for publishing transactions to the network. Defaults to the rpc
configuration if not
provided.
{
"defaultCapacity": {
"maxCapacity": 1,
"resetDuration": "1S",
"minCapacityDuration": "5S"
}
}
Same as a single rpc
endpoint
entry. Only used for estimating priority fees.
{
"capacity": {
"maxCapacity": 3,
"resetDuration": "1S",
"minCapacityDuration": "5S"
}
}
Used to track GLAM Vault account changes.
endpoint
backoff
Defaults to 1 JUP.
Stop executing vote transactions this close to the end of the proposal conclusion.
Number of GLAM vaults to cast new votes for per transaction. Each new vote requires two instructions, create vote account and cast vote. The service will dynamically reduce this size if a transaction exceeds the size limit.
Defaults to 5.
Number of GLAM vaults to change votes for per transaction. Each vote change requires one instruction, cast vote. The service will dynamically reduce this size if a transaction exceeds the size limit.
Defaults to 10.
Caps the maximum priority fee for all transactions within the system. Default is 0.00042 SOL.