Skip to content

Commit

Permalink
add tx_input, tx_output, tx_hash for Android
Browse files Browse the repository at this point in the history
  • Loading branch information
v-almonacid committed Jul 3, 2020
1 parent 0b87dde commit 80db929
Show file tree
Hide file tree
Showing 11 changed files with 432 additions and 3 deletions.
Expand Up @@ -59,6 +59,24 @@ public final void addrKeyHashToBytes(String addrKeyHash, Promise promise) {
.pour(promise);
}

// TransactionHash

@ReactMethod
public final void transactionHashFromBytes(String bytes, Promise promise) {
Native.I
.transactionHashFromBytes(Base64.decode(bytes, Base64.DEFAULT))
.map(RPtr::toJs)
.pour(promise);
}

@ReactMethod
public final void transactionHashToBytes(String addrKeyHash, Promise promise) {
Native.I
.transactionHashToBytes(new RPtr(addrKeyHash))
.map(bytes -> Base64.encodeToString(bytes, Base64.DEFAULT))
.pour(promise);
}

// StakeCredential

@ReactMethod
Expand Down Expand Up @@ -110,4 +128,56 @@ public final void baseAddressStakeCred(String baseAddress, Promise promise) {
.pour(promise);
}

// TransactionInput

@ReactMethod
public final void transactionInputFromBytes(String bytes, Promise promise) {
Native.I
.transactionInputFromBytes(Base64.decode(bytes, Base64.DEFAULT))
.map(RPtr::toJs)
.pour(promise);
}

@ReactMethod
public final void transactionInputToBytes(String transactionInput, Promise promise) {
Native.I
.transactionInputToBytes(new RPtr(transactionInput))
.map(bytes -> Base64.encodeToString(bytes, Base64.DEFAULT))
.pour(promise);
}

@ReactMethod
public final void transactionInputNew(String transactionId, Double index, Promise promise) {
Native.I
.transactionInputNew(new RPtr(transactionId), index.longValue())
.map(RPtr::toJs)
.pour(promise);
}

// TransactionOutput

@ReactMethod
public final void transactionOutputFromBytes(String bytes, Promise promise) {
Native.I
.transactionOutputFromBytes(Base64.decode(bytes, Base64.DEFAULT))
.map(RPtr::toJs)
.pour(promise);
}

@ReactMethod
public final void transactionOutputToBytes(String transactionOutput, Promise promise) {
Native.I
.transactionOutputToBytes(new RPtr(transactionOutput))
.map(bytes -> Base64.encodeToString(bytes, Base64.DEFAULT))
.pour(promise);
}

@ReactMethod
public final void transactionOutputNew(String address, Double amount, Promise promise) {
Native.I
.transactionOutputNew(new RPtr(address), amount.longValue())
.map(RPtr::toJs)
.pour(promise);
}

}
14 changes: 14 additions & 0 deletions android/src/main/java/io/emurgo/rnhaskellshelley/Native.java
Expand Up @@ -23,6 +23,10 @@ private Native() { }
public final native Result<byte[]> addrKeyHashToBytes(RPtr addrKeyHash);
public final native Result<RPtr> addrKeyHashFromBytes(byte[] bytes);

// TransactionHash
public final native Result<byte[]> transactionHashToBytes(RPtr transactionHash);
public final native Result<RPtr> transactionHashFromBytes(byte[] bytes);

// StakeCredential
public final native Result<RPtr> stakeCredentialFromKeyHash(RPtr addrKeyHash);
public final native Result<RPtr> stakeCredentialToKeyHash(RPtr stakeCredential);
Expand All @@ -33,5 +37,15 @@ private Native() { }
public final native Result<RPtr> baseAddressPaymentCred(RPtr baseAddress);
public final native Result<RPtr> baseAddressStakeCred(RPtr baseAddress);

// TransactionInput
public final native Result<byte[]> transactionInputToBytes(RPtr transactionInput);
public final native Result<RPtr> transactionInputFromBytes(byte[] bytes);
public final native Result<RPtr> transactionInputNew(RPtr transactionId, long index);

// TransactionOutput
public final native Result<byte[]> transactionOutputToBytes(RPtr transactionOutput);
public final native Result<RPtr> transactionOutputFromBytes(byte[] bytes);
public final native Result<RPtr> transactionOutputNew(RPtr address, long amount);

public final native void ptrFree(RPtr ptr);
}
12 changes: 12 additions & 0 deletions example/App.js
Expand Up @@ -14,6 +14,7 @@ import {
AddrKeyHash,
BaseAddress,
StakeCredential,
TransactionHash,
} from 'react-native-haskell-shelley'

const assert = (value: any, message: string, ...args: any) => {
Expand All @@ -33,6 +34,7 @@ export default class App extends Component<{}> {
const addr =
'0000b03c3aa052f51c086c54bd4059ead2d2e426ac89fa4b3ce41cbfd8800b51'
const addrBytes = Buffer.from(addr, 'hex')

try {
// ------------------ AddrKeyHash -----------------------
const addrKeyHash = await AddrKeyHash.from_bytes(addrBytes)
Expand All @@ -44,6 +46,15 @@ export default class App extends Component<{}> {
'AddrKeyHash.to_bytes should match original input address',
)

// ------------------ TransactionHash -----------------------
const txHash = await TransactionHash.from_bytes(addrBytes)
const txHashToBytes = await txHash.to_bytes()
console.log(Buffer.from(txHashToBytes).toString('hex'))
assert(
Buffer.from(txHashToBytes).toString('hex') === addr,
'TransactionHash.to_bytes should match original input address',
)

// ---------------- StakeCredential ---------------------
const stakeCred = await StakeCredential.from_keyhash(addrKeyHash)
const addrKeyHashOrig = await stakeCred.to_keyhash()
Expand Down Expand Up @@ -80,6 +91,7 @@ export default class App extends Component<{}> {
})

console.log('addrKeyHash', addrKeyHash)
console.log('txHash', addrKeyHash)
console.log('pymntAddrKeyHash', pymntAddrKeyHash)
console.log('paymentCred', paymentCred)
console.log('stakeCred', stakeCred)
Expand Down
60 changes: 60 additions & 0 deletions index.d.ts
@@ -1,5 +1,9 @@
export type Optional<T> = T | undefined;

export type TransactionIndex = number;

export type Coin = number;

export class Ptr {
/**
* Frees the pointer
Expand Down Expand Up @@ -37,6 +41,20 @@ export class AddrKeyHash extends Ptr {

}

export class TransactionHash extends Ptr {
/**
* @param {Uint8Array} bytes
* @returns {Promise<TransactionHash>}
*/
static from_bytes(bytes: Uint8Array): Promise<TransactionHash>;

/**
* @returns {Promise<Uint8Array>}
*/
to_bytes(): Promise<Uint8Array>;

}

export class StakeCredential extends Ptr {

/**
Expand Down Expand Up @@ -76,3 +94,45 @@ export class BaseAddress extends Ptr {
*/
stake_cred(): Promise<StakeCredential>
}

export class TransactionInput extends Ptr {
/**
* @param {Uint8Array} bytes
* @returns {Promise<TransactionInput>}
*/
static from_bytes(bytes: Uint8Array): Promise<TransactionInput>;

/**
* @returns {Promise<Uint8Array>}
*/
to_bytes(): Promise<Uint8Array>;

/**
* @param {TransactionHash} transactionId
* @param {TransactionIndex} index
* @returns {Promise<TransactionInput>}
*/
static new(transactionId: TransactionHash, index: TransactionIndex): Promise<TransactionInput>;

}

export class TransactionOutput extends Ptr {
/**
* @param {Uint8Array} bytes
* @returns {Promise<TransactionOutput>}
*/
static from_bytes(bytes: Uint8Array): Promise<TransactionOutput>;

/**
* @returns {Promise<Uint8Array>}
*/
to_bytes(): Promise<Uint8Array>;

/**
* @param {Address} address
* @param {Coin} amount
* @returns {Promise<TransactionInput>}
*/
static new(address: Address, amount: Coin): Promise<TransactionOutput>;

}
83 changes: 83 additions & 0 deletions index.js
Expand Up @@ -91,6 +91,26 @@ export class AddrKeyHash extends Ptr {
}
}

export class TransactionHash extends Ptr {

/**
* @param {Uint8Array} bytes
* @returns {Promise<TransactionHash>}
*/
static async from_bytes(bytes) {
const ret = await HaskellShelley.transactionHashFromBytes(b64FromUint8Array(bytes));
return Ptr._wrap(ret, TransactionHash);
}

/**
* @returns {Promise<Uint8Array>}
*/
async to_bytes() {
const b64 = await HaskellShelley.transactionHashToBytes(this.ptr);
return Uint8ArrayFromB64(b64);
}
}

export class StakeCredential extends Ptr {

/**
Expand Down Expand Up @@ -150,3 +170,66 @@ export class BaseAddress extends Ptr {
return Ptr._wrap(ret, StakeCredential);
}
}

export class TransactionInput extends Ptr {
/**
* @param {Uint8Array} bytes
* @returns {Promise<TransactionInput>}
*/
static async from_bytes(bytes) {
const ret = await HaskellShelley.transactionInputFromBytes(b64FromUint8Array(bytes));
return Ptr._wrap(ret, TransactionInput);
}

/**
* @returns {Promise<Uint8Array>}
*/
async to_bytes() {
const b64 = await HaskellShelley.transactionInputToBytes(this.ptr);
return Uint8ArrayFromB64(b64);
}

/**
* @param {TransactionHash} transactionId
* @param {TransactionIndex} index
* @returns {Promise<TransactionInput>}
*/
static async new(transactionId, index) {
const transactionIdPtr = Ptr._assertClass(transactionId, TransactionHash);
const indexPtr = Ptr._assertClass(index, TransactionIndex);
const ret = await HaskellShelley.transactionInputNew(transactionIdPtr, indexPtr);
return Ptr._wrap(ret, TransactionInput);
}

}

export class TransactionOutput extends Ptr {
/**
* @param {Uint8Array} bytes
* @returns {Promise<TransactionOutput>}
*/
static async from_bytes(bytes: Uint8Array) {
const ret = await HaskellShelley.transactionOutputFromBytes(b64FromUint8Array(bytes));
return Ptr._wrap(ret, TransactionOutput);
}

/**
* @returns {Promise<Uint8Array>}
*/
async to_bytes() {
const b64 = await HaskellShelley.transactionOutputToBytes(this.ptr);
return Uint8ArrayFromB64(b64);
}

/**
* @param {Address} address
* @param {Coin} amount
* @returns {Promise<TransactionOutput>}
*/
static async new(address: Address, amount: Coin) {
const addrPtr = Ptr._assertClass(address, Address);
const ret = await HaskellShelley.transactionOutputNew(addrPtr, amount);
return Ptr._wrap(ret, TransactionOutput);
}

}
40 changes: 40 additions & 0 deletions rust/src/android/hash_type.rs
@@ -0,0 +1,40 @@
use super::ptr_j::*;
use super::result::ToJniResult;
use crate::panic::{handle_exception_result, ToResult};
use crate::ptr::RPtrRepresentable;
use jni::objects::{JObject};
use jni::sys::{jbyteArray, jobject};
use jni::JNIEnv;
use wasm_bindgen::JsValue;

pub trait HashType {
fn to_bytes(&self) -> Vec<u8>;
fn from_bytes(bytes: Vec<u8>) -> Result<Self, JsValue> where Self: Sized;
}

pub unsafe fn hash_to_bytes<T: RPtrRepresentable + HashType>(
env: JNIEnv, hash: JRPtr
) -> jobject {
handle_exception_result(|| {
let hash = hash.rptr(&env)?;
hash
.typed_ref::<T>()
.map(|hash| hash.to_bytes())
.and_then(|bytes| env.byte_array_from_slice(&bytes).into_result())
.map(|arr| JObject::from(arr))
})
.jresult(&env)
}

pub unsafe fn hash_from_bytes<T: RPtrRepresentable + HashType>(
env: JNIEnv, bytes: jbyteArray,
) -> jobject {
handle_exception_result(|| {
env
.convert_byte_array(bytes)
.into_result()
.and_then(|bytes| T::from_bytes(bytes).into_result())
.and_then(|hash| hash.rptr().jptr(&env))
})
.jresult(&env)
}
7 changes: 4 additions & 3 deletions rust/src/android/mod.rs
@@ -1,20 +1,21 @@
mod address; // TODO: remove?
mod primitive;
mod ptr_j;
mod hash_type;
mod result;
mod string;
mod addr_key_hash;
mod transaction_hash;
mod stake_credential;
mod base_address;
mod transaction_input;
mod transaction_output;
// declare other modules here
// mod transaction;


pub use address::*;
pub use addr_key_hash::*;
pub use stake_credential::*;
// and here:
// pub use transaction::*;

#[allow(non_snake_case)]
#[no_mangle]
Expand Down

0 comments on commit 80db929

Please sign in to comment.