@parity/product-sdk-contracts 0.5.0 → 0.6.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/README.md +25 -0
- package/dist/codegen.d.ts +1 -1
- package/dist/index.d.ts +34 -184
- package/dist/index.js +101 -15
- package/dist/index.js.map +1 -1
- package/dist/pvm.d.ts +1 -1
- package/dist/types-Bh0tqK9s.d.ts +435 -0
- package/package.json +4 -4
- package/dist/types-BdHp-xWt.d.ts +0 -196
package/README.md
CHANGED
|
@@ -113,6 +113,31 @@ Without this, every fresh-account `.tx()` fails the pre-flight dry-run with `Acc
|
|
|
113
113
|
|
|
114
114
|
Every `.tx()` runs a `ReviveApi.call` dry-run first to size `weight_limit` / `storage_deposit_limit` and to fail fast on revert, OOG, or `AccountNotMapped` before any signing happens. Throws `ContractDryRunFailedError` (with the chain's `dispatchError`) when the dry-run reports failure — caller pays no gas on a tx the chain already rejected. Pass both `gasLimit` and `storageDepositLimit` overrides on `TxOptions` to skip the dry-run entirely.
|
|
115
115
|
|
|
116
|
+
## Query block selection
|
|
117
|
+
|
|
118
|
+
`.query()` and the `.tx()` / `.prepare()` sizing dry-runs target best-block by default, matching `submitAndWatch`'s default resolution. This keeps reads consistent with the state a freshly-submitted transaction observes.
|
|
119
|
+
|
|
120
|
+
Override per call via `QueryOptions.at`, `TxOptions.at`, or `PrepareOptions.at` — each accepts `"best"`, `"finalized"`, or a block hash:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
await counter.getCount.query(); // best-block (default)
|
|
124
|
+
await counter.getCount.query({ at: "finalized" }); // canonical, lagged
|
|
125
|
+
await counter.getCount.query({ at: blockHash }); // pin to a historical block
|
|
126
|
+
|
|
127
|
+
await counter.increment.tx({ at: "finalized" }); // size the dry-run against finalized
|
|
128
|
+
await counter.increment.prepare({ at: blockHash }); // pin the batched call's sizing dry-run
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`.tx({ at })` / `.prepare({ at })` is a no-op when both `gasLimit` and `storageDepositLimit` overrides are supplied — the sizing dry-run is skipped entirely in that case.
|
|
132
|
+
|
|
133
|
+
Change the runtime default by passing `{ at }` to the factory:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
const runtime = createContractRuntimeFromClient(client.raw.assetHub, paseo_asset_hub, {
|
|
137
|
+
at: "finalized", // read finalized state by default
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
116
141
|
## Batching with `.prepare()`
|
|
117
142
|
|
|
118
143
|
Use `.prepare()` to build `BatchableCall` handles consumable by `batchSubmitAndWatch` from `@parity/product-sdk-tx`. Combine multiple contract calls — or contract calls mixed with other Asset Hub transactions — into a single atomic `Utility.batch_all` extrinsic.
|
package/dist/codegen.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,187 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { PolkadotClient, HexString } from 'polkadot-api';
|
|
2
|
+
import { C as CdmJson, a as ContractRuntime, b as ContractManagerOptions, c as ContractDefaults, d as ContractRuntimeOptions, e as Contracts, f as Contract, g as ContractDef, A as AbiEntry, h as ContractOptions } from './types-Bh0tqK9s.js';
|
|
3
|
+
export { i as AbiParam, j as CdmJsonContract, k as CdmJsonTarget, l as ContractDryRunAt, P as PrepareOptions, Q as QueryOptions, m as QueryResult, R as ReviveDryRunCall, n as ReviveDryRunCallOptions, o as ReviveDryRunResult, p as ReviveTypedApi, T as TxOptions, q as createContractRuntime, r as createContractRuntimeFromClient, s as ensureContractAccountMapped } from './types-Bh0tqK9s.js';
|
|
3
4
|
export { BatchableCall, TxResult } from '@parity/product-sdk-tx';
|
|
4
|
-
import { C as CdmJson, a as ContractManagerOptions, b as ContractDefaults, c as Contracts, d as Contract, e as ContractDef, A as AbiEntry, f as ContractOptions } from './types-BdHp-xWt.js';
|
|
5
|
-
export { g as AbiParam, h as CdmJsonContract, i as CdmJsonTarget, P as PrepareOptions, Q as QueryOptions, j as QueryResult, T as TxOptions } from './types-BdHp-xWt.js';
|
|
6
5
|
import '@parity/product-sdk-signer';
|
|
7
6
|
|
|
8
|
-
/**
|
|
9
|
-
* Result of a `Revive.call` extrinsic — present on the typed API as
|
|
10
|
-
* `api.tx.Revive.call(args)`. Returned object is a PAPI submittable that
|
|
11
|
-
* `submitAndWatch` consumes natively.
|
|
12
|
-
*
|
|
13
|
-
* `dest` is an H160 hex string and `data` is a raw `Uint8Array`: this matches
|
|
14
|
-
* what `polkadot-api` ≥2.0 codecs accept and produce. The class-based
|
|
15
|
-
* `Binary` / `FixedSizeBinary` wrappers from `@polkadot-api/substrate-bindings`
|
|
16
|
-
* 0.12 are *not* accepted by PAPI 2.x's compatibility check.
|
|
17
|
-
*/
|
|
18
|
-
type ReviveCallTx = (args: {
|
|
19
|
-
dest: HexString;
|
|
20
|
-
value: bigint;
|
|
21
|
-
weight_limit: Weight;
|
|
22
|
-
storage_deposit_limit: bigint;
|
|
23
|
-
data: Uint8Array;
|
|
24
|
-
}) => SubmittableTransaction;
|
|
25
|
-
/**
|
|
26
|
-
* Dry-run result returned by `ReviveApi.call`. Mirrors the shape exposed by
|
|
27
|
-
* descriptors (`paseo-asset-hub`, `polkadot-asset-hub`, `kusama-asset-hub`).
|
|
28
|
-
*
|
|
29
|
-
* `data` is a raw `Uint8Array` because PAPI ≥2.0 dropped the `Binary` class
|
|
30
|
-
* wrapper for `Vec<u8>` codecs.
|
|
31
|
-
*/
|
|
32
|
-
interface ReviveDryRunResult {
|
|
33
|
-
weight_consumed: Weight;
|
|
34
|
-
weight_required: Weight;
|
|
35
|
-
storage_deposit: {
|
|
36
|
-
type: "Refund" | "Charge";
|
|
37
|
-
value: bigint;
|
|
38
|
-
};
|
|
39
|
-
max_storage_deposit: {
|
|
40
|
-
type: "Refund" | "Charge";
|
|
41
|
-
value: bigint;
|
|
42
|
-
};
|
|
43
|
-
gas_consumed: bigint;
|
|
44
|
-
/**
|
|
45
|
-
* `success: true` carries `{ flags, data }`; `success: false` carries the
|
|
46
|
-
* dispatch error as the chain encoded it.
|
|
47
|
-
*/
|
|
48
|
-
result: {
|
|
49
|
-
success: true;
|
|
50
|
-
value: {
|
|
51
|
-
flags: number;
|
|
52
|
-
data: Uint8Array;
|
|
53
|
-
};
|
|
54
|
-
} | {
|
|
55
|
-
success: false;
|
|
56
|
-
value: unknown;
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
/** Structural shape consumed by `ContractManager` / `createContract`. */
|
|
60
|
-
interface ReviveTypedApi {
|
|
61
|
-
tx: {
|
|
62
|
-
Revive: {
|
|
63
|
-
call: ReviveCallTx;
|
|
64
|
-
map_account(): SubmittableTransaction;
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
query: {
|
|
68
|
-
Revive: {
|
|
69
|
-
OriginalAccount: {
|
|
70
|
-
getValue(address: HexString): Promise<SS58String | undefined>;
|
|
71
|
-
};
|
|
72
|
-
};
|
|
73
|
-
};
|
|
74
|
-
apis: {
|
|
75
|
-
ReviveApi: {
|
|
76
|
-
call(origin: SS58String, dest: HexString, value: bigint, gas_limit: Weight | undefined, storage_deposit_limit: bigint | undefined, input_data: Uint8Array): Promise<ReviveDryRunResult>;
|
|
77
|
-
};
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Signature of a `ReviveApi.call` dry-run, used by the wrapped contract layer
|
|
82
|
-
* to estimate weight + storage deposit and surface revert / OOG /
|
|
83
|
-
* `AccountNotMapped` failures before a tx is signed.
|
|
84
|
-
*
|
|
85
|
-
* Identical to `ReviveTypedApi.apis.ReviveApi.call`, but extracted so the
|
|
86
|
-
* runtime can route this single hot call through PAPI's *unsafe* API
|
|
87
|
-
* (skipping compatibility-token checks) on production runtimes whose
|
|
88
|
-
* descriptors lag a chain upgrade — every other surface still uses the
|
|
89
|
-
* compat-checked typed API.
|
|
90
|
-
*/
|
|
91
|
-
type ReviveDryRunCall = (origin: SS58String, dest: HexString, value: bigint, gas_limit: Weight | undefined, storage_deposit_limit: bigint | undefined, input_data: Uint8Array) => Promise<ReviveDryRunResult>;
|
|
92
|
-
/**
|
|
93
|
-
* Runtime handle that drives queries and transactions against a
|
|
94
|
-
* pallet-revive-capable chain.
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
* ```ts
|
|
98
|
-
* import { createChainClient } from "@parity/product-sdk-chain-client";
|
|
99
|
-
* import { paseo_asset_hub } from "@parity/product-sdk-descriptors/paseo-asset-hub";
|
|
100
|
-
* import { createContractRuntimeFromClient } from "@parity/product-sdk-contracts";
|
|
101
|
-
*
|
|
102
|
-
* const client = await createChainClient({
|
|
103
|
-
* chains: { assetHub: paseo_asset_hub },
|
|
104
|
-
* rpcs: { assetHub: ["wss://sys.ibp.network/asset-hub-paseo"] },
|
|
105
|
-
* });
|
|
106
|
-
* const runtime = createContractRuntimeFromClient(client.raw.assetHub, paseo_asset_hub);
|
|
107
|
-
* ```
|
|
108
|
-
*/
|
|
109
|
-
interface ContractRuntime {
|
|
110
|
-
readonly api: ReviveTypedApi;
|
|
111
|
-
/**
|
|
112
|
-
* Dry-run entry point. Production factories route this through the
|
|
113
|
-
* *unsafe* API to avoid compatibility-token failures when the descriptor
|
|
114
|
-
* trails a runtime upgrade. The {@link createContractRuntime} test factory
|
|
115
|
-
* delegates to `api.apis.ReviveApi.call`.
|
|
116
|
-
*/
|
|
117
|
-
readonly dryRunCall: ReviveDryRunCall;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Wrap a typed PAPI API as a `ContractRuntime`. Intended for tests and
|
|
121
|
-
* advanced setups where the caller already holds a typed API. Routes the
|
|
122
|
-
* dry-run through the typed (compatibility-token-checked) `ReviveApi.call`
|
|
123
|
-
* — fine for mocks but susceptible to `Incompatible runtime entry` errors
|
|
124
|
-
* on a live chain whose descriptor lags. Prefer
|
|
125
|
-
* {@link createContractRuntimeFromClient} for production use.
|
|
126
|
-
*/
|
|
127
|
-
declare function createContractRuntime(api: ReviveTypedApi): ContractRuntime;
|
|
128
|
-
/**
|
|
129
|
-
* Build a `ContractRuntime` from a raw `PolkadotClient` plus its descriptor.
|
|
130
|
-
*
|
|
131
|
-
* The typed API powers `tx.Revive.call`, `tx.Revive.map_account`, and
|
|
132
|
-
* `query.Revive.OriginalAccount` (extrinsics + storage are tolerant of
|
|
133
|
-
* descriptor drift). The runtime-API dry-run, which is *not* tolerant of
|
|
134
|
-
* descriptor drift on PAPI's compat-token path, is routed through
|
|
135
|
-
* `client.getUnsafeApi()` — bypassing the compat check while preserving
|
|
136
|
-
* argument and return shapes.
|
|
137
|
-
*
|
|
138
|
-
* Use this on every production code path that calls a contract's `.tx()` or
|
|
139
|
-
* `.query()` against a live chain.
|
|
140
|
-
*
|
|
141
|
-
* @example
|
|
142
|
-
* ```ts
|
|
143
|
-
* import { paseo_asset_hub } from "@parity/product-sdk-descriptors/paseo-asset-hub";
|
|
144
|
-
* import { createContractRuntimeFromClient } from "@parity/product-sdk-contracts";
|
|
145
|
-
*
|
|
146
|
-
* const runtime = createContractRuntimeFromClient(rawClient, paseo_asset_hub);
|
|
147
|
-
* ```
|
|
148
|
-
*/
|
|
149
|
-
declare function createContractRuntimeFromClient<TDescriptor>(client: PolkadotClient, descriptor: TDescriptor): ContractRuntime;
|
|
150
|
-
/**
|
|
151
|
-
* Ensure the SS58 account is mapped to its derived H160 on `pallet-revive`.
|
|
152
|
-
*
|
|
153
|
-
* `pallet-revive` requires every signing account to have a registered
|
|
154
|
-
* `OriginalAccount` mapping before the runtime accepts its `Revive.call`
|
|
155
|
-
* extrinsics. The mapping is one-time and cheap. This helper:
|
|
156
|
-
*
|
|
157
|
-
* 1. Reads `Revive.OriginalAccount` for the H160 derived from `address`.
|
|
158
|
-
* 2. Returns `null` if already mapped (idempotent fast-path).
|
|
159
|
-
* 3. Otherwise submits `Revive.map_account()` and waits for inclusion.
|
|
160
|
-
*
|
|
161
|
-
* Call this once per signing account at app startup — after that, every
|
|
162
|
-
* subsequent `contract.<method>.tx({ signer })` against the same chain will
|
|
163
|
-
* succeed without further mapping work.
|
|
164
|
-
*
|
|
165
|
-
* @param runtime - The contract runtime (typically `createContractRuntime(...)`).
|
|
166
|
-
* @param address - The SS58 address of the account to map.
|
|
167
|
-
* @param signer - A signer matching `address`.
|
|
168
|
-
* @param options - Optional timeout / status callback (forwarded to the underlying tx).
|
|
169
|
-
* @returns The `TxResult` from the mapping extrinsic, or `null` if already mapped.
|
|
170
|
-
*
|
|
171
|
-
* @example
|
|
172
|
-
* ```ts
|
|
173
|
-
* import { createContractRuntime, ensureContractAccountMapped } from "@parity/product-sdk-contracts";
|
|
174
|
-
*
|
|
175
|
-
* const runtime = createContractRuntime(client.getTypedApi(paseo_asset_hub));
|
|
176
|
-
* await ensureContractAccountMapped(runtime, signerManager.getState().selectedAccount!.address, signer);
|
|
177
|
-
* // now safe to call contract.<method>.tx({ signer })
|
|
178
|
-
* ```
|
|
179
|
-
*/
|
|
180
|
-
declare function ensureContractAccountMapped(runtime: ContractRuntime, address: SS58String, signer: PolkadotSigner, options?: {
|
|
181
|
-
timeoutMs?: number;
|
|
182
|
-
onStatus?: (s: string) => void;
|
|
183
|
-
}): Promise<TxResult | null>;
|
|
184
|
-
|
|
185
7
|
/**
|
|
186
8
|
* Manages typed contract interactions backed by a `cdm.json` manifest.
|
|
187
9
|
*
|
|
@@ -231,7 +53,7 @@ declare class ContractManager {
|
|
|
231
53
|
* @param descriptor - The chain descriptor used to derive the typed API.
|
|
232
54
|
* @param options - Optional configuration (signerManager, defaults).
|
|
233
55
|
*/
|
|
234
|
-
static fromClient<TDescriptor>(cdmJson: CdmJson, client: PolkadotClient, descriptor: TDescriptor, options?: ContractManagerOptions): ContractManager;
|
|
56
|
+
static fromClient<TDescriptor>(cdmJson: CdmJson, client: PolkadotClient, descriptor: TDescriptor, options?: ContractManagerOptions & ContractRuntimeOptions): ContractManager;
|
|
235
57
|
private getContractData;
|
|
236
58
|
/**
|
|
237
59
|
* Get a typed contract handle.
|
|
@@ -282,7 +104,7 @@ declare function createContract(runtime: ContractRuntime, address: HexString, ab
|
|
|
282
104
|
* const { value } = await counter.getCount.query();
|
|
283
105
|
* ```
|
|
284
106
|
*/
|
|
285
|
-
declare function createContractFromClient<TDescriptor>(client: PolkadotClient, descriptor: TDescriptor, address: HexString, abi: AbiEntry[], options?: ContractOptions): Contract<ContractDef>;
|
|
107
|
+
declare function createContractFromClient<TDescriptor>(client: PolkadotClient, descriptor: TDescriptor, address: HexString, abi: AbiEntry[], options?: ContractOptions & ContractRuntimeOptions): Contract<ContractDef>;
|
|
286
108
|
|
|
287
109
|
/** Base class for all contract errors. Use `instanceof ContractError` to catch any contract-related error. */
|
|
288
110
|
declare class ContractError extends Error {
|
|
@@ -312,5 +134,33 @@ declare class ContractDryRunFailedError extends ContractError {
|
|
|
312
134
|
readonly dispatchError: unknown;
|
|
313
135
|
constructor(methodName: string, dispatchError: unknown);
|
|
314
136
|
}
|
|
137
|
+
/** viem-decoded standard or ABI-defined contract error. */
|
|
138
|
+
interface DecodedContractRevert {
|
|
139
|
+
errorName: string;
|
|
140
|
+
args: readonly unknown[] | undefined;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Tagged-enum value surfaced on `QueryResult.value` when a contract reverts
|
|
144
|
+
* via the REVERT flag. The discriminant is intentionally distinct from
|
|
145
|
+
* `pallet-revive`'s bare `{ type: "ContractReverted" }` dispatch-error variant,
|
|
146
|
+
* which is the other path that can populate `QueryResult.value` on failure.
|
|
147
|
+
*/
|
|
148
|
+
interface ContractRevertInfo {
|
|
149
|
+
type: "ContractRevertedWithPayload";
|
|
150
|
+
data: HexString;
|
|
151
|
+
reason?: string;
|
|
152
|
+
decoded?: DecodedContractRevert;
|
|
153
|
+
}
|
|
154
|
+
/** A contract call returned with the `REVERT` flag set on a dispatched-OK call. */
|
|
155
|
+
declare class ContractRevertedError extends ContractError {
|
|
156
|
+
readonly methodName: string;
|
|
157
|
+
readonly data: HexString;
|
|
158
|
+
readonly reason?: string;
|
|
159
|
+
readonly decoded?: DecodedContractRevert;
|
|
160
|
+
constructor(methodName: string, data: HexString, info?: {
|
|
161
|
+
reason?: string;
|
|
162
|
+
decoded?: DecodedContractRevert;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
315
165
|
|
|
316
|
-
export { AbiEntry, CdmJson, Contract, ContractDef, ContractDefaults, ContractDryRunFailedError, ContractError, ContractManager, ContractManagerOptions, ContractNotFoundError, ContractOptions, type
|
|
166
|
+
export { AbiEntry, CdmJson, Contract, ContractDef, ContractDefaults, ContractDryRunFailedError, ContractError, ContractManager, ContractManagerOptions, ContractNotFoundError, ContractOptions, type ContractRevertInfo, ContractRevertedError, ContractRuntime, ContractRuntimeOptions, ContractSignerMissingError, Contracts, type DecodedContractRevert, createContract, createContractFromClient };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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
3
|
import { seedToAccount } from '@parity/product-sdk-keys';
|
|
4
4
|
import { createLogger } from '@parity/product-sdk-logger';
|
|
@@ -44,6 +44,27 @@ var ContractDryRunFailedError = class extends ContractError {
|
|
|
44
44
|
this.dispatchError = dispatchError;
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
|
+
function stringifyArg(arg) {
|
|
48
|
+
if (typeof arg === "bigint") return arg.toString();
|
|
49
|
+
return JSON.stringify(arg, (_, v) => typeof v === "bigint" ? v.toString() : v);
|
|
50
|
+
}
|
|
51
|
+
var ContractRevertedError = class extends ContractError {
|
|
52
|
+
methodName;
|
|
53
|
+
data;
|
|
54
|
+
reason;
|
|
55
|
+
decoded;
|
|
56
|
+
constructor(methodName, data, info) {
|
|
57
|
+
const suffix = info?.reason ?? (info?.decoded ? `${info.decoded.errorName}(${(info.decoded.args ?? []).map(stringifyArg).join(", ")})` : data);
|
|
58
|
+
super(
|
|
59
|
+
`Contract reverted in "${methodName}": ${suffix}. The transaction was not submitted.`
|
|
60
|
+
);
|
|
61
|
+
this.name = "ContractRevertedError";
|
|
62
|
+
this.methodName = methodName;
|
|
63
|
+
this.data = data;
|
|
64
|
+
this.reason = info?.reason;
|
|
65
|
+
this.decoded = info?.decoded;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
47
68
|
|
|
48
69
|
// src/wrap.ts
|
|
49
70
|
var log = createLogger("contracts");
|
|
@@ -95,6 +116,49 @@ function hexToBytes(hex) {
|
|
|
95
116
|
}
|
|
96
117
|
return out;
|
|
97
118
|
}
|
|
119
|
+
var REVERT_FLAG = 1;
|
|
120
|
+
var PANIC_REASONS = {
|
|
121
|
+
"0x01": "assertion failed",
|
|
122
|
+
"0x11": "arithmetic overflow",
|
|
123
|
+
"0x12": "division by zero",
|
|
124
|
+
"0x21": "invalid enum value",
|
|
125
|
+
"0x22": "improperly encoded storage byte array",
|
|
126
|
+
"0x31": "pop on empty array",
|
|
127
|
+
"0x32": "array index out of bounds",
|
|
128
|
+
"0x41": "memory allocation overflow",
|
|
129
|
+
"0x51": "call to uninitialized internal function"
|
|
130
|
+
};
|
|
131
|
+
function decodeRevert(abi, data) {
|
|
132
|
+
const hex = bytesToHex(data);
|
|
133
|
+
const info = {
|
|
134
|
+
type: "ContractRevertedWithPayload",
|
|
135
|
+
data: hex
|
|
136
|
+
};
|
|
137
|
+
if (data.byteLength === 0) return info;
|
|
138
|
+
try {
|
|
139
|
+
const decoded = decodeErrorResult({
|
|
140
|
+
abi,
|
|
141
|
+
data: hex
|
|
142
|
+
});
|
|
143
|
+
info.decoded = {
|
|
144
|
+
errorName: decoded.errorName,
|
|
145
|
+
args: decoded.args
|
|
146
|
+
};
|
|
147
|
+
if (decoded.errorName === "Error" && typeof decoded.args?.[0] === "string") {
|
|
148
|
+
info.reason = decoded.args[0];
|
|
149
|
+
} else if (decoded.errorName === "Panic" && typeof decoded.args?.[0] === "bigint") {
|
|
150
|
+
const code = `0x${decoded.args[0].toString(16).padStart(2, "0")}`;
|
|
151
|
+
info.reason = PANIC_REASONS[code] ? `Panic: ${PANIC_REASONS[code]}` : `Panic(${code})`;
|
|
152
|
+
}
|
|
153
|
+
return info;
|
|
154
|
+
} catch {
|
|
155
|
+
try {
|
|
156
|
+
info.reason = new TextDecoder("utf-8", { fatal: true }).decode(data);
|
|
157
|
+
} catch {
|
|
158
|
+
}
|
|
159
|
+
return info;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
98
162
|
function encodeCalldata(abi, methodName, args) {
|
|
99
163
|
return encodeFunctionData({
|
|
100
164
|
abi,
|
|
@@ -104,14 +168,10 @@ function encodeCalldata(abi, methodName, args) {
|
|
|
104
168
|
}
|
|
105
169
|
function decodeReturn(abi, methodName, returnData) {
|
|
106
170
|
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
171
|
const decoded = decodeFunctionResult({
|
|
112
172
|
abi,
|
|
113
173
|
functionName: methodName,
|
|
114
|
-
data:
|
|
174
|
+
data: bytesToHex(returnData)
|
|
115
175
|
});
|
|
116
176
|
const entry = abi.find((e) => e.type === "function" && e.name === methodName);
|
|
117
177
|
const outputs = entry?.outputs ?? [];
|
|
@@ -134,11 +194,17 @@ async function buildReviveCall(runtime, dest, abi, methodName, positionalArgs, o
|
|
|
134
194
|
value,
|
|
135
195
|
void 0,
|
|
136
196
|
void 0,
|
|
137
|
-
calldata
|
|
197
|
+
calldata,
|
|
198
|
+
overrides?.at !== void 0 ? { at: overrides.at } : void 0
|
|
138
199
|
);
|
|
139
200
|
if (!dryRun.result.success) {
|
|
140
201
|
throw new ContractDryRunFailedError(methodName, dryRun.result.value);
|
|
141
202
|
}
|
|
203
|
+
if ((dryRun.result.value.flags & REVERT_FLAG) !== 0) {
|
|
204
|
+
const { data, reason, decoded } = decodeRevert(abi, dryRun.result.value.data);
|
|
205
|
+
log.debug("Contract reverted", { methodName, reason, errorName: decoded?.errorName });
|
|
206
|
+
throw new ContractRevertedError(methodName, data, { reason, decoded });
|
|
207
|
+
}
|
|
142
208
|
weightLimit = weightLimit ?? dryRun.weight_required;
|
|
143
209
|
if (storageDepositLimit === void 0) {
|
|
144
210
|
storageDepositLimit = dryRun.storage_deposit.type === "Charge" ? dryRun.storage_deposit.value : 0n;
|
|
@@ -175,7 +241,8 @@ function wrapContract(runtime, address, abi, defaults) {
|
|
|
175
241
|
value,
|
|
176
242
|
void 0,
|
|
177
243
|
void 0,
|
|
178
|
-
calldata
|
|
244
|
+
calldata,
|
|
245
|
+
overrides?.at !== void 0 ? { at: overrides.at } : void 0
|
|
179
246
|
);
|
|
180
247
|
if (!dryRun.result.success) {
|
|
181
248
|
return {
|
|
@@ -184,6 +251,19 @@ function wrapContract(runtime, address, abi, defaults) {
|
|
|
184
251
|
gasRequired: dryRun.weight_required
|
|
185
252
|
};
|
|
186
253
|
}
|
|
254
|
+
if ((dryRun.result.value.flags & REVERT_FLAG) !== 0) {
|
|
255
|
+
const info = decodeRevert(abi, dryRun.result.value.data);
|
|
256
|
+
log.debug("Contract reverted", {
|
|
257
|
+
methodName,
|
|
258
|
+
reason: info.reason,
|
|
259
|
+
errorName: info.decoded?.errorName
|
|
260
|
+
});
|
|
261
|
+
return {
|
|
262
|
+
success: false,
|
|
263
|
+
value: info,
|
|
264
|
+
gasRequired: dryRun.weight_required
|
|
265
|
+
};
|
|
266
|
+
}
|
|
187
267
|
const decoded = decodeReturn(abi, methodName, dryRun.result.value.data);
|
|
188
268
|
return {
|
|
189
269
|
success: true,
|
|
@@ -237,20 +317,26 @@ function wrapContract(runtime, address, abi, defaults) {
|
|
|
237
317
|
}
|
|
238
318
|
});
|
|
239
319
|
}
|
|
240
|
-
function createContractRuntime(api) {
|
|
320
|
+
function createContractRuntime(api, options) {
|
|
321
|
+
const defaultAt = options?.at ?? "best";
|
|
241
322
|
return {
|
|
242
323
|
api,
|
|
243
|
-
dryRunCall: (origin, dest, value, gas, deposit, data) => api.apis.ReviveApi.call(origin, dest, value, gas, deposit, data
|
|
324
|
+
dryRunCall: (origin, dest, value, gas, deposit, data, callOpts) => api.apis.ReviveApi.call(origin, dest, value, gas, deposit, data, {
|
|
325
|
+
at: callOpts?.at ?? defaultAt
|
|
326
|
+
})
|
|
244
327
|
};
|
|
245
328
|
}
|
|
246
|
-
function createContractRuntimeFromClient(client, descriptor) {
|
|
329
|
+
function createContractRuntimeFromClient(client, descriptor, options) {
|
|
330
|
+
const defaultAt = options?.at ?? "best";
|
|
247
331
|
const typed = client.getTypedApi(
|
|
248
332
|
descriptor
|
|
249
333
|
);
|
|
250
334
|
const unsafe = client.getUnsafeApi();
|
|
251
335
|
return {
|
|
252
336
|
api: typed,
|
|
253
|
-
dryRunCall: (origin, dest, value, gas, deposit, data) => unsafe.apis.ReviveApi.call(origin, dest, value, gas, deposit, data
|
|
337
|
+
dryRunCall: (origin, dest, value, gas, deposit, data, callOpts) => unsafe.apis.ReviveApi.call(origin, dest, value, gas, deposit, data, {
|
|
338
|
+
at: callOpts?.at ?? defaultAt
|
|
339
|
+
})
|
|
254
340
|
};
|
|
255
341
|
}
|
|
256
342
|
async function ensureContractAccountMapped(runtime, address, signer, options) {
|
|
@@ -308,7 +394,7 @@ var ContractManager = class _ContractManager {
|
|
|
308
394
|
static fromClient(cdmJson, client, descriptor, options) {
|
|
309
395
|
return new _ContractManager(
|
|
310
396
|
cdmJson,
|
|
311
|
-
createContractRuntimeFromClient(client, descriptor),
|
|
397
|
+
createContractRuntimeFromClient(client, descriptor, options),
|
|
312
398
|
options
|
|
313
399
|
);
|
|
314
400
|
}
|
|
@@ -349,13 +435,13 @@ function createContract(runtime, address, abi, options) {
|
|
|
349
435
|
}
|
|
350
436
|
function createContractFromClient(client, descriptor, address, abi, options) {
|
|
351
437
|
return createContract(
|
|
352
|
-
createContractRuntimeFromClient(client, descriptor),
|
|
438
|
+
createContractRuntimeFromClient(client, descriptor, options),
|
|
353
439
|
address,
|
|
354
440
|
abi,
|
|
355
441
|
options
|
|
356
442
|
);
|
|
357
443
|
}
|
|
358
444
|
|
|
359
|
-
export { ContractDryRunFailedError, ContractError, ContractManager, ContractNotFoundError, ContractSignerMissingError, createContract, createContractFromClient, createContractRuntime, createContractRuntimeFromClient, ensureContractAccountMapped };
|
|
445
|
+
export { ContractDryRunFailedError, ContractError, ContractManager, ContractNotFoundError, ContractRevertedError, ContractSignerMissingError, createContract, createContractFromClient, createContractRuntime, createContractRuntimeFromClient, ensureContractAccountMapped };
|
|
360
446
|
//# sourceMappingURL=index.js.map
|
|
361
447
|
//# sourceMappingURL=index.js.map
|