@xelis/sdk 0.11.15 → 0.11.17
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/dist/cjs/address/bech32.js +47 -56
- package/dist/cjs/address/index.js +20 -21
- package/dist/cjs/config.js +26 -38
- package/dist/cjs/contract/contract.js +178 -0
- package/dist/cjs/contract/typed_contract.js +259 -0
- package/dist/cjs/contract/xvm_serializer.js +170 -0
- package/dist/cjs/daemon/rpc.js +157 -168
- package/dist/cjs/daemon/types.js +4 -1
- package/dist/cjs/daemon/websocket.js +170 -181
- package/dist/cjs/data/element.js +39 -41
- package/dist/cjs/data/value.js +106 -111
- package/dist/cjs/react/daemon.js +33 -43
- package/dist/cjs/rpc/http.js +75 -132
- package/dist/cjs/rpc/parse_json/parse_json.js +4 -4
- package/dist/cjs/rpc/types.js +1 -1
- package/dist/cjs/rpc/websocket.js +131 -201
- package/dist/cjs/wallet/rpc.js +98 -117
- package/dist/cjs/wallet/types.js +1 -1
- package/dist/cjs/wallet/websocket.js +105 -126
- package/dist/cjs/xswd/relayer/app.js +57 -36
- package/dist/cjs/xswd/relayer/index.js +25 -27
- package/dist/cjs/xswd/types.js +1 -1
- package/dist/cjs/xswd/websocket.js +15 -33
- package/dist/esm/address/bech32.js +46 -55
- package/dist/esm/address/index.js +16 -17
- package/dist/esm/config.js +25 -37
- package/dist/esm/contract/contract.js +172 -0
- package/dist/esm/contract/typed_contract.js +251 -0
- package/dist/esm/contract/xvm_serializer.js +163 -0
- package/dist/esm/daemon/rpc.js +153 -165
- package/dist/esm/daemon/types.js +3 -0
- package/dist/esm/daemon/websocket.js +166 -179
- package/dist/esm/data/element.js +37 -40
- package/dist/esm/data/value.js +104 -112
- package/dist/esm/react/daemon.js +30 -40
- package/dist/esm/rpc/http.js +73 -131
- package/dist/esm/rpc/parse_json/parse_json.js +1 -1
- package/dist/esm/rpc/websocket.js +126 -197
- package/dist/esm/wallet/rpc.js +93 -113
- package/dist/esm/wallet/websocket.js +101 -124
- package/dist/esm/xswd/relayer/app.js +54 -34
- package/dist/esm/xswd/relayer/index.js +22 -24
- package/dist/esm/xswd/websocket.js +10 -29
- package/dist/types/contract/contract.d.ts +80 -0
- package/dist/types/contract/typed_contract.d.ts +94 -0
- package/dist/types/contract/xvm_serializer.d.ts +69 -0
- package/dist/types/daemon/rpc.d.ts +5 -2
- package/dist/types/daemon/types.d.ts +97 -18
- package/dist/types/daemon/websocket.d.ts +5 -2
- package/package.json +1 -1
|
@@ -1,44 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
4
|
-
if (ar || !(i in from)) {
|
|
5
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
6
|
-
ar[i] = from[i];
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
|
-
};
|
|
11
|
-
exports.__esModule = true;
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.encode = exports.decode = exports.convertBits = void 0;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
const CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
5
|
+
const GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
|
|
6
|
+
const SEPARTOR = ":";
|
|
16
7
|
var ErrHrpMixCase = "mix case is not allowed in human readable part";
|
|
17
8
|
var ErrInvalidChecksum = "invalid checksum";
|
|
18
9
|
var ErrNonZeroPadding = "non zero padding";
|
|
19
10
|
var ErrIllegalZeroPadding = "illegal zero padding";
|
|
20
11
|
var ErrHrpEmpty = "human readable part is empty";
|
|
21
12
|
function ErrSeparatorInvalidPosition(pos) {
|
|
22
|
-
return
|
|
13
|
+
return `invalid separator position: ${pos}`;
|
|
23
14
|
}
|
|
24
15
|
function ErrHrpInvalidCharacter(c) {
|
|
25
|
-
return
|
|
16
|
+
return `invalid character value in human readable part: ${c}`;
|
|
26
17
|
}
|
|
27
18
|
function ErrInvalidIndex(index) {
|
|
28
|
-
return
|
|
19
|
+
return `invalid index ${index}`;
|
|
29
20
|
}
|
|
30
21
|
function ErrInvalidValue(value, max) {
|
|
31
|
-
return
|
|
22
|
+
return `invalid value: ${value}, max is ${max}`;
|
|
32
23
|
}
|
|
33
24
|
function ErrInvalidDataRange(value, from) {
|
|
34
|
-
return
|
|
25
|
+
return `invalid data range: ${value}, max is ${from}`;
|
|
35
26
|
}
|
|
36
27
|
function polymod(values) {
|
|
37
|
-
|
|
38
|
-
values.forEach(
|
|
39
|
-
|
|
28
|
+
let chk = 1;
|
|
29
|
+
values.forEach((value) => {
|
|
30
|
+
let top = chk >> 25;
|
|
40
31
|
chk = ((chk & 0x1ffffff) << 5) ^ value;
|
|
41
|
-
GENERATOR.forEach(
|
|
32
|
+
GENERATOR.forEach((item, i) => {
|
|
42
33
|
if (((top >> i) & 1) === 1) {
|
|
43
34
|
chk ^= item;
|
|
44
35
|
}
|
|
@@ -47,34 +38,34 @@ function polymod(values) {
|
|
|
47
38
|
return chk;
|
|
48
39
|
}
|
|
49
40
|
function hrpExpand(hrp) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
bytes.forEach(
|
|
41
|
+
let encoder = new TextEncoder();
|
|
42
|
+
let bytes = encoder.encode(hrp);
|
|
43
|
+
let result = [];
|
|
44
|
+
bytes.forEach((c) => result.push(c >> 5));
|
|
54
45
|
result.push(0);
|
|
55
|
-
bytes.forEach(
|
|
46
|
+
bytes.forEach((c) => result.push(c & 31));
|
|
56
47
|
return result;
|
|
57
48
|
}
|
|
58
49
|
function verifyChecksum(hrp, data) {
|
|
59
|
-
|
|
60
|
-
vec =
|
|
50
|
+
let vec = hrpExpand(hrp);
|
|
51
|
+
vec = [...vec, ...data];
|
|
61
52
|
return polymod(vec) === 1;
|
|
62
53
|
}
|
|
63
54
|
function createChecksum(hrp, data) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
for (
|
|
55
|
+
let result = [0, 0, 0, 0, 0, 0];
|
|
56
|
+
let values = [...hrpExpand(hrp), ...data, ...result];
|
|
57
|
+
let pm = polymod(values) ^ 1;
|
|
58
|
+
for (let i = 0; i < 6; i++) {
|
|
68
59
|
result[i] = pm >> (5 * (5 - i)) & 31;
|
|
69
60
|
}
|
|
70
61
|
return result;
|
|
71
62
|
}
|
|
72
63
|
function convertBits(data, from, to, pad) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
data.forEach(
|
|
64
|
+
let result = [];
|
|
65
|
+
let acc = 0;
|
|
66
|
+
let bits = 0;
|
|
67
|
+
let maxValue = (1 << to) - 1;
|
|
68
|
+
data.forEach((value) => {
|
|
78
69
|
if (value >> from !== 0) {
|
|
79
70
|
throw ErrInvalidDataRange(value, from);
|
|
80
71
|
}
|
|
@@ -103,25 +94,25 @@ function decode(bech) {
|
|
|
103
94
|
if (bech.toUpperCase() !== bech && bech.toLowerCase() !== bech) {
|
|
104
95
|
throw ErrHrpMixCase;
|
|
105
96
|
}
|
|
106
|
-
|
|
97
|
+
let pos = bech.indexOf(SEPARTOR);
|
|
107
98
|
if (pos < 1 || pos + 7 > bech.length) {
|
|
108
99
|
throw ErrSeparatorInvalidPosition(pos);
|
|
109
100
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
hrpBytes.forEach(
|
|
101
|
+
let hrp = bech.substring(0, pos);
|
|
102
|
+
let encoder = new TextEncoder();
|
|
103
|
+
let hrpBytes = encoder.encode(hrp);
|
|
104
|
+
let decoded = [];
|
|
105
|
+
hrpBytes.forEach((value) => {
|
|
115
106
|
if (value < 33 || value > 126) {
|
|
116
107
|
throw ErrHrpInvalidCharacter(value);
|
|
117
108
|
}
|
|
118
109
|
});
|
|
119
|
-
for (
|
|
110
|
+
for (let i = pos + 1; i < bech.length; i++) {
|
|
120
111
|
if (i >= bech.length) {
|
|
121
112
|
throw ErrInvalidIndex(i);
|
|
122
113
|
}
|
|
123
|
-
|
|
124
|
-
|
|
114
|
+
let c = bech[i];
|
|
115
|
+
let index = CHARSET.indexOf(c);
|
|
125
116
|
if (index === -1) {
|
|
126
117
|
throw ErrHrpInvalidCharacter;
|
|
127
118
|
}
|
|
@@ -131,16 +122,16 @@ function decode(bech) {
|
|
|
131
122
|
throw ErrInvalidChecksum;
|
|
132
123
|
}
|
|
133
124
|
decoded.splice(decoded.length - 6, 6);
|
|
134
|
-
return { hrp
|
|
125
|
+
return { hrp, decoded };
|
|
135
126
|
}
|
|
136
127
|
exports.decode = decode;
|
|
137
128
|
function encode(hrp, data) {
|
|
138
129
|
if (hrp.length === 0) {
|
|
139
130
|
throw ErrHrpEmpty;
|
|
140
131
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
hrpBytes.forEach(
|
|
132
|
+
let encoder = new TextEncoder();
|
|
133
|
+
let hrpBytes = encoder.encode(hrp);
|
|
134
|
+
hrpBytes.forEach((value) => {
|
|
144
135
|
if (value < 33 || value > 126) {
|
|
145
136
|
throw ErrHrpInvalidCharacter(value);
|
|
146
137
|
}
|
|
@@ -149,19 +140,19 @@ function encode(hrp, data) {
|
|
|
149
140
|
throw ErrHrpMixCase;
|
|
150
141
|
}
|
|
151
142
|
hrp = hrp.toLowerCase();
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
combined.forEach(
|
|
143
|
+
let combined = [...data, ...createChecksum(hrp, data)];
|
|
144
|
+
let result = [...Array.from(hrpBytes), SEPARTOR.charCodeAt(0)];
|
|
145
|
+
combined.forEach((index) => {
|
|
155
146
|
if (index > CHARSET.length) {
|
|
156
147
|
throw ErrInvalidValue(index, CHARSET.length);
|
|
157
148
|
}
|
|
158
|
-
|
|
149
|
+
let value = CHARSET.charCodeAt(index);
|
|
159
150
|
if (!value) {
|
|
160
151
|
throw ErrInvalidIndex(index);
|
|
161
152
|
}
|
|
162
153
|
result.push(value);
|
|
163
154
|
});
|
|
164
|
-
|
|
155
|
+
let decoder = new TextDecoder();
|
|
165
156
|
return decoder.decode(new Uint8Array(result));
|
|
166
157
|
}
|
|
167
158
|
exports.encode = encode;
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
exports
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const bech32_1 = require("./bech32");
|
|
4
|
+
const value_1 = require("../data/value");
|
|
5
5
|
var PrefixAddress = "xel";
|
|
6
6
|
var TestnetPrefixAddress = "xet";
|
|
7
7
|
var ExtraDataLimit = 1024;
|
|
8
8
|
var ErrIntegratedDataLimit = "invalid data in integrated address, maximum size reached";
|
|
9
9
|
var ErrInvalidNetworkPrefix = "invalid network prefix (xel or xet)";
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
class Address {
|
|
11
|
+
constructor(data, hrp) {
|
|
12
12
|
this.isMainnet = hrp === PrefixAddress;
|
|
13
13
|
this.publicKey = Array.from(data);
|
|
14
14
|
switch (data[32]) {
|
|
15
15
|
case 1:
|
|
16
16
|
this.isIntegrated = true;
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
let extraData = new Uint8Array(this.publicKey.slice(33));
|
|
18
|
+
let reader = new value_1.ValueReader(extraData);
|
|
19
19
|
this.extraData = reader.read();
|
|
20
20
|
break;
|
|
21
21
|
case 0:
|
|
@@ -25,31 +25,30 @@ var Address = /** @class */ (function () {
|
|
|
25
25
|
throw "invalid address type";
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
static fromString(addr) {
|
|
29
|
+
let { hrp, decoded } = (0, bech32_1.decode)(addr);
|
|
30
30
|
if (hrp !== PrefixAddress && hrp !== TestnetPrefixAddress) {
|
|
31
31
|
throw ErrInvalidNetworkPrefix;
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
let bits = (0, bech32_1.convertBits)(decoded, 5, 8, false);
|
|
34
34
|
return new Address(bits, hrp);
|
|
35
|
-
}
|
|
36
|
-
|
|
35
|
+
}
|
|
36
|
+
static isValid(addr) {
|
|
37
37
|
try {
|
|
38
38
|
Address.fromString(addr);
|
|
39
39
|
return true;
|
|
40
40
|
}
|
|
41
|
-
catch
|
|
41
|
+
catch {
|
|
42
42
|
return false;
|
|
43
43
|
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
}
|
|
45
|
+
format() {
|
|
46
|
+
let bits = (0, bech32_1.convertBits)(this.publicKey, 8, 5, true);
|
|
47
|
+
let hrp = PrefixAddress;
|
|
48
48
|
if (!this.isMainnet) {
|
|
49
49
|
hrp = TestnetPrefixAddress;
|
|
50
50
|
}
|
|
51
51
|
return (0, bech32_1.encode)(hrp, bits);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
exports["default"] = Address;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.default = Address;
|
package/dist/cjs/config.js
CHANGED
|
@@ -1,42 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
exports
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.XELIS_DECIMALS = exports.XELIS_ASSET = exports.LOCAL_XSWD_WS = exports.LOCAL_XSWD_URL = exports.LOCAL_WALLET_WS = exports.LOCAL_WALLET_RPC = exports.LOCAL_WALLET_URL = exports.LOCAL_NODE_WS = exports.TESTNET_NODE_WS = exports.MAINNET_NODE_WS = exports.LOCAL_NODE_RPC = exports.TESTNET_NODE_RPC = exports.MAINNET_NODE_RPC = exports.LOCAL_NODE_URL = exports.TESTNET_NODE_URL = exports.MAINNET_NODE_URL = exports.XSWD_PORT = exports.WALLET_RPC_PORT = exports.DAEMON_RPC_PORT = void 0;
|
|
4
|
-
exports.DAEMON_RPC_PORT =
|
|
5
|
-
exports.WALLET_RPC_PORT =
|
|
6
|
-
exports.XSWD_PORT =
|
|
7
|
-
exports.MAINNET_NODE_URL =
|
|
8
|
-
exports.TESTNET_NODE_URL =
|
|
9
|
-
exports.LOCAL_NODE_URL =
|
|
10
|
-
exports.MAINNET_NODE_RPC =
|
|
11
|
-
exports.TESTNET_NODE_RPC =
|
|
12
|
-
exports.LOCAL_NODE_RPC =
|
|
13
|
-
exports.MAINNET_NODE_WS =
|
|
14
|
-
exports.TESTNET_NODE_WS =
|
|
15
|
-
exports.LOCAL_NODE_WS =
|
|
16
|
-
exports.LOCAL_WALLET_URL =
|
|
17
|
-
exports.LOCAL_WALLET_RPC =
|
|
18
|
-
exports.LOCAL_WALLET_WS =
|
|
19
|
-
exports.LOCAL_XSWD_URL =
|
|
20
|
-
exports.LOCAL_XSWD_WS =
|
|
21
|
-
exports.XELIS_ASSET =
|
|
4
|
+
exports.DAEMON_RPC_PORT = `8080`;
|
|
5
|
+
exports.WALLET_RPC_PORT = `8081`;
|
|
6
|
+
exports.XSWD_PORT = `44325`;
|
|
7
|
+
exports.MAINNET_NODE_URL = `node.xelis.io`;
|
|
8
|
+
exports.TESTNET_NODE_URL = `testnet-node.xelis.io`;
|
|
9
|
+
exports.LOCAL_NODE_URL = `127.0.0.1:${exports.DAEMON_RPC_PORT}`;
|
|
10
|
+
exports.MAINNET_NODE_RPC = `https://${exports.MAINNET_NODE_URL}/json_rpc`;
|
|
11
|
+
exports.TESTNET_NODE_RPC = `https://${exports.TESTNET_NODE_URL}/json_rpc`;
|
|
12
|
+
exports.LOCAL_NODE_RPC = `http://${exports.LOCAL_NODE_URL}/json_rpc`;
|
|
13
|
+
exports.MAINNET_NODE_WS = `wss://${exports.MAINNET_NODE_URL}/json_rpc`;
|
|
14
|
+
exports.TESTNET_NODE_WS = `wss://${exports.TESTNET_NODE_URL}/json_rpc`;
|
|
15
|
+
exports.LOCAL_NODE_WS = `ws://${exports.LOCAL_NODE_URL}/json_rpc`;
|
|
16
|
+
exports.LOCAL_WALLET_URL = `127.0.0.1:${exports.WALLET_RPC_PORT}`;
|
|
17
|
+
exports.LOCAL_WALLET_RPC = `http://${exports.LOCAL_WALLET_URL}/json_rpc`;
|
|
18
|
+
exports.LOCAL_WALLET_WS = `ws://${exports.LOCAL_WALLET_URL}/json_rpc`;
|
|
19
|
+
exports.LOCAL_XSWD_URL = `127.0.0.1:${exports.XSWD_PORT}`;
|
|
20
|
+
exports.LOCAL_XSWD_WS = `ws://${exports.LOCAL_XSWD_URL}/xswd`;
|
|
21
|
+
exports.XELIS_ASSET = `0000000000000000000000000000000000000000000000000000000000000000`;
|
|
22
22
|
exports.XELIS_DECIMALS = 8;
|
|
23
|
-
exports
|
|
24
|
-
MAINNET_NODE_URL: exports.MAINNET_NODE_URL,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
TESTNET_NODE_WS: exports.TESTNET_NODE_WS,
|
|
31
|
-
LOCAL_NODE_WS: exports.LOCAL_NODE_WS,
|
|
32
|
-
DAEMON_RPC_PORT: exports.DAEMON_RPC_PORT,
|
|
33
|
-
WALLET_RPC_PORT: exports.WALLET_RPC_PORT,
|
|
34
|
-
XSWD_PORT: exports.XSWD_PORT,
|
|
35
|
-
LOCAL_WALLET_URL: exports.LOCAL_WALLET_URL,
|
|
36
|
-
LOCAL_WALLET_RPC: exports.LOCAL_WALLET_RPC,
|
|
37
|
-
LOCAL_WALLET_WS: exports.LOCAL_WALLET_WS,
|
|
38
|
-
LOCAL_XSWD_URL: exports.LOCAL_XSWD_URL,
|
|
39
|
-
LOCAL_XSWD_WS: exports.LOCAL_XSWD_WS,
|
|
40
|
-
XELIS_ASSET: exports.XELIS_ASSET,
|
|
41
|
-
XELIS_DECIMALS: exports.XELIS_DECIMALS
|
|
23
|
+
exports.default = {
|
|
24
|
+
MAINNET_NODE_URL: exports.MAINNET_NODE_URL, TESTNET_NODE_URL: exports.TESTNET_NODE_URL,
|
|
25
|
+
MAINNET_NODE_RPC: exports.MAINNET_NODE_RPC, TESTNET_NODE_RPC: exports.TESTNET_NODE_RPC, LOCAL_NODE_RPC: exports.LOCAL_NODE_RPC,
|
|
26
|
+
MAINNET_NODE_WS: exports.MAINNET_NODE_WS, TESTNET_NODE_WS: exports.TESTNET_NODE_WS, LOCAL_NODE_WS: exports.LOCAL_NODE_WS,
|
|
27
|
+
DAEMON_RPC_PORT: exports.DAEMON_RPC_PORT, WALLET_RPC_PORT: exports.WALLET_RPC_PORT, XSWD_PORT: exports.XSWD_PORT,
|
|
28
|
+
LOCAL_WALLET_URL: exports.LOCAL_WALLET_URL, LOCAL_WALLET_RPC: exports.LOCAL_WALLET_RPC, LOCAL_WALLET_WS: exports.LOCAL_WALLET_WS,
|
|
29
|
+
LOCAL_XSWD_URL: exports.LOCAL_XSWD_URL, LOCAL_XSWD_WS: exports.LOCAL_XSWD_WS, XELIS_ASSET: exports.XELIS_ASSET, XELIS_DECIMALS: exports.XELIS_DECIMALS
|
|
42
30
|
};
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContractFactory = exports.createContract = exports.Contract = void 0;
|
|
4
|
+
const xvm_serializer_1 = require("./xvm_serializer");
|
|
5
|
+
;
|
|
6
|
+
// Convert ABI type to our validator type
|
|
7
|
+
function normalizeType(abiType) {
|
|
8
|
+
const typeMap = {
|
|
9
|
+
'Hash': 'Hash',
|
|
10
|
+
'Address': 'Address',
|
|
11
|
+
'PublicKey': 'PublicKey',
|
|
12
|
+
'Blob': 'Blob',
|
|
13
|
+
'u256': 'u256',
|
|
14
|
+
'u128': 'u128',
|
|
15
|
+
'u64': 'u64',
|
|
16
|
+
'u32': 'u32',
|
|
17
|
+
'u16': 'u16',
|
|
18
|
+
'u8': 'u8',
|
|
19
|
+
'boolean': 'boolean',
|
|
20
|
+
'bool': 'boolean',
|
|
21
|
+
'string': 'string',
|
|
22
|
+
'String': 'string',
|
|
23
|
+
'Boolean': 'boolean',
|
|
24
|
+
'U64': 'u64',
|
|
25
|
+
'U32': 'u32',
|
|
26
|
+
'U16': 'u16',
|
|
27
|
+
'U8': 'u8'
|
|
28
|
+
};
|
|
29
|
+
const normalized = typeMap[abiType];
|
|
30
|
+
if (!normalized) {
|
|
31
|
+
throw new Error(`Unknown ABI type: ${abiType}`);
|
|
32
|
+
}
|
|
33
|
+
return normalized;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Contract class that dynamically generates methods based on ABI
|
|
37
|
+
*/
|
|
38
|
+
class Contract {
|
|
39
|
+
constructor(address, abi) {
|
|
40
|
+
this.address = address;
|
|
41
|
+
this.abi = abi;
|
|
42
|
+
this.methods = new Map();
|
|
43
|
+
// Parse ABI and set up methods map
|
|
44
|
+
for (const entry of abi.data) {
|
|
45
|
+
if (entry.type === 'entry') {
|
|
46
|
+
this.methods.set(entry.name, entry);
|
|
47
|
+
// Dynamically add method to the instance
|
|
48
|
+
this.createDynamicMethod(entry);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Creates a dynamic method on the contract instance
|
|
54
|
+
*/
|
|
55
|
+
createDynamicMethod(entry) {
|
|
56
|
+
const methodName = entry.name;
|
|
57
|
+
// Create a method that properly binds 'this'
|
|
58
|
+
const method = (params) => {
|
|
59
|
+
return this.invoke(methodName, params);
|
|
60
|
+
};
|
|
61
|
+
// Add the method to the instance
|
|
62
|
+
this[methodName] = method;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Invoke a contract method by name
|
|
66
|
+
* @param methodName - Name of the method from the ABI
|
|
67
|
+
* @param params - Parameters for the method call
|
|
68
|
+
*/
|
|
69
|
+
invoke(methodName, params = {}) {
|
|
70
|
+
const entry = this.methods.get(methodName);
|
|
71
|
+
if (!entry) {
|
|
72
|
+
throw new Error(`Method '${methodName}' not found in contract ABI`);
|
|
73
|
+
}
|
|
74
|
+
// Extract special parameters
|
|
75
|
+
const { maxGas, deposits, ...methodParams } = params;
|
|
76
|
+
// Build parameter list according to ABI
|
|
77
|
+
const parameters = [];
|
|
78
|
+
for (const abiParam of entry.params) {
|
|
79
|
+
const value = methodParams[abiParam.name];
|
|
80
|
+
if (value === undefined) {
|
|
81
|
+
throw new Error(`Missing required parameter '${abiParam.name}' for method '${methodName}'`);
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
const normalizedType = normalizeType(abiParam.type);
|
|
85
|
+
const vmParam = (0, xvm_serializer_1.createVMParameter)(value, normalizedType);
|
|
86
|
+
parameters.push(vmParam);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
throw new Error(`Invalid parameter '${abiParam.name}' for method '${methodName}': ${error}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Create the contract invocation
|
|
93
|
+
const invocationParams = {
|
|
94
|
+
contract: this.address,
|
|
95
|
+
chunkId: entry.chunk_id,
|
|
96
|
+
parameters,
|
|
97
|
+
maxGas: maxGas || 200000000
|
|
98
|
+
};
|
|
99
|
+
if (deposits && Object.keys(deposits).length > 0) {
|
|
100
|
+
invocationParams.deposits = deposits;
|
|
101
|
+
}
|
|
102
|
+
return (0, xvm_serializer_1.createContractInvocation)(invocationParams);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get list of available methods
|
|
106
|
+
*/
|
|
107
|
+
getMethods() {
|
|
108
|
+
return Array.from(this.methods.keys());
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get method signature information
|
|
112
|
+
*/
|
|
113
|
+
getMethodSignature(methodName) {
|
|
114
|
+
return this.methods.get(methodName);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Validate parameters for a method without creating the transaction
|
|
118
|
+
*/
|
|
119
|
+
validateParams(methodName, params) {
|
|
120
|
+
const entry = this.methods.get(methodName);
|
|
121
|
+
if (!entry) {
|
|
122
|
+
throw new Error(`Method '${methodName}' not found in contract ABI`);
|
|
123
|
+
}
|
|
124
|
+
const { deposits, maxGas, ...methodParams } = params;
|
|
125
|
+
// Check all required parameters are present
|
|
126
|
+
for (const abiParam of entry.params) {
|
|
127
|
+
if (!(abiParam.name in methodParams)) {
|
|
128
|
+
throw new Error(`Missing required parameter '${abiParam.name}'`);
|
|
129
|
+
}
|
|
130
|
+
// Validate type
|
|
131
|
+
try {
|
|
132
|
+
const normalizedType = normalizeType(abiParam.type);
|
|
133
|
+
(0, xvm_serializer_1.createVMParameter)(methodParams[abiParam.name], normalizedType, true);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
throw new Error(`Invalid parameter '${abiParam.name}': ${error}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Check for extra parameters
|
|
140
|
+
const expectedParams = new Set(entry.params.map(p => p.name));
|
|
141
|
+
for (const key in methodParams) {
|
|
142
|
+
if (!expectedParams.has(key)) {
|
|
143
|
+
console.warn(`Warning: Unexpected parameter '${key}' for method '${methodName}'`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.Contract = Contract;
|
|
150
|
+
/**
|
|
151
|
+
* Helper function to create a typed contract instance
|
|
152
|
+
* This provides better TypeScript support when the ABI is known at compile time
|
|
153
|
+
*/
|
|
154
|
+
function createContract(address, abi) {
|
|
155
|
+
return new Contract(address, abi);
|
|
156
|
+
}
|
|
157
|
+
exports.createContract = createContract;
|
|
158
|
+
/**
|
|
159
|
+
* Factory for creating multiple contracts with the same ABI
|
|
160
|
+
*/
|
|
161
|
+
class ContractFactory {
|
|
162
|
+
constructor(abi) {
|
|
163
|
+
this.abi = abi;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Create a new contract instance at the specified address
|
|
167
|
+
*/
|
|
168
|
+
at(address) {
|
|
169
|
+
return createContract(address, this.abi);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get the ABI
|
|
173
|
+
*/
|
|
174
|
+
getABI() {
|
|
175
|
+
return this.abi;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.ContractFactory = ContractFactory;
|