Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treasury selection #58

Merged
merged 46 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2f0fb0f
add lookup table back to config for ease of use in sdk
nonergodic Mar 23, 2024
622c43e
manually update program IDLs in claim_sdk
nonergodic Mar 25, 2024
b38fdd6
formatting
nonergodic Mar 25, 2024
24eb635
fix integration tests
nonergodic Mar 25, 2024
3d17cac
more integration test fixes
nonergodic Mar 25, 2024
14e89a7
fix compilation by putting stub in place
nonergodic Mar 25, 2024
ebf9ac2
formatting
nonergodic Mar 25, 2024
d246f11
adds treasury pub-key to ClaimEvent
solanoepalacio Mar 27, 2024
75cf752
minor fix
solanoepalacio Mar 29, 2024
112d1d2
multi-treasury deployment
solanoepalacio Mar 30, 2024
f7282a5
mt-02
solanoepalacio Mar 30, 2024
24306be
WIP treasury and funders pull and selection
brianUtn98 Mar 28, 2024
69c94ed
treasury list without env
brianUtn98 Mar 29, 2024
8534310
support multiple funders and use same one than frontend to sign
brianUtn98 Mar 29, 2024
6838acc
sign transaction in the frontend and pass the funder used to the backend
brianUtn98 Mar 29, 2024
ded7c6d
fix mayority of tests
brianUtn98 Mar 29, 2024
ae3570c
remove injective test to be up to date with main
brianUtn98 Mar 29, 2024
6952c78
fix BE tests
brianUtn98 Mar 29, 2024
d2e4a9c
FE prettier
brianUtn98 Mar 29, 2024
f01e43a
BE prettier
brianUtn98 Mar 29, 2024
9789cbc
fix linter
brianUtn98 Mar 29, 2024
50dcf9e
updated treasury addresses
brianUtn98 Apr 1, 2024
fd5ba47
fix linting
brianUtn98 Apr 1, 2024
797c5f1
Fix algorand claim info identity serialization (#56)
M-Picco Mar 29, 2024
c58d4ec
Add message for EVM wallet selector (#59)
valentinoConti Mar 29, 2024
dab02e0
backend: modifies private key secret format
scnale Apr 1, 2024
429529b
backend: adds types for node v18
scnale Apr 1, 2024
9b8e60c
frontend: use `JSON.parse` to parse private key in test
scnale Apr 1, 2024
59d3d09
backend: prettier run
scnale Apr 1, 2024
26c3afa
all: replaces token dispenser program id env var with constant
scnale Apr 1, 2024
9830c93
rebase branch
brianUtn98 Apr 1, 2024
4952b19
update toStringWithDecimals from 9 to 6
solanoepalacio Apr 1, 2024
86eea3c
remove injective test
brianUtn98 Apr 1, 2024
7313386
fix yarn.lock
brianUtn98 Apr 1, 2024
bc3d830
fix backend prettier
brianUtn98 Apr 1, 2024
15317df
frontend fix prettier
brianUtn98 Apr 1, 2024
32dcd1c
token dispenser fix prettier
brianUtn98 Apr 1, 2024
6537760
run pre-commit locally
brianUtn98 Apr 1, 2024
3255cfe
linter
brianUtn98 Apr 1, 2024
c7656c5
added solana/web3 dep
brianUtn98 Apr 1, 2024
9396a85
multi-treasury deployment 03
solanoepalacio Apr 1, 2024
0125746
use tokenDispenserProgramId from same workspace
brianUtn98 Apr 1, 2024
1735ed7
prettier
brianUtn98 Apr 1, 2024
2b75243
remove dep between front and back
brianUtn98 Apr 1, 2024
337cd6f
update treasuries and funders
brianUtn98 Apr 1, 2024
818d21b
frontend prettier
brianUtn98 Apr 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
ENDPOINT: http://localhost:8899

env:
PROGRAM_ID: WabZqXyytFA2XeXswf9DdQkQuSZuRiEgKdDmq7c5Mnp
PROGRAM_ID: WApA1JC9eJLaULc2Ximo5TffuqCESzf47JZsuhYvfzC

defaults:
run:
Expand Down
52 changes: 38 additions & 14 deletions backend/src/handlers/fund-transactions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import NodeWallet from '@coral-xyz/anchor/dist/cjs/nodewallet'
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda'
import { getFundingKey } from '../utils/secrets'
import { getFundingKeys } from '../utils/secrets'
import {
checkTransactions,
deserializeTransactions
Expand All @@ -12,7 +12,7 @@ import { asJsonResponse } from '../utils/response'

export type FundTransactionRequest = Uint8Array[]

let funderWallet: NodeWallet
const funderWallets: Record<string, NodeWallet> = {}

export const fundTransactions = async (
event: APIGatewayProxyEvent
Expand All @@ -21,15 +21,29 @@ export const fundTransactions = async (
const requestBody = JSON.parse(event.body!)
validateFundTransactions(requestBody)
const transactions = deserializeTransactions(requestBody)
const isTransactionsValid = await checkTransactions(transactions)
const isTransactionsValid = await checkTransactions(
transactions.map((txWithFunder) => txWithFunder.transaction)
)

if (!isTransactionsValid) {
return asJsonResponse(403, { error: 'Unauthorized transactions' })
}

const wallet = await loadFunderWallet()
const wallets = await loadFunderWallets()

const signedTransactions: VersionedTransaction[] = []

for (const txWithFunder of transactions) {
const funderWallet = wallets[txWithFunder.funder]
if (!funderWallet) {
return asJsonResponse(403, { error: 'Unauthorized funder' })
}

signedTransactions.push(
await funderWallet.signTransaction(txWithFunder.transaction)
)
}

const signedTransactions = await wallet.signAllTransactions(transactions)
logSignatures(signedTransactions)
return asJsonResponse(
200,
Expand All @@ -56,19 +70,29 @@ function validateFundTransactions(transactions: unknown) {
}
}

async function loadFunderWallet(): Promise<NodeWallet> {
if (funderWallet) {
return funderWallet
async function loadFunderWallets(): Promise<Record<string, NodeWallet>> {
if (Object.keys(funderWallets).length > 0) {
return funderWallets
}

const secretData = await getFundingKey()
const funderWalletKey = secretData.key
const secretData = await getFundingKeys()
const funderWalletKeys = Object.values(secretData)

const keypairs = funderWalletKeys.map((key) => {
scnale marked this conversation as resolved.
Show resolved Hide resolved
const parsedKey = key
.toString()
.replace('[', '')
.replace(']', '')
scnale marked this conversation as resolved.
Show resolved Hide resolved
.split(',')
.map((l) => parseInt(l))
return Keypair.fromSecretKey(Uint8Array.from(parsedKey))
})

const keypair = Keypair.fromSecretKey(Uint8Array.from(funderWalletKey))
keypairs.forEach((keypair) => {
funderWallets[keypair.publicKey.toBase58()] = new NodeWallet(keypair)
})

funderWallet = new NodeWallet(keypair)
console.log('Loaded funder wallet')
return funderWallet
return funderWallets
}

function getSignature(tx: VersionedTransaction): string {
Expand Down
23 changes: 20 additions & 3 deletions backend/src/utils/fund-transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,29 @@ const SET_COMPUTE_UNIT_PRICE_DISCRIMINANT = 3

const MAX_COMPUTE_UNIT_PRICE = BigInt(1_000_000)

export type TransactionWithFunder = {
transaction: VersionedTransaction
funder: string
}

export type SerializedTransactionWithFunder = {
tx: Uint8Array
funder: string
}

export function deserializeTransactions(
abhidtu2014 marked this conversation as resolved.
Show resolved Hide resolved
transactions: unknown
): VersionedTransaction[] {
): TransactionWithFunder[] {
try {
return (transactions as Uint8Array[]).map((serializedTx) =>
VersionedTransaction.deserialize(Buffer.from(serializedTx))
return (transactions as SerializedTransactionWithFunder[]).map(
(serializedTx) => {
return {
transaction: VersionedTransaction.deserialize(
Buffer.from(serializedTx.tx)
),
funder: serializedTx.funder
}
}
)
} catch (err) {
console.error('Failed to deserialize transactions', err)
Expand Down
18 changes: 13 additions & 5 deletions backend/src/utils/secrets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,23 @@ export async function getDispenserKey() {
return { key: JSON.parse(key) }
}

export async function getFundingKey(): Promise<{ key: Uint8Array }> {
let key: string
export async function getFundingKeys(): Promise<Record<string, Uint8Array>> {
let keys: Record<string, Uint8Array> = {}
if (config.keys.funding.key) {
console.log('Using funding key from config')
key = config.keys.funding.key
// TODO: Is this ok??
scnale marked this conversation as resolved.
Show resolved Hide resolved
const privKey = Uint8Array.from(
config.keys.funding.key.split('').map((l) => l.charCodeAt(0))
)
keys = {
key: privKey
}

return keys
}

key = await getSecretKey(config.keys.funding.secretName, 'key')
return { key: JSON.parse(key) }
keys = await getSecret(config.keys.funding.secretName)
return keys
}

export async function getSecretKey(secretName: string, keyName: string) {
Expand Down
11 changes: 9 additions & 2 deletions backend/test/handlers/fund-transactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ const givenDownstreamServicesWork = () => {
server.use(
http.all('https://secretsmanager.us-east-2.amazonaws.com', () => {
return HttpResponse.json({
SecretString: JSON.stringify({ key: `[${[...FUNDER_KEY.secretKey]}]` })
SecretString: JSON.stringify({ keys: `[${[...FUNDER_KEY.secretKey]}]` })
})
})
)
Expand All @@ -238,7 +238,14 @@ const givenDownstreamServicesWork = () => {

const whenFundTransactionsCalled = async () => {
response = await fundTransactions({
body: JSON.stringify(input.map((tx) => Buffer.from(tx.serialize())))
body: JSON.stringify(
input.map((tx) => {
return {
tx: Buffer.from(tx.serialize()),
funder: FUNDER_KEY.publicKey
}
})
)
} as unknown as APIGatewayProxyEvent)
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ FUNDER_KEYPAIR=[145,197,43,77,224,103,196,174,132,195,48,31,177,97,237,163,15,19
DEPLOYER_WALLET=[145,197,43,77,224,103,196,174,132,195,48,31,177,97,237,163,15,196,217,142,181,204,104,107,98,82,213,0,155,140,218,180,30,119,201,38,51,176,207,221,193,222,235,244,163,250,125,66,68,196,45,208,212,201,232,178,100,163,24,21,106,83,66,174]


PROGRAM_ID=WabZqXyytFA2XeXswf9DdQkQuSZuRiEgKdDmq7c5Mnp
PROGRAM_ID=WApA1JC9eJLaULc2Ximo5TffuqCESzf47JZsuhYvfzC
CSV_DIR=/tmp

# Datadog Event Subscriber Configs
Expand Down
30 changes: 6 additions & 24 deletions frontend/claim_sdk/idl/token_dispenser.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,7 @@
{
"name": "mint",
"isMut": false,
"isSigner": false,
"docs": ["Mint of the treasury"]
},
{
"name": "treasury",
"isMut": false,
"isSigner": false,
"docs": [
"Treasury token account. This is an externally owned token account and",
"the owner of this account will approve the config as a delegate using the",
"solana CLI command `spl-token approve <treasury_account_address> <approve_amount> <config_address>`"
]
"isSigner": false
},
{
"name": "systemProgram",
Expand All @@ -56,10 +45,6 @@
"name": "dispenserGuard",
"type": "publicKey"
},
{
"name": "funder",
"type": "publicKey"
},
{
"name": "maxTransfer",
"type": "u64"
Expand Down Expand Up @@ -164,18 +149,10 @@
"name": "mint",
"type": "publicKey"
},
{
"name": "treasury",
"type": "publicKey"
},
{
"name": "addressLookupTable",
"type": "publicKey"
},
{
"name": "funder",
"type": "publicKey"
},
{
"name": "maxTransfer",
"type": "u64"
Expand Down Expand Up @@ -584,6 +561,11 @@
{
"name": "ClaimEvent",
"fields": [
{
"name": "treasury",
"type": "publicKey",
"index": false
},
{
"name": "remainingBalance",
"type": "u64",
Expand Down
56 changes: 10 additions & 46 deletions frontend/claim_sdk/idl/token_dispenser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,6 @@ export type TokenDispenser = {
name: 'mint'
isMut: false
isSigner: false
docs: ['Mint of the treasury']
},
{
name: 'treasury'
isMut: false
isSigner: false
docs: [
'Treasury token account. This is an externally owned token account and',
'the owner of this account will approve the config as a delegate using the',
'solana CLI command `spl-token approve <treasury_account_address> <approve_amount> <config_address>`'
]
},
{
name: 'systemProgram'
Expand All @@ -56,10 +45,6 @@ export type TokenDispenser = {
name: 'dispenserGuard'
type: 'publicKey'
},
{
name: 'funder'
type: 'publicKey'
},
{
name: 'maxTransfer'
type: 'u64'
Expand Down Expand Up @@ -164,18 +149,10 @@ export type TokenDispenser = {
name: 'mint'
type: 'publicKey'
},
{
name: 'treasury'
type: 'publicKey'
},
{
name: 'addressLookupTable'
type: 'publicKey'
},
{
name: 'funder'
type: 'publicKey'
},
{
name: 'maxTransfer'
type: 'u64'
Expand Down Expand Up @@ -584,6 +561,11 @@ export type TokenDispenser = {
{
name: 'ClaimEvent'
fields: [
{
name: 'treasury'
type: 'publicKey'
index: false
},
{
name: 'remainingBalance'
type: 'u64'
Expand Down Expand Up @@ -675,17 +657,6 @@ export const IDL: TokenDispenser = {
name: 'mint',
isMut: false,
isSigner: false,
docs: ['Mint of the treasury'],
},
{
name: 'treasury',
isMut: false,
isSigner: false,
docs: [
'Treasury token account. This is an externally owned token account and',
'the owner of this account will approve the config as a delegate using the',
'solana CLI command `spl-token approve <treasury_account_address> <approve_amount> <config_address>`',
],
},
{
name: 'systemProgram',
Expand All @@ -709,10 +680,6 @@ export const IDL: TokenDispenser = {
name: 'dispenserGuard',
type: 'publicKey',
},
{
name: 'funder',
type: 'publicKey',
},
{
name: 'maxTransfer',
type: 'u64',
Expand Down Expand Up @@ -817,18 +784,10 @@ export const IDL: TokenDispenser = {
name: 'mint',
type: 'publicKey',
},
{
name: 'treasury',
type: 'publicKey',
},
{
name: 'addressLookupTable',
type: 'publicKey',
},
{
name: 'funder',
type: 'publicKey',
},
{
name: 'maxTransfer',
type: 'u64',
Expand Down Expand Up @@ -1237,6 +1196,11 @@ export const IDL: TokenDispenser = {
{
name: 'ClaimEvent',
fields: [
{
name: 'treasury',
type: 'publicKey',
index: false,
},
{
name: 'remainingBalance',
type: 'u64',
Expand Down
Loading
Loading