@polkadot-apps/tx 0.2.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/dist/dev-signers.d.ts +34 -0
- package/dist/dev-signers.d.ts.map +1 -0
- package/dist/dev-signers.js +85 -0
- package/dist/dev-signers.js.map +1 -0
- package/dist/dry-run.d.ts +73 -0
- package/dist/dry-run.d.ts.map +1 -0
- package/dist/dry-run.js +242 -0
- package/dist/dry-run.js.map +1 -0
- package/dist/errors.d.ts +109 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +408 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/retry.d.ts +30 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +157 -0
- package/dist/retry.js.map +1 -0
- package/dist/submit.d.ts +19 -0
- package/dist/submit.d.ts.map +1 -0
- package/dist/submit.js +413 -0
- package/dist/submit.js.map +1 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +32 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { PolkadotSigner } from "polkadot-api";
|
|
2
|
+
import type { DevAccountName } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a PolkadotSigner for a standard Substrate dev account.
|
|
5
|
+
*
|
|
6
|
+
* Dev accounts use the well-known Substrate dev mnemonic (`DEV_PHRASE`) with
|
|
7
|
+
* Sr25519 key derivation at the path `//{Name}`. These accounts have known
|
|
8
|
+
* private keys and are pre-funded on dev/test chains.
|
|
9
|
+
*
|
|
10
|
+
* Only for local development, scripts, and testing. Never use in production.
|
|
11
|
+
*
|
|
12
|
+
* @param name - Dev account name ("Alice", "Bob", "Charlie", "Dave", "Eve", or "Ferdie").
|
|
13
|
+
* @returns A PolkadotSigner that can sign transactions.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { createDevSigner } from "@polkadot-apps/tx";
|
|
18
|
+
*
|
|
19
|
+
* const alice = createDevSigner("Alice");
|
|
20
|
+
* const result = await submitAndWatch(tx, alice);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function createDevSigner(name: DevAccountName): PolkadotSigner;
|
|
24
|
+
/**
|
|
25
|
+
* Get the public key bytes for a dev account.
|
|
26
|
+
*
|
|
27
|
+
* Useful for address derivation or identity checks in tests without
|
|
28
|
+
* needing the full signer.
|
|
29
|
+
*
|
|
30
|
+
* @param name - Dev account name.
|
|
31
|
+
* @returns 32-byte Sr25519 public key.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getDevPublicKey(name: DevAccountName): Uint8Array;
|
|
34
|
+
//# sourceMappingURL=dev-signers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-signers.d.ts","sourceRoot":"","sources":["../src/dev-signers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CAEpE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,CAEhE"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { DEV_PHRASE } from "@polkadot-labs/hdkd-helpers";
|
|
2
|
+
import { seedToAccount } from "@polkadot-apps/keys";
|
|
3
|
+
/**
|
|
4
|
+
* Create a PolkadotSigner for a standard Substrate dev account.
|
|
5
|
+
*
|
|
6
|
+
* Dev accounts use the well-known Substrate dev mnemonic (`DEV_PHRASE`) with
|
|
7
|
+
* Sr25519 key derivation at the path `//{Name}`. These accounts have known
|
|
8
|
+
* private keys and are pre-funded on dev/test chains.
|
|
9
|
+
*
|
|
10
|
+
* Only for local development, scripts, and testing. Never use in production.
|
|
11
|
+
*
|
|
12
|
+
* @param name - Dev account name ("Alice", "Bob", "Charlie", "Dave", "Eve", or "Ferdie").
|
|
13
|
+
* @returns A PolkadotSigner that can sign transactions.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { createDevSigner } from "@polkadot-apps/tx";
|
|
18
|
+
*
|
|
19
|
+
* const alice = createDevSigner("Alice");
|
|
20
|
+
* const result = await submitAndWatch(tx, alice);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function createDevSigner(name) {
|
|
24
|
+
return seedToAccount(DEV_PHRASE, `//${name}`).signer;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the public key bytes for a dev account.
|
|
28
|
+
*
|
|
29
|
+
* Useful for address derivation or identity checks in tests without
|
|
30
|
+
* needing the full signer.
|
|
31
|
+
*
|
|
32
|
+
* @param name - Dev account name.
|
|
33
|
+
* @returns 32-byte Sr25519 public key.
|
|
34
|
+
*/
|
|
35
|
+
export function getDevPublicKey(name) {
|
|
36
|
+
return seedToAccount(DEV_PHRASE, `//${name}`).publicKey;
|
|
37
|
+
}
|
|
38
|
+
if (import.meta.vitest) {
|
|
39
|
+
const { describe, test, expect } = import.meta.vitest;
|
|
40
|
+
// Alice's well-known sr25519 public key
|
|
41
|
+
const ALICE_PUBKEY = new Uint8Array([
|
|
42
|
+
0xd4, 0x35, 0x93, 0xc7, 0x15, 0xfd, 0xd3, 0x1c, 0x61, 0x14, 0x1a, 0xbd, 0x04, 0xa9, 0x9f,
|
|
43
|
+
0xd6, 0x82, 0x2c, 0x85, 0x58, 0x85, 0x4c, 0xcd, 0xe3, 0x9a, 0x56, 0x84, 0xe7, 0xa5, 0x6d,
|
|
44
|
+
0xa2, 0x7d,
|
|
45
|
+
]);
|
|
46
|
+
describe("createDevSigner", () => {
|
|
47
|
+
test("creates a signer for Alice with known public key", () => {
|
|
48
|
+
const signer = createDevSigner("Alice");
|
|
49
|
+
expect(signer).toBeDefined();
|
|
50
|
+
expect(signer.publicKey).toEqual(ALICE_PUBKEY);
|
|
51
|
+
});
|
|
52
|
+
test("different names produce different signers", () => {
|
|
53
|
+
const alice = createDevSigner("Alice");
|
|
54
|
+
const bob = createDevSigner("Bob");
|
|
55
|
+
expect(alice.publicKey).not.toEqual(bob.publicKey);
|
|
56
|
+
});
|
|
57
|
+
test("all dev account names produce valid signers", () => {
|
|
58
|
+
const names = ["Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie"];
|
|
59
|
+
const keys = new Set();
|
|
60
|
+
for (const name of names) {
|
|
61
|
+
const signer = createDevSigner(name);
|
|
62
|
+
expect(signer).toBeDefined();
|
|
63
|
+
expect(signer.publicKey).toBeInstanceOf(Uint8Array);
|
|
64
|
+
expect(signer.publicKey.length).toBe(32);
|
|
65
|
+
// All keys should be unique
|
|
66
|
+
const hex = Array.from(signer.publicKey)
|
|
67
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
68
|
+
.join("");
|
|
69
|
+
expect(keys.has(hex)).toBe(false);
|
|
70
|
+
keys.add(hex);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe("getDevPublicKey", () => {
|
|
75
|
+
test("returns Alice's known public key", () => {
|
|
76
|
+
expect(getDevPublicKey("Alice")).toEqual(ALICE_PUBKEY);
|
|
77
|
+
});
|
|
78
|
+
test("matches the signer's public key", () => {
|
|
79
|
+
const signer = createDevSigner("Bob");
|
|
80
|
+
const pubkey = getDevPublicKey("Bob");
|
|
81
|
+
expect(pubkey).toEqual(signer.publicKey);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=dev-signers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-signers.js","sourceRoot":"","sources":["../src/dev-signers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { SubmittableTransaction, Weight } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Validate an Ink SDK dry-run result and extract the submittable transaction.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the 5-10 line boilerplate that every contract interaction repeats:
|
|
6
|
+
* check `success`, parse the error, verify `send()` exists, and call it.
|
|
7
|
+
*
|
|
8
|
+
* Works with any object whose shape matches the Ink SDK contract query result
|
|
9
|
+
* (typed structurally — no Ink SDK import required):
|
|
10
|
+
*
|
|
11
|
+
* - `contract.query("method", { origin, data })` (Ink SDK)
|
|
12
|
+
* - `contract.write("method", args, origin)` (patched SDK wrappers)
|
|
13
|
+
* - Any object with `{ success: boolean; value?: { send?(): ... } }`
|
|
14
|
+
*
|
|
15
|
+
* @param result - The dry-run result from a contract query or write simulation.
|
|
16
|
+
* @returns The submittable transaction, ready to pass to {@link submitAndWatch}.
|
|
17
|
+
* @throws {TxDryRunError} If the dry run failed or the result has no `send()`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { extractTransaction, submitAndWatch, createDevSigner } from "@polkadot-apps/tx";
|
|
22
|
+
*
|
|
23
|
+
* const dryRun = await contract.query("createItem", { origin, data: { name, price } });
|
|
24
|
+
* const tx = extractTransaction(dryRun);
|
|
25
|
+
* const result = await submitAndWatch(tx, createDevSigner("Alice"));
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example Composing with retry logic:
|
|
29
|
+
* ```ts
|
|
30
|
+
* const tx = extractTransaction(await contract.query("transfer", { origin, data }));
|
|
31
|
+
* const result = await withRetry(() => submitAndWatch(tx, signer));
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function extractTransaction(result: {
|
|
35
|
+
success: boolean;
|
|
36
|
+
value?: unknown;
|
|
37
|
+
error?: unknown;
|
|
38
|
+
}): SubmittableTransaction;
|
|
39
|
+
/**
|
|
40
|
+
* Apply a safety buffer to weight estimates from a dry-run result.
|
|
41
|
+
*
|
|
42
|
+
* Dry-run weight estimates reflect the exact execution cost at the time of
|
|
43
|
+
* simulation. On-chain conditions can change between dry-run and actual
|
|
44
|
+
* submission (storage growth, state changes by other transactions), so a
|
|
45
|
+
* buffer prevents unexpected `OutOfGas` failures.
|
|
46
|
+
*
|
|
47
|
+
* The default 25% buffer matches the convention used across Polkadot
|
|
48
|
+
* ecosystem tooling.
|
|
49
|
+
*
|
|
50
|
+
* @param weight - The `weight_required` from a `ReviveApi.call` or `ReviveApi.eth_transact` dry-run.
|
|
51
|
+
* @param options - Override the buffer percentage (default: 25%).
|
|
52
|
+
* @returns A new weight with both components scaled up.
|
|
53
|
+
*
|
|
54
|
+
* @example Basic usage with ReviveApi dry-run:
|
|
55
|
+
* ```ts
|
|
56
|
+
* const dryRun = await api.apis.ReviveApi.call(origin, dest, value, undefined, undefined, data);
|
|
57
|
+
*
|
|
58
|
+
* const tx = api.tx.Revive.call({
|
|
59
|
+
* dest, value, data,
|
|
60
|
+
* weight_limit: applyWeightBuffer(dryRun.weight_required),
|
|
61
|
+
* storage_deposit_limit: dryRun.storage_deposit.value,
|
|
62
|
+
* });
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @example Custom buffer for latency-sensitive operations:
|
|
66
|
+
* ```ts
|
|
67
|
+
* applyWeightBuffer(dryRun.weight_required, { percent: 50 });
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function applyWeightBuffer(weight: Weight, options?: {
|
|
71
|
+
percent?: number;
|
|
72
|
+
}): Weight;
|
|
73
|
+
//# sourceMappingURL=dry-run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dry-run.d.ts","sourceRoot":"","sources":["../src/dry-run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,sBAAsB,CAkBzB;AAsBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAOxF"}
|
package/dist/dry-run.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { TxDryRunError, formatDryRunError } from "./errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Validate an Ink SDK dry-run result and extract the submittable transaction.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the 5-10 line boilerplate that every contract interaction repeats:
|
|
6
|
+
* check `success`, parse the error, verify `send()` exists, and call it.
|
|
7
|
+
*
|
|
8
|
+
* Works with any object whose shape matches the Ink SDK contract query result
|
|
9
|
+
* (typed structurally — no Ink SDK import required):
|
|
10
|
+
*
|
|
11
|
+
* - `contract.query("method", { origin, data })` (Ink SDK)
|
|
12
|
+
* - `contract.write("method", args, origin)` (patched SDK wrappers)
|
|
13
|
+
* - Any object with `{ success: boolean; value?: { send?(): ... } }`
|
|
14
|
+
*
|
|
15
|
+
* @param result - The dry-run result from a contract query or write simulation.
|
|
16
|
+
* @returns The submittable transaction, ready to pass to {@link submitAndWatch}.
|
|
17
|
+
* @throws {TxDryRunError} If the dry run failed or the result has no `send()`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { extractTransaction, submitAndWatch, createDevSigner } from "@polkadot-apps/tx";
|
|
22
|
+
*
|
|
23
|
+
* const dryRun = await contract.query("createItem", { origin, data: { name, price } });
|
|
24
|
+
* const tx = extractTransaction(dryRun);
|
|
25
|
+
* const result = await submitAndWatch(tx, createDevSigner("Alice"));
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example Composing with retry logic:
|
|
29
|
+
* ```ts
|
|
30
|
+
* const tx = extractTransaction(await contract.query("transfer", { origin, data }));
|
|
31
|
+
* const result = await withRetry(() => submitAndWatch(tx, signer));
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function extractTransaction(result) {
|
|
35
|
+
if (!result.success) {
|
|
36
|
+
const formatted = formatDryRunError(result);
|
|
37
|
+
const revertReason = extractRevertReason(result.value);
|
|
38
|
+
throw new TxDryRunError(result, formatted, revertReason);
|
|
39
|
+
}
|
|
40
|
+
const value = result.value;
|
|
41
|
+
if (value == null || typeof value !== "object") {
|
|
42
|
+
throw new TxDryRunError(result, "dry run returned no value");
|
|
43
|
+
}
|
|
44
|
+
const v = value;
|
|
45
|
+
if (typeof v.send !== "function") {
|
|
46
|
+
throw new TxDryRunError(result, "not a write query (no send())");
|
|
47
|
+
}
|
|
48
|
+
return v.send();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Try to extract a revert reason string from a dry-run result value.
|
|
52
|
+
* Returns `undefined` if no revert reason is available.
|
|
53
|
+
*/
|
|
54
|
+
function extractRevertReason(value) {
|
|
55
|
+
if (value == null || typeof value !== "object")
|
|
56
|
+
return undefined;
|
|
57
|
+
const v = value;
|
|
58
|
+
if (typeof v.revertReason === "string" && v.revertReason) {
|
|
59
|
+
return v.revertReason;
|
|
60
|
+
}
|
|
61
|
+
// Wrapped raw value (patched SDK)
|
|
62
|
+
if ("raw" in v && v.raw != null && typeof v.raw === "object") {
|
|
63
|
+
return extractRevertReason(v.raw);
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Apply a safety buffer to weight estimates from a dry-run result.
|
|
69
|
+
*
|
|
70
|
+
* Dry-run weight estimates reflect the exact execution cost at the time of
|
|
71
|
+
* simulation. On-chain conditions can change between dry-run and actual
|
|
72
|
+
* submission (storage growth, state changes by other transactions), so a
|
|
73
|
+
* buffer prevents unexpected `OutOfGas` failures.
|
|
74
|
+
*
|
|
75
|
+
* The default 25% buffer matches the convention used across Polkadot
|
|
76
|
+
* ecosystem tooling.
|
|
77
|
+
*
|
|
78
|
+
* @param weight - The `weight_required` from a `ReviveApi.call` or `ReviveApi.eth_transact` dry-run.
|
|
79
|
+
* @param options - Override the buffer percentage (default: 25%).
|
|
80
|
+
* @returns A new weight with both components scaled up.
|
|
81
|
+
*
|
|
82
|
+
* @example Basic usage with ReviveApi dry-run:
|
|
83
|
+
* ```ts
|
|
84
|
+
* const dryRun = await api.apis.ReviveApi.call(origin, dest, value, undefined, undefined, data);
|
|
85
|
+
*
|
|
86
|
+
* const tx = api.tx.Revive.call({
|
|
87
|
+
* dest, value, data,
|
|
88
|
+
* weight_limit: applyWeightBuffer(dryRun.weight_required),
|
|
89
|
+
* storage_deposit_limit: dryRun.storage_deposit.value,
|
|
90
|
+
* });
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @example Custom buffer for latency-sensitive operations:
|
|
94
|
+
* ```ts
|
|
95
|
+
* applyWeightBuffer(dryRun.weight_required, { percent: 50 });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export function applyWeightBuffer(weight, options) {
|
|
99
|
+
const percent = options?.percent ?? 25;
|
|
100
|
+
const multiplier = 100n + BigInt(percent);
|
|
101
|
+
return {
|
|
102
|
+
ref_time: (weight.ref_time * multiplier) / 100n,
|
|
103
|
+
proof_size: (weight.proof_size * multiplier) / 100n,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (import.meta.vitest) {
|
|
107
|
+
const { describe, test, expect } = import.meta.vitest;
|
|
108
|
+
describe("extractTransaction", () => {
|
|
109
|
+
test("returns tx from successful dry-run with send()", () => {
|
|
110
|
+
const mockTx = {
|
|
111
|
+
signSubmitAndWatch: () => ({ subscribe: () => ({ unsubscribe: () => { } }) }),
|
|
112
|
+
};
|
|
113
|
+
const result = {
|
|
114
|
+
success: true,
|
|
115
|
+
value: { response: "ok", send: () => mockTx },
|
|
116
|
+
};
|
|
117
|
+
expect(extractTransaction(result)).toBe(mockTx);
|
|
118
|
+
});
|
|
119
|
+
test("throws TxDryRunError on failed dry-run", () => {
|
|
120
|
+
const result = {
|
|
121
|
+
success: false,
|
|
122
|
+
value: { revertReason: "InsufficientBalance" },
|
|
123
|
+
};
|
|
124
|
+
try {
|
|
125
|
+
extractTransaction(result);
|
|
126
|
+
expect.unreachable("should have thrown");
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
expect(e).toBeInstanceOf(TxDryRunError);
|
|
130
|
+
const err = e;
|
|
131
|
+
expect(err.revertReason).toBe("InsufficientBalance");
|
|
132
|
+
expect(err.formatted).toBe("InsufficientBalance");
|
|
133
|
+
expect(err.message).toContain("InsufficientBalance");
|
|
134
|
+
expect(err.raw).toBe(result);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
test("throws TxDryRunError with Module error formatting", () => {
|
|
138
|
+
const result = {
|
|
139
|
+
success: false,
|
|
140
|
+
value: {
|
|
141
|
+
type: "Module",
|
|
142
|
+
value: { type: "Revive", value: { type: "StorageDepositNotEnoughFunds" } },
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
try {
|
|
146
|
+
extractTransaction(result);
|
|
147
|
+
expect.unreachable("should have thrown");
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
const err = e;
|
|
151
|
+
expect(err.formatted).toBe("Revive.StorageDepositNotEnoughFunds");
|
|
152
|
+
expect(err.revertReason).toBeUndefined();
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
test("throws TxDryRunError with error field", () => {
|
|
156
|
+
const result = {
|
|
157
|
+
success: false,
|
|
158
|
+
value: {},
|
|
159
|
+
error: { type: "ContractTrapped" },
|
|
160
|
+
};
|
|
161
|
+
try {
|
|
162
|
+
extractTransaction(result);
|
|
163
|
+
expect.unreachable("should have thrown");
|
|
164
|
+
}
|
|
165
|
+
catch (e) {
|
|
166
|
+
const err = e;
|
|
167
|
+
expect(err.formatted).toBe("ContractTrapped");
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
test("throws when value is missing", () => {
|
|
171
|
+
const result = { success: true };
|
|
172
|
+
expect(() => extractTransaction(result)).toThrow(TxDryRunError);
|
|
173
|
+
});
|
|
174
|
+
test("throws when send is not a function", () => {
|
|
175
|
+
const result = { success: true, value: { response: "ok" } };
|
|
176
|
+
expect(() => extractTransaction(result)).toThrow("not a write query");
|
|
177
|
+
});
|
|
178
|
+
test("throws with revertReason from nested raw (patched SDK)", () => {
|
|
179
|
+
const result = {
|
|
180
|
+
success: false,
|
|
181
|
+
value: { raw: { revertReason: "Unauthorized" } },
|
|
182
|
+
};
|
|
183
|
+
try {
|
|
184
|
+
extractTransaction(result);
|
|
185
|
+
expect.unreachable("should have thrown");
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
const err = e;
|
|
189
|
+
expect(err.revertReason).toBe("Unauthorized");
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
test("throws with ReviveApi Message error", () => {
|
|
193
|
+
const result = {
|
|
194
|
+
success: false,
|
|
195
|
+
value: { type: "Message", value: "Insufficient balance for gas * price + value" },
|
|
196
|
+
};
|
|
197
|
+
try {
|
|
198
|
+
extractTransaction(result);
|
|
199
|
+
expect.unreachable("should have thrown");
|
|
200
|
+
}
|
|
201
|
+
catch (e) {
|
|
202
|
+
const err = e;
|
|
203
|
+
expect(err.formatted).toBe("Insufficient balance for gas * price + value");
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
describe("applyWeightBuffer", () => {
|
|
208
|
+
test("applies default 25% buffer", () => {
|
|
209
|
+
const weight = { ref_time: 1000n, proof_size: 500n };
|
|
210
|
+
const buffered = applyWeightBuffer(weight);
|
|
211
|
+
expect(buffered.ref_time).toBe(1250n);
|
|
212
|
+
expect(buffered.proof_size).toBe(625n);
|
|
213
|
+
});
|
|
214
|
+
test("applies custom buffer percentage", () => {
|
|
215
|
+
const weight = { ref_time: 1000n, proof_size: 1000n };
|
|
216
|
+
const buffered = applyWeightBuffer(weight, { percent: 50 });
|
|
217
|
+
expect(buffered.ref_time).toBe(1500n);
|
|
218
|
+
expect(buffered.proof_size).toBe(1500n);
|
|
219
|
+
});
|
|
220
|
+
test("zero buffer returns same values", () => {
|
|
221
|
+
const weight = { ref_time: 1000n, proof_size: 500n };
|
|
222
|
+
const buffered = applyWeightBuffer(weight, { percent: 0 });
|
|
223
|
+
expect(buffered.ref_time).toBe(1000n);
|
|
224
|
+
expect(buffered.proof_size).toBe(500n);
|
|
225
|
+
});
|
|
226
|
+
test("does not mutate original weight", () => {
|
|
227
|
+
const weight = { ref_time: 1000n, proof_size: 500n };
|
|
228
|
+
const buffered = applyWeightBuffer(weight);
|
|
229
|
+
expect(weight.ref_time).toBe(1000n);
|
|
230
|
+
expect(weight.proof_size).toBe(500n);
|
|
231
|
+
expect(buffered).not.toBe(weight);
|
|
232
|
+
});
|
|
233
|
+
test("works with realistic weight values", () => {
|
|
234
|
+
// Values from tick3t reference repo
|
|
235
|
+
const weight = { ref_time: 4500000000n, proof_size: 1000000n };
|
|
236
|
+
const buffered = applyWeightBuffer(weight);
|
|
237
|
+
expect(buffered.ref_time).toBe(5625000000n);
|
|
238
|
+
expect(buffered.proof_size).toBe(1250000n);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=dry-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dry-run.js","sourceRoot":"","sources":["../src/dry-run.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/** Base class for all transaction errors. Use `instanceof TxError` to catch any tx-related error. */
|
|
2
|
+
export declare class TxError extends Error {
|
|
3
|
+
constructor(message: string, options?: ErrorOptions);
|
|
4
|
+
}
|
|
5
|
+
/** The transaction did not finalize within the configured timeout. It may still be processing on-chain. */
|
|
6
|
+
export declare class TxTimeoutError extends TxError {
|
|
7
|
+
readonly timeoutMs: number;
|
|
8
|
+
constructor(timeoutMs: number);
|
|
9
|
+
}
|
|
10
|
+
/** The transaction was included on-chain but the dispatch failed. */
|
|
11
|
+
export declare class TxDispatchError extends TxError {
|
|
12
|
+
/** Raw dispatch error from polkadot-api. */
|
|
13
|
+
readonly dispatchError: unknown;
|
|
14
|
+
/** Human-readable error string (e.g., "Revive.ContractReverted"). */
|
|
15
|
+
readonly formatted: string;
|
|
16
|
+
constructor(dispatchError: unknown, formatted: string);
|
|
17
|
+
}
|
|
18
|
+
/** The user rejected the signing request in their wallet. */
|
|
19
|
+
export declare class TxSigningRejectedError extends TxError {
|
|
20
|
+
constructor();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Extract a human-readable error from a transaction result's dispatch error.
|
|
24
|
+
*
|
|
25
|
+
* PAPI dispatch errors for pallet modules are nested:
|
|
26
|
+
* `{ type: "Module", value: { type: "Revive", value: { type: "ContractReverted" } } }`
|
|
27
|
+
*
|
|
28
|
+
* This walks the chain to build a string like `"Revive.ContractReverted"`.
|
|
29
|
+
*
|
|
30
|
+
* @param result - A transaction result with `ok` and optional `dispatchError`.
|
|
31
|
+
* @returns A human-readable error string, or `""` if the result is ok, or `"unknown error"` if
|
|
32
|
+
* the dispatch error cannot be decoded.
|
|
33
|
+
*/
|
|
34
|
+
export declare function formatDispatchError(result: {
|
|
35
|
+
ok: boolean;
|
|
36
|
+
dispatchError?: unknown;
|
|
37
|
+
}): string;
|
|
38
|
+
/**
|
|
39
|
+
* A dry-run simulation failed before the transaction was submitted on-chain.
|
|
40
|
+
*
|
|
41
|
+
* Thrown by {@link extractTransaction} when the dry-run result indicates failure.
|
|
42
|
+
* Carries structured error information so callers can distinguish revert reasons
|
|
43
|
+
* from dispatch errors programmatically.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* try {
|
|
48
|
+
* const tx = extractTransaction(await contract.query("mint", { origin, data }));
|
|
49
|
+
* } catch (e) {
|
|
50
|
+
* if (e instanceof TxDryRunError) {
|
|
51
|
+
* console.log(e.revertReason); // "InsufficientBalance" (if contract provided one)
|
|
52
|
+
* console.log(e.formatted); // "Revive.StorageDepositNotEnoughFunds"
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare class TxDryRunError extends TxError {
|
|
58
|
+
/** The raw dry-run result for programmatic inspection. */
|
|
59
|
+
readonly raw: unknown;
|
|
60
|
+
/** Human-readable error string derived from the dry-run result. */
|
|
61
|
+
readonly formatted: string;
|
|
62
|
+
/** Solidity revert reason, if the contract provided one. */
|
|
63
|
+
readonly revertReason?: string;
|
|
64
|
+
constructor(raw: unknown, formatted: string, revertReason?: string);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Extract a human-readable error from a failed dry-run result.
|
|
68
|
+
*
|
|
69
|
+
* Handles every error shape found across the Polkadot contract ecosystem:
|
|
70
|
+
*
|
|
71
|
+
* 1. **Revert reason** (Ink SDK patched results / EVM contracts):
|
|
72
|
+
* `{ value: { revertReason: "InsufficientBalance" } }`
|
|
73
|
+
*
|
|
74
|
+
* 2. **Nested dispatch errors** (raw Ink SDK / pallet errors):
|
|
75
|
+
* `{ value: { type: "Module", value: { type: "Revive", value: { type: "StorageDepositNotEnoughFunds" } } } }`
|
|
76
|
+
* Delegates to {@link formatDispatchError} for the Module.Pallet.Error chain.
|
|
77
|
+
*
|
|
78
|
+
* 3. **ReviveApi runtime messages** (`eth_transact` / `ReviveApi.call`):
|
|
79
|
+
* `{ value: { type: "Message", value: "Insufficient balance for gas * price + value" } }`
|
|
80
|
+
*
|
|
81
|
+
* 4. **ReviveApi contract revert data**:
|
|
82
|
+
* `{ value: { type: "Data", value: "0x08c379a0..." } }`
|
|
83
|
+
*
|
|
84
|
+
* 5. **Wrapped raw errors** (patched SDK wrappers):
|
|
85
|
+
* `{ value: { raw: { type: "Message", value: "..." } } }`
|
|
86
|
+
*
|
|
87
|
+
* 6. **Generic error field**:
|
|
88
|
+
* `{ error: { type: "ContractTrapped" } }` or `{ error: { name: "..." } }`
|
|
89
|
+
*
|
|
90
|
+
* @param result - A dry-run result with at least `success`, and optionally `value` / `error`.
|
|
91
|
+
* @returns A human-readable error string, or `""` if the result succeeded.
|
|
92
|
+
*/
|
|
93
|
+
export declare function formatDryRunError(result: {
|
|
94
|
+
success?: boolean;
|
|
95
|
+
value?: unknown;
|
|
96
|
+
error?: unknown;
|
|
97
|
+
}): string;
|
|
98
|
+
/**
|
|
99
|
+
* Check if an error looks like a user-rejected signing request.
|
|
100
|
+
*
|
|
101
|
+
* Different wallets use different error messages when the user rejects signing:
|
|
102
|
+
* "Cancelled", "Rejected", "User rejected", "denied". This checks for common
|
|
103
|
+
* patterns as a best-effort heuristic. Non-Error values always return false.
|
|
104
|
+
*
|
|
105
|
+
* @param error - The error to check.
|
|
106
|
+
* @returns `true` if the error message matches a known rejection pattern.
|
|
107
|
+
*/
|
|
108
|
+
export declare function isSigningRejection(error: unknown): boolean;
|
|
109
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,qBAAa,OAAQ,SAAQ,KAAK;gBAClB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAItD;AAED,2GAA2G;AAC3G,qBAAa,cAAe,SAAQ,OAAO;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,SAAS,EAAE,MAAM;CAQhC;AAED,qEAAqE;AACrE,qBAAa,eAAgB,SAAQ,OAAO;IACxC,4CAA4C;IAC5C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM;CAMxD;AAED,6DAA6D;AAC7D,qBAAa,sBAAuB,SAAQ,OAAO;;CAKlD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAwB5F;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,aAAc,SAAQ,OAAO;IACtC,0DAA0D;IAC1D,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4DAA4D;IAC5D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;gBAEnB,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;CAOrE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,MAAM,CAcT;AAoDD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAS1D"}
|