## preconditions
* Amount sufficient
* Grab CPFs
* CPFs reserved
```rust=
// sender::State
pub enum State {
Initiated,
Authorizing{
transferred: Vec<Uuid>,
authorized: Vec<Uuid>,
},
Sending,
Completed,
}
struct NewTransction {
amount: proto::Amount
receiver: DynamicVerifier,
}
type Action = Fn(HashMap<Uuid, Transction>, Db, UnboundedSender<Packet>, UnboundedSender<Trigger>, Keychain) -> Result<(), E>;
```
## Sender
| trigger | process/forward | processor |
| ------------------ | --------------- | -------------------------- |
| `NewTransaction` | process | `Sender::new_transaction` |
| `SimplePaymentAck` | forward | `Transaction::process_ack` |
| `AuthorizedPromissory`| forward | `Transaction::process_promissory` |
1.
```rust=
fn forward(&self, uetr: Uuid, trigger: Trigger) -> Result<Action, E> {
if let Some(mut tranasction) = self.map.get(uetr) {
return transaction.process(trigger);
};
let action = |receiver| {
tracing::error!("Tranasction not found {uetr}");
};
Ok(action)
}
fn new_transaction(&self, txn: NewTransction) -> Result<Action, E> {
uetr = Uuid::new_v4();
let action = |map, db, gw_tx, tr_tx| {
map.insert(uetr, Transction::new(txn));
db.set_state(uetr, State::Initiated);
gw_tx.send(proto::SimplePaymentRequest::new(uetr, txn.receiver, txn.amount))
};
Ok(action)
}
```
## SenderTransaction
```rust
impl SenderTransaction for transaction::Transaction {
fn process_ack(&mut self, trigger: Trigger) -> Result<Action, E> {
self.state = State::Authorizing;
let action = |sender| {
sender.db.set_state(self.uetr, State::Authorizing);
let promissories: Vec<AuthorizedPromissory> = db.get_reserved(self.uetr);
for promissory in promissories {
let packet: proto::Packet = AuthorizePromissoryPacket::new(self.uetr, promissory);
gw_tx.send(packet)?;
}
};
}
fn process_promissory(&mut self, promissory: Trigger) -> Result<Action, E> {
let promissory = Promissory::decode(promissory.data)?;
self.state.authorized.push(promissory.id);
if self.state.authorized != self.state.transferred {
let action = |sender: &Sender| {
// and all IDs as vec : [authorized...]/[transferred...]
tracing::info!("{authorized}/{transferred}")
sender.db.set_state(self.uetr, self.state);
sender.db.set_authorized_promissory(promissory);
let promissories: Vec<AuthorizedPromissory> = db.set(self.uetr);
};
return Ok(action);
} else {
let authorized_ids = self.state.authorized;
self.state = State::Sending;
let action = |sender: &Sender| {
tracing::info!("{authorized}/{transferred}")
sender.db.set_state(self.uetr, self.state);
sender.db.set_authorized_promissory(promissory);
let promissories: Vec<AuthorizedPromissory> = sender.db.get_authorized_promissories(authorized_ids);
for promissory in promissores {
sender.gw_tx.send(promissory)?;
}
};
Ok(action)
}
```
## Receiver
| trigger | process/forward | action |
| ---------------- | ------------- | ----------------- |
| `SimplePaymentRequest` | process | `Receiver::new_transaction` |
| `AuthorizedPromissory`| forward | `Transaction::process_promissory`|
1.
```rust=
fn new_transaction(&self, packet: proto::Packet) -> Result<Action, E> {
let msg = deserialize(packet);
let action = |map, db, gw_tx, tr_tx| {
msg = deserialize.map_ok_and_err();
if let Ok(header, req) = msg {
// we auto accept
db.set_state(header.uetr, State::Receiving{expected_amount, vec![]};
map.insert(header.uetr, Transction::new(req));
gw_tx.send(Ack::new(header, req));
} else {
gw_tx.send(Nack::new());
}
};
Ok(action)
}
```
## ReceiverTransaction
```rust!
impl ReceiverTransaction for transaction::Transaction {
fn process_promissory(&mut self, trigger: Trigger) -> Result<Action, E> {
let promissory: AuthorziedPromissory = Promissory::decode(trigger)?;
self.state.received_ids.push(promissory.id);
self.state.received_amount += promissory.amount;
if received_amount < expeceted_amount {
let action = |sender| {
sender.db.set_state(self.uetr, self.state);
sender.db.set_authorized_promissory(promissory);
tracing::info!("{received_amount}/{expected_amount}");
};
return Ok(action);
} else {
self.state = State::Completed{ self.state.received_ids};
let action = |sender| {
sender.db.set_state(self.uetr, self.state);
sender.db.set_authorized_promissory(promissory);
tracing::info!("{received_amount}/{expected_amount}");
sender.gw_tx
.send(SimplePaymentResponse::new(self.state.received_ids));
Ok(())
};
Ok(action)
}
}
```