Skip to content

Commit 37aad36

Browse files
authored
Merge pull request #508 from hashgraph/sr/transfers
2 parents 5573341 + f3fdf6e commit 37aad36

File tree

3 files changed

+81
-49
lines changed

3 files changed

+81
-49
lines changed

src/token/token_nft_transfer.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{
88

99
/// Represents a transfer of an NFT from one account to another.
1010
#[derive(Debug, Clone, Eq, PartialEq)]
11+
#[non_exhaustive]
1112
pub struct TokenNftTransfer {
1213
/// The ID of the NFT's token.
1314
pub token_id: TokenId,

src/transaction/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ impl<D> Transaction<D> {
192192
self.body
193193
}
194194

195+
#[inline(always)]
195196
pub(crate) fn data(&self) -> &D {
196197
&self.body.data
197198
}

src/transfer_transaction.rs

Lines changed: 79 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* ‍
1919
*/
2020

21+
use std::collections::HashMap;
2122
use std::ops::Not;
2223

2324
use hedera_proto::services;
@@ -42,6 +43,7 @@ use crate::{
4243
NftId,
4344
ToProtobuf,
4445
TokenId,
46+
TokenNftTransfer,
4547
Transaction,
4648
ValidateChecksums,
4749
};
@@ -79,23 +81,41 @@ struct TokenTransfer {
7981

8082
transfers: Vec<Transfer>,
8183

82-
nft_transfers: Vec<NftTransfer>,
84+
nft_transfers: Vec<TokenNftTransfer>,
8385

8486
expected_decimals: Option<u32>,
8587
}
8688

87-
#[derive(Debug, Clone)]
88-
#[cfg_attr(test, derive(Eq, PartialEq))]
89-
struct NftTransfer {
90-
sender_account_id: AccountId,
91-
receiver_account_id: AccountId,
89+
impl TransferTransaction {
90+
fn _hbar_transfer(&mut self, account_id: AccountId, amount: Hbar, approved: bool) -> &mut Self {
91+
self.data_mut().transfers.push(Transfer {
92+
account_id,
93+
amount: amount.to_tinybars(),
94+
is_approval: approved,
95+
});
9296

93-
serial: u64,
97+
self
98+
}
9499

95-
is_approval: bool,
96-
}
100+
/// Add a non-approved hbar transfer to the transaction.
101+
pub fn hbar_transfer(&mut self, account_id: AccountId, amount: Hbar) -> &mut Self {
102+
self._hbar_transfer(account_id, amount, false)
103+
}
104+
105+
/// Add an approved hbar transfer to the transaction.
106+
pub fn approved_hbar_transfer(&mut self, account_id: AccountId, amount: Hbar) -> &mut Self {
107+
self._hbar_transfer(account_id, amount, true)
108+
}
109+
110+
/// Returns all transfers associated with this transaction.
111+
pub fn get_hbar_transfers(&self) -> HashMap<AccountId, Hbar> {
112+
self.data()
113+
.transfers
114+
.iter()
115+
.map(|it| (it.account_id, Hbar::from_tinybars(it.amount)))
116+
.collect()
117+
}
97118

98-
impl TransferTransaction {
99119
fn _token_transfer(
100120
&mut self,
101121
token_id: TokenId,
@@ -164,6 +184,27 @@ impl TransferTransaction {
164184
self._token_transfer(token_id, account_id, amount, true, Some(expected_decimals))
165185
}
166186

187+
/// Returns all the token transfers associated associated with this transaction.
188+
pub fn get_token_transfers(&self) -> HashMap<TokenId, HashMap<AccountId, i64>> {
189+
use std::collections::hash_map::Entry;
190+
191+
// note: using fold instead of nested collects on the off chance a token is in here twice.
192+
self.data().token_transfers.iter().fold(
193+
HashMap::with_capacity(self.data().token_transfers.len()),
194+
|mut map, transfer| {
195+
let iter = transfer.transfers.iter().map(|it| (it.account_id, it.amount));
196+
match map.entry(transfer.token_id) {
197+
Entry::Occupied(mut it) => it.get_mut().extend(iter),
198+
Entry::Vacant(it) => {
199+
it.insert(iter.collect());
200+
}
201+
}
202+
203+
map
204+
},
205+
)
206+
}
207+
167208
fn _nft_transfer(
168209
&mut self,
169210
nft_id: NftId,
@@ -172,8 +213,13 @@ impl TransferTransaction {
172213
approved: bool,
173214
) -> &mut Self {
174215
let NftId { token_id, serial } = nft_id;
175-
let transfer =
176-
NftTransfer { serial, sender_account_id, receiver_account_id, is_approval: approved };
216+
let transfer = TokenNftTransfer {
217+
token_id,
218+
serial,
219+
sender: sender_account_id,
220+
receiver: receiver_account_id,
221+
is_approved: approved,
222+
};
177223

178224
let data = self.data_mut();
179225

@@ -211,24 +257,13 @@ impl TransferTransaction {
211257
self._nft_transfer(nft_id.into(), sender_account_id, receiver_account_id, false)
212258
}
213259

214-
fn _hbar_transfer(&mut self, account_id: AccountId, amount: Hbar, approved: bool) -> &mut Self {
215-
self.data_mut().transfers.push(Transfer {
216-
account_id,
217-
amount: amount.to_tinybars(),
218-
is_approval: approved,
219-
});
220-
221-
self
222-
}
223-
224-
/// Add a non-approved hbar transfer to the transaction.
225-
pub fn hbar_transfer(&mut self, account_id: AccountId, amount: Hbar) -> &mut Self {
226-
self._hbar_transfer(account_id, amount, false)
227-
}
228-
229-
/// Add an approved hbar transfer to the transaction.
230-
pub fn approved_hbar_transfer(&mut self, account_id: AccountId, amount: Hbar) -> &mut Self {
231-
self._hbar_transfer(account_id, amount, true)
260+
/// Returns all the NFT transfers associated with this transaction.
261+
pub fn get_nft_transfers(&self) -> HashMap<TokenId, Vec<TokenNftTransfer>> {
262+
self.data()
263+
.token_transfers
264+
.iter()
265+
.map(|it| (it.token_id, it.nft_transfers.clone()))
266+
.collect()
232267
}
233268
}
234269

@@ -256,8 +291,8 @@ impl ValidateChecksums for TransferTransactionData {
256291
transfer.account_id.validate_checksums(ledger_id)?;
257292
}
258293
for nft_transfer in &token_transfer.nft_transfers {
259-
nft_transfer.sender_account_id.validate_checksums(ledger_id)?;
260-
nft_transfer.receiver_account_id.validate_checksums(ledger_id)?;
294+
nft_transfer.sender.validate_checksums(ledger_id)?;
295+
nft_transfer.receiver.validate_checksums(ledger_id)?;
261296
}
262297
}
263298
Ok(())
@@ -288,10 +323,16 @@ impl ToProtobuf for Transfer {
288323

289324
impl FromProtobuf<services::TokenTransferList> for TokenTransfer {
290325
fn from_protobuf(pb: services::TokenTransferList) -> crate::Result<Self> {
326+
let token_id = TokenId::from_protobuf(pb_getf!(pb, token)?)?;
327+
291328
Ok(Self {
292-
token_id: TokenId::from_protobuf(pb_getf!(pb, token)?)?,
329+
token_id,
293330
transfers: Vec::from_protobuf(pb.transfers)?,
294-
nft_transfers: Vec::from_protobuf(pb.nft_transfers)?,
331+
nft_transfers: pb
332+
.nft_transfers
333+
.into_iter()
334+
.map(|pb| TokenNftTransfer::from_protobuf(pb, token_id))
335+
.collect::<Result<Vec<_>, _>>()?,
295336
expected_decimals: pb.expected_decimals,
296337
})
297338
}
@@ -313,26 +354,15 @@ impl ToProtobuf for TokenTransfer {
313354
}
314355
}
315356

316-
impl FromProtobuf<services::NftTransfer> for NftTransfer {
317-
fn from_protobuf(pb: services::NftTransfer) -> crate::Result<Self> {
318-
Ok(Self {
319-
sender_account_id: AccountId::from_protobuf(pb_getf!(pb, sender_account_id)?)?,
320-
receiver_account_id: AccountId::from_protobuf(pb_getf!(pb, receiver_account_id)?)?,
321-
serial: pb.serial_number as u64,
322-
is_approval: pb.is_approval,
323-
})
324-
}
325-
}
326-
327-
impl ToProtobuf for NftTransfer {
357+
impl ToProtobuf for TokenNftTransfer {
328358
type Protobuf = services::NftTransfer;
329359

330360
fn to_protobuf(&self) -> Self::Protobuf {
331361
services::NftTransfer {
332-
sender_account_id: Some(self.sender_account_id.to_protobuf()),
333-
receiver_account_id: Some(self.receiver_account_id.to_protobuf()),
362+
sender_account_id: Some(self.sender.to_protobuf()),
363+
receiver_account_id: Some(self.receiver.to_protobuf()),
334364
serial_number: self.serial as i64,
335-
is_approval: self.is_approval,
365+
is_approval: self.is_approved,
336366
}
337367
}
338368
}

0 commit comments

Comments
 (0)