fix: Rename lastId to blockhash

This commit is contained in:
Michael Vines 2019-03-04 08:06:33 -08:00
parent c867f0d9fe
commit 294dd4f4e7
8 changed files with 89 additions and 84 deletions

View File

@ -22,6 +22,9 @@ declare module '@solana/web3.js' {
toBuffer(): Buffer;
}
// === src/blockhash.js ===
declare export type Blockhash = string;
// === src/account.js ===
declare export class Account {
constructor(secretKey: ?Buffer): Account;
@ -58,7 +61,7 @@ declare module '@solana/web3.js' {
signature: TransactionSignature,
): Promise<SignatureStatus>;
getTransactionCount(): Promise<number>;
getLastId(): Promise<TransactionId>;
getRecentBlockhash(): Promise<Blockhash>;
requestAirdrop(
to: PublicKey,
amount: number,
@ -92,7 +95,6 @@ declare module '@solana/web3.js' {
// === src/transaction.js ===
declare export type TransactionSignature = string;
declare export type TransactionId = string;
declare type TransactionInstructionCtorFields = {|
keys: ?Array<PublicKey>,
@ -113,7 +115,7 @@ declare module '@solana/web3.js' {
declare type TransactionCtorFields = {|
fee?: number,
lastId?: TransactionId,
recentBlockhash?: Blockhash,
signatures?: Array<SignaturePubkeyPair>,
|};
@ -121,7 +123,7 @@ declare module '@solana/web3.js' {
signatures: Array<SignaturePubkeyPair>;
signature: ?Buffer;
instructions: Array<TransactionInstruction>;
lastId: ?TransactionId;
recentBlockhash: ?Blockhash;
fee: number;
constructor(opts?: TransactionCtorFields): Transaction;

6
web3.js/src/blockhash.js Normal file
View File

@ -0,0 +1,6 @@
// @flow
/**
* @typedef {string} Blockhhash
*/
export type Blockhash = string;

View File

@ -10,8 +10,9 @@ import {Client as RpcWebSocketClient} from 'rpc-websockets';
import {Transaction} from './transaction';
import {PublicKey} from './publickey';
import {sleep} from './util/sleep';
import type {Blockhash} from './blockhash';
import type {Account} from './account';
import type {TransactionSignature, TransactionId} from './transaction';
import type {TransactionSignature} from './transaction';
type RpcRequest = (methodName: string, args: Array<any>) => any;
@ -124,9 +125,9 @@ const GetSignatureStatusRpcResult = jsonRpcResult(
const GetTransactionCountRpcResult = jsonRpcResult('number');
/**
* Expected JSON RPC response for the "getLastId" message
* Expected JSON RPC response for the "getRecentBlockhash" message
*/
const GetLastId = jsonRpcResult('string');
const GetRecentBlockhash = jsonRpcResult('string');
/**
* Expected JSON RPC response for the "requestAirdrop" message
@ -188,12 +189,12 @@ export class Connection {
_rpcWebSocket: RpcWebSocketClient;
_rpcWebSocketConnected: boolean = false;
_lastIdInfo: {
lastId: TransactionId | null,
_blockhashInfo: {
recentBlockhash: Blockhash | null,
seconds: number,
transactionSignatures: Array<string>,
};
_disableLastIdCaching: boolean = false;
_disableBlockhashCaching: boolean = false;
_accountChangeSubscriptions: {[number]: AccountSubscriptionInfo} = {};
_accountChangeSubscriptionCounter: number = 0;
@ -206,8 +207,8 @@ export class Connection {
let url = urlParse(endpoint);
this._rpcRequest = createRpcRequest(url.href);
this._lastIdInfo = {
lastId: null,
this._blockhashInfo = {
recentBlockhash: null,
seconds: -1,
transactionSignatures: [],
};
@ -283,7 +284,7 @@ export class Connection {
}
/**
* Fetch the current transaction count of the network
* Fetch the current transaction count of the cluster
*/
async getSignatureStatus(
signature: TransactionSignature,
@ -298,7 +299,7 @@ export class Connection {
}
/**
* Fetch the current transaction count of the network
* Fetch the current transaction count of the cluster
*/
async getTransactionCount(): Promise<number> {
const unsafeRes = await this._rpcRequest('getTransactionCount', []);
@ -311,11 +312,11 @@ export class Connection {
}
/**
* Fetch the identifier to the latest transaction on the network
* Fetch a recent blockhash from the cluster
*/
async getLastId(): Promise<TransactionId> {
const unsafeRes = await this._rpcRequest('getLastId', []);
const res = GetLastId(unsafeRes);
async getRecentBlockhash(): Promise<Blockhash> {
const unsafeRes = await this._rpcRequest('getRecentBlockhash', []);
const res = GetRecentBlockhash(unsafeRes);
if (res.error) {
throw new Error(res.error.message);
}
@ -353,22 +354,22 @@ export class Connection {
// Attempt to use the previous last id for up to 1 second
const seconds = new Date().getSeconds();
if (
this._lastIdInfo.lastId != null &&
this._lastIdInfo.seconds === seconds
this._blockhashInfo.recentBlockhash != null &&
this._blockhashInfo.seconds === seconds
) {
transaction.lastId = this._lastIdInfo.lastId;
transaction.recentBlockhash = this._blockhashInfo.recentBlockhash;
transaction.sign(...signers);
if (!transaction.signature) {
throw new Error('!signature'); // should never happen
}
// If the signature of this transaction has not been seen before with the
// current lastId, all done.
// current recentBlockhash, all done.
const signature = transaction.signature.toString();
if (!this._lastIdInfo.transactionSignatures.includes(signature)) {
this._lastIdInfo.transactionSignatures.push(signature);
if (this._disableLastIdCaching) {
this._lastIdInfo.seconds = -1;
if (!this._blockhashInfo.transactionSignatures.includes(signature)) {
this._blockhashInfo.transactionSignatures.push(signature);
if (this._disableBlockhashCaching) {
this._blockhashInfo.seconds = -1;
}
break;
}
@ -378,11 +379,11 @@ export class Connection {
let attempts = 0;
const startTime = Date.now();
for (;;) {
const lastId = await this.getLastId();
const recentBlockhash = await this.getRecentBlockhash();
if (this._lastIdInfo.lastId != lastId) {
this._lastIdInfo = {
lastId,
if (this._blockhashInfo.recentBlockhash != recentBlockhash) {
this._blockhashInfo = {
recentBlockhash,
seconds: new Date().getSeconds(),
transactionSignatures: [],
};

View File

@ -9,17 +9,13 @@ import * as Layout from './layout';
import {PublicKey} from './publickey';
import {Account} from './account';
import * as shortvec from './util/shortvec-encoding';
import type {Blockhash} from './blockhash';
/**
* @typedef {string} TransactionSignature
*/
export type TransactionSignature = string;
/**
* @typedef {string} TransactionId
*/
export type TransactionId = string;
/**
* Maximum over-the-wire size of a Transaction
*/
@ -76,13 +72,13 @@ type SignaturePubkeyPair = {|
*
* @typedef {Object} TransactionCtorFields
* @property {?number} fee
* @property (?lastId} A recent transaction id
* @property (?recentBlockhash} A recent block hash
* @property (?signatures} One or more signatures
*
*/
type TransactionCtorFields = {|
fee?: number,
lastId?: TransactionId,
recentBlockhash?: Blockhash,
signatures?: Array<SignaturePubkeyPair>,
|};
@ -114,7 +110,7 @@ export class Transaction {
/**
* A recent transaction id. Must be populated by the caller
*/
lastId: ?TransactionId;
recentBlockhash: ?Blockhash;
/**
* Fee for this transaction
@ -152,9 +148,9 @@ export class Transaction {
* @private
*/
_getSignData(): Buffer {
const {lastId} = this;
if (!lastId) {
throw new Error('Transaction lastId required');
const {recentBlockhash} = this;
if (!recentBlockhash) {
throw new Error('Transaction recentBlockhash required');
}
if (this.instructions.length < 1) {
@ -245,7 +241,7 @@ export class Transaction {
const signDataLayout = BufferLayout.struct([
BufferLayout.blob(keyCount.length, 'keyCount'),
BufferLayout.seq(Layout.publicKey('key'), keys.length, 'keys'),
Layout.publicKey('lastId'),
Layout.publicKey('recentBlockhash'),
BufferLayout.ns64('fee'),
BufferLayout.blob(programIdCount.length, 'programIdCount'),
@ -259,7 +255,7 @@ export class Transaction {
const transaction = {
keyCount: Buffer.from(keyCount),
keys: keys.map(key => new PublicKey(key).toBuffer()),
lastId: Buffer.from(bs58.decode(lastId)),
recentBlockhash: Buffer.from(bs58.decode(recentBlockhash)),
fee: this.fee,
programIdCount: Buffer.from(programIdCount),
programIds: programIds.map(programId =>
@ -284,7 +280,7 @@ export class Transaction {
* as doing so may invalidate the signature and cause the Transaction to be
* rejected.
*
* The Transaction must be assigned a valid `lastId` before invoking this method
* The Transaction must be assigned a valid `recentBlockhash` before invoking this method
*/
sign(...signers: Array<Account>) {
this.signPartial(...signers);
@ -442,7 +438,7 @@ export class Transaction {
accounts.push(account);
}
const lastId = byteArray.slice(0, PUBKEY_LENGTH);
const recentBlockhash = byteArray.slice(0, PUBKEY_LENGTH);
byteArray = byteArray.slice(PUBKEY_LENGTH);
let fee = 0;
@ -473,7 +469,7 @@ export class Transaction {
}
// Populate Transaction object
transaction.lastId = new PublicKey(lastId).toBase58();
transaction.recentBlockhash = new PublicKey(recentBlockhash).toBase58();
transaction.fee = fee;
for (let i = 0; i < signatureCount; i++) {
const sigPubkeyPair = {

View File

@ -8,7 +8,7 @@ import {
sendAndConfirmTransaction,
} from '../src';
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
import {mockGetLastId} from './mockrpc/getlastid';
import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash';
import {url} from './url';
import {sleep} from '../src/util/sleep';
@ -117,10 +117,10 @@ test('get transaction count', async () => {
test('get last Id', async () => {
const connection = new Connection(url);
mockGetLastId();
mockGetRecentBlockhash();
const lastId = await connection.getLastId();
expect(lastId.length).toBeGreaterThanOrEqual(43);
const recentBlockhash = await connection.getRecentBlockhash();
expect(recentBlockhash.length).toBeGreaterThanOrEqual(43);
});
test('request airdrop', async () => {
@ -282,7 +282,7 @@ test('transaction', async () => {
await connection.requestAirdrop(accountTo.publicKey, 21);
expect(await connection.getBalance(accountTo.publicKey)).toBe(21);
mockGetLastId();
mockGetRecentBlockhash();
mockRpc.push([
url,
{

View File

@ -4,18 +4,18 @@ import {Account} from '../../src';
import {url} from '../url';
import {mockRpc} from '../__mocks__/node-fetch';
export function mockGetLastId() {
const lastId = new Account();
export function mockGetRecentBlockhash() {
const recentBlockhash = new Account();
mockRpc.push([
url,
{
method: 'getLastId',
method: 'getRecentBlockhash',
params: [],
},
{
error: null,
result: lastId.publicKey.toBase58(),
result: recentBlockhash.publicKey.toBase58(),
},
]);
}

View File

@ -5,7 +5,7 @@ import {SYSTEM_TOKEN_PROGRAM_ID} from '../src/token-program';
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
import {url} from './url';
import {newAccountWithTokens} from './new-account-with-tokens';
import {mockGetLastId} from './mockrpc/getlastid';
import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash';
import {sleep} from '../src/util/sleep';
if (!mockRpcEnabled) {
@ -48,29 +48,29 @@ let initialOwnerTokenAccount: PublicKey;
test('create new token', async () => {
const connection = new Connection(url);
connection._disableLastIdCaching = mockRpcEnabled;
connection._disableBlockhashCaching = mockRpcEnabled;
initialOwner = await newAccountWithTokens(connection, 1024);
{
// mock SystemProgram.createAccount transaction for Token.createNewToken()
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
// mock Token.newAccount() transaction
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus('SignatureNotFound');
mockGetSignatureStatus();
// mock SystemProgram.createAccount transaction for Token.createNewToken()
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
// mock Token.createNewToken() transaction
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus('SignatureNotFound');
mockGetSignatureStatus();
@ -228,17 +228,17 @@ test('create new token', async () => {
test('create new token account', async () => {
const connection = new Connection(url);
connection._disableLastIdCaching = mockRpcEnabled;
connection._disableBlockhashCaching = mockRpcEnabled;
const destOwner = await newAccountWithTokens(connection);
{
// mock SystemProgram.createAccount transaction for Token.newAccount()
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
// mock Token.newAccount() transaction
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
}
@ -287,17 +287,17 @@ test('create new token account', async () => {
test('transfer', async () => {
const connection = new Connection(url);
connection._disableLastIdCaching = mockRpcEnabled;
connection._disableBlockhashCaching = mockRpcEnabled;
const destOwner = await newAccountWithTokens(connection);
{
// mock SystemProgram.createAccount transaction for Token.newAccount()
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
// mock Token.newAccount() transaction
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
}
@ -337,7 +337,7 @@ test('transfer', async () => {
]);
// mock Token.transfer() transaction
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
}
@ -385,17 +385,17 @@ test('transfer', async () => {
test('approve/revoke', async () => {
const connection = new Connection(url);
connection._disableLastIdCaching = mockRpcEnabled;
connection._disableBlockhashCaching = mockRpcEnabled;
const delegateOwner = await newAccountWithTokens(connection);
{
// mock SystemProgram.createAccount transaction for Token.newAccount()
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
// mock Token.newAccount() transaction
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
}
@ -406,7 +406,7 @@ test('approve/revoke', async () => {
{
// mock Token.approve() transaction
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
}
@ -474,7 +474,7 @@ test('approve/revoke', async () => {
{
// mock Token.revoke() transaction
mockGetLastId();
mockGetRecentBlockhash();
mockSendTransaction();
mockGetSignatureStatus();
}
@ -542,7 +542,7 @@ test('invalid approve', async () => {
}
const connection = new Connection(url);
connection._disableLastIdCaching = mockRpcEnabled;
connection._disableBlockhashCaching = mockRpcEnabled;
const owner = await newAccountWithTokens(connection);
const account1 = await testToken.newAccount(owner);
@ -567,7 +567,7 @@ test('fail on approve overspend', async () => {
}
const connection = new Connection(url);
connection._disableLastIdCaching = mockRpcEnabled;
connection._disableBlockhashCaching = mockRpcEnabled;
const owner = await newAccountWithTokens(connection);
const account1 = await testToken.newAccount(owner);
@ -611,7 +611,7 @@ test('set owner', async () => {
}
const connection = new Connection(url);
connection._disableLastIdCaching = mockRpcEnabled;
connection._disableBlockhashCaching = mockRpcEnabled;
const owner = await newAccountWithTokens(connection);
const newOwner = await newAccountWithTokens(connection);

View File

@ -7,13 +7,13 @@ import {SystemProgram} from '../src/system-program';
test('signPartial', () => {
const account1 = new Account();
const account2 = new Account();
const lastId = account1.publicKey.toBase58(); // Fake lastId
const recentBlockhash = account1.publicKey.toBase58(); // Fake recentBlockhash
const move = SystemProgram.move(account1.publicKey, account2.publicKey, 123);
const transaction = new Transaction({lastId}).add(move);
const transaction = new Transaction({recentBlockhash}).add(move);
transaction.sign(account1, account2);
const partialTransaction = new Transaction({lastId}).add(move);
const partialTransaction = new Transaction({recentBlockhash}).add(move);
partialTransaction.signPartial(account1, account2.publicKey);
expect(partialTransaction.signatures[1].signature).toBeNull();
partialTransaction.addSigner(account2);
@ -24,15 +24,15 @@ test('signPartial', () => {
test('transfer signatures', () => {
const account1 = new Account();
const account2 = new Account();
const lastId = account1.publicKey.toBase58(); // Fake lastId
const recentBlockhash = account1.publicKey.toBase58(); // Fake recentBlockhash
const move1 = SystemProgram.move(account1.publicKey, account2.publicKey, 123);
const move2 = SystemProgram.move(account2.publicKey, account1.publicKey, 123);
const orgTransaction = new Transaction({lastId}).add(move1, move2);
const orgTransaction = new Transaction({recentBlockhash}).add(move1, move2);
orgTransaction.sign(account1, account2);
const newTransaction = new Transaction({
lastId: orgTransaction.lastId,
recentBlockhash: orgTransaction.recentBlockhash,
fee: orgTransaction.fee,
signatures: orgTransaction.signatures,
}).add(move1, move2);
@ -41,13 +41,13 @@ test('transfer signatures', () => {
});
test('parse wire format and serialize', () => {
const lastId = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known lastId
const recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known recentBlockhash
const sender = new Account(Buffer.alloc(64, 8)); // Arbitrary known account
const recipient = new PublicKey(
'J3dxNj7nDRRqRRXuEMynDG57DkZK4jYRuv3Garmb1i99',
); // Arbitrary known public key
const move = SystemProgram.move(sender.publicKey, recipient, 49);
const expectedTransaction = new Transaction({lastId}).add(move);
const expectedTransaction = new Transaction({recentBlockhash}).add(move);
expectedTransaction.sign(sender);
const wireTransaction = Buffer.from([