-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: adds send command to example client
- Loading branch information
Showing
7 changed files
with
244 additions
and
8 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
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
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
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
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,125 @@ | ||
import { | ||
Transaction as NativeTransaction, | ||
TRANSACTION_VERSION, | ||
Note as NativeNote, | ||
Asset, | ||
} from "@ironfish/rust-nodejs"; | ||
import { MerkleWitness, notesTree } from "./merkle"; | ||
import { AccountData } from "./AccountsManager"; | ||
|
||
/* | ||
This function is meant as example as to how to create a transaction using the core ironfish rust codebase, instead of the sdk. | ||
For an example of using the sdk, see the ironfish wallet | ||
In this case, we are using our own ironfish-rust-nodejs bindings, but other languages could be used as well with | ||
separate bindings to the underlying functions. | ||
*/ | ||
export async function createTransaction( | ||
account: AccountData, | ||
to: { publicAddress: string }, | ||
sendAmount: bigint, | ||
sendAssetId: Buffer, | ||
fee: bigint, // fee is always in native asset, $IRON | ||
memo: string, | ||
): Promise<NativeTransaction> { | ||
const transaction = new NativeTransaction( | ||
account.key.spendingKey, | ||
TRANSACTION_VERSION, | ||
); | ||
const amountsNeeded = buildAmountsNeeded(sendAssetId, sendAmount, fee); | ||
|
||
// fund the transaction and calculate the witnesses | ||
for (const [assetId, amount] of amountsNeeded) { | ||
const fundedAmount = await fundTransaction( | ||
transaction, | ||
account, | ||
assetId, | ||
amount, | ||
); | ||
const sendNote = new NativeNote( | ||
to.publicAddress, | ||
amount, | ||
memo, | ||
assetId, | ||
account.key.publicAddress, | ||
); | ||
transaction.output(sendNote); | ||
|
||
// issue change if necessary | ||
if (fundedAmount > amount) { | ||
const changeNote = new NativeNote( | ||
account.key.publicAddress, | ||
fundedAmount - amount, | ||
memo, | ||
assetId, | ||
account.key.publicAddress, | ||
); | ||
transaction.output(changeNote); | ||
} | ||
} | ||
// TODO mark notes as spent | ||
return transaction; | ||
} | ||
|
||
function buildAmountsNeeded( | ||
assetId: Buffer, | ||
amount: bigint, | ||
fee: bigint, | ||
): Map<Buffer, bigint> { | ||
const amountsNeeded = new Map<Buffer, bigint>(); | ||
amountsNeeded.set(Asset.nativeId(), fee); | ||
|
||
// add spend | ||
const currentAmount = amountsNeeded.get(assetId) ?? 0n; | ||
amountsNeeded.set(assetId, currentAmount + amount); | ||
|
||
return amountsNeeded; | ||
} | ||
|
||
async function fundTransaction( | ||
transaction: NativeTransaction, | ||
from: AccountData, | ||
assetId: Buffer, | ||
amount: bigint, | ||
): Promise<bigint> { | ||
let currentValue = 0n; | ||
const notesToSpend: { note: NativeNote; witness: MerkleWitness }[] = []; | ||
const notes = from.assets.get(assetId.toString("hex")); | ||
if (!notes) { | ||
throw new Error("No notes found for asset: " + assetId.toString("hex")); | ||
} | ||
for (const note of notes.decryptedNotes.values()) { | ||
if (currentValue >= amount) { | ||
break; | ||
} | ||
if ( | ||
note.note.assetId() !== assetId || | ||
note.spent === true || | ||
!note.sequence || | ||
!note.merkleIndex | ||
) { | ||
continue; | ||
} | ||
const witness = await notesTree.witness(note.merkleIndex); | ||
if (!witness) { | ||
console.warn( | ||
"Could not calculate witness for note: ", | ||
note.note.hash().toString("hex"), | ||
); | ||
continue; | ||
} | ||
currentValue += note.note.value(); | ||
transaction.spend(note.note, note); | ||
notesToSpend.push({ note: note.note, witness }); | ||
} | ||
if (currentValue < amount) { | ||
throw new Error( | ||
"Insufficient funds for asset: " + | ||
assetId.toString("hex") + | ||
" needed: " + | ||
amount.toString() + | ||
" have: " + | ||
currentValue.toString(), | ||
); | ||
} | ||
return currentValue; | ||
} |
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
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 |
---|---|---|
|
@@ -9,6 +9,54 @@ | |
dependencies: | ||
"@jridgewell/trace-mapping" "0.3.9" | ||
|
||
"@ironfish/[email protected]": | ||
version "1.7.0" | ||
resolved "https://registry.yarnpkg.com/@ironfish/rust-nodejs-darwin-arm64/-/rust-nodejs-darwin-arm64-1.7.0.tgz#e707ebee3785276d18676a554a8fe468757f9a54" | ||
integrity sha512-PDh+pfAsjA1q9K9GPwXWPZ+Vf+Hu3AHCRNPFq0LJ35gvWg8/cVwmaBQo2505hMJe+LT03i5wn0f4J6N63b4lkA== | ||
|
||
"@ironfish/[email protected]": | ||
version "1.7.0" | ||
resolved "https://registry.yarnpkg.com/@ironfish/rust-nodejs-darwin-x64/-/rust-nodejs-darwin-x64-1.7.0.tgz#c6e589bd6e4d737865232b0ac2c4bd6198540082" | ||
integrity sha512-fFfKTcsUxnqJPtYWxfJtRPOcFaziJw4SbLP2jfXemk7kp9ddoaYWJVqvoydVMe4cndDCz/OA/jLLFXn1Bm2MCw== | ||
|
||
"@ironfish/[email protected]": | ||
version "1.7.0" | ||
resolved "https://registry.yarnpkg.com/@ironfish/rust-nodejs-linux-arm64-gnu/-/rust-nodejs-linux-arm64-gnu-1.7.0.tgz#5cf76485229c612f464ef4f49aa9c98b7b017ef8" | ||
integrity sha512-LqJMDSO6MFPzF+EOAGdarIOJbCtkOL9kH1tpmMkhMbgfumpj+2Ma6jtDy6f3jX25jXW6YG3xV2oVWyApJuEgKw== | ||
|
||
"@ironfish/[email protected]": | ||
version "1.7.0" | ||
resolved "https://registry.yarnpkg.com/@ironfish/rust-nodejs-linux-arm64-musl/-/rust-nodejs-linux-arm64-musl-1.7.0.tgz#ffc88fc9139eaf39a5217a35529db3fa96d0c0cf" | ||
integrity sha512-ImsA9NJZQqPwSmeCDmk3kA66ccriOGEz/acljmwTgSvDYNea4RUJHwfMqn3fPV64iSGBgyH6NnVjtRwxjinaXQ== | ||
|
||
"@ironfish/[email protected]": | ||
version "1.7.0" | ||
resolved "https://registry.yarnpkg.com/@ironfish/rust-nodejs-linux-x64-gnu/-/rust-nodejs-linux-x64-gnu-1.7.0.tgz#a4102ec5fc5f913da2a3b78967238bb3ad7ccc96" | ||
integrity sha512-L6BaYQzHcHSsmjL97rh+ie+V8elOMwBeOmTzvggyw92Doe/orxAmwJclKGFe8WBPpbMh4RZuiecBznm7lSqw3Q== | ||
|
||
"@ironfish/[email protected]": | ||
version "1.7.0" | ||
resolved "https://registry.yarnpkg.com/@ironfish/rust-nodejs-linux-x64-musl/-/rust-nodejs-linux-x64-musl-1.7.0.tgz#ed10bcd88db864f9c257895debe2ac6841578dc6" | ||
integrity sha512-afDj8jAFdpTxYLXb4iv+3MpeR+TAKj9n/O46+1o8NxHWElgDgieJWmF/kC68nvGnxZY9ZxIibsPgfWxSNVHIQg== | ||
|
||
"@ironfish/[email protected]": | ||
version "1.7.0" | ||
resolved "https://registry.yarnpkg.com/@ironfish/rust-nodejs-win32-x64-msvc/-/rust-nodejs-win32-x64-msvc-1.7.0.tgz#8cf4cf07299899adb4a8544d315738fe5d9914b2" | ||
integrity sha512-6vpeIgJPCkTMpihARRiNQBAV/MDxakep7LJoBytOG0EbmJmzNqJHQwA3XcycXpLIpT2QrRsiHAtxK+O2VfuHjQ== | ||
|
||
"@ironfish/rust-nodejs@^1.7.0": | ||
version "1.7.0" | ||
resolved "https://registry.yarnpkg.com/@ironfish/rust-nodejs/-/rust-nodejs-1.7.0.tgz#6868812975839041d7579068df03e4663b6a8bb5" | ||
integrity sha512-ELYdc2pzMCyY1lGO8ewanZy+BYahbllcUOV11fcN2XlpHD6NiA0W5v0lUqbSres4A76+GNKJqFjgB9V+XqTwdg== | ||
optionalDependencies: | ||
"@ironfish/rust-nodejs-darwin-arm64" "1.7.0" | ||
"@ironfish/rust-nodejs-darwin-x64" "1.7.0" | ||
"@ironfish/rust-nodejs-linux-arm64-gnu" "1.7.0" | ||
"@ironfish/rust-nodejs-linux-arm64-musl" "1.7.0" | ||
"@ironfish/rust-nodejs-linux-x64-gnu" "1.7.0" | ||
"@ironfish/rust-nodejs-linux-x64-musl" "1.7.0" | ||
"@ironfish/rust-nodejs-win32-x64-msvc" "1.7.0" | ||
|
||
"@jridgewell/resolve-uri@^3.0.3": | ||
version "3.1.1" | ||
resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" | ||
|