Skip to content

Commit

Permalink
feat(ABI): build generic data collection from ABI (#65)
Browse files Browse the repository at this point in the history
  • Loading branch information
rahulyadav-57 authored Jul 19, 2024
1 parent 9109cf8 commit 6923353
Showing 1 changed file with 154 additions and 0 deletions.
154 changes: 154 additions & 0 deletions src/utility/abi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { ContractLanguage } from '@/interfaces/workspace.interface';
import {
ABIArgument,
ABIField,
ABIType,
ABITypeRef,
ContractABI,
} from '@ton/core';
import { Maybe } from '@ton/core/dist/utils/maybe';

export type ABITypeObject = Record<string, ABIType>;

interface TactContractABI extends ContractABI {
init: Maybe<ABIArgument[]>;
}

export interface TactABIField {
name: string;
type: ABITypeRef;
fields: ABIField[] | null;
}

export class ABIParser {
private language: ContractLanguage;
private abi: TactContractABI;
private abiTypes: Maybe<ABITypeObject>;

constructor(abi: TactContractABI, language: ContractLanguage = 'tact') {
this.language = language;
this.abi = abi;
this.abiTypes = this.generateAbiTypes();
}

get init() {
if (!this.abi.init) {
return undefined;
}
return this.abi.init.map((item) => {
return {
name: item.name,
type: item.type,
fields:
item.type.kind === 'simple'
? this.resolveFields(item.type.type)
: null,
};
});
}

get getters() {
if (!this.abi.getters) {
return undefined;
}

return this.abi.getters.map((getter) => {
let getterArguments: TactABIField[] = [];
if (getter.arguments) {
getterArguments = getter.arguments.map((argument) => {
return {
name: argument.name,
type: argument.type,
fields:
argument.type.kind === 'simple'
? this.resolveFields(argument.type.type)
: null,
};
});
}
return {
name: getter.name,
params: getterArguments,
returnType: getter.returnType,
};
});
}

get receivers() {
if (!this.abi.receivers) {
return undefined;
}

return this.abi.receivers.map((receiver) => {
let argumentName: string;

switch (receiver.message.kind) {
case 'typed':
argumentName = receiver.message.type;
break;
case 'text':
argumentName = receiver.message.text ?? '';
break;
case 'any':
argumentName = 'null';
break;
case 'empty':
argumentName = 'empty';
break;
default:
argumentName = 'unknown';
break;
}

return {
name: receiver.receiver,
params: [
{
name: argumentName,
type: {
kind: receiver.message.kind,
},
fields:
receiver.message.kind === 'typed'
? this.resolveFields(receiver.message.type)
: null,
},
],
};
});
}

getABI() {
return this.abi;
}

private generateAbiTypes() {
if (!this.abi.types || this.language === 'func') {
return undefined;
}
return this.abi.types.reduce((acc, type) => {
acc[type.name] = type;
return acc;
}, {} as ABITypeObject);
}

private resolveFields(field: string | null): ABIField[] | null {
if (!field || !this.abiTypes) {
return null;
}
if (!Object.prototype.hasOwnProperty.call(this.abiTypes, field)) {
return null;
}
const type = this.abiTypes[field];
return type.fields.map((item) => {
return {
name: item.name,
type: item.type,
fields:
item.type.kind === 'simple'
? this.resolveFields(item.type.type)
: null,
};
});
}
}

0 comments on commit 6923353

Please sign in to comment.