koilib 5.0.0 → 5.1.1

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 CHANGED
@@ -123,7 +123,7 @@ a transaction, and read contracts.
123
123
  }
124
124
 
125
125
  // wait to be mined
126
- const blockNumber = await transaction.wait();
126
+ const { blockNumber } = await transaction.wait();
127
127
  console.log(`Transaction mined. Block number: ${blockNumber}`);
128
128
 
129
129
  // read the balance
@@ -150,13 +150,56 @@ It's also possible to upload contracts. First, follow the instructions in [koino
150
150
  console.log("Transaction submitted. Receipt:");
151
151
  console.log(receipt);
152
152
  // wait to be mined
153
- const blockNumber = await transaction.wait();
153
+ const { blockNumber } = await transaction.wait();
154
154
  console.log(`Contract uploaded in block number ${blockNumber}`);
155
155
  })();
156
156
  ```
157
157
 
158
158
  You can also upload a contract in a new address. It is not required that this new address has funds, you just have to set your principal wallet as payer.
159
159
 
160
+ ```typescript
161
+ (async () => {
162
+ // define signer, provider and bytecode
163
+ const provider = new Provider(["http://api.koinos.io:8080"]);
164
+ const accountWithFunds = Signer.fromSeed("this account has funds");
165
+ const newAccount = Signer.fromSeed("new account without funds");
166
+ accountWithFunds.provider = provider;
167
+ newAccount.provider = provider;
168
+
169
+ const bytecode = fs.readFileSync("my_contract.wasm");
170
+
171
+ // create contract. Set newAccount as signer
172
+ const contract = new Contract({
173
+ signer: newAccount,
174
+ provider,
175
+ bytecode,
176
+ options: {
177
+ // transaction options
178
+ // set payer
179
+ payer: accountWithFunds.address,
180
+
181
+ // use "beforeSend" function to sign
182
+ // the transaction with the payer
183
+ beforeSend: async (tx) => {
184
+ accountWithFunds.signTransaction(tx);
185
+ },
186
+ },
187
+ });
188
+
189
+ // call deploy()
190
+ // By default it is signed by "newAccount". But, as
191
+ // in beforeSend it is signed by the payer then it
192
+ // will have 2 signatures
193
+ const { receipt } = await contract.deploy();
194
+ console.log("Transaction submitted. Receipt: ");
195
+ console.log(receipt);
196
+ const { blockNumber } = await transaction.wait();
197
+ console.log(`Contract uploaded in block number ${blockNumber}`);
198
+ })();
199
+ ```
200
+
201
+ In fact, there are several ways to set a different payer and use it to upload a contract. This is another example:
202
+
160
203
  ```typescript
161
204
  (async () => {
162
205
  // define signer, provider and bytecode
@@ -193,11 +236,37 @@ You can also upload a contract in a new address. It is not required that this ne
193
236
  const { receipt } = await newAccount.sendTransaction(transaction);
194
237
  console.log("Transaction submitted. Receipt: ");
195
238
  console.log(receipt);
196
- const blockNumber = await transaction.wait();
239
+ const { blockNumber } = await transaction.wait();
197
240
  console.log(`Contract uploaded in block number ${blockNumber}`);
198
241
  })();
199
242
  ```
200
243
 
244
+ ### Multisignatures
245
+
246
+ It can be configured to sign a single transaction with multiple accounts. Here is an example:
247
+
248
+ ```ts
249
+ const signer2 = Signer.fromSeed("signer2");
250
+ const signer3 = Signer.fromSeed("signer3");
251
+
252
+ const addMoreSignatures = async (tx) => {
253
+ await signer2.signTransaction(tx);
254
+ await signer3.signTransaction(tx);
255
+ };
256
+
257
+ const { transaction } = await koin.transfer(
258
+ {
259
+ from: "16MT1VQFgsVxEfJrSGinrA5buiqBsN5ViJ",
260
+ to: "1Gvqdo9if6v6tFomEuTuMWP1D7H7U9yksb",
261
+ value: "1000000",
262
+ },
263
+ {
264
+ payer: signer2.getAddress(),
265
+ beforeSend: addMoreSignatures,
266
+ }
267
+ );
268
+ ```
269
+
201
270
  ### Create ABIs
202
271
 
203
272
  ABIs are composed of 2 elements: methods and types.
@@ -209,7 +278,7 @@ To generate the types is necessary to use the dependency protobufjs. The followi
209
278
 
210
279
  ```js
211
280
  const fs = require("fs");
212
- const pbjs = require("protobufjs/cli/pbjs");
281
+ const pbjs = require("protobufjs-cli/pbjs");
213
282
 
214
283
  pbjs.main(["--target", "json", "./token.proto"], (err, output) => {
215
284
  if (err) throw err;
@@ -245,12 +314,6 @@ const abiToken = {
245
314
  };
246
315
  ```
247
316
 
248
- Note that this example uses "default_output" for the method
249
- "balanceOf". This is used when the smart contract returns an
250
- empty response (for instance when there are no balance records
251
- for a specific address) and you require a default output in
252
- such cases.
253
-
254
317
  ## FAQ
255
318
 
256
319
  1. Can this library be used to create smart contracts?
@@ -269,7 +332,7 @@ such cases.
269
332
  For the ABI you need the .proto file and the library
270
333
  [protobufjs](https://www.npmjs.com/package/protobufjs). Then follow the format
271
334
  for the ABI as described in the previous section. It's important to note that
272
- this ABI has a diffence with respect to the ABI used in [koinos-cli](https://docs.koinos.io/architecture/contract-abi.html).
335
+ this ABI has a difference with respect to the ABI used in [koinos-cli](https://docs.koinos.io/architecture/contract-abi.html).
273
336
  In particular, koilib takes the descriptor from `koilib_types`, which is a
274
337
  descriptor in json format, while the ABI in koinos-cli takes the descriptor from
275
338
  `types`, which is a descriptor in binary format.
package/dist/koinos.js CHANGED
@@ -10007,11 +10007,7 @@ class Contract {
10007
10007
  ...c.options,
10008
10008
  };
10009
10009
  this.functions = {};
10010
- if (this.signer &&
10011
- this.provider &&
10012
- this.abi &&
10013
- this.abi.methods &&
10014
- this.serializer) {
10010
+ if (this.abi && this.abi.methods) {
10015
10011
  Object.keys(this.abi.methods).forEach((name) => {
10016
10012
  this.functions[name] = async (argu = {}, options) => {
10017
10013
  if (!this.provider)
@@ -10052,29 +10048,33 @@ class Contract {
10052
10048
  throw new Error("signer not found");
10053
10049
  let tx = await this.signer.prepareTransaction({
10054
10050
  header: {
10055
- ...((opts === null || opts === void 0 ? void 0 : opts.chainId) && { chain_id: opts === null || opts === void 0 ? void 0 : opts.chainId }),
10056
- ...((opts === null || opts === void 0 ? void 0 : opts.rcLimit) && { rc_limit: opts === null || opts === void 0 ? void 0 : opts.rcLimit }),
10057
- ...((opts === null || opts === void 0 ? void 0 : opts.nonce) && { nonce: opts === null || opts === void 0 ? void 0 : opts.nonce }),
10058
- ...((opts === null || opts === void 0 ? void 0 : opts.payer) && { payer: opts === null || opts === void 0 ? void 0 : opts.payer }),
10059
- ...((opts === null || opts === void 0 ? void 0 : opts.payee) && { payee: opts === null || opts === void 0 ? void 0 : opts.payee }),
10051
+ ...(opts.chainId && { chain_id: opts.chainId }),
10052
+ ...(opts.rcLimit && { rc_limit: opts.rcLimit }),
10053
+ ...(opts.nonce && { nonce: opts.nonce }),
10054
+ ...(opts.payer && { payer: opts.payer }),
10055
+ ...(opts.payee && { payee: opts.payee }),
10060
10056
  },
10061
10057
  operations: [operation],
10062
10058
  });
10063
- const abis = {};
10064
- if (opts === null || opts === void 0 ? void 0 : opts.sendAbis) {
10059
+ const optsSend = {
10060
+ broadcast: opts.broadcast,
10061
+ beforeSend: opts.beforeSend,
10062
+ };
10063
+ if (opts.sendAbis) {
10064
+ optsSend.abis = {};
10065
10065
  const contractId = (0, utils_1.encodeBase58)(this.id);
10066
- abis[contractId] = this.abi;
10066
+ optsSend.abis[contractId] = this.abi;
10067
10067
  }
10068
10068
  // return result if the transaction will not be broadcasted
10069
- if (!(opts === null || opts === void 0 ? void 0 : opts.sendTransaction)) {
10069
+ if (!opts.sendTransaction) {
10070
10070
  const noWait = () => {
10071
10071
  throw new Error("This transaction was not broadcasted");
10072
10072
  };
10073
10073
  if (opts.signTransaction)
10074
- tx = await this.signer.signTransaction(tx, abis);
10074
+ tx = await this.signer.signTransaction(tx, optsSend.abis);
10075
10075
  return { operation, transaction: { ...tx, wait: noWait } };
10076
10076
  }
10077
- const { transaction, receipt } = await this.signer.sendTransaction(tx, opts.broadcast, abis);
10077
+ const { transaction, receipt } = await this.signer.sendTransaction(tx, optsSend);
10078
10078
  return { operation, transaction, receipt };
10079
10079
  };
10080
10080
  });
@@ -10148,30 +10148,34 @@ class Contract {
10148
10148
  upload_contract: {
10149
10149
  contract_id: contractId,
10150
10150
  bytecode: (0, utils_1.encodeBase64url)(this.bytecode),
10151
- ...((opts === null || opts === void 0 ? void 0 : opts.abi) && { abi: opts === null || opts === void 0 ? void 0 : opts.abi }),
10152
- ...((opts === null || opts === void 0 ? void 0 : opts.authorizesCallContract) && {
10153
- authorizes_call_contract: opts === null || opts === void 0 ? void 0 : opts.authorizesCallContract,
10151
+ ...(opts.abi && { abi: opts.abi }),
10152
+ ...(opts.authorizesCallContract && {
10153
+ authorizes_call_contract: opts.authorizesCallContract,
10154
10154
  }),
10155
- ...((opts === null || opts === void 0 ? void 0 : opts.authorizesTransactionApplication) && {
10156
- authorizes_transaction_application: opts === null || opts === void 0 ? void 0 : opts.authorizesTransactionApplication,
10155
+ ...(opts.authorizesTransactionApplication && {
10156
+ authorizes_transaction_application: opts.authorizesTransactionApplication,
10157
10157
  }),
10158
- ...((opts === null || opts === void 0 ? void 0 : opts.authorizesUploadContract) && {
10159
- authorizes_upload_contract: opts === null || opts === void 0 ? void 0 : opts.authorizesUploadContract,
10158
+ ...(opts.authorizesUploadContract && {
10159
+ authorizes_upload_contract: opts.authorizesUploadContract,
10160
10160
  }),
10161
10161
  },
10162
10162
  };
10163
10163
  let tx = await this.signer.prepareTransaction({
10164
10164
  header: {
10165
- ...((opts === null || opts === void 0 ? void 0 : opts.chainId) && { chain_id: opts === null || opts === void 0 ? void 0 : opts.chainId }),
10166
- ...((opts === null || opts === void 0 ? void 0 : opts.rcLimit) && { rc_limit: opts === null || opts === void 0 ? void 0 : opts.rcLimit }),
10167
- ...((opts === null || opts === void 0 ? void 0 : opts.nonce) && { nonce: opts === null || opts === void 0 ? void 0 : opts.nonce }),
10168
- ...((opts === null || opts === void 0 ? void 0 : opts.payer) && { payer: opts === null || opts === void 0 ? void 0 : opts.payer }),
10169
- ...((opts === null || opts === void 0 ? void 0 : opts.payee) && { payee: opts === null || opts === void 0 ? void 0 : opts.payee }),
10165
+ ...(opts.chainId && { chain_id: opts.chainId }),
10166
+ ...(opts.rcLimit && { rc_limit: opts.rcLimit }),
10167
+ ...(opts.nonce && { nonce: opts.nonce }),
10168
+ ...(opts.payer && { payer: opts.payer }),
10169
+ ...(opts.payee && { payee: opts.payee }),
10170
10170
  },
10171
10171
  operations: [operation],
10172
10172
  });
10173
+ const optsSend = {
10174
+ broadcast: opts.broadcast,
10175
+ beforeSend: opts.beforeSend,
10176
+ };
10173
10177
  // return result if the transaction will not be broadcasted
10174
- if (!(opts === null || opts === void 0 ? void 0 : opts.sendTransaction)) {
10178
+ if (!opts.sendTransaction) {
10175
10179
  const noWait = () => {
10176
10180
  throw new Error("This transaction was not broadcasted");
10177
10181
  };
@@ -10179,7 +10183,7 @@ class Contract {
10179
10183
  tx = await this.signer.signTransaction(tx);
10180
10184
  return { operation, transaction: { ...tx, wait: noWait } };
10181
10185
  }
10182
- const { transaction, receipt } = await this.signer.sendTransaction(tx, opts.broadcast);
10186
+ const { transaction, receipt } = await this.signer.sendTransaction(tx, optsSend);
10183
10187
  return { operation, transaction, receipt };
10184
10188
  }
10185
10189
  /**
@@ -10495,14 +10499,17 @@ class Provider {
10495
10499
  if (transactions &&
10496
10500
  transactions[0] &&
10497
10501
  transactions[0].containing_blocks)
10498
- return transactions[0].containing_blocks[0];
10502
+ return {
10503
+ blockId: transactions[0].containing_blocks[0],
10504
+ };
10499
10505
  }
10500
10506
  throw new Error(`Transaction not mined after ${timeout} ms`);
10501
10507
  }
10502
10508
  // byBlock
10503
10509
  const findTxInBlocks = async (ini, numBlocks, idRef) => {
10504
10510
  const blocks = await this.getBlocks(ini, numBlocks, idRef);
10505
- let bNum = 0; //console.log(JSON.stringify(blocks,null,2))
10511
+ let bNum = 0;
10512
+ let bId = "";
10506
10513
  blocks.forEach((block) => {
10507
10514
  if (!block ||
10508
10515
  !block.block ||
@@ -10510,11 +10517,13 @@ class Provider {
10510
10517
  !block.block.transactions)
10511
10518
  return;
10512
10519
  const tx = block.block.transactions.find((t) => t.id === txId);
10513
- if (tx)
10520
+ if (tx) {
10514
10521
  bNum = Number(block.block_height);
10522
+ bId = block.block_id;
10523
+ }
10515
10524
  });
10516
10525
  const lastId = blocks[blocks.length - 1].block_id;
10517
- return [bNum, lastId];
10526
+ return [bNum, bId, lastId];
10518
10527
  };
10519
10528
  let blockNumber = 0;
10520
10529
  let iniBlock = 0;
@@ -10529,18 +10538,24 @@ class Provider {
10529
10538
  if (Number(headTopology.height) === blockNumber - 1 &&
10530
10539
  previousId &&
10531
10540
  previousId !== headTopology.id) {
10532
- const [bNum, lastId] = await findTxInBlocks(iniBlock, Number(headTopology.height) - iniBlock + 1, headTopology.id);
10541
+ const [bNum, bId, lastId] = await findTxInBlocks(iniBlock, Number(headTopology.height) - iniBlock + 1, headTopology.id);
10533
10542
  if (bNum)
10534
- return bNum;
10543
+ return {
10544
+ blockId: bId,
10545
+ blockNumber: bNum,
10546
+ };
10535
10547
  previousId = lastId;
10536
10548
  blockNumber = Number(headTopology.height) + 1;
10537
10549
  }
10538
10550
  // eslint-disable-next-line no-continue
10539
10551
  if (blockNumber > Number(headTopology.height))
10540
10552
  continue;
10541
- const [bNum, lastId] = await findTxInBlocks(blockNumber, 1, headTopology.id);
10553
+ const [bNum, bId, lastId] = await findTxInBlocks(blockNumber, 1, headTopology.id);
10542
10554
  if (bNum)
10543
- return bNum;
10555
+ return {
10556
+ blockId: bId,
10557
+ blockNumber: bNum,
10558
+ };
10544
10559
  if (!previousId)
10545
10560
  previousId = lastId;
10546
10561
  blockNumber += 1;
@@ -10686,7 +10701,11 @@ class Serializer {
10686
10701
  valueBtypeDecoded[name] = valueBtypeEncoded[name].map((itemEncoded) => {
10687
10702
  // custom objects
10688
10703
  if (!nativeTypes.includes(type)) {
10689
- const protoBuf = this.root.lookupType(type);
10704
+ const protoBuf = this.root.lookupTypeOrEnum(type);
10705
+ if (!protoBuf.fields) {
10706
+ // it's an enum
10707
+ return itemEncoded;
10708
+ }
10690
10709
  return this.btypeDecode(itemEncoded, protoBuf);
10691
10710
  }
10692
10711
  // native types
@@ -10696,7 +10715,12 @@ class Serializer {
10696
10715
  }
10697
10716
  // custom objects
10698
10717
  if (!nativeTypes.includes(type)) {
10699
- const protoBuf = this.root.lookupType(type);
10718
+ const protoBuf = this.root.lookupTypeOrEnum(type);
10719
+ if (!protoBuf.fields) {
10720
+ // it's an enum
10721
+ valueBtypeDecoded[name] = valueBtypeEncoded[name];
10722
+ return;
10723
+ }
10700
10724
  valueBtypeDecoded[name] = this.btypeDecode(valueBtypeEncoded[name], protoBuf);
10701
10725
  return;
10702
10726
  }
@@ -10724,7 +10748,11 @@ class Serializer {
10724
10748
  valueBtypeEncoded[name] = valueBtypeDecoded[name].map((itemDecoded) => {
10725
10749
  // custom objects
10726
10750
  if (!nativeTypes.includes(type)) {
10727
- const protoBuf = this.root.lookupType(type);
10751
+ const protoBuf = this.root.lookupTypeOrEnum(type);
10752
+ if (!protoBuf.fields) {
10753
+ // it's an enum
10754
+ return itemDecoded;
10755
+ }
10728
10756
  return this.btypeEncode(itemDecoded, protoBuf);
10729
10757
  }
10730
10758
  // native types
@@ -10734,7 +10762,12 @@ class Serializer {
10734
10762
  }
10735
10763
  // custom objects
10736
10764
  if (!nativeTypes.includes(type)) {
10737
- const protoBuf = this.root.lookupType(type);
10765
+ const protoBuf = this.root.lookupTypeOrEnum(type);
10766
+ if (!protoBuf.fields) {
10767
+ // it's an enum
10768
+ valueBtypeEncoded[name] = valueBtypeDecoded[name];
10769
+ return;
10770
+ }
10738
10771
  valueBtypeEncoded[name] = this.btypeEncode(valueBtypeDecoded[name], protoBuf);
10739
10772
  return;
10740
10773
  }
@@ -10976,6 +11009,10 @@ class Signer {
10976
11009
  }
10977
11010
  if (c.chainId)
10978
11011
  this.chainId = c.chainId;
11012
+ this.sendOptions = {
11013
+ broadcast: true,
11014
+ ...c.sendOptions,
11015
+ };
10979
11016
  }
10980
11017
  /**
10981
11018
  * Function to import a private key from the WIF
@@ -11124,21 +11161,24 @@ class Signer {
11124
11161
  /**
11125
11162
  * Function to sign and send a transaction. It internally uses
11126
11163
  * [[Provider.sendTransaction]]
11127
- * @param tx - Transaction to send. It will be signed inside this function
11128
- * if it is not signed yet
11129
- * @param broadcast - Option to broadcast the transaction to the
11130
- * different nodes in the network
11131
- * @param _abis - Collection of Abis to parse the operations in the
11132
- * transaction. This parameter is optional.
11133
- * @returns
11164
+ * @param transaction - Transaction to send. It will be signed inside this
11165
+ * function if it is not signed yet
11166
+ * @param options - Options for sending the transaction
11134
11167
  */
11135
- async sendTransaction(tx, broadcast, _abis) {
11168
+ async sendTransaction(transaction, options) {
11136
11169
  var _a;
11137
- if (!tx.signatures || !((_a = tx.signatures) === null || _a === void 0 ? void 0 : _a.length))
11138
- tx = await this.signTransaction(tx);
11170
+ if (!transaction.signatures || !((_a = transaction.signatures) === null || _a === void 0 ? void 0 : _a.length))
11171
+ transaction = await this.signTransaction(transaction);
11139
11172
  if (!this.provider)
11140
11173
  throw new Error("provider is undefined");
11141
- return this.provider.sendTransaction(tx, broadcast);
11174
+ const opts = {
11175
+ ...this.sendOptions,
11176
+ ...options,
11177
+ };
11178
+ if (opts.beforeSend) {
11179
+ await opts.beforeSend(transaction);
11180
+ }
11181
+ return this.provider.sendTransaction(transaction, opts.broadcast);
11142
11182
  }
11143
11183
  /**
11144
11184
  * Function to recover the public key from hash and signature