Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ pub unsafe extern "C" fn platform_wallet_register_identity_with_signer(
));

let option = PLATFORM_WALLET_STORAGE.with_item(wallet_handle, |wallet| {
let identity_wallet = wallet.identity().clone();
let wallet = wallet.clone();

let placeholder = Identity::V0(IdentityV0 {
id: Identifier::default(),
Expand All @@ -455,7 +455,10 @@ pub unsafe extern "C" fn platform_wallet_register_identity_with_signer(
let address_signer: &VTableSigner =
unsafe { &*(signer_address_addr as *const VTableSigner) };

identity_wallet
// The composite registers the identity AND reconciles the
// spent funding addresses' platform-address balances from
// the proof.
wallet
.register_from_addresses(
&placeholder,
input_map,
Expand Down
34 changes: 15 additions & 19 deletions packages/rs-platform-wallet-ffi/src/identity_top_up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
//!
//! Mirrors [`crate::identity_registration_with_signer`] (registration)
//! but for an *existing* identity. The single entry point —
//! [`platform_wallet_top_up_from_addresses_with_signer`] — wraps
//! [`IdentityWallet::top_up_from_addresses`](platform_wallet::IdentityWallet::top_up_from_addresses)
//! [`platform_wallet_top_up_from_addresses_with_signer`] — wraps the
//! composite
//! [`PlatformWallet::top_up_from_addresses`](platform_wallet::PlatformWallet::top_up_from_addresses)
//! and reuses the same address-input shape (`IdentityFundingInputFFI`)
//! the registration FFI exposes.
//!
Expand All @@ -17,10 +18,10 @@
//!
//! On success the function writes the post-transition credit balance
//! back through `out_new_balance`. The local `ManagedIdentity`
//! manager is updated synchronously inside the library call (see
//! [`top_up_from_addresses`](platform_wallet::IdentityWallet::top_up_from_addresses)
//! for the bookkeeping); callers can re-read the balance via
//! `ManagedIdentity` once this returns.
//! manager is updated and the spent platform-address balances are
//! reconciled synchronously inside the composite library call;
//! callers can re-read the balance via `ManagedIdentity` once this
//! returns.

use std::collections::BTreeMap;
use std::slice;
Expand Down Expand Up @@ -117,22 +118,17 @@ pub unsafe extern "C" fn platform_wallet_top_up_from_addresses_with_signer(
let signer_addr = signer_address_handle as usize;

let option = PLATFORM_WALLET_STORAGE.with_item(wallet_handle, |wallet| {
let identity_wallet = wallet.identity().clone();
let platform_wallet = wallet.platform().clone();
let wallet = wallet.clone();
block_on_worker(async move {
let address_signer: &VTableSigner = unsafe { &*(signer_addr as *const VTableSigner) };
let (address_infos, new_balance) = identity_wallet
// The composite tops up the identity AND reconciles the spent
// platform-address balances from the proof, so the wallet's
// displayed balance and next input selection reflect the spend
// (covering addresses restored from disk that are no longer in
// a live derived pool).
wallet
.top_up_from_addresses(&identity_id, input_map, address_signer, None)
.await?;
// Reconcile the spent platform-address balances from the proof so
// the wallet's displayed balance and next input selection reflect
// the spend. Resolves spent addresses via the address provider, so
// it covers addresses restored from disk that are no longer in a
// live derived pool.
platform_wallet
.apply_top_up_reconciliation(&address_infos)
.await;
Ok::<_, platform_wallet::PlatformWalletError>(new_balance)
.await
})
});
let result = unwrap_option_or_return!(option);
Expand Down
13 changes: 9 additions & 4 deletions packages/rs-platform-wallet-ffi/src/identity_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@ pub unsafe extern "C" fn platform_wallet_transfer_credits_with_signer(
/// [`PlatformAddressCreditOutputFFI`] recipients using the supplied
/// `signer_handle`.
///
/// Wraps
/// [`IdentityWallet::transfer_credits_to_addresses_with_external_signer`](platform_wallet::IdentityWallet::transfer_credits_to_addresses_with_external_signer).
/// Wraps the composite
/// [`PlatformWallet::transfer_credits_to_addresses_with_external_signer`](platform_wallet::PlatformWallet::transfer_credits_to_addresses_with_external_signer),
/// which also reconciles wallet-owned recipient addresses' platform
/// balances from the transfer proof.
///
/// `out_new_balance` (when non-null) receives the sender's remaining
/// balance after the transfer.
Expand Down Expand Up @@ -149,10 +151,13 @@ pub unsafe extern "C" fn platform_wallet_transfer_credits_to_addresses_with_sign
let signer_addr = signer_handle as usize;

let option = PLATFORM_WALLET_STORAGE.with_item(wallet_handle, |wallet| {
let identity_wallet = wallet.identity().clone();
let wallet = wallet.clone();
block_on_worker(async move {
let signer: &VTableSigner = &*(signer_addr as *const VTableSigner);
identity_wallet
// The composite transfers the credits AND reconciles any
// wallet-owned recipient addresses' platform balances from
// the proof (third-party recipients are skipped).
wallet
.transfer_credits_to_addresses_with_external_signer(
&from_id, output_map, signer, None,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ impl IdentityWallet {
/// DIP-9 auth pubkeys) and both signers; the wallet struct
/// carries no key material.
///
/// Returns the registered identity alongside the proof-attested
/// post-spend `AddressInfos` for the funding addresses. Prefer the
/// composite [`PlatformWallet::register_from_addresses`], which feeds
/// the returned `AddressInfos` through
/// [`PlatformAddressWallet::reconcile_address_infos`] so the spent
/// balances and advanced nonces are reflected locally without waiting
/// for the next BLAST sync round.
///
/// [`PlatformWallet::register_from_addresses`]:
/// crate::wallet::PlatformWallet::register_from_addresses
/// [`PlatformAddressWallet::reconcile_address_infos`]:
/// crate::wallet::PlatformAddressWallet::reconcile_address_infos
///
/// # Arguments
///
/// * `identity` — fully-constructed placeholder identity (with
Expand Down Expand Up @@ -74,7 +87,7 @@ impl IdentityWallet {
identity_signer: &IS,
input_address_signer: &AS,
settings: Option<PutSettings>,
) -> Result<Identity, PlatformWalletError> {
) -> Result<(Identity, dash_sdk::query_types::AddressInfos), PlatformWalletError> {
if inputs.is_empty() {
return Err(PlatformWalletError::InvalidIdentityData(
"At least one input address is required".to_string(),
Expand All @@ -84,7 +97,7 @@ impl IdentityWallet {
// Route through the auto-fetching SDK variant so the caller
// doesn't need to maintain its own nonce cache — Platform is
// always the source of truth at submit time.
let (mut registered_identity, _address_infos) = identity
let (mut registered_identity, address_infos) = identity
.put_with_address_funding_fetching_nonces(
&self.sdk,
inputs,
Expand Down Expand Up @@ -136,12 +149,10 @@ impl IdentityWallet {
)?;
}

// TODO(platform-wallet): mirror `transfer()` and push the
// returned `address_infos` through the platform-address
// balance cache so SwiftData reflects the spent balances +
// advanced nonces immediately. For now the next BLAST sync
// round refreshes them.

Ok(identity)
// The spent platform-address balances are reconciled by the
// composite `PlatformWallet::register_from_addresses`, which routes
// the returned `AddressInfos` through the platform-address wallet's
// shared reconciliation seam.
Ok((identity, address_infos))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,20 @@ impl IdentityWallet {
/// Uses the `TopUpIdentityFromAddresses` SDK trait. Address nonces are
/// looked up automatically.
///
/// Returns the proof-attested post-spend `AddressInfos` alongside the new
/// identity balance. The caller MUST reconcile the spent platform-address
/// balances from the `AddressInfos` via
/// [`PlatformAddressWallet::apply_top_up_reconciliation`] — this method
/// only owns the identity-side balance update, because resolving a spent
/// address back to its derivation index needs the address provider, which
/// lives on the platform-address wallet (and covers addresses restored
/// from disk that are no longer in a live derived pool).
/// This method owns only the identity-side balance update and returns
/// the proof-attested post-spend `AddressInfos` alongside the new
/// identity balance. Prefer the composite
/// [`PlatformWallet::top_up_from_addresses`], which feeds the returned
/// `AddressInfos` through
/// [`PlatformAddressWallet::reconcile_address_infos`] — the
/// platform-address wallet holds the address provider needed to map a
/// spent address back to its derivation index (including addresses
/// restored from disk that are no longer in a live derived pool).
///
/// [`PlatformWallet::top_up_from_addresses`]:
/// crate::wallet::PlatformWallet::top_up_from_addresses
/// [`PlatformAddressWallet::reconcile_address_infos`]:
/// crate::wallet::PlatformAddressWallet::reconcile_address_infos
///
/// # Arguments
///
Expand Down Expand Up @@ -100,10 +106,10 @@ impl IdentityWallet {
}
}

// The spent platform-address balances are reconciled by the caller via
// `PlatformAddressWallet::apply_top_up_reconciliation`, which has the
// address provider needed to map restored addresses back to their
// derivation index.
// The spent platform-address balances are reconciled by the
// composite `PlatformWallet::top_up_from_addresses`, which routes
// the returned `AddressInfos` through the platform-address wallet's
// shared reconciliation seam.
Ok((address_infos, new_balance))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,26 @@ impl IdentityWallet {
///
/// Signing is routed through the supplied `&S: Signer<IdentityPublicKey>`.
/// Required for external-signable wallets.
///
/// Returns the proof-attested post-transfer `AddressInfos` for the
/// recipient addresses alongside the sender's new balance. Prefer the
/// composite [`PlatformWallet::transfer_credits_to_addresses_with_external_signer`],
/// which feeds the returned `AddressInfos` through
/// [`PlatformAddressWallet::reconcile_address_infos`] so recipients
/// owned by this wallet see their new balance immediately instead of
/// waiting for the next BLAST sync round.
///
/// [`PlatformWallet::transfer_credits_to_addresses_with_external_signer`]:
/// crate::wallet::PlatformWallet::transfer_credits_to_addresses_with_external_signer
/// [`PlatformAddressWallet::reconcile_address_infos`]:
/// crate::wallet::PlatformAddressWallet::reconcile_address_infos
pub async fn transfer_credits_to_addresses_with_external_signer<S>(
&self,
identity_id: &Identifier,
recipient_addresses: BTreeMap<PlatformAddress, Credits>,
signer: &S,
settings: Option<PutSettings>,
) -> Result<Credits, PlatformWalletError>
) -> Result<(dash_sdk::query_types::AddressInfos, Credits), PlatformWalletError>
where
S: Signer<IdentityPublicKey> + Send + Sync,
{
Expand All @@ -87,7 +100,7 @@ impl IdentityWallet {
.ok_or(PlatformWalletError::IdentityNotFound(*identity_id))?
};

let (_address_infos, new_balance) = identity
let (address_infos, new_balance) = identity
.transfer_credits_to_addresses(
&self.sdk,
recipient_addresses,
Expand Down Expand Up @@ -126,6 +139,10 @@ impl IdentityWallet {
}
}

Ok(new_balance)
// Recipient platform-address balances are reconciled by the
// composite `PlatformWallet::transfer_credits_to_addresses_with_external_signer`,
// which routes the returned `AddressInfos` through the
// platform-address wallet's shared reconciliation seam.
Ok((address_infos, new_balance))
}
}
Loading
Loading