1use std::error;
13
14use flow::access_api_client::AccessApiClient;
15
16use flow::*;
17
18pub mod flow {
19 tonic::include_proto!("flow.access");
23}
24
25use bytes::Bytes;
27pub use p256_flow::ecdsa::SigningKey;
28use p256_flow::ecdsa::{signature_flow::Signature, signature_flow::Signer};
29use p256_flow::elliptic_curve_flow::SecretKey;
30pub use rand_core::OsRng;
31pub extern crate hex;
32pub extern crate rlp;
33use rlp::*;
34
35pub struct FlowConnection<T> {
42 pub client: AccessApiClient<T>,
43}
44
45impl FlowConnection<tonic::transport::Channel> {
47 pub async fn new(
49 network_address: &str,
50 ) -> Result<FlowConnection<tonic::transport::Channel>, Box<dyn error::Error>> {
51 let mut client = AccessApiClient::connect(network_address.to_owned()).await?;
52 let request = tonic::Request::new(PingRequest {});
53 client.ping(request).await?;
54 Ok(FlowConnection::<tonic::transport::Channel> { client })
55 }
56 pub async fn get_account(
58 &mut self,
59 account_address: &str,
60 ) -> Result<AccountResponse, Box<dyn error::Error>> {
61 let request = tonic::Request::new(GetAccountAtLatestBlockRequest {
62 address: hex::decode(account_address).unwrap(),
63 });
64 let response = self.client.get_account_at_latest_block(request).await?;
65 Ok(response.into_inner())
66 }
67 pub async fn execute_script(
69 &mut self,
70 script: Vec<u8>,
71 arguments: Vec<Vec<u8>>,
72 block_height: Option<u64>,
73 block_id: Option<Vec<u8>>,
74 ) -> Result<ExecuteScriptResponse, Box<dyn error::Error>> {
75 if block_id.is_some() {
76 let request = tonic::Request::new(ExecuteScriptAtBlockIdRequest {
78 script,
79 arguments,
80 block_id: block_id.unwrap(),
81 });
82 let response = self.client.execute_script_at_block_id(request).await?;
83 Ok(response.into_inner())
84 } else if block_height.is_some() {
85 let request = tonic::Request::new(ExecuteScriptAtBlockHeightRequest {
87 script,
88 arguments,
89 block_height: block_height.unwrap(),
90 });
91 let response = self.client.execute_script_at_block_height(request).await?;
92 Ok(response.into_inner())
93 } else {
94 let request =
95 tonic::Request::new(ExecuteScriptAtLatestBlockRequest { script, arguments });
96 let response = self.client.execute_script_at_latest_block(request).await?;
97 Ok(response.into_inner())
98 }
99 }
100 pub async fn send_transaction(
103 &mut self,
104 transaction: Option<Transaction>,
105 ) -> Result<SendTransactionResponse, Box<dyn error::Error>> {
106 let request = tonic::Request::new(SendTransactionRequest { transaction });
108 let response = self.client.send_transaction(request).await?;
109 Ok(response.into_inner())
110 }
111 pub async fn get_transaction_result(
113 &mut self,
114 id: Vec<u8>,
115 ) -> Result<TransactionResultResponse, Box<dyn error::Error>> {
116 let request = tonic::Request::new(GetTransactionRequest { id });
118 let response = self.client.get_transaction_result(request).await?;
119 Ok(response.into_inner())
120 }
121 pub async fn get_block(
123 &mut self,
124 block_id: Option<String>,
125 block_height: Option<u64>,
126 is_sealed: Option<bool>,
127 ) -> Result<BlockResponse, Box<dyn error::Error>> {
128 if block_id.is_some() {
129 let request = tonic::Request::new(GetBlockByIdRequest {
131 id: hex::decode(block_id.unwrap())?,
132 });
133 let response = self.client.get_block_by_id(request).await?;
134 Ok(response.into_inner())
135 } else if block_height.is_some() {
136 let request = tonic::Request::new(GetBlockByHeightRequest {
138 height: block_height.unwrap(),
139 });
140 let response = self.client.get_block_by_height(request).await?;
141 Ok(response.into_inner())
142 } else {
143 if is_sealed.is_some() {
145 let request = tonic::Request::new(GetLatestBlockRequest {
146 is_sealed: is_sealed.unwrap(),
147 });
148 let response = self.client.get_latest_block(request).await?;
149 Ok(response.into_inner())
150 } else {
151 let request = tonic::Request::new(GetLatestBlockRequest { is_sealed: false });
152 let response = self.client.get_latest_block(request).await?;
153 Ok(response.into_inner())
154 }
155 }
156 }
157 pub async fn get_events_for_height_range(
159 &mut self,
160 event_type: &str,
161 start_height: u64,
162 end_height: u64,
163 ) -> Result<EventsResponse, Box<dyn error::Error>> {
164 let request = tonic::Request::new(GetEventsForHeightRangeRequest {
165 r#type: event_type.to_owned(),
166 start_height,
167 end_height,
168 });
169 let response = self.client.get_events_for_height_range(request).await?;
170 Ok(response.into_inner())
171 }
172 pub async fn get_events_for_block_ids(
174 &mut self,
175 event_type: &str,
176 ids: Vec<Vec<u8>>,
177 ) -> Result<EventsResponse, Box<dyn error::Error>> {
178 let request = tonic::Request::new(GetEventsForBlockIdsRequest {
179 r#type: event_type.to_owned(),
180 block_ids: ids,
181 });
182 let response = self.client.get_events_for_block_i_ds(request).await?;
183 Ok(response.into_inner())
184 }
185 pub async fn get_collection(
187 &mut self,
188 collection_id: Vec<u8>,
189 ) -> Result<CollectionResponse, Box<dyn error::Error>> {
190 let request = tonic::Request::new(GetCollectionByIdRequest { id: collection_id });
191 let response = self.client.get_collection_by_id(request).await?;
192 Ok(response.into_inner())
193 }
194 pub async fn create_account(
196 &mut self,
197 account_keys: Vec<String>,
198 payer: &str,
199 payer_private_key: &str,
200 key_id: u32,
201 ) -> Result<flow::Account, Box<dyn error::Error>> {
202 let create_account_template = b"
203 import Crypto
204
205 transaction(publicKeys: [String], contracts: {String: String}) {
206 prepare(signer: AuthAccount) {
207 let acct = AuthAccount(payer: signer)
208
209 for pkey in publicKeys {
210 let key = PublicKey(
211 publicKey: pkey.decodeHex(),
212 signatureAlgorithm: SignatureAlgorithm.ECDSA_P256
213 )
214 acct.keys.add(publicKey: key, hashAlgorithm: HashAlgorithm.SHA3_256, weight: 1000.0)
215 }
216
217 for contract in contracts.keys {
218 acct.contracts.add(name: contract, code: contracts[contract]!.decodeHex())
219 }
220 }
221 }";
222
223 let latest_block: BlockResponse = self.get_block(None, None, Some(false)).await?;
224 let account: flow::Account = self.get_account(payer).await?.account.unwrap();
225 let proposer = TransactionProposalKey {
226 address: hex::decode(payer).unwrap(),
227 key_id,
228 sequence_number: account.keys[key_id as usize].sequence_number as u64,
229 };
230 let keys_arg = process_keys_args(account_keys);
231 let contracts_arg = Argument::dictionary(vec![]);
233 let keys_arg = json!(keys_arg);
234 let contracts_arg = json!(contracts_arg);
235 let transaction: Transaction = build_transaction(
236 create_account_template.to_vec(),
237 vec![to_vec(&keys_arg)?, to_vec(&contracts_arg)?],
238 latest_block.block.unwrap().id,
239 1000,
240 proposer,
241 vec![payer.to_owned()],
242 payer.to_owned(),
243 )
244 .await?;
245 let signature = Sign {
246 address: payer.to_owned(),
247 key_id,
248 private_key: payer_private_key.to_owned(),
249 };
250 let transaction: Option<Transaction> =
251 sign_transaction(transaction, vec![], vec![&signature]).await?;
252 let transaction: SendTransactionResponse = self.send_transaction(transaction).await?;
253 let mut time: u64 = 50;
255 let mut i = 0;
256 println!("{}", hex::encode(transaction.id.to_vec()));
257 while i < 50 {
258 i += 1;
259 sleep(Duration::from_millis(time)).await;
260 let res = self.get_transaction_result(transaction.id.to_vec()).await?;
261 match res.status {
262 0 | 1 | 2 | 3 => {
263 time += 200;
264 }
265 4 => {
266 if res.status_code == 1 {
267 return Err("Error during execution".into());
269 }
270 let new_account_address: flow::Event = res
271 .events
272 .into_iter()
273 .filter(|x| x.r#type == "flow.AccountCreated")
274 .collect::<Vec<flow::Event>>()
275 .pop()
276 .unwrap();
277 let payload: Value = from_slice(&new_account_address.payload)?;
278 let address: String = payload["value"]["fields"][0]["value"]["value"]
279 .to_string()
280 .split_at(3)
281 .1
282 .to_string()
283 .split_at(16)
284 .0
285 .to_string();
286 let acct: flow::Account = self
287 .get_account(&address)
288 .await?
289 .account
290 .expect("could not get newly created account");
291 return Ok(acct);
292 }
293 _ => return Err("Cadence Runtime Error".into()),
294 }
295 }
296 Err("Could not produce result".into())
297 }
298 pub async fn add_key(
300 &mut self,
301 public_key_to_add: &str,
302 payer: &str,
303 payer_private_key: &str,
304 key_id: u32,
305 ) -> Result<flow::SendTransactionResponse, Box<dyn error::Error>> {
306 let update_contract_template = b"
307 import Crypto
308
309 transaction(publicKey: String) {
310 prepare(signer: AuthAccount) {
311 let key = PublicKey(
312 publicKey: pkey.decodeHex(),
313 signatureAlgorithm: SignatureAlgorithm.ECDSA_P256
314 )
315 signer.keys.add(publicKey: key, hashAlgorithm: HashAlgorithm.SHA3_256, weight: 1000.0)
316 }
317 }
318 ";
319 let latest_block: BlockResponse = self.get_block(None, None, Some(false)).await?;
320 let account: flow::Account = self.get_account(payer).await?.account.unwrap();
321 let proposer = TransactionProposalKey {
322 address: hex::decode(payer).unwrap(),
323 key_id,
324 sequence_number: account.keys[key_id as usize].sequence_number as u64,
325 };
326 let public_key_to_add_arg = Argument::str(public_key_to_add);
327 let transaction: Transaction = build_transaction(
328 update_contract_template.to_vec(),
329 vec![public_key_to_add_arg.encode_str()],
330 latest_block.block.unwrap().id,
331 1000,
332 proposer,
333 vec![payer.to_owned()],
334 payer.to_owned(),
335 )
336 .await?;
337 let signature = Sign {
338 address: payer.to_owned(),
339 key_id,
340 private_key: payer_private_key.to_owned(),
341 };
342 let transaction: Option<Transaction> =
343 sign_transaction(transaction, vec![], vec![&signature]).await?;
344 let transaction: SendTransactionResponse = self.send_transaction(transaction).await?;
345
346 Ok(transaction)
347 }
348 pub async fn remove_key(
350 &mut self,
351 key_to_remove: u64,
352 payer: &str,
353 payer_private_key: &str,
354 key_id: u32,
355 ) -> Result<flow::SendTransactionResponse, Box<dyn error::Error>> {
356 let update_contract_template = b"
357 transaction(keyIndex: Int) {
358 prepare(signer: AuthAccount) {
359 signer.keys.revoke(keyIndex)
360 }
361 }
362 ";
363 let latest_block: BlockResponse = self.get_block(None, None, Some(false)).await?;
364 let account: flow::Account = self.get_account(payer).await?.account.unwrap();
365 let proposer = TransactionProposalKey {
366 address: hex::decode(payer).unwrap(),
367 key_id,
368 sequence_number: account.keys[key_id as usize].sequence_number as u64,
369 };
370 let key_to_remove_arg = Argument::uint64(key_to_remove);
371 let transaction: Transaction = build_transaction(
372 update_contract_template.to_vec(),
373 vec![key_to_remove_arg.encode()],
374 latest_block.block.unwrap().id,
375 1000,
376 proposer,
377 vec![payer.to_owned()],
378 payer.to_owned(),
379 )
380 .await?;
381 let signature = Sign {
382 address: payer.to_owned(),
383 key_id,
384 private_key: payer_private_key.to_owned(),
385 };
386 let transaction: Option<Transaction> =
387 sign_transaction(transaction, vec![], vec![&signature]).await?;
388 let transaction: SendTransactionResponse = self.send_transaction(transaction).await?;
389
390 Ok(transaction)
391 }
392 pub async fn add_contract(
394 &mut self,
395 contract_name: &str,
396 contract_code: &str,
397 payer: &str,
398 payer_private_key: &str,
399 key_id: u32,
400 ) -> Result<flow::SendTransactionResponse, Box<dyn error::Error>> {
401 let update_contract_template = b"
402 transaction(name: String, code: String) {
403 prepare(signer: AuthAccount) {
404 signer.contracts.add(name: name, code: code.decodeHex())
405 }
406 }
407 ";
408 let latest_block: BlockResponse = self.get_block(None, None, Some(false)).await?;
409 let account: flow::Account = self.get_account(payer).await?.account.unwrap();
410 let proposer = TransactionProposalKey {
411 address: hex::decode(payer).unwrap(),
412 key_id,
413 sequence_number: account.keys[key_id as usize].sequence_number as u64,
414 };
415 let contract_name_arg = Argument::str(contract_name);
416 let contract_code_arg = Argument::str(contract_code);
417 let transaction: Transaction = build_transaction(
418 update_contract_template.to_vec(),
419 vec![
420 contract_name_arg.encode_str(),
421 contract_code_arg.encode_str(),
422 ],
423 latest_block.block.unwrap().id,
424 1000,
425 proposer,
426 vec![payer.to_owned()],
427 payer.to_owned(),
428 )
429 .await?;
430 let signature = Sign {
431 address: payer.to_owned(),
432 key_id,
433 private_key: payer_private_key.to_owned(),
434 };
435 let transaction: Option<Transaction> =
436 sign_transaction(transaction, vec![], vec![&signature]).await?;
437 let transaction: SendTransactionResponse = self.send_transaction(transaction).await?;
438
439 Ok(transaction)
440 }
441 pub async fn update_contract(
443 &mut self,
444 contract_name: &str,
445 contract_code: &str,
446 payer: &str,
447 payer_private_key: &str,
448 key_id: u32,
449 ) -> Result<flow::SendTransactionResponse, Box<dyn error::Error>> {
450 let update_contract_template = b"
451 transaction(name: String, code: String) {
452 prepare(signer: AuthAccount) {
453 signer.contracts.update__experimental(name: name, code: code.decodeHex())
454 }
455 }
456 ";
457 let latest_block: BlockResponse = self.get_block(None, None, Some(false)).await?;
458 let account: flow::Account = self.get_account(payer).await?.account.unwrap();
459 let proposer = TransactionProposalKey {
460 address: hex::decode(payer).unwrap(),
461 key_id,
462 sequence_number: account.keys[key_id as usize].sequence_number as u64,
463 };
464 let contract_name_arg = Argument::str(contract_name);
465 let contract_code_arg = Argument::str(contract_code);
466 let transaction: Transaction = build_transaction(
467 update_contract_template.to_vec(),
468 vec![
469 contract_name_arg.encode_str(),
470 contract_code_arg.encode_str(),
471 ],
472 latest_block.block.unwrap().id,
473 1000,
474 proposer,
475 vec![payer.to_owned()],
476 payer.to_owned(),
477 )
478 .await?;
479 let signature = Sign {
480 address: payer.to_owned(),
481 key_id,
482 private_key: payer_private_key.to_owned(),
483 };
484 let transaction: Option<Transaction> =
485 sign_transaction(transaction, vec![], vec![&signature]).await?;
486 let transaction: SendTransactionResponse = self.send_transaction(transaction).await?;
487
488 Ok(transaction)
489 }
490 pub async fn remove_contract(
492 &mut self,
493 contract_name: &str,
494 payer: &str,
495 payer_private_key: &str,
496 key_id: u32,
497 ) -> Result<flow::SendTransactionResponse, Box<dyn error::Error>> {
498 let update_contract_template = b"
499 transaction(name: String) {
500 prepare(signer: AuthAccount) {
501 signer.contracts.remove(name: name)
502 }
503 }
504 ";
505 let latest_block: BlockResponse = self.get_block(None, None, Some(false)).await?;
506 let account: flow::Account = self.get_account(payer).await?.account.unwrap();
507 let proposer = TransactionProposalKey {
508 address: hex::decode(payer).unwrap(),
509 key_id,
510 sequence_number: account.keys[key_id as usize].sequence_number as u64,
511 };
512 let contract_name_arg = Argument::str(contract_name);
513 let transaction: Transaction = build_transaction(
514 update_contract_template.to_vec(),
515 vec![contract_name_arg.encode_str()],
516 latest_block.block.unwrap().id,
517 1000,
518 proposer,
519 vec![payer.to_owned()],
520 payer.to_owned(),
521 )
522 .await?;
523 let signature = Sign {
524 address: payer.to_owned(),
525 key_id,
526 private_key: payer_private_key.to_owned(),
527 };
528 let transaction: Option<Transaction> =
529 sign_transaction(transaction, vec![], vec![&signature]).await?;
530 let transaction: SendTransactionResponse = self.send_transaction(transaction).await?;
531
532 Ok(transaction)
533 }
534}
535
536use serde::Serialize;
541pub use serde_json::{from_slice, json, to_vec, Value};
542use tokio::time::{sleep, Duration};
543
544#[derive(Serialize)]
546pub struct Argument<T> {
547 r#type: &'static str,
548 value: T,
549}
550impl Argument<Vec<Value>> {
552 pub fn array(values: Vec<Value>) -> Argument<Vec<Value>> {
554 Argument {
555 r#type: "Array",
556 value: values,
557 }
558 }
559 pub fn dictionary(values: Vec<(String, String)>) -> Argument<Vec<Value>> {
561 Argument {
562 r#type: "Dictionary",
563 value: values
564 .into_iter()
565 .map(|(x, y)| json!({"Key":x, "Value":y}))
566 .collect(),
567 }
568 }
569 pub fn encode_arr(&self) -> Vec<u8> {
571 to_vec(&json!(self)).unwrap()
572 }
573}
574impl Argument<bool> {
576 pub fn boolean(value: bool) -> Argument<bool> {
577 Argument {
578 r#type: "Bool",
579 value,
580 }
581 }
582}
583impl Argument<&str> {
585 pub fn str(value: &str) -> Argument<&str> {
586 Argument {
587 r#type: "String",
588 value,
589 }
590 }
591 pub fn encode_str(&self) -> Vec<u8> {
593 to_vec(&json!(self)).unwrap()
594 }
595}
596impl Argument<String> {
598 pub fn string(value: String) -> Argument<String> {
600 Argument {
601 r#type: "String",
602 value,
603 }
604 }
605 pub fn ufix64(value: f64) -> Argument<String> {
607 assert!(value >= 0.0, "{}", true); Argument {
609 r#type: "UFix64",
610 value: value.to_string(),
611 }
612 }
613 pub fn fix64(value: f64) -> Argument<String> {
615 Argument {
616 r#type: "Fix64",
617 value: value.to_string(),
618 }
619 }
620 pub fn uint64(value: u64) -> Argument<String> {
622 Argument {
623 r#type: "UInt64",
624 value: value.to_string(),
625 }
626 }
627 pub fn int64(value: i64) -> Argument<String> {
629 Argument {
630 r#type: "Int64",
631 value: value.to_string(),
632 }
633 }
634 pub fn address(value: String) -> Argument<String> {
636 Argument {
637 r#type: "Address",
638 value,
639 }
640 }
641 pub fn encode(&self) -> Vec<u8> {
643 to_vec(&json!(self)).unwrap()
644 }
645}
646fn padding(vec: &mut Vec<u8>, count: usize) {
648 let mut i: usize = count;
649 i -= vec.len();
650 while i > 0 {
651 vec.push(0);
652 i -= 1;
653 }
654}
655pub struct Sign {
658 pub address: String,
659 pub key_id: u32,
660 pub private_key: String,
661}
662pub async fn build_transaction(
665 script: Vec<u8>,
666 arguments: Vec<Vec<u8>>,
667 reference_block_id: Vec<u8>,
668 gas_limit: u64,
669 proposer: TransactionProposalKey,
670 authorizers: Vec<String>,
671 payer: String,
672) -> Result<Transaction, Box<dyn error::Error>> {
673 Ok(Transaction {
674 script,
675 arguments,
676 reference_block_id,
677 gas_limit,
678 proposal_key: Some(proposer),
679 authorizers: authorizers
680 .iter()
681 .map(|x| hex::decode(x).unwrap())
682 .collect(),
683 payload_signatures: vec![],
684 envelope_signatures: vec![],
685 payer: hex::decode(payer).unwrap(),
686 })
687}
688fn envelope_from_transaction(
690 transaction: Transaction,
691 payload_signatures: &[TransactionSignature],
692) -> Vec<u8> {
693 let proposal_key = transaction.proposal_key.unwrap();
694 let mut proposal_address = proposal_key.address;
695 padding(&mut proposal_address, 8);
696 let mut ref_block = transaction.reference_block_id;
697 padding(&mut ref_block, 32);
698 let mut stream = RlpStream::new_list(2);
699
700 stream.begin_list(9);
701 stream.append(&Bytes::from(transaction.script).to_vec());
702 stream.begin_list(transaction.arguments.len());
703 for (_i, arg) in transaction.arguments.into_iter().enumerate() {
704 stream.append(&Bytes::from(arg).to_vec());
705 }
706
707 stream.append(&Bytes::from(ref_block).to_vec());
708 stream.append(&transaction.gas_limit);
709 stream.append(&Bytes::from(proposal_address).to_vec());
710 stream.append(&proposal_key.key_id);
711 stream.append(&proposal_key.sequence_number);
712 stream.append(&Bytes::from(transaction.payer).to_vec());
713
714 stream.begin_list(transaction.authorizers.len());
715 for (_i, auth) in transaction.authorizers.into_iter().enumerate() {
716 stream.append(&Bytes::from(auth).to_vec());
717 }
718
719 stream.begin_list(payload_signatures.len());
720 for (i, sig) in payload_signatures.iter().enumerate() {
721 let signature = sig.signature.to_vec();
722 stream.begin_list(3);
723 stream.append(&(i as u32));
724 stream.append(&sig.key_id);
725 stream.append(&signature);
726 }
727
728 stream.out().to_vec()
729}
730fn payload_from_transaction(transaction: Transaction) -> Vec<u8> {
732 let proposal_key = transaction.proposal_key.unwrap();
733 let mut proposal_address = proposal_key.address;
734 padding(&mut proposal_address, 8);
735 let mut ref_block = transaction.reference_block_id;
736 padding(&mut ref_block, 32);
737
738 let mut stream = RlpStream::new_list(9);
739 stream.append(&Bytes::from(transaction.script).to_vec());
740 stream.begin_list(transaction.arguments.len());
741 for (_i, arg) in transaction.arguments.into_iter().enumerate() {
742 stream.append(&Bytes::from(arg).to_vec());
743 }
744
745 stream.append(&Bytes::from(ref_block).to_vec());
746 stream.append(&transaction.gas_limit);
747 stream.append(&Bytes::from(proposal_address).to_vec());
748 stream.append(&proposal_key.key_id);
749 stream.append(&proposal_key.sequence_number);
750 stream.append(&Bytes::from(transaction.payer).to_vec());
751
752 stream.begin_list(transaction.authorizers.len());
753 for (_i, auth) in transaction.authorizers.into_iter().enumerate() {
754 stream.append(&Bytes::from(auth).to_vec());
755 }
756 stream.out().to_vec()
757}
758fn sign(message: Vec<u8>, private_key: String) -> Result<Vec<u8>, Box<dyn error::Error>> {
760 let secret_key = SecretKey::from_be_bytes(&hex::decode(private_key)?)?;
761 let sig_key = SigningKey::from(secret_key);
762 let signature = sig_key.sign(&message);
763 Ok(signature.as_bytes().to_vec())
764}
765pub fn process_keys_args(account_keys: Vec<String>) -> Argument<Vec<Value>> {
767 Argument::array(
772 account_keys
773 .into_iter()
774 .map(|x| json!(Argument::string(format!("f847b840{}02038203e8", x))))
775 .collect::<Vec<Value>>(),
776 )
777}
778pub async fn sign_transaction(
781 built_transaction: Transaction,
782 payload_signatures: Vec<&Sign>,
783 envelope_signatures: Vec<&Sign>,
784) -> Result<Option<Transaction>, Box<dyn error::Error>> {
785 let mut payload: Vec<TransactionSignature> = vec![];
786 let mut envelope: Vec<TransactionSignature> = vec![];
787 for signer in payload_signatures {
789 let encoded_payload: &[u8] = &payload_from_transaction(built_transaction.clone());
790 let mut domain_tag: Vec<u8> = b"FLOW-V0.0-transaction".to_vec();
791 padding(&mut domain_tag, 32);
793
794 let fully_encoded: Vec<u8> = [&domain_tag, encoded_payload].concat();
795 let mut addr = hex::decode(signer.address.clone()).unwrap();
796 padding(&mut addr, 8);
797
798 payload.push(TransactionSignature {
799 address: addr,
800 key_id: signer.key_id,
801 signature: sign(fully_encoded, signer.private_key.clone())?,
802 });
803 }
804 for signer in envelope_signatures {
806 let encoded_payload: &[u8] =
807 &envelope_from_transaction(built_transaction.clone(), &payload);
808 let mut domain_tag: Vec<u8> = b"FLOW-V0.0-transaction".to_vec();
809 padding(&mut domain_tag, 32);
811
812 let fully_encoded: Vec<u8> = [&domain_tag, encoded_payload].concat();
813 let mut addr = hex::decode(signer.address.clone()).unwrap();
814 padding(&mut addr, 8);
815
816 envelope.push(TransactionSignature {
817 address: addr,
818 key_id: signer.key_id,
819 signature: sign(fully_encoded, signer.private_key.clone())?,
820 });
821 }
822 let signed_transaction = Some(Transaction {
823 script: built_transaction.script,
824 arguments: built_transaction.arguments,
825 reference_block_id: built_transaction.reference_block_id,
826 gas_limit: built_transaction.gas_limit,
827 proposal_key: built_transaction.proposal_key,
828 authorizers: built_transaction.authorizers,
829 payload_signatures: payload,
830 envelope_signatures: envelope,
831 payer: built_transaction.payer,
832 });
833 Ok(signed_transaction)
834}
835
836#[cfg(test)]
841mod tests {
842 #[tokio::test]
843 async fn meaningful_test() {
844 println!("does not exist yet. :)")
845 }
846}