Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
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.

32 changes: 32 additions & 0 deletions packages/js-evo-sdk/src/dpns/facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,38 @@ export class DpnsFacade {
return w.dpnsResolveName(name);
}

/**
* Register a DPNS username on Dash Platform.
*
* Two parameter styles are supported:
*
* **Style A - Typed objects (full control):**
* ```typescript
* const identity = await sdk.identities.fetch(identityId);
* const identityKey = identity.getPublicKeyById(publicKeyId);
* const signer = new IdentitySigner();
* signer.addKeyFromWif(privateKeyWif);
*
* await sdk.dpns.registerName({
* label: 'alice',
* identity,
* identityKey,
* signer,
* });
* ```
*
* **Style B - Simple credentials (convenience):**
* ```typescript
* await sdk.dpns.registerName({
* label: 'alice',
* identityId: '...', // Identity ID (string, Identifier, or bytes)
* publicKeyId: 1, // Key index on the identity
* privateKey: bytes, // 32-byte Uint8Array
* });
* ```
*
* Style B automatically fetches the identity and retrieves the public key internally.
*/
async registerName(options: wasm.DpnsRegisterNameOptions): Promise<wasm.RegisterDpnsNameResult> {
const w = await this.sdk.getWasmSdkConnected();
return w.dpnsRegisterName(options);
Expand Down
3 changes: 3 additions & 0 deletions packages/rs-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ platform-wallet = { path = "../rs-platform-wallet", optional = true }

drive-proof-verifier = { path = "../rs-drive-proof-verifier", default-features = false }
dash-context-provider = { path = "../rs-context-provider", default-features = false }
simple-signer = { path = "../simple-signer", default-features = false, features = [
"state-transitions",
] }
dash-platform-macros = { path = "../rs-dash-platform-macros" }
http = { version = "1.1" }
rustls-pemfile = { version = "2.0.0" }
Expand Down
78 changes: 77 additions & 1 deletion packages/rs-sdk/src/platform/dpns_usernames/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
use dpp::document::{DocumentV0, DocumentV0Getters};
use dpp::identity::accessors::IdentityGettersV0;
use dpp::identity::signer::Signer;
use dpp::identity::{Identity, IdentityPublicKey};
use dpp::identity::{Identity, IdentityPublicKey, KeyID};
use dpp::platform_value::{Bytes32, Value};
use dpp::prelude::Identifier;
use simple_signer::signer::SimpleSigner;
use std::collections::BTreeMap;
use std::sync::Arc;

Expand Down Expand Up @@ -361,6 +362,81 @@ impl Sdk {
})
}

/// Register a DPNS username using simple credentials
///
/// This is a convenience method that accepts simple credential parameters instead of
/// requiring pre-constructed typed objects. It internally fetches the identity,
/// retrieves the public key, and creates the signer.
///
/// # Arguments
///
/// * `label` - The label for the domain (e.g., "alice" for "alice.dash")
/// * `identity_id` - The identifier of the identity that will own the domain
/// * `public_key_id` - The ID of the public key to use for signing
/// * `private_key` - The 32-byte private key corresponding to the public key
/// * `preorder_callback` - Optional callback to be called with the preorder document result
///
/// # Returns
///
/// Returns a `RegisterDpnsNameResult` containing both created documents and the full domain name
///
/// # Errors
///
/// Returns an error if:
/// - The identity cannot be fetched
/// - The public key is not found on the identity
/// - The DPNS contract cannot be fetched
/// - Document creation or submission fails
///
/// # Example
///
/// ```ignore
/// let result = sdk.register_dpns_name_with_credentials(
/// "alice".to_string(),
/// identity_id,
/// 1, // public key ID
/// private_key_bytes,
/// None,
/// ).await?;
/// ```
pub async fn register_dpns_name_with_credentials(
&self,
label: String,
identity_id: Identifier,
public_key_id: KeyID,
private_key: [u8; 32],
preorder_callback: Option<PreorderCallback>,
) -> Result<RegisterDpnsNameResult, Error> {
// Fetch the identity
let identity = Identity::fetch(self, identity_id)
.await?
.ok_or_else(|| Error::Generic(format!("Identity {} not found", identity_id)))?;

// Get the public key by ID
let identity_public_key = identity
.get_public_key_by_id(public_key_id)
.ok_or_else(|| {
Error::Generic(format!(
"Public key with ID {} not found on identity {}",
public_key_id, identity_id
))
})?
.clone();

// Create the signer with the private key
let signer = SimpleSigner::from_private_key(identity_public_key.clone(), private_key);

// Call the existing register method
self.register_dpns_name(RegisterDpnsNameInput {
label,
identity,
identity_public_key,
signer,
preorder_callback,
})
.await
}

/// Check if a DPNS name is available
///
/// # Arguments
Expand Down
71 changes: 70 additions & 1 deletion packages/simple-signer/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ use dpp::{bls_signatures, dashcore, ed25519_dalek, ProtocolError};
use std::collections::BTreeMap;
use std::fmt::{Debug, Formatter};

/// This simple signer is only to be used in tests
/// A simple signer implementation for signing operations with identity keys.
///
/// This signer stores private keys in memory and can be used for both testing
/// and production scenarios where convenience methods are preferred.
#[derive(Default, Clone, PartialEq, Encode, Decode)]
pub struct SimpleSigner {
/// Private keys is a map from the public key to the Private key bytes
Expand Down Expand Up @@ -82,6 +85,72 @@ impl SimpleSigner {
self.address_private_keys_in_creation.extend(keys)
}

/// Add a key from a WIF-encoded private key string.
///
/// This method parses the WIF string and adds the key to the signer.
///
/// # Arguments
///
/// * `identity_public_key` - The identity public key associated with this private key
/// * `wif` - The WIF-encoded private key string
///
/// # Returns
///
/// Returns `Ok(())` if the key was added successfully, or an error if WIF parsing fails.
pub fn add_key_from_wif(
&mut self,
identity_public_key: IdentityPublicKey,
wif: &str,
) -> Result<(), ProtocolError> {
let private_key = dashcore::PrivateKey::from_wif(wif)
.map_err(|e| ProtocolError::Generic(format!("Invalid WIF private key: {}", e)))?;
self.add_identity_public_key(identity_public_key, private_key.inner.secret_bytes());
Ok(())
}

/// Create a new SimpleSigner with a single key loaded from WIF.
///
/// This is a convenience method for creating a signer with a single key.
///
/// # Arguments
///
/// * `identity_public_key` - The identity public key associated with this private key
/// * `wif` - The WIF-encoded private key string
///
/// # Returns
///
/// Returns a new `SimpleSigner` with the key loaded, or an error if WIF parsing fails.
pub fn from_wif(
identity_public_key: IdentityPublicKey,
wif: &str,
) -> Result<Self, ProtocolError> {
let mut signer = Self::default();
signer.add_key_from_wif(identity_public_key, wif)?;
Ok(signer)
}

/// Create a new SimpleSigner with a single key from raw bytes.
///
/// This is a convenience method for creating a signer with a single key
/// when you already have the private key as raw bytes.
///
/// # Arguments
///
/// * `identity_public_key` - The identity public key associated with this private key
/// * `private_key` - The 32-byte private key
///
/// # Returns
///
/// Returns a new `SimpleSigner` with the key loaded.
pub fn from_private_key(
identity_public_key: IdentityPublicKey,
private_key: [u8; 32],
) -> Self {
let mut signer = Self::default();
signer.add_identity_public_key(identity_public_key, private_key);
signer
}

/// Commit keys in creation
pub fn commit_block_keys(&mut self) {
self.private_keys.append(&mut self.private_keys_in_creation);
Expand Down
Loading
Loading