feat: wrap public key in a class
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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
70
web3.js/src/publickey.js
Normal 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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user