Skip to content

Commit 508e38c

Browse files
committed
Implement JSON description objects
1 parent 1dd0d07 commit 508e38c

File tree

6 files changed

+128
-1
lines changed

6 files changed

+128
-1
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module.exports = {
2323
ts: 'never',
2424
},
2525
],
26+
'import/prefer-default-export': 'off',
2627
'lines-between-class-members': [
2728
'error',
2829
'always',

src/abi/contract.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { ABIMethod, ABIMethodParams } from './method';
2+
3+
export interface ABIContractParams {
4+
name: string;
5+
// eslint-disable-next-line camelcase
6+
app_id: number;
7+
methods: ABIMethodParams[];
8+
}
9+
10+
export class ABIContract {
11+
public readonly name: string;
12+
// eslint-disable-next-line camelcase
13+
public readonly app_id: number;
14+
public readonly methods: ABIMethod[];
15+
16+
constructor(params: ABIContractParams) {
17+
this.name = params.name;
18+
this.app_id = params.app_id;
19+
this.methods = params.methods.map((method) => new ABIMethod(method));
20+
}
21+
}

src/abi/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './abi_type';
2+
export * from './contract';
3+
export * from './interface';
4+
export * from './method';

src/abi/interface.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { ABIMethod, ABIMethodParams } from './method';
2+
3+
export interface ABIInterfaceParams {
4+
name: string;
5+
methods: ABIMethodParams[];
6+
}
7+
8+
export class ABIInterface {
9+
public readonly name: string;
10+
public readonly methods: ABIMethod[];
11+
12+
constructor(params: ABIInterfaceParams) {
13+
this.name = params.name;
14+
this.methods = params.methods.map((method) => new ABIMethod(method));
15+
}
16+
}

src/abi/method.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { genericHash } from '../nacl/naclWrappers';
2+
import { ABIType, ABITupleType } from './abi_type';
3+
4+
const transactionTypes = ['pay', 'keyreg', 'acfg', 'axfer', 'afrz', 'appl'];
5+
6+
function parseMethodSignature(
7+
signature: string
8+
): { name: string; args: string[]; returns: string } {
9+
const argsStart = signature.indexOf('(');
10+
const argsEnd = signature.lastIndexOf(')');
11+
12+
if (argsStart === -1 || argsEnd === -1) {
13+
throw new Error(`Invalid method signature: ${signature}`);
14+
}
15+
16+
return {
17+
name: signature.slice(argsStart),
18+
args: ABITupleType.parseTupleContent(
19+
signature.slice(argsStart + 1, argsEnd)
20+
),
21+
returns: signature.slice(argsEnd + 1),
22+
};
23+
}
24+
25+
export interface ABIMethodParams {
26+
name: string;
27+
desc?: string;
28+
args: Array<{ name?: string; type: string; desc?: string }>;
29+
returns?: { type: string; desc?: string };
30+
}
31+
32+
export class ABIMethod {
33+
public readonly name: string;
34+
public readonly desc?: string;
35+
public readonly args: Array<{ name?: string; type: string; desc?: string }>;
36+
public readonly returns?: { type: string; desc?: string };
37+
38+
constructor(params: ABIMethodParams) {
39+
this.name = params.name;
40+
this.desc = params.desc;
41+
this.args = params.args;
42+
this.returns = params.returns;
43+
}
44+
45+
getSignature(): string {
46+
const args = this.args.map((arg) => arg.type).join(',');
47+
const returns = this.returns ? this.returns.type : 'void';
48+
return `${this.name}(${args})${returns}`;
49+
}
50+
51+
getSelector(): Uint8Array {
52+
const hash = genericHash(this.getSignature());
53+
return new Uint8Array(hash.slice(0, 4));
54+
}
55+
56+
txnCount(): number {
57+
let count = 1;
58+
for (const arg of this.args) {
59+
if (transactionTypes.includes(arg.type)) {
60+
count += 1;
61+
}
62+
}
63+
return count;
64+
}
65+
66+
static fromSignature(signature: string): ABIMethod {
67+
const { name, args, returns } = parseMethodSignature(signature);
68+
69+
// ensure each arg and return type is valid
70+
args.forEach((arg) => {
71+
if (!transactionTypes.includes(arg)) {
72+
ABIType.from(arg);
73+
}
74+
});
75+
if (returns !== 'void') {
76+
ABIType.from(returns);
77+
}
78+
79+
return new ABIMethod({
80+
name,
81+
args: args.map((arg) => ({ type: arg })),
82+
returns: returns === 'void' ? undefined : { type: returns },
83+
});
84+
}
85+
}

src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,4 @@ export const LogicTemplates = LogicTemplatesCommonJSExport.default;
165165
export * from './makeTxn';
166166
export * from './transaction';
167167
export * from './types';
168-
export * from './abi/abi_type';
168+
export * from './abi';

0 commit comments

Comments
 (0)