Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for non participation (nonpart) flag in keyreg transaction #271

Merged
merged 2 commits into from Feb 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions src/makeTxn.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ function makePaymentTxn(from, to, fee, amount, closeRemainderTo, firstRound, las
* genesisHash - string specifies hash genesis block of network in use
* genesisID - string specifies genesis ID of network in use
* @param rekeyTo - rekeyTo address, optional
* @Deprecated in version 2.0 this will change to use the "WithSuggestedParams" signature.
* @returns {Transaction}
*/
function makePaymentTxnWithSuggestedParams(from, to, amount, closeRemainderTo, note, suggestedParams, rekeyTo=undefined) {
Expand Down Expand Up @@ -85,19 +84,21 @@ function makePaymentTxnWithSuggestedParamsFromObject(o) {
* @param voteLast - last round on which voteKey is valid
* @param voteKeyDilution - integer
* @param rekeyTo - rekeyTo address, optional
* @param nonParticipation - configure whether the address wants to stop participating. If true,
* voteKey, selectionKey, voteFirst, voteLast, and voteKeyDilution must be undefined.
* @Deprecated in version 2.0 this will change to use the "WithSuggestedParams" signature.
* @returns {Transaction}
*/
function makeKeyRegistrationTxn(from, fee, firstRound, lastRound, note, genesisHash, genesisID,
voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution, rekeyTo=undefined) {
voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution, rekeyTo=undefined, nonParticipation=false) {
let suggestedParams = {
"genesisHash": genesisHash,
"genesisID": genesisID,
"firstRound": firstRound,
"lastRound": lastRound,
"fee": fee
};
return makeKeyRegistrationTxnWithSuggestedParams(from, note, voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution, suggestedParams, rekeyTo);
return makeKeyRegistrationTxnWithSuggestedParams(from, note, voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution, suggestedParams, rekeyTo, nonParticipation);
}

/**
Expand All @@ -120,10 +121,11 @@ function makeKeyRegistrationTxn(from, fee, firstRound, lastRound, note, genesisH
* genesisHash - string specifies hash genesis block of network in use
* genesisID - string specifies genesis ID of network in use
* @param rekeyTo - rekeyTo address, optional
* @Deprecated in version 2.0 this will change to use the "WithSuggestedParams" signature.
* @param nonParticipation - configure whether the address wants to stop participating. If true,
* voteKey, selectionKey, voteFirst, voteLast, and voteKeyDilution must be undefined.
* @returns {Transaction}
*/
function makeKeyRegistrationTxnWithSuggestedParams(from, note, voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution, suggestedParams, rekeyTo=undefined) {
function makeKeyRegistrationTxnWithSuggestedParams(from, note, voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution, suggestedParams, rekeyTo=undefined, nonParticipation=false) {
let o = {
"from": from,
"note": note,
Expand All @@ -134,15 +136,16 @@ function makeKeyRegistrationTxnWithSuggestedParams(from, note, voteKey, selectio
"voteKeyDilution": voteKeyDilution,
"suggestedParams": suggestedParams,
"type": "keyreg",
"reKeyTo": rekeyTo
"reKeyTo": rekeyTo,
"nonParticipation": nonParticipation,
};
return new txnBuilder.Transaction(o);
}

// helper for above makeKeyRegistrationTxnWithSuggestedParams, instead accepting an arguments object
function makeKeyRegistrationTxnWithSuggestedParamsFromObject(o) {
return makeKeyRegistrationTxnWithSuggestedParams(o.from, o.note, o.voteKey, o.selectionKey, o.voteFirst, o.voteLast,
o.voteKeyDilution, o.suggestedParams, o.rekeyTo);
o.voteKeyDilution, o.suggestedParams, o.rekeyTo, o.nonParticipation);
}

/** makeAssetCreateTxn takes asset creation arguments and returns a Transaction object
Expand Down
18 changes: 15 additions & 3 deletions src/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ const ASSET_METADATA_HASH_LENGTH = 32;
* */
class Transaction {
constructor({from, to, fee, amount, firstRound, lastRound, note, genesisID, genesisHash, lease,
closeRemainderTo, voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution,
closeRemainderTo, voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution,
assetIndex, assetTotal, assetDecimals, assetDefaultFrozen, assetManager, assetReserve,
assetFreeze, assetClawback, assetUnitName, assetName, assetURL, assetMetadataHash,
freezeAccount, freezeState, assetRevocationTarget,
appIndex, appOnComplete, appLocalInts, appLocalByteSlices,
appGlobalInts, appGlobalByteSlices, appApprovalProgram, appClearProgram,
appArgs, appAccounts, appForeignApps, appForeignAssets,
type="pay", flatFee=false, suggestedParams=undefined,
reKeyTo=undefined}) {
reKeyTo=undefined, nonParticipation=false}) {
this.name = "Transaction";
this.tag = Buffer.from("TX");

Expand Down Expand Up @@ -126,6 +126,9 @@ class Transaction {
if (selectionKey !== undefined) {
selectionKey = Buffer.from(selectionKey, "base64");
}
if (nonParticipation && (voteKey || selectionKey || voteFirst || voteLast || voteKeyDilution)) {
throw new Error('nonParticipation is true but participation params are present.');
}

Object.assign(this, {
from, to, fee, amount, firstRound, lastRound, note, genesisID, genesisHash, lease,
Expand All @@ -135,7 +138,7 @@ class Transaction {
freezeAccount, freezeState, assetRevocationTarget,
appIndex, appOnComplete, appLocalInts, appLocalByteSlices, appGlobalInts, appGlobalByteSlices,
appApprovalProgram, appClearProgram, appArgs, appAccounts, appForeignApps, appForeignAssets,
type, reKeyTo
type, reKeyTo, nonParticipation
});

// Modify Fee
Expand Down Expand Up @@ -212,6 +215,14 @@ class Transaction {
if ((this.reKeyTo !== undefined)) {
txn.rekey = Buffer.from(this.reKeyTo.publicKey)
}
if (this.nonParticipation) {
txn.nonpart = true;
delete txn.votekey;
delete txn.selkey;
delete txn.votefst;
delete txn.votelst;
delete txn.votekd;
}
return txn;
}
else if (this.type == "acfg") {
Expand Down Expand Up @@ -448,6 +459,7 @@ class Transaction {
txn.voteKeyDilution = txnForEnc.votekd;
txn.voteFirst = txnForEnc.votefst;
txn.voteLast = txnForEnc.votelst;
txn.nonParticipation = txnForEnc.nonpart;
}
else if (txnForEnc.type === "acfg") {
// asset creation, or asset reconfigure, or asset destruction
Expand Down
39 changes: 39 additions & 0 deletions tests/5.Transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,45 @@ describe('Sign', function () {
assert.deepStrictEqual(expectedTxn, actualTxn);
});

it('should be able to use helper to make a nonparticipating keyreg transaction', function() {
let from = "XMHLMNAVJIMAW2RHJXLXKKK4G3J3U6VONNO3BTAQYVDC3MHTGDP3J5OCRU";
let fee = 10;
let firstRound = 51;
let lastRound = 61;
let note = new Uint8Array([123, 12, 200]);
let genesisHash = "JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=";
let genesisID = "";
let rekeyTo = "GAQVB24XEPYOPBQNJQAE4K3OLNYTRYD65ZKR3OEW5TDOOGL7MDKABXHHTM";
let voteKey = "5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=";
let selectionKey = "oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=";
let voteKeyDilution = 1234;
let voteFirst = 123;
let voteLast = 456;
let nonParticipation = true;
let o = {
"from": from,
"fee": fee,
"firstRound": firstRound,
"lastRound": lastRound,
"note": note,
"genesisHash": genesisHash,
"nonParticipation": nonParticipation,
"genesisID": genesisID,
"reKeyTo": rekeyTo,
"type": "keyreg"
};

assert.throws(
() => new algosdk.Transaction({ ...o, voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution }),
new Error("nonParticipation is true but participation params are present.")
);

let expectedTxn = new algosdk.Transaction(o);
let actualTxn = algosdk.makeKeyRegistrationTxn(from, fee, firstRound, lastRound, note, genesisHash, genesisID,
undefined, undefined, undefined, undefined, undefined, rekeyTo, nonParticipation);
assert.deepStrictEqual(expectedTxn, actualTxn);
});

it('should be able to use helper to make an asset create transaction', function() {
let addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4";
let fee = 10;
Expand Down