Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#397] Add ZIP 321 URI parser #1409

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,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,
Expand Down Expand Up @@ -573,6 +589,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(
Expand Down
43 changes: 43 additions & 0 deletions backend-lib/src/main/rust/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1402,6 +1402,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>,
Expand Down
13 changes: 13 additions & 0 deletions sdk-lib/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,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,
Expand Down
13 changes: 13 additions & 0 deletions sdk-lib/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ internal interface TypesafeBackend {
recoverUntil: BlockHeight?
): UnifiedSpendingKey

suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal

@Suppress("LongParameterList")
suspend fun proposeTransfer(
account: Account,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down