Skip to content

Commit

Permalink
chore: Improve types and reformat exporter
Browse files Browse the repository at this point in the history
Improve types for decorators and babel plugin
Improve performance of bindgen exporter and clean up code
  • Loading branch information
petarvujovic98 committed Sep 22, 2022
1 parent 3b82668 commit aab75a2
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 143 deletions.
5 changes: 2 additions & 3 deletions lib/build-tools/near-bindgen-exporter.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

82 changes: 41 additions & 41 deletions lib/build-tools/near-bindgen-exporter.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions lib/near-bindgen.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 9 additions & 13 deletions lib/near-bindgen.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

102 changes: 51 additions & 51 deletions src/build-tools/near-bindgen-exporter.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
import * as t from "@babel/types";

const methodTypes = ["call", "view", "initialize"];
Expand Down Expand Up @@ -165,8 +166,51 @@ function executePromise(classId) {
);
}

function createDeclaration(classId, methodName, methodType) {
return t.exportNamedDeclaration(
t.functionDeclaration(
t.identifier(methodName),
[],
t.blockStatement([
// Read the state of the contract from storage.
// const _state = Counter._getState();
readState(classId),
// Throw if initialized on any subsequent init function calls.
// if (_state) { throw new Error('Contract already initialized'); }
preventDoubleInit(methodType),
// Throw if NOT initialized on any non init function calls.
// if (!_state) { throw new Error('Contract must be initialized'); }
ensureInitBeforeCall(classId, methodType),
// Create instance of contract by calling _create function.
// let _contract = Counter._create();
initializeContractClass(classId),
// Reconstruct the contract with the state if the state is valid.
// if (_state) { Counter._reconstruct(_contract, _state); }
reconstructState(classId, methodType),
// Collect the arguments sent to the function.
// const _args = Counter._getArgs();
collectArguments(classId),
// Perform the actual function call to the appropriate contract method.
// const _result = _contract.method(args);
callContractMethod(methodName),
// If the method called is either an initialize or call method type, save the changes to storage.
// Counter._saveToStorage(_contract);
saveToStorage(classId, methodType),
// If a NearPromise is returned from the function call the onReturn method to execute the promise.
// if (_result !== undefined)
// if (_result && _result.constructor && _result.constructor.name === 'NearPromise')
// _result.onReturn();
// else
// near.valueReturn(_contract._serialize(result));
executePromise(classId),
])
)
);
}

export default function () {
return {
/** @type {import('@babel/traverse').Visitor} */
visitor: {
ClassDeclaration(path) {
const classNode = path.node;
Expand All @@ -175,10 +219,7 @@ export default function () {
classNode.decorators &&
classNode.decorators[0].expression.callee.name === "NearBindgen"
) {
const classId = classNode.id;
const contractMethods = {};

for (let child of classNode.body.body) {
classNode.body.body.forEach((child) => {
if (
child.type === "ClassMethod" &&
child.kind === "method" &&
Expand All @@ -187,55 +228,14 @@ export default function () {
const methodType = child.decorators[0].expression.callee.name;

if (methodTypes.includes(methodType)) {
contractMethods[child.key.name] = methodType;
path.insertAfter(
createDeclaration(classNode.id, child.key.name, methodType)
);

console.log(`Babel ${child.key.name} method export done`);
}
}
}

for (let methodName of Object.keys(contractMethods)) {
path.insertAfter(
t.exportNamedDeclaration(
t.functionDeclaration(
t.identifier(methodName),
[],
t.blockStatement([
// Read the state of the contract from storage.
// const _state = Counter._getState();
readState(classId),
// Throw if initialized on any subsequent init function calls.
// if (_state) { throw new Error('Contract already initialized'); }
preventDoubleInit(contractMethods[methodName]),
// Throw if NOT initialized on any non init function calls.
// if (!_state) { throw new Error('Contract must be initialized'); }
ensureInitBeforeCall(classId, contractMethods[methodName]),
// Create instance of contract by calling _create function.
// let _contract = Counter._create();
initializeContractClass(classId),
// Reconstruct the contract with the state if the state is valid.
// if (_state) { Counter._reconstruct(_contract, _state); }
reconstructState(classId, contractMethods[methodName]),
// Collect the arguments sent to the function.
// const _args = Counter._getArgs();
collectArguments(classId),
// Perform the actual function call to the appropriate contract method.
// const _result = _contract.method(args);
callContractMethod(methodName),
// If the method called is either an initialize or call method type, save the changes to storage.
// Counter._saveToStorage(_contract);
saveToStorage(classId, contractMethods[methodName]),
// If a NearPromise is returned from the function call the onReturn method to execute the promise.
// if (_result !== undefined)
// if (_result && _result.constructor && _result.constructor.name === 'NearPromise')
// _result.onReturn();
// else
// near.valueReturn(_contract._serialize(result));
executePromise(classId),
])
)
)
);
console.log(`Babel ${methodName} method export done`);
}
});
}
},
},
Expand Down
64 changes: 33 additions & 31 deletions src/near-bindgen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,28 @@ import { deserialize, serialize } from "./utils";

type EmptyParameterObject = Record<never, never>;
type AnyObject = Record<string, unknown>;
type AnyFunction = (...args: unknown[]) => unknown;
// type DecoratorFunction = (
// target: AnyObject,
// key: string | symbol,
// descriptor: TypedPropertyDescriptor<Function>
// ) => void;

export function initialize(_empty: EmptyParameterObject) {
/* eslint-disable @typescript-eslint/no-empty-function */
return function (
_target: unknown,
type DecoratorFunction = <Function extends (...args: any) => any>(
target: object,
key: string | symbol,
descriptor: TypedPropertyDescriptor<Function>
) => void;

export function initialize(_empty: EmptyParameterObject): DecoratorFunction {
return function <Function extends (...args: any) => any>(
_target: object,
_key: string | symbol,
_descriptor: TypedPropertyDescriptor<AnyFunction>
_descriptor: TypedPropertyDescriptor<Function>
// eslint-disable-next-line @typescript-eslint/no-empty-function
): void {};
}

export function view(_empty: EmptyParameterObject): DecoratorFunction {
return function <Function extends (...args: any) => any>(
_target: object,
_key: string | symbol,
_descriptor: TypedPropertyDescriptor<Function>
// eslint-disable-next-line @typescript-eslint/no-empty-function
): void {};
/* eslint-enable @typescript-eslint/no-empty-function */
}

export function call({
Expand All @@ -26,39 +33,34 @@ export function call({
}: {
privateFunction?: boolean;
payableFunction?: boolean;
}) {
return function (
_target: unknown,
}): DecoratorFunction {
return function <Function extends (...args: any) => any>(
_target: object,
_key: string | symbol,
descriptor: TypedPropertyDescriptor<AnyFunction>
descriptor: TypedPropertyDescriptor<Function>
): void {
const originalMethod = descriptor.value;

descriptor.value = function (...args: unknown[]) {
// @ts-ignore
descriptor.value = function (
...args: Parameters<Function>
): ReturnType<Function> {
if (
privateFunction &&
near.predecessorAccountId() !== near.currentAccountId()
) {
throw Error("Function is private");
throw new Error("Function is private");
}
if (!payableFunction && near.attachedDeposit() > BigInt(0)) {
throw Error("Function is not payable");

if (!payableFunction && near.attachedDeposit() > 0n) {
throw new Error("Function is not payable");
}

return originalMethod.apply(this, args);
};
};
}

export function view(_empty: EmptyParameterObject) {
/* eslint-disable @typescript-eslint/no-empty-function */
return function (
_target: unknown,
_key: string | symbol,
_descriptor: TypedPropertyDescriptor<AnyFunction>
): void {};
/* eslint-enable @typescript-eslint/no-empty-function */
}

export function NearBindgen({
requireInit = false,
serializer = serialize,
Expand Down

0 comments on commit aab75a2

Please sign in to comment.