@cityofzion/bs-ethereum 3.1.17 → 3.1.18

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.
@@ -1,11 +1,9 @@
1
1
  import { type TBSAccount, type TTransferIntent, type TBSToken, type TTransferParams, type TGetLedgerTransport, type ITokenService, type TBSNetwork, type IBlockchainDataService, type IExchangeDataService, type INftDataService, type IExplorerService, type TPingNetworkResponse, type IFullTransactionsDataService, type TTransactionDefault, type TBSNetworkId, BSBigUnitAmount } from '@cityofzion/blockchain-service';
2
- import { ethers } from 'ethers';
2
+ import { ethers, type Signer } from 'ethers';
3
3
  import { EthersLedgerServiceEthereum } from './services/ledger/EthersLedgerServiceEthereum';
4
4
  import type { IBSEthereum, TBSEthereumName, TBSEthereumNetworkId } from './types';
5
- import { TypedDataSigner } from '@ethersproject/abstract-signer';
6
5
  import { WalletConnectServiceEthereum } from './services/wallet-connect/WalletConnectServiceEthereum';
7
6
  export declare class BSEthereum<N extends string = TBSEthereumName, A extends TBSNetworkId = TBSEthereumNetworkId> implements IBSEthereum<N, A> {
8
- #private;
9
7
  readonly name: N;
10
8
  readonly bipDerivationPath: string;
11
9
  readonly isMultiTransferSupported = false;
@@ -26,11 +24,12 @@ export declare class BSEthereum<N extends string = TBSEthereumName, A extends TB
26
24
  walletConnectService: WalletConnectServiceEthereum<N, A>;
27
25
  fullTransactionsDataService: IFullTransactionsDataService<N>;
28
26
  constructor(name: N, network?: TBSNetwork<A>, getLedgerTransport?: TGetLedgerTransport<N>);
29
- _generateSigner(account: TBSAccount<N>): Promise<ethers.Signer & TypedDataSigner>;
27
+ _getSigner(account: TBSAccount<N>): Promise<Signer>;
30
28
  _buildTransferParams(intent: TTransferIntent): Promise<{
31
- transactionParams: ethers.utils.Deferrable<ethers.providers.TransactionRequest>;
29
+ transactionParams: ethers.TransactionRequest;
32
30
  gasPriceBn: BSBigUnitAmount;
33
31
  }>;
32
+ _setTokens(network: TBSNetwork<A>): void;
34
33
  setNetwork(network: TBSNetwork<A>): void;
35
34
  pingNetwork(url: string): Promise<TPingNetworkResponse>;
36
35
  validateAddress(address: string): boolean;
@@ -32,15 +32,9 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
36
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
37
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
38
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
39
- };
40
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
41
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
42
37
  };
43
- var _BSEthereum_instances, _BSEthereum_setTokens;
44
38
  Object.defineProperty(exports, "__esModule", { value: true });
45
39
  exports.BSEthereum = void 0;
46
40
  const blockchain_service_1 = require("@cityofzion/blockchain-service");
@@ -60,7 +54,6 @@ const axios_1 = __importDefault(require("axios"));
60
54
  const MoralisFullTransactionsDataServiceEthereum_1 = require("./services/full-transactions-data/MoralisFullTransactionsDataServiceEthereum");
61
55
  class BSEthereum {
62
56
  constructor(name, network, getLedgerTransport) {
63
- _BSEthereum_instances.add(this);
64
57
  this.isMultiTransferSupported = false;
65
58
  this.isCustomNetworkSupported = false;
66
59
  this.name = name;
@@ -75,8 +68,8 @@ class BSEthereum {
75
68
  this.defaultNetwork = this.availableNetworks.find(network => network.type === 'mainnet');
76
69
  this.setNetwork(network ?? this.defaultNetwork);
77
70
  }
78
- async _generateSigner(account) {
79
- const provider = new ethers_1.ethers.providers.JsonRpcProvider(this.network.url);
71
+ async _getSigner(account) {
72
+ const provider = new ethers_1.JsonRpcProvider(this.network.url);
80
73
  if (account.isHardware) {
81
74
  if (!this.ledgerService.getLedgerTransport)
82
75
  throw new Error('You must provide getLedgerTransport function to use Ledger');
@@ -89,12 +82,13 @@ class BSEthereum {
89
82
  return new ethers_1.ethers.Wallet(account.key, provider);
90
83
  }
91
84
  async _buildTransferParams(intent) {
92
- const provider = new ethers_1.ethers.providers.JsonRpcProvider(this.network.url);
85
+ const provider = new ethers_1.JsonRpcProvider(this.network.url);
93
86
  const amount = new blockchain_service_1.BSBigHumanAmount(intent.amount, intent.token.decimals).toUnit().toString();
94
- const gasPrice = await provider.getGasPrice();
95
- const gasPriceBn = new blockchain_service_1.BSBigUnitAmount(gasPrice.toString(), BSEthereumConstants_1.BSEthereumConstants.DEFAULT_DECIMALS);
87
+ const { gasPrice } = await provider.getFeeData();
88
+ const gasPriceBn = new blockchain_service_1.BSBigUnitAmount(gasPrice?.toString() || '0', BSEthereumConstants_1.BSEthereumConstants.DEFAULT_DECIMALS);
96
89
  let transactionParams = {
97
90
  type: 2,
91
+ chainId: parseInt(this.network.id),
98
92
  };
99
93
  const isNative = this.tokenService.predicateByHash(this.feeToken, intent.token.hash);
100
94
  if (isNative) {
@@ -105,7 +99,7 @@ class BSEthereum {
105
99
  const contract = new ethers_1.ethers.Contract(intent.token.hash, [
106
100
  'function transfer(address to, uint amount) returns (bool)',
107
101
  ]);
108
- const populatedTransaction = await contract.populateTransaction.transfer(intent.receiverAddress, amount);
102
+ const populatedTransaction = await contract.transfer.populateTransaction(intent.receiverAddress, amount);
109
103
  transactionParams = {
110
104
  ...populatedTransaction,
111
105
  ...transactionParams,
@@ -116,13 +110,19 @@ class BSEthereum {
116
110
  gasPriceBn,
117
111
  };
118
112
  }
113
+ _setTokens(network) {
114
+ const nativeAsset = BSEthereumHelper_1.BSEthereumHelper.getNativeAsset(network);
115
+ this.tokens = [nativeAsset];
116
+ this.nativeTokens = [nativeAsset];
117
+ this.feeToken = nativeAsset;
118
+ }
119
119
  setNetwork(network) {
120
120
  const networkUrls = BSEthereumConstants_1.BSEthereumConstants.RPC_LIST_BY_NETWORK_ID[network.id] || [];
121
121
  const isValidNetwork = blockchain_service_1.BSUtilsHelper.validateNetwork(network, this.availableNetworks, networkUrls);
122
122
  if (!isValidNetwork) {
123
123
  throw new Error(`Network with id ${network.id} is not available for ${this.name}`);
124
124
  }
125
- __classPrivateFieldGet(this, _BSEthereum_instances, "m", _BSEthereum_setTokens).call(this, network);
125
+ this._setTokens(network);
126
126
  this.network = network;
127
127
  this.networkUrls = networkUrls;
128
128
  this.nftDataService = new MoralisNDSEthereum_1.MoralisNDSEthereum(this);
@@ -150,7 +150,7 @@ class BSEthereum {
150
150
  };
151
151
  }
152
152
  validateAddress(address) {
153
- return ethers_1.ethers.utils.isAddress(address);
153
+ return (0, ethers_1.isAddress)(address);
154
154
  }
155
155
  validateEncrypted(json) {
156
156
  return ethersJsonWallets.isCrowdsaleWallet(json) || ethersJsonWallets.isKeystoreWallet(json);
@@ -171,7 +171,8 @@ class BSEthereum {
171
171
  }
172
172
  async generateAccountFromMnemonic(mnemonic, index) {
173
173
  const bipPath = blockchain_service_1.BSKeychainHelper.getBipPath(this.bipDerivationPath, index);
174
- const hd = ethers_1.ethers.utils.HDNode.fromMnemonic(Array.isArray(mnemonic) ? mnemonic.join(' ') : mnemonic).derivePath(bipPath);
174
+ const ethersMnemonic = ethers_1.ethers.Mnemonic.fromPhrase(Array.isArray(mnemonic) ? mnemonic.join(' ') : mnemonic);
175
+ const hd = ethers_1.ethers.HDNodeWallet.fromMnemonic(ethersMnemonic, bipPath);
175
176
  return {
176
177
  address: hd.address,
177
178
  key: hd.privateKey,
@@ -190,7 +191,7 @@ class BSEthereum {
190
191
  };
191
192
  }
192
193
  async generateAccountFromPublicKey(publicKey) {
193
- const address = ethers_1.ethers.utils.computeAddress(publicKey);
194
+ const address = (0, ethers_1.computeAddress)(publicKey);
194
195
  return {
195
196
  address,
196
197
  key: publicKey,
@@ -212,12 +213,12 @@ class BSEthereum {
212
213
  return wallet.encrypt(password);
213
214
  }
214
215
  async transfer({ senderAccount, intents }) {
215
- const signer = await this._generateSigner(senderAccount);
216
+ const signer = await this._getSigner(senderAccount);
216
217
  const { address } = senderAccount;
217
218
  const addressUrl = this.explorerService.buildAddressUrl(address);
218
219
  const transactions = [];
219
220
  let error;
220
- let nonce = await signer.getTransactionCount('pending');
221
+ let nonce = await signer.getNonce('pending');
221
222
  for (const intent of intents) {
222
223
  try {
223
224
  const { transactionParams, gasPriceBn } = await this._buildTransferParams(intent);
@@ -277,7 +278,7 @@ class BSEthereum {
277
278
  return transactions;
278
279
  }
279
280
  async calculateTransferFee(params) {
280
- const signer = await this._generateSigner(params.senderAccount);
281
+ const signer = await this._getSigner(params.senderAccount);
281
282
  let feeBn = new blockchain_service_1.BSBigUnitAmount(0, BSEthereumConstants_1.BSEthereumConstants.DEFAULT_DECIMALS);
282
283
  for (const intent of params.intents) {
283
284
  const { gasPriceBn, transactionParams } = await this._buildTransferParams(intent);
@@ -288,7 +289,7 @@ class BSEthereum {
288
289
  return feeBn.toHuman().toFormatted();
289
290
  }
290
291
  async resolveNameServiceDomain(domainName) {
291
- const provider = new ethers_1.ethers.providers.JsonRpcProvider(this.network.url);
292
+ const provider = new ethers_1.JsonRpcProvider(this.network.url);
292
293
  const address = await provider.resolveName(domainName);
293
294
  if (!address)
294
295
  throw new Error('No address found for domain name');
@@ -296,9 +297,3 @@ class BSEthereum {
296
297
  }
297
298
  }
298
299
  exports.BSEthereum = BSEthereum;
299
- _BSEthereum_instances = new WeakSet(), _BSEthereum_setTokens = function _BSEthereum_setTokens(network) {
300
- const nativeAsset = BSEthereumHelper_1.BSEthereumHelper.getNativeAsset(network);
301
- this.tokens = [nativeAsset];
302
- this.nativeTokens = [nativeAsset];
303
- this.feeToken = nativeAsset;
304
- };
@@ -63,11 +63,11 @@ BSEthereumConstants.RPC_LIST_BY_NETWORK_ID = {
63
63
  'https://endpoints.omniatech.io/v1/bsc/mainnet/public',
64
64
  ],
65
65
  '137': [
66
- 'https://polygon.meowrpc.com',
66
+ 'https://poly.api.pocket.network',
67
67
  'https://polygon-rpc.com',
68
68
  'https://polygon.llamarpc.com',
69
69
  'https://polygon.drpc.org',
70
- 'https://endpoints.omniatech.io/v1/matic/mainnet/public',
70
+ 'https://1rpc.io/matic',
71
71
  ],
72
72
  '250': [
73
73
  'https://rpcapi.fantom.network',
@@ -82,9 +82,10 @@ BSEthereumConstants.RPC_LIST_BY_NETWORK_ID = {
82
82
  'https://polygon-zkevm.blockpi.network/v1/rpc/public',
83
83
  ],
84
84
  '80002': [
85
- 'https://polygon-amoy.drpc.org',
86
85
  'https://polygon-amoy-bor-rpc.publicnode.com',
87
86
  'https://rpc.ankr.com/polygon_amoy',
87
+ 'https://rpc-amoy.polygon.technology',
88
+ 'https://polygon-amoy.drpc.org',
88
89
  ],
89
90
  '8453': [
90
91
  'https://base.llamarpc.com',
@@ -32,12 +32,13 @@ class RpcBDSEthereum {
32
32
  const receipt = await __classPrivateFieldGet(this, _RpcBDSEthereum_instances, "a", _RpcBDSEthereum_provider_get).getTransactionReceipt(hash);
33
33
  if (!receipt)
34
34
  throw new Error('Receipt not found');
35
- const effectiveGasPrice = receipt.effectiveGasPrice ?? transaction.gasPrice;
36
- const fee = effectiveGasPrice.mul(receipt.gasUsed);
35
+ const effectiveGasPrice = receipt.gasPrice ?? transaction.gasPrice;
36
+ const fee = (effectiveGasPrice || BigInt(0)) * receipt.gasUsed;
37
37
  const token = BSEthereumHelper_1.BSEthereumHelper.getNativeAsset(this._service.network);
38
38
  const fromUrl = this._service.explorerService.buildAddressUrl(transaction.from);
39
39
  const toUrl = this._service.explorerService.buildAddressUrl(transaction.to);
40
- const timestamp = transaction.timestamp ?? 0;
40
+ const block = await __classPrivateFieldGet(this, _RpcBDSEthereum_instances, "a", _RpcBDSEthereum_provider_get).getBlock(receipt.blockNumber);
41
+ const timestamp = block?.timestamp || 0;
41
42
  return {
42
43
  blockchain: this._service.name,
43
44
  isPending: false,
@@ -104,7 +105,7 @@ class RpcBDSEthereum {
104
105
  exports.RpcBDSEthereum = RpcBDSEthereum;
105
106
  _RpcBDSEthereum_providerInstance = new WeakMap(), _RpcBDSEthereum_instances = new WeakSet(), _RpcBDSEthereum_provider_get = function _RpcBDSEthereum_provider_get() {
106
107
  if (!__classPrivateFieldGet(this, _RpcBDSEthereum_providerInstance, "f")) {
107
- __classPrivateFieldSet(this, _RpcBDSEthereum_providerInstance, new ethers_1.ethers.providers.JsonRpcProvider(this._service.network.url), "f");
108
+ __classPrivateFieldSet(this, _RpcBDSEthereum_providerInstance, new ethers_1.JsonRpcProvider(this._service.network.url), "f");
108
109
  }
109
110
  return __classPrivateFieldGet(this, _RpcBDSEthereum_providerInstance, "f");
110
111
  };
@@ -1,17 +1,16 @@
1
1
  import { type TBSAccount, type TLedgerServiceEmitter, type TGetLedgerTransport, type TUntilIndexRecord, type ILedgerService } from '@cityofzion/blockchain-service';
2
2
  import Transport from '@ledgerhq/hw-transport';
3
- import { ethers, Signer } from 'ethers';
4
- import { TypedDataSigner } from '@ethersproject/abstract-signer';
3
+ import { ethers, AbstractSigner, type Provider, Transaction, TransactionLike } from 'ethers';
5
4
  import { BSEthereum } from '../../BSEthereum';
6
- export declare class EthersLedgerSigner extends Signer implements TypedDataSigner {
5
+ export declare class EthersLedgerSigner extends AbstractSigner {
7
6
  #private;
8
- static shouldRetry: (error: any) => boolean;
9
- constructor(transport: Transport, bipPath: string, provider?: ethers.providers.Provider, emitter?: TLedgerServiceEmitter);
10
- connect(provider: ethers.providers.Provider): EthersLedgerSigner;
7
+ constructor(transport: Transport, bipPath: string, provider?: Provider, emitter?: TLedgerServiceEmitter);
8
+ static shouldRetry(error: any): boolean;
9
+ connect(provider: Provider): EthersLedgerSigner;
11
10
  getAddress(): Promise<string>;
12
- signMessage(message: string | ethers.utils.Bytes): Promise<string>;
13
- signTransaction(transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>): Promise<string>;
14
- _signTypedData(domain: ethers.TypedDataDomain, types: Record<string, ethers.TypedDataField[]>, value: Record<string, any>): Promise<string>;
11
+ signMessage(message: string | Uint8Array): Promise<string>;
12
+ signTransaction(transaction: Transaction | TransactionLike): Promise<string>;
13
+ signTypedData(domain: ethers.TypedDataDomain, types: Record<string, ethers.TypedDataField[]>, value: Record<string, any>): Promise<string>;
15
14
  }
16
15
  export declare class EthersLedgerServiceEthereum<N extends string> implements ILedgerService<N> {
17
16
  #private;
@@ -20,5 +19,5 @@ export declare class EthersLedgerServiceEthereum<N extends string> implements IL
20
19
  constructor(blockchainService: BSEthereum<N>, getLedgerTransport?: TGetLedgerTransport<N>);
21
20
  getAccounts(transport: Transport, untilIndexByBlockchainService?: TUntilIndexRecord<N>): Promise<TBSAccount<N>[]>;
22
21
  getAccount(transport: Transport, index: number): Promise<TBSAccount<N>>;
23
- getSigner(transport: Transport, path: string, provider?: ethers.providers.Provider): EthersLedgerSigner;
22
+ getSigner(transport: Transport, path: string, provider?: Provider): EthersLedgerSigner;
24
23
  }
@@ -54,9 +54,12 @@ const hw_app_eth_1 = __importStar(require("@ledgerhq/hw-app-eth"));
54
54
  const ethers_1 = require("ethers");
55
55
  const properties_1 = require("@ethersproject/properties");
56
56
  const events_1 = __importDefault(require("events"));
57
- class EthersLedgerSigner extends ethers_1.Signer {
57
+ const ensure0x = (value) => {
58
+ return value.startsWith('0x') ? value : `0x${value}`;
59
+ };
60
+ class EthersLedgerSigner extends ethers_1.AbstractSigner {
58
61
  constructor(transport, bipPath, provider, emitter) {
59
- super();
62
+ super(provider);
60
63
  _EthersLedgerSigner_transport.set(this, void 0);
61
64
  _EthersLedgerSigner_emitter.set(this, void 0);
62
65
  _EthersLedgerSigner_bipPath.set(this, void 0);
@@ -65,7 +68,11 @@ class EthersLedgerSigner extends ethers_1.Signer {
65
68
  __classPrivateFieldSet(this, _EthersLedgerSigner_transport, transport, "f");
66
69
  __classPrivateFieldSet(this, _EthersLedgerSigner_emitter, emitter, "f");
67
70
  __classPrivateFieldSet(this, _EthersLedgerSigner_ledgerApp, new hw_app_eth_1.default(transport), "f");
68
- (0, properties_1.defineReadOnly)(this, 'provider', provider);
71
+ if (provider)
72
+ (0, properties_1.defineReadOnly)(this, 'provider', provider);
73
+ }
74
+ static shouldRetry(error) {
75
+ return error?.id === 'TransportLocked';
69
76
  }
70
77
  connect(provider) {
71
78
  return new EthersLedgerSigner(__classPrivateFieldGet(this, _EthersLedgerSigner_transport, "f"), __classPrivateFieldGet(this, _EthersLedgerSigner_bipPath, "f"), provider, __classPrivateFieldGet(this, _EthersLedgerSigner_emitter, "f"));
@@ -79,15 +86,14 @@ class EthersLedgerSigner extends ethers_1.Signer {
79
86
  async signMessage(message) {
80
87
  try {
81
88
  if (typeof message === 'string') {
82
- message = ethers_1.ethers.utils.toUtf8Bytes(message);
89
+ message = (0, ethers_1.toUtf8Bytes)(message);
83
90
  }
84
91
  __classPrivateFieldGet(this, _EthersLedgerSigner_emitter, "f")?.emit('getSignatureStart');
85
- const obj = await __classPrivateFieldGet(this, _EthersLedgerSigner_ledgerApp, "f").signPersonalMessage(__classPrivateFieldGet(this, _EthersLedgerSigner_bipPath, "f"), ethers_1.ethers.utils.hexlify(message).substring(2));
92
+ const signature = await __classPrivateFieldGet(this, _EthersLedgerSigner_ledgerApp, "f").signPersonalMessage(__classPrivateFieldGet(this, _EthersLedgerSigner_bipPath, "f"), (0, ethers_1.hexlify)(message).substring(2));
86
93
  __classPrivateFieldGet(this, _EthersLedgerSigner_emitter, "f")?.emit('getSignatureEnd');
87
- // Normalize the signature for Ethers
88
- obj.r = '0x' + obj.r;
89
- obj.s = '0x' + obj.s;
90
- return ethers_1.ethers.utils.joinSignature(obj);
94
+ signature.r = ensure0x(signature.r);
95
+ signature.s = ensure0x(signature.s);
96
+ return ethers_1.Signature.from(signature).serialized;
91
97
  }
92
98
  catch (error) {
93
99
  __classPrivateFieldGet(this, _EthersLedgerSigner_emitter, "f")?.emit('getSignatureEnd');
@@ -96,28 +102,29 @@ class EthersLedgerSigner extends ethers_1.Signer {
96
102
  }
97
103
  async signTransaction(transaction) {
98
104
  try {
99
- const tx = await ethers_1.ethers.utils.resolveProperties(transaction);
100
- const serializedUnsignedTransaction = ethers_1.ethers.utils
101
- .serializeTransaction(tx)
102
- .substring(2);
105
+ const { from: _from, ...transactionRecord } = transaction instanceof ethers_1.Transaction ? transaction.toJSON() : transaction;
106
+ const serializedUnsignedTransaction = ethers_1.Transaction.from(transactionRecord).unsignedSerialized.substring(2);
103
107
  const resolution = await hw_app_eth_1.ledgerService.resolveTransaction(serializedUnsignedTransaction, {}, {});
104
108
  __classPrivateFieldGet(this, _EthersLedgerSigner_emitter, "f")?.emit('getSignatureStart');
105
109
  const signature = await __classPrivateFieldGet(this, _EthersLedgerSigner_ledgerApp, "f").signTransaction(__classPrivateFieldGet(this, _EthersLedgerSigner_bipPath, "f"), serializedUnsignedTransaction, resolution);
106
110
  __classPrivateFieldGet(this, _EthersLedgerSigner_emitter, "f")?.emit('getSignatureEnd');
107
- return ethers_1.ethers.utils.serializeTransaction(tx, {
108
- v: blockchain_service_1.BSBigNumber.ensureNumber('0x' + signature.v),
109
- r: '0x' + signature.r,
110
- s: '0x' + signature.s,
111
- });
111
+ return ethers_1.Transaction.from({
112
+ ...transactionRecord,
113
+ signature: {
114
+ v: blockchain_service_1.BSBigNumber.ensureNumber(ensure0x(signature.v)),
115
+ r: ensure0x(signature.r),
116
+ s: ensure0x(signature.s),
117
+ },
118
+ }).serialized;
112
119
  }
113
120
  catch (error) {
114
121
  __classPrivateFieldGet(this, _EthersLedgerSigner_emitter, "f")?.emit('getSignatureEnd');
115
122
  throw error;
116
123
  }
117
124
  }
118
- async _signTypedData(domain, types, value) {
125
+ async signTypedData(domain, types, value) {
119
126
  try {
120
- const populated = await ethers_1.ethers.utils._TypedDataEncoder.resolveNames(domain, types, value, async (name) => {
127
+ const populated = await ethers_1.TypedDataEncoder.resolveNames(domain, types, value, async (name) => {
121
128
  if (!this.provider)
122
129
  throw new Error('Cannot resolve ENS names without a provider');
123
130
  const resolved = await this.provider.resolveName(name);
@@ -125,22 +132,21 @@ class EthersLedgerSigner extends ethers_1.Signer {
125
132
  throw new Error('No address found for domain name');
126
133
  return resolved;
127
134
  });
128
- const payload = ethers_1.ethers.utils._TypedDataEncoder.getPayload(populated.domain, types, populated.value);
135
+ const payload = ethers_1.TypedDataEncoder.getPayload(populated.domain, types, populated.value);
129
136
  __classPrivateFieldGet(this, _EthersLedgerSigner_emitter, "f")?.emit('getSignatureStart');
130
- let obj;
137
+ let signature;
131
138
  try {
132
- obj = await __classPrivateFieldGet(this, _EthersLedgerSigner_ledgerApp, "f").signEIP712Message(__classPrivateFieldGet(this, _EthersLedgerSigner_bipPath, "f"), payload);
139
+ signature = await __classPrivateFieldGet(this, _EthersLedgerSigner_ledgerApp, "f").signEIP712Message(__classPrivateFieldGet(this, _EthersLedgerSigner_bipPath, "f"), payload);
133
140
  }
134
141
  catch {
135
- const domainSeparatorHex = ethers_1.ethers.utils._TypedDataEncoder.hashDomain(payload.domain);
136
- const hashStructMessageHex = ethers_1.ethers.utils._TypedDataEncoder.hashStruct(payload.primaryType, types, payload.message);
137
- obj = await __classPrivateFieldGet(this, _EthersLedgerSigner_ledgerApp, "f").signEIP712HashedMessage(__classPrivateFieldGet(this, _EthersLedgerSigner_bipPath, "f"), domainSeparatorHex, hashStructMessageHex);
142
+ const domainSeparatorHex = ethers_1.TypedDataEncoder.hashDomain(payload.domain);
143
+ const hashStructMessageHex = ethers_1.TypedDataEncoder.hashStruct(payload.primaryType, types, payload.message);
144
+ signature = await __classPrivateFieldGet(this, _EthersLedgerSigner_ledgerApp, "f").signEIP712HashedMessage(__classPrivateFieldGet(this, _EthersLedgerSigner_bipPath, "f"), domainSeparatorHex, hashStructMessageHex);
138
145
  }
139
146
  __classPrivateFieldGet(this, _EthersLedgerSigner_emitter, "f")?.emit('getSignatureEnd');
140
- // Normalize the signature for Ethers
141
- obj.r = '0x' + obj.r;
142
- obj.s = '0x' + obj.s;
143
- return ethers_1.ethers.utils.joinSignature(obj);
147
+ signature.r = ensure0x(signature.r);
148
+ signature.s = ensure0x(signature.s);
149
+ return ethers_1.Signature.from(signature).serialized;
144
150
  }
145
151
  catch (error) {
146
152
  __classPrivateFieldGet(this, _EthersLedgerSigner_emitter, "f")?.emit('getSignatureEnd');
@@ -150,9 +156,6 @@ class EthersLedgerSigner extends ethers_1.Signer {
150
156
  }
151
157
  exports.EthersLedgerSigner = EthersLedgerSigner;
152
158
  _EthersLedgerSigner_transport = new WeakMap(), _EthersLedgerSigner_emitter = new WeakMap(), _EthersLedgerSigner_bipPath = new WeakMap(), _EthersLedgerSigner_ledgerApp = new WeakMap();
153
- EthersLedgerSigner.shouldRetry = (error) => {
154
- return error?.id === 'TransportLocked';
155
- };
156
159
  class EthersLedgerServiceEthereum {
157
160
  constructor(blockchainService, getLedgerTransport) {
158
161
  _EthersLedgerServiceEthereum_blockchainService.set(this, void 0);
@@ -173,7 +176,7 @@ class EthersLedgerServiceEthereum {
173
176
  const { publicKey, address } = await blockchain_service_1.BSUtilsHelper.retry(() => ledgerApp.getAddress(bipPath), {
174
177
  shouldRetry: EthersLedgerSigner.shouldRetry,
175
178
  });
176
- const publicKeyWithPrefix = '0x' + publicKey;
179
+ const publicKeyWithPrefix = ensure0x(publicKey);
177
180
  return {
178
181
  address,
179
182
  key: publicKeyWithPrefix,
@@ -12,7 +12,7 @@ class GhostMarketNDSEthereum extends blockchain_service_1.GhostMarketNDS {
12
12
  try {
13
13
  if (!collectionHash)
14
14
  return false;
15
- const provider = new ethers_1.ethers.providers.JsonRpcProvider(this._service.network.url);
15
+ const provider = new ethers_1.JsonRpcProvider(this._service.network.url);
16
16
  const contract = new ethers_1.ethers.Contract(collectionHash, ERC20_1.ERC20_ABI, provider);
17
17
  const response = await contract.balanceOf(address);
18
18
  if (!response)
@@ -7,7 +7,7 @@ class TokenServiceEthereum extends blockchain_service_1.TokenService {
7
7
  normalizeHash(hash) {
8
8
  let fixedHash = hash.startsWith('0x') ? hash : `0x${hash}`;
9
9
  try {
10
- fixedHash = ethers_1.ethers.utils.getAddress(fixedHash); // Normalize to checksum address
10
+ fixedHash = (0, ethers_1.getAddress)(fixedHash); // Normalize to checksum address
11
11
  }
12
12
  catch {
13
13
  /* empty */
@@ -1,7 +1,7 @@
1
1
  import { type IWalletConnectService, type TBSNetworkId, type TWalletConnectServiceHandlers, type TWalletConnectServiceMethodHandler, type TWalletConnectServiceRequestMethodParams } from '@cityofzion/blockchain-service';
2
2
  import type { IBSEthereum, TWalletConnectServiceEthereumMethod } from '../../types';
3
3
  import { z } from 'zod';
4
- import { ethers } from 'ethers';
4
+ import { type TransactionRequest } from 'ethers';
5
5
  declare const personalSignParamsSchema: z.ZodTuple<[z.ZodString, z.ZodString], null>;
6
6
  declare const signTypedDataParamsSchema: z.ZodTuple<[z.ZodString, z.ZodUnion<readonly [z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<any, string>>, z.ZodObject<{
7
7
  primaryType: z.ZodString;
@@ -35,7 +35,7 @@ declare const signTransactionParamsSchema: z.ZodTuple<[z.ZodObject<{
35
35
  gas: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
36
36
  maxPriorityFeePerGas: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
37
37
  maxFeePerGas: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
38
- nonce: z.ZodOptional<z.ZodNumber>;
38
+ nonce: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
39
39
  chainId: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
40
40
  gasLimit: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
41
41
  type: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
@@ -61,7 +61,6 @@ export type TWalletConnectEthereumHandlers = {
61
61
  wallet_requestPermissions: unknown;
62
62
  };
63
63
  export declare class WalletConnectServiceEthereum<N extends string, A extends TBSNetworkId, M extends string = TWalletConnectServiceEthereumMethod, H extends Record<string, any> = TWalletConnectEthereumHandlers> implements IWalletConnectService<N, M> {
64
- #private;
65
64
  readonly namespace: string;
66
65
  readonly chain: string;
67
66
  supportedMethods: M[];
@@ -80,9 +79,10 @@ export declare class WalletConnectServiceEthereum<N extends string, A extends TB
80
79
  _requestAccount: TWalletConnectServiceMethodHandler<N>;
81
80
  _nullHandlers: TWalletConnectServiceMethodHandler<N>;
82
81
  _emptyHandlers: TWalletConnectServiceMethodHandler<N>;
82
+ _convertHexToUtf8(value: string): string;
83
83
  _resolveTransactionParams(args: TWalletConnectServiceRequestMethodParams<N, z.infer<typeof signTransactionParamsSchema>>): Promise<{
84
- connectedWallet: ethers.Signer;
85
- transaction: ethers.providers.TransactionRequest;
84
+ connectedWallet: import("ethers").Signer;
85
+ transaction: TransactionRequest;
86
86
  }>;
87
87
  calculateRequestFee(args: TWalletConnectServiceRequestMethodParams<N>): Promise<string>;
88
88
  }
@@ -1,17 +1,10 @@
1
1
  "use strict";
2
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
- };
7
- var _WalletConnectServiceEthereum_instances, _WalletConnectServiceEthereum_convertHexToUtf8;
8
2
  Object.defineProperty(exports, "__esModule", { value: true });
9
3
  exports.WalletConnectServiceEthereum = void 0;
10
4
  const blockchain_service_1 = require("@cityofzion/blockchain-service");
11
5
  const zod_1 = require("zod");
12
6
  const ethers_1 = require("ethers");
13
7
  const BSEthereumConstants_1 = require("../../constants/BSEthereumConstants");
14
- const utils_1 = require("ethers/lib/utils");
15
8
  const personalSignParamsSchema = zod_1.z.tuple([zod_1.z.string(), zod_1.z.string()]);
16
9
  const typedDataParamSchema = zod_1.z.object({
17
10
  primaryType: zod_1.z.string(),
@@ -50,7 +43,7 @@ const signTransactionParamsSchema = zod_1.z.tuple([
50
43
  gas: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
51
44
  maxPriorityFeePerGas: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
52
45
  maxFeePerGas: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
53
- nonce: zod_1.z.number().optional(),
46
+ nonce: zod_1.z.union([zod_1.z.number(), zod_1.z.string()]).optional(),
54
47
  chainId: zod_1.z.union([zod_1.z.number(), zod_1.z.string()]).optional(),
55
48
  gasLimit: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
56
49
  type: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
@@ -60,7 +53,6 @@ const signTransactionParamsSchema = zod_1.z.tuple([
60
53
  const sendRawTransactionParamsSchema = zod_1.z.tuple([zod_1.z.string()]);
61
54
  class WalletConnectServiceEthereum {
62
55
  constructor(service) {
63
- _WalletConnectServiceEthereum_instances.add(this);
64
56
  this.namespace = 'eip155';
65
57
  // prettier-ignore
66
58
  this.supportedMethods = [
@@ -79,19 +71,19 @@ class WalletConnectServiceEthereum {
79
71
  this._personalSignHandler = {
80
72
  validate: async (params) => await personalSignParamsSchema.parseAsync(params),
81
73
  process: async (args) => {
82
- const wallet = await this._service._generateSigner(args.account);
83
- const convertedMessage = __classPrivateFieldGet(this, _WalletConnectServiceEthereum_instances, "m", _WalletConnectServiceEthereum_convertHexToUtf8).call(this, args.params[0]);
74
+ const wallet = await this._service._getSigner(args.account);
75
+ const convertedMessage = this._convertHexToUtf8(args.params[0]);
84
76
  return await wallet.signMessage(convertedMessage);
85
77
  },
86
78
  };
87
79
  this._signTypedDataHandlers = {
88
80
  validate: async (params) => await signTypedDataParamsSchema.parseAsync(params),
89
81
  process: async (args) => {
90
- const wallet = await this._service._generateSigner(args.account);
82
+ const wallet = await this._service._getSigner(args.account);
91
83
  const { domain, types, message } = args.params[1];
92
84
  // https://github.com/ethers-io/ethers.js/issues/687#issuecomment-714069471
93
85
  delete types?.EIP712Domain;
94
- return await wallet._signTypedData(domain, types, message);
86
+ return await wallet.signTypedData(domain, types, message);
95
87
  },
96
88
  };
97
89
  this._signTransactionHandler = {
@@ -112,8 +104,8 @@ class WalletConnectServiceEthereum {
112
104
  this._sendRawTransactionHandler = {
113
105
  validate: async (params) => await sendRawTransactionParamsSchema.parseAsync(params),
114
106
  process: async (args) => {
115
- const provider = new ethers_1.ethers.providers.JsonRpcProvider(this._service.network.url);
116
- const { hash } = await provider.sendTransaction(args.params[0]);
107
+ const provider = new ethers_1.JsonRpcProvider(this._service.network.url);
108
+ const { hash } = await provider.broadcastTransaction(args.params[0]);
117
109
  return hash;
118
110
  },
119
111
  };
@@ -127,7 +119,7 @@ class WalletConnectServiceEthereum {
127
119
  this._requestAccount = {
128
120
  validate: async () => { },
129
121
  process: async (args) => {
130
- const wallet = await this._service._generateSigner(args.account);
122
+ const wallet = await this._service._getSigner(args.account);
131
123
  return [await wallet.getAddress()];
132
124
  },
133
125
  };
@@ -164,20 +156,31 @@ class WalletConnectServiceEthereum {
164
156
  wallet_requestPermissions: this._emptyHandlers,
165
157
  };
166
158
  }
159
+ _convertHexToUtf8(value) {
160
+ if ((0, ethers_1.isHexString)(value)) {
161
+ return (0, ethers_1.toUtf8String)(value);
162
+ }
163
+ return value;
164
+ }
167
165
  async _resolveTransactionParams(args) {
168
166
  const params = args.params[0];
169
- const provider = new ethers_1.ethers.providers.JsonRpcProvider(this._service.network.url);
170
- const wallet = await this._service._generateSigner(args.account);
167
+ const provider = new ethers_1.JsonRpcProvider(this._service.network.url);
168
+ const wallet = await this._service._getSigner(args.account);
171
169
  const connectedWallet = wallet.connect(provider);
172
170
  const transaction = {
173
171
  to: params.to,
174
172
  value: params.value,
175
173
  data: params.data,
176
174
  };
177
- transaction.chainId = parseInt(params.chainId?.toString() ?? this._service.network.id);
178
- transaction.nonce = params.nonce;
179
- if (!transaction.nonce) {
180
- transaction.nonce = await connectedWallet.getTransactionCount('pending');
175
+ transaction.chainId = parseInt(params.chainId?.toString() || this._service.network.id);
176
+ if (typeof params.nonce === 'string') {
177
+ const nonce = parseInt(params.nonce);
178
+ if (!isNaN(nonce)) {
179
+ transaction.nonce = nonce;
180
+ }
181
+ }
182
+ if (typeof transaction.nonce !== 'number' || isNaN(transaction.nonce)) {
183
+ transaction.nonce = await connectedWallet.getNonce('pending');
181
184
  }
182
185
  if (params.type) {
183
186
  const typeAsNumber = parseInt(params.type.toString());
@@ -189,7 +192,7 @@ class WalletConnectServiceEthereum {
189
192
  transaction.maxFeePerGas = params.maxFeePerGas;
190
193
  transaction.maxPriorityFeePerGas = params.maxPriorityFeePerGas;
191
194
  if (!transaction.maxFeePerGas || !transaction.maxPriorityFeePerGas) {
192
- const feeData = await connectedWallet.getFeeData();
195
+ const feeData = await provider.getFeeData();
193
196
  transaction.maxFeePerGas = transaction.maxFeePerGas ?? feeData.maxFeePerGas ?? undefined;
194
197
  transaction.maxPriorityFeePerGas = transaction.maxPriorityFeePerGas ?? feeData.maxPriorityFeePerGas ?? undefined;
195
198
  }
@@ -197,20 +200,19 @@ class WalletConnectServiceEthereum {
197
200
  else {
198
201
  transaction.gasPrice = params.gasPrice?.toString();
199
202
  if (!transaction.gasPrice) {
200
- const gasPrice = await provider.getGasPrice();
201
- transaction.gasPrice = gasPrice;
203
+ const { gasPrice } = await provider.getFeeData();
204
+ transaction.gasPrice = gasPrice?.toString();
202
205
  }
203
206
  }
204
207
  transaction.gasLimit = params.gasLimit ?? params.gas;
205
208
  if (!transaction.gasLimit) {
206
209
  try {
207
- const estimatedGas = await connectedWallet.estimateGas({
210
+ transaction.gasLimit = await connectedWallet.estimateGas({
208
211
  ...transaction,
209
212
  gasPrice: undefined,
210
213
  maxFeePerGas: undefined,
211
214
  maxPriorityFeePerGas: undefined,
212
215
  });
213
- transaction.gasLimit = estimatedGas;
214
216
  }
215
217
  catch {
216
218
  transaction.gasLimit = BSEthereumConstants_1.BSEthereumConstants.DEFAULT_GAS_LIMIT_BN.toString();
@@ -231,26 +233,19 @@ class WalletConnectServiceEthereum {
231
233
  const params = await this._sendRawTransactionHandler.validate(args.params).catch(error => {
232
234
  throw new blockchain_service_1.BSError('Params validation failed: ' + error.message, 'INVALID_PARAMS');
233
235
  });
234
- transactionToEstimate = (0, utils_1.parseTransaction)(params[0]);
236
+ transactionToEstimate = ethers_1.Transaction.from(params[0]);
235
237
  }
236
238
  else {
237
239
  throw new blockchain_service_1.BSError(`Method ${args.method} is not supported for fee calculation`, 'UNSUPPORTED_METHOD');
238
240
  }
239
- const provider = new ethers_1.ethers.providers.JsonRpcProvider(this._service.network.url);
240
- const wallet = await this._service._generateSigner(args.account);
241
+ const provider = new ethers_1.JsonRpcProvider(this._service.network.url);
242
+ const wallet = await this._service._getSigner(args.account);
241
243
  const connectedWallet = wallet.connect(provider);
242
- const gasPrice = await connectedWallet.getGasPrice();
243
- const gasPriceBn = new blockchain_service_1.BSBigUnitAmount(gasPrice.toString(), this._service.feeToken.decimals);
244
+ const { gasPrice } = await provider.getFeeData();
245
+ const gasPriceBn = new blockchain_service_1.BSBigUnitAmount(gasPrice?.toString() || '0', this._service.feeToken.decimals);
244
246
  const estimatedGas = await connectedWallet.estimateGas(transactionToEstimate);
245
247
  const estimatedGasBn = new blockchain_service_1.BSBigUnitAmount(estimatedGas.toString(), this._service.feeToken.decimals);
246
- const feeFormatted = gasPriceBn.multipliedBy(estimatedGasBn).toHuman().toFormatted();
247
- return feeFormatted;
248
+ return gasPriceBn.multipliedBy(estimatedGasBn).toHuman().toFormatted();
248
249
  }
249
250
  }
250
251
  exports.WalletConnectServiceEthereum = WalletConnectServiceEthereum;
251
- _WalletConnectServiceEthereum_instances = new WeakSet(), _WalletConnectServiceEthereum_convertHexToUtf8 = function _WalletConnectServiceEthereum_convertHexToUtf8(value) {
252
- if (ethers_1.ethers.utils.isHexString(value)) {
253
- return ethers_1.ethers.utils.toUtf8String(value);
254
- }
255
- return value;
256
- };
package/dist/types.d.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import type { IBlockchainService, IBSWithEncryption, IBSWithExplorer, IBSWithFee, IBSWithLedger, IBSWithNameService, IBSWithNft, IBSWithWalletConnect, TBSAccount, TBSNetworkId, IBSWithFullTransactions } from '@cityofzion/blockchain-service';
2
- import { TypedDataSigner } from '@ethersproject/abstract-signer';
3
- import { ethers } from 'ethers';
2
+ import { type Signer } from 'ethers';
4
3
  export type TBSEthereumNetworkId = TBSNetworkId<'1' | '10' | '25' | '56' | '137' | '250' | '1101' | '8453' | '80002' | '42161' | '42220' | '43114' | '59144' | '11155111'>;
5
4
  export type TBSEthereumName = 'ethereum' | 'polygon' | 'base' | 'arbitrum';
6
5
  export interface IBSEthereum<N extends string = TBSEthereumName, A extends TBSNetworkId = TBSEthereumNetworkId> extends IBlockchainService<N, A>, IBSWithNameService, IBSWithNft, IBSWithFee<N>, IBSWithLedger<N>, IBSWithExplorer, IBSWithEncryption<N>, IBSWithWalletConnect<N>, IBSWithFullTransactions<N> {
7
- _generateSigner(account: TBSAccount<N>): Promise<ethers.Signer & TypedDataSigner>;
6
+ _getSigner(account: TBSAccount<N>): Promise<Signer>;
8
7
  }
9
8
  export type TMoralisBDSEthereumNativeBalanceApiResponse = {
10
9
  balance: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cityofzion/bs-ethereum",
3
- "version": "3.1.17",
3
+ "version": "3.1.18",
4
4
  "repository": "https://github.com/CityOfZion/blockchain-services",
5
5
  "license": "GPL-3.0-only",
6
6
  "author": "Coz",
@@ -16,20 +16,21 @@
16
16
  "@ethersproject/bytes": "5.8.0",
17
17
  "@ethersproject/json-wallets": "5.8.0",
18
18
  "@ethersproject/properties": "5.8.0",
19
- "@ledgerhq/hw-app-eth": "~7.3.0",
20
- "axios": "~1.15.0",
21
- "ethers": "5.8.0",
22
- "zod": "~4.3.6",
23
- "@cityofzion/blockchain-service": "3.1.17"
19
+ "@ledgerhq/hw-app-eth": "~7.8.1",
20
+ "axios": "1.16.0",
21
+ "ethers": "6.16.0",
22
+ "zod": "~4.4.3",
23
+ "@cityofzion/blockchain-service": "3.1.18"
24
24
  },
25
25
  "devDependencies": {
26
- "@ledgerhq/hw-transport": "~6.32.0",
27
- "@ledgerhq/hw-transport-node-hid": "~6.30.0",
26
+ "@ledgerhq/hw-transport": "6.35.1",
27
+ "@ledgerhq/hw-transport-node-hid": "~6.33.1",
28
+ "@types/node": "~25.6.0",
28
29
  "date-fns": "~4.1.0",
29
- "dotenv": "~17.3.1",
30
- "eslint": "~9.37.0",
31
- "typescript": "~5.9.2",
32
- "vitest": "~4.0.18"
30
+ "dotenv": "~17.4.2",
31
+ "eslint": "~10.3.0",
32
+ "typescript": "~6.0.3",
33
+ "vitest": "~4.1.5"
33
34
  },
34
35
  "scripts": {
35
36
  "build": "rm -rf ./dist && rm -f *.tgz && npm run typecheck && tsc --project tsconfig.build.json",