@ocap/state 1.28.9 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/esm/_virtual/rolldown_runtime.mjs +18 -0
  2. package/esm/contexts/state.d.mts +15 -0
  3. package/esm/contexts/state.mjs +17 -0
  4. package/esm/index.d.mts +20 -0
  5. package/esm/index.mjs +47 -0
  6. package/esm/states/account.d.mts +18 -0
  7. package/esm/states/account.mjs +91 -0
  8. package/esm/states/asset.d.mts +14 -0
  9. package/esm/states/asset.mjs +80 -0
  10. package/esm/states/blacklist.d.mts +36 -0
  11. package/esm/states/blacklist.mjs +71 -0
  12. package/esm/states/chain.d.mts +30 -0
  13. package/esm/states/chain.mjs +52 -0
  14. package/esm/states/delegation.d.mts +11 -0
  15. package/esm/states/delegation.mjs +42 -0
  16. package/esm/states/evidence.d.mts +12 -0
  17. package/esm/states/evidence.mjs +35 -0
  18. package/esm/states/factory.d.mts +12 -0
  19. package/esm/states/factory.mjs +76 -0
  20. package/esm/states/rollup-block.d.mts +13 -0
  21. package/esm/states/rollup-block.mjs +75 -0
  22. package/esm/states/rollup.d.mts +18 -0
  23. package/esm/states/rollup.mjs +215 -0
  24. package/esm/states/stake.d.mts +13 -0
  25. package/esm/states/stake.mjs +89 -0
  26. package/esm/states/token-factory.d.mts +13 -0
  27. package/esm/states/token-factory.mjs +76 -0
  28. package/esm/states/token.d.mts +14 -0
  29. package/esm/states/token.mjs +109 -0
  30. package/esm/states/tx.d.mts +233 -0
  31. package/esm/states/tx.mjs +867 -0
  32. package/esm/util.d.mts +6 -0
  33. package/esm/util.mjs +18 -0
  34. package/lib/_virtual/rolldown_runtime.cjs +43 -0
  35. package/lib/contexts/state.cjs +19 -0
  36. package/lib/contexts/state.d.cts +15 -0
  37. package/lib/index.cjs +121 -0
  38. package/lib/index.d.cts +20 -0
  39. package/lib/states/account.cjs +106 -0
  40. package/lib/states/account.d.cts +18 -0
  41. package/lib/states/asset.cjs +91 -0
  42. package/lib/states/asset.d.cts +14 -0
  43. package/lib/states/blacklist.cjs +74 -0
  44. package/lib/states/blacklist.d.cts +36 -0
  45. package/lib/states/chain.cjs +62 -0
  46. package/lib/states/chain.d.cts +30 -0
  47. package/lib/states/delegation.cjs +50 -0
  48. package/lib/states/delegation.d.cts +11 -0
  49. package/lib/states/evidence.cjs +44 -0
  50. package/lib/states/evidence.d.cts +12 -0
  51. package/lib/states/factory.cjs +85 -0
  52. package/lib/states/factory.d.cts +12 -0
  53. package/lib/states/rollup-block.cjs +85 -0
  54. package/lib/states/rollup-block.d.cts +13 -0
  55. package/lib/states/rollup.cjs +230 -0
  56. package/lib/states/rollup.d.cts +18 -0
  57. package/lib/states/stake.cjs +99 -0
  58. package/lib/states/stake.d.cts +13 -0
  59. package/lib/states/token-factory.cjs +86 -0
  60. package/lib/states/token-factory.d.cts +13 -0
  61. package/lib/states/token.cjs +121 -0
  62. package/lib/states/token.d.cts +14 -0
  63. package/lib/states/tx.cjs +889 -0
  64. package/lib/states/tx.d.cts +233 -0
  65. package/lib/util.cjs +19 -0
  66. package/lib/util.d.cts +6 -0
  67. package/package.json +46 -14
  68. package/lib/contexts/state.js +0 -19
  69. package/lib/index.js +0 -63
  70. package/lib/states/account.js +0 -95
  71. package/lib/states/asset.js +0 -91
  72. package/lib/states/blacklist.js +0 -103
  73. package/lib/states/chain.js +0 -49
  74. package/lib/states/delegation.js +0 -46
  75. package/lib/states/evidence.js +0 -35
  76. package/lib/states/factory.js +0 -92
  77. package/lib/states/rollup-block.js +0 -84
  78. package/lib/states/rollup.js +0 -297
  79. package/lib/states/stake.js +0 -83
  80. package/lib/states/token-factory.js +0 -74
  81. package/lib/states/token.js +0 -124
  82. package/lib/states/tx.js +0 -896
  83. package/lib/util.js +0 -28
@@ -1,103 +0,0 @@
1
- const fs = require('node:fs');
2
- const { isSameDid } = require('@ocap/util');
3
- const { CustomError: Error } = require('@ocap/util/lib/error');
4
- const { BloomFilter } = require('bloom-filters');
5
-
6
- class Blacklist {
7
- constructor({
8
- size = 256,
9
- numHashFns = 4,
10
- dumpPath = '',
11
- dumpInterval = 0,
12
- getBlockedAccounts = null,
13
- getTrustedAccounts = null,
14
- } = {}) {
15
- let filter;
16
-
17
- if (dumpPath && fs.existsSync(dumpPath)) {
18
- try {
19
- const json = JSON.parse(fs.readFileSync(dumpPath));
20
- filter = BloomFilter.fromJSON(json);
21
- } catch (_err) {
22
- throw new Error('INTERNAL', `Cat not read serialized blacklist from json${dumpPath}`);
23
- }
24
- }
25
-
26
- if (!filter) {
27
- filter = new BloomFilter(size, numHashFns);
28
- }
29
-
30
- this.dumpPath = dumpPath;
31
- this.filter = filter;
32
- this.getBlockedAccounts = getBlockedAccounts;
33
- this.getTrustedAccounts = getTrustedAccounts;
34
-
35
- if (dumpPath && dumpInterval > 0) {
36
- this.timer = setTimeout(() => {
37
- this.dump();
38
-
39
- // Schedule for next
40
- this.timer = setTimeout(() => {
41
- this.dump();
42
- }, dumpInterval);
43
- this.timer.unref();
44
- }, dumpInterval);
45
- this.timer.unref();
46
-
47
- process.on('beforeExit', () => {
48
- this.dump();
49
- });
50
- }
51
- }
52
-
53
- has(key) {
54
- return this.filter.has(key);
55
- }
56
-
57
- add(key) {
58
- return this.filter.add(key);
59
- }
60
-
61
- async isBlocked(address) {
62
- if (typeof this.getBlockedAccounts === 'function') {
63
- const blocked = await this.getBlockedAccounts();
64
- if (blocked.length) {
65
- return blocked.some((b) => isSameDid(b, address));
66
- }
67
- }
68
-
69
- return false;
70
- }
71
-
72
- async isTrusted(address) {
73
- if (typeof this.getTrustedAccounts === 'function') {
74
- const trustedAccounts = await this.getTrustedAccounts();
75
- if (trustedAccounts.length) {
76
- return trustedAccounts.some((b) => isSameDid(b, address));
77
- }
78
- }
79
-
80
- return false;
81
- }
82
-
83
- async getTrustedAccountConfig(address) {
84
- if (typeof this.getTrustedAccounts === 'function') {
85
- const trustedAccounts = await this.getTrustedAccounts();
86
- return trustedAccounts.find((x) => isSameDid(x.address, address));
87
- }
88
- return null;
89
- }
90
-
91
- dump() {
92
- try {
93
- const exported = this.filter.saveAsJSON();
94
- const tmpFile = `${this.dumpPath}~`;
95
- fs.writeFileSync(tmpFile, JSON.stringify(exported));
96
- fs.renameSync(tmpFile, this.dumpPath);
97
- } catch (_err) {
98
- // Do nothing
99
- }
100
- }
101
- }
102
-
103
- module.exports = Blacklist;
@@ -1,49 +0,0 @@
1
- const pick = require('lodash/pick');
2
- const isEqual = require('lodash/isEqual');
3
- const get = require('lodash/get');
4
- const { CustomError: Error } = require('@ocap/util/lib/error');
5
-
6
- const { create: createStateContext, update: updateStateContext } = require('../contexts/state');
7
-
8
- const create = (attrs) => {
9
- const context = { txTime: new Date().toISOString() };
10
- const chain = {
11
- context: createStateContext(context),
12
- ...pick(attrs, ['address', 'chainId', 'version', 'transaction', 'moderator', 'accounts', 'token', 'vaults']),
13
- };
14
-
15
- return chain;
16
- };
17
-
18
- const update = (state, updates) => {
19
- const immutableAttrs = ['chainId', 'moderator', 'token.symbol', 'token.decimal'];
20
-
21
- // should not update these attrs cause the token address is generated from these attrs
22
- if (!process.env.CHAIN_TOKEN_ADDRESS) {
23
- immutableAttrs.push(
24
- 'token.name',
25
- 'token.description',
26
- 'token.unit',
27
- 'token.totalSupply',
28
- 'token.initialSupply',
29
- 'token.foreignToken'
30
- );
31
- }
32
-
33
- for (const attr of immutableAttrs) {
34
- if (get(updates, attr) && !isEqual(get(updates, attr), get(state, attr))) {
35
- throw new Error('FORBIDDEN', `Cannot update ${attr} field on chain state`);
36
- }
37
- }
38
-
39
- const context = { txTime: new Date().toISOString() };
40
- const chain = {
41
- ...state,
42
- ...pick(updates, ['version', 'transaction', 'accounts', 'vaults', 'token']),
43
- context: updateStateContext(state.context, context),
44
- };
45
-
46
- return chain;
47
- };
48
-
49
- module.exports = { create, update };
@@ -1,46 +0,0 @@
1
- const pick = require('lodash/pick');
2
- const { toAddress } = require('@ocap/util');
3
-
4
- // FIXME: add better validation
5
- const { create: createStateContext, update: updateStateContext } = require('../contexts/state');
6
- const { nullify } = require('../util');
7
-
8
- const create = (attrs, context) => {
9
- const delegation = {
10
- context: createStateContext(context),
11
- ...pick(attrs, ['address', 'to', 'from', 'ops', 'data']),
12
- };
13
-
14
- if (!delegation.data) {
15
- delegation.data = null;
16
- }
17
-
18
- delegation.address = toAddress(delegation.address);
19
- delegation.ops = nullify(delegation.ops);
20
-
21
- return delegation;
22
- };
23
-
24
- const update = (state, attrs, context) => {
25
- const delegation = {
26
- ...state,
27
- ...pick(attrs, ['ops', 'data']),
28
- context: updateStateContext(state.context, context),
29
- };
30
-
31
- if (!delegation.data) {
32
- delegation.data = null;
33
- }
34
- if (!state.to && attrs.to) {
35
- delegation.to = toAddress(attrs.to);
36
- }
37
- if (!state.from && attrs.from) {
38
- delegation.from = toAddress(attrs.from);
39
- }
40
-
41
- delegation.ops = nullify(delegation.ops);
42
-
43
- return delegation;
44
- };
45
-
46
- module.exports = { create, update };
@@ -1,35 +0,0 @@
1
- const pick = require('lodash/pick');
2
- const { CustomError: Error } = require('@ocap/util/lib/error');
3
- const { Joi, schemas, patterns } = require('@arcblock/validator');
4
-
5
- const { create: createStateContext } = require('../contexts/state');
6
-
7
- const schema = Joi.object({
8
- hash: Joi.string().regex(patterns.txHash).required(),
9
- context: schemas.context,
10
- data: Joi.any().optional().allow(null),
11
- }).options({ stripUnknown: true, noDefaults: false });
12
-
13
- const create = (attrs, context) => {
14
- const evidence = {
15
- context: createStateContext(context),
16
- ...pick(attrs, ['hash', 'data']),
17
- };
18
-
19
- return validate(evidence);
20
- };
21
-
22
- const validate = (state) => {
23
- const { value, error } = schema.validate(state);
24
- if (error) {
25
- throw new Error('INVALID_EVIDENCE', `Invalid evidence state: ${error.details.map((x) => x.message).join(', ')}`);
26
- }
27
-
28
- if (!value.data) {
29
- value.data = null;
30
- }
31
-
32
- return value;
33
- };
34
-
35
- module.exports = { create, validate, schema };
@@ -1,92 +0,0 @@
1
- const pick = require('lodash/pick');
2
- const { Joi, schemas } = require('@arcblock/validator');
3
- const { compile, merge, getQuota } = require('@ocap/contract');
4
- const { toAddress } = require('@ocap/util');
5
-
6
- const { create: createStateContext, update: updateStateContext } = require('../contexts/state');
7
-
8
- const stateSchema = Joi.object({
9
- ...schemas.factoryProps,
10
- owner: Joi.DID().prefix().required(),
11
- numMinted: Joi.number().min(0).default(0),
12
- lastSettlement: Joi.date().iso().raw().allow(''),
13
- tokens: Joi.object().pattern(Joi.DID().prefix().role('ROLE_TOKEN'), Joi.BN().min(0)).default({}),
14
- context: schemas.context,
15
- }).options({
16
- stripUnknown: true,
17
- noDefaults: false,
18
- });
19
-
20
- const compileHook = (hook, quota) => {
21
- if (hook.type === 'contract') {
22
- hook.compiled = merge(compile(hook.hook, quota));
23
- }
24
-
25
- return hook;
26
- };
27
-
28
- const create = (attrs, context) => {
29
- const factory = {
30
- numMinted: 0,
31
- lastSettlement: '',
32
- tokens: {},
33
- context: createStateContext(context),
34
- ...pick(attrs, [
35
- 'address',
36
- 'owner',
37
- 'name',
38
- 'description',
39
- 'settlement',
40
- 'limit',
41
- 'tokens',
42
- 'trustedIssuers',
43
- 'input',
44
- 'output',
45
- 'display',
46
- 'hooks',
47
- 'data',
48
- ]),
49
- };
50
-
51
- if (!factory.data) {
52
- factory.data = null;
53
- }
54
-
55
- const quota = getQuota(factory.input);
56
- factory.hooks = (factory.hooks || []).map((x) => compileHook(x, quota));
57
-
58
- factory.address = toAddress(factory.address);
59
-
60
- return validate(factory);
61
- };
62
-
63
- const update = (state, attrs, context) => {
64
- const factory = {
65
- ...state,
66
- ...pick(attrs, ['numMinted', 'tokens']),
67
- context: updateStateContext(state.context, context),
68
- };
69
-
70
- if (factory.output?.tags === null) {
71
- factory.output.tags = [];
72
- }
73
-
74
- return validate(factory);
75
- };
76
-
77
- const validate = (state) => {
78
- const { value, error } = stateSchema.validate(state);
79
- if (error) {
80
- throw new Error(`Invalid factory: ${error.details.map((x) => x.message).join(', ')}`);
81
- }
82
-
83
- ['display'].forEach((key) => {
84
- if (!value[key]) {
85
- delete value[key];
86
- }
87
- });
88
-
89
- return value;
90
- };
91
-
92
- module.exports = { create, update, validate };
@@ -1,84 +0,0 @@
1
- const pick = require('lodash/pick');
2
- const { CustomError: Error } = require('@ocap/util/lib/error');
3
- const { Joi, schemas, patterns } = require('@arcblock/validator');
4
-
5
- const { create: createStateContext, update: updateStateContext } = require('../contexts/state');
6
-
7
- const schema = Joi.object({
8
- hash: Joi.string().regex(patterns.txHash).required(),
9
- height: Joi.number().integer().greater(0).required(),
10
- merkleRoot: Joi.string().regex(patterns.txHash).required(),
11
- previousHash: Joi.string().when('height', {
12
- is: 1,
13
- then: Joi.string().optional().allow(null).allow(''),
14
- otherwise: Joi.string().regex(patterns.txHash).required(),
15
- }),
16
- txsHash: Joi.string().regex(patterns.txHash).required(),
17
- txs: Joi.array().items(Joi.string().regex(patterns.txHash).required()).min(1).unique().required(),
18
-
19
- proposer: Joi.DID().prefix().wallet('ethereum').required(),
20
- signatures: schemas.multiSig.min(1).required(),
21
-
22
- rollup: Joi.DID().prefix().role('ROLE_ROLLUP').required(),
23
-
24
- mintedAmount: Joi.BN().min(0).optional().allow(null).default('0'),
25
- burnedAmount: Joi.BN().min(0).optional().allow(null).default('0'),
26
- rewardAmount: Joi.BN().min(0).optional().allow(null).default('0'),
27
-
28
- minReward: Joi.BN().min(0).required(),
29
-
30
- governance: Joi.boolean().default(false),
31
-
32
- context: schemas.context,
33
- data: Joi.any().optional().allow(null),
34
- }).options({ stripUnknown: true, noDefaults: false });
35
-
36
- const create = (attrs, context) => {
37
- const block = {
38
- context: createStateContext(context),
39
- ...pick(attrs, [
40
- 'hash',
41
- 'height',
42
- 'merkleRoot',
43
- 'previousHash',
44
- 'txsHash',
45
- 'txs',
46
- 'proposer',
47
- 'signatures',
48
- 'rollup',
49
- 'mintedAmount',
50
- 'burnedAmount',
51
- 'rewardAmount',
52
- 'minReward',
53
- 'governance',
54
- 'data',
55
- ]),
56
- };
57
-
58
- return validate(block);
59
- };
60
-
61
- // We only support update block context
62
- const update = (state, context) => {
63
- const rollup = {
64
- ...state,
65
- context: updateStateContext(state.context, context),
66
- };
67
-
68
- return validate(rollup);
69
- };
70
-
71
- const validate = (state) => {
72
- const { value, error } = schema.validate(state);
73
- if (error) {
74
- throw new Error('INVALID_ROLLUP_BLOCK', `Invalid rollup block: ${error.details.map((x) => x.message).join(', ')}`);
75
- }
76
-
77
- if (!value.data) {
78
- value.data = null;
79
- }
80
-
81
- return value;
82
- };
83
-
84
- module.exports = { create, update, validate, schema };
@@ -1,297 +0,0 @@
1
- const pick = require('lodash/pick');
2
- const { CustomError: Error } = require('@ocap/util/lib/error');
3
- const { toAddress } = require('@ocap/util');
4
-
5
- const { Joi, schemas, patterns } = require('@arcblock/validator');
6
- const { create: createStateContext, update: updateStateContext } = require('../contexts/state');
7
-
8
- const validator = Joi.object({
9
- pk: Joi.string().required(),
10
- address: Joi.DID().prefix().required(),
11
- endpoint: Joi.string()
12
- .uri({ scheme: [/https?/] })
13
- .required(),
14
- });
15
-
16
- const schema = Joi.object({
17
- // a closed rollup must be paused
18
- address: Joi.DID().prefix().role('ROLE_ROLLUP').required(),
19
- tokenAddress: Joi.DID().prefix().role('ROLE_TOKEN').required(),
20
- contractAddress: Joi.DID().prefix().wallet('ethereum').required(),
21
- vaultAddress: Joi.DID().wallet('ethereum').optional().allow(null).allow(''), // FIXME: this should be enforced
22
- migrateHistory: Joi.array().items(Joi.DID().prefix().wallet('ethereum')).default([]),
23
- vaultHistory: Joi.array().items(Joi.DID().prefix().wallet('ethereum')).default([]),
24
- paused: Joi.boolean().default(false),
25
- closed: Joi.boolean().default(false),
26
-
27
- seedValidators: Joi.array().items(validator).min(1).required(),
28
- validators: Joi.array().items(validator).max(24).default([]),
29
-
30
- minStakeAmount: Joi.BN().positive().required(),
31
- maxStakeAmount: Joi.BN().min(Joi.ref('minStakeAmount')).required(),
32
-
33
- minSignerCount: Joi.number()
34
- .integer()
35
- .min(Joi.ref('seedValidators', { adjust: (v) => v.length }))
36
- .required(),
37
- maxSignerCount: Joi.number().integer().min(1).max(8).min(Joi.ref('minSignerCount')).required(),
38
-
39
- minBlockSize: Joi.number().integer().min(1).required(),
40
- maxBlockSize: Joi.number().integer().min(1).max(15).min(Joi.ref('minBlockSize')).required(),
41
-
42
- minBlockInterval: Joi.number()
43
- .integer()
44
- .min(1)
45
- .max(60 * 60)
46
- .required(), // in seconds
47
- minBlockConfirmation: Joi.number().integer().min(1).max(100).required(),
48
-
49
- minDepositAmount: Joi.BN().positive().less(Joi.ref('minStakeAmount')).required(),
50
- maxDepositAmount: Joi.BN().greater(Joi.ref('minDepositAmount')).less(Joi.ref('minStakeAmount')).required(),
51
- minWithdrawAmount: Joi.BN().positive().required(),
52
- maxWithdrawAmount: Joi.BN().greater(Joi.ref('minWithdrawAmount')).required(),
53
-
54
- depositFeeRate: Joi.number().integer().min(0).max(10000).required(),
55
- withdrawFeeRate: Joi.number().integer().min(0).max(10000).required(),
56
- proposerFeeShare: Joi.number().integer().min(1).max(10000).required(),
57
- publisherFeeShare: Joi.number().integer().min(1).max(10000).required(),
58
- minDepositFee: Joi.BN().positive().required(),
59
- maxDepositFee: Joi.BN().min(Joi.ref('minDepositFee')).required(),
60
- minWithdrawFee: Joi.BN().positive().required(),
61
- maxWithdrawFee: Joi.BN().min(Joi.ref('minWithdrawFee')).required(),
62
-
63
- blockHeight: Joi.number().integer().min(0).required(),
64
- blockHash: Joi.string().regex(patterns.txHash).optional().allow(null).allow(''),
65
- issuer: Joi.DID().prefix().optional().allow(null),
66
-
67
- leaveWaitingPeriod: Joi.number().integer().min(Joi.ref('minBlockInterval')).default(0),
68
- publishWaitingPeriod: Joi.number().integer().min(Joi.ref('minBlockInterval')).default(0),
69
- publishSlashRate: Joi.number().integer().min(1).max(10000).required(),
70
-
71
- context: schemas.context,
72
- data: Joi.any().optional().allow(null),
73
- }).options({ stripUnknown: true, noDefaults: false });
74
-
75
- const create = (attrs, context) => {
76
- const rollup = {
77
- context: createStateContext(context),
78
- paused: false,
79
- closed: false,
80
- migrateHistory: [],
81
- vaultHistory: [],
82
- blockHeight: 0,
83
- blockHash: '',
84
- ...pick(attrs, [
85
- 'address',
86
- 'tokenAddress',
87
- 'vaultAddress',
88
- 'contractAddress',
89
- 'seedValidators',
90
- 'validators',
91
- 'minStakeAmount',
92
- 'maxStakeAmount',
93
- 'minSignerCount',
94
- 'maxSignerCount',
95
- 'minBlockSize',
96
- 'maxBlockSize',
97
- 'minBlockInterval',
98
- 'minBlockConfirmation',
99
- 'minDepositAmount',
100
- 'maxDepositAmount',
101
- 'minWithdrawAmount',
102
- 'maxWithdrawAmount',
103
- 'depositFeeRate',
104
- 'withdrawFeeRate',
105
- 'proposerFeeShare',
106
- 'publisherFeeShare',
107
- 'minDepositFee',
108
- 'maxDepositFee',
109
- 'minWithdrawFee',
110
- 'maxWithdrawFee',
111
- 'leaveWaitingPeriod',
112
- 'publishWaitingPeriod',
113
- 'publishSlashRate',
114
- 'issuer',
115
- 'data',
116
- ]),
117
- };
118
-
119
- rollup.address = toAddress(rollup.address);
120
-
121
- return validate(rollup);
122
- };
123
-
124
- const update = (state, updates, context) => {
125
- // latest block height must be incremented on each update
126
- // latest block hash must be updated together with block height
127
- if (updates.blockHeight && !updates.blockHash) {
128
- throw new Error('INVALID_ROLLUP_UPDATE', 'blockHash must be updated together with blockHeight');
129
- }
130
- if (updates.blockHash && !updates.blockHeight) {
131
- throw new Error('INVALID_ROLLUP_UPDATE', 'blockHeight must be updated together with blockHash');
132
- }
133
- if (updates.blockHeight && updates.blockHash) {
134
- if (updates.blockHeight !== state.blockHeight + 1) {
135
- throw new Error('INVALID_ROLLUP_UPDATE', 'blockHeight must be incremented');
136
- }
137
- if (updates.blockHash === state.blockHash) {
138
- throw new Error('INVALID_ROLLUP_UPDATE', 'blockHash can not remain unchanged between blocks');
139
- }
140
- }
141
-
142
- if (typeof updates.blockHeight !== 'undefined' && !updates.blockHeight) {
143
- throw new Error('INVALID_ROLLUP_UPDATE', 'blockHeight can not be unset');
144
- }
145
- if (typeof updates.blockHash !== 'undefined' && !updates.blockHash) {
146
- throw new Error('INVALID_ROLLUP_UPDATE', 'blockHash can not be unset');
147
- }
148
-
149
- const rollup = {
150
- ...state,
151
- ...pick(updates, [
152
- 'validators',
153
- 'minStakeAmount',
154
- 'maxStakeAmount',
155
- 'minSignerCount',
156
- 'maxSignerCount',
157
- 'minBlockSize',
158
- 'maxBlockSize',
159
- 'minBlockInterval',
160
- 'minBlockConfirmation',
161
- 'minDepositAmount',
162
- 'maxDepositAmount',
163
- 'minWithdrawAmount',
164
- 'maxWithdrawAmount',
165
- 'depositFeeRate',
166
- 'withdrawFeeRate',
167
- 'publisherFeeShare',
168
- 'minDepositFee',
169
- 'maxDepositFee',
170
- 'minWithdrawFee',
171
- 'maxWithdrawFee',
172
- 'blockHeight',
173
- 'blockHash',
174
- 'leaveWaitingPeriod',
175
- 'publishWaitingPeriod',
176
- 'publishSlashRate',
177
- 'data',
178
- ]),
179
- context: updateStateContext(state.context, context),
180
- };
181
-
182
- return validate(rollup);
183
- };
184
-
185
- const pause = (state, context) => {
186
- if (state.closed) {
187
- throw new Error('INVALID_PAUSE_ATTEMPT', 'rollup already closed');
188
- }
189
- if (state.paused) {
190
- throw new Error('INVALID_PAUSE_ATTEMPT', 'rollup already paused');
191
- }
192
-
193
- const rollup = {
194
- ...state,
195
- paused: true,
196
- context: updateStateContext(state.context, context),
197
- };
198
-
199
- return validate(rollup);
200
- };
201
-
202
- const close = (state, context) => {
203
- if (state.closed) {
204
- throw new Error('INVALID_CLOSE_ATTEMPT', 'rollup already closed');
205
- }
206
- if (!state.paused) {
207
- throw new Error('INVALID_CLOSE_ATTEMPT', 'rollup must be paused');
208
- }
209
-
210
- const rollup = {
211
- ...state,
212
- closed: true,
213
- context: updateStateContext(state.context, context),
214
- };
215
-
216
- return validate(rollup);
217
- };
218
-
219
- const resume = (state, context) => {
220
- if (state.closed) {
221
- throw new Error('INVALID_RESUME_ATTEMPT', 'rollup is closed');
222
- }
223
- if (state.paused === false) {
224
- throw new Error('INVALID_RESUME_ATTEMPT', 'rollup not paused');
225
- }
226
-
227
- const rollup = {
228
- ...state,
229
- paused: false,
230
- context: updateStateContext(state.context, context),
231
- };
232
-
233
- return validate(rollup);
234
- };
235
-
236
- const migrateContract = (state, to, context) => {
237
- if (state.closed) {
238
- throw new Error('INVALID_MIGRATE_ATTEMPT', 'rollup is closed');
239
- }
240
- if (state.paused === false) {
241
- throw new Error('INVALID_MIGRATE_ATTEMPT', 'rollup not paused');
242
- }
243
- if (state.contractAddress === to) {
244
- throw new Error('INVALID_MIGRATE_ATTEMPT', 'can not migrate contract to self');
245
- }
246
- if (state.migrateHistory.includes(to)) {
247
- throw new Error('INVALID_MIGRATE_ATTEMPT', 'can not migrate contract to history contracts');
248
- }
249
-
250
- const rollup = {
251
- ...state,
252
- contractAddress: to,
253
- migrateHistory: [...state.migrateHistory, state.contractAddress],
254
- context: updateStateContext(state.context, context),
255
- };
256
-
257
- return validate(rollup);
258
- };
259
-
260
- const migrateVault = (state, to, context) => {
261
- if (state.closed) {
262
- throw new Error('INVALID_MIGRATE_ATTEMPT', 'rollup is closed');
263
- }
264
- if (state.paused === false) {
265
- throw new Error('INVALID_MIGRATE_ATTEMPT', 'rollup not paused');
266
- }
267
- if (state.vaultAddress === to) {
268
- throw new Error('INVALID_MIGRATE_ATTEMPT', 'can not migrate vault to self');
269
- }
270
- if (state.vaultHistory.includes(to)) {
271
- throw new Error('INVALID_MIGRATE_ATTEMPT', 'can not migrate vault to history vaults');
272
- }
273
-
274
- const rollup = {
275
- ...state,
276
- vaultAddress: to,
277
- vaultHistory: [...state.vaultHistory, state.vaultAddress],
278
- context: updateStateContext(state.context, context),
279
- };
280
-
281
- return validate(rollup);
282
- };
283
-
284
- const validate = (state) => {
285
- const { value, error } = schema.validate(state);
286
- if (error) {
287
- throw new Error('INVALID_ROLLUP_PROPS', error.details.map((x) => x.message).join(', '));
288
- }
289
-
290
- if (!value.data) {
291
- value.data = null;
292
- }
293
-
294
- return value;
295
- };
296
-
297
- module.exports = { create, update, pause, close, resume, migrateContract, migrateVault, validate, schema };