Skip to content

Commit 4806b69

Browse files
committed
feat: invoke with tickets
1 parent a5912d4 commit 4806b69

File tree

11 files changed

+118
-22
lines changed

11 files changed

+118
-22
lines changed

deku-c/client/src/deku-c/contract.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { DekuCClient } from ".";
22
import { DekuPClient } from "../deku-p/index";
3+
import Balances, { Balances as BalancesType } from "../deku-p/core/balances";
34
import { compileExpression, compileLigoExpression } from "./utils";
45

56
export type JSONType =
@@ -108,21 +109,25 @@ export class Contract {
108109
* @param parameter the parameter of the contract as provided by tunac
109110
* @returns the hash of the operation
110111
*/
111-
async invokeRaw(parameter: any): Promise<string> {
112+
async invokeRaw(parameter: any, tickets?: BalancesType): Promise<string> {
113+
if (tickets === undefined) tickets = [];
114+
112115
const invoke = {
113116
operation: JSON.stringify({
114117
address: this.address,
115118
argument: parameter,
116119
}),
117-
tickets: [],
120+
tickets,
118121
};
119122
const hash = await this.deku.submitVmOperation(invoke);
120123
return hash;
121124
}
122125

123-
async invoke(expression: string): Promise<string> {
126+
async invoke(expression: string, tickets?: BalancesType): Promise<string> {
127+
if (!tickets) tickets = [];
124128
const parameter = { expression, address: this.address };
125129
const invoke = await compileExpression(this.deku.dekuRpc, parameter);
130+
invoke.tickets = Balances.toDTO(tickets);
126131
const hash = await this.deku.submitVmOperation(invoke);
127132
return hash;
128133
}
@@ -132,7 +137,11 @@ export class Contract {
132137
* @param parameter the parameter of the contract, in Ligo // FIXME lang
133138
* @returns the hash of the operation
134139
*/
135-
async invokeLigo(kind: ligo_kind, code: string, expression: string): Promise<string> {
140+
async invokeLigo(
141+
kind: ligo_kind,
142+
code: string,
143+
expression: string
144+
): Promise<string> {
136145
// FIXME the need for the two RPCs stinks (also they're strings)
137146
const parameter = {
138147
kind,

deku-c/client/src/deku-c/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export type Settings = {
1717
export class DekuCClient extends DekuPClient {
1818
readonly ligoRpc?: string;
1919

20-
2120
constructor(settings: Settings) {
2221
super(settings);
2322
this.ligoRpc = settings.ligoRpc;

deku-c/client/src/deku-c/utils.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { JSONType } from "./contract";
2+
import Balances, { Balances as BalancesType } from "../deku-p/core/balances";
23
import * as path from "path";
34

45
export const originateTz = async (
@@ -35,7 +36,10 @@ export const originateLigo = async (
3536
method: "POST",
3637
body: JSON.stringify({ lang: kind, source: code }),
3738
};
38-
const result = await fetch(path.join(ligoRpc, "/api/v1/ligo/originate"), options);
39+
const result = await fetch(
40+
path.join(ligoRpc, "/api/v1/ligo/originate"),
41+
options
42+
);
3943
const { code: source } = await result.json();
4044
return originateTz(dekuRpc, { code: source, initialStorage });
4145
}
@@ -88,7 +92,10 @@ export const compileLigoExpression = async (
8892
expression: ligoExpression,
8993
}),
9094
};
91-
const result = await fetch(path.join(ligoRpc, "/api/v1/ligo/expression"), options);
95+
const result = await fetch(
96+
path.join(ligoRpc, "/api/v1/ligo/expression"),
97+
options
98+
);
9299
const { expression } = await result.json();
93100
return compileExpression(dekuRpc, { expression, address });
94101
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,21 @@
1+
import { validateKeyHash, validateContractAddress } from "@taquito/utils";
2+
13
export type Address = string;
4+
5+
const parseAddress = (s: string): Address => {
6+
if (s[0] === '"') {
7+
if (!(s[s.length - 1] === '"')) throw Error(`Ill-formed address: ${s}`);
8+
s = s.slice(1, -1);
9+
}
10+
11+
// TODO: check that the address is correct for Deku
12+
if (s.slice(0, 2) === "DK") return s;
13+
14+
if (validateKeyHash(s) || validateContractAddress(s)) return s;
15+
16+
throw Error(`Invalid address ${s}`);
17+
};
18+
19+
export default {
20+
parseAddress,
21+
};

deku-c/client/src/deku-p/core/balances.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Amount, { Amount as AmountType } from "./amount";
12
import JSONValue, { JSONType } from "../utils/json";
23
import TicketID, { TicketID as TicketIDType } from "./ticket-id";
34

@@ -23,6 +24,32 @@ const ofDTO = (json: JSONValue): Balances | null => {
2324
return balances;
2425
};
2526

27+
const toDTO = (balances: Balances) => {
28+
const DTO = balances.map((tamount) => {
29+
const ticket = TicketID.toDTO(tamount.ticket);
30+
const amount = tamount.amount.toString(); // FIXME please help
31+
return [ticket, amount];
32+
});
33+
return DTO;
34+
};
35+
36+
const parseTicketAmount = (s: string): TicketAmount => {
37+
if (s[0] === "(") {
38+
if (!(s[s.length - 1] === ")")) throw Error(`Ill-formed pair: ${s}`);
39+
s = s.slice(1, -1);
40+
}
41+
const parts = s.split(" ").filter((x) => x);
42+
let i = 0;
43+
if (parts[0] == "Pair") i = 1;
44+
45+
const ticketID = TicketID.parseTicketID(parts[i] + " " + parts[i + 1]);
46+
const amount = parseInt(parts[i + 2]);
47+
if (amount) return { ticket: ticketID, amount };
48+
else throw Error(`Incorrect amount: ${parts[i + 2]}`);
49+
};
50+
2651
export default {
2752
ofDTO,
53+
toDTO,
54+
parseTicketAmount,
2855
};

deku-c/client/src/deku-p/core/ticket-id.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import JSONValue, { JSONType } from "../utils/json";
2+
import Address, { Address as AddressType } from "./address";
23

34
export type TicketID = {
4-
ticketer: string;
5+
ticketer: AddressType;
56
data: string;
67
};
78

@@ -25,18 +26,32 @@ const ofDTO = (json: JSONValue): TicketID | null => {
2526
return { ticketer, data };
2627
};
2728

28-
const ofString = (str: String): TicketID | null => {
29-
const split = str.split(" ");
29+
const toDTO = (ticket: TicketID) => {
30+
let data = ticket.data;
31+
if (data.startsWith("0x")) data = data.slice(2);
32+
33+
return [
34+
"Ticket_id",
35+
{
36+
ticketer: ticket.ticketer,
37+
data: data,
38+
},
39+
];
40+
};
41+
42+
const parseTicketID = (str: String): TicketID => {
43+
const split = str.split(" ").filter((x) => x);
3044
if (split.length != 2) {
3145
throw Error(`Incorrect argument for TicketID: ${str}`);
3246
}
3347

34-
// TODO test ticketer and data are valid
35-
return { ticketer: split[0], data: split[1] };
48+
// TODO test that data is valid
49+
return { ticketer: Address.parseAddress(split[0]), data: split[1] };
3650
};
3751

3852
export default {
3953
createTicketID,
4054
ofDTO,
41-
ofString,
55+
toDTO,
56+
parseTicketID,
4257
};

deku-c/client/src/deku-p/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,14 +357,14 @@ export class DekuPClient {
357357
return this.submitOperation(noopOperation);
358358
}
359359

360-
async wait(operationHash: OperationHashType): Promise<LevelType> {
361-
console.log(operationHash);
360+
async wait(_operationHash: OperationHashType): Promise<LevelType> {
362361
throw "Feature not yet implemented"; // TODO: implement this feature
363362
}
364363
}
365364

366-
export const parseTicketID = TicketID.ofString;
365+
export const parseTicketID = TicketID.parseTicketID;
367366
export const makeTicketID = TicketID.createTicketID;
367+
export const parseTicketAmount = Balances.parseTicketAmount;
368368
// TODO export type too?
369369

370370
export {

deku-c/client/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ export {
55
fromMemorySigner,
66
parseTicketID,
77
makeTicketID,
8+
parseTicketAmount,
89
} from "./deku-p";
910
export { DekuCClient, Contract } from "./deku-c";

deku-c/client/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"include": ["src/index.ts",],
2+
"include": ["src/index.ts"],
33
"exclude": ["node_modules", "**/*.spec.ts"],
44
"compilerOptions": {
55
"outDir": "dist",

deku-c/deku-cli/commands/invoke.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { fromMemorySigner } from "@marigold-dev/deku";
22
import { InMemorySigner } from "@taquito/signer";
3-
import { Contract, DekuCClient } from "@marigold-dev/deku";
3+
import { Contract, DekuCClient, parseTicketAmount } from "@marigold-dev/deku";
44
import { load } from "../core/wallet";
55
import * as Commander from "commander";
66
import { read, isLigo } from "../core/contract";
@@ -17,21 +17,28 @@ function getContract(apiUri, walletPath, contractAddress, ligoUri?) {
1717
return deku.contract(contractAddress);
1818
}
1919

20+
function parseTicketAmounts(args: string[]) {
21+
return args.map((str) => {
22+
return parseTicketAmount(str);
23+
});
24+
}
25+
2026
async function invokeMain(
2127
apiUri,
2228
walletPath,
2329
contractAddress,
2430
parameter,
31+
ticketAmounts,
2532
options
2633
) {
2734
try {
2835
const contract = getContract(apiUri, walletPath, contractAddress);
2936
if (options.raw !== undefined) {
3037
const parameter_parsed = JSON.parse(parameter);
31-
const hash = await contract.invokeRaw(parameter);
38+
const hash = await contract.invokeRaw(parameter, ticketAmounts);
3239
console.log("Operation hash:", hash);
3340
} else {
34-
const hash = await contract.invoke(parameter);
41+
const hash = await contract.invoke(parameter, ticketAmounts);
3542
console.log("operation hash:", hash);
3643
}
3744
} catch (e) {
@@ -88,8 +95,19 @@ export default function make(command: Commander.Command) {
8895
`URI of the deku API to use (default ${default_.api})`
8996
)
9097
.action((walletPath, contractAddress, parameter, options) => {
98+
const unparsedArguments = invoke.args.slice(3);
99+
console.log("UNPARSED:", unparsedArguments);
91100
const apiUri = options.endpoint ?? default_.api;
92-
invokeMain(apiUri, walletPath, contractAddress, parameter, options);
101+
const tickets = parseTicketAmounts(unparsedArguments);
102+
103+
invokeMain(
104+
apiUri,
105+
walletPath,
106+
contractAddress,
107+
parameter,
108+
tickets,
109+
options
110+
);
93111
});
94112

95113
invokeLigo

0 commit comments

Comments
 (0)