genlayer-js 0.4.7 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/index.cjs +94 -7
- package/dist/index.js +94 -7
- package/package.json +1 -1
- package/src/abi/calldata/consts.ts +14 -0
- package/src/abi/calldata/decoder.ts +86 -0
- package/src/abi/calldata/encoder.ts +92 -31
- package/src/contracts/actions.ts +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
## 0.4.8 (2024-12-18)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* added GenVM decoder to readContract method ([#42](https://github.com/yeagerai/genlayer-js/issues/42)) ([096d36d](https://github.com/yeagerai/genlayer-js/commit/096d36de06d3f4d341f6532ddead694c1882651d))
|
|
9
|
+
|
|
3
10
|
## 0.4.7 (2024-12-03)
|
|
4
11
|
|
|
5
12
|
## 0.4.6 (2024-12-02)
|
package/dist/index.cjs
CHANGED
|
@@ -35,8 +35,7 @@ function accountActions(client) {
|
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
// src/abi/calldata/
|
|
39
|
-
|
|
38
|
+
// src/abi/calldata/consts.ts
|
|
40
39
|
var BITS_IN_TYPE = 3;
|
|
41
40
|
var TYPE_SPECIAL = 0;
|
|
42
41
|
var TYPE_PINT = 1;
|
|
@@ -49,6 +48,92 @@ var SPECIAL_NULL = 0 << BITS_IN_TYPE | TYPE_SPECIAL;
|
|
|
49
48
|
var SPECIAL_FALSE = 1 << BITS_IN_TYPE | TYPE_SPECIAL;
|
|
50
49
|
var SPECIAL_TRUE = 2 << BITS_IN_TYPE | TYPE_SPECIAL;
|
|
51
50
|
var SPECIAL_ADDR = 3 << BITS_IN_TYPE | TYPE_SPECIAL;
|
|
51
|
+
|
|
52
|
+
// src/abi/calldata/decoder.ts
|
|
53
|
+
function readULeb128(data, index) {
|
|
54
|
+
let res = 0n;
|
|
55
|
+
let accum = 0n;
|
|
56
|
+
let shouldContinue = true;
|
|
57
|
+
while (shouldContinue) {
|
|
58
|
+
const byte = data[index.i];
|
|
59
|
+
index.i++;
|
|
60
|
+
const rest = byte & 127;
|
|
61
|
+
res += BigInt(rest) * (1n << accum);
|
|
62
|
+
accum += 7n;
|
|
63
|
+
shouldContinue = byte >= 128;
|
|
64
|
+
}
|
|
65
|
+
return res;
|
|
66
|
+
}
|
|
67
|
+
function decodeImpl(data, index) {
|
|
68
|
+
const cur = readULeb128(data, index);
|
|
69
|
+
switch (cur) {
|
|
70
|
+
case BigInt(SPECIAL_NULL):
|
|
71
|
+
return null;
|
|
72
|
+
case BigInt(SPECIAL_TRUE):
|
|
73
|
+
return true;
|
|
74
|
+
case BigInt(SPECIAL_FALSE):
|
|
75
|
+
return false;
|
|
76
|
+
case BigInt(SPECIAL_ADDR): {
|
|
77
|
+
const res = data.slice(index.i, index.i + 20);
|
|
78
|
+
index.i += 20;
|
|
79
|
+
return new (0, _chunkYI62SDKVcjs.Address)(res);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const type = Number(cur & 0xffn) & (1 << BITS_IN_TYPE) - 1;
|
|
83
|
+
const rest = cur >> BigInt(BITS_IN_TYPE);
|
|
84
|
+
switch (type) {
|
|
85
|
+
case TYPE_BYTES: {
|
|
86
|
+
const ret = data.slice(index.i, index.i + Number(rest));
|
|
87
|
+
index.i += Number(rest);
|
|
88
|
+
return ret;
|
|
89
|
+
}
|
|
90
|
+
case TYPE_PINT:
|
|
91
|
+
return rest;
|
|
92
|
+
case TYPE_NINT:
|
|
93
|
+
return -1n - rest;
|
|
94
|
+
case TYPE_STR: {
|
|
95
|
+
const ret = data.slice(index.i, index.i + Number(rest));
|
|
96
|
+
index.i += Number(rest);
|
|
97
|
+
return new TextDecoder("utf-8").decode(ret);
|
|
98
|
+
}
|
|
99
|
+
case TYPE_ARR: {
|
|
100
|
+
const ret = [];
|
|
101
|
+
let elems = rest;
|
|
102
|
+
while (elems > 0) {
|
|
103
|
+
elems--;
|
|
104
|
+
ret.push(decodeImpl(data, index));
|
|
105
|
+
}
|
|
106
|
+
return ret;
|
|
107
|
+
}
|
|
108
|
+
case TYPE_MAP: {
|
|
109
|
+
const ret = /* @__PURE__ */ new Map();
|
|
110
|
+
let elems = rest;
|
|
111
|
+
while (elems > 0) {
|
|
112
|
+
elems--;
|
|
113
|
+
const strLen = Number(readULeb128(data, index));
|
|
114
|
+
const key = data.slice(index.i, index.i + strLen);
|
|
115
|
+
index.i += strLen;
|
|
116
|
+
const keyStr = new TextDecoder("utf-8").decode(key);
|
|
117
|
+
ret.set(keyStr, decodeImpl(data, index));
|
|
118
|
+
}
|
|
119
|
+
return ret;
|
|
120
|
+
}
|
|
121
|
+
default:
|
|
122
|
+
throw new Error(`can't decode type from ${type} rest is ${rest} at pos ${index.i}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function decode(data) {
|
|
126
|
+
const index = { i: 0 };
|
|
127
|
+
const res = decodeImpl(data, index);
|
|
128
|
+
if (index.i !== data.length) {
|
|
129
|
+
throw new Error("some data left");
|
|
130
|
+
}
|
|
131
|
+
return res;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/abi/calldata/encoder.ts
|
|
135
|
+
|
|
136
|
+
|
|
52
137
|
function reportError(msg, data) {
|
|
53
138
|
throw new Error(`invalid calldata input '${data}'`);
|
|
54
139
|
}
|
|
@@ -162,10 +247,7 @@ function encodeImpl(to, data) {
|
|
|
162
247
|
to.push(c);
|
|
163
248
|
}
|
|
164
249
|
} else if (Object.getPrototypeOf(data) === Object.prototype) {
|
|
165
|
-
encodeMap(
|
|
166
|
-
to,
|
|
167
|
-
Object.keys(data).map((k) => [k, data[k]])
|
|
168
|
-
);
|
|
250
|
+
encodeMap(to, Object.entries(data));
|
|
169
251
|
} else {
|
|
170
252
|
reportError("unknown object type", data);
|
|
171
253
|
}
|
|
@@ -219,7 +301,12 @@ var overrideContractActions = (client) => {
|
|
|
219
301
|
method: "eth_call",
|
|
220
302
|
params: [requestParams, "latest"]
|
|
221
303
|
});
|
|
222
|
-
|
|
304
|
+
if (typeof result === "string") {
|
|
305
|
+
const val = Uint8Array.from(atob(result), (c) => c.charCodeAt(0));
|
|
306
|
+
return decode(val);
|
|
307
|
+
} else {
|
|
308
|
+
return "<unknown>";
|
|
309
|
+
}
|
|
223
310
|
};
|
|
224
311
|
client.writeContract = async (args) => {
|
|
225
312
|
const { account, address, functionName, args: params, value = 0n, leaderOnly = false } = args;
|
package/dist/index.js
CHANGED
|
@@ -35,8 +35,7 @@ function accountActions(client) {
|
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
// src/abi/calldata/
|
|
39
|
-
import { toHex, toRlp } from "viem";
|
|
38
|
+
// src/abi/calldata/consts.ts
|
|
40
39
|
var BITS_IN_TYPE = 3;
|
|
41
40
|
var TYPE_SPECIAL = 0;
|
|
42
41
|
var TYPE_PINT = 1;
|
|
@@ -49,6 +48,92 @@ var SPECIAL_NULL = 0 << BITS_IN_TYPE | TYPE_SPECIAL;
|
|
|
49
48
|
var SPECIAL_FALSE = 1 << BITS_IN_TYPE | TYPE_SPECIAL;
|
|
50
49
|
var SPECIAL_TRUE = 2 << BITS_IN_TYPE | TYPE_SPECIAL;
|
|
51
50
|
var SPECIAL_ADDR = 3 << BITS_IN_TYPE | TYPE_SPECIAL;
|
|
51
|
+
|
|
52
|
+
// src/abi/calldata/decoder.ts
|
|
53
|
+
function readULeb128(data, index) {
|
|
54
|
+
let res = 0n;
|
|
55
|
+
let accum = 0n;
|
|
56
|
+
let shouldContinue = true;
|
|
57
|
+
while (shouldContinue) {
|
|
58
|
+
const byte = data[index.i];
|
|
59
|
+
index.i++;
|
|
60
|
+
const rest = byte & 127;
|
|
61
|
+
res += BigInt(rest) * (1n << accum);
|
|
62
|
+
accum += 7n;
|
|
63
|
+
shouldContinue = byte >= 128;
|
|
64
|
+
}
|
|
65
|
+
return res;
|
|
66
|
+
}
|
|
67
|
+
function decodeImpl(data, index) {
|
|
68
|
+
const cur = readULeb128(data, index);
|
|
69
|
+
switch (cur) {
|
|
70
|
+
case BigInt(SPECIAL_NULL):
|
|
71
|
+
return null;
|
|
72
|
+
case BigInt(SPECIAL_TRUE):
|
|
73
|
+
return true;
|
|
74
|
+
case BigInt(SPECIAL_FALSE):
|
|
75
|
+
return false;
|
|
76
|
+
case BigInt(SPECIAL_ADDR): {
|
|
77
|
+
const res = data.slice(index.i, index.i + 20);
|
|
78
|
+
index.i += 20;
|
|
79
|
+
return new Address(res);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const type = Number(cur & 0xffn) & (1 << BITS_IN_TYPE) - 1;
|
|
83
|
+
const rest = cur >> BigInt(BITS_IN_TYPE);
|
|
84
|
+
switch (type) {
|
|
85
|
+
case TYPE_BYTES: {
|
|
86
|
+
const ret = data.slice(index.i, index.i + Number(rest));
|
|
87
|
+
index.i += Number(rest);
|
|
88
|
+
return ret;
|
|
89
|
+
}
|
|
90
|
+
case TYPE_PINT:
|
|
91
|
+
return rest;
|
|
92
|
+
case TYPE_NINT:
|
|
93
|
+
return -1n - rest;
|
|
94
|
+
case TYPE_STR: {
|
|
95
|
+
const ret = data.slice(index.i, index.i + Number(rest));
|
|
96
|
+
index.i += Number(rest);
|
|
97
|
+
return new TextDecoder("utf-8").decode(ret);
|
|
98
|
+
}
|
|
99
|
+
case TYPE_ARR: {
|
|
100
|
+
const ret = [];
|
|
101
|
+
let elems = rest;
|
|
102
|
+
while (elems > 0) {
|
|
103
|
+
elems--;
|
|
104
|
+
ret.push(decodeImpl(data, index));
|
|
105
|
+
}
|
|
106
|
+
return ret;
|
|
107
|
+
}
|
|
108
|
+
case TYPE_MAP: {
|
|
109
|
+
const ret = /* @__PURE__ */ new Map();
|
|
110
|
+
let elems = rest;
|
|
111
|
+
while (elems > 0) {
|
|
112
|
+
elems--;
|
|
113
|
+
const strLen = Number(readULeb128(data, index));
|
|
114
|
+
const key = data.slice(index.i, index.i + strLen);
|
|
115
|
+
index.i += strLen;
|
|
116
|
+
const keyStr = new TextDecoder("utf-8").decode(key);
|
|
117
|
+
ret.set(keyStr, decodeImpl(data, index));
|
|
118
|
+
}
|
|
119
|
+
return ret;
|
|
120
|
+
}
|
|
121
|
+
default:
|
|
122
|
+
throw new Error(`can't decode type from ${type} rest is ${rest} at pos ${index.i}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function decode(data) {
|
|
126
|
+
const index = { i: 0 };
|
|
127
|
+
const res = decodeImpl(data, index);
|
|
128
|
+
if (index.i !== data.length) {
|
|
129
|
+
throw new Error("some data left");
|
|
130
|
+
}
|
|
131
|
+
return res;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/abi/calldata/encoder.ts
|
|
135
|
+
import { toHex } from "viem";
|
|
136
|
+
import { toRlp } from "viem";
|
|
52
137
|
function reportError(msg, data) {
|
|
53
138
|
throw new Error(`invalid calldata input '${data}'`);
|
|
54
139
|
}
|
|
@@ -162,10 +247,7 @@ function encodeImpl(to, data) {
|
|
|
162
247
|
to.push(c);
|
|
163
248
|
}
|
|
164
249
|
} else if (Object.getPrototypeOf(data) === Object.prototype) {
|
|
165
|
-
encodeMap(
|
|
166
|
-
to,
|
|
167
|
-
Object.keys(data).map((k) => [k, data[k]])
|
|
168
|
-
);
|
|
250
|
+
encodeMap(to, Object.entries(data));
|
|
169
251
|
} else {
|
|
170
252
|
reportError("unknown object type", data);
|
|
171
253
|
}
|
|
@@ -219,7 +301,12 @@ var overrideContractActions = (client) => {
|
|
|
219
301
|
method: "eth_call",
|
|
220
302
|
params: [requestParams, "latest"]
|
|
221
303
|
});
|
|
222
|
-
|
|
304
|
+
if (typeof result === "string") {
|
|
305
|
+
const val = Uint8Array.from(atob(result), (c) => c.charCodeAt(0));
|
|
306
|
+
return decode(val);
|
|
307
|
+
} else {
|
|
308
|
+
return "<unknown>";
|
|
309
|
+
}
|
|
223
310
|
};
|
|
224
311
|
client.writeContract = async (args) => {
|
|
225
312
|
const { account, address, functionName, args: params, value = 0n, leaderOnly = false } = args;
|
package/package.json
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const BITS_IN_TYPE = 3;
|
|
2
|
+
|
|
3
|
+
export const TYPE_SPECIAL = 0;
|
|
4
|
+
export const TYPE_PINT = 1;
|
|
5
|
+
export const TYPE_NINT = 2;
|
|
6
|
+
export const TYPE_BYTES = 3;
|
|
7
|
+
export const TYPE_STR = 4;
|
|
8
|
+
export const TYPE_ARR = 5;
|
|
9
|
+
export const TYPE_MAP = 6;
|
|
10
|
+
|
|
11
|
+
export const SPECIAL_NULL = (0 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
12
|
+
export const SPECIAL_FALSE = (1 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
13
|
+
export const SPECIAL_TRUE = (2 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
14
|
+
export const SPECIAL_ADDR = (3 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type {CalldataEncodable} from "../../types/calldata";
|
|
2
|
+
import {Address} from "../../types/calldata";
|
|
3
|
+
import * as consts from "./consts";
|
|
4
|
+
|
|
5
|
+
function readULeb128(data: Uint8Array, index: {i: number}): bigint {
|
|
6
|
+
let res: bigint = 0n;
|
|
7
|
+
let accum = 0n;
|
|
8
|
+
let shouldContinue = true;
|
|
9
|
+
while (shouldContinue) {
|
|
10
|
+
const byte = data[index.i];
|
|
11
|
+
index.i++;
|
|
12
|
+
const rest = byte & 0x7f;
|
|
13
|
+
res += BigInt(rest) * (1n << accum);
|
|
14
|
+
accum += 7n;
|
|
15
|
+
shouldContinue = byte >= 128;
|
|
16
|
+
}
|
|
17
|
+
return res;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function decodeImpl(data: Uint8Array, index: {i: number}): CalldataEncodable {
|
|
21
|
+
const cur = readULeb128(data, index);
|
|
22
|
+
switch (cur) {
|
|
23
|
+
case BigInt(consts.SPECIAL_NULL):
|
|
24
|
+
return null;
|
|
25
|
+
case BigInt(consts.SPECIAL_TRUE):
|
|
26
|
+
return true;
|
|
27
|
+
case BigInt(consts.SPECIAL_FALSE):
|
|
28
|
+
return false;
|
|
29
|
+
case BigInt(consts.SPECIAL_ADDR): {
|
|
30
|
+
const res = data.slice(index.i, index.i + 20);
|
|
31
|
+
index.i += 20;
|
|
32
|
+
return new Address(res);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const type = Number(cur & 0xffn) & ((1 << consts.BITS_IN_TYPE) - 1);
|
|
36
|
+
const rest = cur >> BigInt(consts.BITS_IN_TYPE);
|
|
37
|
+
switch (type) {
|
|
38
|
+
case consts.TYPE_BYTES: {
|
|
39
|
+
const ret = data.slice(index.i, index.i + Number(rest));
|
|
40
|
+
index.i += Number(rest);
|
|
41
|
+
return ret;
|
|
42
|
+
}
|
|
43
|
+
case consts.TYPE_PINT:
|
|
44
|
+
return rest;
|
|
45
|
+
case consts.TYPE_NINT:
|
|
46
|
+
return -1n - rest;
|
|
47
|
+
case consts.TYPE_STR: {
|
|
48
|
+
const ret = data.slice(index.i, index.i + Number(rest));
|
|
49
|
+
index.i += Number(rest);
|
|
50
|
+
return new TextDecoder("utf-8").decode(ret);
|
|
51
|
+
}
|
|
52
|
+
case consts.TYPE_ARR: {
|
|
53
|
+
const ret = [] as CalldataEncodable[];
|
|
54
|
+
let elems = rest;
|
|
55
|
+
while (elems > 0) {
|
|
56
|
+
elems--;
|
|
57
|
+
ret.push(decodeImpl(data, index));
|
|
58
|
+
}
|
|
59
|
+
return ret;
|
|
60
|
+
}
|
|
61
|
+
case consts.TYPE_MAP: {
|
|
62
|
+
const ret = new Map<string, CalldataEncodable>();
|
|
63
|
+
let elems = rest;
|
|
64
|
+
while (elems > 0) {
|
|
65
|
+
elems--;
|
|
66
|
+
const strLen = Number(readULeb128(data, index));
|
|
67
|
+
const key = data.slice(index.i, index.i + strLen);
|
|
68
|
+
index.i += strLen;
|
|
69
|
+
const keyStr = new TextDecoder("utf-8").decode(key);
|
|
70
|
+
ret.set(keyStr, decodeImpl(data, index));
|
|
71
|
+
}
|
|
72
|
+
return ret;
|
|
73
|
+
}
|
|
74
|
+
default:
|
|
75
|
+
throw new Error(`can't decode type from ${type} rest is ${rest} at pos ${index.i}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function decode(data: Uint8Array): CalldataEncodable {
|
|
80
|
+
const index = {i: 0};
|
|
81
|
+
const res = decodeImpl(data, index);
|
|
82
|
+
if (index.i !== data.length) {
|
|
83
|
+
throw new Error("some data left");
|
|
84
|
+
}
|
|
85
|
+
return res;
|
|
86
|
+
}
|
|
@@ -1,21 +1,8 @@
|
|
|
1
|
-
import {toHex
|
|
1
|
+
import {toHex} from "viem";
|
|
2
|
+
import {toRlp} from "viem";
|
|
2
3
|
import type {CalldataEncodable, TransactionDataElement} from "../../types/calldata";
|
|
3
4
|
import {Address} from "../../types/calldata";
|
|
4
|
-
|
|
5
|
-
const BITS_IN_TYPE = 3;
|
|
6
|
-
|
|
7
|
-
const TYPE_SPECIAL = 0;
|
|
8
|
-
const TYPE_PINT = 1;
|
|
9
|
-
const TYPE_NINT = 2;
|
|
10
|
-
const TYPE_BYTES = 3;
|
|
11
|
-
const TYPE_STR = 4;
|
|
12
|
-
const TYPE_ARR = 5;
|
|
13
|
-
const TYPE_MAP = 6;
|
|
14
|
-
|
|
15
|
-
const SPECIAL_NULL = (0 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
16
|
-
const SPECIAL_FALSE = (1 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
17
|
-
const SPECIAL_TRUE = (2 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
18
|
-
const SPECIAL_ADDR = (3 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
5
|
+
import * as consts from "./consts";
|
|
19
6
|
|
|
20
7
|
function reportError(msg: string, data: CalldataEncodable): never {
|
|
21
8
|
throw new Error(`invalid calldata input '${data}'`);
|
|
@@ -37,15 +24,15 @@ function writeNum(to: number[], data: bigint) {
|
|
|
37
24
|
}
|
|
38
25
|
|
|
39
26
|
function encodeNumWithType(to: number[], data: bigint, type: number) {
|
|
40
|
-
const res = (data << BigInt(BITS_IN_TYPE)) | BigInt(type);
|
|
27
|
+
const res = (data << BigInt(consts.BITS_IN_TYPE)) | BigInt(type);
|
|
41
28
|
writeNum(to, res);
|
|
42
29
|
}
|
|
43
30
|
|
|
44
31
|
function encodeNum(to: number[], data: bigint) {
|
|
45
32
|
if (data >= 0n) {
|
|
46
|
-
encodeNumWithType(to, data, TYPE_PINT);
|
|
33
|
+
encodeNumWithType(to, data, consts.TYPE_PINT);
|
|
47
34
|
} else {
|
|
48
|
-
encodeNumWithType(to, -data - 1n, TYPE_NINT);
|
|
35
|
+
encodeNumWithType(to, -data - 1n, consts.TYPE_NINT);
|
|
49
36
|
}
|
|
50
37
|
}
|
|
51
38
|
|
|
@@ -76,7 +63,7 @@ function encodeMap(to: number[], arr: Iterable<[string, CalldataEncodable]>) {
|
|
|
76
63
|
}
|
|
77
64
|
}
|
|
78
65
|
|
|
79
|
-
encodeNumWithType(to, BigInt(newEntries.length), TYPE_MAP);
|
|
66
|
+
encodeNumWithType(to, BigInt(newEntries.length), consts.TYPE_MAP);
|
|
80
67
|
for (const [, k, v] of newEntries) {
|
|
81
68
|
writeNum(to, BigInt(k.length));
|
|
82
69
|
for (const c of k) {
|
|
@@ -88,15 +75,15 @@ function encodeMap(to: number[], arr: Iterable<[string, CalldataEncodable]>) {
|
|
|
88
75
|
|
|
89
76
|
function encodeImpl(to: number[], data: CalldataEncodable) {
|
|
90
77
|
if (data === null || data === undefined) {
|
|
91
|
-
to.push(SPECIAL_NULL);
|
|
78
|
+
to.push(consts.SPECIAL_NULL);
|
|
92
79
|
return;
|
|
93
80
|
}
|
|
94
81
|
if (data === true) {
|
|
95
|
-
to.push(SPECIAL_TRUE);
|
|
82
|
+
to.push(consts.SPECIAL_TRUE);
|
|
96
83
|
return;
|
|
97
84
|
}
|
|
98
85
|
if (data === false) {
|
|
99
|
-
to.push(SPECIAL_FALSE);
|
|
86
|
+
to.push(consts.SPECIAL_FALSE);
|
|
100
87
|
return;
|
|
101
88
|
}
|
|
102
89
|
switch (typeof data) {
|
|
@@ -113,7 +100,7 @@ function encodeImpl(to: number[], data: CalldataEncodable) {
|
|
|
113
100
|
}
|
|
114
101
|
case "string": {
|
|
115
102
|
const str = new TextEncoder().encode(data);
|
|
116
|
-
encodeNumWithType(to, BigInt(str.length), TYPE_STR);
|
|
103
|
+
encodeNumWithType(to, BigInt(str.length), consts.TYPE_STR);
|
|
117
104
|
for (const c of str) {
|
|
118
105
|
to.push(c);
|
|
119
106
|
}
|
|
@@ -121,27 +108,24 @@ function encodeImpl(to: number[], data: CalldataEncodable) {
|
|
|
121
108
|
}
|
|
122
109
|
case "object": {
|
|
123
110
|
if (data instanceof Uint8Array) {
|
|
124
|
-
encodeNumWithType(to, BigInt(data.length), TYPE_BYTES);
|
|
111
|
+
encodeNumWithType(to, BigInt(data.length), consts.TYPE_BYTES);
|
|
125
112
|
for (const c of data) {
|
|
126
113
|
to.push(c);
|
|
127
114
|
}
|
|
128
115
|
} else if (data instanceof Array) {
|
|
129
|
-
encodeNumWithType(to, BigInt(data.length), TYPE_ARR);
|
|
116
|
+
encodeNumWithType(to, BigInt(data.length), consts.TYPE_ARR);
|
|
130
117
|
for (const c of data) {
|
|
131
118
|
encodeImpl(to, c);
|
|
132
119
|
}
|
|
133
120
|
} else if (data instanceof Map) {
|
|
134
121
|
encodeMap(to, data);
|
|
135
122
|
} else if (data instanceof Address) {
|
|
136
|
-
to.push(SPECIAL_ADDR);
|
|
123
|
+
to.push(consts.SPECIAL_ADDR);
|
|
137
124
|
for (const c of data.bytes) {
|
|
138
125
|
to.push(c);
|
|
139
126
|
}
|
|
140
127
|
} else if (Object.getPrototypeOf(data) === Object.prototype) {
|
|
141
|
-
encodeMap(
|
|
142
|
-
to,
|
|
143
|
-
Object.keys(data).map((k): [string, CalldataEncodable] => [k, data[k]]),
|
|
144
|
-
);
|
|
128
|
+
encodeMap(to, Object.entries(data));
|
|
145
129
|
} else {
|
|
146
130
|
reportError("unknown object type", data);
|
|
147
131
|
}
|
|
@@ -159,6 +143,83 @@ export function encode(data: CalldataEncodable): Uint8Array {
|
|
|
159
143
|
return new Uint8Array(arr);
|
|
160
144
|
}
|
|
161
145
|
|
|
146
|
+
function toStringImplMap(data: Iterable<[string, CalldataEncodable]>, to: string[]) {
|
|
147
|
+
to.push("{");
|
|
148
|
+
for (const [k, v] of data) {
|
|
149
|
+
to.push(JSON.stringify(k));
|
|
150
|
+
to.push(":");
|
|
151
|
+
toStringImpl(v, to);
|
|
152
|
+
}
|
|
153
|
+
to.push("}");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function toStringImpl(data: CalldataEncodable, to: string[]) {
|
|
157
|
+
if (data === null || data === undefined) {
|
|
158
|
+
to.push("null");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (data === true) {
|
|
162
|
+
to.push("true");
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (data === false) {
|
|
166
|
+
to.push("false");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
switch (typeof data) {
|
|
170
|
+
case "number": {
|
|
171
|
+
if (!Number.isInteger(data)) {
|
|
172
|
+
reportError("floats are not supported", data);
|
|
173
|
+
}
|
|
174
|
+
to.push(data.toString());
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
case "bigint": {
|
|
178
|
+
to.push(data.toString());
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
case "string": {
|
|
182
|
+
to.push(JSON.stringify(data));
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
case "object": {
|
|
186
|
+
if (data instanceof Uint8Array) {
|
|
187
|
+
to.push("b#");
|
|
188
|
+
for (const b of data) {
|
|
189
|
+
to.push(b.toString(16));
|
|
190
|
+
}
|
|
191
|
+
} else if (data instanceof Array) {
|
|
192
|
+
to.push("[");
|
|
193
|
+
for (const c of data) {
|
|
194
|
+
toStringImpl(c, to);
|
|
195
|
+
to.push(",");
|
|
196
|
+
}
|
|
197
|
+
to.push("]");
|
|
198
|
+
} else if (data instanceof Map) {
|
|
199
|
+
toStringImplMap(data.entries(), to);
|
|
200
|
+
} else if (data instanceof Address) {
|
|
201
|
+
to.push("addr#");
|
|
202
|
+
for (const c of data.bytes) {
|
|
203
|
+
to.push(c.toString(16));
|
|
204
|
+
}
|
|
205
|
+
} else if (Object.getPrototypeOf(data) === Object.prototype) {
|
|
206
|
+
toStringImplMap(Object.entries(data), to);
|
|
207
|
+
} else {
|
|
208
|
+
reportError("unknown object type", data);
|
|
209
|
+
}
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
default:
|
|
213
|
+
reportError("unknown base type", data);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function toString(data: CalldataEncodable): string {
|
|
218
|
+
const to: string[] = [];
|
|
219
|
+
toStringImpl(data, to);
|
|
220
|
+
return to.join("");
|
|
221
|
+
}
|
|
222
|
+
|
|
162
223
|
export function serialize(data: TransactionDataElement[]): `0x${string}` {
|
|
163
224
|
return toRlp(data.map(param => toHex(param)));
|
|
164
225
|
}
|
package/src/contracts/actions.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {decode} from "@/abi/calldata/decoder";
|
|
1
2
|
import {encode, serialize, encodeAndSerialize} from "@/abi/calldata/encoder";
|
|
2
3
|
import {Account, ContractSchema, SimulatorChain, GenLayerClient, CalldataEncodable, Address} from "@/types";
|
|
3
4
|
|
|
@@ -39,7 +40,13 @@ export const overrideContractActions = (client: GenLayerClient<SimulatorChain>)
|
|
|
39
40
|
method: "eth_call",
|
|
40
41
|
params: [requestParams, "latest"],
|
|
41
42
|
});
|
|
42
|
-
|
|
43
|
+
|
|
44
|
+
if (typeof result === "string") {
|
|
45
|
+
const val = Uint8Array.from(atob(result), c => c.charCodeAt(0));
|
|
46
|
+
return decode(val);
|
|
47
|
+
} else {
|
|
48
|
+
return "<unknown>";
|
|
49
|
+
}
|
|
43
50
|
};
|
|
44
51
|
|
|
45
52
|
client.writeContract = async (args: {
|