Skip to content

Commit 4316de9

Browse files
authored
Merge pull request #34 from AudiusProject/mjp-rewards
Rewards Part 1
2 parents a95c084 + 3e5ede8 commit 4316de9

15 files changed

Lines changed: 1101 additions & 2 deletions

api/dbv1/get_undisbursed_challenges.sql.go

Lines changed: 69 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-- name: GetUndisbursedChallenges :many
2+
SELECT
3+
users.handle,
4+
users.wallet,
5+
user_challenges.challenge_id,
6+
user_challenges.specifier
7+
FROM user_challenges
8+
JOIN users ON users.user_id = user_challenges.user_id
9+
LEFT JOIN challenge_disbursements
10+
ON challenge_disbursements.challenge_id = user_challenges.challenge_id
11+
AND challenge_disbursements.specifier = user_challenges.specifier
12+
WHERE
13+
challenge_disbursements.challenge_id IS NULL
14+
AND user_challenges.is_complete
15+
AND user_challenges.user_id = @user_id
16+
AND (@challenge_id::text = '' OR user_challenges.challenge_id = @challenge_id)
17+
AND (@specifier::text = '' OR user_challenges.specifier = @specifier)
18+
;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package reward_manager
2+
3+
type ChangeManagerAccount struct{}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package reward_manager
2+
3+
type CreateSender struct{}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package reward_manager
2+
3+
type CreateSenderPublic struct{}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package reward_manager
2+
3+
type DeleteSender struct{}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package reward_manager
2+
3+
type DeleteSenderPublic struct{}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package reward_manager
2+
3+
type EvaluateAttestation struct{}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package reward_manager
2+
3+
type Init struct{}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package reward_manager
2+
3+
import (
4+
"encoding/hex"
5+
6+
bin "github.com/gagliardetto/binary"
7+
"github.com/gagliardetto/solana-go"
8+
)
9+
10+
const (
11+
SenderSeedPrefix = "S_"
12+
EthAddressByteLength = 20
13+
AttestationsSeedPrefix = "V_"
14+
)
15+
16+
type SubmitAttestation struct {
17+
DisbursementID string
18+
SenderEthAddress string `bin:"-" borsh_skip:"true"`
19+
RewardManagerState solana.PublicKey `bin:"-" borsh_skip:"true"`
20+
Payer solana.PublicKey `bin:"-" borsh_skip:"true"`
21+
22+
solana.AccountMetaSlice `bin:"-" borsh_skip:"true"`
23+
}
24+
25+
func NewSubmitAttestationInstructionBuilder() *SubmitAttestation {
26+
nd := &SubmitAttestation{}
27+
return nd
28+
}
29+
30+
func (inst *SubmitAttestation) SetDisbursementID(challengeId string, specifier string) *SubmitAttestation {
31+
inst.DisbursementID = challengeId + ":" + specifier
32+
return inst
33+
}
34+
35+
func (inst *SubmitAttestation) SetSenderEthAddress(senderEthAddress string) *SubmitAttestation {
36+
inst.SenderEthAddress = senderEthAddress
37+
return inst
38+
}
39+
40+
func (inst *SubmitAttestation) SetRewardManagerState(state solana.PublicKey) *SubmitAttestation {
41+
inst.RewardManagerState = state
42+
return inst
43+
}
44+
45+
func (inst *SubmitAttestation) SetPayer(payer solana.PublicKey) *SubmitAttestation {
46+
inst.Payer = payer
47+
return inst
48+
}
49+
50+
func deriveAuthority(programId solana.PublicKey, state solana.PublicKey) (solana.PublicKey, uint8, error) {
51+
seeds := make([][]byte, 1)
52+
seeds[0] = state.Bytes()[0:32]
53+
return solana.FindProgramAddress(seeds, programId)
54+
}
55+
56+
func deriveSender(programId solana.PublicKey, authority solana.PublicKey, ethAddress string) (solana.PublicKey, uint8, error) {
57+
58+
senderSeedPrefix := []byte(SenderSeedPrefix)
59+
// Remove 0x and decode hex
60+
decodedEthAddress, err := hex.DecodeString(ethAddress[2:])
61+
if err != nil {
62+
return solana.PublicKey{}, 0, err
63+
}
64+
// Pad the eth address if necessary w/ leading 0
65+
senderSeed := make([]byte, len(senderSeedPrefix)+EthAddressByteLength)
66+
copy(senderSeed, senderSeedPrefix)
67+
copy(senderSeed[len(senderSeed)-len(decodedEthAddress):], decodedEthAddress)
68+
return solana.FindProgramAddress([][]byte{authority.Bytes()[0:32], senderSeed}, programId)
69+
}
70+
71+
func deriveAttestations(programId solana.PublicKey, authority solana.PublicKey, disbursementId string) (solana.PublicKey, uint8, error) {
72+
attestationsSeed := make([]byte, len(AttestationsSeedPrefix)+len(disbursementId))
73+
copy(attestationsSeed, []byte(AttestationsSeedPrefix))
74+
copy(attestationsSeed[len([]byte(AttestationsSeedPrefix)):], disbursementId)
75+
return solana.FindProgramAddress([][]byte{authority.Bytes()[0:32], attestationsSeed}, programId)
76+
}
77+
78+
func (inst SubmitAttestation) Build() *Instruction {
79+
authority, _, _ := deriveAuthority(ProgramID, inst.RewardManagerState)
80+
sender, _, _ := deriveSender(ProgramID, authority, inst.SenderEthAddress)
81+
attestations, _, _ := deriveAttestations(ProgramID, authority, inst.DisbursementID)
82+
83+
inst.AccountMetaSlice = []*solana.AccountMeta{
84+
{
85+
PublicKey: attestations,
86+
IsSigner: false,
87+
IsWritable: true,
88+
},
89+
{
90+
PublicKey: inst.RewardManagerState,
91+
IsSigner: false,
92+
IsWritable: false,
93+
},
94+
{
95+
PublicKey: authority,
96+
IsSigner: false,
97+
IsWritable: false,
98+
},
99+
{
100+
PublicKey: inst.Payer,
101+
IsSigner: true,
102+
IsWritable: false,
103+
},
104+
{
105+
PublicKey: sender,
106+
IsSigner: false,
107+
IsWritable: false,
108+
},
109+
{
110+
PublicKey: solana.SysVarRentPubkey,
111+
IsSigner: false,
112+
IsWritable: false,
113+
},
114+
{
115+
PublicKey: solana.SysVarInstructionsPubkey,
116+
IsSigner: false,
117+
IsWritable: false,
118+
},
119+
{
120+
PublicKey: solana.SystemProgramID,
121+
IsSigner: false,
122+
IsWritable: false,
123+
},
124+
}
125+
126+
return &Instruction{BaseVariant: bin.BaseVariant{
127+
Impl: inst,
128+
TypeID: bin.TypeIDFromUint8(Instruction_SubmitAttestation),
129+
}}
130+
}
131+
132+
func (inst SubmitAttestation) MarshalWithEncoder(encoder *bin.Encoder) error {
133+
return encoder.WriteString(inst.DisbursementID)
134+
}
135+
136+
func (inst *SubmitAttestation) UnmarshalWithDecoder(decoder *bin.Decoder) error {
137+
return decoder.Decode(&inst.DisbursementID)
138+
}
139+
140+
func NewSubmitAttestationInstruction(
141+
challengeId string,
142+
specifier string,
143+
senderEthAddress string,
144+
rewardManagerState solana.PublicKey,
145+
payer solana.PublicKey,
146+
147+
) *SubmitAttestation {
148+
return NewSubmitAttestationInstructionBuilder().
149+
SetRewardManagerState(rewardManagerState).
150+
SetDisbursementID(challengeId, specifier).
151+
SetSenderEthAddress(senderEthAddress).
152+
SetPayer(payer)
153+
}

0 commit comments

Comments
 (0)