feat: add borsh utilities and public key support (#17239)

* feat: add borsh utilities and public key support

* fix: make bn internal for flow

* fix: add Buffer import in borsh file
This commit is contained in:
Jon Cinque
2021-05-18 19:33:06 +02:00
committed by GitHub
parent 75335b4f58
commit 00e198d169
7 changed files with 140 additions and 13 deletions

View File

@@ -16,6 +16,7 @@ export * from './transaction';
export * from './validator-info';
export * from './vote-account';
export * from './sysvar';
export * from './util/borsh-schema';
export * from './util/send-and-confirm-transaction';
export * from './util/send-and-confirm-raw-transaction';
export * from './util/cluster';

View File

@@ -4,6 +4,7 @@ import nacl from 'tweetnacl';
import {sha256} from 'crypto-hash';
import {Buffer} from 'buffer';
import {Struct, SOLANA_SCHEMA} from './util/borsh-schema';
import {toBuffer} from './util/to-buffer';
/**
@@ -11,10 +12,27 @@ import {toBuffer} from './util/to-buffer';
*/
export const MAX_SEED_LENGTH = 32;
type PublicKeyInitData =
| number
| string
| Buffer
| Uint8Array
| Array<number>
| PublicKeyData;
type PublicKeyData = {
/** @internal */
_bn: BN;
};
function isPublicKeyData(value: PublicKeyInitData): value is PublicKeyData {
return (value as PublicKeyData)._bn !== undefined;
}
/**
* A public key
*/
export class PublicKey {
export class PublicKey extends Struct {
/** @internal */
_bn: BN;
@@ -22,20 +40,25 @@ export class PublicKey {
* Create a new PublicKey object
* @param value ed25519 public key as buffer or base-58 encoded string
*/
constructor(value: number | string | Buffer | Uint8Array | Array<number>) {
if (typeof value === 'string') {
// assume base 58 encoding by default
const decoded = bs58.decode(value);
if (decoded.length != 32) {
constructor(value: PublicKeyInitData) {
super({});
if (isPublicKeyData(value)) {
this._bn = value._bn;
} else {
if (typeof value === 'string') {
// assume base 58 encoding by default
const decoded = bs58.decode(value);
if (decoded.length != 32) {
throw new Error(`Invalid public key input`);
}
this._bn = new BN(decoded);
} else {
this._bn = new BN(value);
}
if (this._bn.byteLength() > 32) {
throw new Error(`Invalid public key input`);
}
this._bn = new BN(decoded);
} else {
this._bn = new BN(value);
}
if (this._bn.byteLength() > 32) {
throw new Error(`Invalid public key input`);
}
}
@@ -167,6 +190,11 @@ export class PublicKey {
}
}
SOLANA_SCHEMA.set(PublicKey, {
kind: 'struct',
fields: [['_bn', 'u256']],
});
// @ts-ignore
let naclLowLevel = nacl.lowlevel;

View File

@@ -0,0 +1,34 @@
import {Buffer} from 'buffer';
import {serialize, deserialize} from 'borsh';
// Class wrapping a plain object
export class Struct {
constructor(properties: any) {
Object.assign(this, properties);
}
encode(): Buffer {
return Buffer.from(serialize(SOLANA_SCHEMA, this));
}
static decode(data: Buffer): any {
return deserialize(SOLANA_SCHEMA, this, data);
}
}
// Class representing a Rust-compatible enum, since enums are only strings or
// numbers in pure JS
export class Enum extends Struct {
enum: string = '';
constructor(properties: any) {
super(properties);
if (Object.keys(properties).length !== 1) {
throw new Error('Enum can only take single value');
}
Object.keys(properties).map(key => {
this.enum = key;
});
}
}
export const SOLANA_SCHEMA: Map<Function, any> = new Map();