Skip to content

Commit

Permalink
feat: add nano contract parser and deserializer
Browse files Browse the repository at this point in the history
  • Loading branch information
pedroferreira1 committed Dec 27, 2023
1 parent 20c155e commit 70c866c
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 1 deletion.
55 changes: 55 additions & 0 deletions src/nano_contracts/deserializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Copyright (c) Hathor Labs and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/


import { unpackToFloat, unpackToInt } from '../utils/buffer';


class Deserializer {
deserializeFromType(value: Buffer, type: string): any {
switch (type) {
case 'string':
return this.toString(value);
case 'bytes':
return this.toBytes(value);
case 'int':
return this.toInt(value);
case 'float':
return this.toFloat(value);
case 'bool':
return this.toBool(value);
default:
throw new Error('Invalid type.');
}
}

toString(value: Buffer): string {
return value.toString('utf8');
}

toBytes(value: Buffer): Buffer {
return value;
}

toInt(value: Buffer): number {
return unpackToInt(4, true, value)[0];
}

toFloat(value: Buffer): number {
return unpackToFloat(value)[0];
}

toBool(value: Buffer): boolean {
if (value[0]) {
return true;
} else {
return false;
}
}
}

export default Deserializer;
80 changes: 80 additions & 0 deletions src/nano_contracts/parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Copyright (c) Hathor Labs and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import Config from '../config';
import Address from '../models/address';
import Deserializer from './deserializer';
import ncApi from '../api/nano';
import { Address as bitcoreAddress, PublicKey as bitcorePublicKey } from 'bitcore-lib';
import { get } from 'lodash';
import { hexToBuffer, unpackToInt } from '../utils/buffer';
import {
NanoContractActionType,
NanoContractAction,
NanoContractActionDeposit,
NanoContractActionWithdrawal,
NanoContractDepositData,
NanoContractWithdrawalData,
NanoContractArg
} from './types';


class NanoContractTransactionParser {
blueprintId: string;
method: string;
publicKey: string;
address: Address | null;
args: string | null;
// TODO create type for parsed args
parsedArgs: Object | null;

constructor(blueprintId: string, method: string, publicKey: string, args: string | null) {
this.blueprintId = blueprintId;
this.method = method;
this.publicKey = publicKey;
this.args = args;
this.address = null;
this.parsedArgs = null;
}

parseAddress() {
const network = Config.getNetwork();
const pubkeyBuffer = hexToBuffer(this.publicKey);
const base58 = new bitcoreAddress(bitcorePublicKey(pubkeyBuffer), network.bitcoreNetwork).toString()
this.address = new Address(base58, { network });
}

async parseArguments() {
const parsedArgs: Object[] = [];
if (!this.args) {
return;
}

const deserializer = new Deserializer();
// Get the blueprint data from full node
const blueprintInformation = await ncApi.getBlueprintInformation(this.blueprintId);
const methodArgs = get(blueprintInformation, `public_methods.${this.method}.args`);
if (!methodArgs) {
// TODO Handle error
return;
}

let argsBuffer = Buffer.from(this.args, 'hex');
let size: number;
// TODO handle error
for (const arg of methodArgs) {
[size, argsBuffer] = unpackToInt(2, false, argsBuffer);
const parsed = deserializer.deserializeFromType(argsBuffer.slice(0, size), arg.type);
parsedArgs.push({ ...arg, parsed });
argsBuffer = argsBuffer.slice(size);
}

this.parsedArgs = parsedArgs;
}
}

export default NanoContractTransactionParser;
2 changes: 1 addition & 1 deletion src/nano_contracts/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Serializer {
switch (type) {
case 'string':
return this.fromString(value);
case 'byte':
case 'bytes':
return this.fromBytes(value);
case 'int':
return this.fromInt(value);
Expand Down

0 comments on commit 70c866c

Please sign in to comment.