@ocap/client 1.6.3 → 1.6.10

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 (60) hide show
  1. package/README.md +1 -1
  2. package/dist/base.js +36 -22
  3. package/dist/base.js.map +1 -1
  4. package/dist/browser.d.ts +997 -590
  5. package/dist/browser.js +1 -8
  6. package/dist/browser.js.map +1 -1
  7. package/dist/bundle.js +3 -3
  8. package/dist/client.js +11 -7
  9. package/dist/client.js.map +1 -1
  10. package/dist/extension.js +502 -462
  11. package/dist/extension.js.map +1 -1
  12. package/dist/methods.js +0 -142
  13. package/dist/methods.js.map +1 -1
  14. package/dist/report.html +2 -2
  15. package/dist/schema/graphql.json +9048 -4442
  16. package/dist/schema/graphql.txt +2 -2
  17. package/dist/types.js +2143 -1924
  18. package/dist/types.js.map +1 -1
  19. package/docs/QUERIES.md +1547 -1494
  20. package/docs/README.md +3269 -3138
  21. package/examples/asset.js +7 -7
  22. package/examples/create-secondary-token.js +44 -0
  23. package/examples/declare.js +9 -9
  24. package/examples/{delegate_exchange_both.js → delegate-exchange-both.js} +12 -8
  25. package/examples/{delegate_exchange.js → delegate-exchange.js} +11 -7
  26. package/examples/{delegate_transfer.js → delegate-transfer.js} +12 -6
  27. package/examples/exchange-secondary-token.js +100 -0
  28. package/examples/exchange.js +9 -9
  29. package/examples/{migrate_account.js → migrate-account.js} +5 -5
  30. package/examples/run-no-debug.sh +8 -8
  31. package/examples/run.sh +8 -8
  32. package/examples/subscribe.js +16 -0
  33. package/examples/{transfer_asset.js → transfer-asset.js} +11 -11
  34. package/examples/{transfer_token.js → transfer-primary-token.js} +10 -10
  35. package/examples/transfer-secondary-token.js +62 -0
  36. package/lib/base.js +36 -22
  37. package/lib/base.js.map +1 -1
  38. package/lib/client.js +11 -7
  39. package/lib/client.js.map +1 -1
  40. package/lib/extension.js +502 -462
  41. package/lib/extension.js.map +1 -1
  42. package/lib/methods.js +0 -142
  43. package/lib/methods.js.map +1 -1
  44. package/lib/node.d.ts +997 -590
  45. package/lib/node.js +0 -6
  46. package/lib/node.js.map +1 -1
  47. package/lib/schema/graphql.json +9048 -4442
  48. package/lib/schema/graphql.txt +2 -2
  49. package/lib/types.js +2143 -1924
  50. package/lib/types.js.map +1 -1
  51. package/package.json +30 -32
  52. package/examples/atomic_swap.js +0 -145
  53. package/examples/consume_asset_gatekeeper.js +0 -105
  54. package/examples/consume_asset_simple.js +0 -91
  55. package/examples/declare_forgeweb.js +0 -60
  56. package/examples/declare_restricted.js +0 -47
  57. package/examples/delegate_atomic_swap.js +0 -177
  58. package/examples/get_free_token.js +0 -33
  59. package/examples/subscribe_new_block.js +0 -36
  60. package/examples/subscribe_transfer.js +0 -80
package/lib/extension.js CHANGED
@@ -1,17 +1,27 @@
1
1
  'use strict';
2
2
 
3
+ /* eslint-disable prefer-object-spread */
3
4
  /* eslint-disable no-underscore-dangle */
4
5
  /* eslint-disable object-curly-newline */
5
6
  const get = require('lodash/get');
7
+ const omit = require('lodash/omit');
8
+ const cloneDeep = require('lodash/cloneDeep');
6
9
  const camelCase = require('lodash/camelCase');
7
- const snakeCase = require('lodash/snakeCase');
8
- const padStart = require('lodash/padStart');
9
- const errorCodes = require('@ocap/proto/lib/gen/status-code.json');
10
- const { isValid: isValidDID, toTypeInfo } = require('@arcblock/did');
11
- const { toDelegateAddress, toSwapAddress, toAssetAddress } = require('@arcblock/did-util');
12
- const { transactions, typeUrls, multiSignTxs } = require('@ocap/proto');
13
- const { createMessage, getMessageType, decodeAny } = require('@ocap/message');
10
+ const { toTypeInfo, isValid } = require('@arcblock/did');
11
+ const { transactions, typeUrls, multiSignTxs, multiSignV2Txs } = require('@ocap/proto');
12
+ const { createMessage, getMessageType, toTypeUrl } = require('@ocap/message');
14
13
  const { bytesToHex, toBase58, toBase64, toHex, toBuffer, fromTokenToUnit, fromUnitToToken } = require('@ocap/util');
14
+ const { DEFAULT_TOKEN_DECIMAL } = require('@ocap/util/lib/constant');
15
+ const { formatFactoryState, preMintFromFactory, isValidFactory } = require('@ocap/asset');
16
+ const {
17
+ toDelegateAddress,
18
+ toAssetAddress,
19
+ toFactoryAddress,
20
+ toTokenAddress,
21
+ toStakeAddress,
22
+ toRollupAddress
23
+ } = require('@arcblock/did-util');
24
+
15
25
  const debug = require('debug')(require('../package.json').name);
16
26
 
17
27
  /**
@@ -22,6 +32,14 @@ const debug = require('debug')(require('../package.json').name);
22
32
  * @param {object} [{ encodeTxAsBase64 = false }={}]
23
33
  */
24
34
  const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
35
+ Object.defineProperty(client, 'ctx', {
36
+ value: {
37
+ loading: false,
38
+ ready: false,
39
+ callbacks: []
40
+ }
41
+ });
42
+
25
43
  /**
26
44
  * Format big number presentation amount to token number
27
45
  *
@@ -32,7 +50,7 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
32
50
  * @returns {string}
33
51
  */
34
52
  client.fromUnitToToken = async value => {
35
- const { token } = await client._ensureContext();
53
+ const { token } = await client.getContext();
36
54
  return fromUnitToToken(value, token.decimal);
37
55
  };
38
56
 
@@ -46,36 +64,13 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
46
64
  * @returns {BN}
47
65
  */
48
66
  client.fromTokenToUnit = async amount => {
49
- const { token } = await client._ensureContext();
67
+ const { token } = await client.getContext();
50
68
  return fromTokenToUnit(amount, token.decimal);
51
69
  };
52
70
 
53
- /**
54
- * Converts a relative locktime to absolute locktime
55
- *
56
- * @memberof GraphQLClient
57
- * @function
58
- * @name GraphQLClient#toLocktime
59
- * @param {number} number - number of blocks want to lock
60
- * @param {object} [options={}] - options to underlying methods
61
- * @returns {number}
62
- */
63
- client.toLocktime = async number => {
64
- const result = await client.doRawQuery(`{
65
- getChainInfo {
66
- code
67
- info {
68
- blockHeight
69
- }
70
- }
71
- }`);
72
-
73
- return +get(result, 'getChainInfo.info.blockHeight', 0) + number;
74
- };
75
-
76
71
  /**
77
72
  * List all transaction send methods
78
- * Each method can send one kind of transactions supported by forge core, such as `DeclareTx`, `PokeTx`
73
+ * Each method can send one kind of transactions supported by forge core, such as `DeclareTx`
79
74
  *
80
75
  * @memberof GraphQLClient
81
76
  * @function
@@ -112,7 +107,7 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
112
107
  * @name GraphQLClient#getTxMultiSignMethods
113
108
  * @returns {Array<string>} method name list
114
109
  */
115
- client.getTxMultiSignMethods = () => multiSignTxs.map(x => camelCase(`multi_sign_${x}`));
110
+ client.getTxMultiSignMethods = () => multiSignTxs.concat(multiSignV2Txs).map(x => camelCase(`multi_sign_${x}`));
116
111
 
117
112
  /**
118
113
  * Get protobuf message class by name, only supports forge-built-in types
@@ -139,17 +134,6 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
139
134
  return Transaction.deserializeBinary(toBuffer(input)).toObject();
140
135
  };
141
136
 
142
- if (typeof client._createResponseError !== 'function') {
143
- client._createResponseError = (code, method) => {
144
- const type = snakeCase(method);
145
- const message = (errorCodes[code][type] || errorCodes[code].default || code).trim();
146
- const error = new Error(`${code}: ${message}`);
147
- error.code = code;
148
- error.type = type;
149
- return error;
150
- };
151
- }
152
-
153
137
  /**
154
138
  * Ensure a connection is bootstrapped with some meta info fetched from chain node
155
139
  *
@@ -157,50 +141,97 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
157
141
  * @param {string} [conn=undefined]
158
142
  * @returns {object}
159
143
  */
160
- client._ensureContext = async () => {
161
- if (!client.context) {
162
- if (encodeTxAsBase64) {
163
- const result = await client.doRawQuery(`{
164
- getChainInfo {
165
- code
166
- info {
167
- network
168
- }
144
+ client.getContext = async () => {
145
+ if (client.ctx.ready) {
146
+ return client.context;
147
+ }
148
+
149
+ if (client.ctx.loading) {
150
+ return new Promise(resolve => {
151
+ client.ctx.callbacks.push(() => resolve(client.context));
152
+ });
153
+ }
154
+
155
+ client.ctx.loading = true;
156
+ const result = await client.doRawQuery(`{
157
+ getChainInfo {
158
+ code
159
+ info {
160
+ network
161
+ consensusVersion
162
+ }
163
+ }
164
+ getForgeState {
165
+ code
166
+ state {
167
+ token {
168
+ decimal
169
+ symbol
169
170
  }
170
- getForgeState {
171
- code
172
- state {
173
- token {
174
- decimal
175
- symbol
176
- }
177
- txConfig {
178
- poke {
179
- amount
180
- dailyLimit
181
- enabled
182
- }
183
- }
171
+ txConfig {
172
+ txFee {
173
+ fee
174
+ typeUrl
184
175
  }
185
176
  }
186
- }`);
177
+ }
178
+ }
179
+ }`);
180
+
181
+ client.context = {
182
+ chainId: get(result, 'getChainInfo.info.network'),
183
+ consensus: get(result, 'getChainInfo.info.consensusVersion'),
184
+ token: get(result, 'getForgeState.state.token'),
185
+ txConfig: get(result, 'getForgeState.state.txConfig'),
186
+ tokenStateMap: new Map()
187
+ };
187
188
 
188
- client.context = {
189
- chainId: get(result, 'getChainInfo.info.network'),
190
- token: get(result, 'getForgeState.state.token'),
191
- poke: get(result, 'getForgeState.state.txConfig.poke')
192
- };
189
+ client.ctx.ready = true;
190
+ client.ctx.loading = false;
191
+ client.ctx.callbacks.forEach(cb => cb());
192
+ debug('context ready');
193
+
194
+ return client.context;
195
+ };
196
+
197
+ client.getTokenStateMap = async addressList => {
198
+ const result = new Map();
199
+ const notExistAddressList = [];
200
+ addressList.forEach(address => {
201
+ if (client.context.tokenStateMap.has(address)) {
202
+ result.set(address, client.context.tokenStateMap.get(address));
193
203
  } else {
194
- const [{ state }, { info }] = await Promise.all([client.getForgeState(), client.getChainInfo()]);
195
- client.context = {
196
- chainId: info.network,
197
- token: state.token,
198
- poke: state.txConfig.poke
199
- };
204
+ notExistAddressList.push(address);
200
205
  }
206
+ });
207
+
208
+ if (result.size === addressList.length) {
209
+ return result;
201
210
  }
202
211
 
203
- return client.context;
212
+ const getTokenState = async address => {
213
+ const {
214
+ getTokenState: { code, state }
215
+ } = await client.doRawQuery(`{
216
+ getTokenState(address: "${address}") {
217
+ code
218
+ state {
219
+ decimal
220
+ }
221
+ }
222
+ }`);
223
+
224
+ if (code !== 'OK') {
225
+ throw new Error(`get token ${address} state failed`);
226
+ }
227
+
228
+ result.set(address, state);
229
+ client.context.tokenStateMap.set(address, state);
230
+ };
231
+
232
+ await Promise.all(notExistAddressList.map(address => getTokenState(address)));
233
+
234
+ return result;
204
235
  };
205
236
 
206
237
  // Unify a client wallet | forge managed wallet
@@ -214,7 +245,7 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
214
245
 
215
246
  if (typeof wallet.toAddress === 'function') {
216
247
  return {
217
- address: wallet.toAddress(),
248
+ address: wallet.address,
218
249
  publicKey: wallet.publicKey
219
250
  };
220
251
  }
@@ -236,14 +267,15 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
236
267
  * @param {object} [input.tx.from] - the sender address, can be derived from wallet
237
268
  * @param {object} [input.tx.nonce] - the tx nonce, defaults to Date.now if not set
238
269
  * @param {object} [input.tx.chainId] - the chainId
239
- * @param {object} [input.tx.signature] - the chainId
240
- * @param {object} [input.tx.signatures] - the chainId
241
- * @param {object} input.wallet - the wallet used to sign the transaction, either a forge managed wallet or user managed wallet
270
+ * @param {object} [input.tx.signature] - the signature
271
+ * @param {object} [input.tx.signatures] - the signature list
272
+ * @param {object} input.wallet - the wallet used to sign the transaction
242
273
  * @param {object} input.delegator - the wallet address that delegated permissions to the `input.wallet` address
243
274
  * @returns Promise
244
275
  */
245
276
  const txEncodeFn = async ({ tx, wallet, delegator }) => {
246
277
  const w = getWallet(wallet);
278
+ const context = await client.getContext();
247
279
 
248
280
  // Determine sender address
249
281
  const address = tx.from || w.address;
@@ -251,9 +283,8 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
251
283
 
252
284
  // Determine chainId & nonce, only attach new one when not exist
253
285
  const nonce = typeof tx.nonce === 'undefined' ? Date.now() : tx.nonce;
254
- let chainId = tx.chainId || (client.context ? client.context.chainId : '');
286
+ let chainId = tx.chainId || '';
255
287
  if (!chainId) {
256
- const context = await client._ensureContext();
257
288
  // eslint-disable-next-line prefer-destructuring
258
289
  chainId = context.chainId;
259
290
  }
@@ -277,6 +308,9 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
277
308
  itx = { type: x, value: tx.itx };
278
309
  }
279
310
 
311
+ const type = itx.typeUrl || toTypeUrl(itx.type);
312
+ const feeConfig = get(context, 'txConfig.txFee', []).find(t => t.typeUrl === type);
313
+
280
314
  const txObj = createMessage('Transaction', {
281
315
  from: tx.delegator ? address : delegator || address,
282
316
  nonce,
@@ -285,7 +319,8 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
285
319
  signature: tx.signature || Buffer.from([]),
286
320
  signatures,
287
321
  delegator: tx.delegator || (delegator ? address : ''),
288
- itx
322
+ itx,
323
+ serviceFee: feeConfig ? feeConfig.fee : '0'
289
324
  });
290
325
  const txToSignBytes = txObj.serializeBinary();
291
326
 
@@ -346,16 +381,6 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
346
381
  resolve(hash);
347
382
  }
348
383
  } catch (err) {
349
- if (Array.isArray(err.errors)) {
350
- const code = err.errors[0].message;
351
- if (errorCodes[code]) {
352
- const error = client._createResponseError(code, x);
353
- error.errors = err.errors;
354
- reject(error);
355
- return;
356
- }
357
- }
358
-
359
384
  reject(err);
360
385
  }
361
386
  });
@@ -410,13 +435,13 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
410
435
  tx.signaturesList.unshift({
411
436
  pk: wallet.publicKey,
412
437
  signer: delegator,
413
- delegator: wallet.toAddress(),
438
+ delegator: wallet.address,
414
439
  data
415
440
  });
416
441
  } else {
417
442
  tx.signaturesList.unshift({
418
443
  pk: wallet.publicKey,
419
- signer: wallet.toAddress(),
444
+ signer: wallet.address,
420
445
  delegator: '',
421
446
  data
422
447
  });
@@ -430,6 +455,31 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
430
455
  txMultiSignFn.__tx__ = multiSignMethod;
431
456
  client[multiSignMethod] = txMultiSignFn;
432
457
  }
458
+
459
+ if (multiSignV2Txs.includes(x)) {
460
+ const txMultiSignFn = async ({ tx, wallet, encoding = '' }) => {
461
+ if (typeof wallet.toAddress !== 'function') {
462
+ throw new Error('Multisig requires a valid wallet');
463
+ }
464
+
465
+ const signer = wallet.address;
466
+ const signatures = cloneDeep(tx.signatures || tx.signaturesList || []);
467
+ const item = signatures.find(s => s.signer === signer || s.delegator === signer);
468
+ if (!item) {
469
+ throw new Error('Signer not in the list');
470
+ }
471
+
472
+ tx.signaturesList = signatures.map(s => omit(s, ['signature']));
473
+ const { object, buffer } = await txEncodeFn({ tx, wallet });
474
+
475
+ item.signature = wallet.sign(bytesToHex(buffer));
476
+ object.signaturesList = signatures;
477
+ return _formatEncodedTx(object, encoding);
478
+ };
479
+ const multiSignMethod = camelCase(`multi_sign_${x}`);
480
+ txMultiSignFn.__tx__ = multiSignMethod;
481
+ client[multiSignMethod] = txMultiSignFn;
482
+ }
433
483
  });
434
484
 
435
485
  /**
@@ -450,9 +500,8 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
450
500
  let itxData = data;
451
501
 
452
502
  // If there is no data attached to the account, we can attach wallet type by default
453
- const typeData = wallet.type;
454
- if (!itxData && typeData) {
455
- itxData = { typeUrl: 'json', value: toTypeInfo(typeData, true) };
503
+ if (!itxData) {
504
+ itxData = { typeUrl: 'json', value: toTypeInfo(wallet.address, true) };
456
505
  }
457
506
 
458
507
  return client.sendDeclareTx({
@@ -463,53 +512,6 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
463
512
  }, extra);
464
513
  };
465
514
 
466
- /**
467
- * Prepare an declare transaction when the chain has enabled restricted declare
468
- *
469
- * @memberof GraphQLClient
470
- * @function
471
- * @name GraphQLClient#prepareDeclare
472
- * @param {object} params
473
- * @param {string} params.moniker - account moniker
474
- * @param {string} params.issuer - issuer address
475
- * @param {string} params.delegator - the delegator address
476
- * @param {WalletObject} params.wallet - the wallet that want to do the declare
477
- * @param {object} extra - other param to underlying client implementation
478
- * @returns {Promise} the `transaction` object once resolved
479
- */
480
- client.prepareDeclare = async ({ moniker, issuer, wallet, data, delegator = '' }, extra) => client.signDeclareTx({
481
- tx: {
482
- itx: {
483
- moniker,
484
- issuer,
485
- data
486
- }
487
- },
488
- delegator,
489
- wallet
490
- }, extra);
491
-
492
- /**
493
- * Finalize an declare transaction using the issuer's account
494
- *
495
- * @memberof GraphQLClient
496
- * @function
497
- * @name GraphQLClient#finalizeExchange
498
- * @param {object} params
499
- * @param {object} params.tx - the transaction object from `prepareExchange`
500
- * @param {string} params.delegator - who authorized this transaction
501
- * @param {object} params.data - extra data in the multi sig
502
- * @param {WalletObject} params.wallet - issuer's wallet
503
- * @param {object} extra - other param to underlying client implementation
504
- * @returns {Promise} the `transaction` object once resolved
505
- */
506
- client.finalizeDeclare = ({ tx, delegator = '', data, wallet }, extra) => client.multiSignDeclareTx({
507
- tx,
508
- delegator,
509
- data,
510
- wallet
511
- }, extra);
512
-
513
515
  /**
514
516
  * Migrate current account to a new account
515
517
  *
@@ -525,7 +527,7 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
525
527
  client.migrateAccount = ({ from, to }, extra) => client.sendAccountMigrateTx({
526
528
  tx: {
527
529
  itx: {
528
- address: to.toAddress(),
530
+ address: to.address,
529
531
  pk: to.publicKey,
530
532
  type: to.type
531
533
  }
@@ -562,12 +564,12 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
562
564
  throw new Error('Invalid type url provided for delegation');
563
565
  }
564
566
 
565
- const address = toDelegateAddress(from.toAddress(), to.toAddress());
567
+ const address = toDelegateAddress(from.address, to.address);
566
568
  const hash = await client.sendDelegateTx({
567
569
  tx: {
568
570
  itx: {
569
571
  address,
570
- to: to.toAddress(),
572
+ to: to.address,
571
573
  ops
572
574
  }
573
575
  },
@@ -593,8 +595,8 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
593
595
  client.revokeDelegate = ({ from, to, privileges }, extra) => client.sendRevokeDelegateTx({
594
596
  tx: {
595
597
  itx: {
596
- address: toDelegateAddress(from.toAddress(), to.toAddress()),
597
- to: to.toAddress(),
598
+ address: toDelegateAddress(from.address, to.address),
599
+ to: to.address,
598
600
  typeUrls: privileges.filter(Boolean).map(x => x.toString())
599
601
  }
600
602
  },
@@ -614,13 +616,28 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
614
616
  * @param {number} params.ttl - ttl after first consumption
615
617
  * @param {boolean} params.readonly - whether the asset can be updated after creation
616
618
  * @param {boolean} params.transferrable - whether the asset can be transferred to another account
619
+ * @param {object} params.display - the display of the asset
620
+ * @param {object} params.endpoint - the endpoint of the asset
621
+ * @param {string} params.tags - the tag list of the asset
617
622
  * @param {string} params.delegator - who authorized this transaction
618
623
  * @param {WalletObject} params.wallet - the initial owner of the asset
619
624
  * @param {object} extra - other param to underlying client implementation
620
625
  * @returns {Promise} the `[transactionHash, assetAddress]` once resolved
621
626
  */
622
- client.createAsset = async ({ moniker, parent = '', ttl = 0, data, readonly = false, transferrable = true, delegator = '', wallet }, extra) => {
623
- const payload = { moniker, parent, ttl, readonly, transferrable, data };
627
+ client.createAsset = async ({
628
+ moniker,
629
+ parent = '',
630
+ ttl = 0,
631
+ data,
632
+ readonly = false,
633
+ transferrable = true,
634
+ display,
635
+ endpoint,
636
+ tags = [],
637
+ delegator = '',
638
+ wallet
639
+ }, extra) => {
640
+ const payload = { moniker, parent, ttl, readonly, transferrable, data, display, endpoint, tags };
624
641
  const address = toAssetAddress(payload);
625
642
  payload.address = address;
626
643
  const hash = await client.sendCreateAssetTx({
@@ -641,12 +658,11 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
641
658
  * @param {string} params.address - asset address
642
659
  * @param {string} params.moniker - asset name
643
660
  * @param {object} params.data - asset data payload
644
- * @param {string} params.delegator - who authorized this transaction
645
661
  * @param {WalletObject} params.wallet - the wallet to sign the transaction
646
662
  * @param {object} extra - other param to underlying client implementation
647
663
  * @returns {Promise} the `transactionHash` once resolved
648
664
  */
649
- client.updateAsset = ({ address, moniker, data, delegator, wallet }, extra) => client.sendUpdateAssetTx({
665
+ client.updateAsset = ({ address, moniker, data, wallet }, extra) => client.sendUpdateAssetTx({
650
666
  tx: {
651
667
  itx: {
652
668
  moniker,
@@ -654,344 +670,369 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
654
670
  data
655
671
  }
656
672
  },
657
- delegator,
658
673
  wallet
659
674
  }, extra);
660
675
 
661
676
  /**
662
- * Prepare a transaction that consumes an asset (non-fungible-token)
677
+ * Create an asset factory that can be used to mint new assets in future transactions
663
678
  *
664
679
  * @memberof GraphQLClient
665
680
  * @function
666
- * @name GraphQLClient#prepareConsumeAsset
681
+ * @name GraphQLClient#createAssetFactory
667
682
  * @param {object} params
668
- * @param {string} params.issuer - issuer address
669
- * @param {string} params.address - parent address
670
- * @param {object} params.data - extra data payload
671
- * @param {string} params.delegator - who authorized this transaction
672
- * @param {WalletObject} params.wallet - the wallet to sign the transaction
683
+ * @param {string} params.factory - asset factory
684
+ * @param {WalletObject} params.wallet - the initial owner of the asset
673
685
  * @param {object} extra - other param to underlying client implementation
674
- * @returns {Promise} the `transactionHash` once resolved
686
+ * @returns {Promise} the `[transactionHash, factoryAddress]` once resolved
675
687
  */
676
- client.prepareConsumeAsset = ({ issuer = '', address = '', delegator = '', data, wallet }, extra) => client.signConsumeAssetTx({
677
- tx: {
678
- itx: {
679
- issuer,
680
- address,
681
- data
682
- }
683
- },
684
- delegator,
685
- wallet
686
- }, extra);
688
+ client.createAssetFactory = async ({ factory, wallet }, extra) => {
689
+ const itx = {
690
+ name: factory.name,
691
+ description: factory.description,
692
+ settlement: factory.settlement || 'instant',
693
+ limit: factory.limit || 0,
694
+ trustedIssuers: factory.trustedIssuers || [],
695
+ input: factory.input,
696
+ output: factory.output,
697
+ data: factory.data || null,
698
+ hooks: factory.hooks || [],
699
+ display: factory.display || null
700
+ };
701
+
702
+ isValidFactory(itx, true);
703
+
704
+ itx.address = toFactoryAddress(itx);
705
+
706
+ const hash = await client.sendCreateFactoryTx({ tx: { itx }, wallet }, extra);
707
+ return [hash, itx.address];
708
+ };
687
709
 
688
710
  /**
689
- * Prepare a transaction that consumes an asset (non-fungible-token)
711
+ * Prepare an acquire_asset itx
690
712
  *
691
713
  * @memberof GraphQLClient
692
714
  * @function
693
- * @name GraphQLClient#finalizeConsumeAsset
715
+ * @name GraphQLClient#preMintAsset
694
716
  * @param {object} params
695
- * @param {object} params.tx - transaction to finalize, should be result from `prepareConsumeAsset`
696
- * @param {string} params.address - asset address to be consumed
697
- * @param {string} params.delegator - who authorized this transaction
698
- * @param {WalletObject} params.wallet - the wallet to sign the transaction
699
- * @param {object} extra - other param to underlying client implementation
700
- * @returns {Promise} the `transactionHash` once resolved
717
+ * @param {string} params.factory - asset factory address
718
+ * @param {object} params.inputs - factory inputs
719
+ * @param {string} params.owner - who will own the asset
720
+ * @param {WalletObject} params.wallet - the wallet of the asset issuer
721
+ * @param {object} extra - other param to merge into the itx
722
+ * @returns {Promise} the `[transactionHash, factoryAddress]` once resolved
701
723
  */
702
- client.finalizeConsumeAsset = ({ tx, address, delegator, wallet }, extra) => {
703
- if (isValidDID(address) === false) {
704
- throw new Error('Please provide valid asset address to consume');
724
+ client.preMintAsset = async ({ factory, inputs = {}, owner, wallet, extra = {} }) => {
725
+ const options = { ignoreFields: ['context.genesisTx', 'context.renaissanceTx'] };
726
+ const [{ state: factoryState }, { state: issuerState }] = await Promise.all([client.getFactoryState({ address: factory }, options), client.getAccountState({ address: wallet.address }, options)]);
727
+
728
+ if (!factoryState) {
729
+ throw new Error('Factory does not exist on chain');
705
730
  }
706
731
 
707
- return client.multiSignConsumeAssetTx({
708
- tx,
709
- wallet,
710
- delegator,
711
- data: {
712
- typeUrl: 'fg:x:address',
713
- value: Uint8Array.from(Buffer.from(address))
714
- }
715
- }, extra);
732
+ if (!issuerState) {
733
+ throw new Error('Issuer does not exist on chain');
734
+ }
735
+
736
+ const { asset, address, issuer, variables } = preMintFromFactory({
737
+ factory: formatFactoryState(factoryState),
738
+ inputs,
739
+ owner,
740
+ issuer: { wallet, name: issuerState.moniker }
741
+ });
742
+
743
+ return Object.assign({}, extra, {
744
+ asset: Object.assign({ address, owner, parent: factory }, asset),
745
+ factory,
746
+ address,
747
+ variables: Object.entries(variables).map(([key, value]) => ({ name: key, value })),
748
+ issuer,
749
+ owner
750
+ });
716
751
  };
717
752
 
718
753
  /**
719
- * Send a transaction that consumes an asset (non-fungible-token)
754
+ * Acquire an asset from factory
720
755
  *
721
756
  * @memberof GraphQLClient
722
757
  * @function
723
- * @name GraphQLClient#consumeAsset
758
+ * @name GraphQLClient#acquireAsset
724
759
  * @param {object} params
725
- * @param {object} params.tx - transaction to send, should be result from `finalizeConsumeAsset`
726
- * @param {WalletObject} params.wallet - the wallet to sign the transaction
760
+ * @param {AcquireAssetV2Tx} params.itx - result from preMintAsset
761
+ * @param {string} params.delegator - who authorized this transaction
762
+ * @param {WalletObject} params.wallet - the initial owner of the asset
727
763
  * @param {object} extra - other param to underlying client implementation
728
764
  * @returns {Promise} the `transactionHash` once resolved
729
765
  */
730
- client.consumeAsset = ({ tx, wallet }, extra) => client.sendConsumeAssetTx({ tx, wallet }, extra);
766
+ client.acquireAsset = ({ itx, delegator = '', wallet }, extra) => client.sendAcquireAssetV2Tx({ tx: { itx }, delegator, wallet }, extra);
731
767
 
732
768
  /**
733
- * Create an asset factory that can be used to produce multiple assets in a transaction
769
+ * Mint an asset from factory
734
770
  *
735
771
  * @memberof GraphQLClient
736
772
  * @function
737
- * @name GraphQLClient#createAssetFactory
773
+ * @name GraphQLClient#mintAsset
738
774
  * @param {object} params
739
- * @param {string} params.moniker - asset name
740
- * @param {object} params.factory - asset factory attributes
741
- * @param {string} params.factory.description - asset factory name
742
- * @param {number} params.factory.limit - how many assets can be generated from this factory
743
- * @param {price} params.factory.price - how much should charge user when acquire asset
744
- * @param {string} params.factory.template - mustache compatible
745
- * @param {Array} params.factory.templateVariables - list of allowed template variables
746
- * @param {string} params.factory.assetName - protobuf type known to forge that can be used to create this asset
747
- * @param {string} params.factory.attributes - attributes for assets that are generated from this factory
748
- * @param {boolean} params.readonly - whether the asset can be updated after creation
749
- * @param {boolean} params.transferrable - whether the asset can be transferred to another account
750
- * @param {string} params.delegator - who authorized this transaction
775
+ * @param {MintAssetTx} params.itx - result from preMintAsset
751
776
  * @param {WalletObject} params.wallet - the initial owner of the asset
752
777
  * @param {object} extra - other param to underlying client implementation
753
- * @returns {Promise} the `[transactionHash, factoryAddress]` once resolved
778
+ * @returns {Promise} the `transactionHash` once resolved
754
779
  */
755
- client.createAssetFactory = async ({ moniker, factory, readonly = false, transferrable = true, delegator = '', wallet }, extra) => {
756
- const payload = {
757
- moniker,
758
- readonly,
759
- transferrable,
760
- data: {
761
- type: 'AssetFactory',
762
- value: {
763
- description: factory.description,
764
- limit: factory.limit,
765
- price: await client.fromTokenToUnit(factory.price),
766
- template: factory.template,
767
- allowedSpecArgs: factory.templateVariables,
768
- assetName: factory.assetName,
769
- // eslint-disable-next-line prefer-object-spread
770
- attributes: Object.assign({ ttl: 0, transferrable: true }, factory.attributes || {})
771
- }
772
- }
773
- };
774
- const factoryAddress = toAssetAddress(payload);
775
- payload.address = factoryAddress;
776
-
777
- const hash = await client.sendCreateAssetTx({
778
- tx: {
779
- itx: payload
780
- },
781
- delegator,
782
- wallet
783
- }, extra);
784
- return [hash, factoryAddress];
785
- };
780
+ client.mintAsset = ({ itx, wallet }, extra) => client.sendMintAssetTx({ tx: { itx }, wallet }, extra);
786
781
 
787
782
  /**
788
- * Acquire an asset from factory
783
+ * Transfer token or assets to another account
789
784
  *
790
785
  * @memberof GraphQLClient
791
786
  * @function
792
- * @name GraphQLClient#acquireAsset
787
+ * @name GraphQLClient#transfer
793
788
  * @param {object} params
794
- * @param {string} params.assetFactory - Asset factory address
795
- * @param {Array} params.assetVariables - list of asset variables that can be populated into asset factory template
796
- * @param {boolean} params.readonly - whether the asset can be updated after creation, should match factory settings
797
- * @param {boolean} params.transferrable - whether the asset can be transferred to another account, should match factory settings
798
- * @param {number} params.ttl - asset expire
789
+ * @param {number} params.token - how much token can be transferred
790
+ * @param {Array} params.assets - which assets should be transferred
791
+ * @param {string} params.to - who receive the transfer
792
+ * @param {string} params.memo - transaction note
799
793
  * @param {string} params.delegator - who authorized this transaction
800
- * @param {WalletObject} params.wallet - the initial owner of the asset
794
+ * @param {WalletObject} params.wallet - the wallet to sign the transaction
801
795
  * @param {object} extra - other param to underlying client implementation
802
- * @returns {Promise} the `[transactionHash, [assetAddress]]` once resolved
796
+ * @returns {Promise} the `transactionHash` once resolved
803
797
  */
804
- client.acquireAsset = async ({ assetFactory, assetVariables, delegator = '', wallet }, extra) => {
805
- if (!assetFactory) {
806
- throw new Error('Must specify asset factory address');
798
+ client.transfer = async ({ token = 0, assets = [], tokens = [], to = '', memo = '', delegator = '', wallet }, extra) => {
799
+ if (isValid(to) === false) {
800
+ throw new Error('Can not transfer without valid recipient');
807
801
  }
808
- if (!Array.isArray(assetVariables)) {
809
- throw new Error('Must specify at least on asset template variable');
802
+ if (!token && tokens.length === 0 && assets.length === 0) {
803
+ throw new Error('Can not transfer without payload');
810
804
  }
811
805
 
812
- const { state } = await client.getAssetState({ address: assetFactory }, extra);
813
- if (!state) {
814
- throw new Error('Asset factory address does not exist on chain');
815
- }
806
+ const { token: contextToken } = await client.getContext();
816
807
 
817
- const decoded = decodeAny(state.data);
818
- if (!decoded) {
819
- throw new Error('Asset factory state cannot be decoded');
808
+ let tmpTokens = [];
809
+ if (tokens.length > 0) {
810
+ const tokensMap = await client.getTokenStateMap(tokens.map(t => t.address));
811
+ tmpTokens = tokens.map(t => {
812
+ t.value = fromTokenToUnit(t.value, tokensMap.get(t.address).decimal).toString();
813
+ return t;
814
+ });
820
815
  }
821
816
 
822
- const factory = decoded.value;
823
- debug('acquireAsset.factory', factory);
824
-
825
- const assets = assetVariables.map(x => {
826
- const payload = {
827
- readonly: true,
828
- transferrable: factory.attributes.transferrable,
829
- ttl: factory.attributes.ttl,
830
- parent: assetFactory,
831
- data: {
832
- type: factory.assetName,
833
- value: x
834
- }
835
- };
836
-
837
- const address = toAssetAddress(payload);
838
-
839
- return { address, data: JSON.stringify(x) };
840
- });
841
-
842
- const hash = await client.sendAcquireAssetTx({
817
+ return client.sendTransferV2Tx({
843
818
  tx: {
844
819
  itx: {
845
- to: assetFactory,
846
- specs: assets
820
+ to,
821
+ value: fromTokenToUnit(token, contextToken.decimal),
822
+ assets,
823
+ tokens: tmpTokens,
824
+ data: {
825
+ typeUrl: 'json',
826
+ value: memo || 'empty'
827
+ }
847
828
  }
848
829
  },
849
830
  delegator,
850
831
  wallet
851
832
  }, extra);
852
-
853
- return [hash, assets.map(x => x.address)];
854
833
  };
855
834
 
856
835
  /**
857
- * Do an on-chain upgrade, should be used with forge-cli
836
+ * Stake token or assets for another account
858
837
  *
859
838
  * @memberof GraphQLClient
860
839
  * @function
861
- * @name GraphQLClient#upgradeNode
840
+ * @name GraphQLClient#stake
862
841
  * @param {object} params
863
- * @param {number} params.height - at which height should the chain stop to perform the upgrade
864
- * @param {string} params.version - to which version should upgrade to
865
- * @param {string} params.delegator - who authorized this transaction
842
+ * @param {Array} params.assets - which assets to stake
843
+ * @param {Array} params.tokens - which tokens to stake
844
+ * @param {string} params.to - who receive the stake
845
+ * @param {string} params.locked - is the stake locked on creation
846
+ * @param {string} params.message - stake note
866
847
  * @param {WalletObject} params.wallet - the wallet to sign the transaction
867
848
  * @param {object} extra - other param to underlying client implementation
868
- * @returns {Promise} the `transactionHash` once resolved
849
+ * @returns {Promise} the `transactionHash` and `stakeAddress` once resolved
869
850
  */
870
- client.upgradeNode = ({ height, version, delegator, wallet }, extra) => client.sendUpgradeNodeTx({
871
- tx: { itx: { height, version, override: true } },
872
- delegator,
873
- wallet
874
- }, extra);
875
-
876
- /**
877
- * Setup a swap that's used to accomplish cross-chain operations
878
- *
879
- * @memberof GraphQLClient
880
- * @function
881
- * @name GraphQLClient#setupSwap
882
- * @param {object} params
883
- * @param {number} params.token - how much token to offer
884
- * @param {Array} params.assets - how much assets to offer
885
- * @param {string} params.receiver - who can retrieve this swap
886
- * @param {string} params.hashlock - sha3 from hashkey
887
- * @param {string} params.delegator - who authorized this transaction
888
- * @param {number} [params.locktime=1000] - how much block height to lock the swap before it can be revoked
889
- * @param {WalletObject} params.wallet - the wallet to sign the transaction
890
- * @param {object} extra - other param to underlying client implementation
891
- * @returns {Promise} the `[transactionHash, swapAddress]` once resolved
892
- */
893
- client.setupSwap = async ({
894
- token = 0,
895
- assets = [],
896
- receiver = '',
897
- hashlock = '',
898
- locktime = 1000,
899
- isLocktimeAbsolute = false,
900
- delegator = '',
901
- wallet
902
- }, extra) => {
903
- let finalLocktime = await client.toLocktime(locktime);
904
- if (isLocktimeAbsolute) {
905
- finalLocktime = locktime;
851
+ client.stake = async ({ assets = [], tokens = [], to = '', locked = false, message = '', wallet }, extra) => {
852
+ let tmpTokens = [];
853
+ if (tokens.length > 0) {
854
+ const tokensMap = await client.getTokenStateMap(tokens.map(t => t.address));
855
+ tmpTokens = tokens.map(t => {
856
+ t.value = fromTokenToUnit(t.value, tokensMap.get(t.address).decimal).toString();
857
+ return t;
858
+ });
906
859
  }
907
- const hash = await client.sendSetupSwapTx({
860
+
861
+ const from = wallet.address;
862
+ const address = toStakeAddress(from, to);
863
+ let tx = await client.multiSignStakeTx({
908
864
  tx: {
909
865
  itx: {
910
- value: await client.fromTokenToUnit(token),
911
- assets,
912
- receiver,
913
- hashlock: toBuffer(hashlock),
914
- locktime: finalLocktime
915
- }
866
+ address,
867
+ receiver: to,
868
+ locked,
869
+ message,
870
+ inputs: [{
871
+ owner: from,
872
+ assets,
873
+ tokens: tmpTokens
874
+ }]
875
+ },
876
+ signatures: [{
877
+ signer: from,
878
+ pk: wallet.publicKey
879
+ }]
916
880
  },
917
- delegator,
918
881
  wallet
919
882
  }, extra);
920
883
 
921
- const address = toSwapAddress(`0x${hash}`);
884
+ tx = await client.signStakeTx({ tx, wallet });
885
+ const hash = await client.sendStakeTx({ tx, wallet }, extra);
922
886
  return [hash, address];
923
887
  };
924
888
 
925
889
  /**
926
- * Retrieve a swap during an atomic-swap process
890
+ * Revoke token or assets from some stake
927
891
  *
928
892
  * @memberof GraphQLClient
929
893
  * @function
930
- * @name GraphQLClient#retrieveSwap
894
+ * @name GraphQLClient#revokeStake
931
895
  * @param {object} params
932
- * @param {string} params.address - the swap address to retrieve
933
- * @param {string} params.hashkey - the hashkey to unlock the swap
934
- * @param {string} params.delegator - who authorized this transaction
896
+ * @param {Array} params.assets - which assets to stake
897
+ * @param {Array} params.tokens - which tokens to stake
898
+ * @param {string} params.from - stake address
935
899
  * @param {WalletObject} params.wallet - the wallet to sign the transaction
936
900
  * @param {object} extra - other param to underlying client implementation
937
901
  * @returns {Promise} the `transactionHash` once resolved
938
902
  */
939
- client.retrieveSwap = ({ address, hashkey, delegator, wallet }, extra) => client.sendRetrieveSwapTx({
940
- tx: { itx: { address, hashkey: toBuffer(hashkey) } },
941
- delegator,
942
- wallet
943
- }, extra);
903
+ client.revokeStake = async ({ assets = [], tokens = [], from = '', wallet }, extra) => {
904
+ let tmpTokens = [];
905
+ if (tokens.length > 0) {
906
+ const tokensMap = await client.getTokenStateMap(tokens.map(t => t.address));
907
+ tmpTokens = tokens.map(t => {
908
+ t.value = fromTokenToUnit(t.value, tokensMap.get(t.address).decimal).toString();
909
+ return t;
910
+ });
911
+ }
912
+
913
+ return client.sendRevokeStakeTx({
914
+ tx: {
915
+ itx: {
916
+ address: from,
917
+ outputs: [{
918
+ owner: wallet.address,
919
+ assets,
920
+ tokens: tmpTokens
921
+ }]
922
+ }
923
+ },
924
+ wallet
925
+ }, extra);
926
+ };
944
927
 
945
928
  /**
946
- * Revoke a swap during an atomic-swap process
929
+ * Claim revoked token or assets from stake
947
930
  *
948
931
  * @memberof GraphQLClient
949
932
  * @function
950
- * @name GraphQLClient#revokeSwap
933
+ * @name GraphQLClient#claimStake
951
934
  * @param {object} params
952
- * @param {string} params.address - the swap address to revoke
953
- * @param {string} params.delegator - who authorized this transaction
935
+ * @param {string} params.from - stake address
936
+ * @param {Array} params.evidence - which revoke tx hash to use
954
937
  * @param {WalletObject} params.wallet - the wallet to sign the transaction
955
938
  * @param {object} extra - other param to underlying client implementation
956
939
  * @returns {Promise} the `transactionHash` once resolved
957
940
  */
958
- client.revokeSwap = ({ address, delegator, wallet }, extra) => client.sendRevokeSwapTx({
959
- tx: { itx: { address } },
960
- delegator,
961
- wallet
962
- }, extra);
941
+ client.claimStake = async ({ from, evidence, wallet }, extra) => {
942
+ if (!evidence) {
943
+ throw new Error('Can not claim stake without valid evidence tx hash');
944
+ }
945
+ if (!from) {
946
+ throw new Error('Can not claim stake without stake address');
947
+ }
948
+
949
+ return client.sendClaimStakeTx({
950
+ tx: {
951
+ itx: {
952
+ address: from,
953
+ evidence: { hash: evidence }
954
+ }
955
+ },
956
+ wallet
957
+ }, extra);
958
+ };
963
959
 
964
960
  /**
965
- * Transfer token or assets to another account
961
+ * Create an rollup (sub-chain that lives in ocap)
966
962
  *
967
963
  * @memberof GraphQLClient
968
964
  * @function
969
- * @name GraphQLClient#transfer
965
+ * @name GraphQLClient#createRollup
970
966
  * @param {object} params
971
- * @param {number} params.token - how much token can be transferred
972
- * @param {Array} params.assets - which assets should be transferred
973
- * @param {string} params.to - who receive the transfer
974
- * @param {string} params.memo - transaction note
975
- * @param {string} params.delegator - who authorized this transaction
976
- * @param {WalletObject} params.wallet - the wallet to sign the transaction
967
+ * @param {string} params.tokenAddress - ocap token address
968
+ * @param {string} params.contractAddress - rollup contract address
969
+ * @param {string} params.minStakeAmount
970
+ * @param {string} params.maxStakeAmount
971
+ * @param {number} params.minSignerCount
972
+ * @param {number} params.maxSignerCount
973
+ * @param {number} params.minBlockSize
974
+ * @param {number} params.maxBlockSize
975
+ * @param {number} params.minBlockInterval - in seconds
976
+ * @param {number} params.minBlockConfirmation
977
+ * @param {number} params.leaveWaitingPeriod
978
+ * @param {number} params.publishWaitingPeriod
979
+ * @param {number} params.publishSlashRate
980
+ * @param {Array} params.seedValidators - list of seed validators
981
+ * @param {object} params.data - data payload
982
+ * @param {WalletObject} params.wallet - the initial owner of the asset
977
983
  * @param {object} extra - other param to underlying client implementation
978
- * @returns {Promise} the `transactionHash` once resolved
984
+ * @returns {Promise} the `[transactionHash, rollupAddress]` once resolved
979
985
  */
980
- client.transfer = async ({ token = 0, assets = [], to = '', memo = '', delegator = '', wallet }, extra) => client.sendTransferTx({
981
- tx: {
982
- itx: {
983
- to,
984
- value: await client.fromTokenToUnit(token),
985
- assets,
986
- data: {
987
- typeUrl: 'json',
988
- value: memo || 'empty'
989
- }
986
+ client.createRollup = async (props, extra) => {
987
+ const requiredProps = ['tokenAddress', 'contractAddress', 'seedValidators', 'minStakeAmount'];
988
+ for (const key of requiredProps) {
989
+ if (!props[key]) {
990
+ throw new Error(`Missing required property: ${key} when creating rollup`);
990
991
  }
991
- },
992
- delegator,
993
- wallet
994
- }, extra);
992
+ }
993
+
994
+ const { state } = await client.getTokenState({ address: props.tokenAddress });
995
+ if (!state) {
996
+ throw new Error(`Token ${props.tokenAddress} not found when creating rollup`);
997
+ }
998
+ if (!state.foreignToken) {
999
+ throw new Error(`Token ${props.tokenAddress} does not have foreignToken attached`);
1000
+ }
1001
+
1002
+ const toBNStr = n => fromTokenToUnit(n, state.decimal).toString(10);
1003
+ const itx = Object.assign({
1004
+ maxStakeAmount: props.minStakeAmount,
1005
+ minSignerCount: 3,
1006
+ maxSignerCount: 5,
1007
+ minBlockSize: 1,
1008
+ maxBlockSize: 10,
1009
+ minBlockInterval: 1 * 60, // 1 minute
1010
+ minBlockConfirmation: 3,
1011
+ minDepositAmount: toBNStr(100),
1012
+ maxDepositAmount: toBNStr(1000000),
1013
+ minWithdrawAmount: toBNStr(100),
1014
+ maxWithdrawAmount: toBNStr(1000000),
1015
+ depositFeeRate: 100, // 1%
1016
+ withdrawFeeRate: 100, // 1%
1017
+ publisherFeeShare: 6000, // 60%
1018
+ proposerFeeShare: 3000, // 30%
1019
+ // validatorFeeShare: 1000, // 10%
1020
+ minDepositFee: toBNStr(1),
1021
+ maxDepositFee: toBNStr(10000),
1022
+ minWithdrawFee: toBNStr(1),
1023
+ maxWithdrawFee: toBNStr(10000),
1024
+ leaveWaitingPeriod: 60 * 60, // 1 hour
1025
+ publishWaitingPeriod: 60 * 60, // 1 hour
1026
+ publishSlashRate: 10 // 0.1%
1027
+ }, props);
1028
+
1029
+ const address = toRollupAddress(itx);
1030
+ itx.address = address;
1031
+
1032
+ const hash = await client.sendCreateRollupTx({ tx: { itx }, wallet: props.wallet }, extra);
1033
+
1034
+ return [hash, address];
1035
+ };
995
1036
 
996
1037
  /**
997
1038
  * Prepare an exchange transaction between multiple accounts
@@ -1016,31 +1057,49 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
1016
1057
  offerAssets = [],
1017
1058
  demandToken = 0,
1018
1059
  demandAssets = [],
1060
+ offerTokens = [],
1061
+ demandTokens = [],
1019
1062
  receiver = '',
1020
1063
  memo = '',
1021
1064
  delegator = '',
1022
1065
  wallet
1023
- }, extra) => client.signExchangeTx({
1024
- tx: {
1025
- itx: {
1026
- to: receiver,
1027
- sender: {
1028
- value: await client.fromTokenToUnit(offerToken),
1029
- assets: Array.isArray(offerAssets) ? offerAssets : []
1030
- },
1031
- receiver: {
1032
- value: await client.fromTokenToUnit(demandToken),
1033
- assets: Array.isArray(demandAssets) ? demandAssets : []
1034
- },
1035
- data: {
1036
- typeUrl: 'json',
1037
- value: memo || 'empty'
1066
+ }, extra) => {
1067
+ const { token } = await client.getContext();
1068
+ const tokensMap = await client.getTokenStateMap([...offerTokens, ...demandTokens].map(t => t.address));
1069
+
1070
+ const tmpOfferTokens = offerTokens.map(t => {
1071
+ t.value = fromTokenToUnit(t.value, tokensMap.get(t.address).decimal).toString();
1072
+ return t;
1073
+ });
1074
+ const tmpDemandTokens = demandTokens.map(t => {
1075
+ t.value = fromTokenToUnit(t.value, tokensMap.get(t.address).decimal).toString();
1076
+ return t;
1077
+ });
1078
+
1079
+ return client.signExchangeV2Tx({
1080
+ tx: {
1081
+ itx: {
1082
+ to: receiver,
1083
+ sender: {
1084
+ value: fromTokenToUnit(offerToken, token.decimal),
1085
+ assets: Array.isArray(offerAssets) ? offerAssets : [],
1086
+ tokens: tmpOfferTokens
1087
+ },
1088
+ receiver: {
1089
+ value: fromTokenToUnit(demandToken, token.decimal),
1090
+ assets: Array.isArray(demandAssets) ? demandAssets : [],
1091
+ tokens: tmpDemandTokens
1092
+ },
1093
+ data: {
1094
+ typeUrl: 'json',
1095
+ value: memo || 'empty'
1096
+ }
1038
1097
  }
1039
- }
1040
- },
1041
- delegator,
1042
- wallet
1043
- }, extra);
1098
+ },
1099
+ delegator,
1100
+ wallet
1101
+ }, extra);
1102
+ };
1044
1103
 
1045
1104
  /**
1046
1105
  * Finalize an exchange transaction between multiple accounts
@@ -1056,12 +1115,7 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
1056
1115
  * @param {object} extra - other param to underlying client implementation
1057
1116
  * @returns {Promise} the `transaction` object once resolved
1058
1117
  */
1059
- client.finalizeExchange = ({ tx, delegator = '', data, wallet }, extra) => client.multiSignExchangeTx({
1060
- tx,
1061
- delegator,
1062
- data,
1063
- wallet
1064
- }, extra);
1118
+ client.finalizeExchange = ({ tx, delegator = '', data, wallet }, extra) => client.multiSignExchangeV2Tx({ tx, delegator, data, wallet }, extra);
1065
1119
 
1066
1120
  /**
1067
1121
  * Send an exchange transaction
@@ -1075,65 +1129,51 @@ const createExtensionMethods = (client, { encodeTxAsBase64 = false } = {}) => {
1075
1129
  * @param {object} extra - other param to underlying client implementation
1076
1130
  * @returns {Promise} the `transactionHash` once resolved
1077
1131
  */
1078
- client.exchange = ({ tx, wallet }, extra) => client.sendExchangeTx({ tx, wallet }, extra);
1132
+ client.exchange = ({ tx, wallet }, extra) => client.sendExchangeV2Tx({ tx, wallet }, extra);
1079
1133
 
1080
1134
  /**
1081
- * Send a poke transaction to get some token for free
1135
+ * Create an new token
1082
1136
  *
1083
1137
  * @memberof GraphQLClient
1084
1138
  * @function
1085
- * @name GraphQLClient#checkin
1139
+ * @name GraphQLClient#createToken
1086
1140
  * @param {object} params
1087
- * @param {WalletObject} params.wallet - the wallet to sign the transaction, also who will get the token
1141
+ * @param {string} params.name
1142
+ * @param {string} params.description
1143
+ * @param {string} params.symbol
1144
+ * @param {string} params.unit
1145
+ * @param {string} params.icon
1146
+ * @param {number} params.totalSupply
1147
+ * @param {number} params.initialSupply
1148
+ * @param {number} params.foreignToken
1149
+ * @param {object} params.data - asset data payload
1150
+ * @param {WalletObject} params.wallet - the initial owner of the asset
1088
1151
  * @param {object} extra - other param to underlying client implementation
1089
- * @returns {Promise} the `transactionHash` once resolved
1152
+ * @returns {Promise} the `[transactionHash, assetAddress]` once resolved
1090
1153
  */
1091
- client.checkin = ({ wallet }, extra) => {
1092
- const date = new Date();
1093
- const year = date.getUTCFullYear();
1094
- const month = date.getUTCMonth() + 1;
1095
- const day = date.getUTCDate();
1096
-
1097
- return client.sendPokeTx({
1098
- tx: {
1099
- nonce: 0,
1100
- itx: {
1101
- date: `${year}-${padStart(month, 2, '0')}-${padStart(day, 2, '0')}`,
1102
- address: 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
1103
- }
1104
- },
1105
- wallet
1106
- }, extra);
1107
- };
1154
+ client.createToken = async ({ name, description, symbol, unit, decimal, icon, totalSupply, initialSupply, foreignToken, data, wallet }, extra) => {
1155
+ const tokenDecimal = typeof decimal === 'undefined' ? DEFAULT_TOKEN_DECIMAL : decimal;
1108
1156
 
1109
- /**
1110
- * Send a refuel transaction to get some gas
1111
- *
1112
- * @memberof GraphQLClient
1113
- * @function
1114
- * @name GraphQLClient#refuel
1115
- * @param {object} params
1116
- * @param {WalletObject} params.wallet - the wallet to sign the transaction, also who will get the token
1117
- * @param {object} params.data - extra data to put in itx
1118
- * @param {object} extra - other param to underlying client implementation
1119
- * @returns {Promise} the `transactionHash` once resolved
1120
- */
1121
- client.refuel = ({ wallet, data }, extra) => {
1122
- const date = new Date();
1123
- const year = date.getUTCFullYear();
1124
- const month = date.getUTCMonth() + 1;
1125
- const day = date.getUTCDate();
1157
+ const payload = {
1158
+ name,
1159
+ description,
1160
+ symbol,
1161
+ unit,
1162
+ decimal: tokenDecimal,
1163
+ icon,
1164
+ totalSupply: fromTokenToUnit(totalSupply, tokenDecimal).toString(),
1165
+ initialSupply: fromTokenToUnit(initialSupply || totalSupply, tokenDecimal).toString(),
1166
+ foreignToken: foreignToken || null,
1167
+ data
1168
+ };
1126
1169
 
1127
- return client.sendRefuelTx({
1128
- tx: {
1129
- nonce: 0,
1130
- itx: {
1131
- date: `${year}-${padStart(month, 2, '0')}-${padStart(day, 2, '0')}`,
1132
- data
1133
- }
1134
- },
1170
+ const address = toTokenAddress(payload);
1171
+ payload.address = address;
1172
+ const hash = await client.sendCreateTokenTx({
1173
+ tx: { itx: payload },
1135
1174
  wallet
1136
1175
  }, extra);
1176
+ return [hash, address];
1137
1177
  };
1138
1178
  };
1139
1179