@ocap/tx-protocols 1.24.9 → 1.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/protocols/token/create.js +1 -1
- package/lib/protocols/token-factory/create.js +92 -11
- package/lib/protocols/token-factory/pipes/verify-icon.js +27 -0
- package/lib/protocols/token-factory/pipes/verify-ownership.js +58 -0
- package/lib/protocols/token-factory/pipes/verify-url.js +17 -0
- package/lib/protocols/token-factory/update.js +81 -7
- package/package.json +18 -16
|
@@ -23,7 +23,7 @@ runner.use(pipes.VerifyMultiSig(0));
|
|
|
23
23
|
const schema = Joi.object({
|
|
24
24
|
address: Joi.DID().prefix().role('ROLE_TOKEN').required(),
|
|
25
25
|
name: Joi.string().min(1).max(32).required(),
|
|
26
|
-
description: Joi.string().min(
|
|
26
|
+
description: Joi.string().min(16).max(128).required(),
|
|
27
27
|
symbol: Joi.string().min(2).max(6).uppercase().required(),
|
|
28
28
|
unit: Joi.string().min(1).max(6).lowercase().required(),
|
|
29
29
|
decimal: Joi.number().min(6).max(18).required(),
|
|
@@ -3,20 +3,24 @@ const cloneDeep = require('lodash/cloneDeep');
|
|
|
3
3
|
const { Joi } = require('@arcblock/validator');
|
|
4
4
|
const { CustomError: Error } = require('@ocap/util/lib/error');
|
|
5
5
|
const { Runner, pipes } = require('@ocap/tx-pipeline');
|
|
6
|
-
const { account, token, tokenFactory, delegation } = require('@ocap/state');
|
|
7
|
-
const { toTokenFactoryAddress, toTokenAddress } = require('@arcblock/did-util');
|
|
8
|
-
const {
|
|
6
|
+
const { account, token, tokenFactory, delegation, stake } = require('@ocap/state');
|
|
7
|
+
const { toTokenFactoryAddress, toTokenAddress, toStakeAddress } = require('@arcblock/did-util');
|
|
8
|
+
const { BN, fromTokenToUnit } = require('@ocap/util');
|
|
9
9
|
|
|
10
10
|
// eslint-disable-next-line global-require, import/order
|
|
11
11
|
const debug = require('debug')(`${require('../../../package.json').name}:create-token-factory`);
|
|
12
|
-
|
|
13
|
-
const { decodeAnySafe, getDelegationRequirements } = require('../../util');
|
|
12
|
+
const { applyTokenChange, decodeAnySafe, getDelegationRequirements } = require('../../util');
|
|
14
13
|
|
|
15
14
|
const EnsureTxGas = require('../../pipes/ensure-gas');
|
|
16
15
|
const EnsureTxCost = require('../../pipes/ensure-cost');
|
|
16
|
+
const verifyIcon = require('./pipes/verify-icon');
|
|
17
|
+
const verifyUrl = require('./pipes/verify-url');
|
|
18
|
+
const verifyOwnership = require('./pipes/verify-ownership');
|
|
17
19
|
|
|
18
20
|
const runner = new Runner();
|
|
19
21
|
|
|
22
|
+
const isTest = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test' || process.env.CI;
|
|
23
|
+
|
|
20
24
|
runner.use(pipes.VerifyMultiSig(0));
|
|
21
25
|
|
|
22
26
|
const schema = Joi.object({
|
|
@@ -26,12 +30,21 @@ const schema = Joi.object({
|
|
|
26
30
|
reserveAddress: Joi.DID().prefix().role('ROLE_TOKEN').required(),
|
|
27
31
|
token: Joi.object({
|
|
28
32
|
name: Joi.string().min(1).max(32).required(),
|
|
29
|
-
description: Joi.string().min(
|
|
33
|
+
description: Joi.string().min(16).max(128).required(),
|
|
30
34
|
symbol: Joi.string().min(2).max(6).uppercase().required(),
|
|
31
35
|
unit: Joi.string().min(1).max(6).lowercase().required(),
|
|
32
36
|
decimal: Joi.number().min(6).max(18).required(),
|
|
33
|
-
icon: Joi.string().optional().allow(null
|
|
37
|
+
icon: Joi.string().optional().allow(null, ''),
|
|
34
38
|
maxTotalSupply: Joi.alternatives().try(Joi.BN().greater(0), Joi.string().valid('')).optional().allow(null),
|
|
39
|
+
website: Joi.string()
|
|
40
|
+
.uri({
|
|
41
|
+
scheme: isTest ? ['http', 'https'] : ['https'],
|
|
42
|
+
allowRelative: false,
|
|
43
|
+
})
|
|
44
|
+
.max(256)
|
|
45
|
+
.optional()
|
|
46
|
+
.allow(null, ''),
|
|
47
|
+
metadata: Joi.any().required(),
|
|
35
48
|
}).required(),
|
|
36
49
|
data: Joi.any().optional().allow(null),
|
|
37
50
|
}).options({ stripUnknown: true, noDefaults: false });
|
|
@@ -46,6 +59,16 @@ runner.use((context, next) => {
|
|
|
46
59
|
// filter by curve type
|
|
47
60
|
context.itx.curve = value.curve;
|
|
48
61
|
|
|
62
|
+
// decode and verify metadata
|
|
63
|
+
if (context.itx.token.metadata) {
|
|
64
|
+
const metadata = decodeAnySafe(context.itx.token.metadata);
|
|
65
|
+
const { error: metadataError, value: metadataValue } = token.metadataSchema.validate(metadata.value);
|
|
66
|
+
if (metadataError) {
|
|
67
|
+
return next(new Error('INVALID_TX', `Invalid metadata: ${metadataError.message}`));
|
|
68
|
+
}
|
|
69
|
+
context.itx.token.metadata = { ...metadata, value: metadataValue };
|
|
70
|
+
}
|
|
71
|
+
|
|
49
72
|
return next();
|
|
50
73
|
});
|
|
51
74
|
|
|
@@ -80,6 +103,10 @@ runner.use(
|
|
|
80
103
|
])
|
|
81
104
|
);
|
|
82
105
|
|
|
106
|
+
runner.use(verifyIcon());
|
|
107
|
+
runner.use(verifyUrl({ urlKeys: ['itx.token.website', 'itx.token.metadata.value.communityUrl'] }));
|
|
108
|
+
runner.use(verifyOwnership({ tokenKey: 'itx.token' }));
|
|
109
|
+
|
|
83
110
|
// Ensure symbol is not internal
|
|
84
111
|
runner.use((context, next) => {
|
|
85
112
|
const { reservedSymbols } = context.config;
|
|
@@ -122,6 +149,36 @@ runner.use(pipes.VerifyAccountMigration({ stateKey: 'senderState', addressKey: '
|
|
|
122
149
|
|
|
123
150
|
runner.use(pipes.VerifyBlocked({ stateKeys: ['senderState'] }));
|
|
124
151
|
|
|
152
|
+
// verify staking: get address, extract state, verify amount
|
|
153
|
+
runner.use((context, next) => {
|
|
154
|
+
const { tx, itx } = context;
|
|
155
|
+
context.stakeAddress = toStakeAddress(tx.from, tx.from, itx.token.symbol);
|
|
156
|
+
return next();
|
|
157
|
+
});
|
|
158
|
+
runner.use(
|
|
159
|
+
pipes.ExtractState({ from: 'stakeAddress', to: 'stakeState', status: 'INVALID_STAKE_STATE', table: 'stake' })
|
|
160
|
+
);
|
|
161
|
+
runner.use((context, next) => {
|
|
162
|
+
const { stakeState, config } = context;
|
|
163
|
+
|
|
164
|
+
if (stakeState.revocable === false) {
|
|
165
|
+
return next(new Error('INVALID_STAKE_STATE', `Staking for token creating already locked: ${stakeState.address}`));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const actualStake = new BN(stakeState.tokens[config.token.address] || 0);
|
|
169
|
+
const requiredStake = fromTokenToUnit(config.transaction.txStake.createToken, config.token.decimal);
|
|
170
|
+
if (actualStake.lt(requiredStake)) {
|
|
171
|
+
return next(
|
|
172
|
+
new Error(
|
|
173
|
+
'INVALID_STAKE_STATE',
|
|
174
|
+
`Insufficient stake amount: required ${config.transaction.txStake.createToken} ${config.token.symbol}`
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return next();
|
|
180
|
+
});
|
|
181
|
+
|
|
125
182
|
// Ensure delegation
|
|
126
183
|
runner.use(pipes.ExtractState({ from: 'tx.delegator', to: 'delegatorState', status: 'OK', table: 'account' }));
|
|
127
184
|
runner.use(pipes.VerifyAccountMigration({ stateKey: 'delegatorState', addressKey: 'tx.delegator' }));
|
|
@@ -152,7 +209,7 @@ runner.use(
|
|
|
152
209
|
// Ensure tx fee and gas
|
|
153
210
|
runner.use(
|
|
154
211
|
EnsureTxGas((context) => {
|
|
155
|
-
const result = { create: 2, update:
|
|
212
|
+
const result = { create: 2, update: 2, payment: 0 };
|
|
156
213
|
|
|
157
214
|
if (context.isDelegationChanged) {
|
|
158
215
|
result.update += 1;
|
|
@@ -166,10 +223,22 @@ runner.use(EnsureTxCost({ attachSenderChanges: true }));
|
|
|
166
223
|
// Save context snapshot before updating states
|
|
167
224
|
runner.use(pipes.TakeStateSnapshot());
|
|
168
225
|
|
|
169
|
-
// Update sender state, token factory state
|
|
226
|
+
// Update sender state, token factory state, and lock stake
|
|
170
227
|
runner.use(
|
|
171
228
|
async (context, next) => {
|
|
172
|
-
const {
|
|
229
|
+
const {
|
|
230
|
+
tx,
|
|
231
|
+
itx,
|
|
232
|
+
statedb,
|
|
233
|
+
senderState,
|
|
234
|
+
delegatorState,
|
|
235
|
+
delegationState,
|
|
236
|
+
senderChange,
|
|
237
|
+
stakeState,
|
|
238
|
+
stakeAddress,
|
|
239
|
+
updateVaults,
|
|
240
|
+
config,
|
|
241
|
+
} = context;
|
|
173
242
|
const data = decodeAnySafe(itx.data);
|
|
174
243
|
const owner = delegatorState ? delegatorState.address : senderState.address;
|
|
175
244
|
|
|
@@ -181,7 +250,7 @@ runner.use(
|
|
|
181
250
|
? applyTokenChange({ tokens: senderTokens }, senderChange)
|
|
182
251
|
: { tokens: senderTokens };
|
|
183
252
|
|
|
184
|
-
const [newSenderState, newTokenState, newTokenFactoryState, newDelegationState] = await Promise.all([
|
|
253
|
+
const [newSenderState, newTokenState, newTokenFactoryState, newDelegationState, newStakeState] = await Promise.all([
|
|
185
254
|
statedb.account.update(
|
|
186
255
|
senderState.address,
|
|
187
256
|
account.update(senderState, { nonce: tx.nonce, pk: tx.pk, ...senderUpdates }, context),
|
|
@@ -213,6 +282,17 @@ runner.use(
|
|
|
213
282
|
context.isDelegationChanged
|
|
214
283
|
? statedb.delegation.update(delegationState.address, delegation.update(delegationState, {}, context), context)
|
|
215
284
|
: delegationState,
|
|
285
|
+
|
|
286
|
+
// Lock the stake after successful token creation
|
|
287
|
+
statedb.stake.update(
|
|
288
|
+
stakeAddress,
|
|
289
|
+
stake.update(
|
|
290
|
+
stakeState,
|
|
291
|
+
{ revocable: false, revokeWaitingPeriod: config.transaction.txStake.createTokenLockPeriod },
|
|
292
|
+
context
|
|
293
|
+
),
|
|
294
|
+
context
|
|
295
|
+
),
|
|
216
296
|
]);
|
|
217
297
|
|
|
218
298
|
await updateVaults();
|
|
@@ -221,6 +301,7 @@ runner.use(
|
|
|
221
301
|
context.tokenState = newTokenState;
|
|
222
302
|
context.tokenFactoryState = newTokenFactoryState;
|
|
223
303
|
context.delegationState = newDelegationState;
|
|
304
|
+
context.stakeState = newStakeState;
|
|
224
305
|
|
|
225
306
|
debug('create token factory', newTokenFactoryState);
|
|
226
307
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const get = require('lodash/get');
|
|
2
|
+
const set = require('lodash/set');
|
|
3
|
+
const { CustomError: Error } = require('@ocap/util/lib/error');
|
|
4
|
+
const { isSvgFile, sanitizeSvg } = require('@blocklet/xss');
|
|
5
|
+
|
|
6
|
+
module.exports =
|
|
7
|
+
({ iconKey = 'itx.token.icon', size = 16 * 1024 } = {}) =>
|
|
8
|
+
(context, next) => {
|
|
9
|
+
const icon = get(context, iconKey);
|
|
10
|
+
|
|
11
|
+
if (!icon) return next();
|
|
12
|
+
|
|
13
|
+
if (!isSvgFile(icon)) {
|
|
14
|
+
return next(new Error('INVALID_ICON', 'Token Icon is not a valid SVG file'));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const buffer = Buffer.from(icon, 'utf8');
|
|
18
|
+
if (buffer.length > size) {
|
|
19
|
+
return next(new Error('INVALID_ICON', `Token Icon must be less than ${Math.floor(size / 1024)}k`));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const sanitizedIcon = sanitizeSvg(icon);
|
|
23
|
+
|
|
24
|
+
set(context, iconKey, sanitizedIcon);
|
|
25
|
+
|
|
26
|
+
return next();
|
|
27
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const get = require('lodash/get');
|
|
2
|
+
const { CustomError: Error } = require('@ocap/util/lib/error');
|
|
3
|
+
const { verify: verifyVC } = require('@arcblock/vc');
|
|
4
|
+
|
|
5
|
+
module.exports =
|
|
6
|
+
({ tokenKey = 'itx.token' } = {}) =>
|
|
7
|
+
async (context, next) => {
|
|
8
|
+
const { symbol, address, website } = get(context, tokenKey) || {};
|
|
9
|
+
|
|
10
|
+
if (!website) return next();
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
tx: { from, delegator },
|
|
14
|
+
config: { chainId },
|
|
15
|
+
} = context;
|
|
16
|
+
|
|
17
|
+
const sender = delegator || from;
|
|
18
|
+
const verificationUrl = `${website}/.well-known/ocap/tokens.json`;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const response = await fetch(verificationUrl);
|
|
22
|
+
const data = await response.json();
|
|
23
|
+
|
|
24
|
+
const valids = await Promise.all(
|
|
25
|
+
data
|
|
26
|
+
.filter(Boolean)
|
|
27
|
+
.filter((item) => {
|
|
28
|
+
if (item.type !== 'TokenIssueCredential') return false;
|
|
29
|
+
if (item.issuer.id !== sender) return false;
|
|
30
|
+
|
|
31
|
+
const { id, issued } = item.credentialSubject || {};
|
|
32
|
+
return (
|
|
33
|
+
id === sender &&
|
|
34
|
+
issued.address === address &&
|
|
35
|
+
issued.symbol === symbol &&
|
|
36
|
+
issued.chainId === chainId &&
|
|
37
|
+
issued.website === website
|
|
38
|
+
);
|
|
39
|
+
})
|
|
40
|
+
.map((item) => {
|
|
41
|
+
return verifyVC({
|
|
42
|
+
vc: item,
|
|
43
|
+
ownerDid: sender,
|
|
44
|
+
trustedIssuers: sender,
|
|
45
|
+
});
|
|
46
|
+
})
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (valids.some((valid) => valid)) {
|
|
50
|
+
return next();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
context.logger?.warn('Website verification failed', { address, symbol, website, data });
|
|
54
|
+
return next(new Error('INVALID_WEBSITE', `Website ${website} verification failed`));
|
|
55
|
+
} catch (error) {
|
|
56
|
+
return next(new Error('INVALID_WEBSITE', `Website ${website} verification failed: ${error.message}`));
|
|
57
|
+
}
|
|
58
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const get = require('lodash/get');
|
|
2
|
+
const { CustomError: Error } = require('@ocap/util/lib/error');
|
|
3
|
+
const { verifyUrl } = require('@ocap/util/lib/url');
|
|
4
|
+
|
|
5
|
+
module.exports =
|
|
6
|
+
({ urlKeys = ['itx.token.website', 'itx.token.metadata.value.communityUrl'] } = {}) =>
|
|
7
|
+
(context, next) => {
|
|
8
|
+
for (const key of urlKeys) {
|
|
9
|
+
const url = get(context, key);
|
|
10
|
+
if (url && !verifyUrl(url)) {
|
|
11
|
+
const name = key.split('.').pop();
|
|
12
|
+
return next(new Error('INVALID_TX', `${name} is not valid`));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return next();
|
|
17
|
+
};
|
|
@@ -1,22 +1,41 @@
|
|
|
1
1
|
const { Joi } = require('@arcblock/validator');
|
|
2
2
|
const { CustomError: Error } = require('@ocap/util/lib/error');
|
|
3
3
|
const { Runner, pipes } = require('@ocap/tx-pipeline');
|
|
4
|
-
const { account, tokenFactory, delegation } = require('@ocap/state');
|
|
5
|
-
const { applyTokenChange, getDelegationRequirements } = require('../../util');
|
|
4
|
+
const { account, tokenFactory, delegation, token } = require('@ocap/state');
|
|
5
|
+
const { applyTokenChange, getDelegationRequirements, decodeAnySafe } = require('../../util');
|
|
6
6
|
|
|
7
7
|
// eslint-disable-next-line global-require, import/order
|
|
8
8
|
const debug = require('debug')(`${require('../../../package.json').name}:update-token-factory`);
|
|
9
9
|
|
|
10
10
|
const EnsureTxGas = require('../../pipes/ensure-gas');
|
|
11
11
|
const EnsureTxCost = require('../../pipes/ensure-cost');
|
|
12
|
+
const verifyIcon = require('./pipes/verify-icon');
|
|
13
|
+
const verifyUrl = require('./pipes/verify-url');
|
|
14
|
+
const verifyOwnership = require('./pipes/verify-ownership');
|
|
12
15
|
|
|
13
16
|
const runner = new Runner();
|
|
14
17
|
|
|
18
|
+
const isTest = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test' || process.env.CI;
|
|
19
|
+
|
|
15
20
|
runner.use(pipes.VerifyMultiSig(0));
|
|
16
21
|
|
|
17
22
|
const schema = Joi.object({
|
|
18
23
|
address: Joi.DID().prefix().role('ROLE_TOKEN_FACTORY').required(),
|
|
19
|
-
feeRate: Joi.number().min(0).max(2000).
|
|
24
|
+
feeRate: Joi.number().min(0).max(2000).optional().allow(null),
|
|
25
|
+
token: Joi.object({
|
|
26
|
+
icon: Joi.string().optional().allow(null, ''),
|
|
27
|
+
website: Joi.string()
|
|
28
|
+
.uri({
|
|
29
|
+
scheme: isTest ? ['http', 'https'] : ['https'],
|
|
30
|
+
allowRelative: false,
|
|
31
|
+
})
|
|
32
|
+
.max(256)
|
|
33
|
+
.optional()
|
|
34
|
+
.allow(null, ''),
|
|
35
|
+
metadata: Joi.any().optional().allow(null),
|
|
36
|
+
})
|
|
37
|
+
.optional()
|
|
38
|
+
.allow(null),
|
|
20
39
|
data: Joi.any().optional().allow(null),
|
|
21
40
|
}).options({ stripUnknown: true, noDefaults: false });
|
|
22
41
|
|
|
@@ -27,9 +46,22 @@ runner.use((context, next) => {
|
|
|
27
46
|
return next(new Error('INVALID_TX', `Invalid itx: ${error.message}`));
|
|
28
47
|
}
|
|
29
48
|
|
|
49
|
+
// decode and verify metadata
|
|
50
|
+
if (context.itx.token?.metadata) {
|
|
51
|
+
const metadata = decodeAnySafe(context.itx.token.metadata);
|
|
52
|
+
const { error: metadataError, value: metadataValue } = token.metadataSchema.validate(metadata.value);
|
|
53
|
+
if (metadataError) {
|
|
54
|
+
return next(new Error('INVALID_TX', `Invalid metadata: ${metadataError.message}`));
|
|
55
|
+
}
|
|
56
|
+
context.itx.token.metadata = { ...metadata, value: metadataValue };
|
|
57
|
+
}
|
|
58
|
+
|
|
30
59
|
return next();
|
|
31
60
|
});
|
|
32
61
|
|
|
62
|
+
runner.use(verifyIcon({ iconKey: 'itx.token.icon' }));
|
|
63
|
+
runner.use(verifyUrl({ urlKeys: ['itx.token.website', 'itx.token.metadata.value.communityUrl'] }));
|
|
64
|
+
|
|
33
65
|
// ensure token factory exists
|
|
34
66
|
runner.use(
|
|
35
67
|
pipes.ExtractState({
|
|
@@ -40,6 +72,24 @@ runner.use(
|
|
|
40
72
|
})
|
|
41
73
|
);
|
|
42
74
|
|
|
75
|
+
// ensure token exists
|
|
76
|
+
runner.use(
|
|
77
|
+
pipes.ExtractState({
|
|
78
|
+
from: 'tokenFactoryState.tokenAddress',
|
|
79
|
+
to: 'tokenState',
|
|
80
|
+
table: 'token',
|
|
81
|
+
status: 'INVALID_TOKEN',
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// verify website
|
|
86
|
+
runner.use((context, next) => {
|
|
87
|
+
const { tokenState, itx } = context;
|
|
88
|
+
context.itxToken = { symbol: tokenState.symbol, address: tokenState.address, website: itx.token?.website };
|
|
89
|
+
return next();
|
|
90
|
+
});
|
|
91
|
+
runner.use(verifyOwnership({ tokenKey: 'itxToken' }));
|
|
92
|
+
|
|
43
93
|
// Ensure sender
|
|
44
94
|
runner.use(pipes.ExtractState({ from: 'tx.from', to: 'senderState', status: 'INVALID_SENDER_STATE', table: 'account' })); // prettier-ignore
|
|
45
95
|
runner.use(pipes.VerifyAccountMigration({ stateKey: 'senderState', addressKey: 'tx.from' }));
|
|
@@ -88,7 +138,17 @@ runner.use(pipes.TakeStateSnapshot());
|
|
|
88
138
|
// Update sender state, token factory state
|
|
89
139
|
runner.use(
|
|
90
140
|
async (context, next) => {
|
|
91
|
-
const {
|
|
141
|
+
const {
|
|
142
|
+
tx,
|
|
143
|
+
itx,
|
|
144
|
+
statedb,
|
|
145
|
+
senderState,
|
|
146
|
+
tokenFactoryState,
|
|
147
|
+
tokenState,
|
|
148
|
+
senderChange,
|
|
149
|
+
updateVaults,
|
|
150
|
+
delegationState,
|
|
151
|
+
} = context;
|
|
92
152
|
|
|
93
153
|
const { tokens: senderTokens = {} } = senderState;
|
|
94
154
|
|
|
@@ -96,7 +156,16 @@ runner.use(
|
|
|
96
156
|
? applyTokenChange({ tokens: senderTokens }, senderChange)
|
|
97
157
|
: { tokens: senderTokens };
|
|
98
158
|
|
|
99
|
-
const
|
|
159
|
+
const factoryUpdates = itx.feeRate ? { feeRate: itx.feeRate } : {};
|
|
160
|
+
const tokenUpdates = itx.token
|
|
161
|
+
? {
|
|
162
|
+
icon: itx.token?.icon || tokenState.icon,
|
|
163
|
+
website: itx.token?.website || tokenState.website,
|
|
164
|
+
metadata: itx.token?.metadata || tokenState.metadata,
|
|
165
|
+
}
|
|
166
|
+
: null;
|
|
167
|
+
|
|
168
|
+
const [newSenderState, newTokenFactoryState, newTokenState, newDelegationState] = await Promise.all([
|
|
100
169
|
statedb.account.update(
|
|
101
170
|
senderState.address,
|
|
102
171
|
account.update(senderState, { nonce: tx.nonce, pk: tx.pk, ...senderUpdates }, context),
|
|
@@ -105,10 +174,14 @@ runner.use(
|
|
|
105
174
|
|
|
106
175
|
statedb.tokenFactory.update(
|
|
107
176
|
tokenFactoryState.address,
|
|
108
|
-
tokenFactory.update(tokenFactoryState,
|
|
177
|
+
tokenFactory.update(tokenFactoryState, factoryUpdates, context),
|
|
109
178
|
context
|
|
110
179
|
),
|
|
111
180
|
|
|
181
|
+
tokenUpdates
|
|
182
|
+
? statedb.token.update(tokenState.address, token.update(tokenState, tokenUpdates, context), context)
|
|
183
|
+
: tokenState,
|
|
184
|
+
|
|
112
185
|
// Update delegation state
|
|
113
186
|
context.isDelegationChanged
|
|
114
187
|
? statedb.delegation.update(delegationState.address, delegation.update(delegationState, {}, context), context)
|
|
@@ -119,9 +192,10 @@ runner.use(
|
|
|
119
192
|
|
|
120
193
|
context.senderState = newSenderState;
|
|
121
194
|
context.tokenFactoryState = newTokenFactoryState;
|
|
195
|
+
context.tokenState = newTokenState;
|
|
122
196
|
context.delegationState = newDelegationState;
|
|
123
197
|
|
|
124
|
-
debug('update token factory', newTokenFactoryState);
|
|
198
|
+
debug('update token factory', newTokenFactoryState, newTokenState);
|
|
125
199
|
|
|
126
200
|
next();
|
|
127
201
|
},
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.25.1",
|
|
7
7
|
"description": "Predefined tx pipeline sets to execute certain type of transactions",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -13,24 +13,26 @@
|
|
|
13
13
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"dependencies": {
|
|
16
|
+
"@blocklet/xss": "^0.2.7",
|
|
16
17
|
"debug": "^4.3.6",
|
|
17
18
|
"deep-diff": "^1.0.2",
|
|
18
19
|
"empty-value": "^1.0.1",
|
|
19
20
|
"lodash": "^4.17.21",
|
|
20
21
|
"url-join": "^4.0.1",
|
|
21
|
-
"@arcblock/did": "1.
|
|
22
|
-
"@arcblock/did-util": "1.
|
|
23
|
-
"@arcblock/jwt": "1.
|
|
24
|
-
"@arcblock/validator": "1.
|
|
25
|
-
"@
|
|
26
|
-
"@ocap/client": "1.
|
|
27
|
-
"@ocap/mcrypto": "1.
|
|
28
|
-
"@ocap/merkle-tree": "1.
|
|
29
|
-
"@ocap/
|
|
30
|
-
"@ocap/
|
|
31
|
-
"@ocap/util": "1.
|
|
32
|
-
"@ocap/
|
|
33
|
-
"@ocap/
|
|
22
|
+
"@arcblock/did": "1.25.1",
|
|
23
|
+
"@arcblock/did-util": "1.25.1",
|
|
24
|
+
"@arcblock/jwt": "1.25.1",
|
|
25
|
+
"@arcblock/validator": "1.25.1",
|
|
26
|
+
"@arcblock/vc": "1.25.1",
|
|
27
|
+
"@ocap/client": "1.25.1",
|
|
28
|
+
"@ocap/mcrypto": "1.25.1",
|
|
29
|
+
"@ocap/merkle-tree": "1.25.1",
|
|
30
|
+
"@ocap/state": "1.25.1",
|
|
31
|
+
"@ocap/message": "1.25.1",
|
|
32
|
+
"@ocap/util": "1.25.1",
|
|
33
|
+
"@ocap/tx-pipeline": "1.25.1",
|
|
34
|
+
"@ocap/wallet": "1.25.1",
|
|
35
|
+
"@ocap/asset": "1.25.1"
|
|
34
36
|
},
|
|
35
37
|
"resolutions": {
|
|
36
38
|
"bn.js": "5.2.2",
|
|
@@ -39,8 +41,8 @@
|
|
|
39
41
|
"devDependencies": {
|
|
40
42
|
"jest": "^29.7.0",
|
|
41
43
|
"start-server-and-test": "^1.14.0",
|
|
42
|
-
"@ocap/e2e-test": "1.
|
|
43
|
-
"@ocap/statedb-memory": "1.
|
|
44
|
+
"@ocap/e2e-test": "1.25.1",
|
|
45
|
+
"@ocap/statedb-memory": "1.25.1"
|
|
44
46
|
},
|
|
45
47
|
"scripts": {
|
|
46
48
|
"lint": "eslint tests lib",
|