This repository has been archived by the owner on Sep 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
CU-864dtwgww - Add a way to give hints when parsing #1
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,107 @@ | |
</p> | ||
|
||
# Neo3-parser | ||
|
||
Neo3-parser is a specification of how SmartContract client SDKs can interact with different parsing libraries such as Neon-JS. | ||
|
||
Visit the [main page](../../README.md) of the project. | ||
|
||
## How to parse responses | ||
|
||
After invoking a contract you'll get the results on a stack. Use the `parseRpcResponse(field: RpcResponse, parseConfig?: ParseConfig)` function on each item to get the results parsed. | ||
|
||
### How to use parseConfig | ||
|
||
The `parseConfig` object has the following properties: | ||
|
||
| Property | Description | | ||
|---------------------------|-------------------------------------------------------------------------------------------| | ||
| type: string | a [valid ABI Type](https:/neo-project/proposals/blob/master/nep-14.mediawiki#method)| | ||
| hint?: string | a type that extends from the ABI type | | ||
| generic?: ParseConfig | you only need to pass this prop if `type` is `"Array"` | | ||
| genericKey?: ParseConfig | you only need to pass this prop if `type` is `"Map"` | | ||
| genericItem?: ParseConfig | you only need to pass this prop if `type` is `"Map"` | | ||
| union?: ParseConfig[] | you only need to pass this prop if `type` is `"Any"` and you expect to get multiple types | | ||
|
||
> Note: check [HINT_TYPES](./src/index.ts) to see what types are available to use on `hint`. | ||
|
||
### Example | ||
|
||
```ts | ||
// Simulating a result stack after invoking a contract | ||
const stackResult = [ | ||
{ | ||
type: "ByteString", | ||
value: "AAECAwQFBgcICQoLDA0ODxAREhM=" // This value is a Hash160 | ||
} | ||
] | ||
|
||
// Call parseRpcResponse on an item of the stack | ||
const response = Neo3Parser.parseRpcResponde(stackResult[0]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you put |
||
|
||
console.log(response) | ||
// Expected output: "☺☻♥♦♣♠\n♫☼►◄↕‼" | ||
|
||
// You can use the `parseConfig` parameter to change how to parse the response | ||
const responseHash160 = Neo3Parser.parseRpcResponde(stackResult[0], { type: "Hash160"}) | ||
|
||
console.log(responseHash160) | ||
// Expected output: "0x131211100f0e0d0c0b0a09080706050403020100" | ||
|
||
// Adding a hint might also change how it is parsed | ||
const responseHash160LE = Neo3Parser.parseRpcResponde(stackResult[0], { type: "Hash160", hint: "ScriptHashLittleEndian"}) | ||
|
||
console.log(responseHash160LE) | ||
// Expected output: "000102030405060708090a0b0c0d0e0f10111213" | ||
``` | ||
|
||
#### Using neo3-boa to get the parseConfig | ||
|
||
If you compiled your smart contract with Neo3-boa you can use the ABI inside the `.manifest.json` file as the `parseConfig`. | ||
|
||
For example, compiling [this smart contract](https:/CityOfZion/neo3-boa/blob/d43c0a3cdb1db11e80093d8da8b30441384ba213/boa3_test/test_sc/generation_test/ManifestTypeHintFromUInt160ToScriptHashLittleEndian.py) will generate the following file: | ||
|
||
```json | ||
{ | ||
"name": "ManifestTypeHintFromUInt160ToScriptHashLittleEndian", | ||
"groups": [], | ||
"abi": { | ||
"methods": [ | ||
{ | ||
"name": "Main", | ||
"offset": 0, | ||
"parameters": [], | ||
"safe": false, | ||
"returntype": "Hash160", | ||
"returnhint": "ScriptHashLittleEndian" | ||
} | ||
], | ||
"events": [] | ||
}, | ||
"permissions": [ | ||
{ | ||
"contract": "*", | ||
"methods": "*" | ||
} | ||
], | ||
"trusts": [], | ||
"features": {}, | ||
"supportedstandards": [], | ||
"extra": null | ||
} | ||
``` | ||
|
||
Then, you can copy the properties of the method you want to parse that have the `return` prefix, in this example it should be `returntype` and `returnhint`. | ||
Remove the `return` prefix and attribute it to a `ParseConfig` variable in your TypeScript file. | ||
|
||
```ts | ||
const parseConfigFromNeo3boa = { | ||
"type": "Hash160", | ||
"hint": "ScriptHashLittleEndian" | ||
} | ||
|
||
const responseHash160LE = Neo3Parser.parseRpcResponde(stackResult[0], parseConfigFromNeo3boa) | ||
|
||
console.log(responseHash160LE) | ||
// Expected output: "000102030405060708090a0b0c0d0e0f10111213" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,40 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.EXTENDED_ABI_TYPES = exports.ABI_TYPES = exports.INTERNAL_TYPES = void 0; | ||
exports.INTERNAL_TYPES = { | ||
ARRAY: "Array", | ||
BYTESTRING: "ByteString", | ||
BUFFER: "Buffer", | ||
INTEGER: "Integer", | ||
INTEROPINTERFACE: "InteropInterface", | ||
BOOLEAN: "Boolean", | ||
MAP: "Map", | ||
NULL: "Null", | ||
POINTER: "Pointer", | ||
STRUCT: "Struct", | ||
}; | ||
exports.ABI_TYPES = { | ||
ANY: { name: "Any" }, | ||
SIGNATURE: { name: "Signature", internal: exports.INTERNAL_TYPES.BYTESTRING }, | ||
BOOLEAN: { name: "Boolean", internal: exports.INTERNAL_TYPES.BOOLEAN }, | ||
INTEGER: { name: "Integer", internal: exports.INTERNAL_TYPES.INTEGER }, | ||
HASH160: { name: "Hash160", internal: exports.INTERNAL_TYPES.BYTESTRING }, | ||
HASH256: { name: "Hash256", internal: exports.INTERNAL_TYPES.BYTESTRING }, | ||
BYTEARRAY: { name: "ByteArray", internal: exports.INTERNAL_TYPES.BYTESTRING }, | ||
PUBLICKEY: { name: "PublicKey", internal: exports.INTERNAL_TYPES.BYTESTRING }, | ||
STRING: { name: "String", internal: exports.INTERNAL_TYPES.BYTESTRING }, | ||
ARRAY: { name: "Array", internal: exports.INTERNAL_TYPES.ARRAY }, | ||
MAP: { name: "Map", internal: exports.INTERNAL_TYPES.MAP }, | ||
INTEROPINTERFACE: { name: "InteropInterface", internal: exports.INTERNAL_TYPES.INTEROPINTERFACE }, | ||
VOID: { name: "Void", internal: exports.INTERNAL_TYPES.NULL }, | ||
}; | ||
exports.EXTENDED_ABI_TYPES = { | ||
ADDRESS: { name: "Address", abi: exports.ABI_TYPES.STRING }, | ||
PUBLICKEY: { name: "PublicKey", abi: exports.ABI_TYPES.PUBLICKEY }, | ||
SCRIPTHASH: { name: "ScriptHash", abi: exports.ABI_TYPES.HASH160 }, | ||
SCRIPTHASHLITTLEENDING: { name: "ScriptHashLittleEndian", abi: exports.ABI_TYPES.HASH160 }, | ||
BLOCKHASH: { name: "BlockHash", abi: exports.ABI_TYPES.HASH256 }, | ||
TRANSACTIONID: { name: "TransactionId", abi: exports.ABI_TYPES.HASH256 }, | ||
STORAGECONTEXT: { name: "StorageContext", abi: exports.ABI_TYPES.INTEROPINTERFACE }, | ||
ITERATOR: { name: "Iterator", abi: exports.ABI_TYPES.INTEROPINTERFACE }, | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by "on each item"? It sounds like if I have multiple variables on my response I will need to do this for each of them, and this is not true, I can do this once for my response and it will parse everything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I meant each item inside the result stack, e.g., if I invoked 3 methods on the same transaction, then the result stack would have length 3 and I would need to call parseRpcResponse 3 times.
I could overload the function and have a
function parseRpcResponse(field: RpcResponse, parseConfig?: ParseConfig): any
and afunction parseRpcResponse(field: RpcResponse[], parseConfig?: ParseConfig[]): any[]
if you preferThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the majority of the use cases the user will invoke a single method on the transaction, so I think this overload is not necessary. I am just concern with the understanding. IDK, maybe saying "each item of the stack" might be enought to clarify.