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:
parent
75335b4f58
commit
00e198d169
54
web3.js/package-lock.json
generated
54
web3.js/package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"bn.js": "^5.0.0",
|
"bn.js": "^5.0.0",
|
||||||
|
"borsh": "^0.4.0",
|
||||||
"bs58": "^4.0.1",
|
"bs58": "^4.0.1",
|
||||||
"buffer": "6.0.1",
|
"buffer": "6.0.1",
|
||||||
"buffer-layout": "^1.2.0",
|
"buffer-layout": "^1.2.0",
|
||||||
@ -4682,6 +4683,25 @@
|
|||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/borsh": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/borsh/-/borsh-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-aX6qtLya3K0AkT66CmYWCCDr77qsE9arV05OmdFpmat9qu8Pg9J5tBUPDztAW5fNh/d/MyVG/OYziP52Ndzx1g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/bn.js": "^4.11.5",
|
||||||
|
"bn.js": "^5.0.0",
|
||||||
|
"bs58": "^4.0.0",
|
||||||
|
"text-encoding-utf-8": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/borsh/node_modules/@types/bn.js": {
|
||||||
|
"version": "4.11.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
|
||||||
|
"integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bottleneck": {
|
"node_modules/bottleneck": {
|
||||||
"version": "2.19.5",
|
"version": "2.19.5",
|
||||||
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
||||||
@ -4799,6 +4819,7 @@
|
|||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz",
|
||||||
"integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==",
|
"integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-gyp-build": "^4.2.0"
|
"node-gyp-build": "^4.2.0"
|
||||||
@ -17828,6 +17849,7 @@
|
|||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz",
|
||||||
"integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==",
|
"integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"elliptic": "^6.5.2",
|
"elliptic": "^6.5.2",
|
||||||
"node-addon-api": "^2.0.0",
|
"node-addon-api": "^2.0.0",
|
||||||
@ -19672,6 +19694,11 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/text-encoding-utf-8": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg=="
|
||||||
|
},
|
||||||
"node_modules/text-extensions": {
|
"node_modules/text-extensions": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz",
|
||||||
@ -20157,6 +20184,7 @@
|
|||||||
"version": "5.0.4",
|
"version": "5.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz",
|
||||||
"integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==",
|
"integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==",
|
||||||
|
"hasInstallScript": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-gyp-build": "^4.2.0"
|
"node-gyp-build": "^4.2.0"
|
||||||
@ -24684,6 +24712,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"borsh": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/borsh/-/borsh-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-aX6qtLya3K0AkT66CmYWCCDr77qsE9arV05OmdFpmat9qu8Pg9J5tBUPDztAW5fNh/d/MyVG/OYziP52Ndzx1g==",
|
||||||
|
"requires": {
|
||||||
|
"@types/bn.js": "^4.11.5",
|
||||||
|
"bn.js": "^5.0.0",
|
||||||
|
"bs58": "^4.0.0",
|
||||||
|
"text-encoding-utf-8": "^1.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/bn.js": {
|
||||||
|
"version": "4.11.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
|
||||||
|
"integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"bottleneck": {
|
"bottleneck": {
|
||||||
"version": "2.19.5",
|
"version": "2.19.5",
|
||||||
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
||||||
@ -36400,6 +36449,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"text-encoding-utf-8": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg=="
|
||||||
|
},
|
||||||
"text-extensions": {
|
"text-extensions": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz",
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"bn.js": "^5.0.0",
|
"bn.js": "^5.0.0",
|
||||||
|
"borsh": "^0.4.0",
|
||||||
"bs58": "^4.0.1",
|
"bs58": "^4.0.1",
|
||||||
"buffer": "6.0.1",
|
"buffer": "6.0.1",
|
||||||
"buffer-layout": "^1.2.0",
|
"buffer-layout": "^1.2.0",
|
||||||
|
@ -52,6 +52,7 @@ function generateConfig(configType, format) {
|
|||||||
config.external = [
|
config.external = [
|
||||||
/@babel\/runtime/,
|
/@babel\/runtime/,
|
||||||
'bn.js',
|
'bn.js',
|
||||||
|
'borsh',
|
||||||
'bs58',
|
'bs58',
|
||||||
'buffer-layout',
|
'buffer-layout',
|
||||||
'crypto-hash',
|
'crypto-hash',
|
||||||
@ -81,6 +82,7 @@ function generateConfig(configType, format) {
|
|||||||
config.external = [
|
config.external = [
|
||||||
/@babel\/runtime/,
|
/@babel\/runtime/,
|
||||||
'bn.js',
|
'bn.js',
|
||||||
|
'borsh',
|
||||||
'bs58',
|
'bs58',
|
||||||
'buffer',
|
'buffer',
|
||||||
'buffer-layout',
|
'buffer-layout',
|
||||||
|
@ -16,6 +16,7 @@ export * from './transaction';
|
|||||||
export * from './validator-info';
|
export * from './validator-info';
|
||||||
export * from './vote-account';
|
export * from './vote-account';
|
||||||
export * from './sysvar';
|
export * from './sysvar';
|
||||||
|
export * from './util/borsh-schema';
|
||||||
export * from './util/send-and-confirm-transaction';
|
export * from './util/send-and-confirm-transaction';
|
||||||
export * from './util/send-and-confirm-raw-transaction';
|
export * from './util/send-and-confirm-raw-transaction';
|
||||||
export * from './util/cluster';
|
export * from './util/cluster';
|
||||||
|
@ -4,6 +4,7 @@ import nacl from 'tweetnacl';
|
|||||||
import {sha256} from 'crypto-hash';
|
import {sha256} from 'crypto-hash';
|
||||||
import {Buffer} from 'buffer';
|
import {Buffer} from 'buffer';
|
||||||
|
|
||||||
|
import {Struct, SOLANA_SCHEMA} from './util/borsh-schema';
|
||||||
import {toBuffer} from './util/to-buffer';
|
import {toBuffer} from './util/to-buffer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,10 +12,27 @@ import {toBuffer} from './util/to-buffer';
|
|||||||
*/
|
*/
|
||||||
export const MAX_SEED_LENGTH = 32;
|
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
|
* A public key
|
||||||
*/
|
*/
|
||||||
export class PublicKey {
|
export class PublicKey extends Struct {
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_bn: BN;
|
_bn: BN;
|
||||||
|
|
||||||
@ -22,7 +40,11 @@ export class PublicKey {
|
|||||||
* Create a new PublicKey object
|
* Create a new PublicKey object
|
||||||
* @param value ed25519 public key as buffer or base-58 encoded string
|
* @param value ed25519 public key as buffer or base-58 encoded string
|
||||||
*/
|
*/
|
||||||
constructor(value: number | string | Buffer | Uint8Array | Array<number>) {
|
constructor(value: PublicKeyInitData) {
|
||||||
|
super({});
|
||||||
|
if (isPublicKeyData(value)) {
|
||||||
|
this._bn = value._bn;
|
||||||
|
} else {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
// assume base 58 encoding by default
|
// assume base 58 encoding by default
|
||||||
const decoded = bs58.decode(value);
|
const decoded = bs58.decode(value);
|
||||||
@ -38,6 +60,7 @@ export class PublicKey {
|
|||||||
throw new Error(`Invalid public key input`);
|
throw new Error(`Invalid public key input`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default public key value. (All zeros)
|
* Default public key value. (All zeros)
|
||||||
@ -167,6 +190,11 @@ export class PublicKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SOLANA_SCHEMA.set(PublicKey, {
|
||||||
|
kind: 'struct',
|
||||||
|
fields: [['_bn', 'u256']],
|
||||||
|
});
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let naclLowLevel = nacl.lowlevel;
|
let naclLowLevel = nacl.lowlevel;
|
||||||
|
|
||||||
|
34
web3.js/src/util/borsh-schema.ts
Normal file
34
web3.js/src/util/borsh-schema.ts
Normal 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();
|
@ -342,4 +342,11 @@ describe('PublicKey', function () {
|
|||||||
);
|
);
|
||||||
expect(PublicKey.isOnCurve(offCurve.toBuffer())).to.be.false;
|
expect(PublicKey.isOnCurve(offCurve.toBuffer())).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('canBeSerializedWithBorsh', () => {
|
||||||
|
const publicKey = Keypair.generate().publicKey;
|
||||||
|
const encoded = publicKey.encode();
|
||||||
|
const decoded = PublicKey.decode(encoded);
|
||||||
|
expect(decoded.equals(publicKey)).to.be.true;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user