Compare commits

...

2 Commits

Author SHA1 Message Date
Pacu 0ab4ee3812
Merge 919aa65a10 into 315e8bf4fe 2024-04-12 05:46:14 +08:00
Francisco Gindre 919aa65a10
[#397] Add ZIP 321 URI parser
adds a transaction proposal API for URI strings

Closes #397

Add `proposeFulfillingPaymentUri` to changelog
2024-03-08 22:23:39 -03:00
12 changed files with 185 additions and 0 deletions

View File

@ -53,6 +53,7 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
transactions.
- `Synchronizer.proposeTransfer`
- `Synchronizer.proposeShielding`
- `Synchronizer.proposeFulfillingPaymentUri`
- `Synchronizer.createProposedTransactions`
- `WalletBalanceFixture` class with mock values that are supposed to be used only for testing purposes
- `Memo.countLength(memoString: String)` to count memo length in bytes

View File

@ -28,6 +28,11 @@ interface Backend {
memo: ByteArray? = byteArrayOf()
): ProposalUnsafe
suspend fun proposeTransferFromUri(
account: Int,
uri: String
): ProposalUnsafe
suspend fun proposeShielding(
account: Int,
shieldingThreshold: Long,

View File

@ -300,6 +300,22 @@ class RustBackend private constructor(
)
}
override suspend fun proposeTransferFromUri(
account: Int,
uri: String
): ProposalUnsafe =
withContext(SdkDispatchers.DATABASE_IO) {
ProposalUnsafe.parse(
proposeTransferFromUri(
dataDbFile.absolutePath,
account,
uri,
networkId = networkId,
useZip317Fees = IS_USE_ZIP_317_FEES
)
)
}
override suspend fun proposeTransfer(
account: Int,
to: String,
@ -600,6 +616,16 @@ class RustBackend private constructor(
networkId: Int
)
@JvmStatic
@Suppress("LongParameterList")
private external fun proposeTransferFromUri(
dbDataPath: String,
account: Int,
uri: String,
networkId: Int,
useZip317Fees: Boolean
): ByteArray
@JvmStatic
@Suppress("LongParameterList")
private external fun proposeTransfer(

View File

@ -1535,6 +1535,49 @@ fn zip317_helper<DbT>(
)
}
#[no_mangle]
pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeTransferFromUri<'local>(
mut env: JNIEnv<'local>,
_: JClass<'local>,
db_data: JString<'local>,
account: jint,
payment_uri: JString<'local>,
network_id: jint,
use_zip317_fees: jboolean,
) -> jbyteArray {
let res = catch_unwind(&mut env, |env| {
let _span = tracing::info_span!("RustBackend.proposeTransfer").entered();
let network = parse_network(network_id as u32)?;
let mut db_data = wallet_db(env, network, db_data)?;
let account = account_id_from_jint(account)?;
let payment_uri = utils::java_string_to_rust(env, &payment_uri);
let input_selector = zip317_helper(None, use_zip317_fees);
let request = TransactionRequest::from_uri(&network, &payment_uri)
.map_err(|e| format_err!("Error creating transaction request: {:?}", e))?;
let proposal = propose_transfer::<_, _, _, Infallible>(
&mut db_data,
&network,
account,
&input_selector,
request,
ANCHOR_OFFSET,
)
.map_err(|e| format_err!("Error creating transaction proposal: {}", e))?;
utils::rust_bytes_to_java(
&env,
Proposal::from_standard_proposal(&network, &proposal)
.encode_to_vec()
.as_ref(),
)
.map(|arr| arr.into_raw())
});
unwrap_exc_or(&mut env, res, ptr::null_mut())
}
#[no_mangle]
pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeTransfer<'local>(
mut env: JNIEnv<'local>,

View File

@ -555,6 +555,19 @@ class SdkSynchronizer private constructor(
account
)
/**
* Creates a proposal for fulfilling a payment ZIP-321 URI
*
* @param account the account from which to transfer funds.
* @param uri a ZIP-321 compliant payment URI String
*
* @return the proposal or an exception
*/
@Throws(TransactionEncoderException::class)
override suspend fun proposeFulfillingPaymentUri(
account: Account,
uri: String
): Proposal = txManager.proposeTransferFromUri(account, uri)
@Throws(TransactionEncoderException::class)
override suspend fun proposeTransfer(
account: Account,

View File

@ -186,6 +186,19 @@ interface Synchronizer {
memo: String = ""
): Proposal
/**
* Creates a proposal for fulfilling a payment ZIP-321 URI
*
* @param account the account from which to transfer funds.
* @param uri a ZIP-321 compliant payment URI String
*
* @return the proposal or an exception
*/
suspend fun proposeFulfillingPaymentUri(
account: Account,
uri: String
): Proposal
/**
* Creates a proposal for shielding any transparent funds received by the given account.
*

View File

@ -25,6 +25,11 @@ internal interface TypesafeBackend {
recoverUntil: BlockHeight?
): UnifiedSpendingKey
suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal
@Suppress("LongParameterList")
suspend fun proposeTransfer(
account: Account,

View File

@ -36,6 +36,17 @@ internal class TypesafeBackendImpl(private val backend: Backend) : TypesafeBacke
)
}
override suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal =
Proposal.fromUnsafe(
backend.proposeTransferFromUri(
account.value,
uri
)
)
@Suppress("LongParameterList")
override suspend fun proposeTransfer(
account: Account,

View File

@ -35,6 +35,19 @@ internal interface OutboundTransactionManager {
account: Account
): EncodedTransaction
/**
* Creates a proposal for transferring funds from a ZIP-321 compliant payment URI
*
* @param account the account from which to transfer funds.
* @param uri a ZIP-321 compliant payment URI
*
* @return the proposal or an exception
*/
suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal
/**
* Creates a proposal for transferring funds to the given recipient.
*

View File

@ -43,6 +43,18 @@ internal class OutboundTransactionManagerImpl(
}
}
/**
* Creates a proposal for transferring funds from a ZIP-321 compliant payment URI
*
* @param account the account from which to transfer funds.
* @param uri a ZIP-321 compliant payment URI
*
* @return the proposal or an exception
*/
override suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal = encoder.proposeTransferFromUri(account, uri)
override suspend fun proposeTransfer(
account: Account,
recipient: String,

View File

@ -40,6 +40,19 @@ internal interface TransactionEncoder {
memo: ByteArray? = byteArrayOf()
): EncodedTransaction
/**
* Creates a proposal for transferring from a valid ZIP-321 Payment URI string
*
* @param account the account from which to transfer funds.
* @param uri a valid ZIP-321 Payment URI string
*
* @return the proposal or an exception
*/
suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal
/**
* Creates a proposal for transferring funds to the given recipient.
*

View File

@ -68,6 +68,36 @@ internal class TransactionEncoderImpl(
?: throw TransactionEncoderException.TransactionNotFoundException(transactionId)
}
/**
* Creates a proposal for transferring from a valid ZIP-321 Payment URI string
*
* @param account the account from which to transfer funds.
* @param uri a valid ZIP-321 Payment URI string
*
* @return the proposal or an exception
*/
override suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal {
Twig.debug {
"creating proposal from URI: $uri"
}
@Suppress("TooGenericExceptionCaught")
return try {
backend.proposeTransferFromUri(
account,
uri
)
} catch (t: Throwable) {
Twig.debug(t) { "Caught exception while creating proposal from URI String." }
throw t
}.also { result ->
Twig.debug { "result of proposeTransferFromUri: $result" }
}
}
override suspend fun proposeTransfer(
account: Account,
recipient: String,