@ocap/tx-protocols 1.13.63 → 1.13.67

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 (31) hide show
  1. package/lib/execute.js +1 -1
  2. package/lib/protocols/account/declare.js +2 -1
  3. package/lib/protocols/account/delegate.js +23 -6
  4. package/lib/protocols/account/migrate.js +4 -3
  5. package/lib/protocols/account/revoke-delegate.js +4 -4
  6. package/lib/protocols/asset/acquire-v2.js +3 -2
  7. package/lib/protocols/asset/acquire-v3.js +47 -37
  8. package/lib/protocols/asset/create.js +22 -9
  9. package/lib/protocols/asset/mint.js +20 -9
  10. package/lib/protocols/asset/pipes/verify-itx-address.js +3 -3
  11. package/lib/protocols/asset/pipes/verify-mint-limit.js +1 -1
  12. package/lib/protocols/asset/update.js +7 -2
  13. package/lib/protocols/factory/create.js +21 -17
  14. package/lib/protocols/governance/claim-stake.js +6 -5
  15. package/lib/protocols/governance/revoke-stake.js +2 -2
  16. package/lib/protocols/governance/stake.js +3 -2
  17. package/lib/protocols/rollup/claim-reward.js +4 -3
  18. package/lib/protocols/rollup/create-block.js +8 -7
  19. package/lib/protocols/rollup/create.js +18 -5
  20. package/lib/protocols/rollup/join.js +4 -3
  21. package/lib/protocols/rollup/leave.js +4 -3
  22. package/lib/protocols/rollup/pipes/ensure-tx-fee.js +38 -0
  23. package/lib/protocols/rollup/update.js +2 -1
  24. package/lib/protocols/token/create.js +22 -11
  25. package/lib/protocols/token/deposit-v2.js +26 -20
  26. package/lib/protocols/token/withdraw-v2.js +6 -5
  27. package/lib/protocols/trade/exchange-v2.js +6 -6
  28. package/lib/protocols/trade/transfer-v2.js +21 -13
  29. package/lib/protocols/trade/transfer-v3.js +27 -13
  30. package/lib/util.js +10 -10
  31. package/package.json +13 -12
package/lib/execute.js CHANGED
@@ -29,7 +29,7 @@ module.exports = ({ filter, runAsLambda }) => {
29
29
  // Since bloom-filters may give false positive, we need to check for statedb if replay detected
30
30
  const exist = await context.statedb.tx.get(context.txHash, context);
31
31
  if (exist) {
32
- return next(new Error('FORBIDDEN', 'Can not execute duplicate transaction'));
32
+ return next(new Error('DUPLICATE_TX', 'Can not execute duplicate transaction'));
33
33
  }
34
34
  }
35
35
 
@@ -1,6 +1,7 @@
1
1
  const Error = require('@ocap/util/lib/error');
2
+ const Joi = require('@ocap/validator');
2
3
  const { Runner, pipes } = require('@ocap/tx-pipeline');
3
- const { account, Joi } = require('@ocap/state');
4
+ const { account } = require('@ocap/state');
4
5
  const { toBase58 } = require('@ocap/util');
5
6
 
6
7
  const runner = new Runner();
@@ -1,8 +1,9 @@
1
1
  /* eslint-disable max-len */
2
2
  const get = require('lodash/get');
3
+ const Joi = require('@ocap/validator');
3
4
  const Error = require('@ocap/util/lib/error');
4
5
  const getListField = require('@ocap/util/lib/get-list-field');
5
- const { delegation, account, Joi } = require('@ocap/state');
6
+ const { delegation, account } = require('@ocap/state');
6
7
  const { Runner, pipes } = require('@ocap/tx-pipeline');
7
8
  const { toDelegateAddress } = require('@arcblock/did-util');
8
9
 
@@ -61,9 +62,9 @@ runner.use(
61
62
  );
62
63
 
63
64
  // Ensure sender/receiver exist
64
- runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE' }));
65
+ runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'OK', table: 'account' }));
65
66
  runner.use(pipes.VerifyAccountMigration({ senderKey: 'senderState' }));
66
- runner.use(pipes.ExtractState({ from: 'itx.to', to: 'receiverState', status: 'INVALID_RECEIVER_STATE' }));
67
+ runner.use(pipes.ExtractState({ from: 'itx.to', to: 'receiverState', status: 'OK', table: 'account' }));
67
68
 
68
69
  // Extract delegation
69
70
  runner.use(pipes.ExtractState({ from: 'itx.address', to: 'delegationState', table: 'delegation', status: 'OK' }));
@@ -71,7 +72,7 @@ runner.use(pipes.ExtractState({ from: 'itx.address', to: 'delegationState', tabl
71
72
  // Create delegation state
72
73
  runner.use(
73
74
  async (context, next) => {
74
- const { tx, itx, ops, statedb, senderState, delegationState } = context;
75
+ const { tx, itx, ops, statedb, senderState, receiverState, delegationState } = context;
75
76
 
76
77
  const opsObj = ops.reduce(
77
78
  (acc, x) => {
@@ -86,8 +87,23 @@ runner.use(
86
87
  delegationState ? delegationState.ops : {}
87
88
  );
88
89
 
89
- const [newSenderState, newDelegationState] = await Promise.all([
90
- statedb.account.update(senderState.address, account.update(senderState, { nonce: tx.nonce }, context), context),
90
+ const sender = senderState ? senderState.address : tx.from;
91
+ const receiver = receiverState ? receiverState.address : itx.to;
92
+
93
+ const [newSenderState, newReceiverState, newDelegationState] = await Promise.all([
94
+ // update sender
95
+ statedb.account.updateOrCreate(
96
+ senderState,
97
+ account.updateOrCreate(senderState, { address: sender, nonce: tx.nonce, pk: tx.pk }, context),
98
+ context
99
+ ),
100
+
101
+ // update receiver
102
+ receiverState
103
+ ? Promise.resolve(receiverState)
104
+ : statedb.account.create(receiver, account.create({ address: receiver }, context), context),
105
+
106
+ // update delegation
91
107
  delegationState
92
108
  ? statedb.delegation.update(itx.address, delegation.update(delegationState, { ...itx, ops: opsObj }, context), context) // prettier-ignore
93
109
  : statedb.delegation.create(itx.address, delegation.create({ ...itx, ops: opsObj }, context), context),
@@ -97,6 +113,7 @@ runner.use(
97
113
 
98
114
  // Update context
99
115
  context.senderState = newSenderState;
116
+ context.receiverState = newReceiverState;
100
117
  context.delegationState = newDelegationState;
101
118
 
102
119
  return next();
@@ -1,8 +1,9 @@
1
1
  const Error = require('@ocap/util/lib/error');
2
+ const Joi = require('@ocap/validator');
2
3
  const getRelatedAddresses = require('@ocap/util/lib/get-related-addr');
3
4
  const { Runner, pipes } = require('@ocap/tx-pipeline');
4
5
  const { fromPublicKey, toTypeInfo } = require('@arcblock/did');
5
- const { account, Joi } = require('@ocap/state');
6
+ const { account } = require('@ocap/state');
6
7
 
7
8
  // eslint-disable-next-line global-require
8
9
  const debug = require('debug')(`${require('../../../package.json').name}:migrate`);
@@ -35,7 +36,7 @@ runner.use(
35
36
  );
36
37
 
37
38
  // Ensure sender exist
38
- runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE' }));
39
+ runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE', table: 'account' })); // prettier-ignore
39
40
  runner.use(pipes.VerifyAccountMigration({ senderKey: 'senderState' }));
40
41
 
41
42
  // Create account state, and update old accounts
@@ -48,7 +49,7 @@ runner.use(
48
49
 
49
50
  // Ensure receiver does not exist
50
51
  if (receiver) {
51
- return next(new Error('INVALID_SENDER_STATE', 'Can not migrate to an existing account'));
52
+ return next(new Error('INVALID_RECEIVER_STATE', 'Can not migrate to an existing account'));
52
53
  }
53
54
 
54
55
  // Create new account
@@ -1,8 +1,9 @@
1
1
  const get = require('lodash/get');
2
2
  const cloneDeep = require('lodash/cloneDeep');
3
+ const Joi = require('@ocap/validator');
3
4
  const getListField = require('@ocap/util/lib/get-list-field');
4
5
  const { Runner, pipes } = require('@ocap/tx-pipeline');
5
- const { delegation, account, Joi } = require('@ocap/state');
6
+ const { delegation, account } = require('@ocap/state');
6
7
  const { toDelegateAddress } = require('@arcblock/did-util');
7
8
 
8
9
  // eslint-disable-next-line global-require
@@ -53,10 +54,9 @@ runner.use(
53
54
  );
54
55
 
55
56
  // Ensure sender/receiver/delegation exist
56
- runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE' }));
57
+ runner.use(pipes.ExtractState({ from: 'itx.address', to: 'delegationState', status: 'INVALID_DELEGATION', table: 'delegation' })); // prettier-ignore
58
+ runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE', table: 'account' })); // prettier-ignore
57
59
  runner.use(pipes.VerifyAccountMigration({ senderKey: 'senderState' }));
58
- runner.use(pipes.ExtractState({ from: 'itx.to', to: 'receiverState', status: 'INVALID_RECEIVER_STATE' }));
59
- runner.use(pipes.ExtractState({ from: 'itx.address', to: 'delegationState', status: 'INVALID_DELEGATION' }));
60
60
 
61
61
  // Update delegation state
62
62
  runner.use(
@@ -24,7 +24,7 @@ const runner = new Runner();
24
24
  runner.use(pipes.VerifyMultiSig(0));
25
25
  runner.use(verifyAcquireParams('acquire-v2'));
26
26
 
27
- runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE' }));
27
+ runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE', table: 'account' })); // prettier-ignore
28
28
  runner.use(pipes.VerifyAccountMigration({ senderKey: 'senderState' }));
29
29
 
30
30
  runner.use(pipes.ExtractState({ from: 'tx.delegator', to: 'delegatorState', status: 'OK' }));
@@ -43,7 +43,7 @@ runner.use(
43
43
 
44
44
  // Though tokens are verified on factory creating phase, we need them here to construct tokenSymbols
45
45
  runner.use(extractFactoryTokens);
46
- runner.use(pipes.ExtractState({ from: 'tokenAddress', to: 'tokenStates', status: 'INVALID_TOKEN' }));
46
+ runner.use(pipes.ExtractState({ from: 'tokenAddress', to: 'tokenStates', status: 'INVALID_TOKEN', table: 'token' }));
47
47
 
48
48
  // Verify itx
49
49
  runner.use(verifyMintLimit);
@@ -86,6 +86,7 @@ runner.use(
86
86
  // Sender updates
87
87
  const senderUpdates = {
88
88
  nonce: tx.nonce,
89
+ pk: tx.pk,
89
90
  ...applyTokenUpdates(factoryTokens, senderState, 'sub'),
90
91
  };
91
92
 
@@ -82,9 +82,9 @@ runner.use(
82
82
  );
83
83
 
84
84
  // 5. verify sender & signer & owner
85
- runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE' }));
86
- runner.use(pipes.ExtractState({ from: 'senders', to: 'signerStates', status: 'INVALID_SIGNER_STATE' }));
87
- runner.use(pipes.ExtractState({ from: 'itx.owner', to: 'ownerState', status: 'INVALID_RECEIVER_STATE' }));
85
+ runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE', table: 'account' })); // prettier-ignore
86
+ runner.use(pipes.ExtractState({ from: 'senders', to: 'signerStates', status: 'INVALID_SIGNER_STATE', table: 'account' })); // prettier-ignore
87
+ runner.use(pipes.ExtractState({ from: 'itx.owner', to: 'ownerState', status: 'OK', table: 'account' }));
88
88
  runner.use(pipes.VerifyAccountMigration({ signerKey: 'signerStates', senderKey: 'senderState' }));
89
89
 
90
90
  // 6. verify token state and balance
@@ -153,6 +153,7 @@ runner.use(
153
153
  });
154
154
 
155
155
  const isAlsoSigner = !!signerUpdates[senderState.address];
156
+ const owner = ownerState ? ownerState.address : itx.owner;
156
157
 
157
158
  // Factory updates
158
159
  const factoryUpdates = { numMinted: factoryState.numMinted + 1 };
@@ -163,44 +164,53 @@ runner.use(
163
164
  context.tokenUpdates = applyTokenUpdates(factoryTokens, { tokens: {} }, 'add');
164
165
  }
165
166
 
166
- const [newSenderState, assetState, newSignerStates, newFactoryState, newAssetStates] = await Promise.all([
167
- // Update sender state
168
- statedb.account.update(
169
- senderState.address,
170
- account.update(
171
- senderState,
172
- Object.assign({ nonce: tx.nonce }, signerUpdates[senderState.address] || {}),
167
+ const [newSenderState, newReceiverState, assetState, newSignerStates, newFactoryState, newAssetStates] =
168
+ await Promise.all([
169
+ // Update sender state
170
+ statedb.account.update(
171
+ senderState.address,
172
+ account.update(
173
+ senderState,
174
+ Object.assign({ nonce: tx.nonce, pk: tx.pk }, signerUpdates[senderState.address] || {}),
175
+ context
176
+ ),
173
177
  context
174
178
  ),
175
- context
176
- ),
177
-
178
- // Create asset
179
- statedb.asset.create(
180
- itx.address,
181
- asset.create({ ...mintedAsset, owner: ownerState.address, address: mintedAddress }, context),
182
- context
183
- ),
184
-
185
- // Update signer state
186
- Promise.all(
187
- signerStates
188
- .filter((x) => x.address !== senderState.address)
189
- .map((x) => statedb.account.update(x.address, account.update(x, signerUpdates[x.address], context), context))
190
- ),
191
-
192
- // Update factory state
193
- statedb.factory.update(factoryState.address, factory.update(factoryState, factoryUpdates, context), context),
194
-
195
- // Mark asset as consumed
196
- Promise.all(
197
- assetStates.map((x) =>
198
- statedb.asset.update(x.address, asset.update(x, { consumedTime: txTime }, context), context)
199
- )
200
- ),
201
- ]);
179
+
180
+ // create receiver if not exist: asset owner
181
+ ownerState
182
+ ? Promise.resolve(ownerState)
183
+ : statedb.account.create(owner, account.create({ address: owner }, context), context),
184
+
185
+ // Create asset
186
+ statedb.asset.create(
187
+ itx.address,
188
+ asset.create({ ...mintedAsset, owner, address: mintedAddress }, context),
189
+ context
190
+ ),
191
+
192
+ // Update signer state
193
+ Promise.all(
194
+ signerStates
195
+ .filter((x) => x.address !== senderState.address)
196
+ .map((x) =>
197
+ statedb.account.update(x.address, account.update(x, signerUpdates[x.address], context), context)
198
+ )
199
+ ),
200
+
201
+ // Update factory state
202
+ statedb.factory.update(factoryState.address, factory.update(factoryState, factoryUpdates, context), context),
203
+
204
+ // Mark asset as consumed
205
+ Promise.all(
206
+ assetStates.map((x) =>
207
+ statedb.asset.update(x.address, asset.update(x, { consumedTime: txTime }, context), context)
208
+ )
209
+ ),
210
+ ]);
202
211
 
203
212
  context.senderState = newSenderState;
213
+ context.receiverState = newReceiverState;
204
214
  context.signerStates = isAlsoSigner ? newSignerStates.concat(newSenderState) : newSignerStates;
205
215
  context.assetState = assetState;
206
216
  context.factoryState = newFactoryState;
@@ -1,14 +1,17 @@
1
1
  /* eslint-disable indent */
2
2
  const Error = require('@ocap/util/lib/error');
3
+ const isEmpty = require('lodash/isEmpty');
3
4
  const cloneDeep = require('lodash/cloneDeep');
5
+ const Joi = require('@ocap/validator');
4
6
  const { Runner, pipes } = require('@ocap/tx-pipeline');
5
- const { account, asset, Joi } = require('@ocap/state');
7
+ const { account, asset } = require('@ocap/state');
6
8
  const { toAssetAddress } = require('@arcblock/did-util');
7
9
 
8
10
  // eslint-disable-next-line global-require
9
11
  const debug = require('debug')(`${require('../../../package.json').name}:create-asset`);
10
12
 
11
13
  const { decodeAnySafe } = require('../../util');
14
+ const ensureTxFee = require('../rollup/pipes/ensure-tx-fee');
12
15
 
13
16
  const runner = new Runner();
14
17
 
@@ -64,7 +67,7 @@ runner.use(
64
67
  );
65
68
 
66
69
  // Ensure sender exist
67
- runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE' }));
70
+ runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE', table: 'account' })); // prettier-ignore
68
71
  runner.use(pipes.VerifyAccountMigration({ senderKey: 'senderState' }));
69
72
 
70
73
  // Check if parent is a factory
@@ -74,7 +77,7 @@ runner.use(
74
77
  // For security consideration, user can not create fake assets from a factory
75
78
  // https://github.com/ArcBlock/asset-chain/issues/97
76
79
  {
77
- error: 'FORBIDDEN',
80
+ error: 'CREATE_FROM_FACTORY',
78
81
  message: 'You can only get asset from factory from acquire or mint',
79
82
  fn: ({ itx, factoryState }) => !(itx.parent && factoryState),
80
83
  persist: true,
@@ -83,26 +86,36 @@ runner.use(
83
86
  );
84
87
 
85
88
  // Ensure parent exist
86
- runner.use(pipes.ExtractState({ from: 'itx.parent', to: 'parentAsset', status: 'INVALID_ASSET' }));
89
+ runner.use(pipes.ExtractState({ from: 'itx.parent', to: 'parentAsset', status: 'INVALID_ASSET', table: 'asset' }));
90
+
91
+ runner.use(ensureTxFee);
87
92
 
88
93
  // Update asset state
89
94
  runner.use(
90
95
  async (context, next) => {
91
- const { tx, itx, assetData, statedb, senderState } = context;
96
+ const { tx, itx, assetData, statedb, senderState, senderUpdates, vaultState, vaultUpdates } = context;
97
+
98
+ const [newSenderState, assetState, newVaultState] = await Promise.all([
99
+ statedb.account.update(
100
+ senderState.address,
101
+ account.update(senderState, { nonce: tx.nonce, pk: tx.pk, ...senderUpdates }, context),
102
+ context
103
+ ),
92
104
 
93
- const [newSenderState, assetState] = await Promise.all([
94
- // Update owner state
95
- statedb.account.update(senderState.address, account.update(senderState, { nonce: tx.nonce }, context), context),
96
- // Create asset state
97
105
  statedb.asset.create(
98
106
  itx.address,
99
107
  asset.create({ ...itx, data: assetData, owner: senderState.address }, context),
100
108
  context
101
109
  ),
110
+
111
+ isEmpty(vaultUpdates)
112
+ ? vaultState
113
+ : statedb.account.update(vaultState.address, account.update(vaultState, vaultUpdates, context), context),
102
114
  ]);
103
115
 
104
116
  context.senderState = newSenderState;
105
117
  context.assetState = assetState;
118
+ context.vaultState = newVaultState;
106
119
 
107
120
  debug('createAsset', assetState);
108
121
 
@@ -17,21 +17,21 @@ runner.use(pipes.VerifyMultiSig(0));
17
17
  runner.use(verifyAcquireParams('mint'));
18
18
 
19
19
  // Ensure sender exist
20
- runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE' }));
20
+ runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE', table: 'account' })); // prettier-ignore
21
21
  runner.use(pipes.VerifyAccountMigration({ senderKey: 'senderState' }));
22
22
 
23
23
  // Ensure factory exist
24
24
  runner.use(pipes.ExtractState({ from: 'itx.factory', to: 'factoryState', status: 'INVALID_FACTORY_STATE', table: 'factory' })); // prettier-ignore
25
25
 
26
26
  // Used to assemble issuer object
27
- runner.use(pipes.ExtractState({ from: 'factoryState.owner', to: 'factoryOwnerState', status: 'INVALID_OWNER' }));
27
+ runner.use(pipes.ExtractState({ from: 'factoryState.owner', to: 'factoryOwnerState', status: 'INVALID_OWNER', table: 'account' })); // prettier-ignore
28
28
 
29
29
  // Ensure factory owner exist and equal to sender
30
- runner.use(pipes.ExtractState({ from: 'itx.owner', to: 'ownerState', status: 'INVALID_OWNER' }));
30
+ runner.use(pipes.ExtractState({ from: 'itx.owner', to: 'ownerState', status: 'OK', table: 'account' }));
31
31
  runner.use(
32
32
  pipes.VerifyInfo([
33
33
  {
34
- error: 'FORBIDDEN',
34
+ error: 'OWNER_ONLY_OPERATION',
35
35
  message: 'Only factory owner is allowed to mint',
36
36
  fn: ({ factoryState, senderState }) => factoryState.owner === senderState.address,
37
37
  persist: true,
@@ -72,20 +72,30 @@ runner.use(
72
72
  assetStates = [],
73
73
  } = context;
74
74
 
75
- // account updates
76
- const senderUpdates = { nonce: tx.nonce };
75
+ const owner = ownerState ? ownerState.address : itx.owner;
77
76
 
78
- // Factory updates
77
+ const senderUpdates = { nonce: tx.nonce, pk: tx.pk };
79
78
  const factoryUpdates = { numMinted: factoryState.numMinted + 1 };
80
79
 
81
- const [newSenderState, assetState, newFactoryState, newAssetStates] = await Promise.all([
80
+ const [newSenderState, newReceiverState, assetState, newFactoryState, newAssetStates] = await Promise.all([
81
+ // update sender
82
82
  statedb.account.update(senderState.address, account.update(senderState, senderUpdates, context), context),
83
+
84
+ // create receiver if not exist: asset owner
85
+ ownerState
86
+ ? Promise.resolve(ownerState)
87
+ : statedb.account.create(owner, account.create({ address: owner }, context), context),
88
+
89
+ // create asset
83
90
  statedb.asset.create(
84
91
  itx.address,
85
- asset.create({ ...mintedAsset, owner: ownerState.address, address: mintedAddress }, context),
92
+ asset.create({ ...mintedAsset, owner, address: mintedAddress }, context),
86
93
  context
87
94
  ),
95
+
96
+ // update factory
88
97
  statedb.factory.update(factoryState.address, factory.update(factoryState, factoryUpdates, context), context),
98
+
89
99
  // mark input assets as consumed
90
100
  Promise.all(
91
101
  assetStates.map((x) =>
@@ -95,6 +105,7 @@ runner.use(
95
105
  ]);
96
106
 
97
107
  context.senderState = newSenderState;
108
+ context.receiverState = newReceiverState;
98
109
  context.assetState = assetState;
99
110
  context.factoryState = newFactoryState;
100
111
  context.assetStates = newAssetStates;
@@ -10,11 +10,12 @@ module.exports = (mode) => (context, next) => {
10
10
  if (mode === 'acquire-v2') {
11
11
  owner = delegatorState || senderState;
12
12
  issuer = itx.issuer;
13
+ context.assetOwner = owner;
13
14
  } else if (mode === 'acquire-v3') {
14
- owner = ownerState;
15
+ owner = ownerState || { address: itx.owner };
15
16
  issuer = itx.issuer;
16
17
  } else if (mode === 'mint') {
17
- owner = ownerState;
18
+ owner = ownerState || { address: itx.owner };
18
19
  issuer = {
19
20
  id: factoryOwnerState.address,
20
21
  pk: factoryOwnerState.pk,
@@ -33,7 +34,6 @@ module.exports = (mode) => (context, next) => {
33
34
  return next(new Error('INVALID_ASSET', 'Invalid itx.address: does not match with minted asset address'));
34
35
  }
35
36
 
36
- context.assetOwner = owner;
37
37
  context.mintedAsset = minted.asset;
38
38
  context.mintedAddress = minted.address;
39
39
 
@@ -9,5 +9,5 @@ module.exports = ({ factoryState }, next) => {
9
9
  return next();
10
10
  }
11
11
 
12
- return next(new Error('FORBIDDEN', 'This request will exceed factory mint limit'));
12
+ return next(new Error('EXCEED_MINT_LIMIT', 'This request will exceed factory mint limit'));
13
13
  };
@@ -1,6 +1,7 @@
1
1
  const Error = require('@ocap/util/lib/error');
2
+ const Joi = require('@ocap/validator');
2
3
  const { Runner, pipes } = require('@ocap/tx-pipeline');
3
- const { account, asset, Joi } = require('@ocap/state');
4
+ const { account, asset } = require('@ocap/state');
4
5
 
5
6
  // eslint-disable-next-line global-require
6
7
  const debug = require('debug')(`${require('../../../package.json').name}:update-asset`);
@@ -52,7 +53,11 @@ runner.use(
52
53
 
53
54
  const [newSenderState, newAssetState] = await Promise.all([
54
55
  // update owner state
55
- statedb.account.update(senderState.address, account.update(senderState, { nonce: tx.nonce }, context), context),
56
+ statedb.account.update(
57
+ senderState.address,
58
+ account.update(senderState, { nonce: tx.nonce, pk: tx.pk }, context),
59
+ context
60
+ ),
56
61
 
57
62
  // update asset state
58
63
  statedb.asset.update(
@@ -14,6 +14,7 @@ const { toFactoryAddress } = require('@arcblock/did-util');
14
14
  const debug = require('debug')(`${require('../../../package.json').name}:create-factory`);
15
15
 
16
16
  const { decodeAnySafe } = require('../../util');
17
+ const ensureTxFee = require('../rollup/pipes/ensure-tx-fee');
17
18
 
18
19
  const runner = new Runner();
19
20
 
@@ -71,7 +72,7 @@ runner.use(pipes.ExtractState({ from: 'itx.address', to: 'factoryState', status:
71
72
  runner.use(
72
73
  pipes.VerifyInfo([
73
74
  {
74
- error: 'FORBIDDEN',
75
+ error: 'DUPLICATE_FACTORY',
75
76
  message: 'This asset factory already exist on chain',
76
77
  fn: (context) => isEmpty(context.factoryState),
77
78
  },
@@ -79,23 +80,15 @@ runner.use(
79
80
  );
80
81
 
81
82
  // Ensure sender exist
82
- runner.use(
83
- pipes.ExtractState({ from: 'tx.from', to: 'senderState', table: 'account', status: 'INVALID_SENDER_STATE' })
84
- );
83
+ runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', table: 'account', status: 'INVALID_SENDER_STATE' })); // prettier-ignore
85
84
  runner.use(pipes.VerifyAccountMigration({ senderKey: 'senderState' }));
86
85
 
87
86
  // Ensure tokens exist if we are creating an factory that consume tokens
88
- runner.use(
89
- pipes.ExtractState({ from: 'factoryTokens', to: 'tokenStates', table: 'token', status: 'INVALID_FACTORY_INPUT' })
90
- );
87
+ runner.use(pipes.ExtractState({ from: 'factoryTokens', to: 'tokenStates', table: 'token', status: 'INVALID_FACTORY_INPUT' })); // prettier-ignore
91
88
 
92
89
  // ensure input.assets all exist on chain
93
- runner.use(
94
- pipes.ExtractState({ from: 'factoryProps.input.assets', to: 'inputAssetStates', table: 'asset', status: 'OK' })
95
- );
96
- runner.use(
97
- pipes.ExtractState({ from: 'factoryProps.input.assets', to: 'inputFactoryStates', table: 'factory', status: 'OK' })
98
- );
90
+ runner.use(pipes.ExtractState({ from: 'factoryProps.input.assets', to: 'inputAssetStates', table: 'asset', status: 'OK' })); // prettier-ignore
91
+ runner.use(pipes.ExtractState({ from: 'factoryProps.input.assets', to: 'inputFactoryStates', table: 'factory', status: 'OK' })); // prettier-ignore
99
92
  runner.use((context, next) => {
100
93
  const { inputAssetStates = [], inputFactoryStates = [], factoryProps } = context;
101
94
  if (inputAssetStates.some((x) => !!x.consumedTime)) {
@@ -109,26 +102,37 @@ runner.use((context, next) => {
109
102
  return next(new Error('INVALID_FACTORY_INPUT', 'Not all input.assets exist on chain'));
110
103
  });
111
104
 
105
+ runner.use(ensureTxFee);
106
+
112
107
  // Create factory state
113
- // TODO: we need to support charging when creating new nft-factory
114
108
  runner.use(
115
109
  async (context, next) => {
116
- const { tx, itx, statedb, senderState, factoryProps } = context;
110
+ const { tx, itx, statedb, senderState, senderUpdates, vaultState, vaultUpdates, factoryProps } = context;
117
111
  const tokens = { [context.config.token.address]: '0' };
118
112
 
119
- const [newSenderState, factoryState] = await Promise.all([
113
+ const [newSenderState, factoryState, newVaultState] = await Promise.all([
120
114
  // Update owner state
121
- statedb.account.update(senderState.address, account.update(senderState, { nonce: tx.nonce }, context), context),
115
+ statedb.account.update(
116
+ senderState.address,
117
+ account.update(senderState, { nonce: tx.nonce, pk: tx.pk, ...senderUpdates }, context),
118
+ context
119
+ ),
120
+
122
121
  // Create factory state
123
122
  statedb.factory.create(
124
123
  itx.address,
125
124
  factory.create({ ...factoryProps, tokens, owner: senderState.address }, context),
126
125
  context
127
126
  ),
127
+
128
+ isEmpty(vaultUpdates)
129
+ ? vaultState
130
+ : statedb.account.update(vaultState.address, account.update(vaultState, vaultUpdates, context), context),
128
131
  ]);
129
132
 
130
133
  context.senderState = newSenderState;
131
134
  context.factoryState = factoryState;
135
+ context.vaultState = newVaultState;
132
136
 
133
137
  debug('createFactory', factoryState);
134
138
 
@@ -1,7 +1,8 @@
1
1
  const Error = require('@ocap/util/lib/error');
2
+ const Joi = require('@ocap/validator');
2
3
  const { BN } = require('@ocap/util');
3
4
  const { Runner, pipes } = require('@ocap/tx-pipeline');
4
- const { account, asset, stake, evidence, Joi } = require('@ocap/state');
5
+ const { account, asset, stake, evidence } = require('@ocap/state');
5
6
 
6
7
  // eslint-disable-next-line global-require
7
8
  const debug = require('debug')(`${require('../../../package.json').name}:acquire-asset-v2`);
@@ -16,7 +17,7 @@ runner.use(pipes.VerifyMultiSig(0));
16
17
  const schema = Joi.object({
17
18
  address: Joi.DID().role('ROLE_STAKE').required(),
18
19
  evidence: Joi.object({
19
- hash: Joi.string().regex(Joi.hashRegexp).required(),
20
+ hash: Joi.string().regex(Joi.patterns.txHash).required(),
20
21
  }).required(),
21
22
  data: Joi.any().optional(),
22
23
  }).options({ stripUnknown: true, noDefaults: false });
@@ -30,7 +31,7 @@ runner.use(pipes.ExtractState({ from: 'itx.address', to: 'stakeState', status: '
30
31
  runner.use(
31
32
  pipes.VerifyInfo([
32
33
  {
33
- error: 'FORBIDDEN',
34
+ error: 'SENDER_NOT_MATCH',
34
35
  message: 'You are not allowed to claim stake from this address',
35
36
  fn: ({ tx, stakeState }) => tx.from === stakeState.sender,
36
37
  },
@@ -42,7 +43,7 @@ runner.use(pipes.ExtractState({ from: 'itx.evidence.hash', to: 'evidenceState',
42
43
  runner.use(
43
44
  pipes.VerifyInfo([
44
45
  {
45
- error: 'FORBIDDEN',
46
+ error: 'ALREADY_CLAIMED',
46
47
  message: 'Revoke evidence already seen on this chain',
47
48
  fn: ({ evidenceState }) => !evidenceState,
48
49
  },
@@ -69,7 +70,7 @@ runner.use(
69
70
  fn: ({ txState, itx }) => txState.tx.itxJson.address === itx.address,
70
71
  },
71
72
  {
72
- error: 'FORBIDDEN',
73
+ error: 'WITHIN_WAITING_PERIOD',
73
74
  message: 'You can not claim stake before waiting period ends',
74
75
  fn: ({ txState, stakeState, txTime }) => {
75
76
  const end = +new Date(txState.time) + (stakeState.revokeWaitingPeriod || 0) * 1000;
@@ -49,12 +49,12 @@ runner.use(
49
49
  runner.use(
50
50
  pipes.VerifyInfo([
51
51
  {
52
- error: 'FORBIDDEN',
52
+ error: 'SENDER_NOT_MATCH',
53
53
  message: 'You are not allowed to revoke stake from this address',
54
54
  fn: ({ tx, stakeState }) => tx.from === stakeState.sender,
55
55
  },
56
56
  {
57
- error: 'FORBIDDEN',
57
+ error: 'STAKE_NOT_REVOCABLE',
58
58
  message: 'This stake address is not revocable',
59
59
  fn: ({ stakeState }) => stakeState.revocable,
60
60
  },
@@ -1,10 +1,11 @@
1
1
  const pick = require('lodash/pick');
2
2
  const { promisify } = require('util');
3
3
  const isEmpty = require('empty-value');
4
+ const Joi = require('@ocap/validator');
4
5
  const Error = require('@ocap/util/lib/error');
5
6
  const { Runner, pipes } = require('@ocap/tx-pipeline');
6
7
  const { toStakeAddress } = require('@arcblock/did-util');
7
- const { account, asset, stake, Joi } = require('@ocap/state');
8
+ const { account, asset, stake } = require('@ocap/state');
8
9
 
9
10
  // eslint-disable-next-line global-require
10
11
  const debug = require('debug')(`${require('../../../package.json').name}:acquire-asset-v2`);
@@ -122,7 +123,7 @@ runner.use(
122
123
  senderState.address,
123
124
  account.update(
124
125
  senderState,
125
- Object.assign({ nonce: tx.nonce }, signerUpdates[senderState.address] || {}),
126
+ Object.assign({ nonce: tx.nonce, pk: tx.pk }, signerUpdates[senderState.address] || {}),
126
127
  context
127
128
  ),
128
129
  context