@dedot/contracts 0.13.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/errors.js +31 -6
- package/cjs/executor/ConstructorQueryExecutor.js +4 -3
- package/cjs/executor/ConstructorTxExecutor.js +107 -17
- package/cjs/executor/QueryExecutor.js +4 -3
- package/cjs/executor/TxExecutor.js +41 -14
- package/cjs/utils/ensure.js +7 -1
- package/errors.d.ts +13 -3
- package/errors.js +31 -6
- package/executor/ConstructorQueryExecutor.js +6 -5
- package/executor/ConstructorTxExecutor.js +105 -15
- package/executor/QueryExecutor.js +6 -5
- package/executor/TxExecutor.js +40 -13
- package/package.json +6 -6
- package/types/index.d.ts +16 -8
- package/types/v6.d.ts +1 -1
- package/utils/ensure.d.ts +1 -0
- package/utils/ensure.js +6 -1
package/cjs/errors.js
CHANGED
|
@@ -3,6 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.isContractInstantiateLangError = exports.isContractInstantiateDispatchError = exports.isContractInstantiateError = exports.isContractLangError = exports.isContractDispatchError = exports.isContractExecutionError = exports.ContractLangError = exports.ContractDispatchError = exports.ContractExecutionError = exports.ContractInstantiateLangError = exports.ContractInstantiateDispatchError = exports.ContractInstantiateError = void 0;
|
|
4
4
|
const utils_1 = require("@dedot/utils");
|
|
5
5
|
const index_js_1 = require("./utils/index.js");
|
|
6
|
+
const formatDispatchError = (err, moduleError) => {
|
|
7
|
+
if (moduleError) {
|
|
8
|
+
const { pallet, name, docs } = moduleError;
|
|
9
|
+
let message = `Dispatch error: ${pallet}::${name}`;
|
|
10
|
+
if (docs) {
|
|
11
|
+
message += ` - ${docs.join('\n ')}`;
|
|
12
|
+
}
|
|
13
|
+
return message;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
return `Dispatch error: ${JSON.stringify(err)}`;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
6
19
|
/**
|
|
7
20
|
* Represents an error that occurred during the instantiation of a smart contract.
|
|
8
21
|
* This class extends the base `DedotError` and includes a `raw` property of type `ContractInstantiateResult`.
|
|
@@ -42,16 +55,22 @@ class ContractInstantiateDispatchError extends ContractInstantiateError {
|
|
|
42
55
|
* The error that occurred during the dispatch phase.
|
|
43
56
|
*/
|
|
44
57
|
dispatchError;
|
|
58
|
+
/**
|
|
59
|
+
* The decoded module error, if any.
|
|
60
|
+
*/
|
|
61
|
+
moduleError;
|
|
45
62
|
/**
|
|
46
63
|
* Constructs a new `ContractInstantiateDispatchError` instance.
|
|
47
64
|
*
|
|
48
65
|
* @param err - The `DispatchError` that occurred during the dispatch phase.
|
|
49
66
|
* @param raw - The raw result of the contract instantiation.
|
|
67
|
+
* @param moduleError - The decoded module error, if any.
|
|
50
68
|
*/
|
|
51
|
-
constructor(err, raw) {
|
|
69
|
+
constructor(err, raw, moduleError) {
|
|
52
70
|
super(raw);
|
|
53
71
|
this.dispatchError = err;
|
|
54
|
-
this.
|
|
72
|
+
this.moduleError = moduleError;
|
|
73
|
+
this.message = formatDispatchError(err, moduleError);
|
|
55
74
|
}
|
|
56
75
|
}
|
|
57
76
|
exports.ContractInstantiateDispatchError = ContractInstantiateDispatchError;
|
|
@@ -86,7 +105,7 @@ class ContractInstantiateLangError extends ContractInstantiateError {
|
|
|
86
105
|
super(raw);
|
|
87
106
|
this.langError = err;
|
|
88
107
|
this.flags = (0, index_js_1.toReturnFlags)(raw.result.value.result.flags.bits);
|
|
89
|
-
this.message = `
|
|
108
|
+
this.message = `Lang error: ${JSON.stringify(err)}`;
|
|
90
109
|
}
|
|
91
110
|
}
|
|
92
111
|
exports.ContractInstantiateLangError = ContractInstantiateLangError;
|
|
@@ -129,16 +148,22 @@ class ContractDispatchError extends ContractExecutionError {
|
|
|
129
148
|
* The error that occurred during the dispatch phase.
|
|
130
149
|
*/
|
|
131
150
|
dispatchError;
|
|
151
|
+
/**
|
|
152
|
+
* The decoded module error, if any.
|
|
153
|
+
*/
|
|
154
|
+
moduleError;
|
|
132
155
|
/**
|
|
133
156
|
* Constructs a new `ContractDispatchError` instance.
|
|
134
157
|
*
|
|
135
158
|
* @param err - The `DispatchError` that occurred during the dispatch phase.
|
|
136
159
|
* @param raw - The raw result of the contract call.
|
|
160
|
+
* @param moduleError - The decoded module error, if any.
|
|
137
161
|
*/
|
|
138
|
-
constructor(err, raw) {
|
|
162
|
+
constructor(err, raw, moduleError) {
|
|
139
163
|
super(raw);
|
|
140
164
|
this.dispatchError = err;
|
|
141
|
-
this.
|
|
165
|
+
this.moduleError = moduleError;
|
|
166
|
+
this.message = formatDispatchError(err, moduleError);
|
|
142
167
|
}
|
|
143
168
|
}
|
|
144
169
|
exports.ContractDispatchError = ContractDispatchError;
|
|
@@ -173,7 +198,7 @@ class ContractLangError extends ContractExecutionError {
|
|
|
173
198
|
super(raw);
|
|
174
199
|
this.langError = err;
|
|
175
200
|
this.flags = (0, index_js_1.toReturnFlags)(raw.result.value.flags.bits);
|
|
176
|
-
this.message = `
|
|
201
|
+
this.message = `Lang error: ${JSON.stringify(err)}`;
|
|
177
202
|
}
|
|
178
203
|
}
|
|
179
204
|
exports.ContractLangError = ContractLangError;
|
|
@@ -11,8 +11,7 @@ class ConstructorQueryExecutor extends index_js_2.DeployerExecutor {
|
|
|
11
11
|
(0, utils_1.assert)(meta, `Constructor message not found: ${constructor}`);
|
|
12
12
|
const callFn = async (...params) => {
|
|
13
13
|
const { args } = meta;
|
|
14
|
-
(0,
|
|
15
|
-
(0, utils_1.assertFalse)(params.length > args.length + 1, `Expected at most ${args.length + 1} arguments, got ${params.length}`);
|
|
14
|
+
(0, index_js_1.ensureParamsLength)(args.length, params.length);
|
|
16
15
|
const callOptions = (params[args.length] || {});
|
|
17
16
|
const { caller = this.options.defaultCaller, // --
|
|
18
17
|
value = 0n, gasLimit, storageDepositLimit, salt, } = callOptions;
|
|
@@ -64,7 +63,9 @@ class ConstructorQueryExecutor extends index_js_2.DeployerExecutor {
|
|
|
64
63
|
}
|
|
65
64
|
})();
|
|
66
65
|
if (raw.result.isErr) {
|
|
67
|
-
|
|
66
|
+
const dispatchError = raw.result.err;
|
|
67
|
+
const moduleError = client.registry.findErrorMeta(dispatchError);
|
|
68
|
+
throw new errors_js_1.ContractInstantiateDispatchError(dispatchError, raw, moduleError);
|
|
68
69
|
}
|
|
69
70
|
const data = this.tryDecode(meta, raw.result.value.result.data);
|
|
70
71
|
if (data.isErr) {
|
|
@@ -2,38 +2,128 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ConstructorTxExecutor = void 0;
|
|
4
4
|
const utils_1 = require("@dedot/utils");
|
|
5
|
-
const
|
|
6
|
-
|
|
5
|
+
const Contract_js_1 = require("../Contract.js");
|
|
6
|
+
const index_js_1 = require("../utils/index.js");
|
|
7
|
+
const ConstructorQueryExecutor_js_1 = require("./ConstructorQueryExecutor.js");
|
|
8
|
+
const index_js_2 = require("./abstract/index.js");
|
|
9
|
+
class ConstructorTxExecutor extends index_js_2.DeployerExecutor {
|
|
7
10
|
doExecute(constructor) {
|
|
8
11
|
const meta = this.findConstructorMeta(constructor);
|
|
9
12
|
(0, utils_1.assert)(meta, `Constructor message not found: ${constructor}`);
|
|
13
|
+
// @ts-ignore
|
|
10
14
|
const callFn = (...params) => {
|
|
11
15
|
const { args } = meta;
|
|
12
|
-
(0,
|
|
13
|
-
const txCallOptions = params[args.length];
|
|
16
|
+
(0, index_js_1.ensureParamsLength)(args.length, params.length);
|
|
17
|
+
const txCallOptions = (params[args.length] || {});
|
|
14
18
|
const { value = 0n, gasLimit, storageDepositLimit, salt } = txCallOptions;
|
|
15
|
-
(0, utils_1.assert)(gasLimit, 'Expected a gas limit in ConstructorTxOptions');
|
|
16
19
|
const formattedInputs = args.map((arg, index) => this.tryEncode(arg, params[index]));
|
|
17
20
|
const bytes = (0, utils_1.u8aToHex)((0, utils_1.concatU8a)((0, utils_1.hexToU8a)(meta.selector), ...formattedInputs));
|
|
18
21
|
const client = this.client;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
const tx = (() => {
|
|
23
|
+
if (this.registry.isRevive()) {
|
|
24
|
+
(0, utils_1.assert)((0, utils_1.isUndefined)(salt) || (0, utils_1.toU8a)(salt).byteLength == 32, 'Invalid salt provided in ConstructorCallOptions: expected a 32-byte value as a hex string or a Uint8Array');
|
|
25
|
+
if ((0, utils_1.isPvm)(this.code)) {
|
|
26
|
+
return client.tx.revive.instantiateWithCode(value, gasLimit, storageDepositLimit, this.code, bytes, salt ? (0, utils_1.toHex)(salt) : undefined);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
return client.tx.revive.instantiate(value, gasLimit, storageDepositLimit, (0, utils_1.toHex)(this.code), bytes, salt ? (0, utils_1.toHex)(salt) : undefined);
|
|
30
|
+
}
|
|
24
31
|
}
|
|
25
32
|
else {
|
|
26
|
-
|
|
33
|
+
if ((0, utils_1.isWasm)(this.code)) {
|
|
34
|
+
return client.tx.contracts.instantiateWithCode(value, gasLimit, storageDepositLimit, this.code, bytes, salt || '0x');
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return client.tx.contracts.instantiate(value, gasLimit, storageDepositLimit, (0, utils_1.toHex)(this.code), bytes, salt || '0x');
|
|
38
|
+
}
|
|
27
39
|
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
})();
|
|
41
|
+
let deployerAddress, deployerNonce;
|
|
42
|
+
const calculateContractAddress = async (result) => {
|
|
43
|
+
(0, utils_1.assert)(deployerAddress, 'Deployer Address Not Found');
|
|
44
|
+
const { status, events, dispatchError } = result;
|
|
45
|
+
const onChain = status.type === 'BestChainBlockIncluded' || status.type === 'Finalized';
|
|
46
|
+
(0, utils_1.assert)(onChain, 'The deployment transaction has not yet been included in the best chain block or finalized.');
|
|
47
|
+
(0, utils_1.assert)(!dispatchError, 'The deployment transaction failed to execute. Refer to the dispatch error for more information.');
|
|
48
|
+
if (this.registry.isRevive()) {
|
|
49
|
+
if (salt) {
|
|
50
|
+
let code;
|
|
51
|
+
if ((0, utils_1.isPvm)(this.code)) {
|
|
52
|
+
code = this.code;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// pull the raw code in case we're using a code hash here
|
|
56
|
+
code = await client.query.revive.pristineCode((0, utils_1.toHex)(this.code));
|
|
57
|
+
}
|
|
58
|
+
(0, utils_1.assert)(code, 'Contract Code Binary Not Found');
|
|
59
|
+
return (0, index_js_1.CREATE2)((0, index_js_1.toEvmAddress)(deployerAddress), // --
|
|
60
|
+
code, bytes, salt);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return (0, index_js_1.CREATE1)((0, index_js_1.toEvmAddress)(deployerAddress), // --
|
|
64
|
+
deployerNonce);
|
|
65
|
+
}
|
|
32
66
|
}
|
|
33
67
|
else {
|
|
34
|
-
|
|
68
|
+
const event = client.events.contracts.Instantiated.find(events);
|
|
69
|
+
(0, utils_1.assert)(event, 'Contracts.Instantiated event not found');
|
|
70
|
+
return event.palletEvent.data.contract.address();
|
|
35
71
|
}
|
|
36
|
-
}
|
|
72
|
+
};
|
|
73
|
+
tx.withHooks({
|
|
74
|
+
beforeSign: async (tx, signerAddress) => {
|
|
75
|
+
deployerAddress = signerAddress;
|
|
76
|
+
if (this.registry.isRevive() && !salt) {
|
|
77
|
+
deployerNonce = await client.call.accountNonceApi.accountNonce(deployerAddress);
|
|
78
|
+
}
|
|
79
|
+
const callParams = { ...tx.call.palletCall.params };
|
|
80
|
+
const needsDryRun = !callParams.gasLimit || (this.registry.isRevive() && !callParams.storageDepositLimit);
|
|
81
|
+
if (!needsDryRun)
|
|
82
|
+
return;
|
|
83
|
+
const executor = new ConstructorQueryExecutor_js_1.ConstructorQueryExecutor(this.client, // --
|
|
84
|
+
this.registry, this.code, {
|
|
85
|
+
defaultCaller: signerAddress,
|
|
86
|
+
...this.options,
|
|
87
|
+
});
|
|
88
|
+
const { raw } = await executor.doExecute(constructor)(...params);
|
|
89
|
+
const { gasRequired, storageDeposit } = raw;
|
|
90
|
+
if (!callParams.gasLimit) {
|
|
91
|
+
callParams.gasLimit = gasRequired;
|
|
92
|
+
}
|
|
93
|
+
if (this.registry.isRevive() && !callParams.storageDepositLimit) {
|
|
94
|
+
callParams.storageDepositLimit = storageDeposit.value;
|
|
95
|
+
}
|
|
96
|
+
const newCall = { ...tx.call };
|
|
97
|
+
newCall.palletCall.params = callParams;
|
|
98
|
+
tx.call = newCall;
|
|
99
|
+
},
|
|
100
|
+
transformResult: (result) => {
|
|
101
|
+
let cachedAddress;
|
|
102
|
+
const contractAddress = async () => {
|
|
103
|
+
if (cachedAddress)
|
|
104
|
+
return cachedAddress;
|
|
105
|
+
cachedAddress = await calculateContractAddress(result);
|
|
106
|
+
return cachedAddress;
|
|
107
|
+
};
|
|
108
|
+
const contract = async (overrideOptions) => {
|
|
109
|
+
const address = await contractAddress();
|
|
110
|
+
// Check if the contract is existed on chain or not!
|
|
111
|
+
await (0, index_js_1.ensureContractPresence)(client, this.registry, address);
|
|
112
|
+
return new Contract_js_1.Contract(client, // --
|
|
113
|
+
this.metadata, address, {
|
|
114
|
+
defaultCaller: deployerAddress,
|
|
115
|
+
...this.options,
|
|
116
|
+
...overrideOptions,
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
Object.assign(result, {
|
|
120
|
+
contractAddress,
|
|
121
|
+
contract,
|
|
122
|
+
});
|
|
123
|
+
return result;
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
return tx;
|
|
37
127
|
};
|
|
38
128
|
callFn.meta = meta;
|
|
39
129
|
return callFn;
|
|
@@ -11,8 +11,7 @@ class QueryExecutor extends index_js_2.ContractExecutor {
|
|
|
11
11
|
(0, utils_1.assert)(meta, `Query message not found: ${message}`);
|
|
12
12
|
const callFn = async (...params) => {
|
|
13
13
|
const { args } = meta;
|
|
14
|
-
(0,
|
|
15
|
-
(0, utils_1.assertFalse)(params.length > args.length + 1, `Expected at most ${args.length + 1} arguments, got ${params.length}`);
|
|
14
|
+
(0, index_js_1.ensureParamsLength)(args.length, params.length);
|
|
16
15
|
const callOptions = (params[args.length] || {});
|
|
17
16
|
const { caller = this.options.defaultCaller, value = 0n, gasLimit, storageDepositLimit } = callOptions;
|
|
18
17
|
(0, utils_1.assert)(caller, 'Expected a valid caller address in ContractCallOptions');
|
|
@@ -44,7 +43,9 @@ class QueryExecutor extends index_js_2.ContractExecutor {
|
|
|
44
43
|
}
|
|
45
44
|
})();
|
|
46
45
|
if (raw.result.isErr) {
|
|
47
|
-
|
|
46
|
+
const dispatchError = raw.result.err;
|
|
47
|
+
const moduleError = client.registry.findErrorMeta(dispatchError);
|
|
48
|
+
throw new errors_js_1.ContractDispatchError(dispatchError, raw, moduleError);
|
|
48
49
|
}
|
|
49
50
|
const data = this.tryDecode(meta, raw.result.value.data);
|
|
50
51
|
if (data.isErr) {
|
|
@@ -2,29 +2,56 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TxExecutor = void 0;
|
|
4
4
|
const utils_1 = require("@dedot/utils");
|
|
5
|
-
const index_js_1 = require("
|
|
6
|
-
|
|
5
|
+
const index_js_1 = require("../utils/index.js");
|
|
6
|
+
const QueryExecutor_js_1 = require("./QueryExecutor.js");
|
|
7
|
+
const index_js_2 = require("./abstract/index.js");
|
|
8
|
+
class TxExecutor extends index_js_2.ContractExecutor {
|
|
7
9
|
doExecute(message) {
|
|
8
10
|
const meta = this.findTxMessage(message);
|
|
9
11
|
(0, utils_1.assert)(meta, `Tx message not found: ${message}`);
|
|
10
12
|
const callFn = (...params) => {
|
|
11
13
|
const { args } = meta;
|
|
12
|
-
(0,
|
|
13
|
-
const txCallOptions = params[args.length];
|
|
14
|
+
(0, index_js_1.ensureParamsLength)(args.length, params.length);
|
|
15
|
+
const txCallOptions = (params[args.length] || {});
|
|
14
16
|
const { value = 0n, gasLimit, storageDepositLimit } = txCallOptions;
|
|
15
|
-
(0, utils_1.assert)(gasLimit, 'Expected a gas limit in ContractTxOptions');
|
|
16
17
|
const formattedInputs = args.map((arg, index) => this.tryEncode(arg, params[index]));
|
|
17
18
|
const bytes = (0, utils_1.u8aToHex)((0, utils_1.concatU8a)((0, utils_1.hexToU8a)(meta.selector), ...formattedInputs));
|
|
18
19
|
const client = this.client;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
const tx = (() => {
|
|
21
|
+
if (this.registry.isRevive()) {
|
|
22
|
+
return client.tx.revive.call(this.address, // --
|
|
23
|
+
value, gasLimit, storageDepositLimit || 0n, bytes);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return client.tx.contracts.call(this.address, // --
|
|
27
|
+
value, gasLimit, storageDepositLimit, bytes);
|
|
28
|
+
}
|
|
29
|
+
})();
|
|
30
|
+
tx.withHooks({
|
|
31
|
+
beforeSign: async (tx, signerAddress) => {
|
|
32
|
+
const callParams = { ...tx.call.palletCall.params };
|
|
33
|
+
const needsDryRun = !callParams.gasLimit || (this.registry.isRevive() && !callParams.storageDepositLimit);
|
|
34
|
+
if (!needsDryRun)
|
|
35
|
+
return;
|
|
36
|
+
const executor = new QueryExecutor_js_1.QueryExecutor(this.client, // --
|
|
37
|
+
this.registry, this.address, {
|
|
38
|
+
defaultCaller: signerAddress,
|
|
39
|
+
...this.options,
|
|
40
|
+
});
|
|
41
|
+
const { raw } = await executor.doExecute(message)(...params);
|
|
42
|
+
const { gasRequired, storageDeposit } = raw;
|
|
43
|
+
if (!callParams.gasLimit) {
|
|
44
|
+
callParams.gasLimit = gasRequired;
|
|
45
|
+
}
|
|
46
|
+
if (this.registry.isRevive() && !callParams.storageDepositLimit) {
|
|
47
|
+
callParams.storageDepositLimit = storageDeposit.value;
|
|
48
|
+
}
|
|
49
|
+
const newCall = { ...tx.call };
|
|
50
|
+
newCall.palletCall.params = callParams;
|
|
51
|
+
tx.call = newCall;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
return tx;
|
|
28
55
|
};
|
|
29
56
|
callFn.meta = meta;
|
|
30
57
|
return callFn;
|
package/cjs/utils/ensure.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ensureSupportedContractMetadataVersion = exports.ensureValidCodeHashOrCode = exports.ensureValidContractAddress = exports.ensureContractPresence = exports.ensurePalletPresence = exports.ensureStorageApiSupports = void 0;
|
|
3
|
+
exports.ensureParamsLength = exports.ensureSupportedContractMetadataVersion = exports.ensureValidCodeHashOrCode = exports.ensureValidContractAddress = exports.ensureContractPresence = exports.ensurePalletPresence = exports.ensureStorageApiSupports = void 0;
|
|
4
4
|
const codecs_1 = require("@dedot/codecs");
|
|
5
5
|
const utils_1 = require("@dedot/utils");
|
|
6
6
|
const ensureStorageApiSupports = (version) => {
|
|
@@ -66,3 +66,9 @@ function ensureSupportedContractMetadataVersion(metadata) {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
exports.ensureSupportedContractMetadataVersion = ensureSupportedContractMetadataVersion;
|
|
69
|
+
function ensureParamsLength(expectedArgsLength, actualParamsLength) {
|
|
70
|
+
(0, utils_1.assertFalse)(actualParamsLength < expectedArgsLength, `Expected at least ${expectedArgsLength} arguments, got ${actualParamsLength}`);
|
|
71
|
+
// One extra param for the options
|
|
72
|
+
(0, utils_1.assertFalse)(actualParamsLength > expectedArgsLength + 1, `Expected at most ${expectedArgsLength + 1} arguments, got ${actualParamsLength}`);
|
|
73
|
+
}
|
|
74
|
+
exports.ensureParamsLength = ensureParamsLength;
|
package/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DispatchError } from '@dedot/codecs';
|
|
1
|
+
import { DispatchError, PalletErrorMetadataLatest } from '@dedot/codecs';
|
|
2
2
|
import { DedotError } from '@dedot/utils';
|
|
3
3
|
import { ContractCallResult, ContractInstantiateResult, GenericContractApi, ReturnFlags } from './types/index.js';
|
|
4
4
|
/**
|
|
@@ -36,13 +36,18 @@ export declare class ContractInstantiateDispatchError<ContractApi extends Generi
|
|
|
36
36
|
* The error that occurred during the dispatch phase.
|
|
37
37
|
*/
|
|
38
38
|
dispatchError: DispatchError;
|
|
39
|
+
/**
|
|
40
|
+
* The decoded module error, if any.
|
|
41
|
+
*/
|
|
42
|
+
moduleError?: PalletErrorMetadataLatest;
|
|
39
43
|
/**
|
|
40
44
|
* Constructs a new `ContractInstantiateDispatchError` instance.
|
|
41
45
|
*
|
|
42
46
|
* @param err - The `DispatchError` that occurred during the dispatch phase.
|
|
43
47
|
* @param raw - The raw result of the contract instantiation.
|
|
48
|
+
* @param moduleError - The decoded module error, if any.
|
|
44
49
|
*/
|
|
45
|
-
constructor(err: DispatchError, raw: ContractInstantiateResult<ContractApi['types']['ChainApi']
|
|
50
|
+
constructor(err: DispatchError, raw: ContractInstantiateResult<ContractApi['types']['ChainApi']>, moduleError?: PalletErrorMetadataLatest);
|
|
46
51
|
}
|
|
47
52
|
/**
|
|
48
53
|
* Represents an error that occurred during the instantiation of a smart contract due to a language-specific error.
|
|
@@ -107,13 +112,18 @@ export declare class ContractDispatchError<ContractApi extends GenericContractAp
|
|
|
107
112
|
* The error that occurred during the dispatch phase.
|
|
108
113
|
*/
|
|
109
114
|
dispatchError: DispatchError;
|
|
115
|
+
/**
|
|
116
|
+
* The decoded module error, if any.
|
|
117
|
+
*/
|
|
118
|
+
moduleError?: PalletErrorMetadataLatest;
|
|
110
119
|
/**
|
|
111
120
|
* Constructs a new `ContractDispatchError` instance.
|
|
112
121
|
*
|
|
113
122
|
* @param err - The `DispatchError` that occurred during the dispatch phase.
|
|
114
123
|
* @param raw - The raw result of the contract call.
|
|
124
|
+
* @param moduleError - The decoded module error, if any.
|
|
115
125
|
*/
|
|
116
|
-
constructor(err: DispatchError, raw: ContractCallResult<ContractApi['types']['ChainApi']
|
|
126
|
+
constructor(err: DispatchError, raw: ContractCallResult<ContractApi['types']['ChainApi']>, moduleError?: PalletErrorMetadataLatest);
|
|
117
127
|
}
|
|
118
128
|
/**
|
|
119
129
|
* Represents an error that occurred during the execution of a smart contract call due to a language-specific error.
|
package/errors.js
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { assert, DedotError } from '@dedot/utils';
|
|
2
2
|
import { toReturnFlags } from './utils/index.js';
|
|
3
|
+
const formatDispatchError = (err, moduleError) => {
|
|
4
|
+
if (moduleError) {
|
|
5
|
+
const { pallet, name, docs } = moduleError;
|
|
6
|
+
let message = `Dispatch error: ${pallet}::${name}`;
|
|
7
|
+
if (docs) {
|
|
8
|
+
message += ` - ${docs.join('\n ')}`;
|
|
9
|
+
}
|
|
10
|
+
return message;
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
return `Dispatch error: ${JSON.stringify(err)}`;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
3
16
|
/**
|
|
4
17
|
* Represents an error that occurred during the instantiation of a smart contract.
|
|
5
18
|
* This class extends the base `DedotError` and includes a `raw` property of type `ContractInstantiateResult`.
|
|
@@ -38,16 +51,22 @@ export class ContractInstantiateDispatchError extends ContractInstantiateError {
|
|
|
38
51
|
* The error that occurred during the dispatch phase.
|
|
39
52
|
*/
|
|
40
53
|
dispatchError;
|
|
54
|
+
/**
|
|
55
|
+
* The decoded module error, if any.
|
|
56
|
+
*/
|
|
57
|
+
moduleError;
|
|
41
58
|
/**
|
|
42
59
|
* Constructs a new `ContractInstantiateDispatchError` instance.
|
|
43
60
|
*
|
|
44
61
|
* @param err - The `DispatchError` that occurred during the dispatch phase.
|
|
45
62
|
* @param raw - The raw result of the contract instantiation.
|
|
63
|
+
* @param moduleError - The decoded module error, if any.
|
|
46
64
|
*/
|
|
47
|
-
constructor(err, raw) {
|
|
65
|
+
constructor(err, raw, moduleError) {
|
|
48
66
|
super(raw);
|
|
49
67
|
this.dispatchError = err;
|
|
50
|
-
this.
|
|
68
|
+
this.moduleError = moduleError;
|
|
69
|
+
this.message = formatDispatchError(err, moduleError);
|
|
51
70
|
}
|
|
52
71
|
}
|
|
53
72
|
/**
|
|
@@ -81,7 +100,7 @@ export class ContractInstantiateLangError extends ContractInstantiateError {
|
|
|
81
100
|
super(raw);
|
|
82
101
|
this.langError = err;
|
|
83
102
|
this.flags = toReturnFlags(raw.result.value.result.flags.bits);
|
|
84
|
-
this.message = `
|
|
103
|
+
this.message = `Lang error: ${JSON.stringify(err)}`;
|
|
85
104
|
}
|
|
86
105
|
}
|
|
87
106
|
/**
|
|
@@ -122,16 +141,22 @@ export class ContractDispatchError extends ContractExecutionError {
|
|
|
122
141
|
* The error that occurred during the dispatch phase.
|
|
123
142
|
*/
|
|
124
143
|
dispatchError;
|
|
144
|
+
/**
|
|
145
|
+
* The decoded module error, if any.
|
|
146
|
+
*/
|
|
147
|
+
moduleError;
|
|
125
148
|
/**
|
|
126
149
|
* Constructs a new `ContractDispatchError` instance.
|
|
127
150
|
*
|
|
128
151
|
* @param err - The `DispatchError` that occurred during the dispatch phase.
|
|
129
152
|
* @param raw - The raw result of the contract call.
|
|
153
|
+
* @param moduleError - The decoded module error, if any.
|
|
130
154
|
*/
|
|
131
|
-
constructor(err, raw) {
|
|
155
|
+
constructor(err, raw, moduleError) {
|
|
132
156
|
super(raw);
|
|
133
157
|
this.dispatchError = err;
|
|
134
|
-
this.
|
|
158
|
+
this.moduleError = moduleError;
|
|
159
|
+
this.message = formatDispatchError(err, moduleError);
|
|
135
160
|
}
|
|
136
161
|
}
|
|
137
162
|
/**
|
|
@@ -165,7 +190,7 @@ export class ContractLangError extends ContractExecutionError {
|
|
|
165
190
|
super(raw);
|
|
166
191
|
this.langError = err;
|
|
167
192
|
this.flags = toReturnFlags(raw.result.value.flags.bits);
|
|
168
|
-
this.message = `
|
|
193
|
+
this.message = `Lang error: ${JSON.stringify(err)}`;
|
|
169
194
|
}
|
|
170
195
|
}
|
|
171
196
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { assert,
|
|
1
|
+
import { assert, concatU8a, hexToU8a, isPvm, isUndefined, isWasm, toHex, toU8a, u8aToHex } from '@dedot/utils';
|
|
2
2
|
import { ContractInstantiateDispatchError, ContractInstantiateLangError } from '../errors.js';
|
|
3
|
-
import { toReturnFlags } from '../utils/index.js';
|
|
3
|
+
import { ensureParamsLength, toReturnFlags } from '../utils/index.js';
|
|
4
4
|
import { DeployerExecutor } from './abstract/index.js';
|
|
5
5
|
export class ConstructorQueryExecutor extends DeployerExecutor {
|
|
6
6
|
doExecute(constructor) {
|
|
@@ -8,8 +8,7 @@ export class ConstructorQueryExecutor extends DeployerExecutor {
|
|
|
8
8
|
assert(meta, `Constructor message not found: ${constructor}`);
|
|
9
9
|
const callFn = async (...params) => {
|
|
10
10
|
const { args } = meta;
|
|
11
|
-
|
|
12
|
-
assertFalse(params.length > args.length + 1, `Expected at most ${args.length + 1} arguments, got ${params.length}`);
|
|
11
|
+
ensureParamsLength(args.length, params.length);
|
|
13
12
|
const callOptions = (params[args.length] || {});
|
|
14
13
|
const { caller = this.options.defaultCaller, // --
|
|
15
14
|
value = 0n, gasLimit, storageDepositLimit, salt, } = callOptions;
|
|
@@ -61,7 +60,9 @@ export class ConstructorQueryExecutor extends DeployerExecutor {
|
|
|
61
60
|
}
|
|
62
61
|
})();
|
|
63
62
|
if (raw.result.isErr) {
|
|
64
|
-
|
|
63
|
+
const dispatchError = raw.result.err;
|
|
64
|
+
const moduleError = client.registry.findErrorMeta(dispatchError);
|
|
65
|
+
throw new ContractInstantiateDispatchError(dispatchError, raw, moduleError);
|
|
65
66
|
}
|
|
66
67
|
const data = this.tryDecode(meta, raw.result.value.result.data);
|
|
67
68
|
if (data.isErr) {
|
|
@@ -1,36 +1,126 @@
|
|
|
1
1
|
import { assert, concatU8a, hexToU8a, isPvm, isUndefined, isWasm, toHex, toU8a, u8aToHex } from '@dedot/utils';
|
|
2
|
+
import { Contract } from '../Contract.js';
|
|
3
|
+
import { CREATE1, CREATE2, ensureContractPresence, ensureParamsLength, toEvmAddress } from '../utils/index.js';
|
|
4
|
+
import { ConstructorQueryExecutor } from './ConstructorQueryExecutor.js';
|
|
2
5
|
import { DeployerExecutor } from './abstract/index.js';
|
|
3
6
|
export class ConstructorTxExecutor extends DeployerExecutor {
|
|
4
7
|
doExecute(constructor) {
|
|
5
8
|
const meta = this.findConstructorMeta(constructor);
|
|
6
9
|
assert(meta, `Constructor message not found: ${constructor}`);
|
|
10
|
+
// @ts-ignore
|
|
7
11
|
const callFn = (...params) => {
|
|
8
12
|
const { args } = meta;
|
|
9
|
-
|
|
10
|
-
const txCallOptions = params[args.length];
|
|
13
|
+
ensureParamsLength(args.length, params.length);
|
|
14
|
+
const txCallOptions = (params[args.length] || {});
|
|
11
15
|
const { value = 0n, gasLimit, storageDepositLimit, salt } = txCallOptions;
|
|
12
|
-
assert(gasLimit, 'Expected a gas limit in ConstructorTxOptions');
|
|
13
16
|
const formattedInputs = args.map((arg, index) => this.tryEncode(arg, params[index]));
|
|
14
17
|
const bytes = u8aToHex(concatU8a(hexToU8a(meta.selector), ...formattedInputs));
|
|
15
18
|
const client = this.client;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
const tx = (() => {
|
|
20
|
+
if (this.registry.isRevive()) {
|
|
21
|
+
assert(isUndefined(salt) || toU8a(salt).byteLength == 32, 'Invalid salt provided in ConstructorCallOptions: expected a 32-byte value as a hex string or a Uint8Array');
|
|
22
|
+
if (isPvm(this.code)) {
|
|
23
|
+
return client.tx.revive.instantiateWithCode(value, gasLimit, storageDepositLimit, this.code, bytes, salt ? toHex(salt) : undefined);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return client.tx.revive.instantiate(value, gasLimit, storageDepositLimit, toHex(this.code), bytes, salt ? toHex(salt) : undefined);
|
|
27
|
+
}
|
|
21
28
|
}
|
|
22
29
|
else {
|
|
23
|
-
|
|
30
|
+
if (isWasm(this.code)) {
|
|
31
|
+
return client.tx.contracts.instantiateWithCode(value, gasLimit, storageDepositLimit, this.code, bytes, salt || '0x');
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return client.tx.contracts.instantiate(value, gasLimit, storageDepositLimit, toHex(this.code), bytes, salt || '0x');
|
|
35
|
+
}
|
|
24
36
|
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
})();
|
|
38
|
+
let deployerAddress, deployerNonce;
|
|
39
|
+
const calculateContractAddress = async (result) => {
|
|
40
|
+
assert(deployerAddress, 'Deployer Address Not Found');
|
|
41
|
+
const { status, events, dispatchError } = result;
|
|
42
|
+
const onChain = status.type === 'BestChainBlockIncluded' || status.type === 'Finalized';
|
|
43
|
+
assert(onChain, 'The deployment transaction has not yet been included in the best chain block or finalized.');
|
|
44
|
+
assert(!dispatchError, 'The deployment transaction failed to execute. Refer to the dispatch error for more information.');
|
|
45
|
+
if (this.registry.isRevive()) {
|
|
46
|
+
if (salt) {
|
|
47
|
+
let code;
|
|
48
|
+
if (isPvm(this.code)) {
|
|
49
|
+
code = this.code;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// pull the raw code in case we're using a code hash here
|
|
53
|
+
code = await client.query.revive.pristineCode(toHex(this.code));
|
|
54
|
+
}
|
|
55
|
+
assert(code, 'Contract Code Binary Not Found');
|
|
56
|
+
return CREATE2(toEvmAddress(deployerAddress), // --
|
|
57
|
+
code, bytes, salt);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return CREATE1(toEvmAddress(deployerAddress), // --
|
|
61
|
+
deployerNonce);
|
|
62
|
+
}
|
|
29
63
|
}
|
|
30
64
|
else {
|
|
31
|
-
|
|
65
|
+
const event = client.events.contracts.Instantiated.find(events);
|
|
66
|
+
assert(event, 'Contracts.Instantiated event not found');
|
|
67
|
+
return event.palletEvent.data.contract.address();
|
|
32
68
|
}
|
|
33
|
-
}
|
|
69
|
+
};
|
|
70
|
+
tx.withHooks({
|
|
71
|
+
beforeSign: async (tx, signerAddress) => {
|
|
72
|
+
deployerAddress = signerAddress;
|
|
73
|
+
if (this.registry.isRevive() && !salt) {
|
|
74
|
+
deployerNonce = await client.call.accountNonceApi.accountNonce(deployerAddress);
|
|
75
|
+
}
|
|
76
|
+
const callParams = { ...tx.call.palletCall.params };
|
|
77
|
+
const needsDryRun = !callParams.gasLimit || (this.registry.isRevive() && !callParams.storageDepositLimit);
|
|
78
|
+
if (!needsDryRun)
|
|
79
|
+
return;
|
|
80
|
+
const executor = new ConstructorQueryExecutor(this.client, // --
|
|
81
|
+
this.registry, this.code, {
|
|
82
|
+
defaultCaller: signerAddress,
|
|
83
|
+
...this.options,
|
|
84
|
+
});
|
|
85
|
+
const { raw } = await executor.doExecute(constructor)(...params);
|
|
86
|
+
const { gasRequired, storageDeposit } = raw;
|
|
87
|
+
if (!callParams.gasLimit) {
|
|
88
|
+
callParams.gasLimit = gasRequired;
|
|
89
|
+
}
|
|
90
|
+
if (this.registry.isRevive() && !callParams.storageDepositLimit) {
|
|
91
|
+
callParams.storageDepositLimit = storageDeposit.value;
|
|
92
|
+
}
|
|
93
|
+
const newCall = { ...tx.call };
|
|
94
|
+
newCall.palletCall.params = callParams;
|
|
95
|
+
tx.call = newCall;
|
|
96
|
+
},
|
|
97
|
+
transformResult: (result) => {
|
|
98
|
+
let cachedAddress;
|
|
99
|
+
const contractAddress = async () => {
|
|
100
|
+
if (cachedAddress)
|
|
101
|
+
return cachedAddress;
|
|
102
|
+
cachedAddress = await calculateContractAddress(result);
|
|
103
|
+
return cachedAddress;
|
|
104
|
+
};
|
|
105
|
+
const contract = async (overrideOptions) => {
|
|
106
|
+
const address = await contractAddress();
|
|
107
|
+
// Check if the contract is existed on chain or not!
|
|
108
|
+
await ensureContractPresence(client, this.registry, address);
|
|
109
|
+
return new Contract(client, // --
|
|
110
|
+
this.metadata, address, {
|
|
111
|
+
defaultCaller: deployerAddress,
|
|
112
|
+
...this.options,
|
|
113
|
+
...overrideOptions,
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
Object.assign(result, {
|
|
117
|
+
contractAddress,
|
|
118
|
+
contract,
|
|
119
|
+
});
|
|
120
|
+
return result;
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
return tx;
|
|
34
124
|
};
|
|
35
125
|
callFn.meta = meta;
|
|
36
126
|
return callFn;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { assert,
|
|
1
|
+
import { assert, concatU8a, hexToU8a, u8aToHex } from '@dedot/utils';
|
|
2
2
|
import { ContractDispatchError, ContractLangError } from '../errors.js';
|
|
3
|
-
import { ensureContractPresence, toReturnFlags } from '../utils/index.js';
|
|
3
|
+
import { ensureContractPresence, ensureParamsLength, toReturnFlags } from '../utils/index.js';
|
|
4
4
|
import { ContractExecutor } from './abstract/index.js';
|
|
5
5
|
export class QueryExecutor extends ContractExecutor {
|
|
6
6
|
doExecute(message) {
|
|
@@ -8,8 +8,7 @@ export class QueryExecutor extends ContractExecutor {
|
|
|
8
8
|
assert(meta, `Query message not found: ${message}`);
|
|
9
9
|
const callFn = async (...params) => {
|
|
10
10
|
const { args } = meta;
|
|
11
|
-
|
|
12
|
-
assertFalse(params.length > args.length + 1, `Expected at most ${args.length + 1} arguments, got ${params.length}`);
|
|
11
|
+
ensureParamsLength(args.length, params.length);
|
|
13
12
|
const callOptions = (params[args.length] || {});
|
|
14
13
|
const { caller = this.options.defaultCaller, value = 0n, gasLimit, storageDepositLimit } = callOptions;
|
|
15
14
|
assert(caller, 'Expected a valid caller address in ContractCallOptions');
|
|
@@ -41,7 +40,9 @@ export class QueryExecutor extends ContractExecutor {
|
|
|
41
40
|
}
|
|
42
41
|
})();
|
|
43
42
|
if (raw.result.isErr) {
|
|
44
|
-
|
|
43
|
+
const dispatchError = raw.result.err;
|
|
44
|
+
const moduleError = client.registry.findErrorMeta(dispatchError);
|
|
45
|
+
throw new ContractDispatchError(dispatchError, raw, moduleError);
|
|
45
46
|
}
|
|
46
47
|
const data = this.tryDecode(meta, raw.result.value.data);
|
|
47
48
|
if (data.isErr) {
|
package/executor/TxExecutor.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { assert, concatU8a, hexToU8a,
|
|
1
|
+
import { assert, concatU8a, hexToU8a, u8aToHex } from '@dedot/utils';
|
|
2
|
+
import { ensureParamsLength } from '../utils/index.js';
|
|
3
|
+
import { QueryExecutor } from './QueryExecutor.js';
|
|
2
4
|
import { ContractExecutor } from './abstract/index.js';
|
|
3
5
|
export class TxExecutor extends ContractExecutor {
|
|
4
6
|
doExecute(message) {
|
|
@@ -6,22 +8,47 @@ export class TxExecutor extends ContractExecutor {
|
|
|
6
8
|
assert(meta, `Tx message not found: ${message}`);
|
|
7
9
|
const callFn = (...params) => {
|
|
8
10
|
const { args } = meta;
|
|
9
|
-
|
|
10
|
-
const txCallOptions = params[args.length];
|
|
11
|
+
ensureParamsLength(args.length, params.length);
|
|
12
|
+
const txCallOptions = (params[args.length] || {});
|
|
11
13
|
const { value = 0n, gasLimit, storageDepositLimit } = txCallOptions;
|
|
12
|
-
assert(gasLimit, 'Expected a gas limit in ContractTxOptions');
|
|
13
14
|
const formattedInputs = args.map((arg, index) => this.tryEncode(arg, params[index]));
|
|
14
15
|
const bytes = u8aToHex(concatU8a(hexToU8a(meta.selector), ...formattedInputs));
|
|
15
16
|
const client = this.client;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
const tx = (() => {
|
|
18
|
+
if (this.registry.isRevive()) {
|
|
19
|
+
return client.tx.revive.call(this.address, // --
|
|
20
|
+
value, gasLimit, storageDepositLimit || 0n, bytes);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
return client.tx.contracts.call(this.address, // --
|
|
24
|
+
value, gasLimit, storageDepositLimit, bytes);
|
|
25
|
+
}
|
|
26
|
+
})();
|
|
27
|
+
tx.withHooks({
|
|
28
|
+
beforeSign: async (tx, signerAddress) => {
|
|
29
|
+
const callParams = { ...tx.call.palletCall.params };
|
|
30
|
+
const needsDryRun = !callParams.gasLimit || (this.registry.isRevive() && !callParams.storageDepositLimit);
|
|
31
|
+
if (!needsDryRun)
|
|
32
|
+
return;
|
|
33
|
+
const executor = new QueryExecutor(this.client, // --
|
|
34
|
+
this.registry, this.address, {
|
|
35
|
+
defaultCaller: signerAddress,
|
|
36
|
+
...this.options,
|
|
37
|
+
});
|
|
38
|
+
const { raw } = await executor.doExecute(message)(...params);
|
|
39
|
+
const { gasRequired, storageDeposit } = raw;
|
|
40
|
+
if (!callParams.gasLimit) {
|
|
41
|
+
callParams.gasLimit = gasRequired;
|
|
42
|
+
}
|
|
43
|
+
if (this.registry.isRevive() && !callParams.storageDepositLimit) {
|
|
44
|
+
callParams.storageDepositLimit = storageDeposit.value;
|
|
45
|
+
}
|
|
46
|
+
const newCall = { ...tx.call };
|
|
47
|
+
newCall.palletCall.params = callParams;
|
|
48
|
+
tx.call = newCall;
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
return tx;
|
|
25
52
|
};
|
|
26
53
|
callFn.meta = meta;
|
|
27
54
|
return callFn;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dedot/contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Delightful ink! Contract APIs",
|
|
5
5
|
"author": "Tung Vu <tung@dedot.dev>",
|
|
6
6
|
"homepage": "https://dedot.dev",
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
"test": "npx vitest --watch=false"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@dedot/api": "0.
|
|
22
|
-
"@dedot/codecs": "0.
|
|
23
|
-
"@dedot/types": "0.
|
|
24
|
-
"@dedot/utils": "0.
|
|
21
|
+
"@dedot/api": "0.14.0",
|
|
22
|
+
"@dedot/codecs": "0.14.0",
|
|
23
|
+
"@dedot/types": "0.14.0",
|
|
24
|
+
"@dedot/utils": "0.14.0",
|
|
25
25
|
"@ethereumjs/rlp": "^10.0.0"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"node": ">=18"
|
|
33
33
|
},
|
|
34
34
|
"license": "Apache-2.0",
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "cde1e77566038990fcdd69b291a4231013c16528",
|
|
36
36
|
"module": "./index.js",
|
|
37
37
|
"types": "./index.d.ts",
|
|
38
38
|
"exports": {
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SubstrateApi } from '@dedot/api/chaintypes';
|
|
2
2
|
import { AccountId32Like, type Bytes, BytesLike, type DispatchError, Extrinsic, type H256, type Result, Weight } from '@dedot/codecs';
|
|
3
|
-
import { AnyFunc, AsyncMethod, GenericSubstrateApi, IEventRecord, ISubmittableExtrinsic, RpcVersion, Unsub, VersionedGenericSubstrateApi } from '@dedot/types';
|
|
3
|
+
import { AnyFunc, AsyncMethod, GenericSubstrateApi, IEventRecord, ISubmittableExtrinsic, ISubmittableResult, RpcVersion, Unsub, VersionedGenericSubstrateApi } from '@dedot/types';
|
|
4
|
+
import { Contract } from '../Contract.js';
|
|
4
5
|
import { ContractAddress, ContractCallMessage, ContractConstructorMessage } from './shared.js';
|
|
5
6
|
import { ContractEventV4, ContractMetadataV4 } from './v4.js';
|
|
6
7
|
import { ContractEventV5, ContractMetadataV5 } from './v5.js';
|
|
@@ -69,9 +70,19 @@ export type ContractInstantiateResult<_ extends GenericSubstrateApi> = {
|
|
|
69
70
|
debugMessage?: Bytes;
|
|
70
71
|
result: Result<InstantiateReturnValue, DispatchError>;
|
|
71
72
|
};
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
interface IContractInstantiateSubmittableResult<ContractApi extends GenericContractApi = GenericContractApi> extends ISubmittableResult {
|
|
74
|
+
/**
|
|
75
|
+
* Get deployed contract address
|
|
76
|
+
*/
|
|
77
|
+
contractAddress(): Promise<ContractAddress>;
|
|
78
|
+
/**
|
|
79
|
+
* Get deployed contract instance
|
|
80
|
+
*/
|
|
81
|
+
contract(options?: ExecutionOptions): Promise<Contract<ContractApi>>;
|
|
82
|
+
}
|
|
83
|
+
type SubmittableExtrinsic<R extends ISubmittableResult> = ISubmittableExtrinsic<R> & Extrinsic;
|
|
84
|
+
export type ContractSubmittableExtrinsic<_ extends GenericSubstrateApi> = SubmittableExtrinsic<ISubmittableResult>;
|
|
85
|
+
export type GenericInstantiateSubmittableExtrinsic<_ extends GenericSubstrateApi, ContractApi extends GenericContractApi = GenericContractApi> = SubmittableExtrinsic<IContractInstantiateSubmittableResult<ContractApi>>;
|
|
75
86
|
export type ContractMetadata = ContractMetadataV4 | ContractMetadataV5 | ContractMetadataV6;
|
|
76
87
|
export interface LooseContractMetadata {
|
|
77
88
|
version: number | string;
|
|
@@ -88,14 +99,11 @@ export type ConstructorCallOptions = CallOptions & {
|
|
|
88
99
|
};
|
|
89
100
|
export type ConstructorTxOptions = CallOptions & {
|
|
90
101
|
salt?: BytesLike;
|
|
91
|
-
gasLimit: Weight;
|
|
92
102
|
};
|
|
93
103
|
export type ContractCallOptions = CallOptions & {
|
|
94
104
|
caller?: AccountId32Like;
|
|
95
105
|
};
|
|
96
|
-
export type ContractTxOptions = CallOptions
|
|
97
|
-
gasLimit: Weight;
|
|
98
|
-
};
|
|
106
|
+
export type ContractTxOptions = CallOptions;
|
|
99
107
|
export type GenericContractQueryCall<ChainApi extends GenericSubstrateApi, F extends AsyncMethod = (...args: any[]) => Promise<GenericContractCallResult<any, ContractCallResult<ChainApi>>>> = F & {
|
|
100
108
|
meta: ContractCallMessage;
|
|
101
109
|
};
|
package/types/v6.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContractInformation, ContractSource, ContractType } from './shared';
|
|
1
|
+
import { ContractInformation, ContractSource, ContractType } from './shared.js';
|
|
2
2
|
import { ContractSpecV5, ContractStorageV5 } from './v5.js';
|
|
3
3
|
export interface ContractSourceV6 extends ContractSource {
|
|
4
4
|
contract_binary?: string;
|
package/utils/ensure.d.ts
CHANGED
|
@@ -10,3 +10,4 @@ export declare function ensureContractPresence(client: ISubstrateClient<Substrat
|
|
|
10
10
|
export declare function ensureValidContractAddress(address: ContractAddress, registry: TypinkRegistry): void;
|
|
11
11
|
export declare function ensureValidCodeHashOrCode(codeHashOrCode: Hash | Uint8Array | string, registry: TypinkRegistry): void;
|
|
12
12
|
export declare function ensureSupportedContractMetadataVersion(metadata: LooseContractMetadata): void;
|
|
13
|
+
export declare function ensureParamsLength(expectedArgsLength: number, actualParamsLength: number): void;
|
package/utils/ensure.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { accountId32ToHex } from '@dedot/codecs';
|
|
2
|
-
import { assert, DedotError, ensurePresence, hexToU8a, isEvmAddress, isPvm, isWasm, toU8a, } from '@dedot/utils';
|
|
2
|
+
import { assert, assertFalse, DedotError, ensurePresence, hexToU8a, isEvmAddress, isPvm, isWasm, toU8a, } from '@dedot/utils';
|
|
3
3
|
export const ensureStorageApiSupports = (version) => {
|
|
4
4
|
const numberedVersion = typeof version === 'number' ? version : parseInt(version);
|
|
5
5
|
assert(numberedVersion >= 5, `Contract Storage Api Only Available for metadata version >= 5, current version: ${version}`);
|
|
@@ -57,3 +57,8 @@ export function ensureSupportedContractMetadataVersion(metadata) {
|
|
|
57
57
|
throw new DedotError(`Unsupported metadata version: ${metadata.version}`);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
+
export function ensureParamsLength(expectedArgsLength, actualParamsLength) {
|
|
61
|
+
assertFalse(actualParamsLength < expectedArgsLength, `Expected at least ${expectedArgsLength} arguments, got ${actualParamsLength}`);
|
|
62
|
+
// One extra param for the options
|
|
63
|
+
assertFalse(actualParamsLength > expectedArgsLength + 1, `Expected at most ${expectedArgsLength + 1} arguments, got ${actualParamsLength}`);
|
|
64
|
+
}
|