-
Notifications
You must be signed in to change notification settings - Fork 215
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[wallet-ffi]
wallet_create
takes seed words for recovery
Breaking change in wallet FFI, new argument in `wallet_create` to specify optional seed words for recovery. Also starts alpha quality NodeJS FFI wallet client for testing purposes.
- Loading branch information
Byron Hambly
committed
Jun 3, 2021
1 parent
c8113ec
commit ff63135
Showing
16 changed files
with
1,108 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
libtari_wallet_ffi.* | ||
wallet/ | ||
bak/ | ||
recovered/ | ||
seeds.txt | ||
recovery/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# NodeJS FFI Client | ||
|
||
Still a work in progress. | ||
|
||
## Install deps | ||
|
||
- `npm install` | ||
|
||
## Build FFI lib | ||
|
||
- Build the FFI lib: `cargo build -p tari_wallet_ffi --release --lib` | ||
- Copy the lib into this folder: `cp target/release/libtari_wallet_ffi.dylib /path/to/here` | ||
|
||
_(.dylib for macOS, .so for Linux, .dll for windows)_ | ||
|
||
## Run | ||
|
||
- `npm start` - runs index.js file |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
// this is nasty | ||
// ¯\_(ツ)_/¯ | ||
|
||
const lib = require("./lib"); | ||
const ref = require("ref-napi"); | ||
const ffi = require("ffi-napi"); | ||
|
||
const i32 = ref.types.int32; | ||
const u8 = ref.types.uint8; | ||
const u64 = ref.types.uint64; | ||
const bool = ref.types.bool; | ||
|
||
try { | ||
let err = ref.alloc(i32); | ||
// console.log(err); | ||
|
||
console.log("Create Tor transport..."); | ||
let tor = lib.transport_tor_create( | ||
"/ip4/127.0.0.1/tcp/9051", | ||
ref.NULL, | ||
9051, | ||
ref.NULL, | ||
ref.NULL, | ||
err | ||
); | ||
|
||
// todo: error handling | ||
|
||
console.log("Create Comms config..."); | ||
let comms = lib.comms_config_create( | ||
"/ip4/0.0.0.0/tcp/9838", | ||
tor, | ||
"wallet.dat", | ||
"./wallet", | ||
30, | ||
600, | ||
err | ||
); | ||
|
||
// callback_received_transaction: unsafe extern "C" fn(*mut TariPendingInboundTransaction), | ||
const receivedTx = ffi.Callback("void", ["pointer"], function (ptr) { | ||
console.log("receivedTx: ", ptr); | ||
}); | ||
// callback_received_transaction_reply: unsafe extern "C" fn(*mut TariCompletedTransaction), | ||
const receivedTxReply = ffi.Callback("void", ["pointer"], function (ptr) { | ||
console.log("receivedTxReply: ", ptr); | ||
}); | ||
// callback_received_finalized_transaction: unsafe extern "C" fn(*mut TariCompletedTransaction), | ||
const receivedFinalized = ffi.Callback("void", ["pointer"], function (ptr) { | ||
console.log("receivedFinalized: ", ptr); | ||
}); | ||
// callback_transaction_broadcast: unsafe extern "C" fn(*mut TariCompletedTransaction), | ||
const txBroadcast = ffi.Callback("void", ["pointer"], function (ptr) { | ||
console.log("txBroadcast: ", ptr); | ||
}); | ||
// callback_transaction_mined: unsafe extern "C" fn(*mut TariCompletedTransaction), | ||
const txMined = ffi.Callback("void", ["pointer"], function (ptr) { | ||
console.log("txMined: ", ptr); | ||
}); | ||
// callback_transaction_mined_unconfirmed: unsafe extern "C" fn(*mut TariCompletedTransaction, u64), | ||
const txMinedUnconfirmed = ffi.Callback( | ||
"void", | ||
["pointer"], | ||
function (ptr, confirmations) { | ||
console.log("txMinedUnconfirmed: ", ptr, confirmations); | ||
} | ||
); | ||
// callback_direct_send_result: unsafe extern "C" fn(c_ulonglong, bool), | ||
const directSendResult = ffi.Callback("void", [u64, bool], function (i, j) { | ||
console.log("directSendResult: ", i, j); | ||
}); | ||
// callback_store_and_forward_send_result: unsafe extern "C" fn(c_ulonglong, bool), | ||
const safResult = ffi.Callback("void", [u64, bool], function (i, j) { | ||
console.log("safResult: ", i, j); | ||
}); | ||
// callback_transaction_cancellation: unsafe extern "C" fn(*mut TariCompletedTransaction), | ||
const txCancelled = ffi.Callback("void", ["pointer"], function (ptr) { | ||
console.log("txCancelled: ", ptr); | ||
}); | ||
// callback_utxo_validation_complete: unsafe extern "C" fn(u64, u8), | ||
const utxoValidation = ffi.Callback("void", [u64, u8], function (i, j) { | ||
console.log("utxoValidation: ", i, j); | ||
}); | ||
// callback_stxo_validation_complete: unsafe extern "C" fn(u64, u8), | ||
const stxoValidation = ffi.Callback("void", [u64, u8], function (i, j) { | ||
console.log("stxoValidation: ", i, j); | ||
}); | ||
// callback_invalid_txo_validation_complete: unsafe extern "C" fn(u64, u8), | ||
const itxoValidation = ffi.Callback("void", [u64, u8], function (i, j) { | ||
console.log("itxoValidation: ", i, j); | ||
}); | ||
// callback_transaction_validation_complete: unsafe extern "C" fn(u64, u8), | ||
const txValidation = ffi.Callback("void", [u64, u8], function (i, j) { | ||
console.log("txValidation: ", i, j); | ||
}); | ||
// callback_saf_messages_received: unsafe extern "C" fn(), | ||
const safsReceived = ffi.Callback("void", [], function () { | ||
console.log("safsReceived"); | ||
}); | ||
|
||
console.log("Create Wallet..."); | ||
let wallet = lib.wallet_create( | ||
comms, | ||
"./wallet/logs/wallet.log", | ||
5, | ||
10240, | ||
ref.NULL, // passphrase | ||
ref.NULL, // seed words | ||
receivedTx, | ||
receivedTxReply, | ||
receivedFinalized, | ||
txBroadcast, | ||
txMined, | ||
txMinedUnconfirmed, | ||
directSendResult, | ||
safResult, | ||
txCancelled, | ||
utxoValidation, | ||
stxoValidation, | ||
itxoValidation, | ||
txValidation, | ||
safsReceived, | ||
err | ||
); | ||
|
||
// look ma, zero confs! | ||
lib.wallet_set_num_confirmations_required(wallet, 0, err); | ||
// console.log(err.deref()); | ||
let confs = lib.wallet_get_num_confirmations_required(wallet, err); | ||
// console.log("confs", confs); | ||
// console.log(err.deref()); | ||
|
||
let s = lib.wallet_get_seed_words(wallet, err); | ||
// console.log("seeds words", s); | ||
// console.log("err", err); | ||
let seedWords = []; | ||
for (let i = 0; i < 24; i++) { | ||
let word = lib.seed_words_get_at(s, i, err); | ||
// console.log("word", word); | ||
// console.log("err", err.deref()); | ||
seedWords.push(word); | ||
} | ||
console.log("seedWords", seedWords); | ||
|
||
function getBalance() { | ||
try { | ||
console.log("==="); | ||
console.log("Balance"); | ||
console.log("==="); | ||
let available = lib.wallet_get_available_balance(wallet, err); | ||
console.log(" available : ", available); | ||
let pending_in = lib.wallet_get_pending_incoming_balance(wallet, err); | ||
console.log(" pending_in: ", pending_in); | ||
console.log("==="); | ||
} catch (e) { | ||
console.error("balance error: ", e); | ||
} | ||
} | ||
let j = setInterval(getBalance, 10000); | ||
|
||
const u8ArrayFromHex = (hexString) => | ||
new Uint8Array( | ||
hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)) | ||
); | ||
const u8ArrayToHex = (bytes) => | ||
bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), ""); | ||
|
||
// let myPublicKey = lib.wallet_get_public_key(wallet, err); | ||
// console.log(myPublicKey); | ||
// console.log(err); | ||
// let temp = lib.public_key_get_bytes(myPublicKey, err); | ||
// console.log("temp", temp.deref()); | ||
|
||
// process.exit(); | ||
|
||
let publicKeyHex = | ||
"0c3fe3c23866ed3827e1cd72aae0c9d364d860d597993104e90d9a9401e52f05"; | ||
let publicKeyBytes = u8ArrayFromHex(publicKeyHex); | ||
let publicKeyByteVector = lib.byte_vector_create(publicKeyBytes, 32, err); | ||
let publicKey = lib.public_key_create(publicKeyByteVector, err); | ||
|
||
console.log("Set base node peer...", publicKeyHex); | ||
lib.wallet_add_base_node_peer( | ||
wallet, | ||
publicKey, | ||
"/onion3/2m2xnylrsqbaozsndkbmfisxxbwh2vgvs6oyfak2qah4snnxykrf7zad:18141", | ||
err | ||
); | ||
|
||
setTimeout(function () { | ||
try { | ||
console.log("start tx validation"); | ||
let id = lib.wallet_start_transaction_validation(wallet, err); | ||
console.log("tx validation request id", id); | ||
|
||
console.log("start utxo validation"); | ||
id = lib.wallet_start_utxo_validation(wallet, err); | ||
console.log("utxo validation request id", id); | ||
} catch (e) { | ||
console.error("validation error: ", e); | ||
} | ||
}, 5000); | ||
|
||
console.log("Wallet running..."); | ||
console.log("Ctrl+C to quit."); | ||
process.stdin.resume(); | ||
|
||
function exitHandler(options, exitCode) { | ||
try { | ||
console.log("exitHandler"); | ||
console.log("options", options); | ||
console.log("exitCode", exitCode); | ||
if (options.cleanup) { | ||
console.log("Exiting..."); | ||
lib.wallet_destroy(wallet); | ||
console.log("Goodbye."); | ||
} | ||
if (exitCode || exitCode === 0) console.log("\nExit code:", exitCode); | ||
if (options.exit) process.exit(); | ||
} catch (e) { | ||
console.error("exitHandler error", e); | ||
} | ||
} | ||
|
||
process.on("exit", exitHandler.bind(null, { cleanup: true, signal: "exit" })); | ||
process.on( | ||
"SIGINT", | ||
exitHandler.bind(null, { exit: true, signal: "SIGINT" }) | ||
); | ||
process.on( | ||
"SIGUSR1", | ||
exitHandler.bind(null, { exit: true, signal: "SIGUSR1" }) | ||
); | ||
process.on( | ||
"SIGUSR2", | ||
exitHandler.bind(null, { exit: true, signal: "SIGUSR2" }) | ||
); | ||
process.on( | ||
"uncaughtException", | ||
exitHandler.bind(null, { exit: true, signal: "uncaughtException" }) | ||
); | ||
} catch (e) { | ||
console.error("ERROR: ", e); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
const ffi = require("ffi-napi"); | ||
|
||
const { | ||
strPtr, | ||
errPtr, | ||
transportRef, | ||
commsConfigRef, | ||
walletRef, | ||
fn, | ||
bool, | ||
u8, | ||
u16, | ||
i32, | ||
u32, | ||
u64, | ||
u8Array, | ||
u8ArrayPtr, | ||
byteVectorRef, | ||
publicKeyRef, | ||
strArray, | ||
strArrayPtr, | ||
} = require("./types"); | ||
|
||
// todo: check if the lib exists first | ||
|
||
console.log("Set up library..."); | ||
const libWallet = ffi.Library("./libtari_wallet_ffi.dylib", { | ||
byte_vector_create: [byteVectorRef, [u8ArrayPtr, u32, errPtr]], | ||
comms_config_create: [ | ||
commsConfigRef, | ||
["string", transportRef, "string", "string", u64, u64, errPtr], | ||
], | ||
public_key_create: [publicKeyRef, [byteVectorRef, errPtr]], | ||
public_key_get_bytes: [u8ArrayPtr, [publicKeyRef, errPtr]], | ||
seed_words_create: [strPtr, []], | ||
seed_words_get_at: ["string", [strArrayPtr, u32, errPtr]], | ||
seed_words_push_word: [u8, [strPtr, "string", errPtr]], | ||
transport_tor_create: [ | ||
transportRef, | ||
["string", u8ArrayPtr, u16, "string", "string", errPtr], | ||
], | ||
wallet_add_base_node_peer: [bool, [walletRef, u8ArrayPtr, "string", errPtr]], | ||
wallet_create: [ | ||
walletRef, | ||
[ | ||
commsConfigRef, | ||
"string", | ||
u32, | ||
u32, | ||
"string", | ||
"string", | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
fn, | ||
errPtr, | ||
], | ||
], | ||
wallet_destroy: ["void", [walletRef]], | ||
wallet_get_available_balance: [u64, [walletRef, errPtr]], | ||
wallet_get_pending_incoming_balance: [u64, [walletRef, errPtr]], | ||
wallet_get_public_key: [publicKeyRef, [walletRef, errPtr]], | ||
wallet_get_seed_words: [strArrayPtr, [walletRef, errPtr]], | ||
wallet_get_num_confirmations_required: [u64, [walletRef, errPtr]], | ||
wallet_set_num_confirmations_required: ["void", [walletRef, u64, errPtr]], | ||
wallet_start_transaction_validation: [u64, [walletRef, errPtr]], | ||
wallet_start_utxo_validation: [u64, [walletRef, errPtr]], | ||
wallet_start_recovery: [bool, [walletRef, publicKeyRef, fn, errPtr]], | ||
}); | ||
|
||
module.exports = libWallet; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
const ref = require("ref-napi"); | ||
const ArrayType = require("ref-array-napi"); | ||
|
||
const strPtr = ref.refType(ref.types.CString); | ||
const errPtr = ref.refType(ref.types.int32); | ||
const transportRef = ref.refType(ref.types.void); | ||
const commsConfigRef = ref.refType(ref.types.void); | ||
const walletRef = ref.refType(ref.types.void); | ||
const fn = ref.refType(ref.types.void); | ||
const bool = ref.types.bool; | ||
const u8 = ref.types.uint8; | ||
const u16 = ref.types.uint16; | ||
const i32 = ref.types.int32; | ||
const u32 = ref.types.uint32; | ||
const u64 = ref.types.uint64; | ||
const u8Array = ArrayType(ref.types.uint8); | ||
const u8ArrayPtr = ref.refType(u8Array); | ||
const byteVectorRef = ref.refType(u8Array); | ||
const publicKeyRef = ref.refType(ref.types.void); | ||
const strArray = ArrayType("string"); | ||
const strArrayPtr = ref.refType(ArrayType("string")); | ||
|
||
module.exports = { | ||
strPtr, | ||
errPtr, | ||
transportRef, | ||
commsConfigRef, | ||
walletRef, | ||
fn, | ||
bool, | ||
u8, | ||
u16, | ||
i32, | ||
u32, | ||
u64, | ||
u8Array, | ||
u8ArrayPtr, | ||
byteVectorRef, | ||
publicKeyRef, | ||
strArray, | ||
strArrayPtr, | ||
}; |
Oops, something went wrong.