fix: add Nonce transaction construction option
This commit is contained in:
committed by
Michael Vines
parent
600a295b11
commit
bd0a9348f4
@ -96,9 +96,22 @@ type SignaturePubkeyPair = {|
|
|||||||
*/
|
*/
|
||||||
type TransactionCtorFields = {|
|
type TransactionCtorFields = {|
|
||||||
recentBlockhash?: Blockhash | null,
|
recentBlockhash?: Blockhash | null,
|
||||||
|
nonceInfo?: NonceInformation | null,
|
||||||
signatures?: Array<SignaturePubkeyPair>,
|
signatures?: Array<SignaturePubkeyPair>,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NonceInformation to be used to build a Transaction.
|
||||||
|
*
|
||||||
|
* @typedef {Object} NonceInformation
|
||||||
|
* @property {nonce} The current Nonce blockhash
|
||||||
|
* @property {nonceInstruction} The NonceAdvance Instruction
|
||||||
|
*/
|
||||||
|
type NonceInformation = {|
|
||||||
|
nonce: Blockhash,
|
||||||
|
nonceInstruction: TransactionInstruction,
|
||||||
|
|};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transaction class
|
* Transaction class
|
||||||
*/
|
*/
|
||||||
@ -129,6 +142,12 @@ export class Transaction {
|
|||||||
*/
|
*/
|
||||||
recentBlockhash: Blockhash | null;
|
recentBlockhash: Blockhash | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional Nonce information. If populated, transaction will use a durable
|
||||||
|
* Nonce hash instead of a recentBlockhash. Must be populated by the caller
|
||||||
|
*/
|
||||||
|
nonceInfo: NonceInformation | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an empty Transaction
|
* Construct an empty Transaction
|
||||||
*/
|
*/
|
||||||
@ -164,6 +183,11 @@ export class Transaction {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_getSignData(): Buffer {
|
_getSignData(): Buffer {
|
||||||
|
const {nonceInfo} = this;
|
||||||
|
if (nonceInfo) {
|
||||||
|
this.recentBlockhash = nonceInfo.nonce;
|
||||||
|
this.instructions.unshift(nonceInfo.nonceInstruction);
|
||||||
|
}
|
||||||
const {recentBlockhash} = this;
|
const {recentBlockhash} = this;
|
||||||
if (!recentBlockhash) {
|
if (!recentBlockhash) {
|
||||||
throw new Error('Transaction recentBlockhash required');
|
throw new Error('Transaction recentBlockhash required');
|
||||||
|
@ -4,6 +4,7 @@ import nacl from 'tweetnacl';
|
|||||||
import {Account} from '../src/account';
|
import {Account} from '../src/account';
|
||||||
import {PublicKey} from '../src/publickey';
|
import {PublicKey} from '../src/publickey';
|
||||||
import {Transaction} from '../src/transaction';
|
import {Transaction} from '../src/transaction';
|
||||||
|
import {StakeProgram} from '../src/stake-program';
|
||||||
import {SystemProgram} from '../src/system-program';
|
import {SystemProgram} from '../src/system-program';
|
||||||
|
|
||||||
test('signPartial', () => {
|
test('signPartial', () => {
|
||||||
@ -78,6 +79,54 @@ test('dedup signatures', () => {
|
|||||||
orgTransaction.sign(account1);
|
orgTransaction.sign(account1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('use nonce', () => {
|
||||||
|
const account1 = new Account();
|
||||||
|
const account2 = new Account();
|
||||||
|
const nonceAccount = new Account();
|
||||||
|
const nonce = account2.publicKey.toBase58(); // Fake Nonce hash
|
||||||
|
|
||||||
|
const nonceInfo = {
|
||||||
|
nonce,
|
||||||
|
nonceInstruction: SystemProgram.nonceAdvance(
|
||||||
|
nonceAccount.publicKey,
|
||||||
|
account1.publicKey,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const transferTransaction = new Transaction({nonceInfo}).add(
|
||||||
|
SystemProgram.transfer(account1.publicKey, account2.publicKey, 123),
|
||||||
|
);
|
||||||
|
transferTransaction.sign(account1);
|
||||||
|
|
||||||
|
let expectedData = Buffer.alloc(4);
|
||||||
|
expectedData.writeInt32LE(4, 0);
|
||||||
|
|
||||||
|
expect(transferTransaction.instructions).toHaveLength(2);
|
||||||
|
expect(transferTransaction.instructions[0].programId).toEqual(
|
||||||
|
SystemProgram.programId,
|
||||||
|
);
|
||||||
|
expect(transferTransaction.instructions[0].data).toEqual(expectedData);
|
||||||
|
expect(transferTransaction.recentBlockhash).toEqual(nonce);
|
||||||
|
|
||||||
|
const stakeAccount = new Account();
|
||||||
|
const voteAccount = new Account();
|
||||||
|
const stakeTransaction = new Transaction({nonceInfo}).add(
|
||||||
|
StakeProgram.delegate(
|
||||||
|
stakeAccount.publicKey,
|
||||||
|
account1.publicKey,
|
||||||
|
voteAccount.publicKey,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
stakeTransaction.sign(account1);
|
||||||
|
|
||||||
|
expect(stakeTransaction.instructions).toHaveLength(2);
|
||||||
|
expect(stakeTransaction.instructions[0].programId).toEqual(
|
||||||
|
SystemProgram.programId,
|
||||||
|
);
|
||||||
|
expect(stakeTransaction.instructions[0].data).toEqual(expectedData);
|
||||||
|
expect(stakeTransaction.recentBlockhash).toEqual(nonce);
|
||||||
|
});
|
||||||
|
|
||||||
test('parse wire format and serialize', () => {
|
test('parse wire format and serialize', () => {
|
||||||
const keypair = nacl.sign.keyPair.fromSeed(
|
const keypair = nacl.sign.keyPair.fromSeed(
|
||||||
Uint8Array.from(Array(32).fill(8)),
|
Uint8Array.from(Array(32).fill(8)),
|
||||||
|
Reference in New Issue
Block a user