mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-06-18 03:41:07 +00:00
Initial commit: Pezkuwi Wallet Android
Complete rebrand of Nova Wallet for Pezkuwichain ecosystem. ## Features - Full Pezkuwichain support (HEZ & PEZ tokens) - Polkadot ecosystem compatibility - Staking, Governance, DeFi, NFTs - XCM cross-chain transfers - Hardware wallet support (Ledger, Polkadot Vault) - WalletConnect v2 - Push notifications ## Languages - English, Turkish, Kurmanci (Kurdish), Spanish, French, German, Russian, Japanese, Chinese, Korean, Portuguese, Vietnamese Based on Nova Wallet by Novasama Technologies GmbH © Dijital Kurdistan Tech Institute 2026
This commit is contained in:
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,39 @@
|
||||
apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
|
||||
|
||||
android {
|
||||
|
||||
ndkVersion "26.1.10909125"
|
||||
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
namespace 'io.novafoundation.nova.hydra_dx_math'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation kotlinDep
|
||||
implementation project(':common')
|
||||
|
||||
testImplementation jUnitDep
|
||||
|
||||
androidTestImplementation androidTestRunnerDep
|
||||
androidTestImplementation androidTestRulesDep
|
||||
androidTestImplementation androidJunitDep
|
||||
}
|
||||
|
||||
cargo {
|
||||
module = "rust/"
|
||||
libname = "hydra_dx_math_java"
|
||||
targets = ["arm", "arm64", "x86", "x86_64"]
|
||||
profile = "release"
|
||||
pythonCommand = "python3"
|
||||
}
|
||||
|
||||
tasks.matching { it.name.matches(/merge.*JniLibFolders/) }.configureEach {
|
||||
it.inputs.dir(new File(buildDir, "rustJniLibs/android"))
|
||||
it.dependsOn("cargoBuild")
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
.idea
|
||||
target
|
||||
Generated
+2916
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
[package]
|
||||
authors = ['Novasama Technologies']
|
||||
edition = '2021'
|
||||
license = 'Apache 2.0'
|
||||
name = "hydra-dx-math-java"
|
||||
repository = 'https://github.com/nova-wallet/nova-wallet-android'
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.169", features = ["derive"] }
|
||||
serde_json = "1.0.100"
|
||||
serde-aux = "4.2.0"
|
||||
sp-arithmetic = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch6", default-features = false }
|
||||
hydra-dx-math = { git = "https://github.com/galacticcouncil/HydraDX-node", version="10.3.0"}
|
||||
jni = { version = "0.17.0", default-features = false }
|
||||
|
||||
[profile.release]
|
||||
strip = true
|
||||
lto = true
|
||||
opt-level = "s"
|
||||
|
||||
[lib]
|
||||
name = "hydra_dx_math_java"
|
||||
crate_type = ["cdylib"]
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["sp-arithmetic/std"]
|
||||
stableswap = []
|
||||
@@ -0,0 +1,732 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
extern crate core;
|
||||
extern crate hydra_dx_math;
|
||||
extern crate jni;
|
||||
extern crate serde;
|
||||
extern crate sp_arithmetic;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use hydra_dx_math::stableswap::types::AssetReserve;
|
||||
use jni::objects::{JClass, JString};
|
||||
use jni::sys::jint;
|
||||
use jni::JNIEnv;
|
||||
use serde::Deserialize;
|
||||
use sp_arithmetic::per_things::Permill;
|
||||
use serde_aux::prelude::*;
|
||||
|
||||
fn error() -> String {
|
||||
"-1".to_string()
|
||||
}
|
||||
|
||||
macro_rules! parse_into {
|
||||
($x:ty, $y:expr) => {{
|
||||
let r = if let Some(x) = $y.parse::<$x>().ok() {
|
||||
x
|
||||
} else {
|
||||
println!("Parse failed");
|
||||
return error();
|
||||
};
|
||||
r
|
||||
}};
|
||||
}
|
||||
|
||||
const D_ITERATIONS: u8 = 128;
|
||||
const Y_ITERATIONS: u8 = 64;
|
||||
|
||||
#[derive(Deserialize, Copy, Clone, Debug)]
|
||||
pub struct AssetBalance {
|
||||
asset_id: u32,
|
||||
#[serde(deserialize_with = "deserialize_number_from_string")]
|
||||
amount: u128,
|
||||
decimals: u8,
|
||||
}
|
||||
|
||||
impl From<&AssetBalance> for AssetReserve {
|
||||
fn from(value: &AssetBalance) -> Self {
|
||||
Self {
|
||||
amount: value.amount,
|
||||
decimals: value.decimals,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Copy, Clone, Debug)]
|
||||
pub struct AssetAmount {
|
||||
asset_id: u32,
|
||||
#[serde(deserialize_with = "deserialize_number_from_string")]
|
||||
amount: u128,
|
||||
}
|
||||
|
||||
// Tuple struct to apply per-field deserializers on u128s
|
||||
#[derive(Deserialize, Copy, Clone, Debug)]
|
||||
struct U128Pair(
|
||||
#[serde(deserialize_with = "deserialize_number_from_string")] u128,
|
||||
#[serde(deserialize_with = "deserialize_number_from_string")] u128,
|
||||
);
|
||||
|
||||
// Parse JSON like: [["0","0"],["1000000000000","500000000000"],["42","1337"]]
|
||||
fn parse_pairs(json: &str) -> Option<Vec<(u128, u128)>> {
|
||||
let v: serde_json::Result<Vec<U128Pair>> = serde_json::from_str(json);
|
||||
match v {
|
||||
Ok(vecp) => Some(vecp.into_iter().map(|p| (p.0, p.1)).collect()),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_str<'a>(jni: &'a JNIEnv<'a>, string: JString<'a>) -> String {
|
||||
jni.get_string(string).unwrap().to_str().unwrap().to_string()
|
||||
}
|
||||
|
||||
/* ---------------- STABLESWAP ---------------- */
|
||||
|
||||
#[no_mangle]
|
||||
pub fn Java_io_novafoundation_nova_hydra_1dx_1math_stableswap_StableSwapMathBridge_calculate_1out_1given_1in<'a>(
|
||||
jni_env: JNIEnv<'a>,
|
||||
_: JClass,
|
||||
reserves: JString,
|
||||
asset_in: jint,
|
||||
asset_out: jint,
|
||||
amount_in: JString,
|
||||
amplification: JString,
|
||||
fee: JString,
|
||||
pegs: JString,
|
||||
) -> JString<'a> {
|
||||
let reserves = get_str(&jni_env, reserves);
|
||||
let asset_in = asset_in as u32;
|
||||
let asset_out = asset_out as u32;
|
||||
let amount_in = get_str(&jni_env, amount_in);
|
||||
let amplification = get_str(&jni_env, amplification);
|
||||
let fee = get_str(&jni_env, fee);
|
||||
let pegs = get_str(&jni_env, pegs);
|
||||
|
||||
let out = calculate_out_given_in(
|
||||
reserves,
|
||||
asset_in,
|
||||
asset_out,
|
||||
amount_in,
|
||||
amplification,
|
||||
fee,
|
||||
pegs,
|
||||
);
|
||||
|
||||
jni_env.new_string(out).unwrap()
|
||||
}
|
||||
|
||||
fn calculate_out_given_in(
|
||||
reserves: String,
|
||||
asset_in: u32,
|
||||
asset_out: u32,
|
||||
amount_in: String,
|
||||
amplification: String,
|
||||
fee: String,
|
||||
pegs: String,
|
||||
) -> String {
|
||||
let reserves: serde_json::Result<Vec<AssetBalance>> = serde_json::from_str(&reserves);
|
||||
if reserves.is_err() {
|
||||
return error();
|
||||
}
|
||||
let mut reserves = reserves.unwrap();
|
||||
reserves.sort_by_key(|v| v.asset_id);
|
||||
|
||||
let idx_in = reserves.iter().position(|v| v.asset_id == asset_in);
|
||||
let idx_out = reserves.iter().position(|v| v.asset_id == asset_out);
|
||||
|
||||
if idx_in.is_none() || idx_out.is_none() {
|
||||
return error();
|
||||
}
|
||||
|
||||
let amount_in = parse_into!(u128, amount_in);
|
||||
let amplification = parse_into!(u128, amplification);
|
||||
let fee = Permill::from_float(parse_into!(f64, fee));
|
||||
let balances: Vec<AssetReserve> = reserves.iter().map(|v| v.into()).collect();
|
||||
|
||||
// Parse 7th param
|
||||
let pairs = match parse_pairs(&pegs) {
|
||||
Some(p) => p,
|
||||
None => return error(),
|
||||
};
|
||||
|
||||
let result = hydra_dx_math::stableswap::calculate_out_given_in_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
|
||||
&balances,
|
||||
idx_in.unwrap(),
|
||||
idx_out.unwrap(),
|
||||
amount_in,
|
||||
amplification,
|
||||
fee,
|
||||
&pairs,
|
||||
);
|
||||
|
||||
if let Some(r) = result {
|
||||
r.0.to_string()
|
||||
} else {
|
||||
error()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn Java_io_novafoundation_nova_hydra_1dx_1math_stableswap_StableSwapMathBridge_calculate_1in_1given_1out<'a>(
|
||||
jni_env: JNIEnv<'a>,
|
||||
_: JClass,
|
||||
reserves: JString,
|
||||
asset_in: jint,
|
||||
asset_out: jint,
|
||||
amount_in: JString,
|
||||
amplification: JString,
|
||||
fee: JString,
|
||||
pegs: JString,
|
||||
) -> JString<'a> {
|
||||
let reserves = get_str(&jni_env, reserves);
|
||||
let asset_in = asset_in as u32;
|
||||
let asset_out = asset_out as u32;
|
||||
let amount_in = get_str(&jni_env, amount_in);
|
||||
let amplification = get_str(&jni_env, amplification);
|
||||
let fee = get_str(&jni_env, fee);
|
||||
let pegs = get_str(&jni_env, pegs);
|
||||
|
||||
let result = calculate_in_given_out(
|
||||
reserves,
|
||||
asset_in,
|
||||
asset_out,
|
||||
amount_in,
|
||||
amplification,
|
||||
fee,
|
||||
pegs,
|
||||
);
|
||||
|
||||
jni_env.new_string(result).unwrap()
|
||||
}
|
||||
|
||||
fn calculate_in_given_out(
|
||||
reserves: String,
|
||||
asset_in: u32,
|
||||
asset_out: u32,
|
||||
amount_out: String,
|
||||
amplification: String,
|
||||
fee: String,
|
||||
pegs: String,
|
||||
) -> String {
|
||||
let reserves: serde_json::Result<Vec<AssetBalance>> = serde_json::from_str(&reserves);
|
||||
if reserves.is_err() {
|
||||
return error();
|
||||
}
|
||||
let mut reserves = reserves.unwrap();
|
||||
reserves.sort_by_key(|v| v.asset_id);
|
||||
|
||||
let idx_in = reserves.iter().position(|v| v.asset_id == asset_in);
|
||||
let idx_out = reserves.iter().position(|v| v.asset_id == asset_out);
|
||||
|
||||
if idx_in.is_none() || idx_out.is_none() {
|
||||
return error();
|
||||
}
|
||||
|
||||
let amount_out = parse_into!(u128, amount_out);
|
||||
let amplification = parse_into!(u128, amplification);
|
||||
let fee = Permill::from_float(parse_into!(f64, fee));
|
||||
|
||||
let balances: Vec<AssetReserve> = reserves.iter().map(|v| v.into()).collect();
|
||||
|
||||
// Parse 7th param
|
||||
let pairs = match parse_pairs(&pegs) {
|
||||
Some(p) => p,
|
||||
None => return error(),
|
||||
};
|
||||
|
||||
let result =
|
||||
hydra_dx_math::stableswap::calculate_in_given_out_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
|
||||
&balances,
|
||||
idx_in.unwrap(),
|
||||
idx_out.unwrap(),
|
||||
amount_out,
|
||||
amplification,
|
||||
fee,
|
||||
&pairs,
|
||||
);
|
||||
|
||||
if let Some(r) = result {
|
||||
r.0.to_string()
|
||||
} else {
|
||||
error()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn Java_io_novafoundation_nova_hydra_1dx_1math_stableswap_StableSwapMathBridge_calculate_1amplification<'a>(
|
||||
jni_env: JNIEnv<'a>,
|
||||
_: JClass,
|
||||
initial_amplification: JString,
|
||||
final_amplification: JString,
|
||||
initial_block: JString,
|
||||
final_block: JString,
|
||||
current_block: JString,
|
||||
) -> JString<'a> {
|
||||
let initial_amplification = get_str(&jni_env, initial_amplification);
|
||||
let final_amplification = get_str(&jni_env, final_amplification);
|
||||
let initial_block = get_str(&jni_env, initial_block);
|
||||
let final_block = get_str(&jni_env, final_block);
|
||||
let current_block = get_str(&jni_env, current_block);
|
||||
|
||||
let result = calculate_amplification(
|
||||
initial_amplification,
|
||||
final_amplification,
|
||||
initial_block,
|
||||
final_block,
|
||||
current_block,
|
||||
);
|
||||
|
||||
jni_env.new_string(result).unwrap()
|
||||
}
|
||||
|
||||
fn calculate_amplification(
|
||||
initial_amplification: String,
|
||||
final_amplification: String,
|
||||
initial_block: String,
|
||||
final_block: String,
|
||||
current_block: String,
|
||||
) -> String {
|
||||
let initial_amplification = parse_into!(u128, initial_amplification);
|
||||
let final_amplification = parse_into!(u128, final_amplification);
|
||||
let initial_block = parse_into!(u128, initial_block);
|
||||
let final_block = parse_into!(u128, final_block);
|
||||
let current_block = parse_into!(u128, current_block);
|
||||
|
||||
hydra_dx_math::stableswap::calculate_amplification(
|
||||
initial_amplification,
|
||||
final_amplification,
|
||||
initial_block,
|
||||
final_block,
|
||||
current_block,
|
||||
)
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn Java_io_novafoundation_nova_hydra_1dx_1math_stableswap_StableSwapMathBridge_calculate_1shares<'a>(
|
||||
jni_env: JNIEnv<'a>,
|
||||
_: JClass,
|
||||
reserves: JString,
|
||||
assets: JString,
|
||||
amplification: JString,
|
||||
share_issuance: JString,
|
||||
fee: JString,
|
||||
pegs: JString,
|
||||
) -> JString<'a> {
|
||||
let reserves = get_str(&jni_env, reserves);
|
||||
let assets = get_str(&jni_env, assets);
|
||||
let amplification = get_str(&jni_env, amplification);
|
||||
let share_issuance = get_str(&jni_env, share_issuance);
|
||||
let fee = get_str(&jni_env, fee);
|
||||
let pegs = get_str(&jni_env, pegs);
|
||||
|
||||
let result = calculate_shares(reserves, assets, amplification, share_issuance, fee, pegs);
|
||||
|
||||
jni_env.new_string(result).unwrap()
|
||||
}
|
||||
|
||||
fn calculate_shares(
|
||||
reserves: String,
|
||||
assets: String,
|
||||
amplification: String,
|
||||
share_issuance: String,
|
||||
fee: String,
|
||||
pegs: String,
|
||||
) -> String {
|
||||
let reserves: serde_json::Result<Vec<AssetBalance>> = serde_json::from_str(&reserves);
|
||||
if reserves.is_err() {
|
||||
return error();
|
||||
}
|
||||
let mut reserves = reserves.unwrap();
|
||||
reserves.sort_by_key(|v| v.asset_id);
|
||||
|
||||
let assets: serde_json::Result<Vec<AssetAmount>> = serde_json::from_str(&assets);
|
||||
if assets.is_err() {
|
||||
return error();
|
||||
}
|
||||
let assets = assets.unwrap();
|
||||
if assets.len() > reserves.len() {
|
||||
return error();
|
||||
}
|
||||
|
||||
let mut updated_reserves = reserves.clone();
|
||||
|
||||
let mut liquidity: HashMap<u32, u128> = HashMap::new();
|
||||
for a in assets.iter() {
|
||||
let r = liquidity.insert(a.asset_id, a.amount);
|
||||
if r.is_some() {
|
||||
return error();
|
||||
}
|
||||
}
|
||||
for reserve in updated_reserves.iter_mut() {
|
||||
if let Some(v) = liquidity.get(&reserve.asset_id) {
|
||||
reserve.amount += v;
|
||||
}
|
||||
}
|
||||
let balances: Vec<AssetReserve> = reserves.iter().map(|v| v.into()).collect();
|
||||
let updated_balances: Vec<AssetReserve> = updated_reserves.iter().map(|v| v.into()).collect();
|
||||
let amplification = parse_into!(u128, amplification);
|
||||
let issuance = parse_into!(u128, share_issuance);
|
||||
let fee = Permill::from_float(parse_into!(f64, fee));
|
||||
|
||||
let pairs = match parse_pairs(&pegs) {
|
||||
Some(p) => p,
|
||||
None => return error(),
|
||||
};
|
||||
|
||||
let result = hydra_dx_math::stableswap::calculate_shares::<D_ITERATIONS>(
|
||||
&balances,
|
||||
&updated_balances,
|
||||
amplification,
|
||||
issuance,
|
||||
fee,
|
||||
&pairs,
|
||||
);
|
||||
|
||||
if let Some(r) = result {
|
||||
r.0.to_string()
|
||||
} else {
|
||||
error()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn Java_io_novafoundation_nova_hydra_1dx_1math_stableswap_StableSwapMathBridge_calculate_1shares_1for_1amount<'a>(
|
||||
jni_env: JNIEnv<'a>,
|
||||
_: JClass,
|
||||
reserves: JString,
|
||||
asset_in: jint,
|
||||
amount: JString,
|
||||
amplification: JString,
|
||||
share_issuance: JString,
|
||||
fee: JString,
|
||||
pegs: JString,
|
||||
) -> JString<'a> {
|
||||
let reserves = get_str(&jni_env, reserves);
|
||||
let asset_in = asset_in as u32;
|
||||
let amount = get_str(&jni_env, amount);
|
||||
let amplification = get_str(&jni_env, amplification);
|
||||
let share_issuance = get_str(&jni_env, share_issuance);
|
||||
let fee = get_str(&jni_env, fee);
|
||||
let pegs = get_str(&jni_env, pegs);
|
||||
|
||||
let result = calculate_shares_for_amount(
|
||||
reserves,
|
||||
asset_in,
|
||||
amount,
|
||||
amplification,
|
||||
share_issuance,
|
||||
fee,
|
||||
pegs,
|
||||
);
|
||||
|
||||
jni_env.new_string(result).unwrap()
|
||||
}
|
||||
|
||||
fn calculate_shares_for_amount(
|
||||
reserves: String,
|
||||
asset_in: u32,
|
||||
amount: String,
|
||||
amplification: String,
|
||||
share_issuance: String,
|
||||
fee: String,
|
||||
pegs: String,
|
||||
) -> String {
|
||||
let reserves: serde_json::Result<Vec<AssetBalance>> = serde_json::from_str(&reserves);
|
||||
if reserves.is_err() {
|
||||
return error();
|
||||
}
|
||||
let mut reserves = reserves.unwrap();
|
||||
reserves.sort_by_key(|v| v.asset_id);
|
||||
let idx_in = reserves.iter().position(|v| v.asset_id == asset_in);
|
||||
if idx_in.is_none() {
|
||||
return error();
|
||||
}
|
||||
let amount_in = parse_into!(u128, amount);
|
||||
let balances: Vec<AssetReserve> = reserves.iter().map(|v| v.into()).collect();
|
||||
let amplification = parse_into!(u128, amplification);
|
||||
let issuance = parse_into!(u128, share_issuance);
|
||||
let fee = Permill::from_float(parse_into!(f64, fee));
|
||||
|
||||
// Parse 7th param
|
||||
let pairs = match parse_pairs(&pegs) {
|
||||
Some(p) => p,
|
||||
None => return error(),
|
||||
};
|
||||
|
||||
let result = hydra_dx_math::stableswap::calculate_shares_for_amount::<D_ITERATIONS>(
|
||||
&balances,
|
||||
idx_in.unwrap(),
|
||||
amount_in,
|
||||
amplification,
|
||||
issuance,
|
||||
fee,
|
||||
&pairs,
|
||||
);
|
||||
|
||||
if let Some(r) = result {
|
||||
r.0.to_string()
|
||||
} else {
|
||||
error()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn Java_io_novafoundation_nova_hydra_1dx_1math_stableswap_StableSwapMathBridge_calculate_1add_1one_1asset<'a>(
|
||||
jni_env: JNIEnv<'a>,
|
||||
_: JClass,
|
||||
reserves: JString,
|
||||
shares: JString,
|
||||
asset_in: jint,
|
||||
amplification: JString,
|
||||
share_issuance: JString,
|
||||
fee: JString,
|
||||
pegs: JString,
|
||||
) -> JString<'a> {
|
||||
let reserves = get_str(&jni_env, reserves);
|
||||
let shares = get_str(&jni_env, shares);
|
||||
let asset_in = asset_in as u32;
|
||||
let amplification = get_str(&jni_env, amplification);
|
||||
let share_issuance = get_str(&jni_env, share_issuance);
|
||||
let fee = get_str(&jni_env, fee);
|
||||
let pegs = get_str(&jni_env, pegs);
|
||||
|
||||
let result = calculate_add_one_asset(
|
||||
reserves,
|
||||
shares,
|
||||
asset_in,
|
||||
amplification,
|
||||
share_issuance,
|
||||
fee,
|
||||
pegs,
|
||||
);
|
||||
|
||||
jni_env.new_string(result).unwrap()
|
||||
}
|
||||
|
||||
fn calculate_add_one_asset(
|
||||
reserves: String,
|
||||
shares: String,
|
||||
asset_in: u32,
|
||||
amplification: String,
|
||||
share_issuance: String,
|
||||
fee: String,
|
||||
pegs: String,
|
||||
) -> String {
|
||||
let reserves: serde_json::Result<Vec<AssetBalance>> = serde_json::from_str(&reserves);
|
||||
if reserves.is_err() {
|
||||
return error();
|
||||
}
|
||||
let mut reserves = reserves.unwrap();
|
||||
reserves.sort_by_key(|v| v.asset_id);
|
||||
let idx_in = reserves.iter().position(|v| v.asset_id == asset_in);
|
||||
if idx_in.is_none() {
|
||||
return error();
|
||||
}
|
||||
|
||||
let balances: Vec<AssetReserve> = reserves.iter().map(|v| v.into()).collect();
|
||||
let shares = parse_into!(u128, shares);
|
||||
let amplification = parse_into!(u128, amplification);
|
||||
let issuance = parse_into!(u128, share_issuance);
|
||||
let fee = Permill::from_float(parse_into!(f64, fee));
|
||||
|
||||
let pairs = match parse_pairs(&pegs) {
|
||||
Some(p) => p,
|
||||
None => return error(),
|
||||
};
|
||||
|
||||
let result = hydra_dx_math::stableswap::calculate_add_one_asset::<D_ITERATIONS, Y_ITERATIONS>(
|
||||
&balances,
|
||||
shares,
|
||||
idx_in.unwrap(),
|
||||
issuance,
|
||||
amplification,
|
||||
fee,
|
||||
&pairs,
|
||||
);
|
||||
|
||||
if let Some(r) = result {
|
||||
r.0.to_string()
|
||||
} else {
|
||||
error()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn Java_io_novafoundation_nova_hydra_1dx_1math_stableswap_StableSwapMathBridge_calculate_1liquidity_1out_1one_1asset<'a>(
|
||||
jni_env: JNIEnv<'a>,
|
||||
_: JClass,
|
||||
reserves: JString,
|
||||
shares: JString,
|
||||
asset_out: jint,
|
||||
amplification: JString,
|
||||
share_issuance: JString,
|
||||
withdraw_fee: JString,
|
||||
pegs: JString,
|
||||
) -> JString<'a> {
|
||||
let reserves = get_str(&jni_env, reserves);
|
||||
let shares = get_str(&jni_env, shares);
|
||||
let asset_out = asset_out as u32;
|
||||
let amplification = get_str(&jni_env, amplification);
|
||||
let share_issuance = get_str(&jni_env, share_issuance);
|
||||
let withdraw_fee = get_str(&jni_env, withdraw_fee);
|
||||
let pegs = get_str(&jni_env, pegs);
|
||||
|
||||
let result = calculate_liquidity_out_one_asset(
|
||||
reserves,
|
||||
shares,
|
||||
asset_out,
|
||||
amplification,
|
||||
share_issuance,
|
||||
withdraw_fee,
|
||||
pegs,
|
||||
);
|
||||
|
||||
jni_env.new_string(result).unwrap()
|
||||
}
|
||||
|
||||
fn calculate_liquidity_out_one_asset(
|
||||
reserves: String,
|
||||
shares: String,
|
||||
asset_out: u32,
|
||||
amplification: String,
|
||||
share_issuance: String,
|
||||
withdraw_fee: String,
|
||||
pegs: String,
|
||||
) -> String {
|
||||
let reserves: serde_json::Result<Vec<AssetBalance>> = serde_json::from_str(&reserves);
|
||||
if reserves.is_err() {
|
||||
return error();
|
||||
}
|
||||
let mut reserves = reserves.unwrap();
|
||||
reserves.sort_by_key(|v| v.asset_id);
|
||||
|
||||
let idx_out = reserves.iter().position(|v| v.asset_id == asset_out);
|
||||
if idx_out.is_none() {
|
||||
println!("idx_out error");
|
||||
return error();
|
||||
}
|
||||
|
||||
let shares_out = parse_into!(u128, shares);
|
||||
let amplification = parse_into!(u128, amplification);
|
||||
let issuance = parse_into!(u128, share_issuance);
|
||||
let fee = Permill::from_float(parse_into!(f64, withdraw_fee));
|
||||
|
||||
let balances: Vec<AssetReserve> = reserves.iter().map(|v| v.into()).collect();
|
||||
|
||||
let pairs = match parse_pairs(&pegs) {
|
||||
Some(p) => p,
|
||||
None => { println!("parse_pairs error"); return error(); },
|
||||
};
|
||||
|
||||
let result = hydra_dx_math::stableswap::calculate_withdraw_one_asset::<D_ITERATIONS, Y_ITERATIONS>(
|
||||
&balances,
|
||||
shares_out,
|
||||
idx_out.unwrap(),
|
||||
issuance,
|
||||
amplification,
|
||||
fee,
|
||||
&pairs,
|
||||
);
|
||||
|
||||
if let Some(r) = result {
|
||||
r.0.to_string()
|
||||
} else {
|
||||
println!("final result error");
|
||||
error()
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------- XYK ---------------------- */
|
||||
|
||||
#[no_mangle]
|
||||
pub fn Java_io_novafoundation_nova_hydra_1dx_1math_xyk_HYKSwapMathBridge_calculate_1out_1given_1in<'a>(
|
||||
jni_env: JNIEnv<'a>,
|
||||
_: JClass,
|
||||
balance_in: JString,
|
||||
balance_out: JString,
|
||||
amount_in: JString,
|
||||
) -> JString<'a> {
|
||||
let balance_in: String = get_str(&jni_env, balance_in);
|
||||
let balance_out: String = get_str(&jni_env, balance_out);
|
||||
let amount_in: String = get_str(&jni_env, amount_in);
|
||||
|
||||
let out = xyk_calculate_out_given_in(balance_in, balance_out, amount_in);
|
||||
|
||||
jni_env.new_string(out).unwrap()
|
||||
}
|
||||
|
||||
fn xyk_calculate_out_given_in(balance_in: String, balance_out: String, amount_in: String) -> String {
|
||||
let balance_in = parse_into!(u128, balance_in);
|
||||
let balance_out = parse_into!(u128, balance_out);
|
||||
let amount_in = parse_into!(u128, amount_in);
|
||||
|
||||
let result = hydra_dx_math::xyk::calculate_out_given_in(balance_in, balance_out, amount_in);
|
||||
|
||||
if let Ok(r) = result {
|
||||
r.to_string()
|
||||
} else {
|
||||
error()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn Java_io_novafoundation_nova_hydra_1dx_1math_xyk_HYKSwapMathBridge_calculate_1in_1given_1out<'a>(
|
||||
jni_env: JNIEnv<'a>,
|
||||
_: JClass,
|
||||
balance_in: JString,
|
||||
balance_out: JString,
|
||||
amount_in: JString,
|
||||
) -> JString<'a> {
|
||||
let balance_in: String = get_str(&jni_env, balance_in);
|
||||
let balance_out: String = get_str(&jni_env, balance_out);
|
||||
let amount_in: String = get_str(&jni_env, amount_in);
|
||||
|
||||
let out = xyk_calculate_in_given_out(balance_in, balance_out, amount_in);
|
||||
|
||||
jni_env.new_string(out).unwrap()
|
||||
}
|
||||
|
||||
fn xyk_calculate_in_given_out(balance_in: String, balance_out: String, amount_out: String) -> String {
|
||||
let balance_in = parse_into!(u128, balance_in);
|
||||
let balance_out = parse_into!(u128, balance_out);
|
||||
let amount_out = parse_into!(u128, amount_out);
|
||||
|
||||
let result = hydra_dx_math::xyk::calculate_in_given_out(balance_out, balance_in, amount_out);
|
||||
|
||||
if let Ok(r) = result {
|
||||
r.to_string()
|
||||
} else {
|
||||
error()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn Java_io_novafoundation_nova_hydra_1dx_1math_xyk_HYKSwapMathBridge_calculate_1pool_1trade_1fee<'a>(
|
||||
jni_env: JNIEnv<'a>,
|
||||
_: JClass,
|
||||
amount: JString,
|
||||
fee_nominator: JString,
|
||||
fee_denominator: JString,
|
||||
) -> JString<'a> {
|
||||
let amount: String = get_str(&jni_env, amount);
|
||||
let fee_nominator: String = get_str(&jni_env, fee_nominator);
|
||||
let fee_denominator: String = get_str(&jni_env, fee_denominator);
|
||||
|
||||
let out = calculate_pool_trade_fee(amount, fee_nominator, fee_denominator);
|
||||
|
||||
jni_env.new_string(out).unwrap()
|
||||
}
|
||||
|
||||
fn calculate_pool_trade_fee(amount: String, fee_nominator: String, fee_denominator: String) -> String {
|
||||
let amount = parse_into!(u128, amount);
|
||||
let fee_nominator = parse_into!(u32, fee_nominator);
|
||||
let fee_denominator = parse_into!(u32, fee_denominator);
|
||||
|
||||
let result = hydra_dx_math::fee::calculate_pool_trade_fee(amount, (fee_nominator, fee_denominator));
|
||||
|
||||
if let Some(r) = result {
|
||||
r.to_string()
|
||||
} else {
|
||||
error()
|
||||
}
|
||||
}
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
package io.novafoundation.nova.hydra_dx_math.stableswap
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
class StableSwapTest {
|
||||
|
||||
@Test
|
||||
fun shouldCalculateOutGivenIn() {
|
||||
val data = """
|
||||
[{
|
||||
"asset_id": 1,
|
||||
"amount": "1000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 0,
|
||||
"amount": "1000000000000",
|
||||
"decimals": 12
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
val result = StableSwapMathBridge.calculate_out_given_in(
|
||||
data,
|
||||
0,
|
||||
1,
|
||||
"1000000000",
|
||||
"1",
|
||||
"0",
|
||||
""
|
||||
)
|
||||
|
||||
assertEquals("999500248", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCalculateInGiveOut() {
|
||||
val data = """
|
||||
[{
|
||||
"asset_id": 1,
|
||||
"amount": "1000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 0,
|
||||
"amount": "1000000000000",
|
||||
"decimals": 12
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
val result = StableSwapMathBridge.calculate_in_given_out(
|
||||
data,
|
||||
0,
|
||||
1,
|
||||
"1000000000",
|
||||
"1",
|
||||
"0",
|
||||
""
|
||||
)
|
||||
|
||||
assertNotEquals("-1", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCalculateAmplification() {
|
||||
val result = StableSwapMathBridge.calculate_amplification("10", "10", "0", "100", "50")
|
||||
|
||||
assertEquals("10", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCalculateShares() {
|
||||
val data = """
|
||||
[{
|
||||
"asset_id": 0,
|
||||
"amount":"90000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 1,
|
||||
"amount": "5000000000000000000000",
|
||||
"decimals": 12
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
val assets = """
|
||||
[{"asset_id":1,"amount":"43000000000000000000"}]
|
||||
"""
|
||||
|
||||
val result = StableSwapMathBridge.calculate_shares(
|
||||
data,
|
||||
assets,
|
||||
"1000",
|
||||
"64839594451719860",
|
||||
"0",
|
||||
""
|
||||
)
|
||||
|
||||
assertEquals("371541351762585", result.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCalculateSharesForAmount() {
|
||||
val data = """
|
||||
[
|
||||
{
|
||||
"asset_id": 0,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 1,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 2,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 3,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 4,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
val result = StableSwapMathBridge.calculate_shares_for_amount(
|
||||
data,
|
||||
0,
|
||||
"100000000000000",
|
||||
"100",
|
||||
"20000000000000000000000",
|
||||
"0",
|
||||
""
|
||||
)
|
||||
|
||||
assertEquals("40001593768209443008", result.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("The test fails with last digit being 0 instead of 1. We need to check why it happens later")
|
||||
fun shouldCalculateAddOneAsset() {
|
||||
val data = """
|
||||
[
|
||||
{
|
||||
"asset_id": 0,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 1,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 2,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 3,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 4,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
val result = StableSwapMathBridge.calculate_add_one_asset(
|
||||
data,
|
||||
"399850144492663029649",
|
||||
2,
|
||||
"100",
|
||||
"20000000000000000000000",
|
||||
"0",
|
||||
""
|
||||
)
|
||||
|
||||
assertEquals("1000000000000001", result.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldcalculateLiquidityOutOneAsset() {
|
||||
val data = """
|
||||
[
|
||||
{
|
||||
"asset_id": 0,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 1,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 2,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 3,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
},
|
||||
{
|
||||
"asset_id": 4,
|
||||
"amount": "10000000000000000",
|
||||
"decimals": 12
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
val result = StableSwapMathBridge.calculate_liquidity_out_one_asset(
|
||||
data,
|
||||
"40001593768209443008",
|
||||
0,
|
||||
"100",
|
||||
"20000000000000000000000",
|
||||
"0",
|
||||
""
|
||||
)
|
||||
|
||||
assertEquals("99999999999999", result.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun failingCase() {
|
||||
val data = """
|
||||
[{"amount":"2246975221087","decimals":6,"asset_id":10},{"amount":"2256486088023","decimals":6,"asset_id":22}]
|
||||
"""
|
||||
|
||||
val result = StableSwapMathBridge.calculate_liquidity_out_one_asset(
|
||||
data,
|
||||
"1000000000",
|
||||
10,
|
||||
"100",
|
||||
"4502091550542833181457210",
|
||||
"0.00040",
|
||||
""
|
||||
)
|
||||
|
||||
assertEquals("99999999999999", result.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun failingCase2() {
|
||||
val data = """
|
||||
[{"amount":"505342304916","decimals":6,"asset_id":10},{"amount":"368030436758902944990436","decimals":18,"asset_id":18},{"amount":"410374848833","decimals":6,"asset_id":21},{"amount":"0","decimals":6,"asset_id":23}] """
|
||||
|
||||
val result = StableSwapMathBridge.calculate_shares_for_amount(
|
||||
data,
|
||||
10,
|
||||
"10",
|
||||
"320",
|
||||
"1662219218861236418723363",
|
||||
"0.00040",
|
||||
""
|
||||
)
|
||||
|
||||
assertEquals("99999999999999", result.toString())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<manifest />
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package io.novafoundation.nova.hydra_dx_math
|
||||
|
||||
import io.novafoundation.nova.common.utils.atLeastZero
|
||||
import java.math.BigInteger
|
||||
|
||||
object HydraDxMathConversions {
|
||||
|
||||
fun String.fromBridgeResultToBalance(): BigInteger? {
|
||||
return if (this == "-1") null else toBigInteger().atLeastZero()
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package io.novafoundation.nova.hydra_dx_math.stableswap;
|
||||
|
||||
public class StableSwapMathBridge {
|
||||
|
||||
static {
|
||||
System.loadLibrary("hydra_dx_math_java");
|
||||
}
|
||||
|
||||
public static native String calculate_out_given_in(
|
||||
String reserves,
|
||||
int asset_in,
|
||||
int asset_out,
|
||||
String amount_in,
|
||||
String amplification,
|
||||
String fee,
|
||||
String pegs
|
||||
);
|
||||
|
||||
public static native String calculate_in_given_out(
|
||||
String reserves,
|
||||
int asset_in,
|
||||
int asset_out,
|
||||
String amount_out,
|
||||
String amplification,
|
||||
String fee,
|
||||
String pegs
|
||||
);
|
||||
|
||||
public static native String calculate_amplification(
|
||||
String initial_amplification,
|
||||
String final_amplification,
|
||||
String initial_block,
|
||||
String final_block,
|
||||
String current_block
|
||||
);
|
||||
|
||||
public static native String calculate_shares(
|
||||
String reserves,
|
||||
String assets,
|
||||
String amplification,
|
||||
String share_issuance,
|
||||
String fee,
|
||||
String pegs
|
||||
);
|
||||
|
||||
public static native String calculate_shares_for_amount(
|
||||
String reserves,
|
||||
int asset_in,
|
||||
String amount,
|
||||
String amplification,
|
||||
String share_issuance,
|
||||
String fee,
|
||||
String pegs
|
||||
);
|
||||
|
||||
public static native String calculate_add_one_asset(
|
||||
String reserves,
|
||||
String shares,
|
||||
int asset_in,
|
||||
String amplification,
|
||||
String share_issuance,
|
||||
String fee,
|
||||
String pegs
|
||||
);
|
||||
|
||||
public static native String calculate_liquidity_out_one_asset(
|
||||
String reserves,
|
||||
String shares,
|
||||
int asset_out,
|
||||
String amplification,
|
||||
String share_issuance,
|
||||
String withdraw_fee,
|
||||
String pegs
|
||||
);
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package io.novafoundation.nova.hydra_dx_math.xyk;
|
||||
|
||||
public class HYKSwapMathBridge {
|
||||
|
||||
static {
|
||||
System.loadLibrary("hydra_dx_math_java");
|
||||
}
|
||||
|
||||
public static native String calculate_out_given_in(
|
||||
String balanceIn,
|
||||
String balanceOut,
|
||||
String amountIn
|
||||
);
|
||||
|
||||
public static native String calculate_in_given_out(
|
||||
String balanceIn,
|
||||
String balanceOut,
|
||||
String amountOut
|
||||
);
|
||||
|
||||
public static native String calculate_pool_trade_fee(
|
||||
String amount,
|
||||
String feeNumerator,
|
||||
String feeDenominator
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user