feat(server): ProposalKind ::GrantWalletAccess and ::ApproveServerUpdate
Some checks failed
ci/woodpecker/pr/server-lint Pipeline failed
ci/woodpecker/pr/server-audit Pipeline was successful
ci/woodpecker/pr/server-vet Pipeline failed
ci/woodpecker/pr/server-test Pipeline was successful

This commit is contained in:
CleverWild
2026-06-13 15:51:22 +02:00
parent 0b331d90bf
commit 514a4cb2d1
4 changed files with 173 additions and 2 deletions

View File

@@ -17,18 +17,29 @@ pub const DEFAULT_TTL_SECS: i64 = 7 * 24 * 60 * 60; // 7 days
#[derive(Debug, Clone)]
pub enum ProposalKind {
ApproveSdkClient { client_id: i32 },
GrantWalletAccess { wallet_id: i32, client_id: i32 },
ApproveServerUpdate,
}
impl ProposalKind {
pub const fn kind_str(&self) -> &'static str {
match self {
Self::ApproveSdkClient { .. } => "approve_sdk_client",
Self::GrantWalletAccess { .. } => "grant_wallet_access",
Self::ApproveServerUpdate => "approve_server_update",
}
}
pub fn encode_payload(&self) -> Vec<u8> {
match self {
Self::ApproveSdkClient { client_id } => client_id.to_be_bytes().to_vec(),
Self::GrantWalletAccess { wallet_id, client_id } => {
let mut buf = Vec::with_capacity(8);
buf.extend_from_slice(&wallet_id.to_be_bytes());
buf.extend_from_slice(&client_id.to_be_bytes());
buf
}
Self::ApproveServerUpdate => vec![],
}
}
@@ -41,6 +52,15 @@ impl ProposalKind {
client_id: i32::from_be_bytes(bytes),
})
}
"grant_wallet_access" => {
let bytes = <[u8; 8]>::try_from(payload)
.map_err(|_| "invalid payload for grant_wallet_access".to_owned())?;
Ok(Self::GrantWalletAccess {
wallet_id: i32::from_be_bytes(bytes[..4].try_into().unwrap()),
client_id: i32::from_be_bytes(bytes[4..].try_into().unwrap()),
})
}
"approve_server_update" => Ok(Self::ApproveServerUpdate),
other => Err(format!("unknown proposal kind: {other}")),
}
}
@@ -365,9 +385,30 @@ impl ProposalManager {
ProposalKind::ApproveSdkClient { client_id } => {
self.execute_approve_sdk_client(client_id).await
}
ProposalKind::GrantWalletAccess { wallet_id, client_id } => {
self.execute_grant_wallet_access(wallet_id, client_id).await
}
ProposalKind::ApproveServerUpdate => Ok(()),
}
}
async fn execute_grant_wallet_access(&self, wallet_id: i32, client_id: i32) -> Result<(), Error> {
use crate::db::models::EvmWalletId;
let mut conn = self.db.get().await.map_err(Error::DatabaseConnection)?;
diesel::insert_into(schema::evm_wallet_access::table)
.values((
schema::evm_wallet_access::wallet_id.eq(EvmWalletId::from_raw(wallet_id)),
schema::evm_wallet_access::client_id.eq(client_id),
))
.execute(&mut conn)
.await
.map_err(|e| Error::ExecutionFailed(format!("grant wallet access: {e}")))?;
Ok(())
}
async fn execute_approve_sdk_client(&self, client_id: i32) -> Result<(), Error> {
use arbiter_crypto::authn;
use crate::{

View File

@@ -48,6 +48,11 @@ async fn handle_create(
Some(ProtoKind::ApproveSdkClient(p)) => ProposalKind::ApproveSdkClient {
client_id: p.client_id,
},
Some(ProtoKind::GrantWalletAccess(p)) => ProposalKind::GrantWalletAccess {
wallet_id: p.wallet_id,
client_id: p.client_id,
},
Some(ProtoKind::ApproveServerUpdate(_)) => ProposalKind::ApproveServerUpdate,
None => return Err(Status::invalid_argument("Missing proposal kind")),
};
let ttl_secs = req.ttl_secs.map(i64::from);