Skip to content

Commit a415962

Browse files
use manifest to contract
1 parent 8434670 commit a415962

4 files changed

Lines changed: 52 additions & 73 deletions

File tree

example/transactionBuilder/app.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,14 +249,11 @@ let namedParams = [];
249249

250250
window.onChangeRecipient = async () => {
251251
const address = document.querySelector("#recipient").value;
252-
const contractCode = await archethic.network.getContractCode(address);
253-
if (contractCode == "") {
254-
return;
255-
}
252+
const contractContext = await archethic.network.getContractCode(address);
256253

257254
document.querySelector("#namedActionsContainer").style.display = "block";
258255

259-
const actions = await Contract.extractActionsFromContract(contractCode);
256+
const actions = await Contract.extractActionsFromContract(contractContext);
260257
actions.forEach((action) => {
261258
const option = document.createElement("option");
262259
option.text = action.name;

src/api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,9 @@ export async function getContractCode(address: string | Uint8Array, endpoint: st
355355
.then(handleResponse)
356356
.then((res): string => {
357357
if (res.errors || res.data == null) {
358-
return "";
358+
throw new Error("No contract at this address")
359359
} else {
360-
return res.data.lastTransaction.data.code;
360+
return res.data.lastTransaction.data.code
361361
}
362362
});
363363
}

src/contract.ts

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,64 @@ import { ContractAction } from "./types.js";
22
import { encryptSecret, deriveAddress } from "./crypto.js";
33
import { ExtendedTransactionBuilder } from "./transaction.js";
44
import Archethic from "./index.js";
5-
import { hexToUint8Array, isHex } from "./utils.js";
5+
import { isHex } from "./utils.js";
66

7-
export async function extractActionsFromContract(code: string): Promise<ContractAction[]> {
8-
let actions = [];
7+
type CodeWithManifest = {
8+
bytecode: string;
9+
manifest: WasmManifest
10+
}
911

10-
if (isHex(code)) {
11-
const wasmModule = await WebAssembly.instantiate(hexToUint8Array(code), {
12-
"archethic/env": {
13-
log: (offset: bigint, length: bigint) => {},
14-
store_u8: (offset: bigint, data: bigint) => {},
15-
load_u8: (offset: bigint): number => 0,
16-
input_size: (): bigint => 0n,
17-
alloc: (length: bigint): bigint => 0n,
18-
set_output: (offset: bigint, length: bigint) => {},
19-
set_error: (offset: bigint, length: bigint) => {}
20-
},
21-
// FIXME with JSON RPC like request
22-
"archethic/IO": {
23-
get_balance: (offset: bigint, length: bigint) => 0
24-
}
25-
});
12+
type WasmManifest = {
13+
abi: WasmABI
14+
}
2615

27-
const reservedFunctions = ["spec", "init", "onUpgrade"];
28-
for (let key in wasmModule.instance.exports) {
29-
if (wasmModule.instance.exports[key] instanceof Function) {
30-
if (!reservedFunctions.includes(key)) {
31-
actions.push({ name: key, parameters: ["WASM JSON Input"] });
32-
}
33-
}
34-
}
16+
type WasmABI = {
17+
functions: Record<string, WASMFunctionABI>
18+
}
3519

36-
actions.push({ name: "upgrade", parameters: ['WASM JSON Input ( {"code": "wasm code as hex"})'] });
20+
type WASMFunctionABI = {
21+
type: string;
22+
name: string;
23+
input: Record<string, any>
24+
}
3725

38-
return actions;
26+
export async function extractActionsFromContract(code: string): Promise<ContractAction[]> {
27+
try {
28+
const codeWithManifest: CodeWithManifest = JSON.parse(code)
29+
const manifest = codeWithManifest.manifest
30+
let actions: ContractAction[] = []
31+
for (let name of Object.keys(manifest.abi.functions)) {
32+
const functionABI = manifest.abi.functions[name]
33+
if (functionABI.type == "action") {
34+
actions.push({
35+
name: name,
36+
parameters: Object.keys(functionABI.input)
37+
})
38+
}
39+
}
40+
return actions
3941
}
42+
catch(e) {
43+
let actions = [];
4044

41-
const regex = /actions\s+triggered_by:\s+transaction,\s+on:\s+([\w\s.,()]+?)\s+do/g;
45+
const regex = /actions\s+triggered_by:\s+transaction,\s+on:\s+([\w\s.,()]+?)\s+do/g;
4246

43-
for (const match of code.matchAll(regex)) {
44-
const fullAction = match[1];
47+
for (const match of code.matchAll(regex)) {
48+
const fullAction = match[1];
4549

46-
const regexActionName = /(\w+)\((.*?)\)/g;
47-
for (const actionMatch of fullAction.matchAll(regexActionName)) {
48-
const name = actionMatch[1];
49-
const parameters = actionMatch[2] != "" ? actionMatch[2].split(",") : [];
50-
actions.push({
51-
name: name,
52-
parameters: parameters
53-
});
50+
const regexActionName = /(\w+)\((.*?)\)/g;
51+
for (const actionMatch of fullAction.matchAll(regexActionName)) {
52+
const name = actionMatch[1];
53+
const parameters = actionMatch[2] != "" ? actionMatch[2].split(",") : [];
54+
actions.push({
55+
name: name,
56+
parameters: parameters
57+
});
58+
}
5459
}
55-
}
5660

57-
return actions;
61+
return actions;
62+
}
5863
}
5964

6065
export function parseTypedArgument(input: any): any {

src/transaction_builder.ts

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -433,36 +433,13 @@ export default class TransactionBuilder {
433433
* JSON RPC API SEND_TRANSACTION
434434
*/
435435
async toNodeRPC(): Promise<TransactionRPC> {
436-
async function asyncConcatUint8Arrays(uint8arrays: Uint8Array[]) {
437-
const blob = new Blob(uint8arrays);
438-
const buffer = await blob.arrayBuffer();
439-
return new Uint8Array(buffer);
440-
}
441-
442-
async function compress(str: Uint8Array): Promise<Uint8Array> {
443-
// Convert the string to a byte stream.
444-
const stream = new Blob([str]).stream();
445-
446-
// Create a compressed stream.
447-
const compressedStream = stream.pipeThrough(new CompressionStream("deflate-raw"));
448-
449-
// Read all the bytes from this stream.
450-
const chunks: Uint8Array[] = [];
451-
//@ts-ignore
452-
for await (const chunk of compressedStream) {
453-
chunks.push(chunk);
454-
}
455-
456-
return await asyncConcatUint8Arrays(chunks);
457-
}
458-
459436
return {
460437
version: this.version,
461438
address: uint8ArrayToHex(this.address),
462439
type: this.type,
463440
data: {
464441
content: new TextDecoder().decode(this.data.content),
465-
code: uint8ArrayToHex(await compress(this.data.code)),
442+
code: new TextDecoder().decode(this.data.code),
466443
ownerships: this.data.ownerships.map(({ secret, authorizedPublicKeys }) => {
467444
return {
468445
secret: uint8ArrayToHex(secret),

0 commit comments

Comments
 (0)