@trustvc/trustvc 2.10.0 → 2.11.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 +54 -0
- package/dist/cjs/index.js +11 -0
- package/dist/cjs/transaction/cancel.js +57 -0
- package/dist/cjs/transaction/index.js +10 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/transaction/cancel.js +55 -0
- package/dist/esm/transaction/index.js +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/transaction/cancel.d.ts +37 -0
- package/dist/types/transaction/index.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ TrustVC is a comprehensive wrapper library designed to simplify the signing and
|
|
|
27
27
|
- [b) Token Registry V5](#b-token-registry-v5)
|
|
28
28
|
- [8. **Document Builder**](#8-document-builder)
|
|
29
29
|
- [9. **Document Store**](#9-document-store)
|
|
30
|
+
- [10. **Transaction Cancel**](#10-transaction-cancel)
|
|
30
31
|
|
|
31
32
|
## Installation
|
|
32
33
|
|
|
@@ -1107,3 +1108,56 @@ for (const hash of documentHashes) {
|
|
|
1107
1108
|
await documentStoreIssue(storeAddress, hash, signer);
|
|
1108
1109
|
}
|
|
1109
1110
|
```
|
|
1111
|
+
|
|
1112
|
+
---
|
|
1113
|
+
|
|
1114
|
+
## 10. Transaction Cancel
|
|
1115
|
+
|
|
1116
|
+
TrustVC provides a utility to cancel a pending Ethereum transaction by replacing it with a 0-value transaction to the same address, using the same nonce and a higher gas price (replace-by-fee). This works with both ethers v5 and v6 signers.
|
|
1117
|
+
|
|
1118
|
+
**Reference:** [How to cancel Ethereum pending transactions](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/)
|
|
1119
|
+
|
|
1120
|
+
### cancelTransaction
|
|
1121
|
+
|
|
1122
|
+
#### Description
|
|
1123
|
+
|
|
1124
|
+
Cancels a pending transaction by sending a 0-value transaction to the signer’s address with the same nonce and a higher gas price. You can specify the pending transaction either by **transaction hash** (nonce and gas price are fetched; gas price is doubled) or by **nonce and gas price** explicitly. Transactions that use EIP-1559 (no legacy `gasPrice`) must be cancelled using nonce and gas price.
|
|
1125
|
+
|
|
1126
|
+
#### Parameters
|
|
1127
|
+
|
|
1128
|
+
- **signer** – Signer with a connected provider; type `CancelTransactionSigner` (compatible with ethers v5 and v6 signers).
|
|
1129
|
+
- **options** – `CancelTransactionOptions`:
|
|
1130
|
+
- **transactionHash** (optional): Pending transaction hash (`0x...`). If provided, nonce and gas price are read from the chain and gas price is increased by 100%.
|
|
1131
|
+
- **nonce** (optional): Pending transaction nonce. Must be used together with `gasPrice`.
|
|
1132
|
+
- **gasPrice** (optional): Gas price in wei for the replacement transaction. Must be used together with `nonce`.
|
|
1133
|
+
|
|
1134
|
+
Either `(nonce, gasPrice)` or `transactionHash` must be provided.
|
|
1135
|
+
|
|
1136
|
+
#### Returns
|
|
1137
|
+
|
|
1138
|
+
**Promise<string>** – The replacement transaction hash.
|
|
1139
|
+
|
|
1140
|
+
#### Throws
|
|
1141
|
+
|
|
1142
|
+
- If the signer has no provider.
|
|
1143
|
+
- If neither `(nonce, gasPrice)` nor `transactionHash` is provided.
|
|
1144
|
+
- If `transactionHash` is given but the transaction is not found.
|
|
1145
|
+
- If the transaction uses EIP-1559 (no `gasPrice`); in that case use nonce and gas price explicitly.
|
|
1146
|
+
|
|
1147
|
+
#### Example
|
|
1148
|
+
|
|
1149
|
+
```ts
|
|
1150
|
+
import { cancelTransaction } from '@trustvc/trustvc';
|
|
1151
|
+
|
|
1152
|
+
// Cancel by transaction hash (gas price is fetched and doubled)
|
|
1153
|
+
const replacementHash = await cancelTransaction(signer, {
|
|
1154
|
+
transactionHash: '0x...',
|
|
1155
|
+
});
|
|
1156
|
+
console.log('Replacement tx:', replacementHash);
|
|
1157
|
+
|
|
1158
|
+
// Or cancel by nonce and gas price (e.g. for EIP-1559 txs)
|
|
1159
|
+
const replacementHash2 = await cancelTransaction(signer, {
|
|
1160
|
+
nonce: '5',
|
|
1161
|
+
gasPrice: '25000000000', // 25 gwei in wei
|
|
1162
|
+
});
|
|
1163
|
+
```
|
package/dist/cjs/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var tokenRegistryV4 = require('./token-registry-v4');
|
|
4
4
|
var tokenRegistryV5 = require('./token-registry-v5');
|
|
5
5
|
var documentStore = require('./document-store');
|
|
6
|
+
var transaction = require('./transaction');
|
|
6
7
|
var tokenRegistryFunctions = require('./token-registry-functions');
|
|
7
8
|
var core = require('./core');
|
|
8
9
|
var openAttestation = require('./open-attestation');
|
|
@@ -118,6 +119,16 @@ Object.defineProperty(exports, "getRoleString", {
|
|
|
118
119
|
enumerable: true,
|
|
119
120
|
get: function () { return documentStore.getRoleString; }
|
|
120
121
|
});
|
|
122
|
+
Object.defineProperty(exports, "cancelTransaction", {
|
|
123
|
+
enumerable: true,
|
|
124
|
+
get: function () { return transaction.cancelTransaction; }
|
|
125
|
+
});
|
|
126
|
+
Object.keys(transaction).forEach(function (k) {
|
|
127
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
128
|
+
enumerable: true,
|
|
129
|
+
get: function () { return transaction[k]; }
|
|
130
|
+
});
|
|
131
|
+
});
|
|
121
132
|
Object.keys(tokenRegistryFunctions).forEach(function (k) {
|
|
122
133
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
123
134
|
enumerable: true,
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ethers = require('ethers');
|
|
4
|
+
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
const GAS_PRICE_SCALE_WHEN_FROM_HASH = 2;
|
|
8
|
+
const cancelTransaction = /* @__PURE__ */ __name(async (signer, options) => {
|
|
9
|
+
if (!signer.provider) {
|
|
10
|
+
throw new Error("Provider is required on signer");
|
|
11
|
+
}
|
|
12
|
+
const { nonce, gasPrice, transactionHash } = options;
|
|
13
|
+
let transactionNonce = nonce;
|
|
14
|
+
let transactionGasPrice = gasPrice;
|
|
15
|
+
if (transactionHash) {
|
|
16
|
+
if (typeof signer.provider.getTransaction !== "function") {
|
|
17
|
+
throw new Error("Provider does not support getTransaction");
|
|
18
|
+
}
|
|
19
|
+
const tx = await signer.provider.getTransaction(transactionHash);
|
|
20
|
+
if (!tx) {
|
|
21
|
+
throw new Error(`Transaction not found: ${transactionHash}`);
|
|
22
|
+
}
|
|
23
|
+
const txNonce = tx.nonce;
|
|
24
|
+
const txGasPrice = tx.gasPrice;
|
|
25
|
+
if (txGasPrice == null) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
"Transaction uses EIP-1559 (no gasPrice). Cancel by providing --nonce and --gas-price explicitly."
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
transactionNonce = String(txNonce);
|
|
31
|
+
const scaled = typeof txGasPrice === "bigint" ? txGasPrice * BigInt(GAS_PRICE_SCALE_WHEN_FROM_HASH) : ethers.BigNumber.from(txGasPrice).mul(GAS_PRICE_SCALE_WHEN_FROM_HASH);
|
|
32
|
+
transactionGasPrice = String(scaled);
|
|
33
|
+
}
|
|
34
|
+
if (!transactionNonce || !transactionGasPrice) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
"Provide either (--nonce and --gas-price) or --transaction-hash to cancel the pending transaction"
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
const address = await signer.getAddress();
|
|
40
|
+
if (!/^\d+$/.test(transactionNonce)) {
|
|
41
|
+
throw new Error("Invalid nonce: expected a non-negative integer");
|
|
42
|
+
}
|
|
43
|
+
if (!/^\d+$/.test(transactionGasPrice) || transactionGasPrice === "0") {
|
|
44
|
+
throw new Error("Invalid gasPrice: expected a positive integer string in wei");
|
|
45
|
+
}
|
|
46
|
+
const nonceNum = Number(transactionNonce);
|
|
47
|
+
const txResponse = await signer.sendTransaction({
|
|
48
|
+
to: address,
|
|
49
|
+
value: 0,
|
|
50
|
+
nonce: nonceNum,
|
|
51
|
+
gasPrice: transactionGasPrice,
|
|
52
|
+
gasLimit: 21e3
|
|
53
|
+
});
|
|
54
|
+
return txResponse.hash;
|
|
55
|
+
}, "cancelTransaction");
|
|
56
|
+
|
|
57
|
+
exports.cancelTransaction = cancelTransaction;
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { v4ComputeInterfaceId, v4ComputeTitleEscrowAddress, v4ContractAddress, v4Contracts, v4EncodeInitParams, v4GetEventFromReceipt, v4RoleHash, v4SupportInterfaceIds, v4Utils } from './token-registry-v4';
|
|
2
2
|
export { v5ComputeInterfaceId, v5ContractAddress, v5Contracts, v5EncodeInitParams, v5GetEventFromReceipt, v5RoleHash, v5SupportInterfaceIds, v5Utils } from './token-registry-v5';
|
|
3
3
|
export { DocumentStore__factory, TransferableDocumentStore__factory, deployDocumentStore, documentStoreGrantRole, documentStoreIssue, documentStoreRevoke, documentStoreRevokeRole, documentStoreTransferOwnership, getRoleString } from './document-store';
|
|
4
|
+
export * from './transaction';
|
|
5
|
+
export { cancelTransaction } from './transaction';
|
|
4
6
|
export * from './token-registry-functions';
|
|
5
7
|
export * from './core';
|
|
6
8
|
export * from './open-attestation';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { BigNumber } from 'ethers';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
+
const GAS_PRICE_SCALE_WHEN_FROM_HASH = 2;
|
|
6
|
+
const cancelTransaction = /* @__PURE__ */ __name(async (signer, options) => {
|
|
7
|
+
if (!signer.provider) {
|
|
8
|
+
throw new Error("Provider is required on signer");
|
|
9
|
+
}
|
|
10
|
+
const { nonce, gasPrice, transactionHash } = options;
|
|
11
|
+
let transactionNonce = nonce;
|
|
12
|
+
let transactionGasPrice = gasPrice;
|
|
13
|
+
if (transactionHash) {
|
|
14
|
+
if (typeof signer.provider.getTransaction !== "function") {
|
|
15
|
+
throw new Error("Provider does not support getTransaction");
|
|
16
|
+
}
|
|
17
|
+
const tx = await signer.provider.getTransaction(transactionHash);
|
|
18
|
+
if (!tx) {
|
|
19
|
+
throw new Error(`Transaction not found: ${transactionHash}`);
|
|
20
|
+
}
|
|
21
|
+
const txNonce = tx.nonce;
|
|
22
|
+
const txGasPrice = tx.gasPrice;
|
|
23
|
+
if (txGasPrice == null) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
"Transaction uses EIP-1559 (no gasPrice). Cancel by providing --nonce and --gas-price explicitly."
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
transactionNonce = String(txNonce);
|
|
29
|
+
const scaled = typeof txGasPrice === "bigint" ? txGasPrice * BigInt(GAS_PRICE_SCALE_WHEN_FROM_HASH) : BigNumber.from(txGasPrice).mul(GAS_PRICE_SCALE_WHEN_FROM_HASH);
|
|
30
|
+
transactionGasPrice = String(scaled);
|
|
31
|
+
}
|
|
32
|
+
if (!transactionNonce || !transactionGasPrice) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
"Provide either (--nonce and --gas-price) or --transaction-hash to cancel the pending transaction"
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
const address = await signer.getAddress();
|
|
38
|
+
if (!/^\d+$/.test(transactionNonce)) {
|
|
39
|
+
throw new Error("Invalid nonce: expected a non-negative integer");
|
|
40
|
+
}
|
|
41
|
+
if (!/^\d+$/.test(transactionGasPrice) || transactionGasPrice === "0") {
|
|
42
|
+
throw new Error("Invalid gasPrice: expected a positive integer string in wei");
|
|
43
|
+
}
|
|
44
|
+
const nonceNum = Number(transactionNonce);
|
|
45
|
+
const txResponse = await signer.sendTransaction({
|
|
46
|
+
to: address,
|
|
47
|
+
value: 0,
|
|
48
|
+
nonce: nonceNum,
|
|
49
|
+
gasPrice: transactionGasPrice,
|
|
50
|
+
gasLimit: 21e3
|
|
51
|
+
});
|
|
52
|
+
return txResponse.hash;
|
|
53
|
+
}, "cancelTransaction");
|
|
54
|
+
|
|
55
|
+
export { cancelTransaction };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cancelTransaction } from './cancel';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export { documentStoreTransferOwnership } from './document-store/transferOwnersh
|
|
|
19
19
|
export { deployDocumentStore } from './deploy/document-store.js';
|
|
20
20
|
export { getRoleString } from './document-store/document-store-roles.js';
|
|
21
21
|
export { DocumentStore__factory, TransferableDocumentStore__factory } from '@trustvc/document-store';
|
|
22
|
+
export { CancelTransactionOptions, CancelTransactionSigner, cancelTransaction } from './transaction/cancel.js';
|
|
22
23
|
export { nominate, transferBeneficiary, transferHolder, transferOwners } from './token-registry-functions/transfer.js';
|
|
23
24
|
export { rejectTransferBeneficiary, rejectTransferHolder, rejectTransferOwners } from './token-registry-functions/rejectTransfers.js';
|
|
24
25
|
export { acceptReturned, rejectReturned, returnToIssuer } from './token-registry-functions/returnToken.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transaction Cancel Module
|
|
3
|
+
*
|
|
4
|
+
* Cancels a pending transaction by replacing it with a 0-value transaction to self
|
|
5
|
+
* using the same nonce and a higher gas price (e.g. 2x when using --transaction-hash).
|
|
6
|
+
* @see https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/
|
|
7
|
+
*/
|
|
8
|
+
interface CancelTransactionOptions {
|
|
9
|
+
/** Pending transaction nonce (use with gasPrice, or use transactionHash instead) */
|
|
10
|
+
nonce?: string;
|
|
11
|
+
/** Gas price higher than the pending transaction (use with nonce) */
|
|
12
|
+
gasPrice?: string;
|
|
13
|
+
/** Pending transaction hash; nonce and gas price will be fetched and gas price increased by 100% */
|
|
14
|
+
transactionHash?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Signer with provider, compatible with ethers v5 and v6. */
|
|
17
|
+
interface CancelTransactionSigner {
|
|
18
|
+
getAddress(): Promise<string>;
|
|
19
|
+
provider: {
|
|
20
|
+
getTransaction?(hash: string): Promise<unknown>;
|
|
21
|
+
} | null;
|
|
22
|
+
sendTransaction(tx: Record<string, unknown>): Promise<{
|
|
23
|
+
hash: string;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Cancels a pending transaction by sending a 0-value transaction to self with the same nonce
|
|
28
|
+
* and a higher gas price. Supports both ethers v5 and v6 signers via a unified transaction object.
|
|
29
|
+
* @param {CancelTransactionSigner} signer - Signer with provider (ethers v5 or v6)
|
|
30
|
+
* @param {CancelTransactionOptions} options - Either (nonce + gasPrice) or transactionHash
|
|
31
|
+
* @returns {Promise<string>} The replacement transaction hash
|
|
32
|
+
* @throws If neither (nonce and gasPrice) nor transactionHash is provided
|
|
33
|
+
* @throws If provider is not available on signer
|
|
34
|
+
*/
|
|
35
|
+
declare const cancelTransaction: (signer: CancelTransactionSigner, options: CancelTransactionOptions) => Promise<string>;
|
|
36
|
+
|
|
37
|
+
export { type CancelTransactionOptions, type CancelTransactionSigner, cancelTransaction };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CancelTransactionOptions, CancelTransactionSigner, cancelTransaction } from './cancel.js';
|