wowok 1.0.6 → 1.0.8

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/src/passport.ts CHANGED
@@ -1,36 +1,62 @@
1
1
  import { SuiObjectResponse, SuiObjectDataOptions } from '@mysten/sui.js/client';
2
- import { TransactionBlock, TransactionResult, type TransactionObjectInput, Inputs } from '@mysten/sui.js/transactions';
3
- import { PROTOCOL, FnCallType, CLOCK_OBJECT, Query_Param, OBJECTS_TYPE, OBJECTS_TYPE_PREFIX, PassportObject, GuardObject, TXB_OBJECT} from './protocol';
4
- import { parse_object_type, array_unique } from './utils';
5
- import { rpc_sense_objects_fn } from './guard';
2
+ import { TransactionBlock, TransactionResult, type TransactionObjectInput, Inputs, TransactionArgument } from '@mysten/sui.js/transactions';
3
+ import { PROTOCOL, FnCallType, CLOCK_OBJECT, Query_Param, OBJECTS_TYPE, OBJECTS_TYPE_PREFIX, PassportObject, GuardObject,
4
+ TXB_OBJECT, ContextType, IsValidAddress, IsValidArray, IsValidObjects} from './protocol';
5
+ import { parse_object_type, array_unique, BCS_CONVERT } from './utils';
6
+ import { rpc_sense_objects_fn, parse_sense_bsc, parse_futures, FutureValueRequest, VariableType, add_variable, add_future_variable} from './guard';
7
+ import { BCS } from '@mysten/bcs';
6
8
 
7
9
  export const MAX_GUARD_COUNT = 8;
8
10
 
11
+ // from guards: get future objects to fill by singer
12
+ export const guard_futures = async (guards:string[]) : Promise<FutureValueRequest[]> => {
13
+ let futrue_objects = guards.map((value) => {
14
+ return {objectid:value, callback:rpc_sense_objects_fn, parser:parse_futures, data:[]} as Query_Param
15
+ });
16
+ await PROTOCOL.Query(futrue_objects); // future objects
17
+ let future_objects_result:FutureValueRequest[] = [];
18
+ futrue_objects.forEach((futrue) => {
19
+ futrue.data.forEach((f:FutureValueRequest) => {
20
+ if (future_objects_result.findIndex((v)=>{ return v.guardid == f.guardid && v.identifier == f.identifier}) == -1) {
21
+ future_objects_result.push(f);
22
+ }
23
+ }) ;
24
+ });
25
+
26
+ return future_objects_result
27
+ }
28
+
29
+ // from guards: get objects to 'guard_query' on chain , with future variables had filled.
9
30
  // passport verify for some guards, MUST be in ONE pxb:
10
31
  // 0. construct Guard_Query_Objects(passport_quries) from queries for guards of objects
11
32
  // 1. create passport
12
- // 2. add all guards
33
+ // 2. add all guards / guards future variables
13
34
  // 3. verify passport
14
35
  // 4. ops using passport(guard set on object)
15
36
  // 5. ops using passport(guard set on object)
16
37
  // 6. destroy passport
17
-
18
-
19
- export const passport_queries = async (guards:string[]) : Promise<Guard_Query_Object[]> => {
38
+ export const guard_queries = async (guards:string[], futures?:FutureValueRequest[]) : Promise<Guard_Query_Object[]> => {
20
39
  let sense_objects = guards.map((value) => {
21
- return {objectid:value, callback:rpc_sense_objects_fn, data:[]} as Query_Param
40
+ let v:VariableType = new Map();
41
+ futures?.forEach((f) => {
42
+ if (f.guardid == value) {
43
+ add_future_variable(v, f.identifier, f.type, f.witness.slice(0), f?.value?f.value.slice(0):undefined, true);
44
+ }
45
+ })
46
+ return {objectid:value, callback:rpc_sense_objects_fn, parser:parse_sense_bsc, data:[], variables:futures?v:undefined} as Query_Param
22
47
  });
48
+
23
49
  await PROTOCOL.Query(sense_objects); // objects need quering in guards
24
50
  let sense_objects_result:string[] = [];
25
51
  sense_objects.forEach((value) => { // DONT CHANGE objects sequence
26
52
  sense_objects_result = sense_objects_result.concat(value.data);
27
53
  });
28
54
  sense_objects_result = array_unique(sense_objects_result); // objects in guards
29
- // console.log(sense_objects_result);
30
-
55
+
31
56
  let queries = sense_objects_result.map((value) => {
32
57
  return {objectid:value, callback:rpc_query_cmd_fn, data:[]} as Query_Param;
33
58
  })
59
+
34
60
  await PROTOCOL.Query(queries, {'showType':true}); // queries for passport verifing
35
61
  let res : Guard_Query_Object[] = [];
36
62
  sense_objects.forEach((guard) => { // DONT CHANGE objects sequence for passport verifying
@@ -51,40 +77,47 @@ export const passport_queries = async (guards:string[]) : Promise<Guard_Query_Ob
51
77
  }
52
78
 
53
79
  // return passport object used
54
- export function verify(txb:TransactionBlock, guards:string[], passport_queries:Guard_Query_Object[]) : PassportObject | boolean {
55
- if (!guards || passport_queries.length == 0 || passport_queries.length > MAX_GUARD_COUNT) {
56
- return false;
57
- }
58
-
80
+ export function verify(txb:TransactionBlock, guards:GuardObject[], guard_queries:Guard_Query_Object[], future_values?:FutureValueRequest[]) : PassportObject | boolean {
81
+ if (!guards || guards.length > MAX_GUARD_COUNT) return false;
82
+ if (!IsValidObjects(guards)) return false;
83
+
59
84
  var passport = txb.moveCall({
60
85
  target: PROTOCOL.PassportFn('new') as FnCallType,
61
- arguments: [ TXB_OBJECT(txb, guards[0]), txb.object(CLOCK_OBJECT)]
86
+ arguments: []
62
87
  });
63
-
88
+
64
89
  // add others guards, if any
65
- for (let i = 1; i < guards.length; i++) {
90
+ guards.forEach((guard) => {
66
91
  txb.moveCall({
67
92
  target:PROTOCOL.PassportFn('guard_add') as FnCallType,
68
- arguments:[passport, TXB_OBJECT(txb, guards[i])]
69
- });
70
- }
93
+ arguments:[passport, TXB_OBJECT(txb, guard)]
94
+ });
95
+ })
71
96
 
72
- // rules: 'verify' & 'query' in turns;'verify' at final end.
73
- for (let i = 0; i < passport_queries.length; i++) {
97
+ future_values?.forEach((v) => {
74
98
  txb.moveCall({
99
+ target:PROTOCOL.PassportFn('future_set') as FnCallType,
100
+ arguments:[passport, txb.pure(BCS_CONVERT.ser_address(v.guardid)), txb.pure(BCS_CONVERT.ser_u8(v.identifier)),
101
+ txb.pure(BCS_CONVERT.ser_address(v.value!))]
102
+ })
103
+ })
104
+
105
+ // rules: 'verify' & 'query' in turns;'verify' at final end.
106
+ for (let i = 0; i < guard_queries.length; i++) {
107
+ let res = txb.moveCall({
75
108
  target: PROTOCOL.PassportFn('passport_verify') as FnCallType,
76
- arguments: [ passport ]
109
+ arguments: [ passport, txb.object(CLOCK_OBJECT), ]
77
110
  });
78
111
  txb.moveCall({
79
- target: passport_queries[i].target as FnCallType,
80
- arguments: [ txb.object(passport_queries[i].object), passport ],
81
- typeArguments: passport_queries[i].types,
112
+ target: guard_queries[i].target as FnCallType,
113
+ arguments: [ txb.object(guard_queries[i].object), passport, res ],
114
+ typeArguments: guard_queries[i].types,
82
115
  })
83
- }
116
+ }
84
117
  txb.moveCall({
85
118
  target: PROTOCOL.PassportFn('passport_verify') as FnCallType,
86
- arguments: [ passport ]
87
- });
119
+ arguments: [ passport, txb.object(CLOCK_OBJECT) ]
120
+ });
88
121
 
89
122
  return passport;
90
123
  }
package/src/progress.ts CHANGED
@@ -55,13 +55,13 @@ export function progress_set_namedOperator(txb:TransactionBlock, machine:Machine
55
55
  if (passport) {
56
56
  txb.moveCall({
57
57
  target:PROTOCOL.ProgressFn('namedOperator_set_with_passport') as FnCallType,
58
- arguments: [passport, TXB_OBJECT(txb, progress), txb.pure(name), txb.pure(array_unique(addresses), 'vector<address>'),
58
+ arguments: [passport, TXB_OBJECT(txb, progress), txb.pure(name, BCS.STRING), txb.pure(array_unique(addresses), 'vector<address>'),
59
59
  TXB_OBJECT(txb, machine), TXB_OBJECT(txb, permission)],
60
60
  })
61
61
  } else {
62
62
  txb.moveCall({
63
63
  target:PROTOCOL.ProgressFn('namedOperator_set') as FnCallType,
64
- arguments: [TXB_OBJECT(txb, progress), txb.pure(name), txb.pure(array_unique(addresses), 'vector<address>'),
64
+ arguments: [TXB_OBJECT(txb, progress), txb.pure(name, BCS.STRING), txb.pure(array_unique(addresses), 'vector<address>'),
65
65
  TXB_OBJECT(txb, machine), TXB_OBJECT(txb, permission)],
66
66
  })
67
67
  }
package/src/protocol.ts CHANGED
@@ -4,18 +4,19 @@ import { Ed25519Keypair } from '@mysten/sui.js/keypairs/ed25519';
4
4
  import { BCS, getSuiMoveConfig, toHEX, fromHEX, BcsReader } from '@mysten/bcs';
5
5
  import { TransactionBlock, Inputs, type TransactionResult, type TransactionArgument } from '@mysten/sui.js/transactions';
6
6
  import { capitalize } from './utils'
7
+ import { VariableType } from './guard';
7
8
 
8
9
  export const MAX_DESCRIPTION_LENGTH = 1024;
9
10
  export const MAX_NAME_LENGTH = 64;
10
11
  export const MAX_ENDPOINT_LENGTH = 1024;
11
12
  export const OptionNone = (txb:TransactionBlock) : TransactionArgument => { return txb.pure([], BCS.U8) };
12
13
 
13
- export const IsValidDesription = (description:string) : boolean => { return description.length <= MAX_DESCRIPTION_LENGTH }
14
- export const IsValidName = (name:string) : boolean => { return name.length <= MAX_NAME_LENGTH && name.length != 0 }
14
+ export const IsValidDesription = (description:string) : boolean => { if (!description) return false; return description.length <= MAX_DESCRIPTION_LENGTH }
15
+ export const IsValidName = (name:string) : boolean => { if(!name) return false; return name.length <= MAX_NAME_LENGTH && name.length != 0 }
15
16
  export const IsValidName_AllowEmpty = (name:string) : boolean => { return name.length <= MAX_NAME_LENGTH }
16
- export const IsValidEndpoint = (endpoint:string) : boolean => { return endpoint.length <= MAX_ENDPOINT_LENGTH }
17
- export const IsValidAddress = (address:string) : boolean => { return address.length != 0 }
18
- export const IsValidArgType = (argType: string) : boolean => { return argType.length != 0 }
17
+ export const IsValidEndpoint = (endpoint:string) : boolean => { if (!endpoint) return false; return endpoint.length <= MAX_ENDPOINT_LENGTH }
18
+ export const IsValidAddress = (addr:string) : boolean => { if (!addr) return false; return true}
19
+ export const IsValidArgType = (argType: string) : boolean => { if (!argType) return false; return argType.length != 0 }
19
20
  export const IsValidUint = (value: number) : boolean => { return Number.isSafeInteger(value) && value != 0 }
20
21
  export const IsValidInt = (value: number) : boolean => { return Number.isSafeInteger(value) }
21
22
  export const IsValidPercent = (value: number) : boolean => { return Number.isSafeInteger(value) && value > 0 && value <= 100 }
@@ -57,7 +58,7 @@ export type PermissionObject = TransactionResult | string;
57
58
  export type RepositoryAddress = TransactionResult;
58
59
  export type RepositoryObject = TransactionResult | string;
59
60
  export type GuardAddress = TransactionResult;
60
- export type GuardObject = TransactionResult | string;
61
+ export type GuardObject = TransactionResult | string ;
61
62
  export type MachineAddress = TransactionResult;
62
63
  export type MachineObject = TransactionResult | string;
63
64
  export type PassportObject = TransactionResult;
@@ -92,13 +93,51 @@ export const CLOCK_OBJECT = Inputs.SharedObjectRef({
92
93
  initialSharedVersion: 1,
93
94
  });
94
95
 
96
+ export enum OperatorType {
97
+ TYPE_QUERY = 1, // query wowok object
98
+ TYPE_FUTURE_QUERY = 2,
99
+ TYPE_QUERY_FROM_CONTEXT = 3,
100
+
101
+ TYPE_LOGIC_OPERATOR_U128_GREATER = 11,
102
+ TYPE_LOGIC_OPERATOR_U128_GREATER_EQUAL = 12,
103
+ TYPE_LOGIC_OPERATOR_U128_LESSER = 13,
104
+ TYPE_LOGIC_OPERATOR_U128_LESSER_EQUAL = 14,
105
+ TYPE_LOGIC_OPERATOR_U128_EQUAL = 15,
106
+ TYPE_LOGIC_OPERATOR_EQUAL = 16, // TYPE&DATA(vector<u8>) MUST BE EQUAL
107
+ TYPE_LOGIC_OPERATOR_HAS_SUBSTRING = 17, // SUBSTRING
108
+ TYPE_LOGIC_ALWAYS_TRUE = 18, // aways true
109
+ }
110
+
111
+ export enum ContextType {
112
+ TYPE_CONTEXT_SIGNER = 60,
113
+ TYPE_CONTEXT_CLOCK = 61,
114
+ TYPE_CONTEXT_FUTURE_ID = 62,
115
+
116
+ TYPE_CONTEXT_bool = 70,
117
+ TYPE_CONTEXT_address = 71,
118
+ TYPE_CONTEXT_u64 = 72,
119
+ TYPE_CONTEXT_u8 = 73,
120
+ TYPE_CONTEXT_vec_u8 = 74,
121
+ /* TYPE_CONTEXT_u128 = 75,
122
+ TYPE_CONTEXT_vec_address = 76,
123
+ TYPE_CONTEXT_vec_bool = 77,
124
+ TYPE_CONTEXT_vec_vec_u8 = 78,
125
+ TYPE_CONTEXT_vec_u64 = 79,
126
+ TYPE_CONTEXT_vec_u128 = 80,
127
+ TYPE_CONTEXT_option_address = 81,
128
+ TYPE_CONTEXT_option_bool = 82,
129
+ TYPE_CONTEXT_option_u8 = 83,
130
+ TYPE_CONTEXT_option_u64 = 84,
131
+ TYPE_CONTEXT_option_u128 = 85,*/
132
+ }
133
+
95
134
  export enum ValueType {
96
135
  TYPE_STATIC_bool = 100,
97
136
  TYPE_STATIC_address = 101,
98
137
  TYPE_STATIC_u64 = 102,
99
138
  TYPE_STATIC_u8 = 103,
100
- TYPE_STATIC_u128 = 104,
101
- TYPE_STATIC_vec_u8 = 105,
139
+ TYPE_STATIC_vec_u8 = 104,
140
+ TYPE_STATIC_u128 = 105,
102
141
  TYPE_STATIC_vec_address = 106,
103
142
  TYPE_STATIC_vec_bool = 107,
104
143
  TYPE_STATIC_vec_vec_u8 = 108,
@@ -111,24 +150,6 @@ export enum ValueType {
111
150
  TYPE_STATIC_option_u128 = 115,
112
151
  }
113
152
 
114
- export enum OperatorType {
115
- TYPE_DYNAMIC_QUERY = 1, // query wowok object
116
- TYPE_LOGIC_OPERATOR_U128_GREATER = 11,
117
- TYPE_LOGIC_OPERATOR_U128_GREATER_EQUAL = 12,
118
- TYPE_LOGIC_OPERATOR_U128_LESSER = 13,
119
- TYPE_LOGIC_OPERATOR_U128_LESSER_EQUAL = 14,
120
- TYPE_LOGIC_OPERATOR_U128_EQUAL = 15,
121
- TYPE_LOGIC_OPERATOR_EQUAL = 16, // TYPE&DATA(vector<u8>) MUST BE EQUAL
122
- TYPE_LOGIC_OPERATOR_HAS_SUBSTRING = 17, // SUBSTRING
123
- TYPE_LOGIC_ALWAYS_TRUE = 18, // aways true
124
- }
125
-
126
- export enum ContextType {
127
- TYPE_CONTEXT_SIGNER = 60,
128
- TYPE_CONTEXT_CURRENT_PROGRESS = 61,
129
- TYPE_CONTEXT_CURRENT_CLOCK = 62,
130
- }
131
-
132
153
  export type Data_Type = ValueType | OperatorType | ContextType;
133
154
 
134
155
  export enum ENTRYPOINT {
@@ -159,7 +180,7 @@ export class Protocol {
159
180
  case ENTRYPOINT.devnet:
160
181
  break;
161
182
  case ENTRYPOINT.testnet:
162
- this.package = "0x877375bc3bde063e4b95f428df218af7faaeef431993f4a68f2dfa5ceb8acb2e";
183
+ this.package = "0xf4233055f40a9f301c85c020496b58ad761fdd2cd6a5d82da7a912adb4608f7f";
163
184
  this.everyone_guard = "0x78a41fcc4f566360839613f6b917fb101ae015e56b43143f496f265b6422fddc";
164
185
  this.graphql = 'https://sui-testnet.mystenlabs.com/graphql';
165
186
  break;
@@ -224,7 +245,8 @@ export class Protocol {
224
245
  const response = await client.signAndExecuteTransactionBlock({
225
246
  transactionBlock: txb,
226
247
  signer: keypair,
227
- options
248
+ options,
249
+
228
250
  });
229
251
  return response;
230
252
  }
@@ -233,7 +255,9 @@ export class Protocol {
233
255
  export type Query_Param = {
234
256
  objectid: string;
235
257
  callback: (response:SuiObjectResponse, param:Query_Param, option:SuiObjectDataOptions)=>void;
258
+ parser?: (result:any[], guardid: string, chain_sense_bsc:Uint8Array, variable?:VariableType) => boolean;
236
259
  data?: any; // response data filted by callback
260
+ variables?: VariableType;
237
261
  };
238
262
  export const PROTOCOL = new Protocol();
239
263
  export const SUI_TYPE = '0x2::coin::Coin<0x2::sui::SUI>';
package/src/service.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { TransactionBlock, type TransactionResult } from '@mysten/sui.js/transactions';
2
- import { BCS } from '@mysten/bcs';
2
+ import { bcs, BCS, toHEX, fromHEX, getSuiMoveConfig } from '@mysten/bcs';
3
3
  import { BCS_CONVERT, array_unique } from './utils'
4
4
  import { CLOCK_OBJECT, FnCallType, GuardObject, PROTOCOL, PassportObject, PermissionObject,
5
5
  RepositoryObject, MachineObject, ServiceAddress, ServiceObject, IsValidObjects, IsValidArgType, IsValidDesription,
@@ -72,7 +72,7 @@ export function service_set_description(pay_type:string, txb:TransactionBlock, s
72
72
  return true
73
73
  }
74
74
  export function service_set_price(pay_type:string, txb:TransactionBlock, service:ServiceObject, permission:PermissionObject,
75
- item:string, price:number, passport?:PassportObject) : boolean {
75
+ item:string, price:number, bNotFoundAssert:boolean=true, passport?:PassportObject) : boolean {
76
76
  if (!IsValidObjects([service, permission])) return false;
77
77
  if (!IsValidArgType(pay_type)) return false;
78
78
  if (!IsValidInt(price) || !IsValidName(item)) return false;
@@ -80,20 +80,22 @@ export function service_set_price(pay_type:string, txb:TransactionBlock, service
80
80
  if (passport) {
81
81
  txb.moveCall({
82
82
  target:PROTOCOL.ServiceFn('price_set_with_passport') as FnCallType,
83
- arguments:[passport, TXB_OBJECT(txb, service), txb.pure(item), txb.pure(price, BCS.U64), TXB_OBJECT(txb, permission)],
83
+ arguments:[passport, TXB_OBJECT(txb, service), txb.pure(item), txb.pure(price, BCS.U64),
84
+ txb.pure(bNotFoundAssert, BCS.BOOL), TXB_OBJECT(txb, permission)],
84
85
  typeArguments:[pay_type]
85
86
  })
86
87
  } else {
87
88
  txb.moveCall({
88
89
  target:PROTOCOL.ServiceFn('price_set') as FnCallType,
89
- arguments:[TXB_OBJECT(txb, service), txb.pure(item), txb.pure(price, BCS.U64), TXB_OBJECT(txb, permission)],
90
+ arguments:[TXB_OBJECT(txb, service), txb.pure(item), txb.pure(price, BCS.U64),
91
+ txb.pure(bNotFoundAssert, BCS.BOOL), TXB_OBJECT(txb, permission)],
90
92
  typeArguments:[pay_type]
91
93
  })
92
94
  }
93
95
  return true
94
96
  }
95
97
  export function service_set_stock(pay_type:string, txb:TransactionBlock, service:ServiceObject, permission:PermissionObject,
96
- item:string, stock:number, passport?:PassportObject) : boolean {
98
+ item:string, stock:number, bNotFoundAssert:boolean=true, passport?:PassportObject) : boolean {
97
99
  if (!IsValidObjects([service, permission])) return false;
98
100
  if (!IsValidArgType(pay_type)) return false;
99
101
  if (!IsValidName(item) || !IsValidInt(stock)) return false;
@@ -101,53 +103,59 @@ export function service_set_stock(pay_type:string, txb:TransactionBlock, service
101
103
  if (passport) {
102
104
  txb.moveCall({
103
105
  target:PROTOCOL.ServiceFn('stock_set_with_passport') as FnCallType,
104
- arguments:[passport, TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock, BCS.U64), TXB_OBJECT(txb, permission)],
106
+ arguments:[passport, TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock, BCS.U64),
107
+ txb.pure(bNotFoundAssert, BCS.BOOL), TXB_OBJECT(txb, permission)],
105
108
  typeArguments:[pay_type]
106
109
  })
107
110
  } else {
108
111
  txb.moveCall({
109
112
  target:PROTOCOL.ServiceFn('stock_set') as FnCallType,
110
- arguments:[TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock, BCS.U64), TXB_OBJECT(txb, permission)],
113
+ arguments:[TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock, BCS.U64),
114
+ txb.pure(bNotFoundAssert, BCS.BOOL), TXB_OBJECT(txb, permission)],
111
115
  typeArguments:[pay_type]
112
116
  })
113
117
  }
114
118
  return true
115
119
  }
116
120
  export function service_add_stock(pay_type:string, txb:TransactionBlock, service:ServiceObject, permission:PermissionObject,
117
- item:string, stock_add:number, passport?:PassportObject) : boolean {
121
+ item:string, stock_add:number, bNotFoundAssert:boolean=true, passport?:PassportObject) : boolean {
118
122
  if (!IsValidObjects([service, permission])) return false;
119
123
  if (!IsValidArgType(pay_type)) return false;
120
124
  if (!IsValidName(item) || !IsValidUint(stock_add)) return false;
121
125
  if (passport) {
122
126
  txb.moveCall({
123
127
  target:PROTOCOL.ServiceFn('stock_add_with_passport') as FnCallType,
124
- arguments:[passport, TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock_add, BCS.U64), TXB_OBJECT(txb, permission)],
128
+ arguments:[passport, TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock_add, BCS.U64),
129
+ txb.pure(bNotFoundAssert, BCS.BOOL), TXB_OBJECT(txb, permission)],
125
130
  typeArguments:[pay_type]
126
131
  })
127
132
  } else {
128
133
  txb.moveCall({
129
134
  target:PROTOCOL.ServiceFn('stock_add') as FnCallType,
130
- arguments:[TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock_add, BCS.U64), TXB_OBJECT(txb, permission)],
135
+ arguments:[TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock_add, BCS.U64),
136
+ txb.pure(bNotFoundAssert, BCS.BOOL), TXB_OBJECT(txb, permission)],
131
137
  typeArguments:[pay_type]
132
138
  })
133
139
  }
134
140
  return true
135
141
  }
136
142
  export function service_reduce_stock(pay_type:string, txb:TransactionBlock, service:ServiceObject, permission:PermissionObject,
137
- item:string, stock_reduce:number, passport?:PassportObject) : boolean {
143
+ item:string, stock_reduce:number, bNotFoundAssert:boolean=true, passport?:PassportObject) : boolean {
138
144
  if (!IsValidObjects([service, permission])) return false;
139
145
  if (!IsValidArgType(pay_type)) return false;
140
146
  if (!IsValidName(item) || !IsValidUint(stock_reduce)) return false;
141
147
  if (passport) {
142
148
  txb.moveCall({
143
149
  target:PROTOCOL.ServiceFn('stock_reduce_with_passport') as FnCallType,
144
- arguments:[passport, TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock_reduce, BCS.U64), TXB_OBJECT(txb, permission)],
150
+ arguments:[passport, TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock_reduce, BCS.U64),
151
+ txb.pure(bNotFoundAssert, BCS.BOOL), TXB_OBJECT(txb, permission)],
145
152
  typeArguments:[pay_type]
146
153
  })
147
154
  } else {
148
155
  txb.moveCall({
149
156
  target:PROTOCOL.ServiceFn('stock_reduce') as FnCallType,
150
- arguments:[TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock_reduce, BCS.U64), TXB_OBJECT(txb, permission)],
157
+ arguments:[TXB_OBJECT(txb, service), txb.pure(item), txb.pure(stock_reduce, BCS.U64),
158
+ txb.pure(bNotFoundAssert, BCS.BOOL), TXB_OBJECT(txb, permission)],
151
159
  typeArguments:[pay_type]
152
160
  })
153
161
  }
@@ -372,30 +380,44 @@ export type Service_Sale = {
372
380
  stock:number;
373
381
  }
374
382
 
375
- export function service_add_sale(pay_type:string, txb:TransactionBlock, service:ServiceObject,
376
- permission:PermissionObject, sales:Service_Sale[], passport?:PassportObject) : boolean {
377
- if (!IsValidObjects([service, permission])) return false;
378
- if (!IsValidArgType(pay_type)) return false;
379
- let bValid = true;
383
+ export function is_valid_sale(sales:Service_Sale[]) : boolean {
384
+ let bValid = true; let names:string[] = [];
380
385
  sales.forEach((v) => {
381
386
  if (!IsValidName(v.item)) bValid = false;
382
387
  if (!IsValidInt(v.price)) bValid = false;
383
- if (!IsValidInt(v.stock)) bValid = false;
388
+ if (!IsValidUint(v.stock)) bValid = false;
389
+ if (names.includes(v.item)) bValid = false;
390
+ names.push(v.item)
384
391
  })
392
+ return bValid
393
+ }
394
+ export function service_add_sale(pay_type:string, txb:TransactionBlock, service:ServiceObject,
395
+ permission:PermissionObject, sales:Service_Sale[], passport?:PassportObject) : boolean {
396
+ if (!IsValidObjects([service, permission])) return false;
397
+ if (!IsValidArgType(pay_type)) return false;
398
+ if (!sales) return false;
399
+ let bValid = is_valid_sale(sales);
385
400
  if (!bValid) return false;
401
+
402
+ let names: string[] = []; let price: number[] = []; let stock: number[] = [];
403
+ sales.forEach((s) => {
404
+ names.push(s.item); price.push(s.price); stock.push(s.stock);
405
+ })
386
406
 
387
407
  if (passport) {
388
- sales.forEach((sale) => txb.moveCall({
408
+ txb.moveCall({
389
409
  target:PROTOCOL.ServiceFn('sales_add_with_passport') as FnCallType,
390
- arguments:[passport, TXB_OBJECT(txb, service), txb.pure(sale.item), txb.pure(sale.price, BCS.U64), txb.pure(sale.stock, BCS.U64), TXB_OBJECT(txb, permission)],
410
+ arguments:[passport, TXB_OBJECT(txb, service), txb.pure(BCS_CONVERT.ser_vector_string(names)),
411
+ txb.pure(BCS_CONVERT.ser_vector_u64(price)), txb.pure(BCS_CONVERT.ser_vector_u64(stock)), TXB_OBJECT(txb, permission)],
391
412
  typeArguments:[pay_type]
392
- }))
413
+ })
393
414
  } else {
394
- sales.forEach((sale) => txb.moveCall({
415
+ txb.moveCall({
395
416
  target:PROTOCOL.ServiceFn('sales_add') as FnCallType,
396
- arguments:[TXB_OBJECT(txb, service), txb.pure(sale.item), txb.pure(sale.price, BCS.U64), txb.pure(sale.stock, BCS.U64), TXB_OBJECT(txb, permission)],
417
+ arguments:[TXB_OBJECT(txb, service), txb.pure(BCS_CONVERT.ser_vector_string(names)),
418
+ txb.pure(BCS_CONVERT.ser_vector_u64(price)), txb.pure(BCS_CONVERT.ser_vector_u64(stock)), TXB_OBJECT(txb, permission)],
397
419
  typeArguments:[pay_type]
398
- }))
420
+ })
399
421
  }
400
422
  return true
401
423
  }
@@ -803,6 +825,7 @@ export function customer_refund(pay_type:string, txb:TransactionBlock, service:S
803
825
  }
804
826
  export type Service_Buy = {
805
827
  item: string;
828
+ max_price: number;
806
829
  count: number;
807
830
  }
808
831
 
@@ -828,42 +851,45 @@ export function buy(pay_type:string, txb:TransactionBlock, service:ServiceObject
828
851
  if (!IsValidArgType(pay_type)) return false;
829
852
  if (!buy_items) return false;
830
853
 
831
- let bValid = true;
854
+ let bValid = true; let names:string[] = [];
832
855
  buy_items.forEach((v) => {
833
856
  if (!IsValidName(v.item)) bValid = false;
857
+ if (!IsValidInt(v.max_price)) bValid = false;
834
858
  if (!IsValidUint(v.count)) bValid = false;
859
+ if (names.includes(v.item)) bValid = false;
860
+ names.push(v.item)
835
861
  })
836
862
  if (!bValid) return false;
837
863
 
838
- let i:string[] = []; let c:number[] = []; let order;
839
- buy_items.forEach((item) => { i.push(item.item); c.push(item.count); })
864
+ let name:string[] = []; let price:number[] = []; let stock:number[] = []; let order;
865
+ buy_items.forEach((b) => { name.push(b.item); price.push(b.max_price); stock.push(b.count)})
840
866
 
841
867
  if (passport) {
842
868
  if (discount) {
843
869
  order = txb.moveCall({
844
870
  target:PROTOCOL.ServiceFn('dicount_buy_with_passport') as FnCallType,
845
- arguments: [passport, TXB_OBJECT(txb, service), txb.pure(BCS_CONVERT.ser_vector_string(i)),
846
- txb.pure(BCS_CONVERT.ser_vector_u64(c)), TXB_OBJECT(txb, coin), TXB_OBJECT(txb, discount), txb.object(CLOCK_OBJECT)],
871
+ arguments: [passport, TXB_OBJECT(txb, service), txb.pure(BCS_CONVERT.ser_vector_string(name)), txb.pure(BCS_CONVERT.ser_vector_u64(price)),
872
+ txb.pure(BCS_CONVERT.ser_vector_u64(stock)), TXB_OBJECT(txb, coin), TXB_OBJECT(txb, discount), txb.object(CLOCK_OBJECT)],
847
873
  typeArguments:[pay_type]
848
874
  })} else {
849
875
  order = txb.moveCall({
850
876
  target:PROTOCOL.ServiceFn('buy_with_passport') as FnCallType,
851
- arguments: [passport, TXB_OBJECT(txb, service), txb.pure(BCS_CONVERT.ser_vector_string(i)),
852
- txb.pure(BCS_CONVERT.ser_vector_u64(c)), TXB_OBJECT(txb, coin)],
877
+ arguments: [passport, TXB_OBJECT(txb, service), txb.pure(BCS_CONVERT.ser_vector_string(name)), txb.pure(BCS_CONVERT.ser_vector_u64(price)),
878
+ txb.pure(BCS_CONVERT.ser_vector_u64(stock)), TXB_OBJECT(txb, coin)],
853
879
  typeArguments:[pay_type]
854
880
  })}
855
881
  } else {
856
882
  if (discount) {
857
883
  order = txb.moveCall({
858
884
  target:PROTOCOL.ServiceFn('disoucnt_buy') as FnCallType,
859
- arguments: [TXB_OBJECT(txb, service), txb.pure(BCS_CONVERT.ser_vector_string(i)),
860
- txb.pure(BCS_CONVERT.ser_vector_u64(c)), TXB_OBJECT(txb, coin), TXB_OBJECT(txb, discount), txb.object(CLOCK_OBJECT)],
885
+ arguments: [TXB_OBJECT(txb, service), txb.pure(BCS_CONVERT.ser_vector_string(name)), txb.pure(BCS_CONVERT.ser_vector_u64(price)),
886
+ txb.pure(BCS_CONVERT.ser_vector_u64(stock)), TXB_OBJECT(txb, coin), TXB_OBJECT(txb, discount), txb.object(CLOCK_OBJECT)],
861
887
  typeArguments:[pay_type]
862
888
  })} else {
863
889
  order = txb.moveCall({
864
890
  target:PROTOCOL.ServiceFn('buy') as FnCallType,
865
- arguments: [TXB_OBJECT(txb, service), txb.pure(BCS_CONVERT.ser_vector_string(i)),
866
- txb.pure(BCS_CONVERT.ser_vector_u64(c)), TXB_OBJECT(txb, coin)],
891
+ arguments: [TXB_OBJECT(txb, service), txb.pure(BCS_CONVERT.ser_vector_string(name)), txb.pure(BCS_CONVERT.ser_vector_u64(price)),
892
+ txb.pure(BCS_CONVERT.ser_vector_u64(stock)), TXB_OBJECT(txb, coin)],
867
893
  typeArguments:[pay_type]
868
894
  })}
869
895
  }
package/src/utils.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { SuiTransactionBlockResponse, SuiObjectChange } from '@mysten/sui.js/client';
2
- import { bcs, BCS, toHEX, fromHEX, getSuiMoveConfig } from '@mysten/bcs';
2
+ import { bcs, BCS, toHEX, fromHEX, getSuiMoveConfig, TypeName, StructTypeDefinition } from '@mysten/bcs';
3
3
  import { PROTOCOL, MODULES, OBJECTS_TYPE } from './protocol';
4
4
 
5
5
  export const ulebDecode = (arr: number[] | Uint8Array) : {value: number, length: number} => {
@@ -97,6 +97,27 @@ export class Bcs {
97
97
  ser_vector_u64(data:number[]) : Uint8Array {
98
98
  return this.bcs.ser('vector<u64>', data).toBytes();
99
99
  }
100
+ ser_vector_u8(data:number[]) : Uint8Array {
101
+ return this.bcs.ser('vector<u8>', data).toBytes();
102
+ }
103
+ ser_address(data:string) : Uint8Array {
104
+ return this.bcs.ser(BCS.ADDRESS, data).toBytes();
105
+ }
106
+ ser_bool(data:boolean) : Uint8Array {
107
+ return this.bcs.ser(BCS.BOOL, data).toBytes();
108
+ }
109
+ ser_u8(data:number) : Uint8Array {
110
+ return this.bcs.ser(BCS.U8, data).toBytes();
111
+ }
112
+ ser_u64(data:number) : Uint8Array {
113
+ return this.bcs.ser(BCS.U64, data).toBytes();
114
+ }
115
+ ser_string(data:string) : Uint8Array {
116
+ return this.bcs.ser(BCS.STRING, data).toBytes();
117
+ }
118
+ de(type:TypeName | StructTypeDefinition, data:Uint8Array) {
119
+ return this.bcs.de(type, data)
120
+ }
100
121
  }
101
122
 
102
123
  export const BCS_CONVERT = new Bcs();
@@ -155,4 +176,29 @@ export function numToUint8Array(num:number) : Uint8Array {
155
176
  a.unshift(num & 255)
156
177
  }
157
178
  return new Uint8Array(a)
158
- }
179
+ }
180
+
181
+ // 判断是否为数组
182
+ export const isArr = (origin: any): boolean => {
183
+ let str = '[object Array]'
184
+ return Object.prototype.toString.call(origin) == str ? true : false
185
+ }
186
+
187
+
188
+ export const deepClone = <T>(origin: T, target?: Record<string, any> | T ): T => {
189
+ let tar = target || {}
190
+
191
+ for (const key in origin) {
192
+ if (Object.prototype.hasOwnProperty.call(origin, key)) {
193
+ if (typeof origin[key] === 'object' && origin[key] !== null) {
194
+ tar[key] = isArr(origin[key]) ? [] : {}
195
+ deepClone(origin[key], tar[key])
196
+ } else {
197
+ tar[key] = origin[key]
198
+ }
199
+
200
+ }
201
+ }
202
+
203
+ return tar as T
204
+ }