wowok 1.2.8 → 1.2.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.
- package/package.json +1 -1
- package/src/demand.ts +1 -1
- package/src/guard.ts +216 -143
- package/src/passport.ts +130 -43
- package/src/protocol.ts +40 -48
- package/src/utils.ts +23 -4
package/package.json
CHANGED
package/src/demand.ts
CHANGED
|
@@ -19,7 +19,7 @@ export class Demand {
|
|
|
19
19
|
let d = new Demand(protocol, bounty_type, permission)
|
|
20
20
|
d.object = Protocol.TXB_OBJECT(protocol.CurrentSession(), object)
|
|
21
21
|
return d
|
|
22
|
-
}
|
|
22
|
+
}
|
|
23
23
|
|
|
24
24
|
private constructor(protocol:Protocol, bounty_type:string, permission:PermissionObject) {
|
|
25
25
|
this.bounty_type = bounty_type;
|
package/src/guard.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
import { BCS } from '@mysten/bcs';
|
|
3
|
-
import { Protocol, GuardAddress, FnCallType, Data_Type, MODULES, ContextType, ValueType, OperatorType, ConstantType, SER_VALUE} from './protocol';
|
|
3
|
+
import { Protocol, LogicsInfo, GuardAddress, FnCallType, Data_Type, MODULES, ContextType, ValueType, OperatorType, ConstantType, SER_VALUE} from './protocol';
|
|
4
4
|
import { concatenate, array_equal } from './utils';
|
|
5
|
-
import { IsValidDesription, Bcs, IsValidInt, IsValidAddress } from './utils';
|
|
5
|
+
import { IsValidDesription, Bcs, IsValidInt, IsValidAddress, FirstLetterUppercase } from './utils';
|
|
6
6
|
import { ERROR, Errors } from './exception';
|
|
7
7
|
|
|
8
8
|
export type GuardConstant = Map<number, Guard_Vriable>;
|
|
@@ -13,6 +13,13 @@ export interface Guard_Vriable {
|
|
|
13
13
|
witness?: Uint8Array,
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export interface Guard_Options {
|
|
17
|
+
from: 'query' | 'type';
|
|
18
|
+
name: string;
|
|
19
|
+
value: number;
|
|
20
|
+
group?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
16
23
|
export class Guard {
|
|
17
24
|
static MAX_INPUT_LENGTH = 2048;
|
|
18
25
|
static launch(protocol:Protocol, description:string, maker:GuardMaker) : GuardAddress {
|
|
@@ -91,154 +98,218 @@ export class Guard {
|
|
|
91
98
|
|
|
92
99
|
static QUERIES:any[] = [
|
|
93
100
|
// module, 'name', 'id', [input], output
|
|
94
|
-
[MODULES.permission, '
|
|
95
|
-
[MODULES.permission, '
|
|
96
|
-
[MODULES.permission, '
|
|
97
|
-
[MODULES.permission, '
|
|
98
|
-
[MODULES.permission, '
|
|
99
|
-
[MODULES.permission, '
|
|
100
|
-
[MODULES.permission, '
|
|
101
|
-
[MODULES.permission, '
|
|
102
|
-
[MODULES.permission, '
|
|
101
|
+
[MODULES.permission, 'Builder', 1, [], ValueType.TYPE_ADDRESS],
|
|
102
|
+
[MODULES.permission, 'Has Admin', 2, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
103
|
+
[MODULES.permission, 'Has Rights', 3, [ValueType.TYPE_ADDRESS, ValueType.TYPE_U64], ValueType.TYPE_BOOL],
|
|
104
|
+
[MODULES.permission, 'Contains Address', 4, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
105
|
+
[MODULES.permission, 'Contains Index of Address', 5, [ValueType.TYPE_ADDRESS, ValueType.TYPE_U64], ValueType.TYPE_BOOL],
|
|
106
|
+
[MODULES.permission, 'Contains Guard of Address', 6, [ValueType.TYPE_ADDRESS, ValueType.TYPE_U64], ValueType.TYPE_BOOL],
|
|
107
|
+
[MODULES.permission, 'Guard of Address', 7, [ValueType.TYPE_ADDRESS, ValueType.TYPE_U64], ValueType.TYPE_ADDRESS],
|
|
108
|
+
[MODULES.permission, 'Entity Count', 8, [], ValueType.TYPE_U64],
|
|
109
|
+
[MODULES.permission, 'Admin Count', 9, [], ValueType.TYPE_U64],
|
|
103
110
|
|
|
104
|
-
[MODULES.repository, '
|
|
105
|
-
[MODULES.repository, '
|
|
106
|
-
[MODULES.repository, '
|
|
107
|
-
[MODULES.repository, '
|
|
108
|
-
[MODULES.repository, '
|
|
109
|
-
[MODULES.repository, '
|
|
110
|
-
[MODULES.repository, '
|
|
111
|
-
[MODULES.repository, '
|
|
112
|
-
[MODULES.repository, '
|
|
113
|
-
[MODULES.repository, '
|
|
114
|
-
[MODULES.repository, '
|
|
115
|
-
[MODULES.repository, '
|
|
116
|
-
[MODULES.repository, '
|
|
117
|
-
|
|
118
|
-
[MODULES.machine, '
|
|
119
|
-
[MODULES.machine, '
|
|
120
|
-
[MODULES.machine, '
|
|
121
|
-
[MODULES.machine, '
|
|
122
|
-
[MODULES.machine, '
|
|
123
|
-
[MODULES.machine, '
|
|
111
|
+
[MODULES.repository, 'Permission', 11, [], ValueType.TYPE_ADDRESS],
|
|
112
|
+
[MODULES.repository, 'Contains Policy', 12, [ValueType.TYPE_VEC_U8], ValueType.TYPE_BOOL],
|
|
113
|
+
[MODULES.repository, 'Has Permission of Policy', 13, [ValueType.TYPE_VEC_U8], ValueType.TYPE_BOOL],
|
|
114
|
+
[MODULES.repository, 'Permission of Policy', 14, [ValueType.TYPE_VEC_U8], ValueType.TYPE_U64],
|
|
115
|
+
[MODULES.repository, 'Value Type of Policy', 15, [ValueType.TYPE_VEC_U8], ValueType.TYPE_U8],
|
|
116
|
+
[MODULES.repository, 'Contains Id', 16, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
117
|
+
[MODULES.repository, 'Contains Value', 17, [ValueType.TYPE_ADDRESS, ValueType.TYPE_VEC_U8], ValueType.TYPE_BOOL],
|
|
118
|
+
[MODULES.repository, 'Value without Type', 18, [ValueType.TYPE_ADDRESS, ValueType.TYPE_VEC_U8], ValueType.TYPE_VEC_U8],
|
|
119
|
+
[MODULES.repository, 'Value', 19, [ValueType.TYPE_ADDRESS, ValueType.TYPE_VEC_U8], ValueType.TYPE_VEC_U8],
|
|
120
|
+
[MODULES.repository, 'Type', 20, [], ValueType.TYPE_U8],
|
|
121
|
+
[MODULES.repository, 'Policy Mode', 21, [], ValueType.TYPE_U8],
|
|
122
|
+
[MODULES.repository, 'Reference Count', 22, [], ValueType.TYPE_U64],
|
|
123
|
+
[MODULES.repository, 'Has Reference', 23, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
124
|
+
|
|
125
|
+
[MODULES.machine, 'Permission', 31, [], ValueType.TYPE_ADDRESS],
|
|
126
|
+
[MODULES.machine, 'Paused', 32, [], ValueType.TYPE_BOOL],
|
|
127
|
+
[MODULES.machine, 'Published', 33, [], ValueType.TYPE_BOOL],
|
|
128
|
+
[MODULES.machine, 'Is Consensus Repository', 34, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
129
|
+
[MODULES.machine, 'Has Endpoint', 35, [], ValueType.TYPE_BOOL],
|
|
130
|
+
[MODULES.machine, 'Endpoint', 36, [], ValueType.TYPE_VEC_U8],
|
|
124
131
|
|
|
125
|
-
[MODULES.progress, '
|
|
126
|
-
[MODULES.progress, '
|
|
127
|
-
[MODULES.progress, '
|
|
128
|
-
[MODULES.progress, '
|
|
129
|
-
[MODULES.progress, '
|
|
130
|
-
[MODULES.progress, '
|
|
131
|
-
[MODULES.progress, '
|
|
132
|
-
[MODULES.progress, '
|
|
133
|
-
[MODULES.progress, '
|
|
134
|
-
[MODULES.progress, '
|
|
132
|
+
[MODULES.progress, 'Machine', 51, [], ValueType.TYPE_ADDRESS],
|
|
133
|
+
[MODULES.progress, 'Current Node', 52, [], ValueType.TYPE_VEC_U8],
|
|
134
|
+
[MODULES.progress, 'Has Parent', 53, [], ValueType.TYPE_BOOL],
|
|
135
|
+
[MODULES.progress, 'Parent', 54, [], ValueType.TYPE_ADDRESS],
|
|
136
|
+
[MODULES.progress, 'Has Task', 55, [], ValueType.TYPE_BOOL],
|
|
137
|
+
[MODULES.progress, 'Task', 56, [], ValueType.TYPE_ADDRESS],
|
|
138
|
+
[MODULES.progress, 'Has Operator', 57, [ValueType.TYPE_VEC_U8], ValueType.TYPE_BOOL],
|
|
139
|
+
[MODULES.progress, 'Is Operator for Address', 58, [ValueType.TYPE_VEC_U8, ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
140
|
+
[MODULES.progress, 'Has Context Repository', 59, [], ValueType.TYPE_BOOL],
|
|
141
|
+
[MODULES.progress, 'Context Repository', 60, [], ValueType.TYPE_ADDRESS],
|
|
135
142
|
|
|
136
|
-
[MODULES.demand, '
|
|
137
|
-
[MODULES.demand, '
|
|
138
|
-
[MODULES.demand, '
|
|
139
|
-
[MODULES.demand, '
|
|
140
|
-
[MODULES.demand, '
|
|
141
|
-
[MODULES.demand, '
|
|
142
|
-
[MODULES.demand, '
|
|
143
|
-
[MODULES.demand, '
|
|
144
|
-
[MODULES.demand, '
|
|
145
|
-
[MODULES.demand, '
|
|
146
|
-
[MODULES.demand, '
|
|
143
|
+
[MODULES.demand, 'Permission', 71, [], ValueType.TYPE_ADDRESS],
|
|
144
|
+
[MODULES.demand, 'Has Deadline', 72, [], ValueType.TYPE_BOOL],
|
|
145
|
+
[MODULES.demand, 'Deadline', 73, [], ValueType.TYPE_U64],
|
|
146
|
+
[MODULES.demand, 'Bounty Count', 74, [], ValueType.TYPE_U64],
|
|
147
|
+
[MODULES.demand, 'Has Guard', 75, [], ValueType.TYPE_BOOL],
|
|
148
|
+
[MODULES.demand, 'Guard', 76, [], ValueType.TYPE_ADDRESS],
|
|
149
|
+
[MODULES.demand, 'Has Service Picked', 77, [], ValueType.TYPE_BOOL],
|
|
150
|
+
[MODULES.demand, 'Service Picked', 78, [], ValueType.TYPE_ADDRESS],
|
|
151
|
+
[MODULES.demand, 'Presenter Count', 79, [], ValueType.TYPE_U64],
|
|
152
|
+
[MODULES.demand, 'Is Presenter', 80, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
153
|
+
[MODULES.demand, 'Who Got Bounty', 81, [ValueType.TYPE_ADDRESS], ValueType.TYPE_ADDRESS],
|
|
147
154
|
|
|
148
|
-
[MODULES.order, '
|
|
149
|
-
[MODULES.order, '
|
|
150
|
-
[MODULES.order, '
|
|
151
|
-
[MODULES.order, '
|
|
152
|
-
[MODULES.order, '
|
|
153
|
-
[MODULES.order, '
|
|
154
|
-
[MODULES.order, '
|
|
155
|
-
[MODULES.order, '
|
|
156
|
-
[MODULES.order, '
|
|
157
|
-
[MODULES.order, '
|
|
158
|
-
[MODULES.order, '
|
|
159
|
-
[MODULES.order, '
|
|
160
|
-
[MODULES.order, '
|
|
161
|
-
[MODULES.order, '
|
|
155
|
+
[MODULES.order, 'Amount', 91, [], ValueType.TYPE_U64],
|
|
156
|
+
[MODULES.order, 'Payer', 92, [], ValueType.TYPE_ADDRESS],
|
|
157
|
+
[MODULES.order, 'Service', 93, [], ValueType.TYPE_ADDRESS],
|
|
158
|
+
[MODULES.order, 'Has Progress', 94, [], ValueType.TYPE_BOOL],
|
|
159
|
+
[MODULES.order, 'Progress', 95, [], ValueType.TYPE_ADDRESS],
|
|
160
|
+
[MODULES.order, 'Has Required Info', 96, [], ValueType.TYPE_BOOL],
|
|
161
|
+
[MODULES.order, 'Required Info of Service-Pubkey', 97, [], ValueType.TYPE_VEC_U8],
|
|
162
|
+
[MODULES.order, 'Required Info of Customer-Pubkey', 98, [], ValueType.TYPE_VEC_U8],
|
|
163
|
+
[MODULES.order, 'Required Info', 99, [], ValueType.TYPE_VEC_VEC_U8],
|
|
164
|
+
[MODULES.order, 'Discount Used', 100, [], ValueType.TYPE_BOOL],
|
|
165
|
+
[MODULES.order, 'Discount', 101, [], ValueType.TYPE_ADDRESS],
|
|
166
|
+
[MODULES.order, 'Balance', 102, [], ValueType.TYPE_U64],
|
|
167
|
+
[MODULES.order, 'Be Refunded', 103, [], ValueType.TYPE_BOOL],
|
|
168
|
+
[MODULES.order, 'Be Withdrawed', 104, [], ValueType.TYPE_BOOL],
|
|
162
169
|
|
|
163
|
-
[MODULES.service, '
|
|
164
|
-
[MODULES.service, '
|
|
165
|
-
[MODULES.service, '
|
|
166
|
-
[MODULES.service, '
|
|
167
|
-
[MODULES.service, '
|
|
168
|
-
[MODULES.service, '
|
|
169
|
-
[MODULES.service, '
|
|
170
|
-
[MODULES.service, '
|
|
171
|
-
[MODULES.service, '
|
|
172
|
-
[MODULES.service, '
|
|
173
|
-
[MODULES.service, '
|
|
174
|
-
[MODULES.service, '
|
|
175
|
-
[MODULES.service, '
|
|
176
|
-
[MODULES.service, '
|
|
177
|
-
[MODULES.service, '
|
|
178
|
-
[MODULES.service, '
|
|
179
|
-
[MODULES.service, '
|
|
180
|
-
[MODULES.service, '
|
|
181
|
-
[MODULES.service, '
|
|
170
|
+
[MODULES.service, 'Permission', 111, [], ValueType.TYPE_ADDRESS],
|
|
171
|
+
[MODULES.service, 'Payee', 112, [], ValueType.TYPE_ADDRESS],
|
|
172
|
+
[MODULES.service, 'Has Buy-Guard', 113, [], ValueType.TYPE_BOOL],
|
|
173
|
+
[MODULES.service, 'Buy-Guard', 114, [], ValueType.TYPE_ADDRESS],
|
|
174
|
+
[MODULES.service, 'Contains Repository', 115, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
175
|
+
[MODULES.service, 'Has Withdraw-Guard', 116, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
176
|
+
[MODULES.service, 'Withdraw-Guard Percent', 117, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
177
|
+
[MODULES.service, 'Has Refund-Guard', 118, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
178
|
+
[MODULES.service, 'Refund-Guard Percent', 119, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
179
|
+
[MODULES.service, 'Has Sale Item', 120, [ValueType.TYPE_VEC_U8], ValueType.TYPE_BOOL],
|
|
180
|
+
[MODULES.service, 'Sale Item Price', 121, [ValueType.TYPE_VEC_U8], ValueType.TYPE_U64],
|
|
181
|
+
[MODULES.service, 'Sale Item Inventory', 122, [ValueType.TYPE_VEC_U8], ValueType.TYPE_U64],
|
|
182
|
+
[MODULES.service, 'Has Machine', 123, [], ValueType.TYPE_BOOL],
|
|
183
|
+
[MODULES.service, 'Machine', 124, [], ValueType.TYPE_ADDRESS],
|
|
184
|
+
[MODULES.service, 'Paused', 125, [], ValueType.TYPE_BOOL],
|
|
185
|
+
[MODULES.service, 'Published', 126, [], ValueType.TYPE_BOOL],
|
|
186
|
+
[MODULES.service, 'Has Required Info', 127, [], ValueType.TYPE_BOOL],
|
|
187
|
+
[MODULES.service, 'Required Info of Service-Pubkey', 128, [], ValueType.TYPE_VEC_U8],
|
|
188
|
+
[MODULES.service, 'Required Info', 129, [], ValueType.TYPE_VEC_VEC_U8],
|
|
182
189
|
|
|
183
|
-
[MODULES.reward, '
|
|
184
|
-
[MODULES.reward, '
|
|
185
|
-
[MODULES.reward, '
|
|
186
|
-
[MODULES.reward, '
|
|
187
|
-
[MODULES.reward, '
|
|
188
|
-
[MODULES.reward, '
|
|
189
|
-
[MODULES.reward, '
|
|
190
|
-
[MODULES.reward, '
|
|
191
|
-
[MODULES.reward, '
|
|
192
|
-
[MODULES.reward, '
|
|
193
|
-
[MODULES.reward, '
|
|
194
|
-
[MODULES.reward, '
|
|
195
|
-
[MODULES.reward, '
|
|
196
|
-
[MODULES.reward, '
|
|
197
|
-
[MODULES.reward, '
|
|
190
|
+
[MODULES.reward, 'Permission', 151, [], ValueType.TYPE_ADDRESS],
|
|
191
|
+
[MODULES.reward, 'Reward Count Left', 152, [], ValueType.TYPE_U64],
|
|
192
|
+
[MODULES.reward, 'Reward Count Supplied', 153, [], ValueType.TYPE_U64],
|
|
193
|
+
[MODULES.reward, 'Guard Count', 154, [], ValueType.TYPE_U64],
|
|
194
|
+
[MODULES.reward, 'Has Guard', 155, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
195
|
+
[MODULES.reward, 'Guard Portion', 156, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
196
|
+
[MODULES.reward, 'Deadline', 157, [], ValueType.TYPE_U64],
|
|
197
|
+
[MODULES.reward, 'Has Claimed by Address', 158, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
198
|
+
[MODULES.reward, 'Claimed by Address', 159, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
199
|
+
[MODULES.reward, 'Address Count Claimed', 160, [], ValueType.TYPE_U64],
|
|
200
|
+
[MODULES.reward, 'Is Sponsor', 161, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
201
|
+
[MODULES.reward, 'Portion by Sponsor', 162, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
202
|
+
[MODULES.reward, 'Sponsor Count', 163, [], ValueType.TYPE_U64],
|
|
203
|
+
[MODULES.reward, 'Allow Repeat Claim', 164, [], ValueType.TYPE_BOOL],
|
|
204
|
+
[MODULES.reward, 'Claimed Portion by Address', 165, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
198
205
|
|
|
199
|
-
[MODULES.vote, '
|
|
200
|
-
[MODULES.vote, '
|
|
201
|
-
[MODULES.vote, '
|
|
202
|
-
[MODULES.vote, '
|
|
203
|
-
[MODULES.vote, '
|
|
204
|
-
[MODULES.vote, '
|
|
205
|
-
[MODULES.vote, '
|
|
206
|
-
[MODULES.vote, '
|
|
207
|
-
[MODULES.vote, '
|
|
208
|
-
[MODULES.vote, '
|
|
209
|
-
[MODULES.vote, '
|
|
210
|
-
[MODULES.vote, '
|
|
211
|
-
[MODULES.vote, '
|
|
212
|
-
[MODULES.vote, '
|
|
213
|
-
[MODULES.vote, '
|
|
214
|
-
[MODULES.vote, '
|
|
215
|
-
[MODULES.vote, '
|
|
216
|
-
[MODULES.vote, '
|
|
217
|
-
[MODULES.vote, '
|
|
218
|
-
[MODULES.vote, '
|
|
219
|
-
[MODULES.vote, '
|
|
220
|
-
[MODULES.vote, '
|
|
221
|
-
|
|
222
|
-
[MODULES.wowok, '
|
|
223
|
-
[MODULES.wowok, '
|
|
224
|
-
[MODULES.wowok, '
|
|
225
|
-
[MODULES.wowok, '
|
|
226
|
-
[MODULES.wowok, '
|
|
227
|
-
[MODULES.wowok, '
|
|
228
|
-
[MODULES.wowok, '
|
|
229
|
-
[MODULES.wowok, '
|
|
230
|
-
[MODULES.wowok, '
|
|
231
|
-
|
|
232
|
-
[MODULES.entity, '
|
|
233
|
-
[MODULES.entity, '
|
|
234
|
-
[MODULES.entity, '
|
|
235
|
-
[MODULES.entity, '
|
|
206
|
+
[MODULES.vote, 'Permission', 171, [], ValueType.TYPE_ADDRESS],
|
|
207
|
+
[MODULES.vote, 'Options Locked', 172, [], ValueType.TYPE_BOOL],
|
|
208
|
+
[MODULES.vote, 'Deadline Locked', 173, [], ValueType.TYPE_BOOL],
|
|
209
|
+
[MODULES.vote, 'Vote-Guard Locked', 174, [], ValueType.TYPE_BOOL],
|
|
210
|
+
[MODULES.vote, 'Max Choice Count', 175, [], ValueType.TYPE_U8],
|
|
211
|
+
[MODULES.vote, 'Deadline', 176, [], ValueType.TYPE_U64],
|
|
212
|
+
[MODULES.vote, 'Has Reference', 177, [], ValueType.TYPE_BOOL],
|
|
213
|
+
[MODULES.vote, 'Reference', 178, [], ValueType.TYPE_ADDRESS],
|
|
214
|
+
[MODULES.vote, 'Has Vote-Guard', 179, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
215
|
+
[MODULES.vote, 'Vote-Guard', 180, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
216
|
+
[MODULES.vote, 'Has Voted by Address', 181, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
217
|
+
[MODULES.vote, 'Voted Weight by Address', 182, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
218
|
+
[MODULES.vote, 'Has Option', 183, [ValueType.TYPE_VEC_U8], ValueType.TYPE_BOOL],
|
|
219
|
+
[MODULES.vote, 'Has Object of Option', 184, [ValueType.TYPE_VEC_U8], ValueType.TYPE_BOOL],
|
|
220
|
+
[MODULES.vote, 'Option Object', 185, [ValueType.TYPE_VEC_U8], ValueType.TYPE_ADDRESS],
|
|
221
|
+
[MODULES.vote, 'Option Count', 186, [ValueType.TYPE_VEC_U8], ValueType.TYPE_U64],
|
|
222
|
+
[MODULES.vote, 'Option Votes', 187, [ValueType.TYPE_VEC_U8], ValueType.TYPE_U64],
|
|
223
|
+
[MODULES.vote, 'Address Count Voted', 188, [], ValueType.TYPE_U64],
|
|
224
|
+
[MODULES.vote, 'Top1 Option by Addresses', 189, [], ValueType.TYPE_VEC_U8],
|
|
225
|
+
[MODULES.vote, 'Top1 Count by Addresses', 190, [], ValueType.TYPE_U64],
|
|
226
|
+
[MODULES.vote, 'Top1 Option by Votes', 191, [], ValueType.TYPE_VEC_U8],
|
|
227
|
+
[MODULES.vote, 'Top1 Count by Votes', 192, [], ValueType.TYPE_U64],
|
|
228
|
+
|
|
229
|
+
[MODULES.wowok, 'Builder', 210, [], ValueType.TYPE_ADDRESS],
|
|
230
|
+
[MODULES.wowok, 'Everyone-Guard', 211, [], ValueType.TYPE_ADDRESS],
|
|
231
|
+
[MODULES.wowok, 'Object of Entities', 212, [], ValueType.TYPE_ADDRESS],
|
|
232
|
+
[MODULES.wowok, 'Grantor Count', 213, [], ValueType.TYPE_U64],
|
|
233
|
+
[MODULES.wowok, 'Has Grantor', 214, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
234
|
+
[MODULES.wowok, 'Grantor Name', 215, [ValueType.TYPE_ADDRESS], ValueType.TYPE_VEC_U8],
|
|
235
|
+
[MODULES.wowok, 'Grantor Registration Time', 216, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
236
|
+
[MODULES.wowok, 'Grantor Expired Time', 217, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
237
|
+
[MODULES.wowok, 'Grantee Object for Grantor', 218, [ValueType.TYPE_ADDRESS], ValueType.TYPE_ADDRESS],
|
|
238
|
+
|
|
239
|
+
[MODULES.entity, 'Has Entity', 230, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
240
|
+
[MODULES.entity, 'Likes', 231, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
241
|
+
[MODULES.entity, 'Dislikes', 232, [ValueType.TYPE_ADDRESS], ValueType.TYPE_U64],
|
|
242
|
+
[MODULES.entity, 'Entity Info', 233, [ValueType.TYPE_ADDRESS], ValueType.TYPE_VEC_U8],
|
|
243
|
+
[MODULES.entity, 'Has Resource by Entity', 234, [ValueType.TYPE_ADDRESS], ValueType.TYPE_BOOL],
|
|
244
|
+
[MODULES.entity, 'Entity Resource', 235, [ValueType.TYPE_ADDRESS], ValueType.TYPE_ADDRESS],
|
|
236
245
|
];
|
|
237
|
-
|
|
246
|
+
|
|
247
|
+
static BoolCmd = Guard.QUERIES.filter(q => q[4] === ValueType.TYPE_BOOL);
|
|
238
248
|
static IsBoolCmd = (cmd:number) : boolean => { return Guard.BoolCmd.includes((q:any) => {return q[2] == cmd}) }
|
|
239
|
-
|
|
249
|
+
|
|
250
|
+
static CmdFilter = (retType:ValueType) => { return Guard.QUERIES.filter((q)=> q[4] === retType)}
|
|
251
|
+
static GetCmd = (cmd:number | undefined) : any => {
|
|
240
252
|
return Guard.QUERIES.find((q:any) => {return q[2] == cmd}) ;
|
|
241
253
|
}
|
|
254
|
+
static GetCmdOption = (cmd:number) : Guard_Options | undefined => {
|
|
255
|
+
const r = Guard.GetCmd(cmd);
|
|
256
|
+
if (!r) return r;
|
|
257
|
+
return {from:'query', name:r[1], value:r[2], group:FirstLetterUppercase(r[0])}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
static GetInputParams = (cmd:number) : ValueType[] => {
|
|
261
|
+
const r = Guard.GetCmd(cmd);
|
|
262
|
+
if (!r) return [];
|
|
263
|
+
return (r as any[])[3];
|
|
264
|
+
}
|
|
265
|
+
static GetModuleName = (cmd:number) : string => {
|
|
266
|
+
let r = Guard.GetCmd(cmd);
|
|
267
|
+
if (!r) return '';
|
|
268
|
+
return FirstLetterUppercase(r[0])
|
|
269
|
+
}
|
|
270
|
+
static NumberOptions = () : Guard_Options[] => {
|
|
271
|
+
const r: Guard_Options[] = [...Guard.CmdFilter(ValueType.TYPE_U8), ...Guard.CmdFilter(ValueType.TYPE_U64),
|
|
272
|
+
...Guard.CmdFilter(ValueType.TYPE_U128), ...Guard.CmdFilter(ValueType.TYPE_U256)].map((v)=> { return {from:'query', name:v[1], value:v[2], group:FirstLetterUppercase(v[0])}});
|
|
273
|
+
r.push({from:'type', name:'Txn Time', value:ContextType.TYPE_CLOCK, group:'Txn Functions'});
|
|
274
|
+
return r;
|
|
275
|
+
}
|
|
276
|
+
static CommonOptions = (retType:ValueType) : Guard_Options[] => {
|
|
277
|
+
return Guard.CmdFilter(retType).map((v)=> {return {from:'query', name:v[1], value:v[2], group:FirstLetterUppercase(v[0])}});
|
|
278
|
+
}
|
|
279
|
+
static AllOptions = () : Guard_Options[] => {
|
|
280
|
+
return Guard.QUERIES.map((v)=>{return {from:'query', name:v[1], value:v[2], group:FirstLetterUppercase(v[0])}});
|
|
281
|
+
}
|
|
282
|
+
static StringOptions = () : Guard_Options[] => {
|
|
283
|
+
return [...Guard.CmdFilter(ValueType.TYPE_VEC_U8), ...Guard.CmdFilter(ValueType.TYPE_STRING)].map((v) => {
|
|
284
|
+
return {from:'query', name:v[1], value:v[2], group:FirstLetterUppercase(v[0])};
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
static BoolOptions = () : Guard_Options[] => {
|
|
288
|
+
const n1:Guard_Options[] = Guard.BoolCmd.map((v)=> { return {from:'query', name:v[1], value:v[2], group:FirstLetterUppercase(v[0])}});
|
|
289
|
+
const n2:Guard_Options[] = LogicsInfo.map((v) => { return {from:'type', name:v[1] as string, value:v[0] as number, group:'Compare or Logic'}});
|
|
290
|
+
return [...n1, ...n2]
|
|
291
|
+
}
|
|
292
|
+
static AddressOptions = () : Guard_Options[] => {
|
|
293
|
+
const n1:Guard_Options[] = Guard.QUERIES.filter(q => q[4] === ValueType.TYPE_ADDRESS).map((v)=> { return {from:'query', name:v[1], value:v[2], group:FirstLetterUppercase(v[0])}});
|
|
294
|
+
n1.push({from:'type', name:'Txn Signer', value:ContextType.TYPE_SIGNER, group:'Txn Functions'});
|
|
295
|
+
return [...n1]
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
static Options = (ret_type: ValueType | 'number' | 'any') : Guard_Options[] => {
|
|
299
|
+
if (ret_type === 'number') {
|
|
300
|
+
return Guard.NumberOptions();
|
|
301
|
+
} else if (ret_type === 'any') {
|
|
302
|
+
return Guard.AllOptions();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
switch(ret_type as number) {
|
|
306
|
+
case ValueType.TYPE_BOOL:
|
|
307
|
+
return Guard.BoolOptions();
|
|
308
|
+
case ValueType.TYPE_STRING:
|
|
309
|
+
return Guard.StringOptions();
|
|
310
|
+
}
|
|
311
|
+
return Guard.CommonOptions(ret_type);
|
|
312
|
+
}
|
|
242
313
|
}
|
|
243
314
|
|
|
244
315
|
export class GuardConstantHelper {
|
|
@@ -302,7 +373,7 @@ export class GuardConstantHelper {
|
|
|
302
373
|
case ValueType.TYPE_VEC_U256:
|
|
303
374
|
let ser = SER_VALUE.find(s=>s.type==type);
|
|
304
375
|
if (!ser) ERROR(Errors.Fail, 'add_constant: invalid type');
|
|
305
|
-
bNeedSerialize ? constants.set(identifier, {type:type, value:Bcs.getInstance().ser(ser!.type, value)}) :
|
|
376
|
+
bNeedSerialize ? constants.set(identifier, {type:type, value:Bcs.getInstance().ser(ser!.type as number, value)}) :
|
|
306
377
|
constants.set(identifier, {type:type, value:value})
|
|
307
378
|
return
|
|
308
379
|
case ValueType.TYPE_VEC_U8:
|
|
@@ -348,7 +419,7 @@ export class GuardMaker {
|
|
|
348
419
|
this.data.push(Bcs.getInstance().ser(ValueType.TYPE_U8, type));
|
|
349
420
|
let ser = SER_VALUE.find(s=>s.type==type);
|
|
350
421
|
if (!ser) ERROR(Errors.Fail, 'serValueParam: invalid type');
|
|
351
|
-
this.data.push(Bcs.getInstance().ser(ser!.type, param));
|
|
422
|
+
this.data.push(Bcs.getInstance().ser(ser!.type as number, param));
|
|
352
423
|
this.type_validator.push(type);
|
|
353
424
|
}
|
|
354
425
|
|
|
@@ -414,7 +485,7 @@ export class GuardMaker {
|
|
|
414
485
|
this.data.push(Bcs.getInstance().ser(ValueType.TYPE_U8, param));
|
|
415
486
|
break;
|
|
416
487
|
default:
|
|
417
|
-
ERROR(Errors.InvalidParam, 'add_param type');
|
|
488
|
+
ERROR(Errors.InvalidParam, 'add_param type' + type);
|
|
418
489
|
};
|
|
419
490
|
return this;
|
|
420
491
|
}
|
|
@@ -497,8 +568,10 @@ export class GuardMaker {
|
|
|
497
568
|
if (this.type_validator[this.type_validator.length -1] != ValueType.TYPE_BOOL) { ERROR(Errors.Fail, 'type_validator check') }
|
|
498
569
|
if (this.type_validator[this.type_validator.length -2] != ValueType.TYPE_BOOL) { ERROR(Errors.Fail, 'type_validator check') }
|
|
499
570
|
break;
|
|
571
|
+
case OperatorType.TYPE_LOGIC_ALWAYS_TRUE:
|
|
572
|
+
break;
|
|
500
573
|
default:
|
|
501
|
-
ERROR(Errors.InvalidParam, 'type')
|
|
574
|
+
ERROR(Errors.InvalidParam, 'add_logic type invalid' + type)
|
|
502
575
|
}
|
|
503
576
|
this.data.push(Bcs.getInstance().ser(ValueType.TYPE_U8, type)); // TYPE
|
|
504
577
|
this.type_validator.splice(this.type_validator.length - splice_len); // delete type stack
|
package/src/passport.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type TransactionObjectInput, Inputs } from '@mysten/sui.js/transactions';
|
|
1
|
+
import { type TransactionObjectInput, Inputs, TransactionObjectArgument} from '@mysten/sui.js/transactions';
|
|
2
|
+
import { SuiObjectResponse } from '@mysten/sui.js/client';
|
|
2
3
|
import { FnCallType, GuardObject, Protocol, ContextType, OperatorType, Data_Type,
|
|
3
4
|
ValueType, SER_VALUE, IsValidOperatorType } from './protocol';
|
|
4
5
|
import { parse_object_type, array_unique, Bcs, ulebDecode, IsValidAddress, IsValidArray, OPTION_NONE, readOption, readOptionString } from './utils';
|
|
@@ -8,7 +9,7 @@ import { Guard } from './guard';
|
|
|
8
9
|
|
|
9
10
|
export type Guard_Query_Object = {
|
|
10
11
|
target: FnCallType, // object fnCall
|
|
11
|
-
object: TransactionObjectInput, // object
|
|
12
|
+
object: TransactionObjectInput | string, // object
|
|
12
13
|
types: string[], // object type
|
|
13
14
|
id: string, // object id
|
|
14
15
|
}
|
|
@@ -19,48 +20,53 @@ export interface QueryInfo {
|
|
|
19
20
|
type: number;
|
|
20
21
|
value_or_witness: string;
|
|
21
22
|
future?: string;
|
|
23
|
+
cmd?: number;
|
|
22
24
|
}
|
|
23
25
|
interface GuardInfo {
|
|
24
|
-
id: string;
|
|
26
|
+
id: string; // guard id
|
|
27
|
+
object: TransactionObjectInput;
|
|
25
28
|
query_list: (string | QueryInfo)[]; // object or witness object query
|
|
26
29
|
constant: QueryInfo[]; // witness in constant & ValueType.TYPE_ADDRESS(for Query)
|
|
27
30
|
input_witness: QueryInfo[]; // witness in input
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
export interface DeGuardConstant {
|
|
31
|
-
type: number;
|
|
32
|
-
value: any;
|
|
33
|
-
identifier?: number;
|
|
34
|
+
type: number; //
|
|
35
|
+
value: any; //
|
|
36
|
+
identifier?: number; // ID
|
|
34
37
|
}
|
|
35
38
|
export interface DeGuardData {
|
|
36
|
-
type: number;
|
|
37
|
-
value?: any;
|
|
38
|
-
identifier?: number;
|
|
39
|
-
cmd?: number;
|
|
39
|
+
type: number; //
|
|
40
|
+
value?: any; //
|
|
41
|
+
identifier?: number; // ID
|
|
42
|
+
cmd?: number; //
|
|
40
43
|
child: DeGuardData[];
|
|
41
44
|
ret_type?: number;
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
export interface
|
|
47
|
+
export interface FutureFill {
|
|
45
48
|
guard: string;
|
|
46
49
|
index: number;
|
|
47
|
-
|
|
50
|
+
witness: string;
|
|
51
|
+
future?: string;
|
|
52
|
+
cmd?: number;
|
|
53
|
+
type?: string;
|
|
48
54
|
}
|
|
49
55
|
export interface PassportQuery {
|
|
50
|
-
guard:
|
|
56
|
+
guard: (string | TransactionObjectInput)[];
|
|
51
57
|
query: Guard_Query_Object[];
|
|
52
58
|
witness: Guard_Query_Object[];
|
|
53
59
|
}
|
|
54
60
|
export class GuardParser {
|
|
55
61
|
protected guard_list: GuardInfo[] = [];
|
|
56
62
|
protected protocol: Protocol;
|
|
57
|
-
protected guards:
|
|
63
|
+
protected guards: string[];
|
|
58
64
|
private index:number = 0;
|
|
59
65
|
private get_index() { return this.index++ }
|
|
60
66
|
|
|
61
67
|
private constructor(protocol: Protocol, guards: string[]) {
|
|
62
68
|
this.protocol = protocol ;
|
|
63
|
-
this.guards = guards
|
|
69
|
+
this.guards = guards;
|
|
64
70
|
}
|
|
65
71
|
guardlist = () => { return this.guard_list }
|
|
66
72
|
|
|
@@ -94,7 +100,7 @@ export class GuardParser {
|
|
|
94
100
|
case ValueType.TYPE_VEC_U256:
|
|
95
101
|
let de = SER_VALUE.find(s=>s.type==v.type);
|
|
96
102
|
if (!de) ERROR(Errors.Fail, 'GuardObject de error')
|
|
97
|
-
value = Bcs.getInstance().de(de!.type, Uint8Array.from(v.value));
|
|
103
|
+
value = Bcs.getInstance().de(de!.type as number, Uint8Array.from(v.value));
|
|
98
104
|
break;
|
|
99
105
|
|
|
100
106
|
default:
|
|
@@ -283,6 +289,7 @@ export class GuardParser {
|
|
|
283
289
|
switch (current.type) {
|
|
284
290
|
case OperatorType.TYPE_LOGIC_ALWAYS_TRUE:
|
|
285
291
|
current.ret_type = ValueType.TYPE_BOOL;
|
|
292
|
+
stack.push(current);
|
|
286
293
|
return;
|
|
287
294
|
case OperatorType.TYPE_LOGIC_NOT:
|
|
288
295
|
current.ret_type = ValueType.TYPE_BOOL;
|
|
@@ -416,7 +423,7 @@ export class GuardParser {
|
|
|
416
423
|
ERROR(Errors.Fail, 'OperateParamCount: type invalid ' + current.type);
|
|
417
424
|
}
|
|
418
425
|
|
|
419
|
-
|
|
426
|
+
/*
|
|
420
427
|
static CreateAsync = async (protocol: Protocol, guards: string[]) => {
|
|
421
428
|
if (!IsValidArray(guards, IsValidAddress)) {
|
|
422
429
|
ERROR(Errors.IsValidArray, 'guards');
|
|
@@ -426,6 +433,7 @@ export class GuardParser {
|
|
|
426
433
|
const me = new GuardParser(protocol, guards);
|
|
427
434
|
|
|
428
435
|
let res = await protocol.Query_Raw(guard_list);
|
|
436
|
+
console.log(res)
|
|
429
437
|
res.forEach((r) => {
|
|
430
438
|
let c = r.data?.content as any;
|
|
431
439
|
if (!c) return;
|
|
@@ -442,11 +450,70 @@ export class GuardParser {
|
|
|
442
450
|
})
|
|
443
451
|
return me
|
|
444
452
|
}
|
|
453
|
+
*/
|
|
454
|
+
private static Parse_Guard_Helper(guards: string[], res:SuiObjectResponse[]) {
|
|
455
|
+
const protocol = Protocol.Instance();
|
|
456
|
+
const me = new GuardParser(protocol, guards);
|
|
457
|
+
res.forEach((r) => {
|
|
458
|
+
let c = r.data?.content as any;
|
|
459
|
+
if (!c) return;
|
|
460
|
+
|
|
461
|
+
let index = protocol.WOWOK_OBJECTS_TYPE().findIndex(v => {return v.includes('guard::Guard') && v == c.type});
|
|
462
|
+
if (index == -1) return;
|
|
463
|
+
|
|
464
|
+
let info:GuardInfo = {id: c.fields.id.id, query_list:[], constant:[], input_witness:[], object:Inputs.ObjectRef(
|
|
465
|
+
{objectId:c.fields.id.id, digest:r.data?.digest??'', version:r.data?.version ?? ''}
|
|
466
|
+
)};
|
|
467
|
+
me.parse_constant(info, c.fields.constants); // MUST first
|
|
468
|
+
if (c.fields.input.type === (protocol.Package() + '::bcs::BCS')) {
|
|
469
|
+
me.parse_bcs(info, Uint8Array.from(c.fields.input.fields.bytes)); // second
|
|
470
|
+
}
|
|
471
|
+
me.guard_list.push(info);
|
|
472
|
+
})
|
|
473
|
+
return me
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
static Create = async (guards: string[], onGuardInfo?:(parser:GuardParser|undefined)=>void) => {
|
|
477
|
+
if (!IsValidArray(guards, IsValidAddress)) {
|
|
478
|
+
if (onGuardInfo) onGuardInfo(undefined);
|
|
479
|
+
return undefined;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
let guard_list = array_unique(guards);
|
|
483
|
+
const protocol = Protocol.Instance();
|
|
484
|
+
|
|
485
|
+
if (onGuardInfo) {
|
|
486
|
+
protocol.Query_Raw(guard_list)
|
|
487
|
+
.then((res) => { onGuardInfo(GuardParser.Parse_Guard_Helper(guards, res)); })
|
|
488
|
+
.catch((e) => { onGuardInfo(undefined); })
|
|
489
|
+
} else {
|
|
490
|
+
const res = await protocol.Query_Raw(guard_list);
|
|
491
|
+
return GuardParser.Parse_Guard_Helper(guards, res);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
future_fills = () : FutureFill[] => {
|
|
496
|
+
const ret : FutureFill[] = [];
|
|
497
|
+
this.guard_list.forEach((g) => {
|
|
498
|
+
g.query_list.forEach((v) => {
|
|
499
|
+
if (typeof(v) !== 'string') {
|
|
500
|
+
ret.push({guard:g.id, index:v.index, witness:v.value_or_witness, cmd:v.cmd});
|
|
501
|
+
}
|
|
502
|
+
})
|
|
503
|
+
// cmd already in query_list, so filter it out.
|
|
504
|
+
g.constant.filter((v)=>v.type === ContextType.TYPE_WITNESS_ID && v.cmd === undefined).forEach((v) => {
|
|
505
|
+
ret.push({guard:g.id, index:v.index, witness:v.value_or_witness});
|
|
506
|
+
})
|
|
507
|
+
g.input_witness.forEach((v) => {
|
|
508
|
+
ret.push({guard:g.id, index:v.index, witness:v.value_or_witness});
|
|
509
|
+
})
|
|
510
|
+
}); return ret;
|
|
511
|
+
}
|
|
445
512
|
|
|
446
513
|
parse_constant = (info:GuardInfo, constants:any) => {
|
|
447
514
|
constants.forEach((v:any) => {
|
|
448
515
|
if (v.type == (this.protocol.Package() + '::guard::Constant')) {
|
|
449
|
-
// ValueType.TYPE_ADDRESS: Query_Cmd maybe used the address, so save it for
|
|
516
|
+
// ValueType.TYPE_ADDRESS: Query_Cmd maybe used the address, so save it for querying
|
|
450
517
|
if (v.fields.type == ContextType.TYPE_WITNESS_ID || v.fields.type == ValueType.TYPE_ADDRESS) {
|
|
451
518
|
info.constant.push({identifier:v.fields.identifier, index:this.get_index(), type:v.fields.type,
|
|
452
519
|
value_or_witness:'0x' + Bcs.getInstance().de(ValueType.TYPE_ADDRESS, Uint8Array.from(v.fields.value))});
|
|
@@ -507,14 +574,14 @@ export class GuardParser {
|
|
|
507
574
|
let type = arr.splice(0, 1);
|
|
508
575
|
if (type[0] == ValueType.TYPE_ADDRESS || type[0] == ContextType.TYPE_WITNESS_ID) {
|
|
509
576
|
let addr = '0x' + Bcs.getInstance().de(ValueType.TYPE_ADDRESS, Uint8Array.from(arr)).toString();
|
|
510
|
-
arr.splice(0, 33); // address + cmd
|
|
577
|
+
const offset = arr.splice(0, 33); // address + cmd
|
|
511
578
|
if (type[0] == ValueType.TYPE_ADDRESS) {
|
|
512
579
|
info.query_list.push(addr);
|
|
513
580
|
} else if (type[0] == ContextType.TYPE_WITNESS_ID){
|
|
514
|
-
info.query_list.push({index:this.get_index(), type:type[0], value_or_witness:addr});
|
|
581
|
+
info.query_list.push({index:this.get_index(), type:type[0], value_or_witness:addr, cmd:offset[offset.length-1]});
|
|
515
582
|
}
|
|
516
583
|
} else if (type[0] == ContextType.TYPE_CONSTANT) {
|
|
517
|
-
|
|
584
|
+
const identifer = arr.splice(0, 2); // key + cmd
|
|
518
585
|
let constant = info.constant.find((v) =>
|
|
519
586
|
(v.identifier == identifer[0]) &&
|
|
520
587
|
((v.type == ValueType.TYPE_ADDRESS) || (v.type == ContextType.TYPE_WITNESS_ID)));
|
|
@@ -522,7 +589,11 @@ export class GuardParser {
|
|
|
522
589
|
if (constant?.type == ValueType.TYPE_ADDRESS) {
|
|
523
590
|
info.query_list.push(constant.value_or_witness);
|
|
524
591
|
} else if (constant?.type == ContextType.TYPE_WITNESS_ID) {
|
|
525
|
-
|
|
592
|
+
const index = this.get_index();
|
|
593
|
+
info.query_list.push({identifier:identifer[0], type:constant.type, value_or_witness:constant.value_or_witness,
|
|
594
|
+
index:index, cmd:identifer[identifer.length-1]}); // query witness in constant
|
|
595
|
+
constant.cmd = identifer[identifer.length-1]; // mark this is a cmd in querylist(avoid multi input future by singer)
|
|
596
|
+
constant.index = index;
|
|
526
597
|
}
|
|
527
598
|
} else {
|
|
528
599
|
ERROR(Errors.Fail, 'constant type invalid');
|
|
@@ -535,7 +606,7 @@ export class GuardParser {
|
|
|
535
606
|
}
|
|
536
607
|
}
|
|
537
608
|
|
|
538
|
-
private get_object(guardid:string, info:QueryInfo, fill?:
|
|
609
|
+
private get_object(guardid:string, info:QueryInfo, fill?:FutureFill[]) : string {
|
|
539
610
|
let r = fill?.find(i => guardid == i.guard && i.index == info.index);
|
|
540
611
|
if (!r || !r.future) {
|
|
541
612
|
if (!info.future) {
|
|
@@ -547,12 +618,14 @@ export class GuardParser {
|
|
|
547
618
|
return info.future!
|
|
548
619
|
}
|
|
549
620
|
|
|
550
|
-
done = async (fill?:
|
|
621
|
+
done = async (fill?:FutureFill[], onPassportQueryReady?:(passport:PassportQuery | undefined)=>void) : Promise<PassportQuery | undefined>=> {
|
|
551
622
|
let objects: string[] = [];
|
|
552
623
|
this.guard_list.forEach((g) => {
|
|
553
|
-
|
|
624
|
+
// futures in constant table (all witness)
|
|
625
|
+
g.constant.filter(v => v.type == ContextType.TYPE_WITNESS_ID /*&& v.cmd === undefined*/).forEach((q) => {
|
|
554
626
|
objects.push(this.get_object(g.id, q, fill));
|
|
555
627
|
})
|
|
628
|
+
// objects to query
|
|
556
629
|
let list = g.query_list.map((q) => {
|
|
557
630
|
if (typeof(q) === "string") {
|
|
558
631
|
objects.push(q)
|
|
@@ -563,40 +636,56 @@ export class GuardParser {
|
|
|
563
636
|
return r
|
|
564
637
|
}
|
|
565
638
|
})
|
|
566
|
-
g.query_list = list;
|
|
639
|
+
g.query_list = list; // all to string to query
|
|
567
640
|
g.input_witness.forEach((q) => {
|
|
568
641
|
objects.push(this.get_object(g.id, q, fill));
|
|
569
642
|
})
|
|
570
643
|
})
|
|
571
644
|
|
|
572
|
-
|
|
573
|
-
|
|
645
|
+
if (onPassportQueryReady) {
|
|
646
|
+
this.protocol.Query_Raw(array_unique(objects), {showType:true}).then((res) => {
|
|
647
|
+
onPassportQueryReady(this.done_helper(res));
|
|
648
|
+
}).catch(e => {
|
|
649
|
+
console.log(e);
|
|
650
|
+
onPassportQueryReady(undefined);
|
|
651
|
+
})
|
|
652
|
+
return undefined;
|
|
653
|
+
} else {
|
|
654
|
+
const res = await this.protocol.Query_Raw(array_unique(objects), {showType:true});
|
|
655
|
+
return this.done_helper(res);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
private done_helper(res:SuiObjectResponse[]) {
|
|
574
660
|
let query: Guard_Query_Object[] = [];
|
|
575
661
|
let witness: Guard_Query_Object[] = [];
|
|
662
|
+
let guards: TransactionObjectInput[] = [];
|
|
576
663
|
this.guard_list.forEach(g => {
|
|
577
|
-
g.query_list.forEach(q => {
|
|
664
|
+
g.query_list.forEach(q => { // query list
|
|
578
665
|
let r = res.find(r => r.data?.objectId == q as string);
|
|
579
666
|
if (!r) { ERROR(Errors.Fail, 'query object not match')}
|
|
580
|
-
let object = this.object_query(r!.data);
|
|
667
|
+
let object = this.object_query(r!.data); // build passport query objects
|
|
581
668
|
if (!object) { ERROR(Errors.Fail, 'query object fail')}
|
|
582
669
|
query.push(object!);
|
|
583
670
|
})
|
|
584
|
-
res.forEach(q => {
|
|
585
|
-
let r1 = g.constant.find(v => v.future
|
|
586
|
-
let r2 = g.input_witness.find(v => v.future
|
|
671
|
+
res.forEach(q => { // witness(address & query) list
|
|
672
|
+
let r1 = g.constant.find(v => v.future === q.data?.objectId);
|
|
673
|
+
let r2 = g.input_witness.find(v => v.future === q.data?.objectId)
|
|
587
674
|
// not match r1 || r2 means query-cmd, not witness-cmd
|
|
588
675
|
if (r1 || r2) {
|
|
589
|
-
let object = this.object_query(q.data, 'witness');
|
|
676
|
+
let object = this.object_query(q.data, 'witness'); // witness address onchain check
|
|
590
677
|
if (!object) { ERROR(Errors.Fail, 'witness object fail') }
|
|
591
678
|
witness.push(object!);
|
|
592
679
|
}
|
|
593
680
|
})
|
|
681
|
+
guards.push(g.object);
|
|
594
682
|
})
|
|
595
683
|
|
|
596
|
-
return {guard:
|
|
684
|
+
return {guard:guards, query:query, witness:witness} as PassportQuery;
|
|
597
685
|
}
|
|
598
686
|
|
|
599
|
-
|
|
687
|
+
// create onchain query for objects : object, movecall-types, id
|
|
688
|
+
private object_query = (data: any, method:'guard_query'|'witness'='guard_query') : Guard_Query_Object | undefined=> {
|
|
600
689
|
for (let k = 0; k < this.protocol.WOWOK_OBJECTS_TYPE().length; k++) {
|
|
601
690
|
if (data.type.includes(this.protocol.WOWOK_OBJECTS_TYPE()[k]) ) { // type: pack::m::Object<...>
|
|
602
691
|
return { target:this.protocol.WOWOK_OBJECTS_PREFIX_TYPE()[k] + method as FnCallType,
|
|
@@ -620,13 +709,11 @@ export class Passport {
|
|
|
620
709
|
|
|
621
710
|
get_object () { return this.passport }
|
|
622
711
|
// return passport object used
|
|
623
|
-
|
|
712
|
+
// bObject(true) in cmd env; (false) in service env
|
|
713
|
+
constructor (protocol:Protocol, query:PassportQuery, bObject:boolean=false) {
|
|
624
714
|
if (!query.guard || query.guard.length > Passport.MAX_GUARD_COUNT) {
|
|
625
715
|
ERROR(Errors.InvalidParam, 'guards' )
|
|
626
716
|
}
|
|
627
|
-
if (!Protocol.IsValidObjects(query.guard)) {
|
|
628
|
-
ERROR(Errors.IsValidObjects, 'guards')
|
|
629
|
-
}
|
|
630
717
|
|
|
631
718
|
this.protocol = protocol;
|
|
632
719
|
let txb = protocol.CurrentSession();
|
|
@@ -639,7 +726,7 @@ export class Passport {
|
|
|
639
726
|
query.guard.forEach((g) => {
|
|
640
727
|
txb.moveCall({
|
|
641
728
|
target:protocol.PassportFn('guard_add') as FnCallType,
|
|
642
|
-
arguments:[this.passport,
|
|
729
|
+
arguments:[this.passport, txb.object(g)]
|
|
643
730
|
});
|
|
644
731
|
})
|
|
645
732
|
|
|
@@ -652,7 +739,7 @@ export class Passport {
|
|
|
652
739
|
})
|
|
653
740
|
})
|
|
654
741
|
|
|
655
|
-
// rules: 'verify' & 'query' in turns
|
|
742
|
+
// rules: 'verify' & 'query' in turns; 'verify' at final end.
|
|
656
743
|
query?.query.forEach((q) => {
|
|
657
744
|
let address = txb.moveCall({
|
|
658
745
|
target: protocol.PassportFn('passport_verify') as FnCallType,
|
|
@@ -660,7 +747,7 @@ export class Passport {
|
|
|
660
747
|
});
|
|
661
748
|
txb.moveCall({
|
|
662
749
|
target: q.target as FnCallType,
|
|
663
|
-
arguments: [ txb.object(q.object), this.passport, address ],
|
|
750
|
+
arguments: [ bObject ? txb.object(q.object) : txb.object(q.id), this.passport, address ],
|
|
664
751
|
typeArguments: q.types,
|
|
665
752
|
})
|
|
666
753
|
})
|
package/src/protocol.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { SuiClient, SuiObjectResponse, SuiObjectDataOptions, SuiTransactionBlock
|
|
|
3
3
|
import { Ed25519Keypair } from '@mysten/sui.js/keypairs/ed25519';
|
|
4
4
|
import { BCS, getSuiMoveConfig, toHEX, fromHEX, BcsReader } from '@mysten/bcs';
|
|
5
5
|
import { TransactionBlock, Inputs, TransactionResult, TransactionArgument } from '@mysten/sui.js/transactions';
|
|
6
|
-
import { capitalize, IsValidArray } from './utils'
|
|
6
|
+
import { capitalize, IsValidAddress, IsValidArray, IsValidU128, IsValidU64, IsValidU8, IsValidUintLarge } from './utils'
|
|
7
7
|
import { GuardConstant } from './guard';
|
|
8
8
|
import { isValidSuiAddress, isValidSuiObjectId } from '@mysten/sui.js/utils'
|
|
9
9
|
|
|
@@ -76,6 +76,20 @@ export enum OperatorType {
|
|
|
76
76
|
TYPE_LOGIC_OR = 21, // OR
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
export const LogicsInfo = [
|
|
80
|
+
[OperatorType.TYPE_LOGIC_AS_U256_GREATER, 'PositiveNumber >'],
|
|
81
|
+
[OperatorType.TYPE_LOGIC_AS_U256_GREATER_EQUAL, 'PositiveNumber >='],
|
|
82
|
+
[OperatorType.TYPE_LOGIC_AS_U256_LESSER, 'PositiveNumber <'],
|
|
83
|
+
[OperatorType.TYPE_LOGIC_AS_U256_LESSER_EQUAL, 'PositiveNumber <='],
|
|
84
|
+
[OperatorType.TYPE_LOGIC_AS_U256_EQUAL, 'PositiveNumber ='],
|
|
85
|
+
[OperatorType.TYPE_LOGIC_EQUAL, 'Strict ='],
|
|
86
|
+
[OperatorType.TYPE_LOGIC_HAS_SUBSTRING, 'Sub String'],
|
|
87
|
+
[OperatorType.TYPE_LOGIC_ALWAYS_TRUE, 'Always True'],
|
|
88
|
+
[OperatorType.TYPE_LOGIC_NOT, 'Not'],
|
|
89
|
+
[OperatorType.TYPE_LOGIC_AND, 'And'],
|
|
90
|
+
[OperatorType.TYPE_LOGIC_OR, 'Or'],
|
|
91
|
+
];
|
|
92
|
+
|
|
79
93
|
export enum ValueType {
|
|
80
94
|
TYPE_BOOL = 100,
|
|
81
95
|
TYPE_ADDRESS = 101,
|
|
@@ -101,6 +115,7 @@ export enum ValueType {
|
|
|
101
115
|
TYPE_VEC_STRING = 121,
|
|
102
116
|
TYPE_U256 = 122,
|
|
103
117
|
}
|
|
118
|
+
|
|
104
119
|
export enum RepositoryValueType {
|
|
105
120
|
Address = 200,
|
|
106
121
|
Address_Vec = 201,
|
|
@@ -119,50 +134,34 @@ export const RepositoryValueTypeInfo = [
|
|
|
119
134
|
{type: RepositoryValueType.PositiveNumber_Vec, name:'Positive number or Zero vector', description:'Vector of positive number or 0'},
|
|
120
135
|
]
|
|
121
136
|
|
|
122
|
-
export const ValueTypeInfo = [
|
|
123
|
-
{type:ValueType.TYPE_BOOL, name:'bool'},
|
|
124
|
-
{type:ValueType.TYPE_ADDRESS, name:'address'},
|
|
125
|
-
{type:ValueType.TYPE_U64, name:'u64'},
|
|
126
|
-
{type:ValueType.TYPE_U8, name:'u8'},
|
|
127
|
-
{type:ValueType.TYPE_VEC_U8, name:'vec-u8'},
|
|
128
|
-
{type:ValueType.TYPE_U128, name:'u128'},
|
|
129
|
-
{type:ValueType.TYPE_VEC_ADDRESS, name:'vec-address'},
|
|
130
|
-
{type:ValueType.TYPE_VEC_BOOL, name:'vec-bool'},
|
|
131
|
-
{type:ValueType.TYPE_VEC_VEC_U8, name:'vec-vec-u8'},
|
|
132
|
-
{type:ValueType.TYPE_VEC_U64, name:'vec-u64'},
|
|
133
|
-
{type:ValueType.TYPE_VEC_U128, name:'vec-u128'},
|
|
134
|
-
{type:ValueType.TYPE_OPTION_ADDRESS, name:'opt-address'},
|
|
135
|
-
{type:ValueType.TYPE_OPTION_BOOL, name:'opt-bool'},
|
|
136
|
-
{type:ValueType.TYPE_OPTION_U8, name:'opt-u8'},
|
|
137
|
-
{type:ValueType.TYPE_OPTION_U64, name:'opt-u64'},
|
|
138
|
-
{type:ValueType.TYPE_OPTION_U128, name:'opt-u128'},
|
|
139
|
-
{type:ValueType.TYPE_OPTION_U256, name:'opt-u256'},
|
|
140
|
-
{type:ValueType.TYPE_OPTION_STRING, name:'opt-string'},
|
|
141
|
-
{type:ValueType.TYPE_OPTION_VEC_U8, name:'opt-vec-u8'},
|
|
142
|
-
{type:ValueType.TYPE_VEC_U256, name:'vec-u256'},
|
|
143
|
-
{type:ValueType.TYPE_STRING, name:'string'},
|
|
144
|
-
{type:ValueType.TYPE_VEC_STRING, name:'vec-string'},
|
|
145
|
-
{type:ValueType.TYPE_U256, name:'u256'},
|
|
146
|
-
]
|
|
147
|
-
|
|
148
137
|
export const OperatorTypeArray = (Object.values(OperatorType) as []).filter((v)=>typeof(v) === 'number') as number[];
|
|
149
138
|
export const ValueTypeArray = (Object.values(ValueType) as []).filter((v)=>typeof(v) === 'number') as number[];
|
|
150
|
-
export const IsValidOperatorType = (type:number) => { return OperatorTypeArray.includes(type)}
|
|
151
|
-
export const IsValidValueType = (type:number) => { return ValueTypeArray.includes(type)}
|
|
139
|
+
export const IsValidOperatorType = (type:number) : boolean => { return OperatorTypeArray.includes(type)}
|
|
140
|
+
export const IsValidValueType = (type:number) : boolean => { return ValueTypeArray.includes(type)}
|
|
152
141
|
|
|
142
|
+
export enum ContextType {
|
|
143
|
+
TYPE_SIGNER = 60,
|
|
144
|
+
TYPE_CLOCK = 61,
|
|
145
|
+
TYPE_WITNESS_ID = 62,
|
|
146
|
+
TYPE_CONSTANT = 80,
|
|
147
|
+
}
|
|
153
148
|
interface ValueTypeString {
|
|
154
|
-
type: ValueType;
|
|
149
|
+
type: ValueType | ContextType;
|
|
155
150
|
name: string;
|
|
156
151
|
description: string;
|
|
152
|
+
validator?: (value:any) => boolean;
|
|
157
153
|
}
|
|
158
154
|
|
|
159
155
|
export const SER_VALUE: ValueTypeString[] = [
|
|
160
|
-
{type: ValueType.TYPE_BOOL, name: 'bool', description:'boolean. eg:true or false'},
|
|
161
|
-
{type: ValueType.TYPE_ADDRESS, name: 'address', description:'address or object-id. eg:0x6789af'},
|
|
162
|
-
{type:
|
|
163
|
-
{type:
|
|
164
|
-
{type:
|
|
165
|
-
{type: ValueType.
|
|
156
|
+
{type: ValueType.TYPE_BOOL, name: 'bool', description:'boolean. eg:true or false', validator:(value:any) => { return (value === true || value === false)}},
|
|
157
|
+
{type: ValueType.TYPE_ADDRESS, name: 'address', description:'address or object-id. eg:0x6789af', validator:IsValidAddress},
|
|
158
|
+
{type: ContextType.TYPE_WITNESS_ID, name: 'future address', description:"eg: machine's future progress, service's future order", validator:IsValidAddress},
|
|
159
|
+
{type: ContextType.TYPE_SIGNER, name: 'txn signer', description:"signer address of the transaction, ", validator:IsValidAddress},
|
|
160
|
+
{type: ContextType.TYPE_CLOCK, name: 'txn time', description:"unsigned-64 number for the transaction time", validator:IsValidU64},
|
|
161
|
+
{type: ValueType.TYPE_U64, name: 'number', description:'unsigned-64 number. eg:23870233', validator:IsValidU64},
|
|
162
|
+
{type: ValueType.TYPE_U8, name: 'number', description:'unsigned-8 number. eg:255', validator:IsValidU8},
|
|
163
|
+
{type: ValueType.TYPE_VEC_U8, name: 'string', description:'string or unsigned-8 number array. eg:"[1,2,3]"'},
|
|
164
|
+
{type: ValueType.TYPE_U128, name: 'number', description:'unsigned-8 number. eg:12348900999', validator:IsValidU128},
|
|
166
165
|
{type: ValueType.TYPE_VEC_ADDRESS, name: '[address]', description:'address array. eg:[0x2277f2, 0x3344af]'},
|
|
167
166
|
{type: ValueType.TYPE_VEC_BOOL, name: '[bool]', description:'boolean array. eg:[true, false, true]'},
|
|
168
167
|
{type: ValueType.TYPE_VEC_VEC_U8, name: '[[number]]', description:'array of unsigned-8 number array. eg:["i", "like", "wowok"]'},
|
|
@@ -176,18 +175,11 @@ export const SER_VALUE: ValueTypeString[] = [
|
|
|
176
175
|
{type: ValueType.TYPE_OPTION_U256, name: 'option', description:'option of u256. eg:none or u256 value'},
|
|
177
176
|
{type: ValueType.TYPE_VEC_U256, name: '[number]', description:'unsigned-256 number array. eg:[123, 778888, 42312]'},
|
|
178
177
|
{type: ValueType.TYPE_VEC_STRING, name: '[string]', description:'ascii string array. eg:["abc", "hi"]'},
|
|
179
|
-
{type: ValueType.TYPE_STRING, name: 'string', description:'ascii string. eg:"wowok"'},
|
|
178
|
+
{type: ValueType.TYPE_STRING, name: 'string', description:'ascii string. eg:"wowok"', },
|
|
180
179
|
{type: ValueType.TYPE_OPTION_STRING, name: 'option', description:'option of string. eg:none or string value'},
|
|
181
|
-
{type: ValueType.TYPE_U256, name: 'number', description:'unsigned-256 number. eg:12345678901233'},
|
|
180
|
+
{type: ValueType.TYPE_U256, name: 'number', description:'unsigned-256 number. eg:12345678901233', validator:IsValidUintLarge},
|
|
182
181
|
]
|
|
183
182
|
|
|
184
|
-
export enum ContextType {
|
|
185
|
-
TYPE_SIGNER = 60,
|
|
186
|
-
TYPE_CLOCK = 61,
|
|
187
|
-
TYPE_WITNESS_ID = 62,
|
|
188
|
-
TYPE_CONSTANT = 80,
|
|
189
|
-
}
|
|
190
|
-
|
|
191
183
|
export type ConstantType = ValueType | ContextType.TYPE_WITNESS_ID;
|
|
192
184
|
export type Data_Type = ValueType | OperatorType | ContextType;
|
|
193
185
|
|
|
@@ -199,9 +191,9 @@ export enum ENTRYPOINT {
|
|
|
199
191
|
}
|
|
200
192
|
|
|
201
193
|
const TESTNET = {
|
|
202
|
-
package: "
|
|
203
|
-
wowok_object: '
|
|
204
|
-
entity_object: '
|
|
194
|
+
package: "0x8ba9f90c9a0e5f2199a92fdc5ea255ac9df5471289cfe40a87ac90f25d93dd5b",
|
|
195
|
+
wowok_object: '0x9d33a57a09f3ff73ba51afe6ed2e671e7d78b771e34b0a1ba66e52264e34b3fd',
|
|
196
|
+
entity_object: '0xb759e1e5569f1f8d5ae30efb6efec0a639c5ef70a7c7abcc012919cf5dae33af',
|
|
205
197
|
}
|
|
206
198
|
|
|
207
199
|
const MAINNET = {
|
package/src/utils.ts
CHANGED
|
@@ -355,7 +355,6 @@ export const deepClone = <T>(origin: T, target?: Record<string, any> | T ): T =>
|
|
|
355
355
|
} else {
|
|
356
356
|
tar[key] = origin[key]
|
|
357
357
|
}
|
|
358
|
-
|
|
359
358
|
}
|
|
360
359
|
}
|
|
361
360
|
|
|
@@ -371,21 +370,36 @@ export const IsValidDesription = (description:string) : boolean => { return desc
|
|
|
371
370
|
export const IsValidName = (name:string) : boolean => { if(!name) return false; return name.length <= MAX_NAME_LENGTH && name.length != 0 }
|
|
372
371
|
export const IsValidName_AllowEmpty = (name:string) : boolean => { return name.length <= MAX_NAME_LENGTH }
|
|
373
372
|
export const IsValidEndpoint = (endpoint:string) : boolean => { if (!endpoint) return false; return endpoint.length <= MAX_ENDPOINT_LENGTH }
|
|
374
|
-
export const IsValidAddress = (addr:string) : boolean => {
|
|
373
|
+
export const IsValidAddress = (addr:string | undefined) : boolean => {
|
|
375
374
|
if (!addr || !isValidSuiAddress(addr)) {
|
|
376
375
|
return false;
|
|
377
376
|
}
|
|
378
377
|
return true
|
|
379
378
|
}
|
|
380
|
-
export const
|
|
379
|
+
export const IsValidBigint = (value:string | number | undefined, max:bigint=MAX_U256) : boolean => {
|
|
380
|
+
if (value === '' || value === undefined) return false;
|
|
381
381
|
try {
|
|
382
382
|
const v = BigInt(value);
|
|
383
|
-
if (v <=
|
|
383
|
+
if (v <= max) {
|
|
384
384
|
return true
|
|
385
385
|
}
|
|
386
386
|
} catch (e) {
|
|
387
387
|
}; return false
|
|
388
388
|
}
|
|
389
|
+
|
|
390
|
+
export const IsValidUintLarge = (value:string | number | undefined) : boolean => {
|
|
391
|
+
return IsValidBigint(value)
|
|
392
|
+
}
|
|
393
|
+
export const IsValidU8 = (value:string | number | undefined) : boolean => {
|
|
394
|
+
return IsValidBigint(value, MAX_U8)
|
|
395
|
+
}
|
|
396
|
+
export const IsValidU64 = (value:string | number | undefined) : boolean => {
|
|
397
|
+
return IsValidBigint(value, MAX_U64)
|
|
398
|
+
}
|
|
399
|
+
export const IsValidU128 = (value:string | number | undefined) : boolean => {
|
|
400
|
+
return IsValidBigint(value, MAX_U128)
|
|
401
|
+
}
|
|
402
|
+
|
|
389
403
|
export const IsValidTokenType = (argType: string) : boolean => {
|
|
390
404
|
if (!argType || argType.length === 0) {
|
|
391
405
|
return false;
|
|
@@ -551,4 +565,9 @@ export const query_object = (param:query_object_param) => {
|
|
|
551
565
|
if (param?.onDynamicErr) param.onDynamicErr(param.id, err);
|
|
552
566
|
})
|
|
553
567
|
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
export const FirstLetterUppercase = (str:string) => {
|
|
571
|
+
if (!str) return str;
|
|
572
|
+
return str.substring(0, 1).toUpperCase() + str.substring(1);
|
|
554
573
|
}
|