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