thruput_signing/
default_wallet.rs1use thruput_xdr::contract::{Contract, ContractEntrypointID};
9use thruput_xdr::transaction::Transaction;
10use thruput_xdr::types::{ContractAddress, SHA256Hash};
11use xdr_common::VecM;
12
13use crate::{
14 BuildCallTransaction, BuildDeployTransaction, PubkeyAccount, SigningError,
15 build_call_transaction, build_deploy_transaction, wallet_contract_hash,
16};
17
18pub const DEFAULT_WALLET_EXECUTE_ENTRYPOINT: ContractEntrypointID =
20 ContractEntrypointID::new(0xc3ed_b11f_dd6d_5d58_u64.to_be_bytes());
21pub const DEFAULT_WALLET_DEPLOY_ENTRYPOINT: ContractEntrypointID =
23 ContractEntrypointID::new(0x6be0_cb0f_6de0_917a_u64.to_be_bytes());
24
25#[derive(Debug, Clone, Copy)]
28pub struct WalletInitCall<'a> {
29 pub entrypoint: ContractEntrypointID,
31 pub gas_limit: u64,
33 pub calldata: &'a [u8],
35}
36
37#[derive(Debug, Clone, Copy)]
39pub struct BuildDefaultWalletCallTransaction<'a> {
40 pub account: &'a PubkeyAccount,
42 pub target_address: ContractAddress,
43 pub target_entrypoint: ContractEntrypointID,
44 pub target_calldata: &'a [u8],
45 pub target_gas_limit: u64,
46 pub gas_limit: u64,
47 pub block_expiry_height: i64,
48 pub nonce: u64,
50}
51
52pub fn build_default_wallet_call_transaction(
54 args: BuildDefaultWalletCallTransaction<'_>,
55) -> Result<Transaction, SigningError> {
56 let call = (
57 args.target_address,
58 args.target_entrypoint,
59 args.target_gas_limit,
60 args.target_calldata,
61 );
62 let calldata = xdrs::cxs::encode(&[call].as_slice())
63 .map_err(|error| SigningError::XdrEncode(error.to_string()))?;
64 Ok(build_call_transaction(BuildCallTransaction {
65 invoked_address: args.account.address(),
66 entrypoint: DEFAULT_WALLET_EXECUTE_ENTRYPOINT,
67 calldata,
68 gas_limit: args.gas_limit,
69 block_expiry_height: args.block_expiry_height,
70 nonce: args.nonce,
71 auth_claim: args.account.auth_claim(),
72 }))
73}
74
75#[derive(Debug, Clone)]
77pub enum DeploymentCode {
78 Attached(Contract),
80 Registered(SHA256Hash),
82}
83
84#[derive(Debug, Clone)]
86pub struct BuildDefaultWalletDeployTransaction<'a> {
87 pub account: &'a PubkeyAccount,
88 pub deployment_nonce: SHA256Hash,
90 pub code: DeploymentCode,
91 pub amount: u128,
93 pub initializer: Option<WalletInitCall<'a>>,
95 pub gas_limit: u64,
96 pub block_expiry_height: i64,
97 pub nonce: u64,
98}
99
100pub fn build_default_wallet_deploy_transaction(
104 args: BuildDefaultWalletDeployTransaction<'_>,
105) -> Result<Transaction, SigningError> {
106 let (hash, contracts_to_deploy) = match args.code {
107 DeploymentCode::Attached(contract) => {
108 (wallet_contract_hash(&contract)?, VecM(vec![contract]))
109 }
110 DeploymentCode::Registered(hash) => (hash, VecM(vec![])),
111 };
112 let initializer = args
113 .initializer
114 .map(|call| (call.entrypoint, call.gas_limit, call.calldata));
115 let calldata = xdrs::cxs::encode(&(args.deployment_nonce, hash, args.amount, initializer))
116 .map_err(|error| SigningError::XdrEncode(error.to_string()))?;
117 Ok(build_deploy_transaction(BuildDeployTransaction {
118 invoked_address: args.account.address(),
119 entrypoint: DEFAULT_WALLET_DEPLOY_ENTRYPOINT,
120 calldata,
121 gas_limit: args.gas_limit,
122 block_expiry_height: args.block_expiry_height,
123 nonce: args.nonce,
124 contracts_to_deploy,
125 auth_claim: args.account.auth_claim(),
126 }))
127}
128
129const DEFAULT_WALLET_RETURN_DECODE_LIMIT: usize = 1024;
130
131pub fn decode_default_wallet_call_return(data: &[u8]) -> Result<Vec<u8>, SigningError> {
136 if data.len() > DEFAULT_WALLET_RETURN_DECODE_LIMIT {
137 return Err(SigningError::XdrDecode(
138 "native wallet return exceeds decoder buffer limit".into(),
139 ));
140 }
141 let mut returns: Vec<Vec<u8>> =
142 xdrs::cxs::decode(data).map_err(|error| SigningError::XdrDecode(error.to_string()))?;
143 if returns.len() != 1 {
144 return Err(SigningError::UnexpectedWalletReturnCount(returns.len()));
145 }
146 Ok(returns.remove(0))
147}