koilib 2.0.0 → 2.4.0
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/README.md +49 -7
- package/dist/koinos.js +4910 -4762
- package/dist/koinos.min.js +1 -1
- package/dist/koinos.min.js.LICENSE.txt +1 -10
- package/lib/Contract.d.ts +48 -140
- package/lib/Contract.js +82 -156
- package/lib/Contract.js.map +1 -1
- package/lib/Provider.d.ts +2 -5
- package/lib/Provider.js +42 -11
- package/lib/Provider.js.map +1 -1
- package/lib/Serializer.d.ts +81 -0
- package/lib/Serializer.js +169 -0
- package/lib/Serializer.js.map +1 -0
- package/lib/Signer.d.ts +130 -24
- package/lib/Signer.js +162 -59
- package/lib/Signer.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/index2.js +2 -0
- package/lib/index2.js.map +1 -1
- package/lib/interface.d.ts +161 -24
- package/lib/{krc20-proto.json → jsonDescriptors/krc20-proto.json} +1 -1
- package/lib/{protocol-proto.json → jsonDescriptors/protocol-proto.json} +22 -18
- package/lib/utils.d.ts +270 -2
- package/lib/utils.js +72 -34
- package/lib/utils.js.map +1 -1
- package/package.json +9 -5
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
/*! koilib - MIT License (c) Julian Gonzalez (joticajulian@gmail.com) */
|
|
2
2
|
|
|
3
|
-
/*! noble-
|
|
3
|
+
/*! noble-hashes - MIT License (c) 2021 Paul Miller (paulmillr.com) */
|
|
4
4
|
|
|
5
5
|
/*! noble-secp256k1 - MIT License (c) Paul Miller (paulmillr.com) */
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* [js-sha256]{@link https://github.com/emn178/js-sha256}
|
|
9
|
-
*
|
|
10
|
-
* @version 0.9.0
|
|
11
|
-
* @author Chen, Yi-Cyuan [emn178@gmail.com]
|
|
12
|
-
* @copyright Chen, Yi-Cyuan 2014-2017
|
|
13
|
-
* @license MIT
|
|
14
|
-
*/
|
package/lib/Contract.d.ts
CHANGED
|
@@ -1,111 +1,7 @@
|
|
|
1
|
-
import { Root, INamespace } from "protobufjs/light";
|
|
2
1
|
import { Signer, SignerInterface } from "./Signer";
|
|
3
|
-
import { Provider
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
* Application Binary Interface (ABI)
|
|
7
|
-
*
|
|
8
|
-
* ABIs are composed of 2 elements: methods and types.
|
|
9
|
-
* - The methods define the names of the entries of the smart contract,
|
|
10
|
-
* the corresponding endpoints and the name of the types used.
|
|
11
|
-
* - The types all the description to serialize and deserialize
|
|
12
|
-
* using proto buffers.
|
|
13
|
-
*
|
|
14
|
-
* To generate the types is necessary to use the dependency
|
|
15
|
-
* protobufjs. The following example shows how to generate the
|
|
16
|
-
* protobuf descriptor from a .proto file.
|
|
17
|
-
*
|
|
18
|
-
* ```js
|
|
19
|
-
* const fs = require("fs");
|
|
20
|
-
* const pbjs = require("protobufjs/cli/pbjs");
|
|
21
|
-
*
|
|
22
|
-
* pbjs.main(
|
|
23
|
-
* ["--target", "json", "./token.proto"],
|
|
24
|
-
* (err, output) => {
|
|
25
|
-
* if (err) throw err;
|
|
26
|
-
* fs.writeFileSync("./token-proto.json", output);
|
|
27
|
-
* }
|
|
28
|
-
* );
|
|
29
|
-
* ```
|
|
30
|
-
*
|
|
31
|
-
* Then this descriptor can be loaded to define the ABI:
|
|
32
|
-
* ```js
|
|
33
|
-
* const tokenJson = require("./token-proto.json");
|
|
34
|
-
* const abiToken = {
|
|
35
|
-
* methods: {
|
|
36
|
-
* balanceOf: {
|
|
37
|
-
* entryPoint: 0x15619248,
|
|
38
|
-
* inputs: "balance_of_arguments",
|
|
39
|
-
* outputs: "balance_of_result",
|
|
40
|
-
* readOnly: true,
|
|
41
|
-
* },
|
|
42
|
-
* transfer: {
|
|
43
|
-
* entryPoint: 0x62efa292,
|
|
44
|
-
* inputs: "transfer_arguments",
|
|
45
|
-
* outputs: "transfer_result",
|
|
46
|
-
* },
|
|
47
|
-
* mint: {
|
|
48
|
-
* entryPoint: 0xc2f82bdc,
|
|
49
|
-
* inputs: "mint_argumnets",
|
|
50
|
-
* outputs: "mint_result",
|
|
51
|
-
* },
|
|
52
|
-
* },
|
|
53
|
-
* types: tokenJson,
|
|
54
|
-
* };
|
|
55
|
-
* ```
|
|
56
|
-
*/
|
|
57
|
-
export interface Abi {
|
|
58
|
-
methods: {
|
|
59
|
-
/** Name of the method */
|
|
60
|
-
[x: string]: {
|
|
61
|
-
/** Entry point ID */
|
|
62
|
-
entryPoint: number;
|
|
63
|
-
/** Protobuffer type for input */
|
|
64
|
-
inputs?: string;
|
|
65
|
-
/** Protobuffer type for output */
|
|
66
|
-
outputs?: string;
|
|
67
|
-
/** Boolean to differentiate write methods
|
|
68
|
-
* (using transactions) from read methods
|
|
69
|
-
* (query the contract)
|
|
70
|
-
*/
|
|
71
|
-
readOnly?: boolean;
|
|
72
|
-
/** Description of the method */
|
|
73
|
-
description?: string;
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
-
/**
|
|
77
|
-
* Protobuffers descriptor in JSON format.
|
|
78
|
-
* See https://www.npmjs.com/package/protobufjs#using-json-descriptors
|
|
79
|
-
*/
|
|
80
|
-
types: INamespace;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Human readable format operation
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* ```ts
|
|
87
|
-
* const opDecoded = {
|
|
88
|
-
* name: "transfer",
|
|
89
|
-
* args: {
|
|
90
|
-
* from: "1Krs7v1rtpgRyfwEZncuKMQQnY5JhqXVSx",
|
|
91
|
-
* to: "1BqtgWBcqm9cSZ97avLGZGJdgso7wx6pCA",
|
|
92
|
-
* value: 1000,
|
|
93
|
-
* },
|
|
94
|
-
* };
|
|
95
|
-
* ```
|
|
96
|
-
*/
|
|
97
|
-
export interface DecodedOperationJson {
|
|
98
|
-
/** Operation name */
|
|
99
|
-
name: string;
|
|
100
|
-
/** Arguments decoded. See [[Abi]] */
|
|
101
|
-
args?: Record<string, unknown>;
|
|
102
|
-
}
|
|
103
|
-
export interface TransactionOptions {
|
|
104
|
-
rcLimit?: number | bigint | string;
|
|
105
|
-
nonce?: number;
|
|
106
|
-
sendTransaction?: boolean;
|
|
107
|
-
sendAbis?: boolean;
|
|
108
|
-
}
|
|
2
|
+
import { Provider } from "./Provider";
|
|
3
|
+
import { Serializer } from "./Serializer";
|
|
4
|
+
import { CallContractOperationNested, UploadContractOperationNested, TransactionJson, Abi, TransactionOptions, DecodedOperationJson, SendTransactionResponse } from "./interface";
|
|
109
5
|
/**
|
|
110
6
|
* The contract class contains the contract ID and contract entries
|
|
111
7
|
* definition needed to encode/decode operations during the
|
|
@@ -116,9 +12,9 @@ export interface TransactionOptions {
|
|
|
116
12
|
* ```ts
|
|
117
13
|
* const { Contract, Provider, Signer, utils } = require("koilib");
|
|
118
14
|
* const rpcNodes = ["http://api.koinos.io:8080"];
|
|
119
|
-
* const
|
|
15
|
+
* const privateKey = "f186a5de49797bfd52dc42505c33d75a46822ed5b60046e09d7c336242e20200";
|
|
120
16
|
* const provider = new Provider(rpcNodes);
|
|
121
|
-
* const signer = new Signer(
|
|
17
|
+
* const signer = new Signer({ privateKey, provider });
|
|
122
18
|
* const koinContract = new Contract({
|
|
123
19
|
* id: "19JntSm8pSNETT9aHTwAUHC5RMoaSmgZPJ",
|
|
124
20
|
* abi: utils.Krc20Abi,
|
|
@@ -127,18 +23,26 @@ export interface TransactionOptions {
|
|
|
127
23
|
* });
|
|
128
24
|
* const koin = koinContract.functions;
|
|
129
25
|
*
|
|
26
|
+
* // optional: preformat input/output
|
|
27
|
+
* koinContract.abi.methods.balanceOf.preformatInput = (owner) =>
|
|
28
|
+
* ({ owner });
|
|
29
|
+
* koinContract.abi.methods.balanceOf.preformatOutput = (res) =>
|
|
30
|
+
* utils.formatUnits(res.value, 8);
|
|
31
|
+
* koinContract.abi.methods.transfer.preformatInput = (input) => ({
|
|
32
|
+
* from: signer.getAddress(),
|
|
33
|
+
* to: input.to,
|
|
34
|
+
* value: utils.parseUnits(input.value, 8),
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
130
37
|
* async funtion main() {
|
|
131
38
|
* // Get balance
|
|
132
|
-
* const { result } = await koin.balanceOf(
|
|
133
|
-
*
|
|
134
|
-
* });
|
|
135
|
-
* console.log(balance.result)
|
|
39
|
+
* const { result } = await koin.balanceOf("12fN2CQnuJM8cMnWZ1hPtM4knjLME8E4PD");
|
|
40
|
+
* console.log(result)
|
|
136
41
|
*
|
|
137
42
|
* // Transfer
|
|
138
43
|
* const { transaction, transactionResponse } = await koin.transfer({
|
|
139
|
-
* from: "12fN2CQnuJM8cMnWZ1hPtM4knjLME8E4PD",
|
|
140
44
|
* to: "172AB1FgCsYrRAW5cwQ8KjadgxofvgPFd6",
|
|
141
|
-
* value: "
|
|
45
|
+
* value: "10.0001",
|
|
142
46
|
* });
|
|
143
47
|
* console.log(`Transaction id ${transaction.id} submitted`);
|
|
144
48
|
*
|
|
@@ -155,17 +59,19 @@ export declare class Contract {
|
|
|
155
59
|
* Contract ID
|
|
156
60
|
*/
|
|
157
61
|
id?: Uint8Array;
|
|
158
|
-
/**
|
|
159
|
-
* Protobuffer definitions
|
|
160
|
-
*/
|
|
161
|
-
protobuffers?: Root;
|
|
162
62
|
/**
|
|
163
63
|
* Set of functions to interact with the smart
|
|
164
64
|
* contract. These functions are automatically generated
|
|
165
65
|
* in the constructor of the class
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* const owner = "1Gvqdo9if6v6tFomEuTuMWP1D7H7U9yksb";
|
|
70
|
+
* await koinContract.functions.balanceOf({ owner });
|
|
71
|
+
* ```
|
|
166
72
|
*/
|
|
167
73
|
functions: {
|
|
168
|
-
[x: string]: <T = Record<string, unknown>>(args?:
|
|
74
|
+
[x: string]: <T = Record<string, unknown>>(args?: unknown, opts?: TransactionOptions) => Promise<{
|
|
169
75
|
operation: CallContractOperationNested;
|
|
170
76
|
transaction?: TransactionJson;
|
|
171
77
|
transactionResponse?: SendTransactionResponse;
|
|
@@ -184,13 +90,17 @@ export declare class Contract {
|
|
|
184
90
|
* Provider to connect with the blockchain
|
|
185
91
|
*/
|
|
186
92
|
provider?: Provider;
|
|
93
|
+
/**
|
|
94
|
+
* Serializer to serialize/deserialize data types
|
|
95
|
+
*/
|
|
96
|
+
serializer?: Serializer;
|
|
187
97
|
/**
|
|
188
98
|
* Bytecode. Needed to deploy the smart contract.
|
|
189
99
|
*/
|
|
190
100
|
bytecode?: Uint8Array;
|
|
191
101
|
/**
|
|
192
102
|
* Options to apply when creating transactions.
|
|
193
|
-
* By default it set
|
|
103
|
+
* By default it set rc_limit to 1e8, sendTransaction true,
|
|
194
104
|
* sendAbis true, and nonce undefined (to get it from the blockchain)
|
|
195
105
|
*/
|
|
196
106
|
options: TransactionOptions;
|
|
@@ -201,6 +111,13 @@ export declare class Contract {
|
|
|
201
111
|
options?: TransactionOptions;
|
|
202
112
|
signer?: Signer;
|
|
203
113
|
provider?: Provider;
|
|
114
|
+
/**
|
|
115
|
+
* Set this option if you can not use _eval_ functions
|
|
116
|
+
* in the current environment. In such cases, the
|
|
117
|
+
* serializer must come from an environment where it
|
|
118
|
+
* is able to use those functions.
|
|
119
|
+
*/
|
|
120
|
+
serializer?: Serializer;
|
|
204
121
|
});
|
|
205
122
|
/**
|
|
206
123
|
* Compute contract Id
|
|
@@ -215,8 +132,9 @@ export declare class Contract {
|
|
|
215
132
|
* The Bytecode must be defined in the constructor of the class
|
|
216
133
|
* @example
|
|
217
134
|
* ```ts
|
|
218
|
-
* const
|
|
135
|
+
* const privateKey = "f186a5de49797bfd52dc42505c33d75a46822ed5b60046e09d7c336242e20200";
|
|
219
136
|
* const provider = new Provider(["http://api.koinos.io:8080"]);
|
|
137
|
+
* const signer = new Signer({ privateKey, provider });
|
|
220
138
|
* const bytecode = new Uint8Array([1, 2, 3, 4]);
|
|
221
139
|
* const contract = new Contract({ signer, provider, bytecode });
|
|
222
140
|
* const { transactionResponse } = await contract.deploy();
|
|
@@ -248,23 +166,23 @@ export declare class Contract {
|
|
|
248
166
|
*
|
|
249
167
|
* console.log(opEncoded);
|
|
250
168
|
* // {
|
|
251
|
-
* //
|
|
252
|
-
* //
|
|
253
|
-
* //
|
|
169
|
+
* // call_contract: {
|
|
170
|
+
* // contract_id: "19JntSm8pSNETT9aHTwAUHC5RMoaSmgZPJ",
|
|
171
|
+
* // entry_point: 0x62efa292,
|
|
254
172
|
* // args: "MBWFsaWNlA2JvYgAAAAAAAAPo",
|
|
255
173
|
* // }
|
|
256
174
|
* // }
|
|
257
175
|
* ```
|
|
258
176
|
*/
|
|
259
|
-
encodeOperation(op: DecodedOperationJson): CallContractOperationNested
|
|
177
|
+
encodeOperation(op: DecodedOperationJson): Promise<CallContractOperationNested>;
|
|
260
178
|
/**
|
|
261
179
|
* Decodes a contract operation to be human readable
|
|
262
180
|
* @example
|
|
263
181
|
* ```ts
|
|
264
182
|
* const opDecoded = contract.decodeOperation({
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
183
|
+
* call_contract: {
|
|
184
|
+
* contract_id: "19JntSm8pSNETT9aHTwAUHC5RMoaSmgZPJ",
|
|
185
|
+
* entry_point: 0x62efa292,
|
|
268
186
|
* args: "MBWFsaWNlA2JvYgAAAAAAAAPo",
|
|
269
187
|
* }
|
|
270
188
|
* });
|
|
@@ -279,16 +197,6 @@ export declare class Contract {
|
|
|
279
197
|
* // }
|
|
280
198
|
* ```
|
|
281
199
|
*/
|
|
282
|
-
decodeOperation(op: CallContractOperationNested): DecodedOperationJson
|
|
283
|
-
/**
|
|
284
|
-
* Function to encode a type using the protobuffer definitions
|
|
285
|
-
* It also prepares the bytes for special cases (base58, hex string)
|
|
286
|
-
*/
|
|
287
|
-
encodeType(valueDecoded: Record<string, unknown>, typeName: string): Uint8Array;
|
|
288
|
-
/**
|
|
289
|
-
* Function to decode bytes using the protobuffer definitions
|
|
290
|
-
* It also encodes the bytes for special cases (base58, hex string)
|
|
291
|
-
*/
|
|
292
|
-
decodeType<T = Record<string, unknown>>(valueEncoded: string | Uint8Array, typeName: string): T;
|
|
200
|
+
decodeOperation(op: CallContractOperationNested): Promise<DecodedOperationJson>;
|
|
293
201
|
}
|
|
294
202
|
export default Contract;
|
package/lib/Contract.js
CHANGED
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Contract = void 0;
|
|
4
|
-
const
|
|
4
|
+
const Serializer_1 = require("./Serializer");
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
|
-
const OP_BYTES = "(koinos_bytes_type)";
|
|
7
|
-
/**
|
|
8
|
-
* Makes a copy of a value. The returned value can be modified
|
|
9
|
-
* without altering the original one. Although this is not needed
|
|
10
|
-
* for strings or numbers and only needed for objects and arrays,
|
|
11
|
-
* all these options are covered in a single function
|
|
12
|
-
*
|
|
13
|
-
* It is assumed that the argument is number, string, or contructions
|
|
14
|
-
* of these types inside objects or arrays.
|
|
15
|
-
*/
|
|
16
|
-
function copyValue(value) {
|
|
17
|
-
if (typeof value === "string" || typeof value === "number") {
|
|
18
|
-
return value;
|
|
19
|
-
}
|
|
20
|
-
return JSON.parse(JSON.stringify(value));
|
|
21
|
-
}
|
|
22
6
|
/**
|
|
23
7
|
* The contract class contains the contract ID and contract entries
|
|
24
8
|
* definition needed to encode/decode operations during the
|
|
@@ -29,9 +13,9 @@ function copyValue(value) {
|
|
|
29
13
|
* ```ts
|
|
30
14
|
* const { Contract, Provider, Signer, utils } = require("koilib");
|
|
31
15
|
* const rpcNodes = ["http://api.koinos.io:8080"];
|
|
32
|
-
* const
|
|
16
|
+
* const privateKey = "f186a5de49797bfd52dc42505c33d75a46822ed5b60046e09d7c336242e20200";
|
|
33
17
|
* const provider = new Provider(rpcNodes);
|
|
34
|
-
* const signer = new Signer(
|
|
18
|
+
* const signer = new Signer({ privateKey, provider });
|
|
35
19
|
* const koinContract = new Contract({
|
|
36
20
|
* id: "19JntSm8pSNETT9aHTwAUHC5RMoaSmgZPJ",
|
|
37
21
|
* abi: utils.Krc20Abi,
|
|
@@ -40,18 +24,26 @@ function copyValue(value) {
|
|
|
40
24
|
* });
|
|
41
25
|
* const koin = koinContract.functions;
|
|
42
26
|
*
|
|
27
|
+
* // optional: preformat input/output
|
|
28
|
+
* koinContract.abi.methods.balanceOf.preformatInput = (owner) =>
|
|
29
|
+
* ({ owner });
|
|
30
|
+
* koinContract.abi.methods.balanceOf.preformatOutput = (res) =>
|
|
31
|
+
* utils.formatUnits(res.value, 8);
|
|
32
|
+
* koinContract.abi.methods.transfer.preformatInput = (input) => ({
|
|
33
|
+
* from: signer.getAddress(),
|
|
34
|
+
* to: input.to,
|
|
35
|
+
* value: utils.parseUnits(input.value, 8),
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
43
38
|
* async funtion main() {
|
|
44
39
|
* // Get balance
|
|
45
|
-
* const { result } = await koin.balanceOf(
|
|
46
|
-
*
|
|
47
|
-
* });
|
|
48
|
-
* console.log(balance.result)
|
|
40
|
+
* const { result } = await koin.balanceOf("12fN2CQnuJM8cMnWZ1hPtM4knjLME8E4PD");
|
|
41
|
+
* console.log(result)
|
|
49
42
|
*
|
|
50
43
|
* // Transfer
|
|
51
44
|
* const { transaction, transactionResponse } = await koin.transfer({
|
|
52
|
-
* from: "12fN2CQnuJM8cMnWZ1hPtM4knjLME8E4PD",
|
|
53
45
|
* to: "172AB1FgCsYrRAW5cwQ8KjadgxofvgPFd6",
|
|
54
|
-
* value: "
|
|
46
|
+
* value: "10.0001",
|
|
55
47
|
* });
|
|
56
48
|
* console.log(`Transaction id ${transaction.id} submitted`);
|
|
57
49
|
*
|
|
@@ -65,46 +57,67 @@ function copyValue(value) {
|
|
|
65
57
|
*/
|
|
66
58
|
class Contract {
|
|
67
59
|
constructor(c) {
|
|
68
|
-
var _a
|
|
60
|
+
var _a;
|
|
69
61
|
if (c.id)
|
|
70
62
|
this.id = utils_1.decodeBase58(c.id);
|
|
71
63
|
this.signer = c.signer;
|
|
72
64
|
this.provider = c.provider || ((_a = c.signer) === null || _a === void 0 ? void 0 : _a.provider);
|
|
73
65
|
this.abi = c.abi;
|
|
74
66
|
this.bytecode = c.bytecode;
|
|
75
|
-
if (
|
|
76
|
-
this.
|
|
67
|
+
if (c.serializer) {
|
|
68
|
+
this.serializer = c.serializer;
|
|
69
|
+
}
|
|
70
|
+
else if (c.abi && c.abi.types) {
|
|
71
|
+
this.serializer = new Serializer_1.Serializer(c.abi.types);
|
|
72
|
+
}
|
|
77
73
|
this.options = {
|
|
78
|
-
|
|
74
|
+
rc_limit: 1e8,
|
|
79
75
|
sendTransaction: true,
|
|
80
76
|
sendAbis: true,
|
|
81
77
|
...c.options,
|
|
82
78
|
};
|
|
83
79
|
this.functions = {};
|
|
84
|
-
if (this.signer &&
|
|
80
|
+
if (this.signer &&
|
|
81
|
+
this.provider &&
|
|
82
|
+
this.abi &&
|
|
83
|
+
this.abi.methods &&
|
|
84
|
+
this.serializer) {
|
|
85
85
|
Object.keys(this.abi.methods).forEach((name) => {
|
|
86
|
-
this.functions[name] = async (
|
|
86
|
+
this.functions[name] = async (argu = {}, options) => {
|
|
87
87
|
if (!this.provider)
|
|
88
88
|
throw new Error("provider not found");
|
|
89
89
|
if (!this.abi || !this.abi.methods)
|
|
90
90
|
throw new Error("Methods are not defined");
|
|
91
|
+
if (!this.abi.methods[name])
|
|
92
|
+
throw new Error(`Method ${name} not defined in the ABI`);
|
|
91
93
|
const opts = {
|
|
92
94
|
...this.options,
|
|
93
95
|
...options,
|
|
94
96
|
};
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
const { readOnly, output, defaultOutput, preformatInput, preformatOutput, } = this.abi.methods[name];
|
|
98
|
+
let args;
|
|
99
|
+
if (typeof preformatInput === "function") {
|
|
100
|
+
args = preformatInput(argu);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
args = argu;
|
|
104
|
+
}
|
|
105
|
+
const operation = await this.encodeOperation({ name, args });
|
|
106
|
+
if (readOnly) {
|
|
107
|
+
if (!output)
|
|
108
|
+
throw new Error(`No output defined for ${name}`);
|
|
99
109
|
// read contract
|
|
100
110
|
const { result: resultEncoded } = await this.provider.readContract({
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
args: utils_1.encodeBase64(operation.
|
|
111
|
+
contract_id: utils_1.encodeBase58(operation.call_contract.contract_id),
|
|
112
|
+
entry_point: operation.call_contract.entry_point,
|
|
113
|
+
args: utils_1.encodeBase64(operation.call_contract.args),
|
|
104
114
|
});
|
|
105
|
-
let result;
|
|
115
|
+
let result = defaultOutput;
|
|
106
116
|
if (resultEncoded) {
|
|
107
|
-
result = this.
|
|
117
|
+
result = await this.serializer.deserialize(resultEncoded, output);
|
|
118
|
+
}
|
|
119
|
+
if (typeof preformatOutput === "function") {
|
|
120
|
+
result = preformatOutput(result);
|
|
108
121
|
}
|
|
109
122
|
return { operation, result };
|
|
110
123
|
}
|
|
@@ -148,8 +161,9 @@ class Contract {
|
|
|
148
161
|
* The Bytecode must be defined in the constructor of the class
|
|
149
162
|
* @example
|
|
150
163
|
* ```ts
|
|
151
|
-
* const
|
|
164
|
+
* const privateKey = "f186a5de49797bfd52dc42505c33d75a46822ed5b60046e09d7c336242e20200";
|
|
152
165
|
* const provider = new Provider(["http://api.koinos.io:8080"]);
|
|
166
|
+
* const signer = new Signer({ privateKey, provider });
|
|
153
167
|
* const bytecode = new Uint8Array([1, 2, 3, 4]);
|
|
154
168
|
* const contract = new Contract({ signer, provider, bytecode });
|
|
155
169
|
* const { transactionResponse } = await contract.deploy();
|
|
@@ -168,8 +182,8 @@ class Contract {
|
|
|
168
182
|
...options,
|
|
169
183
|
};
|
|
170
184
|
const operation = {
|
|
171
|
-
|
|
172
|
-
|
|
185
|
+
upload_contract: {
|
|
186
|
+
contract_id: Contract.computeContractId(this.signer.getAddress()),
|
|
173
187
|
bytecode: this.bytecode,
|
|
174
188
|
},
|
|
175
189
|
};
|
|
@@ -201,32 +215,32 @@ class Contract {
|
|
|
201
215
|
*
|
|
202
216
|
* console.log(opEncoded);
|
|
203
217
|
* // {
|
|
204
|
-
* //
|
|
205
|
-
* //
|
|
206
|
-
* //
|
|
218
|
+
* // call_contract: {
|
|
219
|
+
* // contract_id: "19JntSm8pSNETT9aHTwAUHC5RMoaSmgZPJ",
|
|
220
|
+
* // entry_point: 0x62efa292,
|
|
207
221
|
* // args: "MBWFsaWNlA2JvYgAAAAAAAAPo",
|
|
208
222
|
* // }
|
|
209
223
|
* // }
|
|
210
224
|
* ```
|
|
211
225
|
*/
|
|
212
|
-
encodeOperation(op) {
|
|
226
|
+
async encodeOperation(op) {
|
|
213
227
|
if (!this.abi || !this.abi.methods || !this.abi.methods[op.name])
|
|
214
228
|
throw new Error(`Operation ${op.name} unknown`);
|
|
215
|
-
if (!this.
|
|
216
|
-
throw new Error("
|
|
229
|
+
if (!this.serializer)
|
|
230
|
+
throw new Error("Serializer is not defined");
|
|
217
231
|
if (!this.id)
|
|
218
232
|
throw new Error("Contract id is not defined");
|
|
219
233
|
const method = this.abi.methods[op.name];
|
|
220
234
|
let bufferInputs = new Uint8Array(0);
|
|
221
|
-
if (method.
|
|
235
|
+
if (method.input) {
|
|
222
236
|
if (!op.args)
|
|
223
|
-
throw new Error(`No arguments defined for type '${method.
|
|
224
|
-
bufferInputs = this.
|
|
237
|
+
throw new Error(`No arguments defined for type '${method.input}'`);
|
|
238
|
+
bufferInputs = await this.serializer.serialize(op.args, method.input);
|
|
225
239
|
}
|
|
226
240
|
return {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
241
|
+
call_contract: {
|
|
242
|
+
contract_id: this.id,
|
|
243
|
+
entry_point: method.entryPoint,
|
|
230
244
|
args: bufferInputs,
|
|
231
245
|
},
|
|
232
246
|
};
|
|
@@ -236,9 +250,9 @@ class Contract {
|
|
|
236
250
|
* @example
|
|
237
251
|
* ```ts
|
|
238
252
|
* const opDecoded = contract.decodeOperation({
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
253
|
+
* call_contract: {
|
|
254
|
+
* contract_id: "19JntSm8pSNETT9aHTwAUHC5RMoaSmgZPJ",
|
|
255
|
+
* entry_point: 0x62efa292,
|
|
242
256
|
* args: "MBWFsaWNlA2JvYgAAAAAAAAPo",
|
|
243
257
|
* }
|
|
244
258
|
* });
|
|
@@ -253,118 +267,30 @@ class Contract {
|
|
|
253
267
|
* // }
|
|
254
268
|
* ```
|
|
255
269
|
*/
|
|
256
|
-
decodeOperation(op) {
|
|
270
|
+
async decodeOperation(op) {
|
|
257
271
|
if (!this.id)
|
|
258
272
|
throw new Error("Contract id is not defined");
|
|
259
273
|
if (!this.abi || !this.abi.methods)
|
|
260
274
|
throw new Error("Methods are not defined");
|
|
261
|
-
if (!
|
|
275
|
+
if (!this.serializer)
|
|
276
|
+
throw new Error("Serializer is not defined");
|
|
277
|
+
if (!op.call_contract)
|
|
262
278
|
throw new Error("Operation is not CallContractOperation");
|
|
263
|
-
if (op.
|
|
264
|
-
throw new Error(`Invalid contract id. Expected: ${utils_1.encodeBase58(this.id)}. Received: ${utils_1.encodeBase58(op.
|
|
279
|
+
if (op.call_contract.contract_id !== this.id)
|
|
280
|
+
throw new Error(`Invalid contract id. Expected: ${utils_1.encodeBase58(this.id)}. Received: ${utils_1.encodeBase58(op.call_contract.contract_id)}`);
|
|
265
281
|
for (let i = 0; i < Object.keys(this.abi.methods).length; i += 1) {
|
|
266
282
|
const opName = Object.keys(this.abi.methods)[i];
|
|
267
283
|
const method = this.abi.methods[opName];
|
|
268
|
-
if (op.
|
|
269
|
-
if (!method.
|
|
284
|
+
if (op.call_contract.entry_point === method.entryPoint) {
|
|
285
|
+
if (!method.input)
|
|
270
286
|
return { name: opName };
|
|
271
287
|
return {
|
|
272
288
|
name: opName,
|
|
273
|
-
args: this.
|
|
289
|
+
args: await this.serializer.deserialize(op.call_contract.args, method.input),
|
|
274
290
|
};
|
|
275
291
|
}
|
|
276
292
|
}
|
|
277
|
-
throw new Error(`Unknown method id ${op.
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Function to encode a type using the protobuffer definitions
|
|
281
|
-
* It also prepares the bytes for special cases (base58, hex string)
|
|
282
|
-
*/
|
|
283
|
-
encodeType(valueDecoded, typeName) {
|
|
284
|
-
if (!this.protobuffers)
|
|
285
|
-
throw new Error("Protobuffers are not defined");
|
|
286
|
-
const protobufType = this.protobuffers.lookupType(typeName);
|
|
287
|
-
const object = {};
|
|
288
|
-
// TODO: format from Buffer to base58/base64 for nested fields
|
|
289
|
-
Object.keys(protobufType.fields).forEach((fieldName) => {
|
|
290
|
-
const { options, name, type } = protobufType.fields[fieldName];
|
|
291
|
-
// No byte conversion
|
|
292
|
-
if (type !== "bytes") {
|
|
293
|
-
object[name] = copyValue(valueDecoded[name]);
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
// Default byte conversion
|
|
297
|
-
if (!options || !options[OP_BYTES]) {
|
|
298
|
-
object[name] = utils_1.decodeBase64(valueDecoded[name]);
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
// Specific byte conversion
|
|
302
|
-
switch (options[OP_BYTES]) {
|
|
303
|
-
case "BASE58":
|
|
304
|
-
case "CONTRACT_ID":
|
|
305
|
-
case "ADDRESS":
|
|
306
|
-
object[name] = utils_1.decodeBase58(valueDecoded[name]);
|
|
307
|
-
break;
|
|
308
|
-
case "BASE64":
|
|
309
|
-
object[name] = utils_1.decodeBase64(valueDecoded[name]);
|
|
310
|
-
break;
|
|
311
|
-
case "HEX":
|
|
312
|
-
case "BLOCK_ID":
|
|
313
|
-
case "TRANSACTION_ID":
|
|
314
|
-
object[name] = utils_1.toUint8Array(valueDecoded[name].replace("0x", ""));
|
|
315
|
-
break;
|
|
316
|
-
default:
|
|
317
|
-
throw new Error(`unknown koinos_byte_type ${options[OP_BYTES]}`);
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
const message = protobufType.create(object);
|
|
321
|
-
const buffer = protobufType.encode(message).finish();
|
|
322
|
-
return buffer;
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Function to decode bytes using the protobuffer definitions
|
|
326
|
-
* It also encodes the bytes for special cases (base58, hex string)
|
|
327
|
-
*/
|
|
328
|
-
decodeType(valueEncoded, typeName) {
|
|
329
|
-
if (!this.protobuffers)
|
|
330
|
-
throw new Error("Protobuffers are not defined");
|
|
331
|
-
const valueBuffer = typeof valueEncoded === "string"
|
|
332
|
-
? utils_1.decodeBase64(valueEncoded)
|
|
333
|
-
: valueEncoded;
|
|
334
|
-
const protobufType = this.protobuffers.lookupType(typeName);
|
|
335
|
-
const message = protobufType.decode(valueBuffer);
|
|
336
|
-
const object = protobufType.toObject(message, { longs: String });
|
|
337
|
-
// TODO: format from Buffer to base58/base64 for nested fields
|
|
338
|
-
Object.keys(protobufType.fields).forEach((fieldName) => {
|
|
339
|
-
const { options, name, type } = protobufType.fields[fieldName];
|
|
340
|
-
// No byte conversion
|
|
341
|
-
if (type !== "bytes")
|
|
342
|
-
return;
|
|
343
|
-
// Default byte conversion
|
|
344
|
-
if (!options || !options[OP_BYTES]) {
|
|
345
|
-
object[name] = utils_1.encodeBase64(object[name]);
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
// Specific byte conversion
|
|
349
|
-
switch (options[OP_BYTES]) {
|
|
350
|
-
case "BASE58":
|
|
351
|
-
case "CONTRACT_ID":
|
|
352
|
-
case "ADDRESS":
|
|
353
|
-
object[name] = utils_1.encodeBase58(object[name]);
|
|
354
|
-
break;
|
|
355
|
-
case "BASE64":
|
|
356
|
-
object[name] = utils_1.encodeBase64(object[name]);
|
|
357
|
-
break;
|
|
358
|
-
case "HEX":
|
|
359
|
-
case "BLOCK_ID":
|
|
360
|
-
case "TRANSACTION_ID":
|
|
361
|
-
object[name] = `0x${utils_1.toHexString(object[name])}`;
|
|
362
|
-
break;
|
|
363
|
-
default:
|
|
364
|
-
throw new Error(`unknown koinos_byte_type ${options[OP_BYTES]}`);
|
|
365
|
-
}
|
|
366
|
-
});
|
|
367
|
-
return object;
|
|
293
|
+
throw new Error(`Unknown method id ${op.call_contract.entry_point}`);
|
|
368
294
|
}
|
|
369
295
|
}
|
|
370
296
|
exports.Contract = Contract;
|