@dynamic-labs/waas-evm 5.4.0 → 5.5.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/CHANGELOG.md CHANGED
@@ -1,4 +1,31 @@
1
1
 
2
+ ## [5.5.0](https://github.com/dynamic-labs/dynamic-auth/compare/v5.4.1...v5.5.0) (2026-08-31)
3
+
4
+
5
+ ### Features
6
+
7
+ * **waas-evm:** route embedded EVM sends through gas sponsorship when enabled ([#12306](https://github.com/dynamic-labs/dynamic-auth/issues/12306)) ([6046ff3](https://github.com/dynamic-labs/dynamic-auth/commit/6046ff362d8de9402793bdaa7319fda645ff4c04))
8
+
9
+
10
+ ### Bug Fixes
11
+
12
+ * **bitcoin:** resolve the active BTC wallet and network correctly across the widget ([#12308](https://github.com/dynamic-labs/dynamic-auth/issues/12308)) ([13e9eae](https://github.com/dynamic-labs/dynamic-auth/commit/13e9eaec19b3925db507c878988cfd82da5a6de6))
13
+ * **btc:** unbreak BTC transaction confirmation, testnet balances and taproot testnet switching ([#12305](https://github.com/dynamic-labs/dynamic-auth/issues/12305)) ([5fd999c](https://github.com/dynamic-labs/dynamic-auth/commit/5fd999c4c819d3a74e967c0cfa77c5877a74906b))
14
+ * **react-native-extension:** stop leaking expo-secure-store into consumer autolinking ([#12296](https://github.com/dynamic-labs/dynamic-auth/issues/12296)) ([1e0396a](https://github.com/dynamic-labs/dynamic-auth/commit/1e0396ab00c79aa0b2f45b6d7b1d339c1dac1203)), closes [#12254](https://github.com/dynamic-labs/dynamic-auth/issues/12254)
15
+ * **screening:** wire connected-wallet screening into the Send Balance UI (DYNT-1663) ([#12303](https://github.com/dynamic-labs/dynamic-auth/issues/12303)) ([5d26ff3](https://github.com/dynamic-labs/dynamic-auth/commit/5d26ff375118302522c39bd2f1fa9e04f7378eaf))
16
+
17
+ ### [5.4.1](https://github.com/dynamic-labs/dynamic-auth/compare/v5.4.0...v5.4.1) (2026-08-26)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **webview-controller:** resolve which keychain key a session belongs to ([#12246](https://github.com/dynamic-labs/dynamic-auth/issues/12246)) ([3d110db](https://github.com/dynamic-labs/dynamic-auth/commit/3d110db831c6e9d82d07d86841f5c7733924b17e))
23
+ * **bitcoin:** forward the password through the BTC importPrivateKey override ([#12278](https://github.com/dynamic-labs/dynamic-auth/issues/12278)) ([21e1df3](https://github.com/dynamic-labs/dynamic-auth/commit/21e1df3e33e96e2efdb15ffa0fd29a441056202e))
24
+ * **react-native-extension:** recover 4.x expo-secure-store sessions on keychain miss ([#12254](https://github.com/dynamic-labs/dynamic-auth/issues/12254)) ([217e991](https://github.com/dynamic-labs/dynamic-auth/commit/217e991838f3073c12e2d2fab7a2e12830faad9e)), closes [#12092](https://github.com/dynamic-labs/dynamic-auth/issues/12092) [#12092](https://github.com/dynamic-labs/dynamic-auth/issues/12092) [#12092](https://github.com/dynamic-labs/dynamic-auth/issues/12092) [#12092](https://github.com/dynamic-labs/dynamic-auth/issues/12092) [#12242](https://github.com/dynamic-labs/dynamic-auth/issues/12242) [#12242](https://github.com/dynamic-labs/dynamic-auth/issues/12242)
25
+ * **transaction-card:** use walletConnector prop for network/fee instead of primaryWallet ([#12063](https://github.com/dynamic-labs/dynamic-auth/issues/12063)) ([81314d2](https://github.com/dynamic-labs/dynamic-auth/commit/81314d25fba4b20ab89631bc2d9ceeb9e2b6b2ac))
26
+ * **waas-svm:** instrument sponsorship retry attempts ([#12281](https://github.com/dynamic-labs/dynamic-auth/issues/12281)) ([7273a4b](https://github.com/dynamic-labs/dynamic-auth/commit/7273a4bc456cad512c0e9fbcd2abd66532a2f7df))
27
+ * **webview-controller:** recover 4.x secure-storage sessions and surface init failures ([#12242](https://github.com/dynamic-labs/dynamic-auth/issues/12242)) ([b51605c](https://github.com/dynamic-labs/dynamic-auth/commit/b51605cc9bdbb5d695173192c502a58d899bbbdd)), closes [#12094](https://github.com/dynamic-labs/dynamic-auth/issues/12094) [#12095](https://github.com/dynamic-labs/dynamic-auth/issues/12095) [#12098](https://github.com/dynamic-labs/dynamic-auth/issues/12098) [dynamic-labs/flutter-sdk#256](https://github.com/dynamic-labs/flutter-sdk/issues/256)
28
+
2
29
  ## [5.4.0](https://github.com/dynamic-labs/dynamic-auth/compare/v5.3.2...v5.4.0) (2026-08-25)
3
30
 
4
31
 
package/package.cjs CHANGED
@@ -3,6 +3,6 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "5.4.0";
6
+ var version = "5.5.0";
7
7
 
8
8
  exports.version = version;
package/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  'use client'
2
- var version = "5.4.0";
2
+ var version = "5.5.0";
3
3
 
4
4
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/waas-evm",
3
- "version": "5.4.0",
3
+ "version": "5.5.0",
4
4
  "description": "A React SDK for implementing wallet web3 authentication and authorization to your website.",
5
5
  "author": "Dynamic Labs, Inc.",
6
6
  "license": "MIT",
@@ -18,15 +18,16 @@
18
18
  },
19
19
  "homepage": "https://www.dynamic.xyz/",
20
20
  "dependencies": {
21
+ "@dynamic-labs/ethereum-gasless-core": "5.5.0",
21
22
  "@dynamic-labs/sdk-api-core": "0.12.0",
22
23
  "viem": "^2.45.3",
23
- "@dynamic-labs/assert-package-version": "5.4.0",
24
- "@dynamic-labs/ethereum-core": "5.4.0",
25
- "@dynamic-labs/logger": "5.4.0",
26
- "@dynamic-labs/types": "5.4.0",
27
- "@dynamic-labs/utils": "5.4.0",
28
- "@dynamic-labs/waas": "5.4.0",
29
- "@dynamic-labs/wallet-connector-core": "5.4.0"
24
+ "@dynamic-labs/assert-package-version": "5.5.0",
25
+ "@dynamic-labs/ethereum-core": "5.5.0",
26
+ "@dynamic-labs/logger": "5.5.0",
27
+ "@dynamic-labs/types": "5.5.0",
28
+ "@dynamic-labs/utils": "5.5.0",
29
+ "@dynamic-labs/waas": "5.5.0",
30
+ "@dynamic-labs/wallet-connector-core": "5.5.0"
30
31
  },
31
32
  "peerDependencies": {}
32
33
  }
@@ -8,11 +8,14 @@ var viem = require('viem');
8
8
  var accounts = require('viem/accounts');
9
9
  var utils$1 = require('viem/utils');
10
10
  var ethereumCore = require('@dynamic-labs/ethereum-core');
11
+ var ethereumGaslessCore = require('@dynamic-labs/ethereum-gasless-core');
11
12
  var logger$1 = require('@dynamic-labs/logger');
12
13
  var sdkApiCore = require('@dynamic-labs/sdk-api-core');
13
14
  var utils = require('@dynamic-labs/utils');
14
15
  var waas = require('@dynamic-labs/waas');
15
16
  var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
17
+ var toSponsoredTransactionCalls = require('./gasless/toSponsoredTransactionCalls/toSponsoredTransactionCalls.cjs');
18
+ var withBigintSafeSignTypedData = require('./gasless/withBigintSafeSignTypedData/withBigintSafeSignTypedData.cjs');
16
19
 
17
20
  const logger = new logger$1.Logger('DynamicWaasConnector');
18
21
  class DynamicWaasEVMConnector extends waas.withDynamicWaas(ethereumCore.EthereumWalletConnector) {
@@ -43,6 +46,9 @@ class DynamicWaasEVMConnector extends waas.withDynamicWaas(ethereumCore.Ethereum
43
46
  this.logger = logger;
44
47
  this.overrideKey = 'dynamicwaas';
45
48
  this.isEmbeddedWallet = true;
49
+ this.getEvmGasSponsorshipEnabled = () => false;
50
+ this.getSponsorshipSdkApi = undefined;
51
+ this.delegation7702Registry = ethereumGaslessCore.create7702DelegationRegistry();
46
52
  /**
47
53
  * Chain IDs that have dedicated connectors and should not be handled by this connector.
48
54
  * Networks with these chain IDs are filtered from network lists and rejected during switching.
@@ -475,88 +481,162 @@ class DynamicWaasEVMConnector extends waas.withDynamicWaas(ethereumCore.Ethereum
475
481
  return this.getWalletClient();
476
482
  }
477
483
  // Chain-specific override for exportClientKeyshares - EVM needs to set active account first
478
- exportClientKeyshares(_a) {
484
+ exportClientKeyshares(params) {
479
485
  const _super = Object.create(null, {
480
486
  exportClientKeyshares: { get: () => super.exportClientKeyshares }
481
487
  });
482
- return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress, password, }) {
483
- if (!accountAddress) {
488
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
489
+ if (!params.accountAddress) {
484
490
  throw new Error('Account address is required');
485
491
  }
486
492
  // EVM-specific: set active account before exporting
487
- this.setActiveAccount(accountAddress);
488
- return _super.exportClientKeyshares.call(this, { accountAddress, password });
493
+ this.setActiveAccount(params.accountAddress);
494
+ return _super.exportClientKeyshares.call(this, params);
489
495
  });
490
496
  }
491
497
  // Chain-specific override for backupKeySharesToGoogleDrive - EVM needs to set active account first
492
- backupKeySharesToGoogleDrive(_a) {
498
+ backupKeySharesToGoogleDrive(params) {
493
499
  const _super = Object.create(null, {
494
500
  backupKeySharesToGoogleDrive: { get: () => super.backupKeySharesToGoogleDrive }
495
501
  });
496
- return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress, password, googleDriveAccessToken, }) {
497
- if (!accountAddress) {
502
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
503
+ if (!params.accountAddress) {
498
504
  throw new Error('Account address is required');
499
505
  }
500
506
  // EVM-specific: set active account before backing up
501
- this.setActiveAccount(accountAddress);
502
- return _super.backupKeySharesToGoogleDrive.call(this, {
503
- accountAddress,
504
- googleDriveAccessToken,
505
- password,
506
- });
507
+ this.setActiveAccount(params.accountAddress);
508
+ return _super.backupKeySharesToGoogleDrive.call(this, params);
507
509
  });
508
510
  }
509
511
  // Chain-specific override for refreshWalletAccountShares - EVM needs to set active account first
510
- refreshWalletAccountShares(_a) {
512
+ refreshWalletAccountShares(params) {
511
513
  const _super = Object.create(null, {
512
514
  refreshWalletAccountShares: { get: () => super.refreshWalletAccountShares }
513
515
  });
514
- return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress, password, }) {
515
- if (!accountAddress) {
516
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
517
+ if (!params.accountAddress) {
516
518
  throw new Error('Account address is required');
517
519
  }
518
520
  // EVM-specific: set active account before refreshing
519
- this.setActiveAccount(accountAddress);
520
- return _super.refreshWalletAccountShares.call(this, { accountAddress, password });
521
+ this.setActiveAccount(params.accountAddress);
522
+ return _super.refreshWalletAccountShares.call(this, params);
521
523
  });
522
524
  }
523
525
  // Chain-specific override for reshareWalletAccountShares - EVM needs to set active account first
524
- reshareWalletAccountShares(_a) {
526
+ reshareWalletAccountShares(params) {
525
527
  const _super = Object.create(null, {
526
528
  reshareWalletAccountShares: { get: () => super.reshareWalletAccountShares }
527
529
  });
528
- return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress, password, thresholdSignatureScheme, }) {
529
- if (!accountAddress) {
530
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
531
+ if (!params.accountAddress) {
530
532
  throw new Error('Account address is required');
531
533
  }
532
- this.setActiveAccount(accountAddress);
533
- return _super.reshareWalletAccountShares.call(this, {
534
- accountAddress,
535
- password,
536
- thresholdSignatureScheme,
537
- });
534
+ this.setActiveAccount(params.accountAddress);
535
+ return _super.reshareWalletAccountShares.call(this, params);
538
536
  });
539
537
  }
540
538
  // Chain-specific override for updatePassword - EVM needs to set active account first
541
- updatePassword(_a) {
539
+ updatePassword(params) {
542
540
  const _super = Object.create(null, {
543
541
  updatePassword: { get: () => super.updatePassword }
544
542
  });
545
- return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress, existingPassword, newPassword, }) {
546
- if (!accountAddress) {
543
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
544
+ if (!params.accountAddress) {
547
545
  throw new Error('Account address is required');
548
546
  }
549
547
  // EVM-specific: set active account before updating password
550
- this.setActiveAccount(accountAddress);
551
- return _super.updatePassword.call(this, {
548
+ this.setActiveAccount(params.accountAddress);
549
+ return _super.updatePassword.call(this, params);
550
+ });
551
+ }
552
+ /**
553
+ * Registers the project's EVM gas sponsorship configuration so the send flow
554
+ * can route transactions through the sponsored relay instead of paying fees
555
+ * from the wallet's native balance.
556
+ */
557
+ setEvmGasSponsorshipConfig({ getEnabled, getSdkApi, }) {
558
+ this.getEvmGasSponsorshipEnabled = getEnabled;
559
+ this.getSponsorshipSdkApi = getSdkApi;
560
+ }
561
+ /**
562
+ * Sponsorship requires the project setting, an SDK API client and a relayer
563
+ * funded for the wallet's current chain. Anything missing means the send flow
564
+ * pays fees from the wallet's native balance.
565
+ */
566
+ isGasSponsorshipAvailable() {
567
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
568
+ var _a;
569
+ const { environmentId } = this;
570
+ if (!this.getEvmGasSponsorshipEnabled() || !environmentId) {
571
+ return false;
572
+ }
573
+ const sdkApi = (_a = this.getSponsorshipSdkApi) === null || _a === void 0 ? void 0 : _a.call(this);
574
+ if (!sdkApi) {
575
+ return false;
576
+ }
577
+ const evmNetwork = this.currentEvmNetwork();
578
+ if (!evmNetwork) {
579
+ return false;
580
+ }
581
+ try {
582
+ yield ethereumGaslessCore.getAvailableEvmGaslessRelayer({ chainId: Number(evmNetwork.chainId) }, { environmentId, sdkApi });
583
+ return true;
584
+ }
585
+ catch (_b) {
586
+ logger.debug('No EVM gasless relayer available for chain');
587
+ return false;
588
+ }
589
+ });
590
+ }
591
+ sendSponsoredUiTransaction(_a) {
592
+ return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress, sponsoredChainId, transaction, }) {
593
+ var _b, _c;
594
+ const sdkApi = (_b = this.getSponsorshipSdkApi) === null || _b === void 0 ? void 0 : _b.call(this);
595
+ if (!sdkApi || !this.environmentId) {
596
+ throw new utils.DynamicError('Gas sponsorship is not configured', 'gas_sponsorship_not_configured');
597
+ }
598
+ const evmNetwork = this.currentEvmNetwork();
599
+ if (!evmNetwork) {
600
+ throw new utils.DynamicError('EVM network not found', 'evm_network_not_found');
601
+ }
602
+ if (Number(evmNetwork.chainId) !== sponsoredChainId) {
603
+ throw new utils.DynamicError('Gas sponsorship was not verified for the active chain', 'gas_sponsorship_chain_mismatch');
604
+ }
605
+ const publicClient = yield this.getPublicClient();
606
+ if (!publicClient) {
607
+ throw new utils.DynamicError('No public client available', 'no_public_client_available');
608
+ }
609
+ const accountSource = yield this.getViemAccountCustomSource({
552
610
  accountAddress,
553
- existingPassword,
554
- newPassword,
555
611
  });
612
+ const sponsorshipWalletClient = viem.createWalletClient({
613
+ account: accounts.toAccount(withBigintSafeSignTypedData.withBigintSafeSignTypedData(accountSource)),
614
+ chain: ethereumCore.getOrMapViemChain(evmNetwork),
615
+ transport: viem.http(this.getRpcUrl(evmNetwork), this.providersConfig.httpTransportConfig),
616
+ });
617
+ const calls = toSponsoredTransactionCalls.toSponsoredTransactionCalls({
618
+ nonNativeAddress: transaction.nonNativeAddress,
619
+ nonNativeValue: transaction.nonNativeValue,
620
+ to: (_c = transaction.to) !== null && _c !== void 0 ? _c : undefined,
621
+ value: transaction.value,
622
+ });
623
+ const { transactionHash } = yield ethereumGaslessCore.sendSponsoredTransaction({
624
+ autoDelegate: true,
625
+ calls,
626
+ }, {
627
+ chainId: Number(evmNetwork.chainId),
628
+ delegationRegistry: this.delegation7702Registry,
629
+ environmentId: this.environmentId,
630
+ publicClient: publicClient,
631
+ sdkApi,
632
+ walletClient: sponsorshipWalletClient,
633
+ });
634
+ return transactionHash;
556
635
  });
557
636
  }
558
637
  createUiTransaction(from) {
559
638
  return _tslib.__awaiter(this, void 0, void 0, function* () {
639
+ var _a;
560
640
  yield this.validateActiveWallet(from);
561
641
  const walletClient = this.getWalletClient();
562
642
  const publicClient = yield this.getPublicClient();
@@ -566,9 +646,19 @@ class DynamicWaasEVMConnector extends waas.withDynamicWaas(ethereumCore.Ethereum
566
646
  if (!publicClient || !walletClient) {
567
647
  throw new utils.DynamicError('No public client available', 'no_public_client_available');
568
648
  }
649
+ const isGasSponsored = yield this.isGasSponsorshipAvailable();
650
+ const sponsoredChainId = Number((_a = this.currentEvmNetwork()) === null || _a === void 0 ? void 0 : _a.chainId);
569
651
  return new ethereumCore.ViemUiTransaction({
570
652
  account: from,
653
+ isGasSponsored,
571
654
  onSubmit: (transaction) => _tslib.__awaiter(this, void 0, void 0, function* () {
655
+ if (isGasSponsored) {
656
+ return this.sendSponsoredUiTransaction({
657
+ accountAddress: from,
658
+ sponsoredChainId,
659
+ transaction,
660
+ });
661
+ }
572
662
  // Non native token
573
663
  if (transaction.nonNativeAddress) {
574
664
  return walletClient.writeContract({
@@ -2,10 +2,10 @@ import { Account, CustomSource, Hex, Transport, Chain as ViemChain, WalletClient
2
2
  import { LocalAccount, SignAuthorizationParameters, SignAuthorizationReturnType } from 'viem/accounts';
3
3
  import { EthereumWalletConnector, EthereumWalletConnectorOpts, SwitchNetworkOps } from '@dynamic-labs/ethereum-core';
4
4
  import { Logger } from '@dynamic-labs/logger';
5
- import { JwtVerifiedCredential, MFAAction, SignMessageContext, TokenScope } from '@dynamic-labs/sdk-api-core';
5
+ import { JwtVerifiedCredential, MFAAction, SDKApi, SignMessageContext, TokenScope } from '@dynamic-labs/sdk-api-core';
6
6
  import { IUITransaction } from '@dynamic-labs/types';
7
7
  import { WaasExportHandler } from '@dynamic-labs/waas';
8
- import { IDynamicWaasConnector } from '@dynamic-labs/wallet-connector-core';
8
+ import { BackupKeySharesToGoogleDriveParams, ExportClientKeysharesParams, IDynamicWaasConnector, RefreshWalletAccountSharesParams, ReshareWalletAccountSharesParams, UpdatePasswordParams } from '@dynamic-labs/wallet-connector-core';
9
9
  type EvmNetwork = EthereumWalletConnector['evmNetworks'][number];
10
10
  interface JwtVerifiedCredentialWithSmartWalletRef extends JwtVerifiedCredential {
11
11
  smartWalletRefId?: string;
@@ -60,6 +60,14 @@ declare const DynamicWaasEVMConnector_base: (abstract new (...args: any[]) => {
60
60
  }): Promise<string | undefined>;
61
61
  setEnvironmentId(environmentId: string): void;
62
62
  setBaseApiUrl(baseApiUrl: string): void;
63
+ /**
64
+ * Override getEnabledNetworks to filter out unsupported networks.
65
+ * This is the UI-facing method used by network pickers.
66
+ *
67
+ * Note: We override getEnabledNetworks() instead of the evmNetworks getter because
68
+ * evmNetworks is a class field in EthereumWalletConnector, and class fields create
69
+ * own properties that shadow prototype-based getters/setters.
70
+ */
63
71
  setBaseClientKeysharesRelayApiUrl(baseClientKeysharesRelayApiUrl?: string | undefined): void;
64
72
  setRelayUrl(relayUrl: string): void;
65
73
  setGetSignedSessionIdFunction(getSignedSessionId: () => Promise<string>): void;
@@ -76,12 +84,7 @@ declare const DynamicWaasEVMConnector_base: (abstract new (...args: any[]) => {
76
84
  getWaasWalletClient(traceContext?: import("dist/packages/waas/utils/instrumentation").TraceContext | undefined, { forceRebuild }?: {
77
85
  forceRebuild?: boolean | undefined;
78
86
  } | undefined): Promise<import("@dynamic-labs-wallet/browser-wallet-client").DynamicWalletClient>;
79
- createWalletAccount({ thresholdSignatureScheme, password, bitcoinConfig, businessAccountId, }?: {
80
- thresholdSignatureScheme?: string | undefined;
81
- password?: string | undefined;
82
- bitcoinConfig?: import("@dynamic-labs-wallet/browser-wallet-client").BitcoinConfig | undefined;
83
- businessAccountId?: string | undefined;
84
- } | undefined): Promise<{
87
+ createWalletAccount({ thresholdSignatureScheme, password, bitcoinConfig, businessAccountId, }?: import("@dynamic-labs/wallet-connector-core").CreateWalletAccountParams | undefined): Promise<{
85
88
  chainName: string;
86
89
  accountAddress: string;
87
90
  publicKeyHex: string;
@@ -101,15 +104,7 @@ declare const DynamicWaasEVMConnector_base: (abstract new (...args: any[]) => {
101
104
  }): Promise<{
102
105
  shareSetId: string;
103
106
  }>;
104
- importPrivateKey({ privateKey, thresholdSignatureScheme, publicAddressCheck, addressType, legacyWalletId, password, isRawScalarImport, }: {
105
- privateKey: string;
106
- thresholdSignatureScheme?: string | undefined;
107
- publicAddressCheck?: string | undefined;
108
- addressType?: string | undefined;
109
- legacyWalletId?: string | undefined;
110
- password?: string | undefined;
111
- isRawScalarImport?: boolean | undefined;
112
- }): Promise<void>;
107
+ importPrivateKey({ privateKey, thresholdSignatureScheme, publicAddressCheck, addressType, legacyWalletId, password, isRawScalarImport, }: import("@dynamic-labs/wallet-connector-core").ImportPrivateKeyParams): Promise<void>;
113
108
  migrateFromFireblocks({ deviceId, jwt, walletPassword, ncwStorage, expectedAddresses, coinTypes, password, }: {
114
109
  deviceId: string;
115
110
  jwt: string;
@@ -127,10 +122,7 @@ declare const DynamicWaasEVMConnector_base: (abstract new (...args: any[]) => {
127
122
  getExportHandler(): {
128
123
  clear: () => void;
129
124
  };
130
- exportClientKeyshares({ accountAddress, password, }: {
131
- accountAddress: string;
132
- password?: string | undefined;
133
- }): Promise<void>;
125
+ exportClientKeyshares({ accountAddress, password, }: ExportClientKeysharesParams): Promise<void>;
134
126
  runBackupLifecycle({ provider, accountAddress, password, performBackup, }: {
135
127
  provider: string;
136
128
  accountAddress: string;
@@ -146,11 +138,7 @@ declare const DynamicWaasEVMConnector_base: (abstract new (...args: any[]) => {
146
138
  };
147
139
  }) => Promise<void>;
148
140
  }): Promise<void>;
149
- backupKeySharesToGoogleDrive({ accountAddress, password, googleDriveAccessToken, }: {
150
- accountAddress: string;
151
- password?: string | undefined;
152
- googleDriveAccessToken?: string | undefined;
153
- }): Promise<void>;
141
+ backupKeySharesToGoogleDrive({ accountAddress, password, googleDriveAccessToken, }: BackupKeySharesToGoogleDriveParams): Promise<void>;
154
142
  exportClientKeysharesFromGoogleDrive({ accountAddress, password, }: {
155
143
  accountAddress: string;
156
144
  password?: string | undefined;
@@ -164,24 +152,13 @@ declare const DynamicWaasEVMConnector_base: (abstract new (...args: any[]) => {
164
152
  }): Promise<void>;
165
153
  hideICloudSignIn(): Promise<void>;
166
154
  isICloudAuthenticated(): Promise<boolean>;
167
- refreshWalletAccountShares({ accountAddress, password, }: {
168
- accountAddress: string;
169
- password?: string | undefined;
170
- }): Promise<void>;
171
- reshareWalletAccountShares({ accountAddress, thresholdSignatureScheme, password, }: {
172
- accountAddress: string;
173
- thresholdSignatureScheme: string;
174
- password?: string | undefined;
175
- }): Promise<void>;
155
+ refreshWalletAccountShares({ accountAddress, password, }: RefreshWalletAccountSharesParams): Promise<void>;
156
+ reshareWalletAccountShares({ accountAddress, thresholdSignatureScheme, password, }: ReshareWalletAccountSharesParams): Promise<void>;
176
157
  revokeDelegation({ accountAddress, password, }: {
177
158
  accountAddress: string;
178
159
  password?: string | undefined;
179
160
  }): Promise<void>;
180
- updatePassword({ accountAddress, existingPassword, newPassword, }: {
181
- accountAddress: string;
182
- existingPassword?: string | undefined;
183
- newPassword: string;
184
- }): Promise<void>;
161
+ updatePassword({ accountAddress, existingPassword, newPassword, }: UpdatePasswordParams): Promise<void>;
185
162
  setPassword({ accountAddress, newPassword, }: {
186
163
  accountAddress: string;
187
164
  newPassword: string;
@@ -241,6 +218,9 @@ export declare class DynamicWaasEVMConnector extends DynamicWaasEVMConnector_bas
241
218
  logger: Logger;
242
219
  overrideKey: string;
243
220
  isEmbeddedWallet: boolean;
221
+ private getEvmGasSponsorshipEnabled;
222
+ private getSponsorshipSdkApi;
223
+ private delegation7702Registry;
244
224
  /**
245
225
  * Chain IDs that have dedicated connectors and should not be handled by this connector.
246
226
  * Networks with these chain IDs are filtered from network lists and rejected during switching.
@@ -305,29 +285,27 @@ export declare class DynamicWaasEVMConnector extends DynamicWaasEVMConnector_bas
305
285
  getWalletClientByAddress({ accountAddress, }: {
306
286
  accountAddress: string;
307
287
  }): WalletClient<Transport, ViemChain, Account> | undefined;
308
- exportClientKeyshares({ accountAddress, password, }: {
309
- accountAddress: string;
310
- password?: string;
311
- }): Promise<void>;
312
- backupKeySharesToGoogleDrive({ accountAddress, password, googleDriveAccessToken, }: {
313
- accountAddress: string;
314
- password?: string;
315
- googleDriveAccessToken?: string;
316
- }): Promise<void>;
317
- refreshWalletAccountShares({ accountAddress, password, }: {
318
- accountAddress: string;
319
- password?: string;
320
- }): Promise<void>;
321
- reshareWalletAccountShares({ accountAddress, password, thresholdSignatureScheme, }: {
322
- accountAddress: string;
323
- password?: string;
324
- thresholdSignatureScheme: string;
325
- }): Promise<void>;
326
- updatePassword({ accountAddress, existingPassword, newPassword, }: {
327
- accountAddress: string;
328
- existingPassword: string;
329
- newPassword: string;
330
- }): Promise<void>;
288
+ exportClientKeyshares(params: ExportClientKeysharesParams): Promise<void>;
289
+ backupKeySharesToGoogleDrive(params: BackupKeySharesToGoogleDriveParams): Promise<void>;
290
+ refreshWalletAccountShares(params: RefreshWalletAccountSharesParams): Promise<void>;
291
+ reshareWalletAccountShares(params: ReshareWalletAccountSharesParams): Promise<void>;
292
+ updatePassword(params: UpdatePasswordParams): Promise<void>;
293
+ /**
294
+ * Registers the project's EVM gas sponsorship configuration so the send flow
295
+ * can route transactions through the sponsored relay instead of paying fees
296
+ * from the wallet's native balance.
297
+ */
298
+ setEvmGasSponsorshipConfig({ getEnabled, getSdkApi, }: {
299
+ getEnabled: () => boolean;
300
+ getSdkApi: () => SDKApi;
301
+ }): void;
302
+ /**
303
+ * Sponsorship requires the project setting, an SDK API client and a relayer
304
+ * funded for the wallet's current chain. Anything missing means the send flow
305
+ * pays fees from the wallet's native balance.
306
+ */
307
+ private isGasSponsorshipAvailable;
308
+ private sendSponsoredUiTransaction;
331
309
  createUiTransaction(from: string): Promise<IUITransaction>;
332
310
  getConnectedAccounts(): Promise<string[]>;
333
311
  getAddress(): Promise<string>;
@@ -1,14 +1,17 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../_virtual/_tslib.js';
3
- import { http, serializeTransaction, erc20Abi, parseSignature } from 'viem';
3
+ import { http, serializeTransaction, createWalletClient, erc20Abi, parseSignature } from 'viem';
4
4
  import { toAccount } from 'viem/accounts';
5
5
  import { hashAuthorization } from 'viem/utils';
6
6
  import { EthereumWalletConnector, createWalletClientWithUiConfirmation, getOrMapViemChain, ViemUiTransaction } from '@dynamic-labs/ethereum-core';
7
+ import { create7702DelegationRegistry, getAvailableEvmGaslessRelayer, sendSponsoredTransaction } from '@dynamic-labs/ethereum-gasless-core';
7
8
  import { Logger } from '@dynamic-labs/logger';
8
9
  import { MFAAction, TokenScope } from '@dynamic-labs/sdk-api-core';
9
10
  import { DynamicError } from '@dynamic-labs/utils';
10
11
  import { withDynamicWaas, WaasExportHandler } from '@dynamic-labs/waas';
11
12
  import { isSameAddress } from '@dynamic-labs/wallet-connector-core';
13
+ import { toSponsoredTransactionCalls } from './gasless/toSponsoredTransactionCalls/toSponsoredTransactionCalls.js';
14
+ import { withBigintSafeSignTypedData } from './gasless/withBigintSafeSignTypedData/withBigintSafeSignTypedData.js';
12
15
 
13
16
  const logger = new Logger('DynamicWaasConnector');
14
17
  class DynamicWaasEVMConnector extends withDynamicWaas(EthereumWalletConnector) {
@@ -39,6 +42,9 @@ class DynamicWaasEVMConnector extends withDynamicWaas(EthereumWalletConnector) {
39
42
  this.logger = logger;
40
43
  this.overrideKey = 'dynamicwaas';
41
44
  this.isEmbeddedWallet = true;
45
+ this.getEvmGasSponsorshipEnabled = () => false;
46
+ this.getSponsorshipSdkApi = undefined;
47
+ this.delegation7702Registry = create7702DelegationRegistry();
42
48
  /**
43
49
  * Chain IDs that have dedicated connectors and should not be handled by this connector.
44
50
  * Networks with these chain IDs are filtered from network lists and rejected during switching.
@@ -471,88 +477,162 @@ class DynamicWaasEVMConnector extends withDynamicWaas(EthereumWalletConnector) {
471
477
  return this.getWalletClient();
472
478
  }
473
479
  // Chain-specific override for exportClientKeyshares - EVM needs to set active account first
474
- exportClientKeyshares(_a) {
480
+ exportClientKeyshares(params) {
475
481
  const _super = Object.create(null, {
476
482
  exportClientKeyshares: { get: () => super.exportClientKeyshares }
477
483
  });
478
- return __awaiter(this, arguments, void 0, function* ({ accountAddress, password, }) {
479
- if (!accountAddress) {
484
+ return __awaiter(this, void 0, void 0, function* () {
485
+ if (!params.accountAddress) {
480
486
  throw new Error('Account address is required');
481
487
  }
482
488
  // EVM-specific: set active account before exporting
483
- this.setActiveAccount(accountAddress);
484
- return _super.exportClientKeyshares.call(this, { accountAddress, password });
489
+ this.setActiveAccount(params.accountAddress);
490
+ return _super.exportClientKeyshares.call(this, params);
485
491
  });
486
492
  }
487
493
  // Chain-specific override for backupKeySharesToGoogleDrive - EVM needs to set active account first
488
- backupKeySharesToGoogleDrive(_a) {
494
+ backupKeySharesToGoogleDrive(params) {
489
495
  const _super = Object.create(null, {
490
496
  backupKeySharesToGoogleDrive: { get: () => super.backupKeySharesToGoogleDrive }
491
497
  });
492
- return __awaiter(this, arguments, void 0, function* ({ accountAddress, password, googleDriveAccessToken, }) {
493
- if (!accountAddress) {
498
+ return __awaiter(this, void 0, void 0, function* () {
499
+ if (!params.accountAddress) {
494
500
  throw new Error('Account address is required');
495
501
  }
496
502
  // EVM-specific: set active account before backing up
497
- this.setActiveAccount(accountAddress);
498
- return _super.backupKeySharesToGoogleDrive.call(this, {
499
- accountAddress,
500
- googleDriveAccessToken,
501
- password,
502
- });
503
+ this.setActiveAccount(params.accountAddress);
504
+ return _super.backupKeySharesToGoogleDrive.call(this, params);
503
505
  });
504
506
  }
505
507
  // Chain-specific override for refreshWalletAccountShares - EVM needs to set active account first
506
- refreshWalletAccountShares(_a) {
508
+ refreshWalletAccountShares(params) {
507
509
  const _super = Object.create(null, {
508
510
  refreshWalletAccountShares: { get: () => super.refreshWalletAccountShares }
509
511
  });
510
- return __awaiter(this, arguments, void 0, function* ({ accountAddress, password, }) {
511
- if (!accountAddress) {
512
+ return __awaiter(this, void 0, void 0, function* () {
513
+ if (!params.accountAddress) {
512
514
  throw new Error('Account address is required');
513
515
  }
514
516
  // EVM-specific: set active account before refreshing
515
- this.setActiveAccount(accountAddress);
516
- return _super.refreshWalletAccountShares.call(this, { accountAddress, password });
517
+ this.setActiveAccount(params.accountAddress);
518
+ return _super.refreshWalletAccountShares.call(this, params);
517
519
  });
518
520
  }
519
521
  // Chain-specific override for reshareWalletAccountShares - EVM needs to set active account first
520
- reshareWalletAccountShares(_a) {
522
+ reshareWalletAccountShares(params) {
521
523
  const _super = Object.create(null, {
522
524
  reshareWalletAccountShares: { get: () => super.reshareWalletAccountShares }
523
525
  });
524
- return __awaiter(this, arguments, void 0, function* ({ accountAddress, password, thresholdSignatureScheme, }) {
525
- if (!accountAddress) {
526
+ return __awaiter(this, void 0, void 0, function* () {
527
+ if (!params.accountAddress) {
526
528
  throw new Error('Account address is required');
527
529
  }
528
- this.setActiveAccount(accountAddress);
529
- return _super.reshareWalletAccountShares.call(this, {
530
- accountAddress,
531
- password,
532
- thresholdSignatureScheme,
533
- });
530
+ this.setActiveAccount(params.accountAddress);
531
+ return _super.reshareWalletAccountShares.call(this, params);
534
532
  });
535
533
  }
536
534
  // Chain-specific override for updatePassword - EVM needs to set active account first
537
- updatePassword(_a) {
535
+ updatePassword(params) {
538
536
  const _super = Object.create(null, {
539
537
  updatePassword: { get: () => super.updatePassword }
540
538
  });
541
- return __awaiter(this, arguments, void 0, function* ({ accountAddress, existingPassword, newPassword, }) {
542
- if (!accountAddress) {
539
+ return __awaiter(this, void 0, void 0, function* () {
540
+ if (!params.accountAddress) {
543
541
  throw new Error('Account address is required');
544
542
  }
545
543
  // EVM-specific: set active account before updating password
546
- this.setActiveAccount(accountAddress);
547
- return _super.updatePassword.call(this, {
544
+ this.setActiveAccount(params.accountAddress);
545
+ return _super.updatePassword.call(this, params);
546
+ });
547
+ }
548
+ /**
549
+ * Registers the project's EVM gas sponsorship configuration so the send flow
550
+ * can route transactions through the sponsored relay instead of paying fees
551
+ * from the wallet's native balance.
552
+ */
553
+ setEvmGasSponsorshipConfig({ getEnabled, getSdkApi, }) {
554
+ this.getEvmGasSponsorshipEnabled = getEnabled;
555
+ this.getSponsorshipSdkApi = getSdkApi;
556
+ }
557
+ /**
558
+ * Sponsorship requires the project setting, an SDK API client and a relayer
559
+ * funded for the wallet's current chain. Anything missing means the send flow
560
+ * pays fees from the wallet's native balance.
561
+ */
562
+ isGasSponsorshipAvailable() {
563
+ return __awaiter(this, void 0, void 0, function* () {
564
+ var _a;
565
+ const { environmentId } = this;
566
+ if (!this.getEvmGasSponsorshipEnabled() || !environmentId) {
567
+ return false;
568
+ }
569
+ const sdkApi = (_a = this.getSponsorshipSdkApi) === null || _a === void 0 ? void 0 : _a.call(this);
570
+ if (!sdkApi) {
571
+ return false;
572
+ }
573
+ const evmNetwork = this.currentEvmNetwork();
574
+ if (!evmNetwork) {
575
+ return false;
576
+ }
577
+ try {
578
+ yield getAvailableEvmGaslessRelayer({ chainId: Number(evmNetwork.chainId) }, { environmentId, sdkApi });
579
+ return true;
580
+ }
581
+ catch (_b) {
582
+ logger.debug('No EVM gasless relayer available for chain');
583
+ return false;
584
+ }
585
+ });
586
+ }
587
+ sendSponsoredUiTransaction(_a) {
588
+ return __awaiter(this, arguments, void 0, function* ({ accountAddress, sponsoredChainId, transaction, }) {
589
+ var _b, _c;
590
+ const sdkApi = (_b = this.getSponsorshipSdkApi) === null || _b === void 0 ? void 0 : _b.call(this);
591
+ if (!sdkApi || !this.environmentId) {
592
+ throw new DynamicError('Gas sponsorship is not configured', 'gas_sponsorship_not_configured');
593
+ }
594
+ const evmNetwork = this.currentEvmNetwork();
595
+ if (!evmNetwork) {
596
+ throw new DynamicError('EVM network not found', 'evm_network_not_found');
597
+ }
598
+ if (Number(evmNetwork.chainId) !== sponsoredChainId) {
599
+ throw new DynamicError('Gas sponsorship was not verified for the active chain', 'gas_sponsorship_chain_mismatch');
600
+ }
601
+ const publicClient = yield this.getPublicClient();
602
+ if (!publicClient) {
603
+ throw new DynamicError('No public client available', 'no_public_client_available');
604
+ }
605
+ const accountSource = yield this.getViemAccountCustomSource({
548
606
  accountAddress,
549
- existingPassword,
550
- newPassword,
551
607
  });
608
+ const sponsorshipWalletClient = createWalletClient({
609
+ account: toAccount(withBigintSafeSignTypedData(accountSource)),
610
+ chain: getOrMapViemChain(evmNetwork),
611
+ transport: http(this.getRpcUrl(evmNetwork), this.providersConfig.httpTransportConfig),
612
+ });
613
+ const calls = toSponsoredTransactionCalls({
614
+ nonNativeAddress: transaction.nonNativeAddress,
615
+ nonNativeValue: transaction.nonNativeValue,
616
+ to: (_c = transaction.to) !== null && _c !== void 0 ? _c : undefined,
617
+ value: transaction.value,
618
+ });
619
+ const { transactionHash } = yield sendSponsoredTransaction({
620
+ autoDelegate: true,
621
+ calls,
622
+ }, {
623
+ chainId: Number(evmNetwork.chainId),
624
+ delegationRegistry: this.delegation7702Registry,
625
+ environmentId: this.environmentId,
626
+ publicClient: publicClient,
627
+ sdkApi,
628
+ walletClient: sponsorshipWalletClient,
629
+ });
630
+ return transactionHash;
552
631
  });
553
632
  }
554
633
  createUiTransaction(from) {
555
634
  return __awaiter(this, void 0, void 0, function* () {
635
+ var _a;
556
636
  yield this.validateActiveWallet(from);
557
637
  const walletClient = this.getWalletClient();
558
638
  const publicClient = yield this.getPublicClient();
@@ -562,9 +642,19 @@ class DynamicWaasEVMConnector extends withDynamicWaas(EthereumWalletConnector) {
562
642
  if (!publicClient || !walletClient) {
563
643
  throw new DynamicError('No public client available', 'no_public_client_available');
564
644
  }
645
+ const isGasSponsored = yield this.isGasSponsorshipAvailable();
646
+ const sponsoredChainId = Number((_a = this.currentEvmNetwork()) === null || _a === void 0 ? void 0 : _a.chainId);
565
647
  return new ViemUiTransaction({
566
648
  account: from,
649
+ isGasSponsored,
567
650
  onSubmit: (transaction) => __awaiter(this, void 0, void 0, function* () {
651
+ if (isGasSponsored) {
652
+ return this.sendSponsoredUiTransaction({
653
+ accountAddress: from,
654
+ sponsoredChainId,
655
+ transaction,
656
+ });
657
+ }
568
658
  // Non native token
569
659
  if (transaction.nonNativeAddress) {
570
660
  return walletClient.writeContract({
@@ -0,0 +1,39 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var viem = require('viem');
7
+ var utils = require('@dynamic-labs/utils');
8
+
9
+ /**
10
+ * Maps a UI transaction to the batch of calls the sponsored-transaction
11
+ * delegate executes on behalf of the wallet.
12
+ */
13
+ const toSponsoredTransactionCalls = ({ to, value, nonNativeAddress, nonNativeValue, }) => {
14
+ if (!to) {
15
+ throw new utils.DynamicError('Missing recipient, cannot sponsor transaction', 'sponsorship_missing_recipient');
16
+ }
17
+ if (nonNativeAddress) {
18
+ return [
19
+ {
20
+ data: viem.encodeFunctionData({
21
+ abi: viem.erc20Abi,
22
+ args: [to, nonNativeValue !== null && nonNativeValue !== void 0 ? nonNativeValue : BigInt(0)],
23
+ functionName: 'transfer',
24
+ }),
25
+ target: nonNativeAddress,
26
+ value: BigInt(0),
27
+ },
28
+ ];
29
+ }
30
+ return [
31
+ {
32
+ data: '0x',
33
+ target: to,
34
+ value: value !== null && value !== void 0 ? value : BigInt(0),
35
+ },
36
+ ];
37
+ };
38
+
39
+ exports.toSponsoredTransactionCalls = toSponsoredTransactionCalls;
@@ -0,0 +1,13 @@
1
+ import type { SponsoredTransactionCall } from '@dynamic-labs/ethereum-gasless-core';
2
+ type ToSponsoredTransactionCallsParams = {
3
+ to: string | undefined;
4
+ value: bigint | undefined;
5
+ nonNativeAddress?: string;
6
+ nonNativeValue?: bigint;
7
+ };
8
+ /**
9
+ * Maps a UI transaction to the batch of calls the sponsored-transaction
10
+ * delegate executes on behalf of the wallet.
11
+ */
12
+ export declare const toSponsoredTransactionCalls: ({ to, value, nonNativeAddress, nonNativeValue, }: ToSponsoredTransactionCallsParams) => SponsoredTransactionCall[];
13
+ export {};
@@ -0,0 +1,35 @@
1
+ 'use client'
2
+ import { encodeFunctionData, erc20Abi } from 'viem';
3
+ import { DynamicError } from '@dynamic-labs/utils';
4
+
5
+ /**
6
+ * Maps a UI transaction to the batch of calls the sponsored-transaction
7
+ * delegate executes on behalf of the wallet.
8
+ */
9
+ const toSponsoredTransactionCalls = ({ to, value, nonNativeAddress, nonNativeValue, }) => {
10
+ if (!to) {
11
+ throw new DynamicError('Missing recipient, cannot sponsor transaction', 'sponsorship_missing_recipient');
12
+ }
13
+ if (nonNativeAddress) {
14
+ return [
15
+ {
16
+ data: encodeFunctionData({
17
+ abi: erc20Abi,
18
+ args: [to, nonNativeValue !== null && nonNativeValue !== void 0 ? nonNativeValue : BigInt(0)],
19
+ functionName: 'transfer',
20
+ }),
21
+ target: nonNativeAddress,
22
+ value: BigInt(0),
23
+ },
24
+ ];
25
+ }
26
+ return [
27
+ {
28
+ data: '0x',
29
+ target: to,
30
+ value: value !== null && value !== void 0 ? value : BigInt(0),
31
+ },
32
+ ];
33
+ };
34
+
35
+ export { toSponsoredTransactionCalls };
@@ -0,0 +1,37 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var utils = require('@dynamic-labs/utils');
7
+
8
+ const toJsonSafeValue = (value) => {
9
+ if (typeof value === 'bigint') {
10
+ return value.toString();
11
+ }
12
+ if (Array.isArray(value)) {
13
+ return value.map(toJsonSafeValue);
14
+ }
15
+ if (value !== null && typeof value === 'object') {
16
+ const entries = Object.entries(value).map(([key, nestedValue]) => [
17
+ key,
18
+ toJsonSafeValue(nestedValue),
19
+ ]);
20
+ return Object.fromEntries(entries);
21
+ }
22
+ return value;
23
+ };
24
+ /**
25
+ * Wraps a viem custom source so typed-data payloads are stripped of bigints
26
+ * before signing. The WaaS signing transport serializes messages as JSON and
27
+ * rejects bigint values, which EIP-712 sponsored-transaction intents contain.
28
+ */
29
+ const withBigintSafeSignTypedData = (source) => {
30
+ const { signTypedData } = source;
31
+ if (!signTypedData) {
32
+ throw new utils.DynamicError('Custom source does not support signTypedData', 'sign_typed_data_not_supported');
33
+ }
34
+ return Object.assign(Object.assign({}, source), { signTypedData: (typedData) => signTypedData(toJsonSafeValue(typedData)) });
35
+ };
36
+
37
+ exports.withBigintSafeSignTypedData = withBigintSafeSignTypedData;
@@ -0,0 +1,7 @@
1
+ import { CustomSource } from 'viem';
2
+ /**
3
+ * Wraps a viem custom source so typed-data payloads are stripped of bigints
4
+ * before signing. The WaaS signing transport serializes messages as JSON and
5
+ * rejects bigint values, which EIP-712 sponsored-transaction intents contain.
6
+ */
7
+ export declare const withBigintSafeSignTypedData: (source: CustomSource) => CustomSource;
@@ -0,0 +1,33 @@
1
+ 'use client'
2
+ import { DynamicError } from '@dynamic-labs/utils';
3
+
4
+ const toJsonSafeValue = (value) => {
5
+ if (typeof value === 'bigint') {
6
+ return value.toString();
7
+ }
8
+ if (Array.isArray(value)) {
9
+ return value.map(toJsonSafeValue);
10
+ }
11
+ if (value !== null && typeof value === 'object') {
12
+ const entries = Object.entries(value).map(([key, nestedValue]) => [
13
+ key,
14
+ toJsonSafeValue(nestedValue),
15
+ ]);
16
+ return Object.fromEntries(entries);
17
+ }
18
+ return value;
19
+ };
20
+ /**
21
+ * Wraps a viem custom source so typed-data payloads are stripped of bigints
22
+ * before signing. The WaaS signing transport serializes messages as JSON and
23
+ * rejects bigint values, which EIP-712 sponsored-transaction intents contain.
24
+ */
25
+ const withBigintSafeSignTypedData = (source) => {
26
+ const { signTypedData } = source;
27
+ if (!signTypedData) {
28
+ throw new DynamicError('Custom source does not support signTypedData', 'sign_typed_data_not_supported');
29
+ }
30
+ return Object.assign(Object.assign({}, source), { signTypedData: (typedData) => signTypedData(toJsonSafeValue(typedData)) });
31
+ };
32
+
33
+ export { withBigintSafeSignTypedData };