Skip to content

Commit

Permalink
feat: Register favourite
Browse files Browse the repository at this point in the history
  • Loading branch information
Arrowana authored and dr497 committed Mar 1, 2024
1 parent ad836ce commit a854954
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust-crates/sns-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ console = "0.15.5"
sns-sdk = { version = "1.3.5", path = "../sns-sdk" }
walkdir = "2.3.3"
borsh = "0.9"
bincode = "1.3.3"

[[bin]]
name = "sns"
Expand Down
94 changes: 93 additions & 1 deletion rust-crates/sns-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{fs::File, time::Duration};

use sns_sdk::record;
use sns_sdk::{favourite_domain::register_favourite::Accounts, record, NAME_OFFERS_PROGRAM_ID};
use solana_sdk::{bs58, signature::Keypair, system_program};

use {
anyhow::anyhow,
Expand Down Expand Up @@ -78,6 +79,21 @@ enum Commands {
#[arg(long, short, help = "Optional custom RPC URL")]
url: Option<String>,
},
#[command(arg_required_else_help = true, about = "Register a favourite domain")]
RegisterFavourite {
#[arg(
required = true,
help = "The path to the wallet private key used to set the favourite domain or an owner wallet"
)]
owner: String,
#[arg(
required = true,
help = "The list of domains to transfer with or without .sol suffix"
)]
domain: String,
#[arg(long, short, help = "Optional custom RPC URL")]
url: Option<String>,
},
#[command(
arg_required_else_help = true,
about = "Transfer a list of domains to a new owner"
Expand Down Expand Up @@ -509,6 +525,79 @@ async fn process_register(
Ok(())
}

enum OwnerKind {
Keypair(Keypair),
Pubkey(Pubkey),
}

impl OwnerKind {
fn owner(&self) -> Pubkey {
match self {
OwnerKind::Keypair(keypair) => keypair.pubkey(),
OwnerKind::Pubkey(pk) => *pk,
}
}
}

async fn process_register_favourite(
rpc_client: &RpcClient,
owner_keypair_path_or_address: &str,
domain: &str,
) -> CliResult {
println!("Registering favourite domain...");
let owner_kind = {
match read_keypair_file(owner_keypair_path_or_address) {
Ok(kp) => OwnerKind::Keypair(kp),
Err(e) => match Pubkey::from_str(&owner_keypair_path_or_address) {
Ok(owner) => OwnerKind::Pubkey(owner),
Err(parse_pk_error) => {
return Err(anyhow!(
"Owner was not a valid keypair nor a valid address: {e:?}, {parse_pk_error:?}"
)
.into())
}
},
}
};
let owner = owner_kind.owner();
let domain_key = get_domain_key(&domain)?;
let ix = sns_sdk::favourite_domain::get_register_favourite_instruction(
NAME_OFFERS_PROGRAM_ID,
Accounts {
owner: &owner,
name: &domain_key,
favourite_domain: &sns_sdk::favourite_domain::derive_favourite_domain_key(&owner),
system_program: &system_program::ID,
},
sns_sdk::favourite_domain::register_favourite::Params {},
);
let blockhash = rpc_client.get_latest_blockhash().await?;

match owner_kind {
OwnerKind::Keypair(keypair) => {
let tx = Transaction::new_signed_with_payer(
&[ix],
Some(&keypair.pubkey()),
&[&keypair],
blockhash,
);
let sig = rpc_client.send_and_confirm_transaction(&tx).await?;
println!("Favourite set, txid: {sig}");
}
OwnerKind::Pubkey(_) => {
let mut tx = Transaction::new_with_payer(&[ix.clone()], Some(&owner));
tx.message.recent_blockhash = blockhash;

println!(
"base58 register favourite tx: {}",
bs58::encode(bincode::serialize(&tx).unwrap()).into_string()
);
}
}

Ok(())
}

async fn process_record_set(
rpc_client: &RpcClient,
domain: &str,
Expand Down Expand Up @@ -750,6 +839,9 @@ async fn main() {
space,
url,
} => process_register(&get_rpc_client(url), &keypair_path, domains, space).await,
Commands::RegisterFavourite { owner, domain, url } => {
process_register_favourite(&get_rpc_client(url), &owner, &domain).await
}
Commands::Record(RecordCommand { cmd }) => match cmd {
RecordSubCommand::Get { domain, record } => {
process_record_get(&get_rpc_client(None), &domain, &record).await
Expand Down
36 changes: 35 additions & 1 deletion rust-crates/sns-sdk/src/favourite_domain.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::io::ErrorKind;

use bonfida_utils::InstructionsAccount;
use borsh::BorshDeserialize;
use solana_program::pubkey::Pubkey;
use solana_sdk::instruction::Instruction;

use crate::NAME_OFFERS_PROGRAM_ID;

pub(crate) fn derive_favorite_domain_key(owner: &Pubkey) -> Pubkey {
pub fn derive_favourite_domain_key(owner: &Pubkey) -> Pubkey {
Pubkey::find_program_address(
&[b"favourite_domain", &owner.to_bytes()],
&NAME_OFFERS_PROGRAM_ID,
Expand Down Expand Up @@ -38,3 +40,35 @@ impl FavouriteDomain {
}
}
}

pub mod register_favourite {
use bonfida_utils::{BorshSize, InstructionsAccount};
use borsh::{BorshDeserialize, BorshSerialize};
use solana_sdk::pubkey::Pubkey;

#[derive(InstructionsAccount)]
/// The required accounts for the `create` instruction
pub struct Accounts<'a, T> {
/// The name account
#[cons(writable)]
pub name: &'a T,
#[cons(writable)]
pub favourite_domain: &'a T,
#[cons(writable, signer)]
pub owner: &'a T,
pub system_program: &'a T,
}

#[derive(BorshDeserialize, BorshSerialize, BorshSize, Clone, Copy)]
#[cfg_attr(feature = "instruction_params_casting", derive(Zeroable, Pod))]
#[repr(C)]
pub struct Params {}
}

pub fn get_register_favourite_instruction(
program_id: Pubkey,
accounts: register_favourite::Accounts<Pubkey>,
params: register_favourite::Params,
) -> Instruction {
accounts.get_instruction(program_id, 6, params)
}
4 changes: 2 additions & 2 deletions rust-crates/sns-sdk/src/non_blocking/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
ROOT_DOMAIN_ACCOUNT,
},
error::SnsError,
favourite_domain::{derive_favorite_domain_key, FavouriteDomain},
favourite_domain::{derive_favourite_domain_key, FavouriteDomain},
record::{get_record_key, record_v1::check_sol_record, Record},
};

Expand Down Expand Up @@ -386,7 +386,7 @@ pub async fn get_favourite_domain(
rpc_client: &RpcClient,
owner: &Pubkey,
) -> Result<Option<Pubkey>, SnsError> {
let favourite_domain_state_key = derive_favorite_domain_key(owner);
let favourite_domain_state_key = derive_favourite_domain_key(owner);
let account = rpc_client
.get_account_with_commitment(&favourite_domain_state_key, rpc_client.commitment())
.await?
Expand Down

0 comments on commit a854954

Please sign in to comment.