Skip to content

Commit 89f4640

Browse files
committed
Add rewards_cli
1 parent c2ee6a9 commit 89f4640

File tree

18 files changed

+1772
-4
lines changed

18 files changed

+1772
-4
lines changed

cmd/rewards_cli/cmd/register.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
6+
"api.audius.co/config"
7+
"api.audius.co/logging"
8+
"api.audius.co/solana/spl"
9+
"api.audius.co/solana/spl/programs/reward_manager"
10+
"github.com/ethereum/go-ethereum/common"
11+
"github.com/gagliardetto/solana-go"
12+
"github.com/gagliardetto/solana-go/rpc"
13+
"github.com/spf13/cobra"
14+
"go.uber.org/zap"
15+
)
16+
17+
var registerCmd = &cobra.Command{
18+
Use: "register [address] [operator]",
19+
Short: "Register a single Ethereum address as a sender in the rewards program",
20+
Args: cobra.ExactArgs(2),
21+
RunE: func(cmd *cobra.Command, args []string) error {
22+
// Get flags
23+
rpcOverride, _ := cmd.Flags().GetString("rpc")
24+
openAudioURLOverride, _ := cmd.Flags().GetString("openAudioURL")
25+
keypairPath, _ := cmd.Flags().GetString("keypair")
26+
dryRun, _ := cmd.Flags().GetBool("dry-run")
27+
28+
if dryRun {
29+
return fmt.Errorf("dry-run mode not supported for register command")
30+
}
31+
32+
// Initialize logger
33+
cfg := config.Cfg
34+
logger := logging.NewZapLogger(cfg)
35+
36+
// Initialize config based on environment
37+
if rpcOverride != "" {
38+
cfg.SolanaConfig.RpcProviders = []string{rpcOverride}
39+
}
40+
if openAudioURLOverride != "" {
41+
cfg.OpenAudioURLs = []string{openAudioURLOverride}
42+
}
43+
if keypairPath != "" {
44+
privKey, err := solana.PrivateKeyFromSolanaKeygenFile(keypairPath)
45+
if err != nil {
46+
return fmt.Errorf("failed to load keypair from %s: %w", keypairPath, err)
47+
}
48+
payer, err := solana.WalletFromPrivateKeyBase58(privKey.String())
49+
if err != nil {
50+
return fmt.Errorf("failed to create wallet from private key: %w", err)
51+
}
52+
cfg.SolanaConfig.FeePayers = []solana.Wallet{*payer}
53+
}
54+
55+
address := args[0]
56+
operator := args[1]
57+
58+
ctx := cmd.Context()
59+
payer := cfg.SolanaConfig.FeePayers[0]
60+
validators := cfg.ArtistCoinRewardsStaticSenders
61+
transactionSender := spl.NewTransactionSender(cfg.SolanaConfig.FeePayers, cfg.SolanaConfig.RpcProviders)
62+
63+
logger.Debug("Getting attestations...")
64+
attestations, err := getSenderAttestations(ctx, validators, address, cfg.SolanaConfig.RewardManagerState, logger)
65+
if err != nil {
66+
return fmt.Errorf("failed to get sender attestations: %w", err)
67+
}
68+
logger.Debug("Got attestations", zap.Int("count", len(attestations)))
69+
70+
for _, a := range attestations {
71+
sender, _, err := reward_manager.DeriveSenderAccount(reward_manager.ProgramID, cfg.SolanaConfig.RewardManagerState, common.HexToAddress(a.Owner))
72+
if err != nil {
73+
return fmt.Errorf("failed to derive sender account: %w", err)
74+
}
75+
logger.Debug("Attestation",
76+
zap.String("attester", a.Owner),
77+
zap.String("senderAccount", sender.String()))
78+
}
79+
80+
logger.Debug("Building create sender transaction...")
81+
tx, err := buildCreateSenderPublicTransaction(
82+
cfg.SolanaConfig.RewardManagerState,
83+
payer.PublicKey(),
84+
&config.Node{DelegateWallet: address, Owner: operator},
85+
attestations,
86+
)
87+
if err != nil {
88+
return fmt.Errorf("failed to build create sender transaction: %w", err)
89+
}
90+
91+
logger.Debug("Adding priority fees to transaction...")
92+
err = transactionSender.AddPriorityFees(ctx, tx, spl.AddPriorityFeesParams{})
93+
if err != nil {
94+
return fmt.Errorf("failed to add priority fees: %w", err)
95+
}
96+
logger.Debug("Priority fees added")
97+
98+
tx.SetFeePayer(payer.PublicKey())
99+
txBuilt, err := tx.Build()
100+
if err != nil {
101+
return fmt.Errorf("failed to build transaction: %w", err)
102+
}
103+
fmt.Println(txBuilt.String())
104+
105+
logger.Info("Sending create sender transaction...")
106+
sig, err := transactionSender.SendTransactionWithRetries(
107+
ctx, tx, rpc.CommitmentConfirmed, rpc.TransactionOpts{})
108+
if err != nil {
109+
return fmt.Errorf("failed to send create sender transaction: %w", err)
110+
}
111+
logger.Info("Successfully registered sender", zap.String("signature", sig.String()))
112+
113+
return nil
114+
},
115+
}
116+
117+
func init() {
118+
rootCmd.AddCommand(registerCmd)
119+
}

cmd/rewards_cli/cmd/root.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
6+
"github.com/spf13/cobra"
7+
)
8+
9+
var rootCmd = &cobra.Command{
10+
Use: "rewards_cli",
11+
Short: "Manages the Reward Manager program's registered senders and related lookup table",
12+
}
13+
14+
func init() {
15+
rootCmd.PersistentFlags().StringP("rpc", "r", "", "Solana RPC endpoint (overrides env default)")
16+
rootCmd.PersistentFlags().StringP("openAudioURL", "o", "", "OpenAudio SDK URL (overrides env default)")
17+
rootCmd.PersistentFlags().StringP("keypair", "k", "", "Fee payer keypair file (overrides env default)")
18+
rootCmd.PersistentFlags().Bool("dry-run", false, "Dry run mode - check accounts without registering")
19+
}
20+
21+
func Execute() {
22+
err := rootCmd.Execute()
23+
if err != nil {
24+
os.Exit(1)
25+
}
26+
}

0 commit comments

Comments
 (0)