Learn how to sign a transaction and send Signa to another account
In this slightly more complex but still essential and though basic example we send some Signa to another account. Now, we need to get the senders passphrase to generate the keys we need for signing the transaction. The example assumes that we gathered the information somehow before. To see how to do this interactively in the command line we recommend our working examples in the repository.
The SignumJS library uses a local signing concept for advanced security. That means that under absolutely no circumstances no passphrase or private key is sent over the network.
Following functions from SignumJS are used in this example
composeApi function to create the api instance (the method is called inside provideLedger)
Address Value Object to parse and convert the given address
Amount Value Object to convert between Planck and Signa
generateMasterKeys Essential cryptographic function to derive the cryptographic keys for signing transactions from a passphrase
/** * A small helper function that returns the api object */functionprovideLedger(nodeHost) {constledger=composeApi({ nodeHost });console.info('-------------------------------------------');console.info(`The selected Signum Node is node is: ${ledger.service.settings.nodeHost}`);console.info('-------------------------------------------');return ledger}// some preset networksconstLedgerHostUrls= {'TestNet':'http://localhost:6876','MainNet':'https://europe.signum.network',}/** * This example shows how to send some amount of SIGNA to another account */asyncfunctionsendSigna(args) {try {const {ledgerType,recipient,amount,feeType} = args// actually, the provided ledger is the Api object returned from composeApi// we assume that the values are ['TestNet', 'MainNet']constledger=provideLedger(LedgerHostUrls[ledgerType])// we check if incoming account is either a Signum Address, or Numeric Id// eventually, we convert to Numeric Id, if the value is invalid an error will be thrownconstrecipientId=Address.create(recipient).getNumericId()// now we check if the account exists. If it does not exist the method throws an// exception and the further flow is interrupted.// Using exception to assert certain conditions is IMHO more robust than checking returned// values with if-statements. The code is much cleanerconsole.info("Verifying recipient...")awaitledger.account.getAccount({accountId: recipientId})// before we can send we need to get the private signing key from the user// In this current scenario we ask the user for his passphrase, as we can then derive the necessary key// this is an external function not related to SignumJS - it's here for demonstratopion purposesconst {passphrase} =awaitconfirmTransaction(args)// once we gathered the passphrase, we can generate the signing keysconst {publicKey,signPrivateKey} =generateMasterKeys(passphrase)// as a next step, we use the systems fee suggestion mechanism to give us the current costs for the chosen// fee type. In this example we let it flexible, but you can fix the fee costs to a minimum, i.e. 0,00735 SIGNAconstsuggestedFees=awaitledger.network.getSuggestedFees()// we assume that the feeType is either ['Minimum', 'Cheap', 'Standard', 'Priority']constselectedFeePlanck= suggestedFees[feeType.toLowerCase()]// Now, we execute the transaction// within this method the local signing flow is being executed, i.e.// the private key is used only locally for signinh, but never sent over the networkconst {transaction} =awaitledger.transaction.sendAmountToSingleRecipient( { recipientId, amountPlanck:Amount.fromSigna(amount).getPlanck(), feePlanck: selectedFeePlanck, senderPrivateKey: signPrivateKey, senderPublicKey: publicKey } );// now, some final nice messageconstaddressPrefix= ledgerType ==='MainNet'?AddressPrefix.MainNet :AddressPrefix.TestNet console.info(`Successfully sent ${amount} ${CurrencySymbol} to ${Address.create(recipientId, addressPrefix).getReedSolomonAddress()} - Transaction Id: ${transaction}`)
console.info(`You paid a total of ${Amount.fromSigna(amount).add(Amount.fromPlanck(selectedFeePlanck)).toString()}`)
} catch (e) {handleError(e); }}