feat: wrap public key in a class

This commit is contained in:
Michael Vines
2018-09-30 18:42:45 -07:00
parent 2c3208090c
commit ca6965f8c2
15 changed files with 180 additions and 95 deletions

View File

@ -1,14 +1,8 @@
// @flow
import nacl from 'tweetnacl';
import bs58 from 'bs58';
import type {KeyPair} from 'tweetnacl';
/**
* Base 58 encoded public key
*
* @typedef {string} PublicKey
*/
export type PublicKey = string;
import {PublicKey} from './publickey';
/**
* An account key pair (public and secret keys).
@ -36,7 +30,7 @@ export class Account {
* The public key for this account
*/
get publicKey(): PublicKey {
return bs58.encode(this._keypair.publicKey);
return new PublicKey(this._keypair.publicKey);
}
/**

View File

@ -1,7 +1,7 @@
// @flow
import {Transaction} from './transaction';
import type {PublicKey} from './account';
import {PublicKey} from './publickey';
/**
* Represents a condition that is met by executing a `applySignature()`
@ -54,7 +54,7 @@ export type BudgetCondition = SignatureCondition | TimestampCondition;
* @private
*/
function serializePayment(payment: Payment): Buffer {
const toData = Transaction.serializePublicKey(payment.to);
const toData = payment.to.toBuffer();
const userdata = Buffer.alloc(8 + toData.length);
userdata.writeUInt32LE(payment.amount, 0);
toData.copy(userdata, 8);
@ -98,7 +98,7 @@ function serializeCondition(condition: BudgetCondition) {
case 'timestamp':
{
const date = serializeDate(condition.when);
const from = Transaction.serializePublicKey(condition.from);
const from = condition.from.toBuffer();
const userdata = Buffer.alloc(4 + date.length + from.length);
userdata.writeUInt32LE(0, 0); // Condition enum = Timestamp
@ -108,7 +108,7 @@ function serializeCondition(condition: BudgetCondition) {
}
case 'signature':
{
const from = Transaction.serializePublicKey(condition.from);
const from = condition.from.toBuffer();
const userdata = Buffer.alloc(4 + from.length);
userdata.writeUInt32LE(1, 0); // Condition enum = Signature
@ -130,7 +130,7 @@ export class BudgetProgram {
* Public key that identifies the Budget program
*/
static get programId(): PublicKey {
return '4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM';
return new PublicKey('0x100000000000000000000000000000000000000000000000000000000000000');
}
/**

View File

@ -4,10 +4,10 @@ import assert from 'assert';
import fetch from 'node-fetch';
import jayson from 'jayson/lib/client/browser';
import {struct} from 'superstruct';
import bs58 from 'bs58';
import {Transaction} from './transaction';
import type {Account, PublicKey} from './account';
import {PublicKey} from './publickey';
import type {Account} from './account';
import type {TransactionSignature, TransactionId} from './transaction';
type RpcRequest = (methodName: string, args: Array<any>) => any;
@ -174,7 +174,7 @@ export class Connection {
async getBalance(publicKey: PublicKey): Promise<number> {
const unsafeRes = await this._rpcRequest(
'getBalance',
[publicKey]
[publicKey.toBase58()]
);
const res = GetBalanceRpcResult(unsafeRes);
if (res.error) {
@ -190,7 +190,7 @@ export class Connection {
async getAccountInfo(publicKey: PublicKey): Promise<AccountInfo> {
const unsafeRes = await this._rpcRequest(
'getAccountInfo',
[publicKey]
[publicKey.toBase58()]
);
const res = GetAccountInfoRpcResult(unsafeRes);
if (res.error) {
@ -202,7 +202,7 @@ export class Connection {
return {
tokens: result.tokens,
programId: bs58.encode(result.program_id),
programId: new PublicKey(result.program_id),
userdata: Buffer.from(result.userdata),
};
}
@ -280,7 +280,7 @@ export class Connection {
* Request an allocation of tokens to the specified account
*/
async requestAirdrop(to: PublicKey, amount: number): Promise<TransactionSignature> {
const unsafeRes = await this._rpcRequest('requestAirdrop', [to, amount]);
const unsafeRes = await this._rpcRequest('requestAirdrop', [to.toBase58(), amount]);
const res = RequestAirdropRpcResult(unsafeRes);
if (res.error) {
throw new Error(res.error.message);

View File

@ -1,6 +1,7 @@
// @flow
export {Account} from './account';
export {Connection} from './connection';
export {Transaction} from './transaction';
export {SystemProgram} from './system-program';
export {BudgetProgram} from './budget-program';
export {Connection} from './connection';
export {PublicKey} from './publickey';
export {SystemProgram} from './system-program';
export {Transaction} from './transaction';

70
web3.js/src/publickey.js Normal file
View File

@ -0,0 +1,70 @@
// @flow
import BN from 'bn.js';
import bs58 from 'bs58';
/**
* A public key
*/
export class PublicKey {
_bn: BN;
/**
* Create a new PublicKey object
*/
constructor(number: string | Buffer | Array<number>) {
let radix = 10;
if (typeof number === 'string' && number.startsWith('0x')) {
this._bn = new BN(number.substring(2), 16);
} else {
this._bn = new BN(number, radix);
}
if (this._bn.byteLength() > 32) {
throw new Error(`Invalid public key input`);
}
}
/**
* Checks if the provided object is a PublicKey
*/
static isPublicKey(o: Object): boolean {
return o instanceof PublicKey;
}
/**
* Checks if two publicKeys are equal
*/
equals(publicKey: PublicKey): boolean {
return this._bn.eq(publicKey._bn);
}
/**
* Return the base-58 representation of the public key
*/
toBase58(): string {
return bs58.encode(this.toBuffer());
}
/**
* Return the base-58 representation of the public key
*/
toBuffer(): Buffer {
const b = this._bn.toBuffer();
if (b.length === 32) {
return b;
}
const zeroPad = new Buffer(32);
b.copy(zeroPad, 32 - b.length);
return zeroPad;
}
/**
* Returns a string representation of the public key
*/
toString(): string {
return this.toBase58();
}
}

View File

@ -3,7 +3,7 @@
import assert from 'assert';
import {Transaction} from './transaction';
import type {PublicKey} from './account';
import {PublicKey} from './publickey';
/**
* Factory class for transactions to interact with the System program
@ -13,7 +13,7 @@ export class SystemProgram {
* Public key that identifies the System program
*/
static get programId(): PublicKey {
return '11111111111111111111111111111111';
return new PublicKey('0x000000000000000000000000000000000000000000000000000000000000000');
}
/**
@ -38,7 +38,7 @@ export class SystemProgram {
userdata.writeUInt32LE(space, pos); // space as u64
pos += 8;
const programIdBytes = Transaction.serializePublicKey(programId);
const programIdBytes = programId.toBuffer();
programIdBytes.copy(userdata, pos);
pos += 32;
@ -84,7 +84,7 @@ export class SystemProgram {
userdata.writeUInt32LE(1, pos); // Assign instruction
pos += 4;
const programIdBytes = Transaction.serializePublicKey(programId);
const programIdBytes = programId.toBuffer();
programIdBytes.copy(userdata, pos);
pos += programIdBytes.length;

View File

@ -4,7 +4,8 @@ import assert from 'assert';
import nacl from 'tweetnacl';
import bs58 from 'bs58';
import type {Account, PublicKey} from './account';
import type {Account} from './account';
import type {PublicKey} from './publickey';
/**
* @typedef {string} TransactionSignature
@ -92,14 +93,14 @@ export class Transaction {
transactionData.writeUInt32LE(this.keys.length, pos); // u64
pos += 8;
for (let key of this.keys) {
const keyBytes = Transaction.serializePublicKey(key);
const keyBytes = key.toBuffer();
keyBytes.copy(transactionData, pos);
pos += 32;
}
// serialize `this.programId`
if (this.programId) {
const keyBytes = Transaction.serializePublicKey(this.programId);
const keyBytes = this.programId.toBuffer();
keyBytes.copy(transactionData, pos);
}
pos += 32;
@ -158,14 +159,5 @@ export class Transaction {
transactionData.copy(wireTransaction, signature.length);
return wireTransaction;
}
/**
* Serializes a public key into the wire format
*/
static serializePublicKey(key: PublicKey): Buffer {
const data = Buffer.from(bs58.decode(key));
assert(data.length === 32);
return data;
}
}