@hashgraph/hedera-wallet-connect 2.0.4-canary.a83fb1a.0 → 2.0.4-canary.d2afdf4.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 +6 -8
- package/dist/lib/dapp/DAppSigner.js +47 -4
- package/dist/lib/shared/utils.d.ts +6 -1
- package/dist/lib/shared/utils.js +39 -0
- package/dist/reown/adapter.js +1 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ read transactions. Hedera implements EVM compatible smart contracts using
|
|
|
13
13
|
[Hyperledger Besu](https://besu.hyperledger.org/) under the hood.
|
|
14
14
|
|
|
15
15
|
Ethereum developers and toolsets often expect to interact with Ethereum compatible chains using
|
|
16
|
-
the [Ethereum JSON-RPC](https://ethereum.org/en/developers/docs/apis/json-rpc/). To
|
|
16
|
+
the [Ethereum JSON-RPC](https://ethereum.org/en/developers/docs/apis/json-rpc/). To achieve
|
|
17
17
|
compatibility with this API,
|
|
18
18
|
[Hedera JSON-RPC Providers](https://docs.hedera.com/hedera/core-concepts/smart-contracts/json-rpc-relay#community-hosted-json-rpc-relays)
|
|
19
19
|
operate a software middlelayer that translates Ethereum JSON-RPC compatible API calls into
|
|
@@ -26,7 +26,7 @@ transactions to wallets over the WalletConnect network using the JSON-RPC spec d
|
|
|
26
26
|
Hedera native transactions or use Ethereum JSON-RPC calls sent to a Hedera JSON-RPC Relay
|
|
27
27
|
provider which then communicates with Hedera consensus and mirror nodes.
|
|
28
28
|
|
|
29
|
-
On a high level, JSON-RPC is a type of API
|
|
29
|
+
On a high level, JSON-RPC is a type of API structure, such as SOAP, gRPC, REST, GraphQL, etc. In
|
|
30
30
|
the Hedera ecosystem, there are distinct concepts regarding JSON-RPC APIs to consider:
|
|
31
31
|
|
|
32
32
|
- Ethereum JSON-RPC spec defines how to interact with Ethereum compatible networks
|
|
@@ -34,7 +34,7 @@ the Hedera ecosystem, there are distinct concepts regarding JSON-RPC APIs to con
|
|
|
34
34
|
- Wallets in the Hedera ecosystem also support a separate specification that defines how to send
|
|
35
35
|
transactions and messages to wallets over the WalletConnect network without relying on a
|
|
36
36
|
Hedera JSON-RPC Relay provider. This is a Hedera specific specification defined for utilizing
|
|
37
|
-
the WalletConnect network
|
|
37
|
+
the WalletConnect network distinct from other JSON-RPC specs such as the one defined by the
|
|
38
38
|
Ethereum network.
|
|
39
39
|
|
|
40
40
|
For more information see:
|
|
@@ -64,7 +64,7 @@ reviewing the [Reown docs](https://docs.reown.com/overview).
|
|
|
64
64
|
1. Add Hedera dependencies to your project:
|
|
65
65
|
|
|
66
66
|
```sh
|
|
67
|
-
npm install @hashgraph/hedera-wallet-connect
|
|
67
|
+
npm install @hashgraph/hedera-wallet-connect @hashgraph/sdk @walletconnect/modal
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
2. Initialize dApp Connector
|
|
@@ -121,7 +121,7 @@ await dAppConnector.openModal()
|
|
|
121
121
|
2. Add Hedera dependencies to your project:
|
|
122
122
|
|
|
123
123
|
```sh
|
|
124
|
-
npm install @hashgraph/hedera-wallet-connect@2.0.
|
|
124
|
+
npm install @hashgraph/hedera-wallet-connect@2.0.4-canary.3ca04e9.0 @hashgraph/sdk @walletconnect/universal-provider
|
|
125
125
|
```
|
|
126
126
|
|
|
127
127
|
3. Update `createAppKit` with adapters and a universal provider for Hedera. Note the
|
|
@@ -154,7 +154,7 @@ const hederaEVMAdapter = new HederaAdapter({
|
|
|
154
154
|
})
|
|
155
155
|
|
|
156
156
|
const universalProvider = (await HederaProvider.init({
|
|
157
|
-
projectId: "YOUR_PROJECT_ID"
|
|
157
|
+
projectId: "YOUR_PROJECT_ID",
|
|
158
158
|
metadata,
|
|
159
159
|
})) as unknown as UniversalProvider, // avoid type mismatch error due to missing of private properties in HederaProvider
|
|
160
160
|
|
|
@@ -226,12 +226,10 @@ refer to how to send transactions to wallets using the `hedera:(mainnet|testnet)
|
|
|
226
226
|
While minimal, the main breaking changes are:
|
|
227
227
|
|
|
228
228
|
- remove WalletConnect v1 modals
|
|
229
|
-
|
|
230
229
|
- these are very old, though in the spirit of semver, we kept the dependency until this
|
|
231
230
|
library's v2 release
|
|
232
231
|
|
|
233
232
|
- remove setting node id's within this library for transactions
|
|
234
|
-
|
|
235
233
|
- initially, a transaction created by the Hedera Javascript SDK needed to have one or more
|
|
236
234
|
consensus node ids set to be able to serialize into bytes, sent over a network, and
|
|
237
235
|
deserialized by the SDK
|
|
@@ -146,7 +146,15 @@ export class DAppSigner {
|
|
|
146
146
|
* @returns transaction - `Transaction` object with signature
|
|
147
147
|
*/
|
|
148
148
|
async signTransaction(transaction) {
|
|
149
|
-
|
|
149
|
+
var _a, _b;
|
|
150
|
+
// Ensure transaction is frozen with node account IDs before signing
|
|
151
|
+
// This is required so the transaction can be executed later by any client
|
|
152
|
+
if (!transaction.isFrozen()) {
|
|
153
|
+
transaction.freezeWith(this._getHederaClient());
|
|
154
|
+
}
|
|
155
|
+
// Extract the first node account ID from the frozen transaction to preserve it in the transaction body
|
|
156
|
+
const nodeAccountId = (_b = (_a = transaction.nodeAccountIds) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : null;
|
|
157
|
+
const transactionBody = transactionToTransactionBody(transaction, nodeAccountId);
|
|
150
158
|
if (!transactionBody)
|
|
151
159
|
throw new Error('Failed to serialize transaction body');
|
|
152
160
|
const transactionBodyBase64 = transactionBodyToBase64String(transactionBody);
|
|
@@ -158,9 +166,44 @@ export class DAppSigner {
|
|
|
158
166
|
},
|
|
159
167
|
});
|
|
160
168
|
const sigMap = base64StringToSignatureMap(signatureMap);
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
169
|
+
// Get the original transaction bytes to preserve the full transaction structure
|
|
170
|
+
// including all node account IDs
|
|
171
|
+
const originalTransactionBytes = transaction.toBytes();
|
|
172
|
+
const originalTransactionList = proto.TransactionList.decode(originalTransactionBytes);
|
|
173
|
+
// Add the signature to all transactions in the list
|
|
174
|
+
// Each transaction in the list corresponds to a different node
|
|
175
|
+
const signedTransactionList = originalTransactionList.transactionList.map((tx) => {
|
|
176
|
+
// Check if the transaction has signedTransactionBytes (frozen transactions)
|
|
177
|
+
if (tx.signedTransactionBytes) {
|
|
178
|
+
// Decode the SignedTransaction to access the bodyBytes and existing sigMap
|
|
179
|
+
const signedTx = proto.SignedTransaction.decode(tx.signedTransactionBytes);
|
|
180
|
+
const existingSigMap = signedTx.sigMap || proto.SignatureMap.create({});
|
|
181
|
+
// Merge the new signatures with existing signatures
|
|
182
|
+
const mergedSigPairs = [...(existingSigMap.sigPair || []), ...(sigMap.sigPair || [])];
|
|
183
|
+
// Create updated SignedTransaction with merged signatures
|
|
184
|
+
const updatedSignedTx = proto.SignedTransaction.encode({
|
|
185
|
+
bodyBytes: signedTx.bodyBytes,
|
|
186
|
+
sigMap: proto.SignatureMap.create({
|
|
187
|
+
sigPair: mergedSigPairs,
|
|
188
|
+
}),
|
|
189
|
+
}).finish();
|
|
190
|
+
return {
|
|
191
|
+
signedTransactionBytes: updatedSignedTx,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
// Transaction has bodyBytes and sigMap at the top level (not frozen)
|
|
196
|
+
const existingSigMap = tx.sigMap || proto.SignatureMap.create({});
|
|
197
|
+
// Merge the new signatures with existing signatures
|
|
198
|
+
const mergedSigPairs = [...(existingSigMap.sigPair || []), ...(sigMap.sigPair || [])];
|
|
199
|
+
return Object.assign(Object.assign({}, tx), { sigMap: Object.assign(Object.assign({}, existingSigMap), { sigPair: mergedSigPairs }) });
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
// Encode the signed transaction list back to bytes
|
|
203
|
+
const signedBytes = proto.TransactionList.encode({
|
|
204
|
+
transactionList: signedTransactionList,
|
|
205
|
+
}).finish();
|
|
206
|
+
return Transaction.fromBytes(signedBytes);
|
|
164
207
|
}
|
|
165
208
|
async _tryExecuteTransactionRequest(request) {
|
|
166
209
|
try {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AccountId, PublicKey, Transaction, LedgerId, Query, SignerSignature } from '@hashgraph/sdk';
|
|
1
|
+
import { AccountId, PublicKey, PrivateKey, Transaction, LedgerId, Query, SignerSignature } from '@hashgraph/sdk';
|
|
2
2
|
import { ProposalTypes, SessionTypes } from '@walletconnect/types';
|
|
3
3
|
import { proto } from '@hashgraph/proto';
|
|
4
4
|
/**
|
|
@@ -273,3 +273,8 @@ export declare const accountAndLedgerFromSession: (session: SessionTypes.Struct)
|
|
|
273
273
|
network: LedgerId;
|
|
274
274
|
account: AccountId;
|
|
275
275
|
}[];
|
|
276
|
+
/**
|
|
277
|
+
* Adds an additional signature to an already-signed transaction.
|
|
278
|
+
* Uses proto-level manipulation to preserve existing signatures.
|
|
279
|
+
*/
|
|
280
|
+
export declare function addSignatureToTransaction<T extends Transaction>(transaction: T, privateKey: PrivateKey): Promise<T>;
|
package/dist/lib/shared/utils.js
CHANGED
|
@@ -418,3 +418,42 @@ export const accountAndLedgerFromSession = (session) => {
|
|
|
418
418
|
};
|
|
419
419
|
});
|
|
420
420
|
};
|
|
421
|
+
/**
|
|
422
|
+
* Adds an additional signature to an already-signed transaction.
|
|
423
|
+
* Uses proto-level manipulation to preserve existing signatures.
|
|
424
|
+
*/
|
|
425
|
+
export async function addSignatureToTransaction(transaction, privateKey) {
|
|
426
|
+
const originalBytes = transaction.toBytes();
|
|
427
|
+
const originalList = proto.TransactionList.decode(originalBytes);
|
|
428
|
+
const firstTransaction = originalList.transactionList[0];
|
|
429
|
+
let bodyBytes;
|
|
430
|
+
if (firstTransaction.signedTransactionBytes) {
|
|
431
|
+
const signedTx = proto.SignedTransaction.decode(firstTransaction.signedTransactionBytes);
|
|
432
|
+
bodyBytes = signedTx.bodyBytes;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
bodyBytes = firstTransaction.bodyBytes;
|
|
436
|
+
}
|
|
437
|
+
const signature = await privateKey.sign(bodyBytes);
|
|
438
|
+
const publicKey = privateKey.publicKey;
|
|
439
|
+
const signedTransactionList = originalList.transactionList.map((tx) => {
|
|
440
|
+
const newSigPair = publicKey._toProtobufSignature(signature);
|
|
441
|
+
if (tx.signedTransactionBytes) {
|
|
442
|
+
const signedTx = proto.SignedTransaction.decode(tx.signedTransactionBytes);
|
|
443
|
+
const existingSigMap = signedTx.sigMap || proto.SignatureMap.create({});
|
|
444
|
+
const mergedSigPairs = [...(existingSigMap.sigPair || []), newSigPair];
|
|
445
|
+
const updatedSignedTx = proto.SignedTransaction.encode({
|
|
446
|
+
bodyBytes: signedTx.bodyBytes,
|
|
447
|
+
sigMap: proto.SignatureMap.create({ sigPair: mergedSigPairs }),
|
|
448
|
+
}).finish();
|
|
449
|
+
return { signedTransactionBytes: updatedSignedTx };
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
const existingSigMap = tx.sigMap || proto.SignatureMap.create({});
|
|
453
|
+
const mergedSigPairs = [...(existingSigMap.sigPair || []), newSigPair];
|
|
454
|
+
return Object.assign(Object.assign({}, tx), { sigMap: Object.assign(Object.assign({}, existingSigMap), { sigPair: mergedSigPairs }) });
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
const signedBytes = proto.TransactionList.encode({ transactionList: signedTransactionList }).finish();
|
|
458
|
+
return Transaction.fromBytes(signedBytes);
|
|
459
|
+
}
|
package/dist/reown/adapter.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { CoreHelperUtil, WcHelpersUtil } from '@reown/appkit';
|
|
2
2
|
import { isReownName } from '@reown/appkit-common';
|
|
3
3
|
import { AdapterBlueprint } from '@reown/appkit/adapters';
|
|
4
|
-
import { ProviderUtil } from '@reown/appkit/store';
|
|
5
4
|
import { LedgerId } from '@hashgraph/sdk';
|
|
6
5
|
import { BrowserProvider, Contract, formatUnits, JsonRpcSigner, parseUnits } from 'ethers';
|
|
7
6
|
import { HederaConnector } from './connectors';
|
|
@@ -221,7 +220,7 @@ export class HederaAdapter extends AdapterBlueprint {
|
|
|
221
220
|
if (this.namespace !== 'eip155') {
|
|
222
221
|
throw new Error('Namespace is not eip155');
|
|
223
222
|
}
|
|
224
|
-
const provider =
|
|
223
|
+
const provider = this.provider;
|
|
225
224
|
if (!provider) {
|
|
226
225
|
throw new Error('Provider is undefined');
|
|
227
226
|
}
|
package/package.json
CHANGED