@audius/sp-actions 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +61 -0
  3. package/claim.js +165 -0
  4. package/package.json +29 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # @audius/sp-actions
2
+
3
+ ## 1.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [ca9fbd6]
8
+ - Updated dependencies [fa19828]
9
+ - Updated dependencies [667037e]
10
+ - Updated dependencies [3ef78ea]
11
+ - @audius/sdk@4.2.0
package/README.md ADDED
@@ -0,0 +1,61 @@
1
+ ## Automatic claims
2
+
3
+ This utility enables Audius Service Providers to automatically run claim operations whenever a new round is initiated.
4
+
5
+ This script can run on a recurring basis via cron and takes in two command line arguments: `spOwnerWallet` and `privateKey`.
6
+
7
+ `spOwnerWallet` - The wallet address used to register the nodes
8
+
9
+ `privateKey` - Not the private key of the `spOwnerWallet`. Should be a throwaway wallet used exclusively to claim with just enough ETH to make claims, no more than 1 ETH at any given time with an alert to top up.
10
+
11
+ Any wallet can make a claim on behalf of any node operator and their delegators and the rewards will be distributed to the node operator and the delegators inside the staking system and not to the wallet performing the claim. In order to access the claim, the node operator or delegator would have to request to undelegate.
12
+
13
+ ```
14
+ # 1. Ensure npm is installed on your system
15
+
16
+ # 2. Install the actions utility
17
+ npm install -g @audius/sp-actions
18
+
19
+ # 3. Setup a cron job with the following command: (NOTE: replace <npm_prefix> with the output from 'npm config get prefix')
20
+ (crontab -l 2>/dev/null; echo "0 */6 * * * <npm_prefix>/bin/claim claim-rewards <spOwnerWallet> <privateKey>") | crontab -
21
+ ```
22
+
23
+ ```
24
+ Usage: claim [options] [command]
25
+
26
+ Options:
27
+ -h, --help display help for command
28
+
29
+ Commands:
30
+ initiate-round [options] <privateKey> Initiates new round for claiming rewards
31
+ claim-rewards [options] <spOwnerWallet> <privateKey> Claim rewards for given spOwnerWallet
32
+ help [command] display help for command
33
+ ```
34
+
35
+ ```
36
+ Usage: claim initiate-round [options] <privateKey>
37
+
38
+ Initiates new round for claiming rewards
39
+
40
+ Options:
41
+ --eth-registry-address <ethRegistryAddress> Registry contract address (default: "0xd976d3b4f4e22a238c1A736b6612D22f17b6f64C")
42
+ --eth-token-address <ethTokenAddress> Token contract address (default: "0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998")
43
+ --web3-provider <web3Provider> Web3 provider to use
44
+ --gas <gas> ammount of gas to use (default: 100000)
45
+ --gas-price <gasPrice> gas price in gwei
46
+ -h, --help display help for command
47
+ ```
48
+
49
+ ```
50
+ Usage: claim claim-rewards [options] <spOwnerWallet> <privateKey>
51
+
52
+ Claim rewards for given spOwnerWallet
53
+
54
+ Options:
55
+ --eth-registry-address <ethRegistryAddress> Registry contract address (default: "0xd976d3b4f4e22a238c1A736b6612D22f17b6f64C")
56
+ --eth-token-address <ethTokenAddress> Token contract address (default: "0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998")
57
+ --web3-provider <web3Provider> Web3 provider to use
58
+ --gas <gas> ammount of gas to use (default: 1000000)
59
+ --gas-price <gasPrice> gas price in gwei
60
+ -h, --help display help for command
61
+ ```
package/claim.js ADDED
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env node
2
+
3
+ const axios = require('axios')
4
+ const Web3 = require('web3')
5
+ const HDWalletProvider = require('@truffle/hdwallet-provider')
6
+ const { program } = require('commander')
7
+
8
+ const { AudiusLibs } = require('@audius/sdk')
9
+
10
+ const defaultRegistryAddress = '0xd976d3b4f4e22a238c1A736b6612D22f17b6f64C'
11
+ const defaultTokenAddress = '0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998'
12
+ const defaultWeb3Provider = 'https://eth-mainnet.g.alchemy.com/v2/4hFRA61i6OFXz2UmkyFsSvgXBQBBOGgW'
13
+
14
+ async function configureLibs(ethRegistryAddress, ethTokenAddress, web3Provider) {
15
+ const configuredWeb3 = await AudiusLibs.Utils.configureWeb3(web3Provider, null, false)
16
+
17
+ const audiusLibsConfig = {
18
+ ethWeb3Config: AudiusLibs.configEthWeb3(ethTokenAddress, ethRegistryAddress, configuredWeb3, '0x0'),
19
+ isServer: true,
20
+ }
21
+
22
+ const libs = new AudiusLibs(audiusLibsConfig)
23
+ await libs.init()
24
+
25
+ return libs
26
+ }
27
+
28
+ async function getClaimsManagerContract(ethRegistryAddress, ethTokenAddress, web3) {
29
+ const audiusLibs = await configureLibs(ethRegistryAddress, ethTokenAddress, web3.eth.currentProvider)
30
+ await audiusLibs.ethContracts.ClaimsManagerClient.init()
31
+ return new web3.eth.Contract(
32
+ audiusLibs.ethContracts.ClaimsManagerClient._contract.options.jsonInterface,
33
+ audiusLibs.ethContracts.ClaimsManagerClient._contract.options.address
34
+ )
35
+ }
36
+
37
+ async function getDelegateManagerContract(ethRegistryAddress, ethTokenAddress, web3) {
38
+ const audiusLibs = await configureLibs(ethRegistryAddress, ethTokenAddress, web3.eth.currentProvider)
39
+ await audiusLibs.ethContracts.DelegateManagerClient.init()
40
+ return new web3.eth.Contract(
41
+ audiusLibs.ethContracts.DelegateManagerClient._contract.options.jsonInterface,
42
+ audiusLibs.ethContracts.DelegateManagerClient._contract.options.address
43
+ )
44
+ }
45
+
46
+ async function initiateRound(privateKey, { ethRegistryAddress, ethTokenAddress, web3Provider, gas, gasPrice, transferRewardsToSolana }) {
47
+ const web3 = new Web3(
48
+ new HDWalletProvider({
49
+ privateKeys: [privateKey],
50
+ providerOrUrl: web3Provider,
51
+ })
52
+ )
53
+
54
+ web3.eth.transactionPollingTimeout = 3600
55
+ const accountAddress = web3.eth.accounts.privateKeyToAccount(privateKey).address
56
+
57
+ const claimsManagerContract = await getClaimsManagerContract(ethRegistryAddress, ethTokenAddress, web3)
58
+
59
+ const lastFundedBlock = await claimsManagerContract.methods.getLastFundedBlock().call()
60
+ const requiredBlockDiff = await claimsManagerContract.methods.getFundingRoundBlockDiff().call()
61
+
62
+ const currentBlock = await web3.eth.getBlockNumber()
63
+ const blockDiff = currentBlock - lastFundedBlock - 12
64
+
65
+ if (blockDiff <= requiredBlockDiff) {
66
+ console.log(`Block difference of ${requiredBlockDiff} not met, ${requiredBlockDiff - blockDiff} blocks remaining`)
67
+ process.exit(1)
68
+ }
69
+
70
+ if (gas === undefined) {
71
+ console.log('Estimating Gas')
72
+ gas = await claimsManagerContract.methods.initiateRound().estimateGas()
73
+ console.log('Calculated Gas:', gas)
74
+ }
75
+
76
+ console.log('Initializing Round')
77
+ await claimsManagerContract.methods.initiateRound().send({
78
+ from: accountAddress,
79
+ gas
80
+ })
81
+ console.log('Successfully initiated Round')
82
+
83
+ if (transferRewardsToSolana) {
84
+ const { transferCommunityRewardsToSolana } = require('@audius/sdk/scripts/communityRewards/transferCommunityRewardsToSolana')
85
+ console.log('Running rewards manager transfer')
86
+ await transferCommunityRewardsToSolana()
87
+ console.log('Successfully transferred rewards to solana')
88
+ }
89
+ }
90
+
91
+ async function claimRewards(
92
+ spOwnerWallet,
93
+ privateKey,
94
+ { ethRegistryAddress, ethTokenAddress, web3Provider, gas, gasPrice }
95
+ ) {
96
+ const web3 = new Web3(
97
+ new HDWalletProvider({
98
+ privateKeys: [privateKey],
99
+ providerOrUrl: web3Provider,
100
+ })
101
+ )
102
+
103
+ web3.eth.transactionPollingTimeout = 3600
104
+ const accountAddress = web3.eth.accounts.privateKeyToAccount(privateKey).address
105
+
106
+ const claimsManagerContract = await getClaimsManagerContract(ethRegistryAddress, ethTokenAddress, web3)
107
+ const delegateManagerContract = await getDelegateManagerContract(ethRegistryAddress, ethTokenAddress, web3)
108
+
109
+ const claimPending = await claimsManagerContract.methods.claimPending(spOwnerWallet).call()
110
+
111
+ if (claimPending) {
112
+ if (gas === undefined) {
113
+ console.log('Estimating Gas')
114
+ gas = await delegateManagerContract.methods.claimRewards(spOwnerWallet).estimateGas()
115
+ console.log('Calculated Gas:', gas)
116
+
117
+ const gasPrice = await web3.eth.getGasPrice()
118
+ const estimatedFee = gas * gasPrice
119
+ console.log('Estimated Fee:', web3.utils.fromWei(estimatedFee.toString(), 'ether'), 'ETH')
120
+ }
121
+
122
+ console.log('Claiming Rewards')
123
+ await delegateManagerContract.methods.claimRewards(spOwnerWallet).send({
124
+ from: accountAddress,
125
+ gas,
126
+ gasPrice: gasPrice ? web3.utils.toWei(gasPrice, 'gwei') : (await web3.eth.getGasPrice()),
127
+ })
128
+ console.log('Claimed Rewards successfully')
129
+ } else {
130
+ console.log('No claims pending')
131
+ }
132
+ }
133
+
134
+ async function main() {
135
+ program
136
+ .command('initiate-round <privateKey>')
137
+ .description('Initiates new round for claiming rewards')
138
+ .option('--eth-registry-address <ethRegistryAddress>', 'Registry contract address', defaultRegistryAddress)
139
+ .option('--eth-token-address <ethTokenAddress>', 'Token contract address', defaultTokenAddress)
140
+ .option('--web3-provider <web3Provider>', 'Web3 provider to use', defaultWeb3Provider)
141
+ .option('--gas <gas>', 'amount of gas to use')
142
+ .option('--gas-price <gasPrice>', 'gas price in gwei')
143
+ .option('--transfer-rewards-to-solana', 'whether to also transfer rewards to solana rewards manager on success. Requires env vars to be set.', false)
144
+ .action(initiateRound)
145
+
146
+ program
147
+ .command('claim-rewards <spOwnerWallet> <privateKey>')
148
+ .description('Claim rewards for given spOwnerWallet')
149
+ .option('--eth-registry-address <ethRegistryAddress>', 'Registry contract address', defaultRegistryAddress)
150
+ .option('--eth-token-address <ethTokenAddress>', 'Token contract address', defaultTokenAddress)
151
+ .option('--web3-provider <web3Provider>', 'Web3 provider to use', defaultWeb3Provider)
152
+ .option('--gas <gas>', 'ammount of gas to use')
153
+ .option('--gas-price <gasPrice>', 'gas price in gwei')
154
+ .action(claimRewards)
155
+
156
+ try {
157
+ await program.parseAsync(process.argv)
158
+ process.exit(0)
159
+ } catch (e) {
160
+ console.error(e)
161
+ process.exit(1)
162
+ }
163
+ }
164
+
165
+ main()
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@audius/sp-actions",
3
+ "version": "1.0.1",
4
+ "description": "A utility for audius service providers to claim token rewards.",
5
+ "bin": {
6
+ "claim": "claim.js"
7
+ },
8
+ "author": "Audius",
9
+ "license": "Apache-2.0",
10
+ "dependencies": {
11
+ "@audius/sdk": "4.2.0",
12
+ "@truffle/hdwallet-provider": "^1.2.2",
13
+ "axios": "^0.21.0",
14
+ "commander": "^6.2.1",
15
+ "web3": "^1.3.4"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/AudiusProject/audius-protocol/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/AudiusProject/audius-protocol.git#main"
23
+ },
24
+ "homepage": "https://github.com/AudiusProject/audius-protocol/tree/main/packages/sp-actions",
25
+ "prettier": {
26
+ "semi": false,
27
+ "singleQuote": true
28
+ }
29
+ }