@stellar-expert/contract-wasm-interface-parser 5.0.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/package.json +3 -0
- package/lib/wasmparser.js +1 -1
- package/lib/wasmparser.js.map +1 -1
- package/package.json +2 -2
- package/src/index.js +5 -6
- package/src/xdr-spec-parser.js +41 -48
- package/src/xdr-reader.js +0 -168
package/lib/package.json
ADDED
package/lib/wasmparser.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@stellar/stellar-sdk")):"function"==typeof define&&define.amd?define(["@stellar/stellar-sdk"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).sorobanwasmparser=t(e["@stellar/stellar-sdk"])}(this,function(e){"use strict";
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@stellar/stellar-sdk")):"function"==typeof define&&define.amd?define(["@stellar/stellar-sdk"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).sorobanwasmparser=t(e["@stellar/stellar-sdk"])}(this,function(e){"use strict";class t{constructor(e){this.data=e}data;pointer=8;readCustomSections(){const e=[];for(;this.pointer<this.data.length;){const t=this.readUint8();let r=this.readVarUint32();if(0===t){const t=this.pointer,s=this.readString();r-=this.pointer-t,e.push({name:s,contents:this.data.subarray(this.pointer,this.pointer+r)})}this.pointer+=r}return e}readUint8(){return this.data.readUint8(this.pointer++)}readVarUint32(){let e=0,t=0;for(;;){let r=this.readUint8();if(e|=(127&r)<<t,t+=7,!(128&r))break}return e>>>0}readString(){const e=this.readVarUint32(),t=this.data.subarray(this.pointer,this.pointer+e);return this.pointer+=e,t.toString("utf-8")}}function r(e){const t={};for(const{value:r}of e){const e=r.key.toString(),s=r.val.toString();switch(e){case"rsver":t.rustVersion=s;break;case"rssdkver":t.sdkVersion=s;break;default:t[e]=s}}return t}function s(e){return(new a).parse(e)}class a{constructor(){this.res={}}res;addSpec(e,t,r){let s=this.res[e];void 0===s&&(s=this.res[e]={}),r.call(this,t,s)}parse(e){for(const t of e){const{value:e}=t;switch(t.type){case"scSpecEntryFunctionV0":this.addSpec("functions",e,this.parseFunction);break;case"scSpecEntryUdtStructV0":this.addSpec("structs",e,this.parseStruct);break;case"scSpecEntryUdtUnionV0":this.addSpec("unions",e,this.parseUnion);break;case"scSpecEntryUdtEnumV0":this.addSpec("enums",e,this.parseEnum);break;case"scSpecEntryUdtErrorEnumV0":this.addSpec("errors",e,this.parseError);break;case"scSpecEntryEventV0":this.addSpec("events",e,this.parseEvent);break;default:console.log("Unknown spec type: "+t.type)}}return this.res}parseFunction(e,t){t[e.name.toString()]=this.withDocs({inputs:e.inputs.map(e=>this.parseFuncArgument(e)),outputs:e.outputs.map(e=>this.parseParameterType(e))},e)}parseStruct(e,t){const r={};for(const t of e.fields)this.parseParameter(t,r);t[this.parseStructName(e)]=this.withDocs({fields:r},e)}parseUnion(e,t){const r={};for(const{value:t}of e.cases)r[t.name.toString()]=t.type?t.type.map(e=>this.parseParameterType(e)):[];t[this.parseStructName(e)]=this.withDocs({cases:r},e)}parseEnum(e,t){const r={};for(const t of e.cases){const e=t.value;e.name?r[e.name.toString()]=e.value:r[t.name.toString()]=this.withDocs({value:e},t)}t[this.parseStructName(e)]=this.withDocs({cases:r},e)}parseError(e,t){for(const r of e.cases)t[r.name.toString()]=this.withDocs({value:r.value},r)}parseEvent(e,t){let r;switch(e.dataFormat.value){case 1:r="Vec";break;case 2:r="Map";break;default:r=e.dataFormat.name}const s={prefixTopics:e.prefixTopics.map(e=>e.toString()),params:e.params.map(e=>{const t={name:e.name.toString(),type:this.parseParameterType(e.type),location:0===e.location.value?"data":"topics"};return this.withDocs(t,e)}),dataFormat:r};t[this.parseStructName(e)]=this.withDocs(s,e)}parseParameterType(e){const t=e.type;switch(t){case"scSpecTypeOption":return`Option<${this.parseParameterType(e.value.valueType)}>`;case"scSpecTypeBytesN":return`BytesN<${e.value.n}>`;case"scSpecTypeVec":return`Vec<${this.parseParameterType(e.value.elementType)}>`;case"scSpecTypeMap":return`Map<${this.parseParameterType(e.value.keyType)}, ${this.parseParameterType(e.value.valueType)}>`;case"scSpecTypeResult":return`Result<${this.parseParameterType(e.value.okType)}, ${this.parseParameterType(e.value.errorType)}>`;case"scSpecTypeTuple":return`(${e.value.valueTypes.map(e=>this.parseParameterType(e)).join(", ")})`;case"scSpecTypeUdt":return e.value.name.toString();default:let r=t.replace("scSpecType","");return(/^[IU](8|16|32|64|128)$/.test(r)||"Bool"===r)&&(r=r.toLowerCase()),r}}parseStructName(e){let t=e.name.toString();return e.lib.length&&(t+=":"+e.lib.toString()),t}parseParameter(e,t){t[e.name.toString()]=this.withDocs({type:this.parseParameterType(e.type)},e)}parseFuncArgument(e){return this.withDocs({name:e.name.toString(),type:this.parseParameterType(e.type)},e)}withDocs(e,t){return t.doc?.length&&(e.doc=t.doc.toString()),e}}return{parseContractMetadata:function(a){const n=new t(a).readCustomSections(),i={};for(const t of n)switch(t.name){case"contractenvmetav0":const a=e.xdr.ScEnvMetaEntry.fromXdr(t.contents).value;i.interfaceVersion=`${a.protocol}.${a.preRelease}`;break;case"contractmetav0":Object.assign(i,r(e.xdr.decodeStream(e.xdr.ScMetaEntry,t.contents)));break;case"contractspecv0":Object.assign(i,s(e.xdr.decodeStream(e.xdr.ScSpecEntry,t.contents)));break;default:i[t.name]=t.contents.toString()}return i}}});
|
|
2
2
|
//# sourceMappingURL=wasmparser.js.map
|
package/lib/wasmparser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasmparser.js","sources":["../src/xdr-reader.js","../src/wasm-section-reader.js","../src/xdr-spec-parser.js","../src/bundle.js","../src/index.js"],"sourcesContent":["/**\r\n *\r\n * @param {Buffer} buffer\r\n * @param {{read: function}} xdrContract\r\n * @return {{}[]}\r\n */\r\nexport function parseSectionEntriesXdr(buffer, xdrContract) {\r\n const reader = new XdrReader(buffer)\r\n const entries = []\r\n while (!reader.eof) {\r\n entries.push(xdrContract.read(reader))\r\n }\r\n return entries\r\n}\r\n\r\nclass XdrReader {\r\n /**\r\n * @constructor\r\n * @param {Buffer} source - Buffer containing serialized data\r\n */\r\n constructor(source) {\r\n if (!Buffer.isBuffer(source)) {\r\n if (source instanceof Array) {\r\n source = Buffer.from(source)\r\n } else\r\n throw new Error('Source not specified')\r\n }\r\n\r\n this._buffer = source\r\n this._length = source.length\r\n this._index = 0\r\n }\r\n\r\n /**\r\n * @type {Buffer}\r\n * @private\r\n * @readonly\r\n */\r\n _buffer\r\n /**\r\n * @type {Number}\r\n * @private\r\n * @readonly\r\n */\r\n _length\r\n /**\r\n * @type {Number}\r\n * @private\r\n * @readonly\r\n */\r\n _index\r\n\r\n /**\r\n * Check if the reader reached the end of the input buffer\r\n * @return {Boolean}\r\n */\r\n get eof() {\r\n return this._index === this._length\r\n }\r\n\r\n /**\r\n * Advance reader position, check padding and overflow\r\n * @param {Number} size - Bytes to read\r\n * @return {Number} Position to read from\r\n * @private\r\n */\r\n advance(size) {\r\n const from = this._index\r\n // advance cursor position\r\n this._index += size\r\n // check buffer boundaries\r\n if (this._length < this._index)\r\n throw new Error(\r\n 'attempt to read outside the boundary of the buffer'\r\n )\r\n // check that padding is correct for Opaque and String\r\n const padding = 4 - (size % 4 || 4)\r\n if (padding > 0) {\r\n for (let i = 0; i < padding; i++)\r\n if (this._buffer[this._index + i] !== 0)\r\n // all bytes in the padding should be zeros\r\n throw new Error('Invalid padding')\r\n this._index += padding\r\n }\r\n return from\r\n }\r\n\r\n /**\r\n * Reset reader position\r\n */\r\n rewind() {\r\n this._index = 0\r\n }\r\n\r\n /**\r\n * Read byte array from the buffer\r\n * @param {Number} size - Bytes to read\r\n * @return {Buffer} - Sliced portion of the underlying buffer\r\n */\r\n read(size) {\r\n const from = this.advance(size)\r\n return this._buffer.subarray(from, from + size)\r\n }\r\n\r\n /**\r\n * Read i32 from buffer\r\n * @return {Number}\r\n */\r\n readInt32BE() {\r\n return this._buffer.readInt32BE(this.advance(4))\r\n }\r\n\r\n /**\r\n * Read u32 from buffer\r\n * @return {Number}\r\n */\r\n readUInt32BE() {\r\n return this._buffer.readUInt32BE(this.advance(4))\r\n }\r\n\r\n /**\r\n * Read i64 from buffer\r\n * @return {BigInt}\r\n */\r\n readBigInt64BE() {\r\n return this._buffer.readBigInt64BE(this.advance(8))\r\n }\r\n\r\n /**\r\n * Read u64 from buffer\r\n * @return {BigInt}\r\n */\r\n readBigUInt64BE() {\r\n return this._buffer.readBigUInt64BE(this.advance(8))\r\n }\r\n\r\n /**\r\n * Read float from buffer\r\n * @return {Number}\r\n */\r\n readFloatBE() {\r\n return this._buffer.readFloatBE(this.advance(4))\r\n }\r\n\r\n /**\r\n * Read double from buffer\r\n * @return {Number}\r\n */\r\n readDoubleBE() {\r\n return this._buffer.readDoubleBE(this.advance(8))\r\n }\r\n\r\n /**\r\n * Ensure that input buffer has been consumed in full, otherwise it's a type mismatch\r\n */\r\n ensureInputConsumed() {\r\n if (this._index !== this._length)\r\n throw new Error(`Invalid XDR contract typecast - source buffer not entirely consumed`)\r\n }\r\n\r\n /**\r\n * Get number of bytes remaining in buffer\r\n * @returns {Number}\r\n */\r\n remainingBytes() {\r\n return this._length - this._index\r\n }\r\n}\r\n","/**\r\n * Minimalistic WASM metadata reader\r\n */\r\nexport class WasmSectionReader {\r\n constructor(data) {\r\n this.data = data\r\n }\r\n\r\n /**\r\n * @type {Buffer}\r\n * @private\r\n */\r\n data\r\n /**\r\n * Current reader position\r\n * @type {number}\r\n * @private\r\n */\r\n pointer = 8\r\n\r\n /**\r\n * Read custom metadata sections from raw WASM\r\n * @return {{name: string, contents: Buffer}[]}\r\n */\r\n readCustomSections() {\r\n const sections = []\r\n while (this.pointer < this.data.length) {\r\n const sectionType = this.readUint8()\r\n let length = this.readVarUint32()\r\n if (sectionType === 0) { //accumulate only custom sections\r\n const sectionStart = this.pointer\r\n const name = this.readString()\r\n length -= this.pointer - sectionStart\r\n sections.push({\r\n name,\r\n contents: this.data.subarray(this.pointer, this.pointer + length)\r\n })\r\n }\r\n this.pointer += length\r\n }\r\n return sections\r\n }\r\n\r\n /**\r\n * @return {number}\r\n * @private\r\n */\r\n readUint8() {\r\n return this.data.readUint8(this.pointer++)\r\n }\r\n\r\n /**\r\n * @return {number}\r\n * @private\r\n */\r\n readVarUint32() {\r\n let result = 0\r\n let shift = 0\r\n while (true) {\r\n let byte = this.readUint8()\r\n result |= (byte & 0x7f) << shift\r\n shift += 7\r\n if ((byte & 0x80) === 0)\r\n break\r\n }\r\n return result >>> 0\r\n }\r\n\r\n /**\r\n * @return {string}\r\n * @private\r\n */\r\n readString() {\r\n const length = this.readVarUint32()\r\n const contents = this.data.subarray(this.pointer, this.pointer + length)\r\n this.pointer += length\r\n return contents.toString('utf-8')\r\n }\r\n}","export function parseContractMeta(meta) {\r\n const res = {}\r\n for (const {_value} of meta) {\r\n const key = _value.key().toString()\r\n const val = _value.val().toString()\r\n switch (key) {\r\n case 'rsver':\r\n res.rustVersion = val\r\n break\r\n case 'rssdkver':\r\n res.sdkVersion = val\r\n break\r\n default:\r\n res[key] = val\r\n break\r\n }\r\n }\r\n return res\r\n}\r\n\r\nexport function parseSpec(entries) {\r\n return new SpecParser().parse(entries)\r\n}\r\n\r\n\r\nclass SpecParser {\r\n constructor() {\r\n this.res = {}\r\n }\r\n\r\n /**\r\n * @type {{}}\r\n */\r\n res\r\n\r\n addSpec(key, attr, parser) {\r\n //this.parseFunction(attr), attr.doc\r\n let spec = this.res[key]\r\n if (spec === undefined) {\r\n spec = this.res[key] = {}\r\n }\r\n parser.call(this, attr, spec)\r\n }\r\n\r\n parse(entries) {\r\n for (const spec of entries) {\r\n const value = spec.value()\r\n const {_attributes: attr} = value\r\n switch (spec._arm) {\r\n case 'functionV0':\r\n this.addSpec('functions', attr, this.parseFunction)\r\n break\r\n case 'udtStructV0':\r\n this.addSpec('structs', attr, this.parseStruct)\r\n break\r\n case 'udtUnionV0':\r\n this.addSpec('unions', attr, this.parseUnion)\r\n break\r\n case 'udtEnumV0':\r\n this.addSpec('enums', attr, this.parseEnum)\r\n break\r\n case 'udtErrorEnumV0':\r\n this.addSpec('errors', attr, this.parseError)\r\n break\r\n case 'eventV0':\r\n this.addSpec('events', attr, this.parseEvent)\r\n break\r\n default:\r\n console.log('Unknown spec type: ' + spec._arm)\r\n break\r\n }\r\n }\r\n return this.res\r\n }\r\n\r\n parseFunction(attr, into) {\r\n into[attr.name.toString()] = this.withDocs({\r\n inputs: attr.inputs.map(a => this.parseFuncArgument(a)),\r\n outputs: attr.outputs.map(o => this.parseParameterType(o))\r\n }, attr)\r\n }\r\n\r\n parseStruct(attr, into) {\r\n const fields = {}\r\n for (const f of attr.fields) {\r\n this.parseParameter(f, fields)\r\n }\r\n into[this.parseStructName(attr)] = this.withDocs({fields}, attr)\r\n }\r\n\r\n parseUnion(attr, into) {\r\n const cases = {}\r\n for (const c of attr.cases) {\r\n const value = c.value()\r\n cases[value.name().toString()] = value.type ?\r\n value.type().map(t => this.parseParameterType(t)) :\r\n []\r\n }\r\n into[this.parseStructName(attr)] = this.withDocs({cases}, attr)\r\n }\r\n\r\n parseEnum(attr, into) {\r\n const cases = {}\r\n for (const c of attr.cases) {\r\n const value = c.value()\r\n if (value.name) {\r\n cases[value.name().toString()] = value.value()\r\n } else {\r\n const attr = c._attributes\r\n cases[attr.name.toString()] = this.withDocs({value}, attr)\r\n }\r\n }\r\n into[this.parseStructName(attr)] = this.withDocs({cases}, attr)\r\n }\r\n\r\n parseError(attr, into) {\r\n for (const c of attr.cases) {\r\n const attr = c._attributes\r\n into[attr.name.toString()] = this.withDocs({value: attr.value}, attr)\r\n }\r\n }\r\n\r\n parseEvent(attr, into) {\r\n let dataFormat\r\n switch (attr.dataFormat.value) {\r\n case 1:\r\n dataFormat = 'Vec'\r\n break\r\n case 2:\r\n dataFormat = 'Map'\r\n break\r\n default:\r\n dataFormat = attr.dataFormat.name\r\n break\r\n }\r\n const evt = {\r\n prefixTopics: attr.prefixTopics.map(t => t.toString()),\r\n params: attr.params.map(p => {\r\n const pa = p._attributes\r\n const param = {\r\n name: pa.name.toString(),\r\n type: this.parseParameterType(pa.type),\r\n location: pa.location.value === 0 ? 'data' : 'topics'\r\n }\r\n return this.withDocs(param, pa)\r\n }),\r\n dataFormat\r\n }\r\n into[this.parseStructName(attr)] = this.withDocs(evt, attr)\r\n }\r\n\r\n parseParameterType(type) {\r\n const typeName = type.switch().name\r\n switch (typeName) {\r\n case 'scSpecTypeOption':\r\n return `Option<${this.parseParameterType(type.value().valueType())}>`\r\n case 'scSpecTypeBytesN':\r\n return `BytesN<${type.value().n()}>`\r\n case 'scSpecTypeVec':\r\n return `Vec<${this.parseParameterType(type.value().elementType())}>`\r\n case 'scSpecTypeMap':\r\n return `Map<${this.parseParameterType(type.value().keyType())}, ${this.parseParameterType(type.value().valueType())}>`\r\n case 'scSpecTypeResult':\r\n return `Result<${this.parseParameterType(type.value().okType())}, ${this.parseParameterType(type.value().errorType())}>`\r\n case 'scSpecTypeTuple':\r\n return `(${type.value().valueTypes().map(v => this.parseParameterType(v)).join(', ')})`\r\n case 'scSpecTypeUdt':\r\n return type.value().name().toString()\r\n default:\r\n let res = typeName.replace('scSpecType', '')\r\n if (/^[IU](8|16|32|64|128)$/.test(res) || res === 'Bool') { //remap standard int types\r\n res = res.toLowerCase()\r\n }\r\n return res\r\n }\r\n }\r\n\r\n parseStructName(value) {\r\n let structName = value.name.toString()\r\n if (value.lib.length) {\r\n structName += ':' + value.lib.toString()\r\n }\r\n return structName\r\n }\r\n\r\n parseParameter(param, into) {\r\n const attr = param._attributes\r\n into[attr.name.toString()] = this.withDocs({type: this.parseParameterType(attr.type)}, attr)\r\n }\r\n\r\n parseFuncArgument(arg) {\r\n const attr = arg._attributes\r\n return this.withDocs({\r\n name: attr.name.toString(),\r\n type: this.parseParameterType(attr.type)\r\n }, attr)\r\n }\r\n\r\n withDocs(descriptor, attr) {\r\n if (attr.doc?.length) {\r\n descriptor.doc = attr.doc.toString()\r\n }\r\n return descriptor\r\n }\r\n}\r\n\r\n","import {parseContractMetadata} from './index.js'\r\n\r\nconst index = {parseContractMetadata}\r\n\r\nexport default index","import {xdr} from '@stellar/stellar-sdk'\r\nimport {parseSectionEntriesXdr} from './xdr-reader'\r\nimport {WasmSectionReader} from './wasm-section-reader'\r\nimport {parseContractMeta, parseSpec} from './xdr-spec-parser'\r\n\r\n/**\r\n * Parse contract metadata from WASM sections\r\n * @param {Buffer} rawWasm\r\n * @return {ParsedWasmMeta}\r\n */\r\nexport function parseContractMetadata(rawWasm) {\r\n const wasmSectionReader = new WasmSectionReader(rawWasm)\r\n const sections = wasmSectionReader.readCustomSections()\r\n const res = {}\r\n for (const section of sections) {\r\n switch (section.name) {\r\n case 'contractenvmetav0':\r\n const v = xdr.ScEnvMetaEntry.fromXDR(section.contents).value()._attributes\r\n res.interfaceVersion = `${v.protocol}.${v.preRelease}`\r\n break\r\n case 'contractmetav0':\r\n Object.assign(res, parseContractMeta(parseSectionEntriesXdr(section.contents, xdr.ScMetaEntry)))\r\n break\r\n case 'contractspecv0':\r\n Object.assign(res, parseSpec(parseSectionEntriesXdr(section.contents, xdr.ScSpecEntry)))\r\n break\r\n default:\r\n res[section.name] = section.contents.toString()\r\n break\r\n }\r\n }\r\n return res\r\n}\r\n\r\n/**\r\n * @typedef {{}} ParsedWasmMeta\r\n * @property {{}} functions\r\n * @property {{}} [errors]\r\n * @property {{}} [enums]\r\n * @property {{}} [structs]\r\n * @property {{}} [unions]\r\n * @property {string} rustVersion\r\n * @property {string} sdkVersion\r\n * @property {string} interfaceVersion\r\n */"],"names":["parseSectionEntriesXdr","buffer","xdrContract","reader","XdrReader","entries","eof","push","read","constructor","source","Buffer","isBuffer","Array","Error","from","this","_buffer","_length","length","_index","advance","size","padding","i","rewind","subarray","readInt32BE","readUInt32BE","readBigInt64BE","readBigUInt64BE","readFloatBE","readDoubleBE","ensureInputConsumed","remainingBytes","WasmSectionReader","data","pointer","readCustomSections","sections","sectionType","readUint8","readVarUint32","sectionStart","name","readString","contents","result","shift","byte","toString","parseContractMeta","meta","res","_value","key","val","rustVersion","sdkVersion","parseSpec","SpecParser","parse","addSpec","attr","parser","spec","undefined","call","value","_attributes","_arm","parseFunction","parseStruct","parseUnion","parseEnum","parseError","parseEvent","console","log","into","withDocs","inputs","map","a","parseFuncArgument","outputs","o","parseParameterType","fields","f","parseParameter","parseStructName","cases","c","type","t","dataFormat","evt","prefixTopics","params","p","pa","param","location","typeName","switch","valueType","n","elementType","keyType","okType","errorType","valueTypes","v","join","replace","test","toLowerCase","structName","lib","arg","descriptor","doc","parseContractMetadata","rawWasm","section","xdr","ScEnvMetaEntry","fromXDR","interfaceVersion","protocol","preRelease","Object","assign","ScMetaEntry","ScSpecEntry"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"wasmparser.js","sources":["../src/wasm-section-reader.js","../src/xdr-spec-parser.js","../src/bundle.js","../src/index.js"],"sourcesContent":["/**\r\n * Minimalistic WASM metadata reader\r\n */\r\nexport class WasmSectionReader {\r\n constructor(data) {\r\n this.data = data\r\n }\r\n\r\n /**\r\n * @type {Buffer}\r\n * @private\r\n */\r\n data\r\n /**\r\n * Current reader position\r\n * @type {number}\r\n * @private\r\n */\r\n pointer = 8\r\n\r\n /**\r\n * Read custom metadata sections from raw WASM\r\n * @return {{name: string, contents: Buffer}[]}\r\n */\r\n readCustomSections() {\r\n const sections = []\r\n while (this.pointer < this.data.length) {\r\n const sectionType = this.readUint8()\r\n let length = this.readVarUint32()\r\n if (sectionType === 0) { //accumulate only custom sections\r\n const sectionStart = this.pointer\r\n const name = this.readString()\r\n length -= this.pointer - sectionStart\r\n sections.push({\r\n name,\r\n contents: this.data.subarray(this.pointer, this.pointer + length)\r\n })\r\n }\r\n this.pointer += length\r\n }\r\n return sections\r\n }\r\n\r\n /**\r\n * @return {number}\r\n * @private\r\n */\r\n readUint8() {\r\n return this.data.readUint8(this.pointer++)\r\n }\r\n\r\n /**\r\n * @return {number}\r\n * @private\r\n */\r\n readVarUint32() {\r\n let result = 0\r\n let shift = 0\r\n while (true) {\r\n let byte = this.readUint8()\r\n result |= (byte & 0x7f) << shift\r\n shift += 7\r\n if ((byte & 0x80) === 0)\r\n break\r\n }\r\n return result >>> 0\r\n }\r\n\r\n /**\r\n * @return {string}\r\n * @private\r\n */\r\n readString() {\r\n const length = this.readVarUint32()\r\n const contents = this.data.subarray(this.pointer, this.pointer + length)\r\n this.pointer += length\r\n return contents.toString('utf-8')\r\n }\r\n}","export function parseContractMeta(meta) {\r\n const res = {}\r\n for (const {value} of meta) {\r\n const key = value.key.toString()\r\n const val = value.val.toString()\r\n switch (key) {\r\n case 'rsver':\r\n res.rustVersion = val\r\n break\r\n case 'rssdkver':\r\n res.sdkVersion = val\r\n break\r\n default:\r\n res[key] = val\r\n break\r\n }\r\n }\r\n return res\r\n}\r\n\r\nexport function parseSpec(entries) {\r\n return new SpecParser().parse(entries)\r\n}\r\n\r\n\r\nclass SpecParser {\r\n constructor() {\r\n this.res = {}\r\n }\r\n\r\n /**\r\n * @type {{}}\r\n */\r\n res\r\n\r\n addSpec(key, attr, parser) {\r\n //this.parseFunction(attr), attr.doc\r\n let spec = this.res[key]\r\n if (spec === undefined) {\r\n spec = this.res[key] = {}\r\n }\r\n parser.call(this, attr, spec)\r\n }\r\n\r\n parse(entries) {\r\n for (const spec of entries) {\r\n const {value} = spec\r\n switch (spec.type) {\r\n case 'scSpecEntryFunctionV0':\r\n this.addSpec('functions', value, this.parseFunction)\r\n break\r\n case 'scSpecEntryUdtStructV0':\r\n this.addSpec('structs', value, this.parseStruct)\r\n break\r\n case 'scSpecEntryUdtUnionV0':\r\n this.addSpec('unions', value, this.parseUnion)\r\n break\r\n case 'scSpecEntryUdtEnumV0':\r\n this.addSpec('enums', value, this.parseEnum)\r\n break\r\n case 'scSpecEntryUdtErrorEnumV0':\r\n this.addSpec('errors', value, this.parseError)\r\n break\r\n case 'scSpecEntryEventV0':\r\n this.addSpec('events', value, this.parseEvent)\r\n break\r\n default:\r\n console.log('Unknown spec type: ' + spec.type)\r\n break\r\n }\r\n }\r\n return this.res\r\n }\r\n\r\n parseFunction(attr, into) {\r\n into[attr.name.toString()] = this.withDocs({\r\n inputs: attr.inputs.map(a => this.parseFuncArgument(a)),\r\n outputs: attr.outputs.map(o => this.parseParameterType(o))\r\n }, attr)\r\n }\r\n\r\n parseStruct(attr, into) {\r\n const fields = {}\r\n for (const f of attr.fields) {\r\n this.parseParameter(f, fields)\r\n }\r\n into[this.parseStructName(attr)] = this.withDocs({fields}, attr)\r\n }\r\n\r\n parseUnion(attr, into) {\r\n const cases = {}\r\n for (const {value} of attr.cases) {\r\n cases[value.name.toString()] = value.type ?\r\n value.type.map(t => this.parseParameterType(t)) :\r\n []\r\n }\r\n into[this.parseStructName(attr)] = this.withDocs({cases}, attr)\r\n }\r\n\r\n parseEnum(attr, into) {\r\n const cases = {}\r\n for (const c of attr.cases) {\r\n const value = c.value\r\n if (value.name) {\r\n cases[value.name.toString()] = value.value\r\n } else {\r\n cases[c.name.toString()] = this.withDocs({value}, c)\r\n }\r\n }\r\n into[this.parseStructName(attr)] = this.withDocs({cases}, attr)\r\n }\r\n\r\n parseError(attr, into) {\r\n for (const c of attr.cases) {\r\n into[c.name.toString()] = this.withDocs({value: c.value}, c)\r\n }\r\n }\r\n\r\n parseEvent(attr, into) {\r\n let dataFormat\r\n switch (attr.dataFormat.value) {\r\n case 1:\r\n dataFormat = 'Vec'\r\n break\r\n case 2:\r\n dataFormat = 'Map'\r\n break\r\n default:\r\n dataFormat = attr.dataFormat.name\r\n break\r\n }\r\n const evt = {\r\n prefixTopics: attr.prefixTopics.map(t => t.toString()),\r\n params: attr.params.map(p => {\r\n const param = {\r\n name: p.name.toString(),\r\n type: this.parseParameterType(p.type),\r\n location: p.location.value === 0 ? 'data' : 'topics'\r\n }\r\n return this.withDocs(param, p)\r\n }),\r\n dataFormat\r\n }\r\n into[this.parseStructName(attr)] = this.withDocs(evt, attr)\r\n }\r\n\r\n parseParameterType(type) {\r\n const typeName = type.type\r\n switch (typeName) {\r\n case 'scSpecTypeOption':\r\n return `Option<${this.parseParameterType(type.value.valueType)}>`\r\n case 'scSpecTypeBytesN':\r\n return `BytesN<${type.value.n}>`\r\n case 'scSpecTypeVec':\r\n return `Vec<${this.parseParameterType(type.value.elementType)}>`\r\n case 'scSpecTypeMap':\r\n return `Map<${this.parseParameterType(type.value.keyType)}, ${this.parseParameterType(type.value.valueType)}>`\r\n case 'scSpecTypeResult':\r\n return `Result<${this.parseParameterType(type.value.okType)}, ${this.parseParameterType(type.value.errorType)}>`\r\n case 'scSpecTypeTuple':\r\n return `(${type.value.valueTypes.map(v => this.parseParameterType(v)).join(', ')})`\r\n case 'scSpecTypeUdt':\r\n return type.value.name.toString()\r\n default:\r\n let res = typeName.replace('scSpecType', '')\r\n if (/^[IU](8|16|32|64|128)$/.test(res) || res === 'Bool') { //remap standard int types\r\n res = res.toLowerCase()\r\n }\r\n return res\r\n }\r\n }\r\n\r\n parseStructName(value) {\r\n let structName = value.name.toString()\r\n if (value.lib.length) {\r\n structName += ':' + value.lib.toString()\r\n }\r\n return structName\r\n }\r\n\r\n parseParameter(param, into) {\r\n into[param.name.toString()] = this.withDocs({type: this.parseParameterType(param.type)}, param)\r\n }\r\n\r\n parseFuncArgument(arg) {\r\n return this.withDocs({\r\n name: arg.name.toString(),\r\n type: this.parseParameterType(arg.type)\r\n }, arg)\r\n }\r\n\r\n withDocs(descriptor, attr) {\r\n if (attr.doc?.length) {\r\n descriptor.doc = attr.doc.toString()\r\n }\r\n return descriptor\r\n }\r\n}\r\n\r\n","import {parseContractMetadata} from './index.js'\r\n\r\nconst index = {parseContractMetadata}\r\n\r\nexport default index","import {xdr} from '@stellar/stellar-sdk'\r\nimport {WasmSectionReader} from './wasm-section-reader.js'\r\nimport {parseContractMeta, parseSpec} from './xdr-spec-parser.js'\r\n\r\n/**\r\n * Parse contract metadata from WASM sections\r\n * @param {Buffer} rawWasm\r\n * @return {ParsedWasmMeta}\r\n */\r\nexport function parseContractMetadata(rawWasm) {\r\n const wasmSectionReader = new WasmSectionReader(rawWasm)\r\n const sections = wasmSectionReader.readCustomSections()\r\n const res = {}\r\n for (const section of sections) {\r\n switch (section.name) {\r\n case 'contractenvmetav0':\r\n const v = xdr.ScEnvMetaEntry.fromXdr(section.contents).value\r\n res.interfaceVersion = `${v.protocol}.${v.preRelease}`\r\n break\r\n case 'contractmetav0':\r\n Object.assign(res, parseContractMeta(xdr.decodeStream(xdr.ScMetaEntry, section.contents)))\r\n break\r\n case 'contractspecv0':\r\n Object.assign(res, parseSpec(xdr.decodeStream(xdr.ScSpecEntry, section.contents)))\r\n break\r\n default:\r\n res[section.name] = section.contents.toString()\r\n break\r\n }\r\n }\r\n return res\r\n}\r\n\r\n/**\r\n * @typedef {{}} ParsedWasmMeta\r\n * @property {{}} functions\r\n * @property {{}} [errors]\r\n * @property {{}} [enums]\r\n * @property {{}} [structs]\r\n * @property {{}} [unions]\r\n * @property {string} rustVersion\r\n * @property {string} sdkVersion\r\n * @property {string} interfaceVersion\r\n */"],"names":["WasmSectionReader","constructor","data","this","pointer","readCustomSections","sections","length","sectionType","readUint8","readVarUint32","sectionStart","name","readString","push","contents","subarray","result","shift","byte","toString","parseContractMeta","meta","res","value","key","val","rustVersion","sdkVersion","parseSpec","entries","SpecParser","parse","addSpec","attr","parser","spec","undefined","call","type","parseFunction","parseStruct","parseUnion","parseEnum","parseError","parseEvent","console","log","into","withDocs","inputs","map","a","parseFuncArgument","outputs","o","parseParameterType","fields","f","parseParameter","parseStructName","cases","t","c","dataFormat","evt","prefixTopics","params","p","param","location","typeName","valueType","n","elementType","keyType","okType","errorType","valueTypes","v","join","replace","test","toLowerCase","structName","lib","arg","descriptor","doc","parseContractMetadata","rawWasm","section","xdr","ScEnvMetaEntry","fromXdr","interfaceVersion","protocol","preRelease","Object","assign","decodeStream","ScMetaEntry","ScSpecEntry"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stellar-expert/contract-wasm-interface-parser",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Contract interface metadata parser for binary WASM",
|
|
5
5
|
"author": "orbitlens <orbit@stellar.expert>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"test": "jest"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@stellar/stellar-sdk": ">=
|
|
26
|
+
"@stellar/stellar-sdk": ">=17"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@rollup/plugin-terser": "1.0.0",
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {xdr} from '@stellar/stellar-sdk'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {parseContractMeta, parseSpec} from './xdr-spec-parser'
|
|
2
|
+
import {WasmSectionReader} from './wasm-section-reader.js'
|
|
3
|
+
import {parseContractMeta, parseSpec} from './xdr-spec-parser.js'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Parse contract metadata from WASM sections
|
|
@@ -15,14 +14,14 @@ export function parseContractMetadata(rawWasm) {
|
|
|
15
14
|
for (const section of sections) {
|
|
16
15
|
switch (section.name) {
|
|
17
16
|
case 'contractenvmetav0':
|
|
18
|
-
const v = xdr.ScEnvMetaEntry.
|
|
17
|
+
const v = xdr.ScEnvMetaEntry.fromXdr(section.contents).value
|
|
19
18
|
res.interfaceVersion = `${v.protocol}.${v.preRelease}`
|
|
20
19
|
break
|
|
21
20
|
case 'contractmetav0':
|
|
22
|
-
Object.assign(res, parseContractMeta(
|
|
21
|
+
Object.assign(res, parseContractMeta(xdr.decodeStream(xdr.ScMetaEntry, section.contents)))
|
|
23
22
|
break
|
|
24
23
|
case 'contractspecv0':
|
|
25
|
-
Object.assign(res, parseSpec(
|
|
24
|
+
Object.assign(res, parseSpec(xdr.decodeStream(xdr.ScSpecEntry, section.contents)))
|
|
26
25
|
break
|
|
27
26
|
default:
|
|
28
27
|
res[section.name] = section.contents.toString()
|
package/src/xdr-spec-parser.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export function parseContractMeta(meta) {
|
|
2
2
|
const res = {}
|
|
3
|
-
for (const {
|
|
4
|
-
const key =
|
|
5
|
-
const val =
|
|
3
|
+
for (const {value} of meta) {
|
|
4
|
+
const key = value.key.toString()
|
|
5
|
+
const val = value.val.toString()
|
|
6
6
|
switch (key) {
|
|
7
7
|
case 'rsver':
|
|
8
8
|
res.rustVersion = val
|
|
@@ -44,29 +44,28 @@ class SpecParser {
|
|
|
44
44
|
|
|
45
45
|
parse(entries) {
|
|
46
46
|
for (const spec of entries) {
|
|
47
|
-
const value = spec
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.addSpec('functions', attr, this.parseFunction)
|
|
47
|
+
const {value} = spec
|
|
48
|
+
switch (spec.type) {
|
|
49
|
+
case 'scSpecEntryFunctionV0':
|
|
50
|
+
this.addSpec('functions', value, this.parseFunction)
|
|
52
51
|
break
|
|
53
|
-
case '
|
|
54
|
-
this.addSpec('structs',
|
|
52
|
+
case 'scSpecEntryUdtStructV0':
|
|
53
|
+
this.addSpec('structs', value, this.parseStruct)
|
|
55
54
|
break
|
|
56
|
-
case '
|
|
57
|
-
this.addSpec('unions',
|
|
55
|
+
case 'scSpecEntryUdtUnionV0':
|
|
56
|
+
this.addSpec('unions', value, this.parseUnion)
|
|
58
57
|
break
|
|
59
|
-
case '
|
|
60
|
-
this.addSpec('enums',
|
|
58
|
+
case 'scSpecEntryUdtEnumV0':
|
|
59
|
+
this.addSpec('enums', value, this.parseEnum)
|
|
61
60
|
break
|
|
62
|
-
case '
|
|
63
|
-
this.addSpec('errors',
|
|
61
|
+
case 'scSpecEntryUdtErrorEnumV0':
|
|
62
|
+
this.addSpec('errors', value, this.parseError)
|
|
64
63
|
break
|
|
65
|
-
case '
|
|
66
|
-
this.addSpec('events',
|
|
64
|
+
case 'scSpecEntryEventV0':
|
|
65
|
+
this.addSpec('events', value, this.parseEvent)
|
|
67
66
|
break
|
|
68
67
|
default:
|
|
69
|
-
console.log('Unknown spec type: ' + spec.
|
|
68
|
+
console.log('Unknown spec type: ' + spec.type)
|
|
70
69
|
break
|
|
71
70
|
}
|
|
72
71
|
}
|
|
@@ -90,10 +89,9 @@ class SpecParser {
|
|
|
90
89
|
|
|
91
90
|
parseUnion(attr, into) {
|
|
92
91
|
const cases = {}
|
|
93
|
-
for (const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
value.type().map(t => this.parseParameterType(t)) :
|
|
92
|
+
for (const {value} of attr.cases) {
|
|
93
|
+
cases[value.name.toString()] = value.type ?
|
|
94
|
+
value.type.map(t => this.parseParameterType(t)) :
|
|
97
95
|
[]
|
|
98
96
|
}
|
|
99
97
|
into[this.parseStructName(attr)] = this.withDocs({cases}, attr)
|
|
@@ -102,12 +100,11 @@ class SpecParser {
|
|
|
102
100
|
parseEnum(attr, into) {
|
|
103
101
|
const cases = {}
|
|
104
102
|
for (const c of attr.cases) {
|
|
105
|
-
const value = c.value
|
|
103
|
+
const value = c.value
|
|
106
104
|
if (value.name) {
|
|
107
|
-
cases[value.name
|
|
105
|
+
cases[value.name.toString()] = value.value
|
|
108
106
|
} else {
|
|
109
|
-
|
|
110
|
-
cases[attr.name.toString()] = this.withDocs({value}, attr)
|
|
107
|
+
cases[c.name.toString()] = this.withDocs({value}, c)
|
|
111
108
|
}
|
|
112
109
|
}
|
|
113
110
|
into[this.parseStructName(attr)] = this.withDocs({cases}, attr)
|
|
@@ -115,8 +112,7 @@ class SpecParser {
|
|
|
115
112
|
|
|
116
113
|
parseError(attr, into) {
|
|
117
114
|
for (const c of attr.cases) {
|
|
118
|
-
|
|
119
|
-
into[attr.name.toString()] = this.withDocs({value: attr.value}, attr)
|
|
115
|
+
into[c.name.toString()] = this.withDocs({value: c.value}, c)
|
|
120
116
|
}
|
|
121
117
|
}
|
|
122
118
|
|
|
@@ -136,13 +132,12 @@ class SpecParser {
|
|
|
136
132
|
const evt = {
|
|
137
133
|
prefixTopics: attr.prefixTopics.map(t => t.toString()),
|
|
138
134
|
params: attr.params.map(p => {
|
|
139
|
-
const pa = p._attributes
|
|
140
135
|
const param = {
|
|
141
|
-
name:
|
|
142
|
-
type: this.parseParameterType(
|
|
143
|
-
location:
|
|
136
|
+
name: p.name.toString(),
|
|
137
|
+
type: this.parseParameterType(p.type),
|
|
138
|
+
location: p.location.value === 0 ? 'data' : 'topics'
|
|
144
139
|
}
|
|
145
|
-
return this.withDocs(param,
|
|
140
|
+
return this.withDocs(param, p)
|
|
146
141
|
}),
|
|
147
142
|
dataFormat
|
|
148
143
|
}
|
|
@@ -150,22 +145,22 @@ class SpecParser {
|
|
|
150
145
|
}
|
|
151
146
|
|
|
152
147
|
parseParameterType(type) {
|
|
153
|
-
const typeName = type.
|
|
148
|
+
const typeName = type.type
|
|
154
149
|
switch (typeName) {
|
|
155
150
|
case 'scSpecTypeOption':
|
|
156
|
-
return `Option<${this.parseParameterType(type.value
|
|
151
|
+
return `Option<${this.parseParameterType(type.value.valueType)}>`
|
|
157
152
|
case 'scSpecTypeBytesN':
|
|
158
|
-
return `BytesN<${type.value
|
|
153
|
+
return `BytesN<${type.value.n}>`
|
|
159
154
|
case 'scSpecTypeVec':
|
|
160
|
-
return `Vec<${this.parseParameterType(type.value
|
|
155
|
+
return `Vec<${this.parseParameterType(type.value.elementType)}>`
|
|
161
156
|
case 'scSpecTypeMap':
|
|
162
|
-
return `Map<${this.parseParameterType(type.value
|
|
157
|
+
return `Map<${this.parseParameterType(type.value.keyType)}, ${this.parseParameterType(type.value.valueType)}>`
|
|
163
158
|
case 'scSpecTypeResult':
|
|
164
|
-
return `Result<${this.parseParameterType(type.value
|
|
159
|
+
return `Result<${this.parseParameterType(type.value.okType)}, ${this.parseParameterType(type.value.errorType)}>`
|
|
165
160
|
case 'scSpecTypeTuple':
|
|
166
|
-
return `(${type.value
|
|
161
|
+
return `(${type.value.valueTypes.map(v => this.parseParameterType(v)).join(', ')})`
|
|
167
162
|
case 'scSpecTypeUdt':
|
|
168
|
-
return type.value
|
|
163
|
+
return type.value.name.toString()
|
|
169
164
|
default:
|
|
170
165
|
let res = typeName.replace('scSpecType', '')
|
|
171
166
|
if (/^[IU](8|16|32|64|128)$/.test(res) || res === 'Bool') { //remap standard int types
|
|
@@ -184,16 +179,14 @@ class SpecParser {
|
|
|
184
179
|
}
|
|
185
180
|
|
|
186
181
|
parseParameter(param, into) {
|
|
187
|
-
|
|
188
|
-
into[attr.name.toString()] = this.withDocs({type: this.parseParameterType(attr.type)}, attr)
|
|
182
|
+
into[param.name.toString()] = this.withDocs({type: this.parseParameterType(param.type)}, param)
|
|
189
183
|
}
|
|
190
184
|
|
|
191
185
|
parseFuncArgument(arg) {
|
|
192
|
-
const attr = arg._attributes
|
|
193
186
|
return this.withDocs({
|
|
194
|
-
name:
|
|
195
|
-
type: this.parseParameterType(
|
|
196
|
-
},
|
|
187
|
+
name: arg.name.toString(),
|
|
188
|
+
type: this.parseParameterType(arg.type)
|
|
189
|
+
}, arg)
|
|
197
190
|
}
|
|
198
191
|
|
|
199
192
|
withDocs(descriptor, attr) {
|
package/src/xdr-reader.js
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* @param {Buffer} buffer
|
|
4
|
-
* @param {{read: function}} xdrContract
|
|
5
|
-
* @return {{}[]}
|
|
6
|
-
*/
|
|
7
|
-
export function parseSectionEntriesXdr(buffer, xdrContract) {
|
|
8
|
-
const reader = new XdrReader(buffer)
|
|
9
|
-
const entries = []
|
|
10
|
-
while (!reader.eof) {
|
|
11
|
-
entries.push(xdrContract.read(reader))
|
|
12
|
-
}
|
|
13
|
-
return entries
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
class XdrReader {
|
|
17
|
-
/**
|
|
18
|
-
* @constructor
|
|
19
|
-
* @param {Buffer} source - Buffer containing serialized data
|
|
20
|
-
*/
|
|
21
|
-
constructor(source) {
|
|
22
|
-
if (!Buffer.isBuffer(source)) {
|
|
23
|
-
if (source instanceof Array) {
|
|
24
|
-
source = Buffer.from(source)
|
|
25
|
-
} else
|
|
26
|
-
throw new Error('Source not specified')
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
this._buffer = source
|
|
30
|
-
this._length = source.length
|
|
31
|
-
this._index = 0
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @type {Buffer}
|
|
36
|
-
* @private
|
|
37
|
-
* @readonly
|
|
38
|
-
*/
|
|
39
|
-
_buffer
|
|
40
|
-
/**
|
|
41
|
-
* @type {Number}
|
|
42
|
-
* @private
|
|
43
|
-
* @readonly
|
|
44
|
-
*/
|
|
45
|
-
_length
|
|
46
|
-
/**
|
|
47
|
-
* @type {Number}
|
|
48
|
-
* @private
|
|
49
|
-
* @readonly
|
|
50
|
-
*/
|
|
51
|
-
_index
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Check if the reader reached the end of the input buffer
|
|
55
|
-
* @return {Boolean}
|
|
56
|
-
*/
|
|
57
|
-
get eof() {
|
|
58
|
-
return this._index === this._length
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Advance reader position, check padding and overflow
|
|
63
|
-
* @param {Number} size - Bytes to read
|
|
64
|
-
* @return {Number} Position to read from
|
|
65
|
-
* @private
|
|
66
|
-
*/
|
|
67
|
-
advance(size) {
|
|
68
|
-
const from = this._index
|
|
69
|
-
// advance cursor position
|
|
70
|
-
this._index += size
|
|
71
|
-
// check buffer boundaries
|
|
72
|
-
if (this._length < this._index)
|
|
73
|
-
throw new Error(
|
|
74
|
-
'attempt to read outside the boundary of the buffer'
|
|
75
|
-
)
|
|
76
|
-
// check that padding is correct for Opaque and String
|
|
77
|
-
const padding = 4 - (size % 4 || 4)
|
|
78
|
-
if (padding > 0) {
|
|
79
|
-
for (let i = 0; i < padding; i++)
|
|
80
|
-
if (this._buffer[this._index + i] !== 0)
|
|
81
|
-
// all bytes in the padding should be zeros
|
|
82
|
-
throw new Error('Invalid padding')
|
|
83
|
-
this._index += padding
|
|
84
|
-
}
|
|
85
|
-
return from
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Reset reader position
|
|
90
|
-
*/
|
|
91
|
-
rewind() {
|
|
92
|
-
this._index = 0
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Read byte array from the buffer
|
|
97
|
-
* @param {Number} size - Bytes to read
|
|
98
|
-
* @return {Buffer} - Sliced portion of the underlying buffer
|
|
99
|
-
*/
|
|
100
|
-
read(size) {
|
|
101
|
-
const from = this.advance(size)
|
|
102
|
-
return this._buffer.subarray(from, from + size)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Read i32 from buffer
|
|
107
|
-
* @return {Number}
|
|
108
|
-
*/
|
|
109
|
-
readInt32BE() {
|
|
110
|
-
return this._buffer.readInt32BE(this.advance(4))
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Read u32 from buffer
|
|
115
|
-
* @return {Number}
|
|
116
|
-
*/
|
|
117
|
-
readUInt32BE() {
|
|
118
|
-
return this._buffer.readUInt32BE(this.advance(4))
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Read i64 from buffer
|
|
123
|
-
* @return {BigInt}
|
|
124
|
-
*/
|
|
125
|
-
readBigInt64BE() {
|
|
126
|
-
return this._buffer.readBigInt64BE(this.advance(8))
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Read u64 from buffer
|
|
131
|
-
* @return {BigInt}
|
|
132
|
-
*/
|
|
133
|
-
readBigUInt64BE() {
|
|
134
|
-
return this._buffer.readBigUInt64BE(this.advance(8))
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Read float from buffer
|
|
139
|
-
* @return {Number}
|
|
140
|
-
*/
|
|
141
|
-
readFloatBE() {
|
|
142
|
-
return this._buffer.readFloatBE(this.advance(4))
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Read double from buffer
|
|
147
|
-
* @return {Number}
|
|
148
|
-
*/
|
|
149
|
-
readDoubleBE() {
|
|
150
|
-
return this._buffer.readDoubleBE(this.advance(8))
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Ensure that input buffer has been consumed in full, otherwise it's a type mismatch
|
|
155
|
-
*/
|
|
156
|
-
ensureInputConsumed() {
|
|
157
|
-
if (this._index !== this._length)
|
|
158
|
-
throw new Error(`Invalid XDR contract typecast - source buffer not entirely consumed`)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Get number of bytes remaining in buffer
|
|
163
|
-
* @returns {Number}
|
|
164
|
-
*/
|
|
165
|
-
remainingBytes() {
|
|
166
|
-
return this._length - this._index
|
|
167
|
-
}
|
|
168
|
-
}
|