Skip to content
Draft
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
28 changes: 2 additions & 26 deletions modules/sdk-coin-hbar/src/lib/accountUpdateBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export class AccountUpdateBuilder extends TransactionBuilder {
private readonly _txBodyData: proto.CryptoUpdateTransactionBody;
private _accountId: string;
private _stakedNodeId?: Long;
private _stakedAccountId?: string;
private _declineStakingReward?: boolean;

constructor(_coinConfig: Readonly<CoinConfig>) {
Expand All @@ -31,9 +30,6 @@ export class AccountUpdateBuilder extends TransactionBuilder {
if (updateBody.stakedNodeId != null) {
this._stakedNodeId = Long.fromValue(updateBody.stakedNodeId);
}
if (updateBody.stakedAccountId) {
this._stakedAccountId = stringifyAccountId(updateBody.stakedAccountId);
}
if (updateBody.declineReward != null) {
const raw = updateBody.declineReward;
this._declineStakingReward = typeof raw === 'boolean' ? raw : (raw as { value: boolean }).value;
Expand All @@ -55,9 +51,6 @@ export class AccountUpdateBuilder extends TransactionBuilder {
if (this._stakedNodeId !== undefined) {
this._txBodyData.stakedNodeId = this._stakedNodeId;
}
if (this._stakedAccountId !== undefined) {
this._txBodyData.stakedAccountId = buildHederaAccountID(this._stakedAccountId);
}
if (this._declineStakingReward !== undefined) {
this._txBodyData.declineReward = { value: this._declineStakingReward };
}
Expand All @@ -67,11 +60,8 @@ export class AccountUpdateBuilder extends TransactionBuilder {

/** @inheritdoc */
validateMandatoryFields(): void {
if (this._stakedNodeId === undefined && this._stakedAccountId === undefined) {
throw new BuildTransactionError('Invalid transaction: missing stakedNodeId or stakedAccountId');
}
if (this._stakedNodeId !== undefined && this._stakedAccountId !== undefined) {
throw new BuildTransactionError('Invalid transaction: cannot set both stakedNodeId and stakedAccountId');
if (this._stakedNodeId === undefined) {
throw new BuildTransactionError('Invalid transaction: missing stakedNodeId');
}
super.validateMandatoryFields();
}
Expand Down Expand Up @@ -104,20 +94,6 @@ export class AccountUpdateBuilder extends TransactionBuilder {
return this;
}

/**
* Set the staked account ID for indirect staking. Use "0.0.0" to unstake.
*
* @param {string} accountId - The account ID to stake to in format <shard>.<realm>.<account>, or "0.0.0" to clear
* @returns {AccountUpdateBuilder} - This builder
*/
stakedAccountId(accountId: string): this {
if (!isValidAddress(accountId)) {
throw new BuildTransactionError('Invalid stakedAccountId: ' + accountId);
}
this._stakedAccountId = accountId;
return this;
}

/**
* Set whether to decline staking rewards.
*
Expand Down
1 change: 0 additions & 1 deletion modules/sdk-coin-hbar/src/lib/iface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export interface AccountUpdateInstruction {
params: {
accountId: string;
stakedNodeId?: string;
stakedAccountId?: string;
declineReward?: boolean;
};
}
10 changes: 1 addition & 9 deletions modules/sdk-coin-hbar/src/lib/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,21 +166,13 @@ export class Transaction extends BaseTransaction {
*
* @returns {object} The account update parameters including stakedNodeId and declineReward
*/
private getAccountUpdateData(): {
accountId: string;
stakedNodeId?: string;
stakedAccountId?: string;
declineReward?: boolean;
} {
private getAccountUpdateData(): { accountId: string; stakedNodeId?: string; declineReward?: boolean } {
const updateBody = this._txBody.cryptoUpdateAccount!;
return {
accountId: stringifyAccountId(updateBody.accountIDToUpdate!),
...(updateBody.stakedNodeId != null && {
stakedNodeId: Long.fromValue(updateBody.stakedNodeId).toString(),
}),
...(updateBody.stakedAccountId && {
stakedAccountId: stringifyAccountId(updateBody.stakedAccountId),
}),
...(updateBody.declineReward != null && {
declineReward:
typeof updateBody.declineReward === 'boolean'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,52 +130,6 @@ describe('HBAR Account Update Builder', () => {
const txJson = tx.toJson();
txJson.instructionsData.params.accountId.should.deepEqual(testData.ACCOUNT_2.accountId);
});

it('a stake-to-account transaction with stakedAccountId', async () => {
const txBuilder = factory.getAccountUpdateBuilder();
txBuilder.fee({ fee: testData.FEE });
txBuilder.source({ address: testData.ACCOUNT_1.accountId });
txBuilder.stakedAccountId(testData.ACCOUNT_2.accountId);
txBuilder.validDuration(1000000);
txBuilder.node({ nodeId: '0.0.2345' });
txBuilder.startTime('1596110493.372646570');
const tx = await txBuilder.build();
const txJson = tx.toJson();
txJson.instructionsData.params.stakedAccountId.should.deepEqual(testData.ACCOUNT_2.accountId);
txJson.instructionsData.params.accountId.should.deepEqual(testData.ACCOUNT_1.accountId);
should.not.exist(txJson.instructionsData.params.stakedNodeId);
tx.type.should.equal(TransactionType.AccountUpdate);
});

it('an unstake-from-account transaction with sentinel 0.0.0', async () => {
const txBuilder = factory.getAccountUpdateBuilder();
txBuilder.fee({ fee: testData.FEE });
txBuilder.source({ address: testData.ACCOUNT_1.accountId });
txBuilder.stakedAccountId('0.0.0');
txBuilder.validDuration(1000000);
txBuilder.node({ nodeId: '0.0.2345' });
txBuilder.startTime('1596110493.372646570');
const tx = await txBuilder.build();
const txJson = tx.toJson();
txJson.instructionsData.params.stakedAccountId.should.deepEqual('0.0.0');
should.not.exist(txJson.instructionsData.params.stakedNodeId);
tx.type.should.equal(TransactionType.AccountUpdate);
});

it('a stake-to-account transaction with declineReward', async () => {
const txBuilder = factory.getAccountUpdateBuilder();
txBuilder.fee({ fee: testData.FEE });
txBuilder.source({ address: testData.ACCOUNT_1.accountId });
txBuilder.stakedAccountId(testData.ACCOUNT_2.accountId);
txBuilder.declineStakingReward(true);
txBuilder.validDuration(1000000);
txBuilder.node({ nodeId: '0.0.2345' });
txBuilder.startTime('1596110493.372646570');
const tx = await txBuilder.build();
const txJson = tx.toJson();
txJson.instructionsData.params.stakedAccountId.should.deepEqual(testData.ACCOUNT_2.accountId);
txJson.instructionsData.params.declineReward.should.equal(true);
});
});

describe('serialized transactions', () => {
Expand Down Expand Up @@ -210,54 +164,16 @@ describe('HBAR Account Update Builder', () => {
tx2.toJson().instructionsData.params.accountId.should.deepEqual(testData.ACCOUNT_1.accountId);
tx2.toJson().instructionsData.params.stakedNodeId.should.deepEqual(NODE_ID.toString());
});

it('a stakedAccountId transaction round-trip', async () => {
const txBuilder = factory.getAccountUpdateBuilder();
txBuilder.fee({ fee: testData.FEE });
txBuilder.source({ address: testData.ACCOUNT_1.accountId });
txBuilder.stakedAccountId(testData.ACCOUNT_2.accountId);
txBuilder.validDuration(1000000);
txBuilder.node({ nodeId: '0.0.2345' });
txBuilder.startTime('1596110493.372646570');
const tx = await txBuilder.build();
const serialized = tx.toBroadcastFormat();

const builder2 = factory.from(serialized);
const tx2 = await builder2.build();
tx2.type.should.equal(TransactionType.AccountUpdate);
tx2.toJson().instructionsData.params.stakedAccountId.should.deepEqual(testData.ACCOUNT_2.accountId);
should.not.exist(tx2.toJson().instructionsData.params.stakedNodeId);
});
});
});

describe('should fail', () => {
it('a stake transaction without stakedNodeId or stakedAccountId', async () => {
it('a stake transaction without stakedNodeId', async () => {
const txBuilder = factory.getAccountUpdateBuilder();
txBuilder.fee({ fee: testData.FEE });
txBuilder.source({ address: testData.ACCOUNT_1.accountId });
txBuilder.node({ nodeId: '0.0.2345' });
await txBuilder.build().should.be.rejectedWith('Invalid transaction: missing stakedNodeId or stakedAccountId');
});

it('a stake transaction with both stakedNodeId and stakedAccountId', async () => {
const txBuilder = factory.getAccountUpdateBuilder();
txBuilder.fee({ fee: testData.FEE });
txBuilder.source({ address: testData.ACCOUNT_1.accountId });
txBuilder.stakedNodeId(NODE_ID);
txBuilder.stakedAccountId(testData.ACCOUNT_2.accountId);
txBuilder.node({ nodeId: '0.0.2345' });
await txBuilder
.build()
.should.be.rejectedWith('Invalid transaction: cannot set both stakedNodeId and stakedAccountId');
});

it('a stake transaction with an invalid stakedAccountId', () => {
const txBuilder = factory.getAccountUpdateBuilder();
assert.throws(
() => txBuilder.stakedAccountId('invalidAccountId'),
(e: any) => e.message === 'Invalid stakedAccountId: invalidAccountId'
);
await txBuilder.build().should.be.rejectedWith('Invalid transaction: missing stakedNodeId');
});

it('a stake transaction with an invalid account id', () => {
Expand Down
Loading