@xelis/sdk 0.11.15 → 0.11.16

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 (50) hide show
  1. package/dist/cjs/address/bech32.js +47 -56
  2. package/dist/cjs/address/index.js +20 -21
  3. package/dist/cjs/config.js +26 -38
  4. package/dist/cjs/contract/contract.js +178 -0
  5. package/dist/cjs/contract/typed_contract.js +259 -0
  6. package/dist/cjs/contract/xvm_serializer.js +170 -0
  7. package/dist/cjs/daemon/rpc.js +157 -168
  8. package/dist/cjs/daemon/types.js +4 -1
  9. package/dist/cjs/daemon/websocket.js +170 -181
  10. package/dist/cjs/data/element.js +39 -41
  11. package/dist/cjs/data/value.js +106 -111
  12. package/dist/cjs/react/daemon.js +33 -43
  13. package/dist/cjs/rpc/http.js +75 -132
  14. package/dist/cjs/rpc/parse_json/parse_json.js +4 -4
  15. package/dist/cjs/rpc/types.js +1 -1
  16. package/dist/cjs/rpc/websocket.js +131 -201
  17. package/dist/cjs/wallet/rpc.js +98 -117
  18. package/dist/cjs/wallet/types.js +1 -1
  19. package/dist/cjs/wallet/websocket.js +105 -126
  20. package/dist/cjs/xswd/relayer/app.js +57 -36
  21. package/dist/cjs/xswd/relayer/index.js +25 -27
  22. package/dist/cjs/xswd/types.js +1 -1
  23. package/dist/cjs/xswd/websocket.js +15 -33
  24. package/dist/esm/address/bech32.js +46 -55
  25. package/dist/esm/address/index.js +16 -17
  26. package/dist/esm/config.js +25 -37
  27. package/dist/esm/contract/contract.js +172 -0
  28. package/dist/esm/contract/typed_contract.js +251 -0
  29. package/dist/esm/contract/xvm_serializer.js +163 -0
  30. package/dist/esm/daemon/rpc.js +153 -165
  31. package/dist/esm/daemon/types.js +3 -0
  32. package/dist/esm/daemon/websocket.js +166 -179
  33. package/dist/esm/data/element.js +37 -40
  34. package/dist/esm/data/value.js +104 -112
  35. package/dist/esm/react/daemon.js +30 -40
  36. package/dist/esm/rpc/http.js +73 -131
  37. package/dist/esm/rpc/parse_json/parse_json.js +1 -1
  38. package/dist/esm/rpc/websocket.js +126 -197
  39. package/dist/esm/wallet/rpc.js +93 -113
  40. package/dist/esm/wallet/websocket.js +101 -124
  41. package/dist/esm/xswd/relayer/app.js +54 -34
  42. package/dist/esm/xswd/relayer/index.js +22 -24
  43. package/dist/esm/xswd/websocket.js +10 -29
  44. package/dist/types/contract/contract.d.ts +80 -0
  45. package/dist/types/contract/typed_contract.d.ts +94 -0
  46. package/dist/types/contract/xvm_serializer.d.ts +69 -0
  47. package/dist/types/daemon/rpc.d.ts +5 -2
  48. package/dist/types/daemon/types.d.ts +96 -17
  49. package/dist/types/daemon/websocket.d.ts +5 -2
  50. package/package.json +1 -1
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createContractFromJSON = exports.validateABI = exports.TypedContractFactory = exports.createTypedContract = exports.TypedContract = void 0;
4
+ const xvm_serializer_1 = require("./xvm_serializer");
5
+ // Convert ABI type to validator type
6
+ function normalizeType(abiType) {
7
+ const typeMap = {
8
+ 'Hash': 'Hash',
9
+ 'Address': 'Address',
10
+ 'PublicKey': 'PublicKey',
11
+ 'Blob': 'Blob',
12
+ 'u256': 'u256',
13
+ 'u128': 'u128',
14
+ 'u64': 'u64',
15
+ 'u32': 'u32',
16
+ 'u16': 'u16',
17
+ 'u8': 'u8',
18
+ 'boolean': 'boolean',
19
+ 'bool': 'boolean',
20
+ 'string': 'string',
21
+ 'String': 'string',
22
+ 'Boolean': 'boolean',
23
+ 'U256': 'u256',
24
+ 'U128': 'u128',
25
+ 'U64': 'u64',
26
+ 'U32': 'u32',
27
+ 'U16': 'u16',
28
+ 'U8': 'u8'
29
+ };
30
+ const normalized = typeMap[abiType];
31
+ if (!normalized) {
32
+ throw new Error(`Unknown ABI type: ${abiType}`);
33
+ }
34
+ return normalized;
35
+ }
36
+ /**
37
+ * Strongly typed contract class
38
+ */
39
+ class TypedContract {
40
+ constructor(address, abi) {
41
+ this.address = address;
42
+ this.abi = abi;
43
+ this.methods = new Map();
44
+ // Initialize methods
45
+ for (const entry of abi.data) {
46
+ if (entry.type === 'entry') {
47
+ console.log("new method", entry.name);
48
+ this.methods.set(entry.name, entry);
49
+ }
50
+ }
51
+ // Return a Proxy to handle dynamic method calls
52
+ return new Proxy(this, {
53
+ get(target, prop, receiver) {
54
+ // If it's a known property/method, return it
55
+ if (prop in target) {
56
+ return Reflect.get(target, prop, receiver);
57
+ }
58
+ // If it's a string property that matches a method name, create dynamic method
59
+ if (typeof prop === 'string' && target.methods.has(prop)) {
60
+ return (params) => target.invokeUnsafe(prop, params);
61
+ }
62
+ return undefined;
63
+ }
64
+ });
65
+ }
66
+ /**
67
+ * Internal method to invoke contract functions
68
+ */
69
+ invokeUnsafe(methodName, params = {}) {
70
+ const entry = this.methods.get(methodName);
71
+ if (!entry) {
72
+ throw new Error(`Method '${methodName}' not found in contract ABI`);
73
+ }
74
+ // Extract special parameters
75
+ const { maxGas, deposits, ...methodParams } = params;
76
+ // Build parameter list according to ABI
77
+ const parameters = [];
78
+ for (const abiParam of entry.params) {
79
+ const value = methodParams[abiParam.name];
80
+ // Check if parameter is required
81
+ if (value === undefined && !abiParam.optional) {
82
+ if (abiParam.default !== undefined) {
83
+ methodParams[abiParam.name] = abiParam.default;
84
+ }
85
+ else {
86
+ throw new Error(`Missing required parameter '${abiParam.name}' for method '${methodName}'`);
87
+ }
88
+ }
89
+ if (value !== undefined) {
90
+ try {
91
+ const normalizedType = normalizeType(abiParam.type);
92
+ const vmParam = (0, xvm_serializer_1.createVMParameter)(value, normalizedType);
93
+ parameters.push(vmParam);
94
+ }
95
+ catch (error) {
96
+ throw new Error(`Invalid parameter '${abiParam.name}' for method '${methodName}': ${error}`);
97
+ }
98
+ }
99
+ }
100
+ // Create the contract invocation
101
+ const invocationParams = {
102
+ contract: this.address,
103
+ chunkId: entry.chunk_id,
104
+ parameters,
105
+ maxGas: maxGas || 200000000
106
+ };
107
+ if (deposits && Object.keys(deposits).length > 0) {
108
+ invocationParams.deposits = deposits;
109
+ }
110
+ return (0, xvm_serializer_1.createContractInvocation)(invocationParams);
111
+ }
112
+ /**
113
+ * Type-safe invoke method
114
+ */
115
+ invoke(methodName, params) {
116
+ return this.invokeUnsafe(methodName, params);
117
+ }
118
+ /**
119
+ * Get list of available methods
120
+ */
121
+ getMethods() {
122
+ return Array.from(this.methods.keys());
123
+ }
124
+ /**
125
+ * Get method signature information
126
+ */
127
+ getMethodSignature(methodName) {
128
+ return this.methods.get(methodName);
129
+ }
130
+ /**
131
+ * Generate TypeScript interface for the contract
132
+ */
133
+ generateInterface() {
134
+ const lines = [
135
+ `interface ${this.constructor.name}Methods {`
136
+ ];
137
+ for (const [name, entry] of this.methods) {
138
+ const params = entry.params.map(p => {
139
+ const optional = p.optional ? '?' : '';
140
+ return ` ${p.name}${optional}: ${this.getTypeScriptType(p.type)};`;
141
+ }).join('\n');
142
+ lines.push(` ${name}(params: {`);
143
+ lines.push(params);
144
+ lines.push(' maxGas?: number;');
145
+ lines.push(' deposits?: Record<string, number | bigint>;');
146
+ lines.push(' }): Record<string, any>;');
147
+ lines.push('');
148
+ }
149
+ lines.push('}');
150
+ return lines.join('\n');
151
+ }
152
+ getTypeScriptType(abiType) {
153
+ const typeMap = {
154
+ 'Hash': 'string',
155
+ 'Address': 'string',
156
+ 'PublicKey': 'string',
157
+ 'Blob': 'string',
158
+ 'String': 'string',
159
+ 'string': 'string',
160
+ 'Boolean': 'boolean',
161
+ 'boolean': 'boolean',
162
+ 'bool': 'boolean',
163
+ 'U256': 'bigint | number',
164
+ 'u256': 'bigint | number',
165
+ 'U128': 'bigint | number',
166
+ 'u128': 'bigint | number',
167
+ 'U64': 'bigint | number',
168
+ 'u64': 'bigint | number',
169
+ 'U32': 'number',
170
+ 'u32': 'number',
171
+ 'U16': 'number',
172
+ 'u16': 'number',
173
+ 'U8': 'number',
174
+ 'u8': 'number'
175
+ };
176
+ return typeMap[abiType] || 'any';
177
+ }
178
+ }
179
+ exports.TypedContract = TypedContract;
180
+ /**
181
+ * Create a typed contract instance with full TypeScript support
182
+ */
183
+ function createTypedContract(address, abi) {
184
+ return new TypedContract(address, abi);
185
+ }
186
+ exports.createTypedContract = createTypedContract;
187
+ /**
188
+ * Contract factory with strong typing
189
+ */
190
+ class TypedContractFactory {
191
+ constructor(abi, contractName = 'Contract') {
192
+ this.abi = abi;
193
+ this.contractName = contractName;
194
+ }
195
+ /**
196
+ * Create a new contract instance at the specified address
197
+ */
198
+ at(address) {
199
+ return createTypedContract(address, this.abi);
200
+ }
201
+ /**
202
+ * Get the ABI
203
+ */
204
+ getABI() {
205
+ return this.abi;
206
+ }
207
+ /**
208
+ * Generate TypeScript definitions for this contract
209
+ */
210
+ generateTypeDefinitions() {
211
+ const contract = new TypedContract('0x0', this.abi);
212
+ return contract.generateInterface();
213
+ }
214
+ }
215
+ exports.TypedContractFactory = TypedContractFactory;
216
+ /**
217
+ * Utility to validate ABI structure
218
+ */
219
+ function validateABI(abi) {
220
+ if (!Array.isArray(abi)) {
221
+ return false;
222
+ }
223
+ for (const entry of abi) {
224
+ if (typeof entry !== 'object' || !entry) {
225
+ return false;
226
+ }
227
+ if (typeof entry.chunk_id !== 'number') {
228
+ return false;
229
+ }
230
+ if (typeof entry.name !== 'string') {
231
+ return false;
232
+ }
233
+ if (!Array.isArray(entry.params)) {
234
+ return false;
235
+ }
236
+ if (entry.type !== 'entry' && entry.type !== 'view') {
237
+ return false;
238
+ }
239
+ for (const param of entry.params) {
240
+ if (typeof param.name !== 'string' || typeof param.type !== 'string') {
241
+ return false;
242
+ }
243
+ }
244
+ }
245
+ return true;
246
+ }
247
+ exports.validateABI = validateABI;
248
+ /**
249
+ * Helper to create a contract from JSON ABI
250
+ */
251
+ async function createContractFromJSON(address, abiPath) {
252
+ const response = await fetch(abiPath);
253
+ const abi = await response.json();
254
+ if (!validateABI(abi.data)) {
255
+ throw new Error('Invalid ABI structure');
256
+ }
257
+ return createTypedContract(address, abi);
258
+ }
259
+ exports.createContractFromJSON = createContractFromJSON;
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createContractDeployment = exports.createContractInvocation = exports.createDeposits = exports.vmParam = exports.createVMParameter = void 0;
4
+ // Known opaque types that need special wrapping
5
+ const OPAQUE_TYPES = new Set(['Hash', 'Address', 'PublicKey', 'Blob' /** TODO */]);
6
+ // Type validation and conversion helpers
7
+ const TYPE_VALIDATORS = {
8
+ 'u256': (v) => {
9
+ const num = typeof v === 'bigint' ? v : BigInt(v);
10
+ if (num < 0n)
11
+ throw new Error(`Value ${v} cannot be negative for u256`);
12
+ return Number(num);
13
+ },
14
+ 'u128': (v) => {
15
+ const num = typeof v === 'bigint' ? v : BigInt(v);
16
+ if (num < 0n)
17
+ throw new Error(`Value ${v} cannot be negative for u128`);
18
+ return Number(num);
19
+ },
20
+ 'u64': (v) => {
21
+ const num = typeof v === 'bigint' ? v : BigInt(v);
22
+ if (num < 0n || num > 0xffffffffffffffffn) {
23
+ throw new Error(`Value ${v} is out of range for u64`);
24
+ }
25
+ return Number(num);
26
+ },
27
+ 'u32': (v) => {
28
+ const num = Number(v);
29
+ if (num < 0 || num > 0xFFFFFFFF || !Number.isInteger(num)) {
30
+ throw new Error(`Value ${v} is not a valid u32`);
31
+ }
32
+ return num;
33
+ },
34
+ 'u16': (v) => {
35
+ const num = Number(v);
36
+ if (num < 0 || num > 0xFFFF || !Number.isInteger(num)) {
37
+ throw new Error(`Value ${v} is not a valid u16`);
38
+ }
39
+ return num;
40
+ },
41
+ 'u8': (v) => {
42
+ const num = Number(v);
43
+ if (num < 0 || num > 255 || !Number.isInteger(num)) {
44
+ throw new Error(`Value ${v} is not a valid u8`);
45
+ }
46
+ return num;
47
+ },
48
+ 'boolean': (v) => Boolean(v),
49
+ 'string': (v) => String(v),
50
+ 'Hash': (v) => {
51
+ const str = String(v);
52
+ if (!/^[0-9a-fA-F]{64}$/.test(str)) {
53
+ throw new Error(`Value ${v} is not a valid 64-character hex hash`);
54
+ }
55
+ return str;
56
+ },
57
+ 'Address': (v) => {
58
+ const str = String(v);
59
+ // TODO validate
60
+ return str;
61
+ },
62
+ 'PublicKey': (v) => {
63
+ const str = String(v);
64
+ // TODO validate
65
+ return str;
66
+ },
67
+ 'Blob': (v) => {
68
+ const str = String(v);
69
+ // TODO validate
70
+ return str;
71
+ }
72
+ };
73
+ /**
74
+ * Creates a VM-compatible parameter object
75
+ * @param value - The value to wrap
76
+ * @param type - The type string (e.g., 'u64', 'Hash', 'string')
77
+ * @param validate - Whether to validate and convert the value (default: true)
78
+ */
79
+ function createVMParameter(value, type, validate = true) {
80
+ let processedValue = value;
81
+ // Validate and convert value if requested
82
+ if (validate && TYPE_VALIDATORS[type]) {
83
+ try {
84
+ processedValue = TYPE_VALIDATORS[type](value);
85
+ }
86
+ catch (error) {
87
+ throw new Error(`Failed to create VM parameter for type ${type}: ${error}`);
88
+ }
89
+ }
90
+ // Handle opaque types (Hash, Address, PublicKey)
91
+ if (OPAQUE_TYPES.has(type)) {
92
+ return {
93
+ type: "default",
94
+ value: {
95
+ type: "opaque",
96
+ value: {
97
+ type: type,
98
+ value: processedValue
99
+ }
100
+ }
101
+ };
102
+ }
103
+ // Handle regular types
104
+ return {
105
+ type: "default",
106
+ value: {
107
+ type: type,
108
+ value: processedValue
109
+ }
110
+ };
111
+ }
112
+ exports.createVMParameter = createVMParameter;
113
+ /**
114
+ * Convenience functions for common types
115
+ */
116
+ exports.vmParam = {
117
+ hash: (value) => createVMParameter(value, 'Hash'),
118
+ address: (value) => createVMParameter(value, 'Address'),
119
+ publicKey: (value) => createVMParameter(value, 'PublicKey'),
120
+ blob: (value) => createVMParameter(value, 'Blob'),
121
+ u64: (value) => createVMParameter(value, 'u64'),
122
+ u32: (value) => createVMParameter(value, 'u32'),
123
+ u16: (value) => createVMParameter(value, 'u16'),
124
+ u8: (value) => createVMParameter(value, 'u8'),
125
+ string: (value) => createVMParameter(value, 'string'),
126
+ boolean: (value) => createVMParameter(value, 'boolean'),
127
+ };
128
+ /**
129
+ * Creates a deposits object for contract calls
130
+ * @param deposits - Object mapping token hashes to amounts
131
+ */
132
+ function createDeposits(deposits) {
133
+ const result = {};
134
+ for (const [tokenHash, amount] of Object.entries(deposits)) {
135
+ // Validate hash format
136
+ if (!/^[0-9a-fA-F]{64}$/.test(tokenHash)) {
137
+ throw new Error(`Invalid token hash format: ${tokenHash}`);
138
+ }
139
+ result[tokenHash] = { amount };
140
+ }
141
+ return result;
142
+ }
143
+ exports.createDeposits = createDeposits;
144
+ function createContractInvocation(params) {
145
+ const { contract, chunkId, parameters = [], deposits, maxGas = 200000000 } = params;
146
+ const result = {
147
+ invoke_contract: {
148
+ contract,
149
+ max_gas: maxGas,
150
+ chunk_id: chunkId,
151
+ parameters
152
+ }
153
+ };
154
+ if (deposits && Object.keys(deposits).length > 0) {
155
+ result.invoke_contract.deposits = createDeposits(deposits);
156
+ }
157
+ return result;
158
+ }
159
+ exports.createContractInvocation = createContractInvocation;
160
+ function createContractDeployment(params) {
161
+ const { bytecode, hasConstructor = false, maxGas = 200000000 } = params;
162
+ const result = {
163
+ deploy_contract: {
164
+ module: bytecode,
165
+ ...(hasConstructor && { invoke: { max_gas: maxGas } })
166
+ }
167
+ };
168
+ return result;
169
+ }
170
+ exports.createContractDeployment = createContractDeployment;