Skip to content

Commit 88e8ac5

Browse files
committed
work with both JSON and BCS payloads
1 parent ea20385 commit 88e8ac5

File tree

6 files changed

+135
-53
lines changed

6 files changed

+135
-53
lines changed

src/ast_to_ts.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ pub fn write_app(
259259
if func.signature.type_parameters.len() > 0 {
260260
w.writeln(format!(" $p: TypeTag[], /* <{}>*/", tpnames));
261261
}
262+
w.writeln(" isJSON = false,");
262263
let tags = if func.signature.type_parameters.is_empty() {
263264
""
264265
} else {
@@ -269,10 +270,15 @@ pub fn write_app(
269270
} else {
270271
", "
271272
};
273+
let possibly_comma = if args.is_empty() && tags.is_empty() {
274+
""
275+
} else {
276+
", "
277+
};
272278
w.writeln(") {");
273279
w.writeln(format!(
274-
" return buildPayload_{}({}{}{});",
275-
fname, args, separator, tags
280+
" return buildPayload_{}({}{}{}{}isJSON);",
281+
fname, args, separator, tags, possibly_comma,
276282
));
277283
w.writeln("}");
278284

@@ -284,10 +290,11 @@ pub fn write_app(
284290
w.writeln(format!(" $p: TypeTag[], /* <{}>*/", tpnames));
285291
}
286292
w.writeln(" _maxGas = 1000,");
293+
w.writeln(" _isJSON = false,");
287294
w.writeln(") {");
288295
w.writeln(format!(
289-
" const payload = buildPayload_{}({}{}{});",
290-
fname, args, separator, tags
296+
" const payload = buildPayload_{}({}{}{}{}_isJSON);",
297+
fname, args, separator, tags, possibly_comma
291298
));
292299
w.writeln(" return $.sendPayloadTx(this.client, _account, payload, _maxGas);");
293300
w.writeln("}");
@@ -1007,7 +1014,7 @@ pub fn write_query_function(
10071014

10081015
// params
10091016
w.writeln("client: AptosClient,");
1010-
w.writeln("account: AptosAccount,");
1017+
w.writeln("fetcher: $.SimulationKeys,");
10111018
w.writeln("repo: AptosParserRepo,");
10121019
write_parameters(&f.signature, w, c, true, false)?;
10131020
w.writeln("$p: TypeTag[],");
@@ -1053,7 +1060,7 @@ pub fn write_query_function(
10531060
));
10541061
let output_tag = base_type_to_typetag(return_type, c)?;
10551062
w.writeln(format!("const outputTypeTag = {};", output_tag));
1056-
w.writeln("const output = await $.simulatePayloadTx(client, account, payload);");
1063+
w.writeln("const output = await $.simulatePayloadTx(client, fetcher, payload);");
10571064
w.writeln(format!(
10581065
"return $.takeSimulationValue<{}>(output, outputTypeTag, repo)",
10591066
output_struct_name
@@ -1069,7 +1076,7 @@ pub fn write_query_function(
10691076
w.writeln("function maker(");
10701077
w.increase_indent();
10711078

1072-
w.writeln("account: AptosAccount,");
1079+
w.writeln("fetcher: $.SimulationKeys,");
10731080
write_parameters(&f.signature, w, c, true, false)?;
10741081
w.writeln("$p: TypeTag[],");
10751082

@@ -1080,7 +1087,7 @@ pub fn write_query_function(
10801087
param_list.push("$p".to_string());
10811088
}
10821089
w.writeln(format!(
1083-
" return {}(app.client, account, app.repo, {})",
1090+
" return {}(app.client, fetcher, app.repo, {})",
10841091
query_fname,
10851092
param_list.join(", ")
10861093
));
@@ -1309,6 +1316,7 @@ impl AstTsPrinter for (FunctionName, &Function) {
13091316
if num_tparams > 0 {
13101317
w.writeln(format!(" $p: TypeTag[], /* <{}>*/", tpnames));
13111318
}
1319+
w.writeln(" isJSON = false,");
13121320
// marks returnType or void
13131321
w.write(") ");
13141322
// body:
@@ -1338,14 +1346,15 @@ impl AstTsPrinter for (FunctionName, &Function) {
13381346
w.writeln(" typeParamStrings,");
13391347
// arguments
13401348
if params_no_signers.is_empty() {
1341-
w.writeln(" []");
1349+
w.writeln(" [],");
13421350
} else {
13431351
w.writeln(" [");
13441352
for (pname, _) in params_no_signers.iter() {
13451353
w.writeln(format!(" {},", pname,));
13461354
}
1347-
w.writeln(" ]");
1355+
w.writeln(" ],");
13481356
}
1357+
w.writeln(" isJSON,");
13491358
w.writeln(");");
13501359
Ok(())
13511360
})?;

src/gen_cli.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ pub fn generate_query_printer(query: &CmdParams) -> Result<(String, String), Dia
381381
const {} = async ({}) => {{
382382
const {{client, account}} = readConfig(program);
383383
const repo = getProjectRepo();
384-
const value = await {}(client, account, repo, {}{}[{}])
384+
const value = await {}(client, getSimulationKeys(account), repo, {}{}[{}])
385385
print(value);
386386
}}
387387
@@ -532,7 +532,7 @@ pub fn generate_cli(ctx: &Context) -> Result<(String, String), Diagnostics> {
532532
let filename = "cli.ts".to_string();
533533
let content = format!(
534534
r###"
535-
import {{ AptosParserRepo, getTypeTagFullname, StructTag, parseTypeTagOrThrow, u8, u64, u128, print, strToU8, u8str, DummyCache, ActualStringClass, sendPayloadTx }} from "@manahippo/move-to-ts";
535+
import {{ AptosParserRepo, getTypeTagFullname, StructTag, parseTypeTagOrThrow, u8, u64, u128, print, strToU8, u8str, DummyCache, ActualStringClass, sendPayloadTx, getSimulationKeys }} from "@manahippo/move-to-ts";
536536
import {{ AptosAccount, AptosClient, HexString, Types }} from "aptos";
537537
import {{ Command }} from "commander";
538538
import {{ getProjectRepo }} from "./";

src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use std::collections::BTreeMap;
2424
use std::path::{Path, PathBuf};
2525
use std::process;
2626
use std::rc::Rc;
27-
use move_compiler::expansion::ast::Value_::Address;
2827

2928
fn write_file(root_path: &PathBuf, pair: (String, String)) {
3029
let (filename, content) = pair;

src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub fn generate_package_json(package_name: String, cli: bool, ui: bool) -> (Stri
6767
"dependencies": {{
6868
"aptos": "^1.3.7",
6969
"big-integer": "^1.6.51",{}
70-
"@manahippo/move-to-ts": "^0.1.28"
70+
"@manahippo/move-to-ts": "^0.2.8"
7171
}}
7272
}}
7373
"###,

typescript/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@manahippo/move-to-ts",
3-
"version": "0.1.28",
3+
"version": "0.2.8",
44
"license": "MIT",
55
"scripts": {
66
"build": "rm -rf dist; tsc -p tsconfig.json",

typescript/src/txSender.ts

Lines changed: 112 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { AptosClient, AptosAccount, Types, TxnBuilderTypes, HexString, BCS } from "aptos";
1+
import { AptosClient, AptosAccount, Types, TxnBuilderTypes, HexString, BCS, TransactionBuilderEd25519 } from "aptos";
22
import { TypeTagParser } from "aptos/dist/transaction_builder/builder_utils";
3-
import { UserTransaction, WriteSetChange_WriteResource } from "aptos/dist/generated";
3+
import { $TransactionPayload_EntryFunctionPayload, TransactionPayload_EntryFunctionPayload, TransactionSignature, UserTransaction, WriteSetChange_WriteResource } from "aptos/dist/generated";
44
import { AccountAddress, Identifier, ModuleId, EntryFunction } from "aptos/dist/transaction_builder/aptos_types";
55
import { AptosParserRepo } from "./parserRepo";
6-
import { AtomicTypeTag, StructTag, TypeTag } from "./typeTag";
6+
import { StructTag } from "./typeTag";
77
import { U128, U64, U8 } from "./builtinTypes";
8-
import { ActualStringClass, serializeMoveValue, serializeMoveValueWithoutTag, serializeVector } from ".";
8+
import { ActualStringClass, payloadArg, serializeMoveValueWithoutTag } from ".";
99

1010
type AcceptedScriptFuncArgType = any[] | U8 | U64 | U128 | HexString | boolean | ActualStringClass;
1111

@@ -15,59 +15,133 @@ export function buildPayload(
1515
funcName: string,
1616
typeArguments: string[],
1717
args: AcceptedScriptFuncArgType[],
18-
): TxnBuilderTypes.TransactionPayloadEntryFunction {
18+
isJSON = false,
19+
): TxnBuilderTypes.TransactionPayloadEntryFunction | TransactionPayload_EntryFunctionPayload {
1920

20-
const bytes = args.map(arg => {
21-
const serializer = new BCS.Serializer();
22-
serializeMoveValueWithoutTag(serializer, arg);
23-
return serializer.getBytes();
24-
});
21+
if (isJSON) {
22+
// JSON
23+
return {
24+
type: "entry_function_payload",
25+
function: `${moduleAddress.toShortString()}::${moduleName}::${funcName}`,
26+
type_arguments: typeArguments,
27+
arguments: args.map(v => payloadArg(v)),
28+
};
29+
}
30+
else {
31+
// BCS
32+
const bytes = args.map(arg => {
33+
const serializer = new BCS.Serializer();
34+
serializeMoveValueWithoutTag(serializer, arg);
35+
return serializer.getBytes();
36+
});
2537

26-
27-
const scriptFunction = new EntryFunction(
28-
new ModuleId(new AccountAddress(moduleAddress.toUint8Array()), new Identifier(moduleName)),
29-
new Identifier(funcName),
30-
typeArguments.map(str => new TypeTagParser(str).parseTypeTag()),
31-
bytes,
32-
);
33-
return new TxnBuilderTypes.TransactionPayloadEntryFunction(scriptFunction);
38+
39+
const scriptFunction = new EntryFunction(
40+
new ModuleId(new AccountAddress(moduleAddress.toUint8Array()), new Identifier(moduleName)),
41+
new Identifier(funcName),
42+
typeArguments.map(str => new TypeTagParser(str).parseTypeTag()),
43+
bytes,
44+
);
45+
return new TxnBuilderTypes.TransactionPayloadEntryFunction(scriptFunction);
46+
}
3447
}
3548

3649
export async function sendPayloadTx(
3750
client: AptosClient,
3851
account: AptosAccount,
39-
payload: TxnBuilderTypes.TransactionPayload,
52+
payload: TxnBuilderTypes.TransactionPayload | TransactionPayload_EntryFunctionPayload,
4053
max_gas=1000
4154
){
42-
console.log("Building tx...");
43-
// RawTransaction
44-
const rawTxn = await client.generateRawTransaction(account.address(), payload, {maxGasAmount: BigInt(max_gas)});
45-
// Signed BCS representation
46-
const bcsTxn = AptosClient.generateBCSTransaction(account, rawTxn);
47-
console.log("Submitting...");
48-
const txnResult = await client.submitSignedBCSTransaction(bcsTxn);
49-
console.log("Submitted");
50-
await client.waitForTransaction(txnResult.hash);
51-
console.log("Confirmed");
52-
const txDetails = (await client.getTransactionByHash(txnResult.hash)) as Types.UserTransaction;
53-
console.log(txDetails);
54-
return txDetails;
55+
// send BCS transaction
56+
if (payload instanceof TxnBuilderTypes.TransactionPayloadEntryFunction) {
57+
console.log("Building tx...");
58+
// RawTransaction
59+
const rawTxn = await client.generateRawTransaction(account.address(), payload, {maxGasAmount: BigInt(max_gas)});
60+
// Signed BCS representation
61+
const bcsTxn = AptosClient.generateBCSTransaction(account, rawTxn);
62+
console.log("Submitting...");
63+
const txnResult = await client.submitSignedBCSTransaction(bcsTxn);
64+
console.log("Submitted");
65+
await client.waitForTransaction(txnResult.hash);
66+
console.log("Confirmed");
67+
const txDetails = (await client.getTransactionByHash(txnResult.hash)) as Types.UserTransaction;
68+
console.log(txDetails);
69+
return txDetails;
70+
}
71+
// send JSON transaction
72+
else {
73+
console.log("Building tx...");
74+
const pld = payload as TransactionPayload_EntryFunctionPayload;
75+
// RawTransaction
76+
const txn = await client.generateTransaction(account.address(), pld, {max_gas_amount: max_gas.toString()});
77+
// Signed json representation
78+
console.log("Signing tx...");
79+
const signedTxn = await client.signTransaction(account, txn);
80+
console.log("Submitting...");
81+
const txnResult = await client.submitTransaction(signedTxn);
82+
console.log("Submitted");
83+
await client.waitForTransaction(txnResult.hash);
84+
console.log("Confirmed");
85+
const txDetails = (await client.getTransactionByHash(txnResult.hash)) as Types.UserTransaction;
86+
console.log(txDetails);
87+
return txDetails;
88+
}
89+
}
90+
91+
export type SimulationKeys = {
92+
pubkey: HexString;
93+
address: HexString;
94+
}
95+
96+
export function getSimulationKeys(account: AptosAccount): SimulationKeys {
97+
return {
98+
pubkey: account.pubKey(),
99+
address: account.address(),
100+
}
55101
}
56102

57103
export async function simulatePayloadTx(
58104
client: AptosClient,
59-
account: AptosAccount,
60-
payload: TxnBuilderTypes.TransactionPayload,
105+
keys: SimulationKeys,
106+
payload: TxnBuilderTypes.TransactionPayload | TransactionPayload_EntryFunctionPayload,
61107
max_gas=1000
62108
){
63-
const rawTxn = await client.generateRawTransaction(account.address(), payload, {maxGasAmount: BigInt(max_gas)});
64-
const bcsTxn = AptosClient.generateBCSSimulation(account, rawTxn);
65-
const outputs = await client.submitBCSSimulation(bcsTxn);
66-
return outputs[0];
109+
if (payload instanceof TxnBuilderTypes.TransactionPayload) {
110+
const rawTxn = await client.generateRawTransaction(keys.address, payload, {maxGasAmount: BigInt(max_gas)});
111+
const bcsTxn = generateBCSSimulation(keys.pubkey, rawTxn);
112+
const outputs = await client.submitBCSSimulation(bcsTxn);
113+
return outputs[0];
114+
}
115+
else {
116+
const pld = payload as TransactionPayload_EntryFunctionPayload;
117+
const txn = await client.generateTransaction(keys.address, pld, {max_gas_amount: max_gas.toString()});
118+
const transactionSignature: TransactionSignature = {
119+
type: "ed25519_signature",
120+
public_key: keys.pubkey.hex(),
121+
// use invalid signature for simulation
122+
signature: HexString.fromUint8Array(new Uint8Array(64)).hex(),
123+
};
124+
125+
const request = { ...txn, signature: transactionSignature };
126+
const outputs = await client.client.transactions.simulateTransaction(request);
127+
return outputs[0];
128+
}
129+
}
130+
131+
export function generateBCSSimulation(pubkey: HexString, rawTxn: TxnBuilderTypes.RawTransaction): Uint8Array {
132+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
133+
const txnBuilder = new TransactionBuilderEd25519((_signingMessage: TxnBuilderTypes.SigningMessage) => {
134+
// @ts-ignore
135+
const invalidSigBytes = new Uint8Array(64);
136+
return new TxnBuilderTypes.Ed25519Signature(invalidSigBytes);
137+
}, pubkey.toUint8Array());
138+
139+
return txnBuilder.sign(rawTxn);
67140
}
68141

69142
export function takeSimulationValue<T>(tx: UserTransaction, tag: StructTag, repo: AptosParserRepo): T {
70143
if (!tx.success) {
144+
console.log(tx);
71145
throw new Error("Simulation failed");
72146
}
73147
const valueData = tx.changes.filter(change => {

0 commit comments

Comments
 (0)