Message processing heavy refactoring
This commit is contained in:
parent
c3e435a228
commit
bc6f95a98f
@ -25,7 +25,8 @@ use sp_client::bitcoin::key::Secp256k1;
|
||||
use sp_client::bitcoin::secp256k1::ecdh::shared_secret_point;
|
||||
use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey};
|
||||
use sp_client::bitcoin::{Amount, Network, OutPoint, Psbt, Transaction, Txid};
|
||||
use sp_client::silentpayments::Error as SpError;
|
||||
use sp_client::silentpayments::utils as sp_utils;
|
||||
use sp_client::silentpayments::{Error as SpError, Network as SpNetwork};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_client::silentpayments::sending::SilentPaymentAddress;
|
||||
@ -34,11 +35,12 @@ use wasm_bindgen::convert::FromWasmAbi;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use sdk_common::network::{
|
||||
self, AnkFlag, AnkNetworkMsg, CachedMessage, CachedMessageStatus, FaucetMessage, NewTxMessage, UnknownMessage
|
||||
self, AnkFlag, AnkNetworkMsg, CachedMessage, CachedMessageStatus, FaucetMessage, NewTxMessage,
|
||||
UnknownMessage,
|
||||
};
|
||||
use sdk_common::silentpayments::{
|
||||
create_transaction, create_transaction_for_address_with_shared_secret,
|
||||
create_transaction_spend_outpoint, map_outputs_to_sp_address
|
||||
create_transaction_spend_outpoint, map_outputs_to_sp_address,
|
||||
};
|
||||
|
||||
use sp_client::spclient::{
|
||||
@ -402,23 +404,29 @@ fn handle_recover_transaction(
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
{
|
||||
}) {
|
||||
let message = messages.get_mut(pos).unwrap();
|
||||
match message.status {
|
||||
CachedMessageStatus::FaucetWaiting => {
|
||||
message.status = CachedMessageStatus::FaucetComplete;
|
||||
message.commited_in = utxo_created.into_iter().next().map(|(outpoint, _)| *outpoint);
|
||||
message.commited_in = utxo_created
|
||||
.into_iter()
|
||||
.next()
|
||||
.map(|(outpoint, _)| *outpoint);
|
||||
return Ok(message.clone());
|
||||
},
|
||||
}
|
||||
// Actually this is unreachable
|
||||
CachedMessageStatus::FaucetComplete => return Ok(message.clone()),
|
||||
_ => ()
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
// we inspect inputs looking for links with previous tx
|
||||
for input in tx.input.iter() {
|
||||
if let Some(pos) = messages.iter().position(|m| {
|
||||
if let Some(pos) = messages
|
||||
.iter()
|
||||
.position(|m| {
|
||||
debug!("{:?}", Some(input.previous_output));
|
||||
m.confirmed_by == Some(input.previous_output)
|
||||
})
|
||||
{
|
||||
@ -426,9 +434,9 @@ fn handle_recover_transaction(
|
||||
// If we are receiver, that's pretty much it, just set status to complete
|
||||
message.status = CachedMessageStatus::Complete;
|
||||
return Ok(message.clone());
|
||||
} else if let Some(pos) = messages.iter().position(|m| {
|
||||
m.commited_in == Some(input.previous_output)
|
||||
})
|
||||
} else if let Some(pos) = messages
|
||||
.iter()
|
||||
.position(|m| m.commited_in == Some(input.previous_output))
|
||||
{
|
||||
// sender needs to spent it back again to receiver
|
||||
let (outpoint, output) = utxo_created.into_iter().next().unwrap();
|
||||
@ -444,9 +452,16 @@ fn handle_recover_transaction(
|
||||
}
|
||||
|
||||
// if we've found nothing we are being notified
|
||||
let shared_point =
|
||||
shared_secret_point(&tweak_data, &sp_wallet.get_client().get_scan_key());
|
||||
let shared_secret = AnkSharedSecret::new(shared_point);
|
||||
let shared_point = sp_utils::receiving::calculate_shared_point(
|
||||
&tweak_data,
|
||||
&sp_wallet.get_client().get_scan_key(),
|
||||
);
|
||||
let shared_secret = AnkSharedSecret::new(PublicKey::from_slice(&shared_point)?);
|
||||
|
||||
debug!(
|
||||
"Shared secret: {}",
|
||||
shared_secret.to_byte_array().to_lower_hex_string()
|
||||
);
|
||||
|
||||
if let Some(cipher_pos) = messages.iter().position(|m| {
|
||||
if m.status != CachedMessageStatus::CipherWaitingTx {
|
||||
@ -454,15 +469,13 @@ fn handle_recover_transaction(
|
||||
}
|
||||
m.try_decrypt_with_shared_secret(shared_secret.to_byte_array())
|
||||
.is_ok()
|
||||
})
|
||||
{
|
||||
}) {
|
||||
let message = messages.get_mut(cipher_pos).unwrap();
|
||||
|
||||
let (outpoint, output) = utxo_created.into_iter().next().unwrap();
|
||||
|
||||
message.commited_in = Some(outpoint.clone());
|
||||
message.shared_secret =
|
||||
Some(shared_secret.to_byte_array().to_lower_hex_string());
|
||||
message.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string());
|
||||
message.commitment = Some(commitment_str);
|
||||
|
||||
let plaintext = message
|
||||
@ -474,16 +487,18 @@ fn handle_recover_transaction(
|
||||
message.recipient = Some(sp_wallet.get_client().get_receiving_address());
|
||||
message.status = CachedMessageStatus::ReceivedMustConfirm;
|
||||
|
||||
return Ok(message.clone())
|
||||
return Ok(message.clone());
|
||||
} else {
|
||||
// store it and wait for the message
|
||||
let mut new_msg = CachedMessage::new();
|
||||
let (outpoint, output) = utxo_created.into_iter().next().expect("utxo_created shouldn't be empty");
|
||||
let (outpoint, output) = utxo_created
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("utxo_created shouldn't be empty");
|
||||
new_msg.commited_in = Some(outpoint.clone());
|
||||
new_msg.commitment = Some(commitment.to_lower_hex_string());
|
||||
new_msg.recipient = Some(sp_wallet.get_client().get_receiving_address());
|
||||
new_msg.shared_secret =
|
||||
Some(shared_secret.to_byte_array().to_lower_hex_string());
|
||||
new_msg.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string());
|
||||
new_msg.status = CachedMessageStatus::TxWaitingCipher;
|
||||
messages.push(new_msg.clone());
|
||||
return Ok(new_msg.clone());
|
||||
@ -491,14 +506,15 @@ fn handle_recover_transaction(
|
||||
} else {
|
||||
// We are sender of a transaction
|
||||
// We only need to return the message
|
||||
if let Some(message) = messages.iter()
|
||||
.find(|m| {
|
||||
m.commitment.as_ref() == Some(&commitment_str)
|
||||
})
|
||||
if let Some(message) = messages
|
||||
.iter()
|
||||
.find(|m| m.commitment.as_ref() == Some(&commitment_str))
|
||||
{
|
||||
return Ok(message.clone());
|
||||
} else {
|
||||
return Err(anyhow::Error::msg("We spent a transaction for a commitment we don't know"));
|
||||
return Err(anyhow::Error::msg(
|
||||
"We spent a transaction for a commitment we don't know",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -577,7 +593,7 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<CachedMessage>
|
||||
AnkFlag::Faucet => unimplemented!(),
|
||||
AnkFlag::Error => {
|
||||
let error_msg = CachedMessage::new_error(ank_msg.content);
|
||||
return Ok(error_msg)
|
||||
return Ok(error_msg);
|
||||
}
|
||||
AnkFlag::Unknown => {
|
||||
// let's try to decrypt with keys we found in transactions but haven't used yet
|
||||
@ -597,16 +613,15 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<CachedMessage>
|
||||
message.plaintext = Some(unknown_msg.message);
|
||||
message.sender = Some(unknown_msg.sender);
|
||||
message.ciphertext = Some(ank_msg.content);
|
||||
message.status = CachedMessageStatus::ReceivedMustConfirm;
|
||||
return Ok(message.clone());
|
||||
} else {
|
||||
// let's keep it in case we receive the transaction later
|
||||
let mut new_msg = CachedMessage::new();
|
||||
new_msg.status = CachedMessageStatus::CipherWaitingTx;
|
||||
new_msg.ciphertext = Some(ank_msg.content);
|
||||
messages.push(new_msg);
|
||||
return Err(ApiError {
|
||||
message: "Can't decrypt message".to_owned(),
|
||||
});
|
||||
messages.push(new_msg.clone());
|
||||
return Ok(new_msg);
|
||||
}
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
@ -679,19 +694,30 @@ pub struct createTransactionReturn {
|
||||
/// This is what we call to answer a confirmation as a sender
|
||||
#[wasm_bindgen]
|
||||
pub fn answer_confirmation_transaction(
|
||||
message: CachedMessage,
|
||||
message_id: u32,
|
||||
fee_rate: u32,
|
||||
) -> ApiResult<createTransactionReturn> {
|
||||
if message.recipient.is_none() || message.confirmed_by.is_none() {
|
||||
return Err(ApiError { message: "Invalid network message".to_owned() });
|
||||
let mut messages = lock_messages()?;
|
||||
let message: &mut CachedMessage;
|
||||
if let Some(m) = messages.iter_mut().find(|m| m.id == message_id) {
|
||||
if m.sender.is_none() || m.commited_in.is_none() {
|
||||
return Err(ApiError {
|
||||
message: "Invalid network message".to_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
message = m;
|
||||
} else {
|
||||
return Err(ApiError { message: format!("Can't find message for id {}", message_id) });
|
||||
}
|
||||
|
||||
let sp_address: SilentPaymentAddress = message.recipient.as_ref().unwrap().as_str().try_into()?;
|
||||
let sp_address: SilentPaymentAddress =
|
||||
message.recipient.as_ref().unwrap().as_str().try_into()?;
|
||||
|
||||
let connected_user = lock_connected_user()?;
|
||||
|
||||
let sp_wallet: &SpWallet;
|
||||
if sp_address.is_testnet() {
|
||||
if sp_address.get_network() != SpNetwork::Mainnet {
|
||||
sp_wallet = connected_user.try_get_recover()?;
|
||||
} else {
|
||||
sp_wallet = connected_user.try_get_main()?;
|
||||
@ -703,38 +729,53 @@ pub fn answer_confirmation_transaction(
|
||||
nb_outputs: 1,
|
||||
};
|
||||
|
||||
let confirmed_by = message.confirmed_by.clone().unwrap();
|
||||
let commited_in = message.commited_in.clone().unwrap();
|
||||
|
||||
let signed_psbt = create_transaction_spend_outpoint(
|
||||
&message.confirmed_by.unwrap(),
|
||||
&confirmed_by,
|
||||
sp_wallet,
|
||||
recipient,
|
||||
Amount::from_sat(fee_rate.into())
|
||||
&commited_in.txid,
|
||||
Amount::from_sat(fee_rate.into()),
|
||||
)?;
|
||||
|
||||
let final_tx = signed_psbt.extract_tx()?;
|
||||
|
||||
message.status = CachedMessageStatus::Complete;
|
||||
|
||||
Ok(createTransactionReturn {
|
||||
txid: final_tx.txid().to_string(),
|
||||
transaction: serialize(&final_tx).to_lower_hex_string(),
|
||||
new_network_msg: message
|
||||
new_network_msg: message.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// This is what we call to confirm as a receiver
|
||||
#[wasm_bindgen]
|
||||
pub fn create_confirmation_transaction(
|
||||
message: CachedMessage,
|
||||
message_id: u32,
|
||||
fee_rate: u32,
|
||||
) -> ApiResult<createTransactionReturn> {
|
||||
if message.sender.is_none() || message.confirmed_by.is_none() {
|
||||
return Err(ApiError { message: "Invalid network message".to_owned() });
|
||||
let mut messages = lock_messages()?;
|
||||
let message: &mut CachedMessage;
|
||||
if let Some(m) = messages.iter_mut().find(|m| m.id == message_id) {
|
||||
if m.sender.is_none() || m.commited_in.is_none() {
|
||||
return Err(ApiError {
|
||||
message: "Invalid network message".to_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
message = m;
|
||||
} else {
|
||||
return Err(ApiError { message: format!("Can't find message for id {}", message_id) });
|
||||
}
|
||||
|
||||
let sp_address: SilentPaymentAddress = message.sender.as_ref().unwrap().as_str().try_into()?;
|
||||
|
||||
let connected_user = lock_connected_user()?;
|
||||
|
||||
let sp_wallet: &SpWallet;
|
||||
if sp_address.is_testnet() {
|
||||
if sp_address.get_network() != SpNetwork::Mainnet {
|
||||
sp_wallet = connected_user.try_get_recover()?;
|
||||
} else {
|
||||
sp_wallet = connected_user.try_get_main()?;
|
||||
@ -746,26 +787,38 @@ pub fn create_confirmation_transaction(
|
||||
nb_outputs: 1,
|
||||
};
|
||||
|
||||
let commited_in = message.commited_in.clone().unwrap();
|
||||
|
||||
let signed_psbt = create_transaction_spend_outpoint(
|
||||
&message.confirmed_by.unwrap(),
|
||||
&commited_in,
|
||||
sp_wallet,
|
||||
recipient,
|
||||
Amount::from_sat(fee_rate.into())
|
||||
&commited_in.txid,
|
||||
Amount::from_sat(fee_rate.into()),
|
||||
)?;
|
||||
|
||||
// what's the vout of the output sent to sender?
|
||||
let sp_address2vouts = map_outputs_to_sp_address(&signed_psbt.to_string())?;
|
||||
let recipients_vouts = sp_address2vouts
|
||||
.get::<String>(&sp_address.into())
|
||||
.expect("recipients didn't change")
|
||||
.as_slice();
|
||||
|
||||
let final_tx = signed_psbt.extract_tx()?;
|
||||
|
||||
message.confirmed_by = Some(OutPoint { txid: final_tx.txid(), vout: recipients_vouts[0] as u32 });
|
||||
|
||||
Ok(createTransactionReturn {
|
||||
txid: final_tx.txid().to_string(),
|
||||
transaction: serialize(&final_tx).to_lower_hex_string(),
|
||||
new_network_msg: message
|
||||
new_network_msg: message.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_notification_transaction(
|
||||
address: String,
|
||||
commitment: Option<String>,
|
||||
message: UnknownMessage,
|
||||
fee_rate: u32,
|
||||
) -> ApiResult<createTransactionReturn> {
|
||||
let sp_address: SilentPaymentAddress = address.as_str().try_into()?;
|
||||
@ -773,7 +826,7 @@ pub fn create_notification_transaction(
|
||||
let connected_user = lock_connected_user()?;
|
||||
|
||||
let sp_wallet: &SpWallet;
|
||||
if sp_address.is_testnet() {
|
||||
if sp_address.get_network() != SpNetwork::Mainnet {
|
||||
sp_wallet = connected_user.try_get_recover()?;
|
||||
} else {
|
||||
sp_wallet = connected_user.try_get_main()?;
|
||||
@ -785,42 +838,47 @@ pub fn create_notification_transaction(
|
||||
nb_outputs: 1,
|
||||
};
|
||||
|
||||
let commitment = create_commitment(serde_json::to_string(&message)?);
|
||||
|
||||
let signed_psbt = create_transaction_for_address_with_shared_secret(
|
||||
recipient,
|
||||
sp_wallet,
|
||||
commitment.as_deref(),
|
||||
Some(&commitment),
|
||||
Amount::from_sat(fee_rate.into()),
|
||||
)?;
|
||||
|
||||
let psbt = Psbt::from_str(&signed_psbt)?;
|
||||
|
||||
let partial_secret = sp_wallet
|
||||
.get_client()
|
||||
.get_partial_secret_from_psbt(&psbt)?;
|
||||
let partial_secret = sp_wallet.get_client().get_partial_secret_from_psbt(&psbt)?;
|
||||
|
||||
let shared_point = shared_secret_point(
|
||||
&sp_wallet
|
||||
.get_client()
|
||||
.get_scan_key()
|
||||
.public_key(&Secp256k1::signing_only()),
|
||||
&partial_secret,
|
||||
);
|
||||
let shared_point =
|
||||
sp_utils::sending::calculate_shared_point(&sp_address.get_scan_key(), &partial_secret);
|
||||
|
||||
let shared_secret = AnkSharedSecret::new(shared_point);
|
||||
let shared_secret = AnkSharedSecret::new(PublicKey::from_slice(&shared_point)?);
|
||||
|
||||
debug!(
|
||||
"Created transaction with secret {}",
|
||||
shared_secret.to_byte_array().to_lower_hex_string()
|
||||
);
|
||||
|
||||
let cipher = encrypt_with_key(serde_json::to_string(&message)?, shared_secret.to_byte_array().to_lower_hex_string())?;
|
||||
|
||||
// update our cache
|
||||
let sp_address2vouts = map_outputs_to_sp_address(&signed_psbt)?;
|
||||
let recipients_vouts = sp_address2vouts.get::<String>(&address).expect("recipients didn't change").as_slice();
|
||||
let recipients_vouts = sp_address2vouts
|
||||
.get::<String>(&address)
|
||||
.expect("recipients didn't change")
|
||||
.as_slice();
|
||||
// for now let's just take the smallest vout that belongs to the recipient
|
||||
let final_tx = psbt.extract_tx()?;
|
||||
let mut new_msg = CachedMessage::default();
|
||||
new_msg.commitment = commitment;
|
||||
new_msg.commited_in = Some(OutPoint { txid: final_tx.txid(), vout: recipients_vouts[0] as u32 });
|
||||
let mut new_msg = CachedMessage::new();
|
||||
new_msg.plaintext = Some(message.message);
|
||||
new_msg.ciphertext = Some(cipher);
|
||||
new_msg.commitment = Some(commitment);
|
||||
new_msg.commited_in = Some(OutPoint {
|
||||
txid: final_tx.txid(),
|
||||
vout: recipients_vouts[0] as u32,
|
||||
});
|
||||
new_msg.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string());
|
||||
new_msg.recipient = Some(address);
|
||||
new_msg.sender = Some(sp_wallet.get_client().get_receiving_address());
|
||||
@ -908,7 +966,7 @@ pub fn create_faucet_msg() -> ApiResult<CachedMessage> {
|
||||
let user = lock_connected_user()?;
|
||||
let sp_address = user.try_get_recover()?.get_client().get_receiving_address();
|
||||
|
||||
let mut commitment = [0u8;64];
|
||||
let mut commitment = [0u8; 64];
|
||||
thread_rng().fill_bytes(&mut commitment);
|
||||
|
||||
let mut cached_msg = CachedMessage::new();
|
||||
|
111
src/services.ts
111
src/services.ts
@ -1,4 +1,4 @@
|
||||
import { createUserReturn, User, Process, createTransactionReturn, parse_network_msg, outputs_list, FaucetMessage, AnkFlag, NewTxMessage, encryptWithNewKeyResult, AnkSharedSecret, CachedMessage } from '../dist/pkg/sdk_client';
|
||||
import { createUserReturn, User, Process, createTransactionReturn, parse_network_msg, outputs_list, FaucetMessage, AnkFlag, NewTxMessage, encryptWithNewKeyResult, AnkSharedSecret, CachedMessage, UnknownMessage } from '../dist/pkg/sdk_client';
|
||||
import IndexedDB from './database'
|
||||
import { WebSocketClient } from './websockets';
|
||||
|
||||
@ -105,36 +105,24 @@ class Services {
|
||||
const recipientSpAddress = spAddressElement.value;
|
||||
const message = messageElement.value;
|
||||
|
||||
const msg_payload = JSON.stringify({sender: this.sp_address, message: message});
|
||||
const msg_payload: UnknownMessage = {sender: this.sp_address!, message: message};
|
||||
|
||||
let notificationInfo = await services.notify_address_for_message(recipientSpAddress, msg_payload);
|
||||
if (notificationInfo) {
|
||||
let networkMsg = notificationInfo.new_network_msg;
|
||||
let shared_secret = '';
|
||||
if (networkMsg.shared_secret) {
|
||||
shared_secret = networkMsg.shared_secret;
|
||||
} else {
|
||||
throw 'no shared_secret';
|
||||
}
|
||||
console.info('Successfully sent notification transaction');
|
||||
console.debug(networkMsg);
|
||||
|
||||
const connection = await services.pickWebsocketConnectionRandom();
|
||||
const flag: AnkFlag = "Unknown";
|
||||
// encrypt the message(s)
|
||||
// TODO we'd rather do that in the wasm as part of notify_address_for_message
|
||||
try {
|
||||
const cipher = await services.encryptData(msg_payload, shared_secret);
|
||||
let updated_msg = notificationInfo.new_network_msg;
|
||||
updated_msg.plaintext = msg_payload;
|
||||
updated_msg.ciphertext = cipher;
|
||||
await services.updateMessages(updated_msg);
|
||||
connection?.sendMessage(flag, cipher);
|
||||
// send message (transaction in envelope)
|
||||
await services.updateMessages(networkMsg);
|
||||
connection?.sendMessage(flag, networkMsg.ciphertext!);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
// add peers list
|
||||
// add processes list
|
||||
// send message (transaction in envelope)
|
||||
}
|
||||
}
|
||||
|
||||
@ -820,6 +808,41 @@ class Services {
|
||||
}
|
||||
}
|
||||
|
||||
public async answer_confirmation_message(msg: CachedMessage): Promise<void> {
|
||||
const services = await Services.getInstance();
|
||||
const connection = await services.pickWebsocketConnectionRandom();
|
||||
if (!connection) {
|
||||
throw new Error("No connection to relay");
|
||||
}
|
||||
let user: User;
|
||||
try {
|
||||
let possibleUser = await services.getUserInfo();
|
||||
if (!possibleUser) {
|
||||
throw new Error("No user loaded, please first create a new user or login");
|
||||
} else {
|
||||
user = possibleUser;
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
let notificationInfo: createTransactionReturn;
|
||||
try {
|
||||
const feeRate = 1;
|
||||
notificationInfo = services.sdkClient.answer_confirmation_transaction(msg.id, feeRate);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to create confirmation transaction: ${error}`);
|
||||
}
|
||||
const flag: AnkFlag = "NewTx";
|
||||
const newTxMsg: NewTxMessage = {
|
||||
'transaction': notificationInfo.transaction,
|
||||
'tweak_data': null
|
||||
}
|
||||
connection.sendMessage(flag, JSON.stringify(newTxMsg));
|
||||
await services.updateMessages(notificationInfo.new_network_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
public async confirm_sender_address(msg: CachedMessage): Promise<void> {
|
||||
const services = await Services.getInstance();
|
||||
const connection = await services.pickWebsocketConnectionRandom();
|
||||
@ -841,7 +864,7 @@ class Services {
|
||||
let notificationInfo: createTransactionReturn;
|
||||
try {
|
||||
const feeRate = 1;
|
||||
notificationInfo = services.sdkClient.answer_confirmation_transaction(msg, feeRate);
|
||||
notificationInfo = services.sdkClient.create_confirmation_transaction(msg.id, feeRate);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to create confirmation transaction: ${error}`);
|
||||
}
|
||||
@ -851,10 +874,11 @@ class Services {
|
||||
'tweak_data': null
|
||||
}
|
||||
connection.sendMessage(flag, JSON.stringify(newTxMsg));
|
||||
await services.updateMessages(notificationInfo.new_network_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
public async notify_address_for_message(sp_address: string, message: string): Promise<createTransactionReturn> {
|
||||
public async notify_address_for_message(sp_address: string, message: UnknownMessage): Promise<createTransactionReturn> {
|
||||
const services = await Services.getInstance();
|
||||
const connection = await services.pickWebsocketConnectionRandom();
|
||||
if (!connection) {
|
||||
@ -863,62 +887,19 @@ class Services {
|
||||
|
||||
try {
|
||||
const feeRate = 1;
|
||||
const commitment = services.sdkClient.create_commitment(message);
|
||||
let notificationInfo: createTransactionReturn = services.sdkClient.create_notification_transaction(sp_address, commitment, feeRate);
|
||||
let notificationInfo: createTransactionReturn = services.sdkClient.create_notification_transaction(sp_address, message, feeRate);
|
||||
const flag: AnkFlag = "NewTx";
|
||||
const newTxMsg: NewTxMessage = {
|
||||
'transaction': notificationInfo.transaction,
|
||||
'tweak_data': null
|
||||
}
|
||||
connection.sendMessage(flag, JSON.stringify(newTxMsg));
|
||||
console.info('Successfully sent notification transaction');
|
||||
return notificationInfo;
|
||||
} catch (error) {
|
||||
throw 'Failed to create notification transaction:", error';
|
||||
}
|
||||
}
|
||||
|
||||
// public async encryptData(data: string, sharedSecret: Record<string, AnkSharedSecret>): Promise<Map<string, string>> {
|
||||
// const services = await Services.getInstance();
|
||||
// let msg_cipher: encryptWithNewKeyResult;
|
||||
// try {
|
||||
// msg_cipher = services.sdkClient.encrypt_with_new_key(data);
|
||||
// } catch (error) {
|
||||
// throw error;
|
||||
// }
|
||||
|
||||
// let res = new Map<string, string>();
|
||||
// for (const [recipient, secret] of Object.entries(sharedSecret)) {
|
||||
// try {
|
||||
// const key = secret.secret;
|
||||
// const encryptedKey: string = await services.sdkClient.encrypt_with_key(msg_cipher.key, key);
|
||||
// res.set(recipient, encryptedKey);
|
||||
// } catch (error) {
|
||||
// throw new Error(`Failed to encrypt key for recipient ${recipient}: ${error}`);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return res;
|
||||
// }
|
||||
public async encryptData(data: string, key: string): Promise<string> {
|
||||
const services = await Services.getInstance();
|
||||
|
||||
try {
|
||||
let res: string = services.sdkClient.encrypt_with_key(data, key);
|
||||
return res;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
public async decryptData(cipher: string, key: string): Promise<string> {
|
||||
const services = await Services.getInstance();
|
||||
try {
|
||||
let res = services.sdkClient.try_decrypt_with_key(cipher, key);
|
||||
return res;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Services;
|
||||
|
@ -34,7 +34,7 @@ class WebSocketClient {
|
||||
if (res.status === 'FaucetComplete') {
|
||||
// we received a faucet tx, there's nothing else to do
|
||||
window.alert(`New faucet output\n${res.commited_in}`);
|
||||
await services.removeMessage(res.id);
|
||||
await services.updateMessages(res);
|
||||
await services.updateOwnedOutputsForUser();
|
||||
} else if (res.status === 'TxWaitingCipher') {
|
||||
// we received a tx but we don't have the cipher
|
||||
@ -47,6 +47,7 @@ class WebSocketClient {
|
||||
await services.updateMessages(res);
|
||||
} else if (res.status === 'SentWaitingConfirmation') {
|
||||
// We are sender and we're waiting for the challenge that will confirm recipient got the transaction and the message
|
||||
await services.updateMessages(res);
|
||||
await services.updateOwnedOutputsForUser();
|
||||
} else if (res.status === 'MustSpendConfirmation') {
|
||||
// we received a challenge for a notification we made
|
||||
@ -54,7 +55,17 @@ class WebSocketClient {
|
||||
window.alert(`Spending ${res.confirmed_by} to prove our identity`);
|
||||
console.debug(`sending confirm message to ${res.recipient}`);
|
||||
await services.updateMessages(res);
|
||||
await services.answer_confirmation_message(res);
|
||||
} else if (res.status === 'ReceivedMustConfirm') {
|
||||
// we found a notification and decrypted the cipher
|
||||
window.alert(`Received message from ${res.sender}\n${res.plaintext}`);
|
||||
// we must spend the commited_in output to sender
|
||||
await services.updateMessages(res);
|
||||
await services.confirm_sender_address(res);
|
||||
} else if (res.status === 'Complete') {
|
||||
window.alert(`Received confirmation that ${res.sender} is the author of message ${res.plaintext}`)
|
||||
await services.updateMessages(res);
|
||||
await services.updateOwnedOutputsForUser();
|
||||
} else {
|
||||
console.debug('Received an unimplemented valid message');
|
||||
}
|
||||
@ -88,7 +99,7 @@ class WebSocketClient {
|
||||
// console.debug("Sending message:", JSON.stringify(networkMessage));
|
||||
this.ws.send(JSON.stringify(networkMessage));
|
||||
} else {
|
||||
console.error('WebSocket is not open. ReadyState:', this.ws.readyState);
|
||||
console.warn('WebSocket is not open. ReadyState:', this.ws.readyState);
|
||||
this.messageQueue.push(message);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user