@parity/product-sdk-contracts 0.5.1 → 0.6.1

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/dist/index.js CHANGED
@@ -1,8 +1,7 @@
1
- import { encodeFunctionData, decodeFunctionResult } from 'viem';
1
+ import { encodeFunctionData, bytesToHex, decodeErrorResult, decodeFunctionResult } from 'viem';
2
2
  import { ensureAccountMapped, submitAndWatch } from '@parity/product-sdk-tx';
3
- import { seedToAccount } from '@parity/product-sdk-keys';
4
3
  import { createLogger } from '@parity/product-sdk-logger';
5
- import { DEV_PHRASE, ss58Address } from '@polkadot-labs/hdkd-helpers';
4
+ import { ss58Address } from '@polkadot-labs/hdkd-helpers';
6
5
  import { ss58ToH160 } from '@parity/product-sdk-address';
7
6
 
8
7
  // src/wrap.ts
@@ -44,6 +43,27 @@ var ContractDryRunFailedError = class extends ContractError {
44
43
  this.dispatchError = dispatchError;
45
44
  }
46
45
  };
46
+ function stringifyArg(arg) {
47
+ if (typeof arg === "bigint") return arg.toString();
48
+ return JSON.stringify(arg, (_, v) => typeof v === "bigint" ? v.toString() : v);
49
+ }
50
+ var ContractRevertedError = class extends ContractError {
51
+ methodName;
52
+ data;
53
+ reason;
54
+ decoded;
55
+ constructor(methodName, data, info) {
56
+ const suffix = info?.reason ?? (info?.decoded ? `${info.decoded.errorName}(${(info.decoded.args ?? []).map(stringifyArg).join(", ")})` : data);
57
+ super(
58
+ `Contract reverted in "${methodName}": ${suffix}. The transaction was not submitted.`
59
+ );
60
+ this.name = "ContractRevertedError";
61
+ this.methodName = methodName;
62
+ this.data = data;
63
+ this.reason = info?.reason;
64
+ this.decoded = info?.decoded;
65
+ }
66
+ };
47
67
 
48
68
  // src/wrap.ts
49
69
  var log = createLogger("contracts");
@@ -65,14 +85,16 @@ function extractOverrides(argNames, args) {
65
85
  }
66
86
  return { positionalArgs: args };
67
87
  }
68
- var QUERY_FALLBACK_ORIGIN = seedToAccount(DEV_PHRASE, "//Alice").ss58Address;
88
+ var REVIVE_PALLET_ACCOUNT = new Uint8Array(32);
89
+ REVIVE_PALLET_ACCOUNT.set(new TextEncoder().encode("modlpy/reviv"));
90
+ var QUERY_FALLBACK_ORIGIN = ss58Address(REVIVE_PALLET_ACCOUNT);
69
91
  function resolveOrigin(defaults, override, forQuery) {
70
92
  if (override) return override;
71
93
  const sourceAddr = defaults.signerManager?.getState().selectedAccount?.address;
72
94
  if (sourceAddr) return sourceAddr;
73
95
  if (defaults.origin) return defaults.origin;
74
96
  if (forQuery) {
75
- log.warn("No origin configured \u2014 using dev fallback (Alice) for query dry-run");
97
+ log.warn("No origin configured \u2014 using pallet-revive account fallback for query dry-run");
76
98
  return QUERY_FALLBACK_ORIGIN;
77
99
  }
78
100
  return void 0;
@@ -95,6 +117,49 @@ function hexToBytes(hex) {
95
117
  }
96
118
  return out;
97
119
  }
120
+ var REVERT_FLAG = 1;
121
+ var PANIC_REASONS = {
122
+ "0x01": "assertion failed",
123
+ "0x11": "arithmetic overflow",
124
+ "0x12": "division by zero",
125
+ "0x21": "invalid enum value",
126
+ "0x22": "improperly encoded storage byte array",
127
+ "0x31": "pop on empty array",
128
+ "0x32": "array index out of bounds",
129
+ "0x41": "memory allocation overflow",
130
+ "0x51": "call to uninitialized internal function"
131
+ };
132
+ function decodeRevert(abi, data) {
133
+ const hex = bytesToHex(data);
134
+ const info = {
135
+ type: "ContractRevertedWithPayload",
136
+ data: hex
137
+ };
138
+ if (data.byteLength === 0) return info;
139
+ try {
140
+ const decoded = decodeErrorResult({
141
+ abi,
142
+ data: hex
143
+ });
144
+ info.decoded = {
145
+ errorName: decoded.errorName,
146
+ args: decoded.args
147
+ };
148
+ if (decoded.errorName === "Error" && typeof decoded.args?.[0] === "string") {
149
+ info.reason = decoded.args[0];
150
+ } else if (decoded.errorName === "Panic" && typeof decoded.args?.[0] === "bigint") {
151
+ const code = `0x${decoded.args[0].toString(16).padStart(2, "0")}`;
152
+ info.reason = PANIC_REASONS[code] ? `Panic: ${PANIC_REASONS[code]}` : `Panic(${code})`;
153
+ }
154
+ return info;
155
+ } catch {
156
+ try {
157
+ info.reason = new TextDecoder("utf-8", { fatal: true }).decode(data);
158
+ } catch {
159
+ }
160
+ return info;
161
+ }
162
+ }
98
163
  function encodeCalldata(abi, methodName, args) {
99
164
  return encodeFunctionData({
100
165
  abi,
@@ -104,14 +169,10 @@ function encodeCalldata(abi, methodName, args) {
104
169
  }
105
170
  function decodeReturn(abi, methodName, returnData) {
106
171
  if (returnData.byteLength === 0) return void 0;
107
- let hex = "0x";
108
- for (let i = 0; i < returnData.byteLength; i++) {
109
- hex += returnData[i].toString(16).padStart(2, "0");
110
- }
111
172
  const decoded = decodeFunctionResult({
112
173
  abi,
113
174
  functionName: methodName,
114
- data: hex
175
+ data: bytesToHex(returnData)
115
176
  });
116
177
  const entry = abi.find((e) => e.type === "function" && e.name === methodName);
117
178
  const outputs = entry?.outputs ?? [];
@@ -134,11 +195,17 @@ async function buildReviveCall(runtime, dest, abi, methodName, positionalArgs, o
134
195
  value,
135
196
  void 0,
136
197
  void 0,
137
- calldata
198
+ calldata,
199
+ overrides?.at !== void 0 ? { at: overrides.at } : void 0
138
200
  );
139
201
  if (!dryRun.result.success) {
140
202
  throw new ContractDryRunFailedError(methodName, dryRun.result.value);
141
203
  }
204
+ if ((dryRun.result.value.flags & REVERT_FLAG) !== 0) {
205
+ const { data, reason, decoded } = decodeRevert(abi, dryRun.result.value.data);
206
+ log.debug("Contract reverted", { methodName, reason, errorName: decoded?.errorName });
207
+ throw new ContractRevertedError(methodName, data, { reason, decoded });
208
+ }
142
209
  weightLimit = weightLimit ?? dryRun.weight_required;
143
210
  if (storageDepositLimit === void 0) {
144
211
  storageDepositLimit = dryRun.storage_deposit.type === "Charge" ? dryRun.storage_deposit.value : 0n;
@@ -175,7 +242,8 @@ function wrapContract(runtime, address, abi, defaults) {
175
242
  value,
176
243
  void 0,
177
244
  void 0,
178
- calldata
245
+ calldata,
246
+ overrides?.at !== void 0 ? { at: overrides.at } : void 0
179
247
  );
180
248
  if (!dryRun.result.success) {
181
249
  return {
@@ -184,6 +252,19 @@ function wrapContract(runtime, address, abi, defaults) {
184
252
  gasRequired: dryRun.weight_required
185
253
  };
186
254
  }
255
+ if ((dryRun.result.value.flags & REVERT_FLAG) !== 0) {
256
+ const info = decodeRevert(abi, dryRun.result.value.data);
257
+ log.debug("Contract reverted", {
258
+ methodName,
259
+ reason: info.reason,
260
+ errorName: info.decoded?.errorName
261
+ });
262
+ return {
263
+ success: false,
264
+ value: info,
265
+ gasRequired: dryRun.weight_required
266
+ };
267
+ }
187
268
  const decoded = decodeReturn(abi, methodName, dryRun.result.value.data);
188
269
  return {
189
270
  success: true,
@@ -237,20 +318,26 @@ function wrapContract(runtime, address, abi, defaults) {
237
318
  }
238
319
  });
239
320
  }
240
- function createContractRuntime(api) {
321
+ function createContractRuntime(api, options) {
322
+ const defaultAt = options?.at ?? "best";
241
323
  return {
242
324
  api,
243
- dryRunCall: (origin, dest, value, gas, deposit, data) => api.apis.ReviveApi.call(origin, dest, value, gas, deposit, data)
325
+ dryRunCall: (origin, dest, value, gas, deposit, data, callOpts) => api.apis.ReviveApi.call(origin, dest, value, gas, deposit, data, {
326
+ at: callOpts?.at ?? defaultAt
327
+ })
244
328
  };
245
329
  }
246
- function createContractRuntimeFromClient(client, descriptor) {
330
+ function createContractRuntimeFromClient(client, descriptor, options) {
331
+ const defaultAt = options?.at ?? "best";
247
332
  const typed = client.getTypedApi(
248
333
  descriptor
249
334
  );
250
335
  const unsafe = client.getUnsafeApi();
251
336
  return {
252
337
  api: typed,
253
- dryRunCall: (origin, dest, value, gas, deposit, data) => unsafe.apis.ReviveApi.call(origin, dest, value, gas, deposit, data)
338
+ dryRunCall: (origin, dest, value, gas, deposit, data, callOpts) => unsafe.apis.ReviveApi.call(origin, dest, value, gas, deposit, data, {
339
+ at: callOpts?.at ?? defaultAt
340
+ })
254
341
  };
255
342
  }
256
343
  async function ensureContractAccountMapped(runtime, address, signer, options) {
@@ -308,7 +395,7 @@ var ContractManager = class _ContractManager {
308
395
  static fromClient(cdmJson, client, descriptor, options) {
309
396
  return new _ContractManager(
310
397
  cdmJson,
311
- createContractRuntimeFromClient(client, descriptor),
398
+ createContractRuntimeFromClient(client, descriptor, options),
312
399
  options
313
400
  );
314
401
  }
@@ -349,13 +436,13 @@ function createContract(runtime, address, abi, options) {
349
436
  }
350
437
  function createContractFromClient(client, descriptor, address, abi, options) {
351
438
  return createContract(
352
- createContractRuntimeFromClient(client, descriptor),
439
+ createContractRuntimeFromClient(client, descriptor, options),
353
440
  address,
354
441
  abi,
355
442
  options
356
443
  );
357
444
  }
358
445
 
359
- export { ContractDryRunFailedError, ContractError, ContractManager, ContractNotFoundError, ContractSignerMissingError, createContract, createContractFromClient, createContractRuntime, createContractRuntimeFromClient, ensureContractAccountMapped };
446
+ export { ContractDryRunFailedError, ContractError, ContractManager, ContractNotFoundError, ContractRevertedError, ContractSignerMissingError, createContract, createContractFromClient, createContractRuntime, createContractRuntimeFromClient, ensureContractAccountMapped };
360
447
  //# sourceMappingURL=index.js.map
361
448
  //# sourceMappingURL=index.js.map