koilib 5.7.0 → 7.0.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.
Files changed (45) hide show
  1. package/README.md +39 -40
  2. package/dist/koinos.js +1649 -83
  3. package/dist/koinos.min.js +1 -1
  4. package/lib/Contract.d.ts +12 -24
  5. package/lib/Contract.js +11 -23
  6. package/lib/Contract.js.map +1 -1
  7. package/lib/Provider.d.ts +257 -12
  8. package/lib/Provider.js +262 -9
  9. package/lib/Provider.js.map +1 -1
  10. package/lib/Signer.d.ts +75 -6
  11. package/lib/Signer.js +87 -6
  12. package/lib/Signer.js.map +1 -1
  13. package/lib/Transaction.d.ts +4 -3
  14. package/lib/Transaction.js +13 -10
  15. package/lib/Transaction.js.map +1 -1
  16. package/lib/browser/Contract.d.ts +12 -24
  17. package/lib/browser/Contract.js +11 -23
  18. package/lib/browser/Contract.js.map +1 -1
  19. package/lib/browser/Provider.d.ts +257 -12
  20. package/lib/browser/Provider.js +262 -9
  21. package/lib/browser/Provider.js.map +1 -1
  22. package/lib/browser/Signer.d.ts +75 -6
  23. package/lib/browser/Signer.js +87 -6
  24. package/lib/browser/Signer.js.map +1 -1
  25. package/lib/browser/Transaction.d.ts +4 -3
  26. package/lib/browser/Transaction.js +13 -10
  27. package/lib/browser/Transaction.js.map +1 -1
  28. package/lib/browser/interface.d.ts +33 -0
  29. package/lib/browser/utils.d.ts +39 -0
  30. package/lib/browser/utils.js +1276 -27
  31. package/lib/browser/utils.js.map +1 -1
  32. package/lib/interface.d.ts +33 -0
  33. package/lib/utils.d.ts +39 -0
  34. package/lib/utils.js +1276 -27
  35. package/lib/utils.js.map +1 -1
  36. package/package.json +1 -1
  37. package/src/Contract.ts +12 -24
  38. package/src/Provider.ts +271 -20
  39. package/src/Signer.ts +126 -7
  40. package/src/Transaction.ts +17 -16
  41. package/src/interface.ts +38 -0
  42. package/src/utils.ts +1283 -23
  43. package/lib/browser/jsonDescriptors/token-proto.json +0 -234
  44. package/lib/jsonDescriptors/token-proto.json +0 -234
  45. package/src/jsonDescriptors/token-proto.json +0 -234
package/src/Signer.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  import { sha256 } from "@noble/hashes/sha256";
3
3
  import * as secp from "@noble/secp256k1";
4
4
  import { Provider } from "./Provider";
5
+ import { Transaction } from "./Transaction";
5
6
  import {
6
7
  TransactionJson,
7
8
  TransactionJsonWait,
@@ -11,6 +12,7 @@ import {
11
12
  TypeField,
12
13
  TransactionReceipt,
13
14
  SendTransactionOptions,
15
+ ResourceCreditsOptions,
14
16
  } from "./interface";
15
17
  import {
16
18
  bitcoinAddress,
@@ -139,11 +141,6 @@ export class Signer implements SignerInterface {
139
141
  */
140
142
  address: string;
141
143
 
142
- /**
143
- * Chain id
144
- */
145
- chainId = "";
146
-
147
144
  /**
148
145
  * Provider to connect with the blockchain
149
146
  */
@@ -156,6 +153,33 @@ export class Signer implements SignerInterface {
156
153
  */
157
154
  sendOptions?: SendTransactionOptions;
158
155
 
156
+ /**
157
+ * Options related to the estimation of the rcLimit.
158
+ * By default the estimation is enabled and increased
159
+ * by 10%.
160
+ *
161
+ * @example
162
+ * This code estimates the mana by multiplying the rc_used
163
+ * by 2.
164
+ * ```ts
165
+ * const signer = new Signer({
166
+ * privateKey,
167
+ * provider,
168
+ * rcOptions: {
169
+ * estimateRc: true,
170
+ * adjustRcLimit: (receipt) => 2 * Number(receipt.rc_used),
171
+ * },
172
+ * });
173
+ *
174
+ * // you can also update rcOptions
175
+ * signer.rcOptions = {
176
+ * estimateRc: true,
177
+ * adjustRcLimit: (receipt) => 2 * Number(receipt.rc_used),
178
+ * }
179
+ * ```
180
+ */
181
+ rcOptions: ResourceCreditsOptions;
182
+
159
183
  /**
160
184
  * The constructor receives de private key as hexstring, bigint or Uint8Array.
161
185
  * See also the functions [[Signer.fromWif]] and [[Signer.fromSeed]]
@@ -164,6 +188,8 @@ export class Signer implements SignerInterface {
164
188
  * @param privateKey - Private key as hexstring, bigint or Uint8Array
165
189
  * @param compressed - compressed format is true by default
166
190
  * @param provider - provider to connect with the blockchain
191
+ * @param sendOptions - Send options
192
+ * @param rcOptions - options for mana estimation
167
193
  * @example
168
194
  * ```ts
169
195
  * const privateKey = "ec8601a24f81decd57f4b611b5ac6eb801cb3780bb02c0f9cdfe9d09daaddf9c";
@@ -171,13 +197,46 @@ export class Signer implements SignerInterface {
171
197
  * console.log(signer.getAddress());
172
198
  * // 1MbL6mG8ASAvSYdoMnGUfG3ZXkmQ2dpL5b
173
199
  * ```
200
+ *
201
+ * By default the mana is estimated as 110% the mana used. This
202
+ * estimation is computed using the "broadcast:false" option.
203
+ * For instance, if the transaction consumes 1 mana, the rc_limit
204
+ * will be set to 1.1 mana.
205
+ *
206
+ * You can also adjust the rc limit.
207
+ * @example
208
+ * ```ts
209
+ * const privateKey = "ec8601a24f81decd57f4b611b5ac6eb801cb3780bb02c0f9cdfe9d09daaddf9c";
210
+ * cons signer = new Signer({
211
+ * privateKey,
212
+ * provider,
213
+ * rcOptions: {
214
+ * estimateRc: true,
215
+ * // use 2 times rc_used as rc_limit
216
+ * adjustRcLimit: (r) => 2 * Number(r.rc_used),
217
+ * },
218
+ * });
219
+ * ```
220
+ *
221
+ * The rpc node must be highly trusted because the transaction
222
+ * is signed during the estimation of the mana. You can also
223
+ * disable the mana estimation:
224
+ * @example
225
+ * ```ts
226
+ * const privateKey = "ec8601a24f81decd57f4b611b5ac6eb801cb3780bb02c0f9cdfe9d09daaddf9c";
227
+ * cons signer = new Signer({
228
+ * privateKey,
229
+ * provider,
230
+ * rcOptions: { estimateRc: false },
231
+ * });
232
+ * ```
174
233
  */
175
234
  constructor(c: {
176
235
  privateKey: string | number | bigint | Uint8Array;
177
236
  compressed?: boolean;
178
- chainId?: string;
179
237
  provider?: Provider;
180
238
  sendOptions?: SendTransactionOptions;
239
+ rcOptions?: ResourceCreditsOptions;
181
240
  }) {
182
241
  this.compressed = typeof c.compressed === "undefined" ? true : c.compressed;
183
242
  this.privateKey = c.privateKey;
@@ -189,11 +248,20 @@ export class Signer implements SignerInterface {
189
248
  this.publicKey = secp.getPublicKey(c.privateKey, this.compressed);
190
249
  this.address = bitcoinAddress(this.publicKey);
191
250
  }
192
- if (c.chainId) this.chainId = c.chainId;
193
251
  this.sendOptions = {
194
252
  broadcast: true,
195
253
  ...c.sendOptions,
196
254
  };
255
+ this.rcOptions = c.rcOptions ?? {
256
+ estimateRc: true,
257
+ adjustRcLimit: (receipt) =>
258
+ Promise.resolve(
259
+ Math.min(
260
+ Number(receipt.max_payer_rc),
261
+ Math.floor(1.1 * Number(receipt.rc_used))
262
+ )
263
+ ),
264
+ };
197
265
  }
198
266
 
199
267
  /**
@@ -324,6 +392,18 @@ export class Signer implements SignerInterface {
324
392
  ): Promise<TransactionJson> {
325
393
  if (!tx.id) throw new Error("Missing transaction id");
326
394
 
395
+ // estimation of rcLimit
396
+ if (
397
+ this.rcOptions.estimateRc &&
398
+ (!tx.signatures || tx.signatures.length === 0)
399
+ ) {
400
+ const receipt = await this.estimateReceipt(tx);
401
+ tx.header!.rc_limit = this.rcOptions.adjustRcLimit
402
+ ? await this.rcOptions.adjustRcLimit(receipt)
403
+ : receipt.rc_used;
404
+ tx.id = Transaction.computeTransactionId(tx.header!);
405
+ }
406
+
327
407
  // multihash 0x1220. 12: code sha2-256. 20: length (32 bytes)
328
408
  // tx id is a stringified multihash, need to extract the hash digest only
329
409
  const hash = toUint8Array(tx.id.slice(6));
@@ -386,6 +466,45 @@ export class Signer implements SignerInterface {
386
466
  return this.provider.sendTransaction(transaction, opts.broadcast);
387
467
  }
388
468
 
469
+ /**
470
+ * Estimate the receipt associated to the transaction if
471
+ * it sent to the blockchain. It is useful to estimate the
472
+ * consumption of mana.
473
+ * The transaction is signed during this process and sent
474
+ * to the rpc node with the "broadcast:false" option to
475
+ * just compute the transaction without broadcasting it to
476
+ * the network.
477
+ * After that, the initial signatures are restored (if any)
478
+ * and the ones used for the estimation will be removed.
479
+ */
480
+ async estimateReceipt(
481
+ tx: TransactionJson | TransactionJsonWait
482
+ ): Promise<TransactionReceipt> {
483
+ if (!tx.id) throw new Error("Missing transaction id");
484
+ if (!tx.signatures) tx.signatures = [];
485
+ const signaturesCopy = [...tx.signatures];
486
+
487
+ // sign if there are no signatures
488
+ if (tx.signatures.length === 0) {
489
+ const hash = toUint8Array(tx.id.slice(6));
490
+ const signature = await this.signHash(hash);
491
+ tx.signatures.push(encodeBase64url(signature));
492
+ }
493
+
494
+ try {
495
+ const { receipt } = await this.sendTransaction(tx, {
496
+ broadcast: false,
497
+ });
498
+ // restore signatures
499
+ tx.signatures = signaturesCopy;
500
+ return receipt;
501
+ } catch (error) {
502
+ // restore signatures
503
+ tx.signatures = signaturesCopy;
504
+ throw error;
505
+ }
506
+ }
507
+
389
508
  /**
390
509
  * Function to recover the public key from hash and signature
391
510
  * @param hash - hash sha256
@@ -7,6 +7,7 @@ import {
7
7
  Abi,
8
8
  OperationJson,
9
9
  SendTransactionOptions,
10
+ TransactionHeaderJson,
10
11
  TransactionJson,
11
12
  TransactionOptions,
12
13
  TransactionReceipt,
@@ -137,7 +138,7 @@ export class Transaction {
137
138
  * @example
138
139
  * ```ts
139
140
  * const koin = new Contract({
140
- * id: "19JntSm8pSNETT9aHTwAUHC5RMoaSmgZPJ",
141
+ * id: "15DJN4a8SgrbGhhGksSBASiSYjGnMU8dGL",
141
142
  * abi: utils.tokenAbi,
142
143
  * }).functions;
143
144
  * const signer = Signer.fromSeed("my seed");
@@ -216,6 +217,19 @@ export class Transaction {
216
217
  this.transaction.operations.push(operation);
217
218
  }
218
219
 
220
+ static computeTransactionId(txHeader: TransactionHeaderJson): string {
221
+ const headerDecoded = btypeDecode(txHeader, btypeTransactionHeader!, false);
222
+ const message = koinos.protocol.transaction_header.create(headerDecoded);
223
+ const headerBytes = koinos.protocol.transaction_header
224
+ .encode(message)
225
+ .finish() as Uint8Array;
226
+
227
+ const hash = sha256(headerBytes);
228
+
229
+ // multihash 0x1220. 12: code sha2-256. 20: length (32 bytes)
230
+ return `0x1220${toHexString(hash)}`;
231
+ }
232
+
219
233
  /**
220
234
  * Function to prepare a transaction
221
235
  * @param tx - Do not set the nonce to get it from the blockchain
@@ -303,25 +317,12 @@ export class Transaction {
303
317
  // TODO: Option to resolve names (payer, payee)
304
318
  };
305
319
 
306
- const headerDecoded = btypeDecode(
307
- tx.header,
308
- btypeTransactionHeader!,
309
- false
310
- );
311
- const message = koinos.protocol.transaction_header.create(headerDecoded);
312
- const headerBytes = koinos.protocol.transaction_header
313
- .encode(message)
314
- .finish() as Uint8Array;
315
-
316
- const hash = sha256(headerBytes);
317
-
318
- // multihash 0x1220. 12: code sha2-256. 20: length (32 bytes)
319
- tx.id = `0x1220${toHexString(hash)}`;
320
+ tx.id = Transaction.computeTransactionId(tx.header);
320
321
  return tx;
321
322
  }
322
323
 
323
324
  /**
324
- * Functon to prepare the transaction (set headers, merkle
325
+ * Function to prepare the transaction (set headers, merkle
325
326
  * root, etc)
326
327
  */
327
328
  async prepare(options?: TransactionOptions): Promise<TransactionJson> {
package/src/interface.ts CHANGED
@@ -231,6 +231,39 @@ export interface DecodedOperationJson {
231
231
  args?: Record<string, unknown>;
232
232
  }
233
233
 
234
+ export interface ResourceCreditsOptions {
235
+ /**
236
+ * Boolean to define if the mana should be estimated
237
+ * and the rcLimit be updated before signing the transaction.
238
+ * It is true by default
239
+ */
240
+ estimateRc?: boolean;
241
+
242
+ /**
243
+ * Function to adjust the rc limit after the estimation.
244
+ * It is useful to give an extra margin to the rc limit.
245
+ * By default the Signer will use a function that increases
246
+ * the rcLimit by 10% with respect to the estimation.
247
+ *
248
+ * @example
249
+ * ```ts
250
+ * const signer = Signer.fromWif("Kab...");
251
+ * signer.rcOptions = {
252
+ * estimateRc: true,
253
+ * adjustRcLimit: async (receipt) => {
254
+ * return Math.min(
255
+ * Number(receipt.max_payer_rc),
256
+ * Math.floor(1.1 * Number(receipt.rc_used))
257
+ * );
258
+ * },
259
+ * }
260
+ * ```
261
+ */
262
+ adjustRcLimit?: (
263
+ receipt: TransactionReceipt
264
+ ) => Promise<string | number> | string | number;
265
+ }
266
+
234
267
  export interface SendTransactionOptions {
235
268
  /**
236
269
  * Broadcast
@@ -472,6 +505,11 @@ export type WaitFunction = (
472
505
  blockNumber?: number;
473
506
  }>;
474
507
 
508
+ export interface GetBlockOptions {
509
+ returnBlock?: boolean;
510
+ returnReceipt?: boolean;
511
+ }
512
+
475
513
  export interface GenesisDataEntryEncoded {
476
514
  space: {
477
515
  system?: boolean;