@meshconnect/uwc-injected-connector 0.11.0 → 0.12.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.
@@ -41,5 +41,13 @@ export declare class InjectedConnector implements Connector {
41
41
  * wallet_getCapabilities and the hex address format it requires.
42
42
  */
43
43
  getWalletCapabilities(from: string, networks: Network[]): Promise<Record<string, EVMCapabilities>>;
44
+ /**
45
+ * Sign serialized Solana tx bytes without broadcasting (raw bytes in/out, no
46
+ * @solana/web3.js for callers). Tries: bridge (iframe) → Wallet Standard
47
+ * feature → legacy adapter. The feature path avoids Transaction.serialize(),
48
+ * which crashes some mobile WebViews. Errors go through parseError (typed
49
+ * "rejected" on user cancel).
50
+ */
51
+ signSolanaTransactionBytes(serializedTx: Uint8Array): Promise<Uint8Array>;
44
52
  }
45
53
  //# sourceMappingURL=injected-connector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"injected-connector.d.ts","sourceRoot":"","sources":["../src/injected-connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAEP,yBAAyB,EACzB,iCAAiC,EACjC,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EAEjB,aAAa,EACb,eAAe,EACf,aAAa,EACb,cAAc,EACd,gBAAgB,EACjB,MAAM,wBAAwB,CAAA;AAY/B,qBAAa,iBAAkB,YAAW,SAAS;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,iBAAiB,CAAmB;IAC5C,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,kBAAkB,CAAoB;IAC9C,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,qBAAqB,CAAqC;gBAGhE,aAAa,GAAE,aAAkB,EACjC,eAAe,GAAE,cAAc,EAAO,EACtC,gBAAgB,CAAC,EAAE,gBAAgB;IA8BrC;;OAEG;IACG,mBAAmB,CACvB,SAAS,EAAE,SAAS,EACpB,eAAe,GAAE,cAAc,EAAO,GACrC,OAAO,CACN,yBAAyB,EAAE,GAC3B,wBAAwB,EAAE,GAC1B,sBAAsB,EAAE,GACxB,qBAAqB,EAAE,CAC1B;IAwDD;;OAEG;IACG,OAAO,CACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,yBAAyB,GAAG,iCAAiC,GACtE,OAAO,CAAC,eAAe,CAAC;IAyC3B;;OAEG;IACG,aAAa,CACjB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,yBAAyB,GAAG,iCAAiC,GACtE,OAAO,CAAC,mBAAmB,CAAC;IAI/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACG,WAAW,CACf,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,yBAAyB,GAAG,iCAAiC,GACtE,OAAO,CAAC,aAAa,CAAC;IAiFzB;;OAEG;IACG,eAAe,CACnB,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,yBAAyB,GAAG,iCAAiC,GACtE,OAAO,CAAC,iBAAiB,CAAC;IA+D7B;;;;OAIG;IACG,qBAAqB,CACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,EAAE,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAQ5C"}
1
+ {"version":3,"file":"injected-connector.d.ts","sourceRoot":"","sources":["../src/injected-connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAEP,yBAAyB,EACzB,iCAAiC,EACjC,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EAEjB,aAAa,EACb,eAAe,EACf,aAAa,EACb,cAAc,EACd,gBAAgB,EACjB,MAAM,wBAAwB,CAAA;AAkB/B,qBAAa,iBAAkB,YAAW,SAAS;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,iBAAiB,CAAmB;IAC5C,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,kBAAkB,CAAoB;IAC9C,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,qBAAqB,CAAqC;gBAGhE,aAAa,GAAE,aAAkB,EACjC,eAAe,GAAE,cAAc,EAAO,EACtC,gBAAgB,CAAC,EAAE,gBAAgB;IA8BrC;;OAEG;IACG,mBAAmB,CACvB,SAAS,EAAE,SAAS,EACpB,eAAe,GAAE,cAAc,EAAO,GACrC,OAAO,CACN,yBAAyB,EAAE,GAC3B,wBAAwB,EAAE,GAC1B,sBAAsB,EAAE,GACxB,qBAAqB,EAAE,CAC1B;IAwDD;;OAEG;IACG,OAAO,CACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,yBAAyB,GAAG,iCAAiC,GACtE,OAAO,CAAC,eAAe,CAAC;IAyC3B;;OAEG;IACG,aAAa,CACjB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,yBAAyB,GAAG,iCAAiC,GACtE,OAAO,CAAC,mBAAmB,CAAC;IAI/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACG,WAAW,CACf,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,yBAAyB,GAAG,iCAAiC,GACtE,OAAO,CAAC,aAAa,CAAC;IAiFzB;;OAEG;IACG,eAAe,CACnB,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,yBAAyB,GAAG,iCAAiC,GACtE,OAAO,CAAC,iBAAiB,CAAC;IA+D7B;;;;OAIG;IACG,qBAAqB,CACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,EAAE,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAS3C;;;;;;OAMG;IACG,0BAA0B,CAC9B,YAAY,EAAE,UAAU,GACvB,OAAO,CAAC,UAAU,CAAC;CAgGvB"}
@@ -1,3 +1,5 @@
1
+ import { assertSameMessage } from '@meshconnect/uwc-types';
2
+ import { Transaction, VersionedTransaction } from '@solana/web3.js';
1
3
  import { BridgeChild } from '@meshconnect/uwc-bridge-child';
2
4
  import { EthereumWalletService } from './services/ethereum/ethereum-wallet-service';
3
5
  import { SolanaWalletService } from './services/solana/solana-wallet-service';
@@ -7,6 +9,8 @@ import { StorageService } from './services/storage-service';
7
9
  import { ConnectionManager } from './services/connection-manager';
8
10
  import { SignatureService } from './services/signature-service';
9
11
  import { TransactionService } from './services/transaction-service';
12
+ import { parseError } from './utils/error-utils';
13
+ import { resolveSigningAccount } from './utils/solana-account-utils';
10
14
  export class InjectedConnector {
11
15
  storageService;
12
16
  ethereumService;
@@ -246,5 +250,91 @@ export class InjectedConnector {
246
250
  }
247
251
  return await this.ethereumService.getCapabilities(from, networks);
248
252
  }
253
+ /**
254
+ * Sign serialized Solana tx bytes without broadcasting (raw bytes in/out, no
255
+ * @solana/web3.js for callers). Tries: bridge (iframe) → Wallet Standard
256
+ * feature → legacy adapter. The feature path avoids Transaction.serialize(),
257
+ * which crashes some mobile WebViews. Errors go through parseError (typed
258
+ * "rejected" on user cancel).
259
+ */
260
+ async signSolanaTransactionBytes(serializedTx) {
261
+ const currentNetworkId = this.connectionManager.getCurrentNetworkId();
262
+ if (!currentNetworkId?.startsWith('solana:')) {
263
+ throw new Error('signSolanaTransactionBytes requires an active Solana connection');
264
+ }
265
+ const solanaAdapter = this.solanaService.getConnectedAdapter();
266
+ if (!solanaAdapter) {
267
+ throw new Error('No connected Solana adapter');
268
+ }
269
+ try {
270
+ // Path 1: bridge (iframe). The wallet lives on the parent; forward bytes.
271
+ // `await customFunctions` (not a truthy check) — Comlink proxies every
272
+ // property as truthy, so the awaited list is the only reliable signal.
273
+ const extendedAdapter = solanaAdapter;
274
+ const customFns = await extendedAdapter.customFunctions;
275
+ if (customFns?.includes('signSolanaTransactionBytes')) {
276
+ // Sign with the child's connected account — the parent's publicKey may
277
+ // have drifted.
278
+ const signed = await extendedAdapter.signSolanaTransactionBytes(serializedTx, this.connectionManager.getCurrentAccount() ?? undefined);
279
+ // Verify in the iframe (trusted), not on the parent, so a tampered
280
+ // parent can't bypass it. Byte-stable round-trip → safe for the bridge's
281
+ // legacy sub-path too (see the "byte-stable" test).
282
+ assertSameMessage(serializedTx, signed);
283
+ return signed;
284
+ }
285
+ // Path 2: Wallet Standard solana:signTransaction (raw bytes in/out).
286
+ const wallet = solanaAdapter.wallet;
287
+ const SIGN_TX = 'solana:signTransaction';
288
+ if (wallet && SIGN_TX in wallet.features && wallet.accounts.length > 0) {
289
+ const account = resolveSigningAccount(wallet.accounts, this.connectionManager.getCurrentAccount());
290
+ const feature = wallet.features[SIGN_TX];
291
+ const [output] = await feature.signTransaction({
292
+ account,
293
+ transaction: serializedTx
294
+ });
295
+ if (!output?.signedTransaction) {
296
+ throw new Error('Wallet returned no signed transaction');
297
+ }
298
+ // Reject a tampered message before the relay broadcasts.
299
+ assertSameMessage(serializedTx, output.signedTransaction);
300
+ return output.signedTransaction;
301
+ }
302
+ // Path 3: legacy adapter (no .wallet getter).
303
+ if (!solanaAdapter.signTransaction) {
304
+ throw new Error('Connected wallet does not support signTransaction');
305
+ }
306
+ // V0 + legacy. requireAllSignatures:false — the relay fills the fee-payer slot.
307
+ let transaction;
308
+ try {
309
+ transaction = VersionedTransaction.deserialize(serializedTx);
310
+ }
311
+ catch {
312
+ try {
313
+ transaction = Transaction.from(serializedTx);
314
+ }
315
+ catch {
316
+ throw new Error('Failed to deserialize transaction as either versioned or legacy format');
317
+ }
318
+ }
319
+ const signed = await solanaAdapter.signTransaction(transaction);
320
+ const signedBytes = signed instanceof VersionedTransaction
321
+ ? signed.serialize()
322
+ : new Uint8Array(signed.serialize({
323
+ requireAllSignatures: false,
324
+ verifySignatures: false
325
+ }));
326
+ // Same guard as Path 1/2. The deserialize→sign→reserialize round-trip is
327
+ // byte-stable (see the "byte-stable" tests), so this rejects a tampering
328
+ // adapter without false-positiving a legit sign.
329
+ assertSameMessage(serializedTx, signedBytes);
330
+ return signedBytes;
331
+ }
332
+ catch (err) {
333
+ // Normalize: turns a wallet rejection (EIP-1193 4001 / "user rejected")
334
+ // into a WalletConnectorError{ type: 'rejected' } so the Link UI can tell
335
+ // "user cancelled" apart from a real failure. parseError always throws.
336
+ throw parseError(err);
337
+ }
338
+ }
249
339
  }
250
340
  //# sourceMappingURL=injected-connector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"injected-connector.js","sourceRoot":"","sources":["../src/injected-connector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"injected-connector.js","sourceRoot":"","sources":["../src/injected-connector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Pick which wallet account signs. We must sign with the account the user
3
+ * actually connected — never guess. A wrong signer produces a useless signature
4
+ * for a payment, so we throw instead of silently falling back.
5
+ */
6
+ export declare function resolveSigningAccount<T extends {
7
+ address: string;
8
+ }>(accounts: ReadonlyArray<T>, connectedAddress: string | null | undefined): T;
9
+ //# sourceMappingURL=solana-account-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solana-account-utils.d.ts","sourceRoot":"","sources":["../../src/utils/solana-account-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EACjE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,EAC1B,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,CAAC,CAeH"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Pick which wallet account signs. We must sign with the account the user
3
+ * actually connected — never guess. A wrong signer produces a useless signature
4
+ * for a payment, so we throw instead of silently falling back.
5
+ */
6
+ export function resolveSigningAccount(accounts, connectedAddress) {
7
+ if (connectedAddress) {
8
+ const match = accounts.find(a => a.address === connectedAddress);
9
+ if (!match) {
10
+ throw new Error('Connected Solana account not found in the wallet — refusing to sign with a different account');
11
+ }
12
+ return match;
13
+ }
14
+ // No explicit selection is only safe when the wallet has exactly one account.
15
+ if (accounts.length === 1)
16
+ return accounts[0];
17
+ throw new Error('Cannot determine which Solana account to sign with — multiple accounts and none selected');
18
+ }
19
+ //# sourceMappingURL=solana-account-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solana-account-utils.js","sourceRoot":"","sources":["../../src/utils/solana-account-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAA0B,EAC1B,gBAA2C;IAE3C,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,gBAAgB,CAAC,CAAA;QAChE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CACb,8FAA8F,CAC/F,CAAA;QACH,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IACD,8EAA8E;IAC9E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC,CAAC,CAAE,CAAA;IAC9C,MAAM,IAAI,KAAK,CACb,0FAA0F,CAC3F,CAAA;AACH,CAAC"}
@@ -6,10 +6,11 @@
6
6
  import { StandardWalletAdapter } from '@solana/wallet-standard-wallet-adapter-base';
7
7
  import type { Transaction } from '@solana/web3.js';
8
8
  export interface ExtendedStandardWalletAdapter extends StandardWalletAdapter {
9
- customFunctions: ('sendSerializedTransaction' | 'signSerializedTransaction' | 'signAllSerializedTransactions')[];
9
+ customFunctions: ('sendSerializedTransaction' | 'signSerializedTransaction' | 'signAllSerializedTransactions' | 'signSolanaTransactionBytes')[];
10
10
  sendSerializedTransaction: (transaction: unknown, rpcUrl: string) => Promise<string>;
11
11
  signSerializedTransaction: (transaction: unknown) => Promise<Error | Transaction>;
12
12
  signAllSerializedTransactions: (transactions: unknown[]) => Promise<Error | Transaction[]>;
13
+ signSolanaTransactionBytes: (transaction: unknown, connectedAddress?: string) => Promise<Uint8Array>;
13
14
  }
14
15
  export type SolanaAdapter = ExtendedStandardWalletAdapter | StandardWalletAdapter;
15
16
  export interface WalletStandardInfo {
@@ -1 +1 @@
1
- {"version":3,"file":"wallet-standard-discovery.d.ts","sourceRoot":"","sources":["../src/wallet-standard-discovery.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAA;AACnF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,MAAM,WAAW,6BAA8B,SAAQ,qBAAqB;IAC1E,eAAe,EAAE,CACb,2BAA2B,GAC3B,2BAA2B,GAC3B,+BAA+B,CAClC,EAAE,CAAA;IACH,yBAAyB,EAAE,CACzB,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,MAAM,CAAC,CAAA;IACpB,yBAAyB,EAAE,CACzB,WAAW,EAAE,OAAO,KACjB,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,CAAA;IACjC,6BAA6B,EAAE,CAC7B,YAAY,EAAE,OAAO,EAAE,KACpB,OAAO,CAAC,KAAK,GAAG,WAAW,EAAE,CAAC,CAAA;CACpC;AAED,MAAM,MAAM,aAAa,GACrB,6BAA6B,GAC7B,qBAAqB,CAAA;AAEzB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,OAAO,EAAE,aAAa,GAAG,SAAS,CAAA;CACnC;AA6CD;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAwCtE"}
1
+ {"version":3,"file":"wallet-standard-discovery.d.ts","sourceRoot":"","sources":["../src/wallet-standard-discovery.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAA;AACnF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,MAAM,WAAW,6BAA8B,SAAQ,qBAAqB;IAC1E,eAAe,EAAE,CACb,2BAA2B,GAC3B,2BAA2B,GAC3B,+BAA+B,GAC/B,4BAA4B,CAC/B,EAAE,CAAA;IACH,yBAAyB,EAAE,CACzB,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,MAAM,CAAC,CAAA;IACpB,yBAAyB,EAAE,CACzB,WAAW,EAAE,OAAO,KACjB,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,CAAA;IACjC,6BAA6B,EAAE,CAC7B,YAAY,EAAE,OAAO,EAAE,KACpB,OAAO,CAAC,KAAK,GAAG,WAAW,EAAE,CAAC,CAAA;IAGnC,0BAA0B,EAAE,CAC1B,WAAW,EAAE,OAAO,EACpB,gBAAgB,CAAC,EAAE,MAAM,KACtB,OAAO,CAAC,UAAU,CAAC,CAAA;CACzB;AAED,MAAM,MAAM,aAAa,GACrB,6BAA6B,GAC7B,qBAAqB,CAAA;AAEzB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,OAAO,EAAE,aAAa,GAAG,SAAS,CAAA;CACnC;AA6CD;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAwCtE"}
@@ -1 +1 @@
1
- {"version":3,"file":"wallet-standard-discovery.js","sourceRoot":"","sources":["../src/wallet-standard-discovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wallet-standard-discovery.js","sourceRoot":"","sources":["../src/wallet-standard-discovery.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshconnect/uwc-injected-connector",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Injected connector for Universal Wallet Connector",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -28,9 +28,9 @@
28
28
  "uuid": "^13.0.0",
29
29
  "viem": "^2.44.4",
30
30
  "@meshconnect/uwc-bridge-child": "0.2.1",
31
- "@meshconnect/uwc-constants": "0.6.2",
32
- "@meshconnect/uwc-ton-connector": "0.6.0",
33
- "@meshconnect/uwc-types": "0.13.0"
31
+ "@meshconnect/uwc-constants": "0.6.3",
32
+ "@meshconnect/uwc-ton-connector": "0.6.1",
33
+ "@meshconnect/uwc-types": "0.14.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "typescript": "^5.9.3"
@@ -20,6 +20,9 @@ import type {
20
20
  WalletMetadata,
21
21
  TonConnectConfig
22
22
  } from '@meshconnect/uwc-types'
23
+ import { assertSameMessage } from '@meshconnect/uwc-types'
24
+ import { Transaction, VersionedTransaction } from '@solana/web3.js'
25
+ import type { StandardWalletAdapter } from '@solana/wallet-standard-wallet-adapter-base'
23
26
  import { BridgeChild } from '@meshconnect/uwc-bridge-child'
24
27
 
25
28
  import { EthereumWalletService } from './services/ethereum/ethereum-wallet-service'
@@ -30,6 +33,9 @@ import { StorageService } from './services/storage-service'
30
33
  import { ConnectionManager } from './services/connection-manager'
31
34
  import { SignatureService } from './services/signature-service'
32
35
  import { TransactionService } from './services/transaction-service'
36
+ import type { ExtendedStandardWalletAdapter } from './wallet-standard-discovery'
37
+ import { parseError } from './utils/error-utils'
38
+ import { resolveSigningAccount } from './utils/solana-account-utils'
33
39
 
34
40
  export class InjectedConnector implements Connector {
35
41
  private readonly storageService: StorageService
@@ -379,4 +385,110 @@ export class InjectedConnector implements Connector {
379
385
  }
380
386
  return await this.ethereumService.getCapabilities(from, networks)
381
387
  }
388
+
389
+ /**
390
+ * Sign serialized Solana tx bytes without broadcasting (raw bytes in/out, no
391
+ * @solana/web3.js for callers). Tries: bridge (iframe) → Wallet Standard
392
+ * feature → legacy adapter. The feature path avoids Transaction.serialize(),
393
+ * which crashes some mobile WebViews. Errors go through parseError (typed
394
+ * "rejected" on user cancel).
395
+ */
396
+ async signSolanaTransactionBytes(
397
+ serializedTx: Uint8Array
398
+ ): Promise<Uint8Array> {
399
+ const currentNetworkId = this.connectionManager.getCurrentNetworkId()
400
+ if (!currentNetworkId?.startsWith('solana:')) {
401
+ throw new Error(
402
+ 'signSolanaTransactionBytes requires an active Solana connection'
403
+ )
404
+ }
405
+
406
+ const solanaAdapter = this.solanaService.getConnectedAdapter()
407
+ if (!solanaAdapter) {
408
+ throw new Error('No connected Solana adapter')
409
+ }
410
+
411
+ try {
412
+ // Path 1: bridge (iframe). The wallet lives on the parent; forward bytes.
413
+ // `await customFunctions` (not a truthy check) — Comlink proxies every
414
+ // property as truthy, so the awaited list is the only reliable signal.
415
+ const extendedAdapter = solanaAdapter as ExtendedStandardWalletAdapter
416
+ const customFns = await extendedAdapter.customFunctions
417
+ if (customFns?.includes('signSolanaTransactionBytes')) {
418
+ // Sign with the child's connected account — the parent's publicKey may
419
+ // have drifted.
420
+ const signed = await extendedAdapter.signSolanaTransactionBytes(
421
+ serializedTx,
422
+ this.connectionManager.getCurrentAccount() ?? undefined
423
+ )
424
+ // Verify in the iframe (trusted), not on the parent, so a tampered
425
+ // parent can't bypass it. Byte-stable round-trip → safe for the bridge's
426
+ // legacy sub-path too (see the "byte-stable" test).
427
+ assertSameMessage(serializedTx, signed)
428
+ return signed
429
+ }
430
+
431
+ // Path 2: Wallet Standard solana:signTransaction (raw bytes in/out).
432
+ const wallet = (solanaAdapter as StandardWalletAdapter).wallet
433
+ const SIGN_TX = 'solana:signTransaction'
434
+
435
+ if (wallet && SIGN_TX in wallet.features && wallet.accounts.length > 0) {
436
+ const account = resolveSigningAccount(
437
+ wallet.accounts,
438
+ this.connectionManager.getCurrentAccount()
439
+ )
440
+ const feature = wallet.features[SIGN_TX]
441
+ const [output] = await feature.signTransaction({
442
+ account,
443
+ transaction: serializedTx
444
+ })
445
+ if (!output?.signedTransaction) {
446
+ throw new Error('Wallet returned no signed transaction')
447
+ }
448
+ // Reject a tampered message before the relay broadcasts.
449
+ assertSameMessage(serializedTx, output.signedTransaction)
450
+ return output.signedTransaction
451
+ }
452
+
453
+ // Path 3: legacy adapter (no .wallet getter).
454
+ if (!solanaAdapter.signTransaction) {
455
+ throw new Error('Connected wallet does not support signTransaction')
456
+ }
457
+
458
+ // V0 + legacy. requireAllSignatures:false — the relay fills the fee-payer slot.
459
+ let transaction: Transaction | VersionedTransaction
460
+ try {
461
+ transaction = VersionedTransaction.deserialize(serializedTx)
462
+ } catch {
463
+ try {
464
+ transaction = Transaction.from(serializedTx)
465
+ } catch {
466
+ throw new Error(
467
+ 'Failed to deserialize transaction as either versioned or legacy format'
468
+ )
469
+ }
470
+ }
471
+
472
+ const signed = await solanaAdapter.signTransaction(transaction)
473
+ const signedBytes =
474
+ signed instanceof VersionedTransaction
475
+ ? signed.serialize()
476
+ : new Uint8Array(
477
+ signed.serialize({
478
+ requireAllSignatures: false,
479
+ verifySignatures: false
480
+ })
481
+ )
482
+ // Same guard as Path 1/2. The deserialize→sign→reserialize round-trip is
483
+ // byte-stable (see the "byte-stable" tests), so this rejects a tampering
484
+ // adapter without false-positiving a legit sign.
485
+ assertSameMessage(serializedTx, signedBytes)
486
+ return signedBytes
487
+ } catch (err) {
488
+ // Normalize: turns a wallet rejection (EIP-1193 4001 / "user rejected")
489
+ // into a WalletConnectorError{ type: 'rejected' } so the Link UI can tell
490
+ // "user cancelled" apart from a real failure. parseError always throws.
491
+ throw parseError(err)
492
+ }
493
+ }
382
494
  }
@@ -0,0 +1,747 @@
1
+ // @vitest-environment node
2
+ //
3
+ // Node env: @solana/web3.js's VersionedTransaction.deserialize fails its
4
+ // `instanceof Uint8Array` check under jsdom. @vitest-environment is per-file,
5
+ // so this is a separate file from injected-connector.test.ts (jsdom).
6
+ import { describe, it, expect, beforeEach, vi } from 'vitest'
7
+ import { assertSameMessage } from '@meshconnect/uwc-types'
8
+ import { InjectedConnector } from './injected-connector'
9
+
10
+ // Mock all service dependencies — same pattern as injected-connector.test.ts
11
+ vi.mock('./services/storage-service')
12
+ vi.mock('./services/ethereum/ethereum-wallet-service')
13
+ vi.mock('./services/tron/tron-wallet-service')
14
+ vi.mock('./services/connection-manager')
15
+ vi.mock('./services/signature-service')
16
+ vi.mock('./services/transaction-service')
17
+ vi.mock('@meshconnect/uwc-bridge-child', () => ({ BridgeChild: vi.fn() }))
18
+
19
+ // SolanaWalletService needs fine-grained control — we mock at the module level
20
+ // and override getConnectedAdapter per test.
21
+ vi.mock('./services/solana/solana-wallet-service')
22
+
23
+ // Build a minimal valid serialized VersionedTransaction for deserialize tests.
24
+ // We import the real web3.js so the bytes are structurally sound.
25
+ import {
26
+ Keypair,
27
+ SystemProgram,
28
+ Transaction,
29
+ TransactionMessage,
30
+ VersionedTransaction
31
+ } from '@solana/web3.js'
32
+
33
+ const payer = Keypair.generate()
34
+ const recipient = Keypair.generate().publicKey
35
+
36
+ function buildSerializedV0Tx(): Uint8Array {
37
+ const msg = new TransactionMessage({
38
+ payerKey: payer.publicKey,
39
+ recentBlockhash: '11111111111111111111111111111111',
40
+ instructions: [
41
+ SystemProgram.transfer({
42
+ fromPubkey: payer.publicKey,
43
+ toPubkey: recipient,
44
+ lamports: 1
45
+ })
46
+ ]
47
+ }).compileToV0Message()
48
+ return new VersionedTransaction(msg).serialize()
49
+ }
50
+
51
+ // Signed bytes simulated by signing a copy of the tx with the payer key.
52
+ function buildSignedV0Bytes(): Uint8Array {
53
+ const msg = new TransactionMessage({
54
+ payerKey: payer.publicKey,
55
+ recentBlockhash: '11111111111111111111111111111111',
56
+ instructions: [
57
+ SystemProgram.transfer({
58
+ fromPubkey: payer.publicKey,
59
+ toPubkey: recipient,
60
+ lamports: 1
61
+ })
62
+ ]
63
+ }).compileToV0Message()
64
+ const tx = new VersionedTransaction(msg)
65
+ tx.sign([payer])
66
+ return tx.serialize()
67
+ }
68
+
69
+ // Same message shape as the builders above but a different transfer amount, so
70
+ // its message bytes differ — models a wallet that tampered with the request.
71
+ function buildSignedV0BytesWith(lamports: number): Uint8Array {
72
+ const msg = new TransactionMessage({
73
+ payerKey: payer.publicKey,
74
+ recentBlockhash: '11111111111111111111111111111111',
75
+ instructions: [
76
+ SystemProgram.transfer({
77
+ fromPubkey: payer.publicKey,
78
+ toPubkey: recipient,
79
+ lamports
80
+ })
81
+ ]
82
+ }).compileToV0Message()
83
+ const tx = new VersionedTransaction(msg)
84
+ tx.sign([payer])
85
+ return tx.serialize()
86
+ }
87
+
88
+ describe('InjectedConnector.signSolanaTransactionBytes', () => {
89
+ let connector: InjectedConnector
90
+ // References to the auto-mocked service instances created during construction.
91
+ let mockConnManager: ReturnType<typeof vi.fn>
92
+ let mockSolService: ReturnType<typeof vi.fn>
93
+
94
+ beforeEach(async () => {
95
+ vi.clearAllMocks()
96
+
97
+ connector = new InjectedConnector()
98
+
99
+ const { ConnectionManager } = await import('./services/connection-manager')
100
+ const { SolanaWalletService } =
101
+ await import('./services/solana/solana-wallet-service')
102
+
103
+ mockConnManager = (vi.mocked(ConnectionManager).mock.results[0] as any)
104
+ .value
105
+ mockSolService = (vi.mocked(SolanaWalletService).mock.results[0] as any)
106
+ .value
107
+
108
+ // Default: active Solana connection
109
+ mockConnManager.getCurrentNetworkId.mockReturnValue(
110
+ 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'
111
+ )
112
+ })
113
+
114
+ // ── Guard errors ──────────────────────────────────────────────────────────
115
+
116
+ it('throws when the active network is not solana', async () => {
117
+ mockConnManager.getCurrentNetworkId.mockReturnValue('eip155:1')
118
+
119
+ await expect(
120
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
121
+ ).rejects.toThrow(
122
+ 'signSolanaTransactionBytes requires an active Solana connection'
123
+ )
124
+ })
125
+
126
+ it('throws when getCurrentNetworkId returns null', async () => {
127
+ mockConnManager.getCurrentNetworkId.mockReturnValue(null)
128
+
129
+ await expect(
130
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
131
+ ).rejects.toThrow(
132
+ 'signSolanaTransactionBytes requires an active Solana connection'
133
+ )
134
+ })
135
+
136
+ it('throws when no Solana adapter is connected', async () => {
137
+ mockSolService.getConnectedAdapter.mockReturnValue(null)
138
+
139
+ await expect(
140
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
141
+ ).rejects.toThrow('No connected Solana adapter')
142
+ })
143
+
144
+ it('throws when adapter lacks signTransaction and wallet getter is absent', async () => {
145
+ // Adapter with no .wallet, no .signTransaction — unsupported wallet
146
+ mockSolService.getConnectedAdapter.mockReturnValue({
147
+ signAndSendTransaction: vi.fn()
148
+ // signTransaction intentionally absent
149
+ })
150
+
151
+ await expect(
152
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
153
+ ).rejects.toThrow('Connected wallet does not support signTransaction')
154
+ })
155
+
156
+ // ── Direct Wallet Standard feature path ──────────────────────────────────
157
+
158
+ it('calls the solana:signTransaction feature directly and returns signedTransaction bytes', async () => {
159
+ const signedBytes = buildSignedV0Bytes()
160
+ const featureSignTx = vi
161
+ .fn()
162
+ .mockResolvedValue([{ signedTransaction: signedBytes }])
163
+ const mockAccount = { address: payer.publicKey.toBase58() }
164
+ const mockWallet = {
165
+ accounts: [mockAccount],
166
+ features: {
167
+ 'solana:signTransaction': { signTransaction: featureSignTx }
168
+ }
169
+ }
170
+ // Adapter shaped as StandardWalletAdapter — exposes .wallet getter
171
+ const mockAdapter = {
172
+ wallet: mockWallet,
173
+ signTransaction: vi.fn(), // present but must NOT be called
174
+ signAndSendTransaction: vi.fn() // must NEVER be called
175
+ }
176
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
177
+
178
+ const serialized = buildSerializedV0Tx()
179
+ const result = await connector.signSolanaTransactionBytes(serialized)
180
+
181
+ expect(result).toBe(signedBytes)
182
+ expect(featureSignTx).toHaveBeenCalledOnce()
183
+ expect(featureSignTx).toHaveBeenCalledWith({
184
+ account: mockAccount,
185
+ transaction: serialized
186
+ })
187
+ })
188
+
189
+ it('SECURITY: rejects a wallet that returns a different transaction (tampered message)', async () => {
190
+ // Asked to sign lamports:1, the wallet returns a signed lamports:999 tx.
191
+ const tampered = buildSignedV0BytesWith(999)
192
+ const featureSignTx = vi
193
+ .fn()
194
+ .mockResolvedValue([{ signedTransaction: tampered }])
195
+ const mockAccount = { address: payer.publicKey.toBase58() }
196
+ const mockAdapter = {
197
+ wallet: {
198
+ accounts: [mockAccount],
199
+ features: {
200
+ 'solana:signTransaction': { signTransaction: featureSignTx }
201
+ }
202
+ },
203
+ signTransaction: vi.fn()
204
+ }
205
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
206
+
207
+ await expect(
208
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
209
+ ).rejects.toThrow('Signed transaction does not match the request')
210
+ })
211
+
212
+ it('passes the raw bytes, not a deserialized object, to the feature', async () => {
213
+ const signedBytes = buildSignedV0Bytes()
214
+ const featureSignTx = vi
215
+ .fn()
216
+ .mockResolvedValue([{ signedTransaction: signedBytes }])
217
+ const serialized = buildSerializedV0Tx()
218
+ mockSolService.getConnectedAdapter.mockReturnValue({
219
+ wallet: {
220
+ accounts: [{ address: 'any' }],
221
+ features: {
222
+ 'solana:signTransaction': { signTransaction: featureSignTx }
223
+ }
224
+ },
225
+ signTransaction: vi.fn(),
226
+ signAndSendTransaction: vi.fn()
227
+ })
228
+
229
+ await connector.signSolanaTransactionBytes(serialized)
230
+
231
+ // The argument passed to the feature must be the exact same Uint8Array reference
232
+ const callArg = featureSignTx.mock.calls[0][0]
233
+ expect(callArg.transaction).toBe(serialized)
234
+ })
235
+
236
+ // ── INVARIANT: sign-only never broadcasts ─────────────────────────────────
237
+
238
+ it('INVARIANT: signAndSendTransaction is never called on the direct-feature path', async () => {
239
+ const signedBytes = buildSignedV0Bytes()
240
+ const signAndSend = vi.fn()
241
+ mockSolService.getConnectedAdapter.mockReturnValue({
242
+ wallet: {
243
+ accounts: [{ address: 'any' }],
244
+ features: {
245
+ 'solana:signTransaction': {
246
+ signTransaction: vi
247
+ .fn()
248
+ .mockResolvedValue([{ signedTransaction: signedBytes }])
249
+ }
250
+ }
251
+ },
252
+ signTransaction: vi.fn(),
253
+ signAndSendTransaction: signAndSend
254
+ })
255
+
256
+ await connector.signSolanaTransactionBytes(buildSerializedV0Tx())
257
+
258
+ expect(signAndSend).not.toHaveBeenCalled()
259
+ })
260
+
261
+ it('surfaces a wallet rejection on the feature path as a typed "rejected" error', async () => {
262
+ // The Link UI needs to tell "user cancelled" apart from a real failure, so a
263
+ // rejection must arrive as WalletConnectorError{ type: 'rejected' } — not a
264
+ // generic Error.
265
+ mockSolService.getConnectedAdapter.mockReturnValue({
266
+ wallet: {
267
+ accounts: [{ address: 'any' }],
268
+ features: {
269
+ 'solana:signTransaction': {
270
+ signTransaction: vi
271
+ .fn()
272
+ .mockRejectedValue(new Error('user rejected'))
273
+ }
274
+ }
275
+ },
276
+ signTransaction: vi.fn(),
277
+ signAndSendTransaction: vi.fn()
278
+ })
279
+
280
+ await expect(
281
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
282
+ ).rejects.toMatchObject({ type: 'rejected', message: 'user rejected' })
283
+ })
284
+
285
+ it('falls back to direct feature path even when wallet.accounts is empty (zero-account edge)', async () => {
286
+ // accounts.length === 0 → falls through to the adapter fallback
287
+ const signedBytes = buildSignedV0Bytes()
288
+ const adapterSignTx = vi
289
+ .fn()
290
+ .mockResolvedValue(VersionedTransaction.deserialize(signedBytes))
291
+ mockSolService.getConnectedAdapter.mockReturnValue({
292
+ wallet: {
293
+ accounts: [], // empty → skip feature path
294
+ features: {
295
+ 'solana:signTransaction': {
296
+ signTransaction: vi.fn() // must NOT be called
297
+ }
298
+ }
299
+ },
300
+ signTransaction: adapterSignTx,
301
+ signAndSendTransaction: vi.fn()
302
+ })
303
+
304
+ const result = await connector.signSolanaTransactionBytes(
305
+ buildSerializedV0Tx()
306
+ )
307
+
308
+ expect(adapterSignTx).toHaveBeenCalledOnce()
309
+ expect(result).toBeInstanceOf(Uint8Array)
310
+ expect(result.length).toBeGreaterThan(0)
311
+ })
312
+
313
+ // ── Adapter fallback path ─────────────────────────────────────────────────
314
+
315
+ it('falls back to adapter.signTransaction when wallet getter is absent', async () => {
316
+ const signedBytes = buildSignedV0Bytes()
317
+ const adapterSignTx = vi
318
+ .fn()
319
+ .mockResolvedValue(VersionedTransaction.deserialize(signedBytes))
320
+ // No .wallet property at all — undefined
321
+ mockSolService.getConnectedAdapter.mockReturnValue({
322
+ wallet: undefined,
323
+ signTransaction: adapterSignTx,
324
+ signAndSendTransaction: vi.fn()
325
+ })
326
+
327
+ const result = await connector.signSolanaTransactionBytes(
328
+ buildSerializedV0Tx()
329
+ )
330
+
331
+ expect(adapterSignTx).toHaveBeenCalledOnce()
332
+ // Deserialized → re-serialized; returned bytes must be a non-empty Uint8Array
333
+ expect(result).toBeInstanceOf(Uint8Array)
334
+ expect(result.length).toBeGreaterThan(0)
335
+ })
336
+
337
+ it('falls back when wallet lacks the solana:signTransaction feature key', async () => {
338
+ const signedBytes = buildSignedV0Bytes()
339
+ const adapterSignTx = vi
340
+ .fn()
341
+ .mockResolvedValue(VersionedTransaction.deserialize(signedBytes))
342
+ mockSolService.getConnectedAdapter.mockReturnValue({
343
+ wallet: {
344
+ accounts: [{ address: 'any' }],
345
+ features: {} // key absent
346
+ },
347
+ signTransaction: adapterSignTx,
348
+ signAndSendTransaction: vi.fn()
349
+ })
350
+
351
+ await connector.signSolanaTransactionBytes(buildSerializedV0Tx())
352
+
353
+ expect(adapterSignTx).toHaveBeenCalledOnce()
354
+ })
355
+
356
+ it('INVARIANT: signAndSendTransaction is never called on the adapter fallback path', async () => {
357
+ const signedBytes = buildSignedV0Bytes()
358
+ const signAndSend = vi.fn()
359
+ mockSolService.getConnectedAdapter.mockReturnValue({
360
+ wallet: undefined,
361
+ signTransaction: vi
362
+ .fn()
363
+ .mockResolvedValue(VersionedTransaction.deserialize(signedBytes)),
364
+ signAndSendTransaction: signAndSend
365
+ })
366
+
367
+ await connector.signSolanaTransactionBytes(buildSerializedV0Tx())
368
+
369
+ expect(signAndSend).not.toHaveBeenCalled()
370
+ })
371
+
372
+ it('surfaces an adapter-fallback failure as a typed "unknown" error, preserving the message', async () => {
373
+ // A non-rejection failure (e.g. locked wallet) stays type 'unknown' but keeps
374
+ // the original message so it is still actionable in logs.
375
+ mockSolService.getConnectedAdapter.mockReturnValue({
376
+ wallet: undefined,
377
+ signTransaction: vi.fn().mockRejectedValue(new Error('wallet locked')),
378
+ signAndSendTransaction: vi.fn()
379
+ })
380
+
381
+ await expect(
382
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
383
+ ).rejects.toMatchObject({ type: 'unknown', message: 'wallet locked' })
384
+ })
385
+
386
+ it('deserializes the input bytes before passing to adapter.signTransaction', async () => {
387
+ const signedBytes = buildSignedV0Bytes()
388
+ const adapterSignTx = vi
389
+ .fn()
390
+ .mockResolvedValue(VersionedTransaction.deserialize(signedBytes))
391
+ mockSolService.getConnectedAdapter.mockReturnValue({
392
+ wallet: undefined,
393
+ signTransaction: adapterSignTx,
394
+ signAndSendTransaction: vi.fn()
395
+ })
396
+
397
+ await connector.signSolanaTransactionBytes(buildSerializedV0Tx())
398
+
399
+ const arg = adapterSignTx.mock.calls[0][0]
400
+ // adapter receives a VersionedTransaction, not raw bytes
401
+ expect(arg).toBeInstanceOf(VersionedTransaction)
402
+ })
403
+
404
+ it('SECURITY (Path 3): rejects a tampered tx from a legacy adapter', async () => {
405
+ // Adapter returns a signed tx with a different message (lamports 999).
406
+ const adapterSignTx = vi
407
+ .fn()
408
+ .mockResolvedValue(
409
+ VersionedTransaction.deserialize(buildSignedV0BytesWith(999))
410
+ )
411
+ mockSolService.getConnectedAdapter.mockReturnValue({
412
+ wallet: undefined,
413
+ signTransaction: adapterSignTx,
414
+ signAndSendTransaction: vi.fn()
415
+ })
416
+
417
+ await expect(
418
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
419
+ ).rejects.toThrow('Signed transaction does not match the request')
420
+ })
421
+
422
+ // ── Bridge path (Comlink-proxied adapter) ────────────────────────────────
423
+
424
+ it('BRIDGE PATH: calls adapter.signSolanaTransactionBytes and returns its bytes without touching wallet.features', async () => {
425
+ const bridgeBytes = buildSignedV0Bytes()
426
+ const bridgeFn = vi.fn().mockResolvedValue(bridgeBytes)
427
+ // wallet.features is present but must NOT be touched — assert via spy
428
+ const featureSignTx = vi.fn()
429
+ const mockAdapter = {
430
+ // Bridge advertises the customFunction; detection awaits this list.
431
+ customFunctions: ['signSolanaTransactionBytes'],
432
+ // Extended bridge property — present on the Comlink-proxied adapter
433
+ signSolanaTransactionBytes: bridgeFn,
434
+ // Direct path artifacts — must remain untouched
435
+ wallet: {
436
+ accounts: [{ address: 'AAA' }],
437
+ features: {
438
+ 'solana:signTransaction': { signTransaction: featureSignTx }
439
+ }
440
+ },
441
+ signTransaction: vi.fn(),
442
+ signAndSendTransaction: vi.fn()
443
+ }
444
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
445
+ mockConnManager.getCurrentAccount.mockReturnValue('AAA')
446
+
447
+ const serialized = buildSerializedV0Tx()
448
+ const result = await connector.signSolanaTransactionBytes(serialized)
449
+
450
+ expect(result).toBe(bridgeBytes)
451
+ expect(bridgeFn).toHaveBeenCalledOnce()
452
+ // The connected account is threaded to the parent so it can't fall back to
453
+ // a drifted publicKey.
454
+ expect(bridgeFn).toHaveBeenCalledWith(serialized, 'AAA')
455
+ // The Wallet Standard feature path must NOT have been used
456
+ expect(featureSignTx).not.toHaveBeenCalled()
457
+ })
458
+
459
+ it('BRIDGE PATH: threads the connected account even when it differs from accounts[0]', async () => {
460
+ const bridgeFn = vi.fn().mockResolvedValue(buildSignedV0Bytes())
461
+ mockSolService.getConnectedAdapter.mockReturnValue({
462
+ customFunctions: ['signSolanaTransactionBytes'],
463
+ signSolanaTransactionBytes: bridgeFn,
464
+ wallet: undefined,
465
+ signTransaction: vi.fn(),
466
+ signAndSendTransaction: vi.fn()
467
+ })
468
+ mockConnManager.getCurrentAccount.mockReturnValue('CONNECTED_ACCT')
469
+
470
+ const serialized = buildSerializedV0Tx()
471
+ await connector.signSolanaTransactionBytes(serialized)
472
+
473
+ expect(bridgeFn).toHaveBeenCalledWith(serialized, 'CONNECTED_ACCT')
474
+ })
475
+
476
+ it('BRIDGE PATH INVARIANT: signAndSendTransaction is never called when the bridge wrapper handles signing', async () => {
477
+ const signAndSend = vi.fn()
478
+ const mockAdapter = {
479
+ customFunctions: ['signSolanaTransactionBytes'],
480
+ signSolanaTransactionBytes: vi
481
+ .fn()
482
+ .mockResolvedValue(buildSignedV0Bytes()),
483
+ wallet: undefined,
484
+ signTransaction: vi.fn(),
485
+ signAndSendTransaction: signAndSend
486
+ }
487
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
488
+
489
+ await connector.signSolanaTransactionBytes(buildSerializedV0Tx())
490
+
491
+ expect(signAndSend).not.toHaveBeenCalled()
492
+ })
493
+
494
+ it('BRIDGE PATH: returns the exact Uint8Array the bridge wrapper resolves with', async () => {
495
+ // Ensures no re-serialization happens on the bridge path — bytes pass through as-is
496
+ const expectedBytes = buildSignedV0Bytes()
497
+ const mockAdapter = {
498
+ customFunctions: ['signSolanaTransactionBytes'],
499
+ signSolanaTransactionBytes: vi.fn().mockResolvedValue(expectedBytes),
500
+ wallet: undefined,
501
+ signTransaction: vi.fn(),
502
+ signAndSendTransaction: vi.fn()
503
+ }
504
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
505
+
506
+ const result = await connector.signSolanaTransactionBytes(
507
+ buildSerializedV0Tx()
508
+ )
509
+
510
+ expect(result).toBe(expectedBytes)
511
+ })
512
+
513
+ it('BRIDGE PATH SECURITY: rejects tampered bytes returned by the parent', async () => {
514
+ // The wallet signs on the parent (client page); the child (iframe) verifies
515
+ // here. A parent that returns a different-message tx must be rejected.
516
+ const tampered = buildSignedV0BytesWith(999)
517
+ const mockAdapter = {
518
+ customFunctions: ['signSolanaTransactionBytes'],
519
+ signSolanaTransactionBytes: vi.fn().mockResolvedValue(tampered),
520
+ wallet: undefined,
521
+ signTransaction: vi.fn(),
522
+ signAndSendTransaction: vi.fn()
523
+ }
524
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
525
+
526
+ await expect(
527
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
528
+ ).rejects.toThrow('Signed transaction does not match the request')
529
+ })
530
+
531
+ // Closes the version-coupling break: an older bridge-parent without
532
+ // `signSolanaTransactionBytes` in customFunctions must NOT trigger the bridge
533
+ // path (Comlink would otherwise present every property as truthy and we'd
534
+ // call a method that doesn't exist on the parent).
535
+ it('BRIDGE COMPAT: falls back to direct path when bridge customFunctions lacks signSolanaTransactionBytes (old bridge-parent)', async () => {
536
+ const signedBytes = buildSignedV0Bytes()
537
+ const bridgeFn = vi.fn()
538
+ const featureSignTx = vi
539
+ .fn()
540
+ .mockResolvedValue([{ signedTransaction: signedBytes }])
541
+ const mockAdapter = {
542
+ // Old bridge: only the previous customFunctions, NOT signSolanaTransactionBytes
543
+ customFunctions: [
544
+ 'sendSerializedTransaction',
545
+ 'signSerializedTransaction'
546
+ ],
547
+ // Sync truthy check would falsely match this on a real Comlink proxy
548
+ signSolanaTransactionBytes: bridgeFn,
549
+ wallet: {
550
+ accounts: [{ address: 'AAA' }],
551
+ features: {
552
+ 'solana:signTransaction': { signTransaction: featureSignTx }
553
+ }
554
+ },
555
+ signTransaction: vi.fn(),
556
+ signAndSendTransaction: vi.fn()
557
+ }
558
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
559
+
560
+ const result = await connector.signSolanaTransactionBytes(
561
+ buildSerializedV0Tx()
562
+ )
563
+
564
+ expect(result).toBe(signedBytes)
565
+ expect(bridgeFn).not.toHaveBeenCalled()
566
+ expect(featureSignTx).toHaveBeenCalledOnce()
567
+ })
568
+
569
+ // Gap #18: bridge-path error propagation. Comlink flattens the parent's error
570
+ // to a plain Error, so we re-classify by message — a parent-side rejection must
571
+ // still reach the caller as type 'rejected'.
572
+ it('BRIDGE PATH: a wallet rejection on the parent surfaces as a typed "rejected" error', async () => {
573
+ const mockAdapter = {
574
+ customFunctions: ['signSolanaTransactionBytes'],
575
+ signSolanaTransactionBytes: vi
576
+ .fn()
577
+ .mockRejectedValue(new Error('user rejected on the parent')),
578
+ wallet: undefined,
579
+ signTransaction: vi.fn(),
580
+ signAndSendTransaction: vi.fn()
581
+ }
582
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
583
+
584
+ await expect(
585
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
586
+ ).rejects.toMatchObject({ type: 'rejected' })
587
+ })
588
+
589
+ // ── Multi-account direct path ──────────────────────────────────────────────
590
+
591
+ it('MULTI-ACCOUNT: picks the account matching getCurrentAccount(), not accounts[0]', async () => {
592
+ const signedBytes = buildSignedV0Bytes()
593
+ const featureSignTx = vi
594
+ .fn()
595
+ .mockResolvedValue([{ signedTransaction: signedBytes }])
596
+ const accountAAA = { address: 'AAA' }
597
+ const accountBBB = { address: 'BBB' }
598
+ const mockAdapter = {
599
+ // No bridge wrapper — must use direct feature path
600
+ wallet: {
601
+ accounts: [accountAAA, accountBBB],
602
+ features: {
603
+ 'solana:signTransaction': { signTransaction: featureSignTx }
604
+ }
605
+ },
606
+ signTransaction: vi.fn(),
607
+ signAndSendTransaction: vi.fn()
608
+ }
609
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
610
+ // Simulate user connected as second account
611
+ mockConnManager.getCurrentAccount.mockReturnValue('BBB')
612
+
613
+ await connector.signSolanaTransactionBytes(buildSerializedV0Tx())
614
+
615
+ const callArg = featureSignTx.mock.calls[0][0]
616
+ expect(callArg.account).toBe(accountBBB)
617
+ expect(callArg.account).not.toBe(accountAAA)
618
+ })
619
+
620
+ it('MULTI-ACCOUNT: throws instead of guessing when no account is selected and several exist', async () => {
621
+ // Signing with the wrong key yields a useless signature for a payment, so we
622
+ // refuse rather than fall back to accounts[0].
623
+ const featureSignTx = vi.fn()
624
+ const mockAdapter = {
625
+ wallet: {
626
+ accounts: [{ address: 'AAA' }, { address: 'BBB' }],
627
+ features: {
628
+ 'solana:signTransaction': { signTransaction: featureSignTx }
629
+ }
630
+ },
631
+ signTransaction: vi.fn(),
632
+ signAndSendTransaction: vi.fn()
633
+ }
634
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
635
+ mockConnManager.getCurrentAccount.mockReturnValue(null)
636
+
637
+ await expect(
638
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
639
+ ).rejects.toThrow('Cannot determine which Solana account to sign with')
640
+ expect(featureSignTx).not.toHaveBeenCalled()
641
+ })
642
+
643
+ it('MULTI-ACCOUNT: throws when the selected account is not in the wallet (never signs with a different account)', async () => {
644
+ const featureSignTx = vi.fn()
645
+ const mockAdapter = {
646
+ wallet: {
647
+ accounts: [{ address: 'AAA' }, { address: 'BBB' }],
648
+ features: {
649
+ 'solana:signTransaction': { signTransaction: featureSignTx }
650
+ }
651
+ },
652
+ signTransaction: vi.fn(),
653
+ signAndSendTransaction: vi.fn()
654
+ }
655
+ mockSolService.getConnectedAdapter.mockReturnValue(mockAdapter)
656
+ // Address that doesn't match any wallet account
657
+ mockConnManager.getCurrentAccount.mockReturnValue('ZZZZ_NOT_IN_WALLET')
658
+
659
+ await expect(
660
+ connector.signSolanaTransactionBytes(buildSerializedV0Tx())
661
+ ).rejects.toThrow('Connected Solana account not found in the wallet')
662
+ expect(featureSignTx).not.toHaveBeenCalled()
663
+ })
664
+
665
+ it('SINGLE-ACCOUNT: signs with the only account when none is explicitly selected', async () => {
666
+ const signedBytes = buildSignedV0Bytes()
667
+ const featureSignTx = vi
668
+ .fn()
669
+ .mockResolvedValue([{ signedTransaction: signedBytes }])
670
+ const onlyAccount = { address: 'AAA' }
671
+ mockSolService.getConnectedAdapter.mockReturnValue({
672
+ wallet: {
673
+ accounts: [onlyAccount],
674
+ features: {
675
+ 'solana:signTransaction': { signTransaction: featureSignTx }
676
+ }
677
+ },
678
+ signTransaction: vi.fn(),
679
+ signAndSendTransaction: vi.fn()
680
+ })
681
+ mockConnManager.getCurrentAccount.mockReturnValue(null)
682
+
683
+ await connector.signSolanaTransactionBytes(buildSerializedV0Tx())
684
+
685
+ expect(featureSignTx.mock.calls[0][0].account).toBe(onlyAccount)
686
+ })
687
+ })
688
+
689
+ describe('reserialize is byte-stable (Path 1 + Path 3 check safety)', () => {
690
+ // Paths 1 (bridge legacy) and 3 (direct legacy) deserialize → sign →
691
+ // re-serialize, then assertSameMessage runs on the result. These prove the
692
+ // round-trip preserves the message, so a legit sign isn't wrongly rejected.
693
+ it('preserves the message through deserialize → user-sign → serialize (v0)', () => {
694
+ const feePayer = Keypair.generate()
695
+ const user = Keypair.generate()
696
+ const msg = new TransactionMessage({
697
+ payerKey: feePayer.publicKey,
698
+ recentBlockhash: '11111111111111111111111111111111',
699
+ instructions: [
700
+ SystemProgram.transfer({
701
+ fromPubkey: user.publicKey, // makes `user` a required signer (slot 1)
702
+ toPubkey: recipient,
703
+ lamports: 1
704
+ })
705
+ ]
706
+ }).compileToV0Message()
707
+
708
+ // Relay (Alchemy) signs slot 0; the user slot is still empty — this is what
709
+ // the FE receives from /build.
710
+ const built = new VersionedTransaction(msg)
711
+ built.sign([feePayer])
712
+ const input = built.serialize()
713
+
714
+ // Bridge legacy fallback: deserialize → user signs slot 1 → re-serialize.
715
+ const round = VersionedTransaction.deserialize(input)
716
+ round.sign([user])
717
+ const reserialized = round.serialize()
718
+
719
+ // The canonical check must accept the re-serialized output.
720
+ expect(() => assertSameMessage(input, reserialized)).not.toThrow()
721
+ })
722
+
723
+ it('preserves the message through deserialize → user-sign → serialize (legacy)', () => {
724
+ const feePayer = Keypair.generate()
725
+ const user = Keypair.generate()
726
+ const tx = new Transaction()
727
+ tx.recentBlockhash = '11111111111111111111111111111111'
728
+ tx.feePayer = feePayer.publicKey
729
+ tx.add(
730
+ SystemProgram.transfer({
731
+ fromPubkey: user.publicKey,
732
+ toPubkey: recipient,
733
+ lamports: 1
734
+ })
735
+ )
736
+ tx.partialSign(feePayer) // slot 0 signed; user slot empty
737
+ const input = new Uint8Array(tx.serialize({ requireAllSignatures: false }))
738
+
739
+ const round = Transaction.from(input)
740
+ round.partialSign(user)
741
+ const reserialized = new Uint8Array(
742
+ round.serialize({ requireAllSignatures: false })
743
+ )
744
+
745
+ expect(() => assertSameMessage(input, reserialized)).not.toThrow()
746
+ })
747
+ })
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Pick which wallet account signs. We must sign with the account the user
3
+ * actually connected — never guess. A wrong signer produces a useless signature
4
+ * for a payment, so we throw instead of silently falling back.
5
+ */
6
+ export function resolveSigningAccount<T extends { address: string }>(
7
+ accounts: ReadonlyArray<T>,
8
+ connectedAddress: string | null | undefined
9
+ ): T {
10
+ if (connectedAddress) {
11
+ const match = accounts.find(a => a.address === connectedAddress)
12
+ if (!match) {
13
+ throw new Error(
14
+ 'Connected Solana account not found in the wallet — refusing to sign with a different account'
15
+ )
16
+ }
17
+ return match
18
+ }
19
+ // No explicit selection is only safe when the wallet has exactly one account.
20
+ if (accounts.length === 1) return accounts[0]!
21
+ throw new Error(
22
+ 'Cannot determine which Solana account to sign with — multiple accounts and none selected'
23
+ )
24
+ }
@@ -15,6 +15,7 @@ export interface ExtendedStandardWalletAdapter extends StandardWalletAdapter {
15
15
  | 'sendSerializedTransaction'
16
16
  | 'signSerializedTransaction'
17
17
  | 'signAllSerializedTransactions'
18
+ | 'signSolanaTransactionBytes'
18
19
  )[]
19
20
  sendSerializedTransaction: (
20
21
  transaction: unknown,
@@ -26,6 +27,12 @@ export interface ExtendedStandardWalletAdapter extends StandardWalletAdapter {
26
27
  signAllSerializedTransactions: (
27
28
  transactions: unknown[]
28
29
  ) => Promise<Error | Transaction[]>
30
+ // Sign-only, raw bytes (so no Transaction object crosses Comlink). See
31
+ // BridgeParent for the connectedAddress rationale.
32
+ signSolanaTransactionBytes: (
33
+ transaction: unknown,
34
+ connectedAddress?: string
35
+ ) => Promise<Uint8Array>
29
36
  }
30
37
 
31
38
  export type SolanaAdapter =