@dynamic-labs-sdk/evm 1.3.0 → 1.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/dist/{addEIP6963Extension-6q4uKJ2S.cjs → addEIP6963Extension-C-2D7v76.cjs} +3 -3
- package/dist/{addEIP6963Extension-6q4uKJ2S.cjs.map → addEIP6963Extension-C-2D7v76.cjs.map} +1 -1
- package/dist/{addEIP6963Extension-C_IKf5DD.native.esm.js → addEIP6963Extension-CrpzqtkA.native.esm.js} +1 -1
- package/dist/{addEIP6963Extension-C_IKf5DD.native.esm.js.map → addEIP6963Extension-CrpzqtkA.native.esm.js.map} +1 -1
- package/dist/{addEIP6963Extension-CSo4PZ83.esm.js → addEIP6963Extension-Dt582bCZ.esm.js} +3 -3
- package/dist/{addEIP6963Extension-CSo4PZ83.esm.js.map → addEIP6963Extension-Dt582bCZ.esm.js.map} +1 -1
- package/dist/{addWaasEvmExtension-L8dUNmj8.native.esm.js → addWaasEvmExtension-CrLafMzM.native.esm.js} +3 -3
- package/dist/{addWaasEvmExtension-L8dUNmj8.native.esm.js.map → addWaasEvmExtension-CrLafMzM.native.esm.js.map} +1 -1
- package/dist/{addWaasEvmExtension-DTmPsJ-R.esm.js → addWaasEvmExtension-CzyCQ7fp.esm.js} +3 -3
- package/dist/{addWaasEvmExtension-DTmPsJ-R.esm.js.map → addWaasEvmExtension-CzyCQ7fp.esm.js.map} +1 -1
- package/dist/{addWaasEvmExtension-FyQx6Qlo.cjs → addWaasEvmExtension-D8O6IjQG.cjs} +3 -3
- package/dist/{addWaasEvmExtension-FyQx6Qlo.cjs.map → addWaasEvmExtension-D8O6IjQG.cjs.map} +1 -1
- package/dist/baseAccount.cjs +3 -3
- package/dist/baseAccount.esm.js +3 -3
- package/dist/baseAccount.native.esm.js +4 -4
- package/dist/{createWalletClientForWalletAccount-CKBR4V6M.cjs → createWalletClientForWalletAccount-CTDnbreU.cjs} +8 -2
- package/dist/{createWalletClientForWalletAccount-CKBR4V6M.cjs.map → createWalletClientForWalletAccount-CTDnbreU.cjs.map} +1 -1
- package/dist/{createWalletClientForWalletAccount-BotF25Kn.native.esm.js → createWalletClientForWalletAccount-CuakQYYA.native.esm.js} +2 -2
- package/dist/{createWalletClientForWalletAccount-BotF25Kn.native.esm.js.map → createWalletClientForWalletAccount-CuakQYYA.native.esm.js.map} +1 -1
- package/dist/{createWalletClientForWalletAccount-DRs8Ja_I.esm.js → createWalletClientForWalletAccount-CzeWTBwv.esm.js} +3 -3
- package/dist/{createWalletClientForWalletAccount-DRs8Ja_I.esm.js.map → createWalletClientForWalletAccount-CzeWTBwv.esm.js.map} +1 -1
- package/dist/{createWalletProviderFromEIP1193Provider-CWWLWjod.native.esm.js → createWalletProviderFromEIP1193Provider-B8doAYSi.native.esm.js} +2 -2
- package/dist/{createWalletProviderFromEIP1193Provider-CWWLWjod.native.esm.js.map → createWalletProviderFromEIP1193Provider-B8doAYSi.native.esm.js.map} +1 -1
- package/dist/{createWalletProviderFromEIP1193Provider-p3Aa46Bi.esm.js → createWalletProviderFromEIP1193Provider-Di6l7mjB.esm.js} +2 -2
- package/dist/{createWalletProviderFromEIP1193Provider-p3Aa46Bi.esm.js.map → createWalletProviderFromEIP1193Provider-Di6l7mjB.esm.js.map} +1 -1
- package/dist/{createWalletProviderFromEIP1193Provider-D-6PlGdy.cjs → createWalletProviderFromEIP1193Provider-_EtpThZ6.cjs} +2 -2
- package/dist/{createWalletProviderFromEIP1193Provider-D-6PlGdy.cjs.map → createWalletProviderFromEIP1193Provider-_EtpThZ6.cjs.map} +1 -1
- package/dist/eip6963.cjs +4 -4
- package/dist/eip6963.esm.js +4 -4
- package/dist/eip6963.native.esm.js +2 -2
- package/dist/evmTransferAmount-3m9QeANI.esm.js +875 -0
- package/dist/evmTransferAmount-3m9QeANI.esm.js.map +1 -0
- package/dist/evmTransferAmount-BQDSXSva.native.esm.js +875 -0
- package/dist/evmTransferAmount-BQDSXSva.native.esm.js.map +1 -0
- package/dist/evmTransferAmount-Bb1YvuCX.cjs +964 -0
- package/dist/evmTransferAmount-Bb1YvuCX.cjs.map +1 -0
- package/dist/exports/metamask.d.ts +6 -0
- package/dist/exports/metamask.d.ts.map +1 -0
- package/dist/gasless/relaySponsoredTransaction/relaySponsoredTransaction.d.ts +6 -0
- package/dist/gasless/relaySponsoredTransaction/relaySponsoredTransaction.d.ts.map +1 -1
- package/dist/gasless/sendSponsoredTransaction/sendSponsoredTransaction.d.ts +6 -0
- package/dist/gasless/sendSponsoredTransaction/sendSponsoredTransaction.d.ts.map +1 -1
- package/dist/gasless/signSponsoredTransaction/signSponsoredTransaction.d.ts +11 -1
- package/dist/gasless/signSponsoredTransaction/signSponsoredTransaction.d.ts.map +1 -1
- package/dist/index.cjs +15 -531
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +7 -523
- package/dist/index.esm.js.map +1 -1
- package/dist/index.native.esm.js +7 -523
- package/dist/index.native.esm.js.map +1 -1
- package/dist/metamask/connectAndVerifyWithMetaMaskUriEvm/connectAndVerifyWithMetaMaskUriEvm.d.ts +17 -0
- package/dist/metamask/connectAndVerifyWithMetaMaskUriEvm/connectAndVerifyWithMetaMaskUriEvm.d.ts.map +1 -0
- package/dist/metamask/connectAndVerifyWithMetaMaskUriEvm/index.d.ts +2 -0
- package/dist/metamask/connectAndVerifyWithMetaMaskUriEvm/index.d.ts.map +1 -0
- package/dist/metamask/connectWithMetaMaskUriEvm/connectWithMetaMaskUriEvm.d.ts +17 -0
- package/dist/metamask/connectWithMetaMaskUriEvm/connectWithMetaMaskUriEvm.d.ts.map +1 -0
- package/dist/metamask/connectWithMetaMaskUriEvm/index.d.ts +3 -0
- package/dist/metamask/connectWithMetaMaskUriEvm/index.d.ts.map +1 -0
- package/dist/metamask/createMetaMaskEvmWalletProvider/createMetaMaskEvmWalletProvider.d.ts +7 -12
- package/dist/metamask/createMetaMaskEvmWalletProvider/createMetaMaskEvmWalletProvider.d.ts.map +1 -1
- package/dist/metamask/createMetaMaskEvmWalletProvider/index.d.ts +0 -1
- package/dist/metamask/createMetaMaskEvmWalletProvider/index.d.ts.map +1 -1
- package/dist/metamask/getMetaMaskEvmExtensionWalletProviderKey/getMetaMaskEvmExtensionWalletProviderKey.d.ts +10 -0
- package/dist/metamask/getMetaMaskEvmExtensionWalletProviderKey/getMetaMaskEvmExtensionWalletProviderKey.d.ts.map +1 -0
- package/dist/metamask/getMetaMaskEvmExtensionWalletProviderKey/index.d.ts +2 -0
- package/dist/metamask/getMetaMaskEvmExtensionWalletProviderKey/index.d.ts.map +1 -0
- package/dist/metamask/metamask.types.d.ts +8 -36
- package/dist/metamask/metamask.types.d.ts.map +1 -1
- package/dist/metamask/utils/createMetaMaskEvmController/createMetaMaskEvmController.d.ts +5 -27
- package/dist/metamask/utils/createMetaMaskEvmController/createMetaMaskEvmController.d.ts.map +1 -1
- package/dist/metamask.cjs +317 -0
- package/dist/metamask.cjs.map +1 -0
- package/dist/metamask.esm.js +309 -0
- package/dist/metamask.esm.js.map +1 -0
- package/dist/metamask.native.esm.js +310 -0
- package/dist/metamask.native.esm.js.map +1 -0
- package/dist/{package-DGj3wg-e.native.esm.js → package-CVMy4p36.native.esm.js} +2 -2
- package/dist/package-CVMy4p36.native.esm.js.map +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/utils/evmExecuteSponsoredSwapTransaction/evmExecuteSponsoredSwapTransaction.d.ts +31 -0
- package/dist/utils/evmExecuteSponsoredSwapTransaction/evmExecuteSponsoredSwapTransaction.d.ts.map +1 -0
- package/dist/utils/evmExecuteSponsoredSwapTransaction/index.d.ts +2 -0
- package/dist/utils/evmExecuteSponsoredSwapTransaction/index.d.ts.map +1 -0
- package/dist/utils/evmExecuteSwapTransaction/evmExecuteSwapTransaction.d.ts +10 -6
- package/dist/utils/evmExecuteSwapTransaction/evmExecuteSwapTransaction.d.ts.map +1 -1
- package/dist/viem.cjs +1 -1
- package/dist/viem.esm.js +1 -1
- package/dist/viem.native.esm.js +2 -2
- package/dist/waas.cjs +3 -3
- package/dist/waas.esm.js +3 -3
- package/dist/waas.native.esm.js +4 -4
- package/dist/walletConnect.cjs +2 -2
- package/dist/walletConnect.esm.js +2 -2
- package/dist/walletConnect.native.esm.js +3 -3
- package/dist/windowInjected.cjs +3 -3
- package/dist/windowInjected.esm.js +3 -3
- package/dist/windowInjected.native.esm.js +4 -4
- package/package.json +10 -4
- package/dist/evmTransferAmount-BJswh1ID.esm.js +0 -289
- package/dist/evmTransferAmount-BJswh1ID.esm.js.map +0 -1
- package/dist/evmTransferAmount-BY0rW4dg.native.esm.js +0 -289
- package/dist/evmTransferAmount-BY0rW4dg.native.esm.js.map +0 -1
- package/dist/evmTransferAmount-CkF4KIge.cjs +0 -324
- package/dist/evmTransferAmount-CkF4KIge.cjs.map +0 -1
- package/dist/metamask/utils/clearMetaMaskEvmSessionStorage/clearMetaMaskEvmSessionStorage.d.ts +0 -34
- package/dist/metamask/utils/clearMetaMaskEvmSessionStorage/clearMetaMaskEvmSessionStorage.d.ts.map +0 -1
- package/dist/metamask/utils/clearMetaMaskEvmSessionStorage/index.d.ts +0 -2
- package/dist/metamask/utils/clearMetaMaskEvmSessionStorage/index.d.ts.map +0 -1
- package/dist/metamask/utils/isConnectShapedResponse/index.d.ts +0 -3
- package/dist/metamask/utils/isConnectShapedResponse/index.d.ts.map +0 -1
- package/dist/metamask/utils/isConnectShapedResponse/isConnectShapedResponse.d.ts +0 -21
- package/dist/metamask/utils/isConnectShapedResponse/isConnectShapedResponse.d.ts.map +0 -1
- package/dist/package-DGj3wg-e.native.esm.js.map +0 -1
|
@@ -0,0 +1,964 @@
|
|
|
1
|
+
const require_createWalletClientForWalletAccount = require('./createWalletClientForWalletAccount-CTDnbreU.cjs');
|
|
2
|
+
let _dynamic_labs_sdk_client = require("@dynamic-labs-sdk/client");
|
|
3
|
+
let _dynamic_labs_sdk_client_core = require("@dynamic-labs-sdk/client/core");
|
|
4
|
+
let viem = require("viem");
|
|
5
|
+
let viem_actions = require("viem/actions");
|
|
6
|
+
|
|
7
|
+
//#region src/errors/SponsorTransactionError/SponsorTransactionError.ts
|
|
8
|
+
var SponsorTransactionError = class extends _dynamic_labs_sdk_client.BaseError {
|
|
9
|
+
constructor(cause, details) {
|
|
10
|
+
super({
|
|
11
|
+
cause: cause ?? null,
|
|
12
|
+
code: "sponsor_transaction_error",
|
|
13
|
+
details,
|
|
14
|
+
docsUrl: null,
|
|
15
|
+
name: "SponsorTransactionError",
|
|
16
|
+
shortMessage: "Failed to sponsor EVM transaction"
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/gasless/constants.ts
|
|
23
|
+
/** The Fireblocks Universal Gasless Delegate (UGD) contract address used for EIP-7702 delegation. */
|
|
24
|
+
const DELEGATION_CONTRACT_ADDRESS = "0x0000Fb7702036ff9f76044a501ac1aA74cbab16b";
|
|
25
|
+
/** Default sponsored transaction validity duration in seconds (10 minutes). */
|
|
26
|
+
const DEFAULT_VALID_FOR_SECONDS = 600;
|
|
27
|
+
/** EIP-7702 delegation code prefix used to identify delegated accounts. */
|
|
28
|
+
const DELEGATION_CODE_PREFIX = "0xef0100";
|
|
29
|
+
/** ERC-7579 batch call with opData and auth mode identifier. */
|
|
30
|
+
const BATCH_CALL_OPDATA_AUTH_MODE = "0x0100000000007821000100000000000000000000000000000000000000000000";
|
|
31
|
+
/** EIP-712 typed data types for UGD AuthorizedExecutions signing. */
|
|
32
|
+
const AUTHORIZED_EXECUTIONS_TYPES = {
|
|
33
|
+
AuthorizedExecutions: [
|
|
34
|
+
{
|
|
35
|
+
name: "calls",
|
|
36
|
+
type: "Execution[]"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "deadline",
|
|
40
|
+
type: "uint256"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "mode",
|
|
44
|
+
type: "bytes32"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "nonce",
|
|
48
|
+
type: "uint256"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "relayer",
|
|
52
|
+
type: "address"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
Execution: [
|
|
56
|
+
{
|
|
57
|
+
name: "target",
|
|
58
|
+
type: "address"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "value",
|
|
62
|
+
type: "uint256"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "data",
|
|
66
|
+
type: "bytes"
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
};
|
|
70
|
+
/** Minimal ABI for the UGD contract's nonce validation function. */
|
|
71
|
+
const UGD_ABI = [{
|
|
72
|
+
inputs: [{
|
|
73
|
+
name: "nonce",
|
|
74
|
+
type: "uint256"
|
|
75
|
+
}],
|
|
76
|
+
name: "isNonceUsed",
|
|
77
|
+
outputs: [{
|
|
78
|
+
name: "",
|
|
79
|
+
type: "bool"
|
|
80
|
+
}],
|
|
81
|
+
stateMutability: "view",
|
|
82
|
+
type: "function"
|
|
83
|
+
}];
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/gasless/generateRandomNonce/generateRandomNonce.ts
|
|
87
|
+
/**
|
|
88
|
+
* Generates a cryptographically random 256-bit nonce.
|
|
89
|
+
*
|
|
90
|
+
* @returns A random bigint nonce.
|
|
91
|
+
* @not-instrumented
|
|
92
|
+
*/
|
|
93
|
+
const generateRandomNonce = () => {
|
|
94
|
+
const bytes = new Uint8Array(32);
|
|
95
|
+
crypto.getRandomValues(bytes);
|
|
96
|
+
return bytes.reduce((acc, byte) => acc << 8n | BigInt(byte), 0n);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/gasless/generateIntentNonce/generateIntentNonce.ts
|
|
101
|
+
/**
|
|
102
|
+
* Generates a random bitmap nonce for UGD AuthorizedExecutions signing.
|
|
103
|
+
*
|
|
104
|
+
* Uses crypto.getRandomValues() for 256-bit randomness. Validates against
|
|
105
|
+
* the on-chain isNonceUsed check as a safety measure, although collision
|
|
106
|
+
* is essentially impossible with 256-bit random values.
|
|
107
|
+
*
|
|
108
|
+
* @param params.walletAccount - The wallet account whose delegation contract is checked.
|
|
109
|
+
* @param [client] - The Dynamic client instance.
|
|
110
|
+
* @returns A unique bigint nonce for the EIP-712 intent.
|
|
111
|
+
* @not-instrumented
|
|
112
|
+
*/
|
|
113
|
+
const generateIntentNonce = async ({ walletAccount }, client) => {
|
|
114
|
+
const nonce = generateRandomNonce();
|
|
115
|
+
const { networkData } = await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, client);
|
|
116
|
+
(0, _dynamic_labs_sdk_client_core.assertDefined)(networkData, `No network data found for wallet account ${walletAccount.address}`);
|
|
117
|
+
const publicClient = require_createWalletClientForWalletAccount.createPublicClientFromNetworkData({ networkData });
|
|
118
|
+
try {
|
|
119
|
+
if (await publicClient.readContract({
|
|
120
|
+
abi: UGD_ABI,
|
|
121
|
+
address: walletAccount.address,
|
|
122
|
+
args: [nonce],
|
|
123
|
+
functionName: "isNonceUsed"
|
|
124
|
+
})) return generateRandomNonce();
|
|
125
|
+
} catch {}
|
|
126
|
+
return nonce;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/gasless/getAvailableEvmGaslessRelayer/getAvailableEvmGaslessRelayer.ts
|
|
131
|
+
/**
|
|
132
|
+
* Fetches the relayer address to embed in the EIP-712 sponsored-transaction
|
|
133
|
+
* intent for the given chain.
|
|
134
|
+
*
|
|
135
|
+
* The returned address is owned by the project's relay backend and is the
|
|
136
|
+
* eventual `from` of the on-chain broadcast. It must be set as the `relayer`
|
|
137
|
+
* field of the EIP-712 intent before signing — the on-chain delegate validates
|
|
138
|
+
* the signature against this address.
|
|
139
|
+
*
|
|
140
|
+
* @param params.chainId - The EVM chain ID the sponsored transaction targets.
|
|
141
|
+
* @param client - The Dynamic client instance.
|
|
142
|
+
* @returns The relayer address to embed in the EIP-712 intent.
|
|
143
|
+
* @throws {SponsorTransactionError} If the API call fails or returns no relayer address.
|
|
144
|
+
* @not-instrumented
|
|
145
|
+
*/
|
|
146
|
+
const getAvailableEvmGaslessRelayer = async ({ chainId }, client) => {
|
|
147
|
+
const core = (0, _dynamic_labs_sdk_client_core.getCore)(client);
|
|
148
|
+
const apiClient = (0, _dynamic_labs_sdk_client_core.createApiClient)({}, client);
|
|
149
|
+
let data;
|
|
150
|
+
try {
|
|
151
|
+
data = await apiClient.getAvailableEVMGaslessRelayer({
|
|
152
|
+
chainId,
|
|
153
|
+
environmentId: core.environmentId
|
|
154
|
+
});
|
|
155
|
+
} catch (error) {
|
|
156
|
+
throw new SponsorTransactionError(error instanceof Error ? error : null);
|
|
157
|
+
}
|
|
158
|
+
if (!data.relayerAddress) throw new SponsorTransactionError();
|
|
159
|
+
return { relayerAddress: data.relayerAddress };
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/gasless/create7702DelegationRegistry/create7702DelegationRegistry.ts
|
|
164
|
+
/**
|
|
165
|
+
* Creates an in-memory registry that tracks which wallet+chain combinations
|
|
166
|
+
* have active EIP-7702 delegation. Only active delegations are cached —
|
|
167
|
+
* a missing entry means the status is unknown and should be checked via RPC.
|
|
168
|
+
*
|
|
169
|
+
* @not-instrumented
|
|
170
|
+
*/
|
|
171
|
+
const create7702DelegationRegistry = () => {
|
|
172
|
+
const delegated = /* @__PURE__ */ new Map();
|
|
173
|
+
const buildKey = ({ chainId, walletAddress }) => `${walletAddress.toLowerCase()}:${chainId}`;
|
|
174
|
+
return {
|
|
175
|
+
isDelegated: (params) => delegated.has(buildKey(params)),
|
|
176
|
+
markDelegated: (params) => {
|
|
177
|
+
delegated.set(buildKey(params), true);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region src/gasless/get7702DelegationRegistry/get7702DelegationRegistry.ts
|
|
184
|
+
/**
|
|
185
|
+
* Returns the per-client EIP-7702 delegation registry, creating it on first access.
|
|
186
|
+
*
|
|
187
|
+
* @not-instrumented
|
|
188
|
+
*/
|
|
189
|
+
const get7702DelegationRegistry = (0, _dynamic_labs_sdk_client_core.createRuntimeServiceAccessKey)("evm-7702-delegation-registry", () => create7702DelegationRegistry());
|
|
190
|
+
|
|
191
|
+
//#endregion
|
|
192
|
+
//#region src/gasless/is7702DelegationActive/is7702DelegationActive.ts
|
|
193
|
+
/**
|
|
194
|
+
* Checks whether EIP-7702 delegation to the Dynamic gasless contract is active
|
|
195
|
+
* for the given wallet account on its current network.
|
|
196
|
+
*
|
|
197
|
+
* Results are cached per wallet+chain in an in-memory registry
|
|
198
|
+
*
|
|
199
|
+
* @param params.walletAccount - The EVM wallet account to check delegation status for.
|
|
200
|
+
* @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
|
|
201
|
+
* @returns True if the wallet has an active delegation to the gasless contract.
|
|
202
|
+
* @not-instrumented
|
|
203
|
+
*/
|
|
204
|
+
const is7702DelegationActive = async ({ walletAccount }, client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
|
|
205
|
+
const { networkData } = await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, client);
|
|
206
|
+
(0, _dynamic_labs_sdk_client_core.assertDefined)(networkData, `No network data found for wallet account ${walletAccount.address}`);
|
|
207
|
+
const chainId = require_createWalletClientForWalletAccount.mapNetworkDataToViemChain(networkData).id;
|
|
208
|
+
const registry = get7702DelegationRegistry(client);
|
|
209
|
+
if (registry.isDelegated({
|
|
210
|
+
chainId,
|
|
211
|
+
walletAddress: walletAccount.address
|
|
212
|
+
})) return true;
|
|
213
|
+
const bytecode = await require_createWalletClientForWalletAccount.createPublicClientFromNetworkData({ networkData }).getCode({ address: walletAccount.address });
|
|
214
|
+
if (!bytecode) return false;
|
|
215
|
+
const expectedPrefix = DELEGATION_CODE_PREFIX + DELEGATION_CONTRACT_ADDRESS.slice(2).toLowerCase();
|
|
216
|
+
const isActive = bytecode.toLowerCase().startsWith(expectedPrefix);
|
|
217
|
+
if (isActive) registry.markDelegated({
|
|
218
|
+
chainId,
|
|
219
|
+
walletAddress: walletAccount.address
|
|
220
|
+
});
|
|
221
|
+
return isActive;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region src/gasless/resolveChainId/resolveChainId.ts
|
|
226
|
+
/**
|
|
227
|
+
* Resolves a chain ID from either an explicit override or the wallet's active network.
|
|
228
|
+
*
|
|
229
|
+
* @param params.chainId - Explicit chain ID override.
|
|
230
|
+
* @param params.walletAccount - The wallet account to resolve the chain from.
|
|
231
|
+
* @param client - The Dynamic client instance.
|
|
232
|
+
* @returns The resolved chain ID.
|
|
233
|
+
* @not-instrumented
|
|
234
|
+
*/
|
|
235
|
+
const resolveChainId = async ({ chainId, walletAccount }, client) => {
|
|
236
|
+
if (chainId !== void 0) return chainId;
|
|
237
|
+
const { networkData } = await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, client);
|
|
238
|
+
(0, _dynamic_labs_sdk_client_core.assertDefined)(networkData, `No network data found for wallet account ${walletAccount.address}`);
|
|
239
|
+
return require_createWalletClientForWalletAccount.mapNetworkDataToViemChain(networkData).id;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region src/gasless/sign7702Authorization/sign7702Authorization.ts
|
|
244
|
+
/**
|
|
245
|
+
* Signs an EIP-7702 authorization to delegate the wallet to the Dynamic
|
|
246
|
+
* gasless delegation contract.
|
|
247
|
+
*
|
|
248
|
+
* The signed authorization can be included in a sponsored transaction to
|
|
249
|
+
* activate the delegation on-chain. If no chainId is provided, the wallet's
|
|
250
|
+
* active network chain ID is used.
|
|
251
|
+
*
|
|
252
|
+
* @param params.walletAccount - The EVM wallet account to sign the authorization for.
|
|
253
|
+
* @param [params.chainId] - Override chain ID. Defaults to the wallet's active network.
|
|
254
|
+
* @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
|
|
255
|
+
* @returns The signed EIP-7702 authorization.
|
|
256
|
+
* @not-instrumented
|
|
257
|
+
*/
|
|
258
|
+
const sign7702Authorization = async ({ walletAccount, chainId }, client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
|
|
259
|
+
return (0, viem_actions.signAuthorization)(await require_createWalletClientForWalletAccount.createWalletClientForWalletAccount({ walletAccount }, client), {
|
|
260
|
+
chainId: await resolveChainId({
|
|
261
|
+
chainId,
|
|
262
|
+
walletAccount
|
|
263
|
+
}, client),
|
|
264
|
+
contractAddress: DELEGATION_CONTRACT_ADDRESS
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
//#endregion
|
|
269
|
+
//#region src/gasless/resolveAuthorization/resolveAuthorization.ts
|
|
270
|
+
/**
|
|
271
|
+
* Resolves the EIP-7702 authorization for a sponsored transaction.
|
|
272
|
+
*
|
|
273
|
+
* Returns the provided authorization if given, auto-signs one if needed
|
|
274
|
+
* and autoDelegate is true, or returns undefined if the wallet is already
|
|
275
|
+
* delegated or autoDelegate is false.
|
|
276
|
+
*
|
|
277
|
+
* @not-instrumented
|
|
278
|
+
*/
|
|
279
|
+
const resolveAuthorization = async ({ authorization, autoDelegate, walletAccount }, client) => {
|
|
280
|
+
if (authorization) return authorization;
|
|
281
|
+
if (!autoDelegate) return;
|
|
282
|
+
if (await is7702DelegationActive({ walletAccount }, client)) return;
|
|
283
|
+
return sign7702Authorization({ walletAccount }, client);
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
//#endregion
|
|
287
|
+
//#region src/gasless/toSerializedAuthorization/toSerializedAuthorization.ts
|
|
288
|
+
/**
|
|
289
|
+
* Converts a viem SignAuthorizationReturnType into a plain serializable object
|
|
290
|
+
* suitable for JSON transport to the sponsorship API.
|
|
291
|
+
*
|
|
292
|
+
* @not-instrumented
|
|
293
|
+
*/
|
|
294
|
+
const toSerializedAuthorization = (auth) => {
|
|
295
|
+
(0, _dynamic_labs_sdk_client_core.assertDefined)(auth.yParity, "Signed authorization is missing yParity");
|
|
296
|
+
return {
|
|
297
|
+
address: auth.address,
|
|
298
|
+
chainId: auth.chainId,
|
|
299
|
+
nonce: auth.nonce,
|
|
300
|
+
r: auth.r,
|
|
301
|
+
s: auth.s,
|
|
302
|
+
yParity: auth.yParity
|
|
303
|
+
};
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region src/gasless/signSponsoredTransaction/signSponsoredTransaction.ts
|
|
308
|
+
/**
|
|
309
|
+
* Signs a sponsored transaction by creating an EIP-712 intent signature.
|
|
310
|
+
*
|
|
311
|
+
* This function handles the complete signing flow:
|
|
312
|
+
* - If an authorization is provided, it is included in the payload.
|
|
313
|
+
* - If autoDelegate is true (default) and no authorization is provided,
|
|
314
|
+
* checks whether delegation is active and signs a 7702 authorization if needed.
|
|
315
|
+
* - If autoDelegate is false and no authorization is provided, the intent
|
|
316
|
+
* is signed without any authorization (user manages delegation separately).
|
|
317
|
+
*
|
|
318
|
+
* @param params.walletAccount - The EVM wallet account to sign with.
|
|
319
|
+
* @param params.calls - The batch of calls to execute.
|
|
320
|
+
* @param [params.authorization] - Pre-signed EIP-7702 authorization. Takes priority over autoDelegate.
|
|
321
|
+
* @param [params.autoDelegate] - Whether to auto-sign 7702 if not delegated. Defaults to true.
|
|
322
|
+
* @param [params.nonce] - Optional bitmap nonce. When provided, nonce generation (and its on-chain check) is skipped and the supplied value is used.
|
|
323
|
+
* @param [params.validForSeconds] - How long the signed intent remains valid, in seconds. Defaults to 600 (10 minutes).
|
|
324
|
+
* @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
|
|
325
|
+
* @returns The signed sponsored transaction payload ready to be sent to the API.
|
|
326
|
+
* @not-instrumented
|
|
327
|
+
*/
|
|
328
|
+
const signSponsoredTransaction = async ({ walletAccount, calls, authorization, autoDelegate = true, nonce: providedNonce, validForSeconds = DEFAULT_VALID_FOR_SECONDS }, client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
|
|
329
|
+
const { networkData } = await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, client);
|
|
330
|
+
(0, _dynamic_labs_sdk_client_core.assertDefined)(networkData, `No network data found for wallet account ${walletAccount.address}`);
|
|
331
|
+
const resolvedAuthorization = await resolveAuthorization({
|
|
332
|
+
authorization,
|
|
333
|
+
autoDelegate,
|
|
334
|
+
walletAccount
|
|
335
|
+
}, client);
|
|
336
|
+
const nonce = providedNonce ?? await generateIntentNonce({ walletAccount }, client);
|
|
337
|
+
const deadline = BigInt(Math.floor(Date.now() / 1e3) + validForSeconds);
|
|
338
|
+
const chainId = require_createWalletClientForWalletAccount.mapNetworkDataToViemChain(networkData).id;
|
|
339
|
+
const { relayerAddress } = await getAvailableEvmGaslessRelayer({ chainId }, client);
|
|
340
|
+
const signature = await (await require_createWalletClientForWalletAccount.createWalletClientForWalletAccount({ walletAccount }, client)).signTypedData({
|
|
341
|
+
domain: {
|
|
342
|
+
chainId,
|
|
343
|
+
verifyingContract: DELEGATION_CONTRACT_ADDRESS
|
|
344
|
+
},
|
|
345
|
+
message: {
|
|
346
|
+
calls: calls.map((c) => ({
|
|
347
|
+
data: c.data,
|
|
348
|
+
target: c.target,
|
|
349
|
+
value: c.value
|
|
350
|
+
})),
|
|
351
|
+
deadline,
|
|
352
|
+
mode: BATCH_CALL_OPDATA_AUTH_MODE,
|
|
353
|
+
nonce,
|
|
354
|
+
relayer: relayerAddress
|
|
355
|
+
},
|
|
356
|
+
primaryType: "AuthorizedExecutions",
|
|
357
|
+
types: AUTHORIZED_EXECUTIONS_TYPES
|
|
358
|
+
});
|
|
359
|
+
return {
|
|
360
|
+
authorization: resolvedAuthorization ? toSerializedAuthorization(resolvedAuthorization) : void 0,
|
|
361
|
+
calls,
|
|
362
|
+
chainId,
|
|
363
|
+
deadline: deadline.toString(),
|
|
364
|
+
nonce: nonce.toString(),
|
|
365
|
+
relayer: relayerAddress,
|
|
366
|
+
signature,
|
|
367
|
+
walletAddress: walletAccount.address
|
|
368
|
+
};
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
//#endregion
|
|
372
|
+
//#region src/gasless/relaySponsoredTransaction/relaySponsoredTransaction.ts
|
|
373
|
+
const isSignedTransactionParams = (params) => "signedTransaction" in params;
|
|
374
|
+
/**
|
|
375
|
+
* Relays a sponsored EVM transaction to the Dynamic backend.
|
|
376
|
+
*
|
|
377
|
+
* Accepts either a pre-signed transaction or unsigned calls. When given
|
|
378
|
+
* unsigned calls, signs the transaction first via signSponsoredTransaction.
|
|
379
|
+
*
|
|
380
|
+
* The backend encodes the transaction, submits it to the relay provider,
|
|
381
|
+
* and returns a request ID for tracking. The relay may retry the on-chain
|
|
382
|
+
* submission, so the request ID (not a transaction hash) is the stable
|
|
383
|
+
* identifier for the sponsored transaction.
|
|
384
|
+
*
|
|
385
|
+
* @param params - Either { signedTransaction } or { walletAccount, calls, ... }.
|
|
386
|
+
* @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
|
|
387
|
+
* @returns An object containing the request ID for tracking the relayed transaction.
|
|
388
|
+
* @throws {SponsorTransactionError} If the API call fails or returns an unexpected response.
|
|
389
|
+
* @not-instrumented
|
|
390
|
+
*/
|
|
391
|
+
const relaySponsoredTransaction = async (params, client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
|
|
392
|
+
const signedTransaction = isSignedTransactionParams(params) ? params.signedTransaction : await signSponsoredTransaction({
|
|
393
|
+
authorization: params.authorization,
|
|
394
|
+
autoDelegate: params.autoDelegate,
|
|
395
|
+
calls: params.calls,
|
|
396
|
+
nonce: params.nonce,
|
|
397
|
+
validForSeconds: params.validForSeconds ?? DEFAULT_VALID_FOR_SECONDS,
|
|
398
|
+
walletAccount: params.walletAccount
|
|
399
|
+
}, client);
|
|
400
|
+
const core = (0, _dynamic_labs_sdk_client_core.getCore)(client);
|
|
401
|
+
const apiClient = (0, _dynamic_labs_sdk_client_core.createApiClient)({}, client);
|
|
402
|
+
let data;
|
|
403
|
+
try {
|
|
404
|
+
data = await apiClient.sponsorEVMTransaction({
|
|
405
|
+
environmentId: core.environmentId,
|
|
406
|
+
sponsorEVMTransactionRequest: {
|
|
407
|
+
authorization: signedTransaction.authorization,
|
|
408
|
+
calls: signedTransaction.calls.map((c) => ({
|
|
409
|
+
data: c.data,
|
|
410
|
+
target: c.target,
|
|
411
|
+
value: c.value.toString()
|
|
412
|
+
})),
|
|
413
|
+
chainId: signedTransaction.chainId,
|
|
414
|
+
deadline: signedTransaction.deadline,
|
|
415
|
+
nonce: signedTransaction.nonce,
|
|
416
|
+
relayer: signedTransaction.relayer,
|
|
417
|
+
signature: signedTransaction.signature,
|
|
418
|
+
walletAddress: signedTransaction.walletAddress
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
} catch (error) {
|
|
422
|
+
throw new SponsorTransactionError(error instanceof Error ? error : null);
|
|
423
|
+
}
|
|
424
|
+
if (!data.requestId) throw new SponsorTransactionError();
|
|
425
|
+
return { requestId: data.requestId };
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/gasless/getEVMSponsoredTransactionStatus/getEVMSponsoredTransactionStatus.ts
|
|
430
|
+
/**
|
|
431
|
+
* Fetches the current relay state for a sponsored EVM transaction.
|
|
432
|
+
*
|
|
433
|
+
* Returns the lifecycle status, the on-chain transaction hash (when the relay
|
|
434
|
+
* has broadcast it), and any terminal-failure error message. Use this as the
|
|
435
|
+
* building block for custom polling flows; for the common "wait until done"
|
|
436
|
+
* case prefer `waitForSponsoredTransaction`.
|
|
437
|
+
*
|
|
438
|
+
* @param params.requestId - The request ID returned when the transaction was relayed.
|
|
439
|
+
* @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
|
|
440
|
+
* @returns The current status, optional transaction hash, and optional error message.
|
|
441
|
+
* @throws {SponsorTransactionError} If the API call fails.
|
|
442
|
+
* @not-instrumented
|
|
443
|
+
*/
|
|
444
|
+
const getEVMSponsoredTransactionStatus = async ({ requestId }, client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
|
|
445
|
+
const core = (0, _dynamic_labs_sdk_client_core.getCore)(client);
|
|
446
|
+
const apiClient = (0, _dynamic_labs_sdk_client_core.createApiClient)({}, client);
|
|
447
|
+
let data;
|
|
448
|
+
try {
|
|
449
|
+
data = await apiClient.getEVMSponsoredTransactionStatus({
|
|
450
|
+
environmentId: core.environmentId,
|
|
451
|
+
requestId
|
|
452
|
+
});
|
|
453
|
+
} catch (error) {
|
|
454
|
+
throw new SponsorTransactionError(error instanceof Error ? error : null);
|
|
455
|
+
}
|
|
456
|
+
return {
|
|
457
|
+
errorMessage: data.errorMessage,
|
|
458
|
+
status: data.status,
|
|
459
|
+
transactionHash: data.transactionHash
|
|
460
|
+
};
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
//#endregion
|
|
464
|
+
//#region src/gasless/waitForSponsoredTransaction/waitForSponsoredTransaction.ts
|
|
465
|
+
const POLL_INTERVAL_MS = 2e3;
|
|
466
|
+
const MAX_POLLING_ATTEMPTS = 6e4 / POLL_INTERVAL_MS;
|
|
467
|
+
const TERMINAL_FAILURE_STATUSES = new Set(["failure"]);
|
|
468
|
+
/**
|
|
469
|
+
* Polls `getEVMSponsoredTransactionStatus` until the relay reports the
|
|
470
|
+
* transaction has been included on-chain, then returns the transaction hash.
|
|
471
|
+
*
|
|
472
|
+
* @param params.requestId - The request ID returned when the transaction was relayed.
|
|
473
|
+
* @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
|
|
474
|
+
* @returns An object containing the on-chain transaction hash.
|
|
475
|
+
* @throws {SponsorTransactionError} If the relay returns a terminal failure or polling times out.
|
|
476
|
+
* @not-instrumented
|
|
477
|
+
*/
|
|
478
|
+
const waitForSponsoredTransaction = async ({ requestId }, client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => {
|
|
479
|
+
for (let attempt = 0; attempt < MAX_POLLING_ATTEMPTS; attempt++) {
|
|
480
|
+
const result = await getEVMSponsoredTransactionStatus({ requestId }, client);
|
|
481
|
+
if (TERMINAL_FAILURE_STATUSES.has(result.status)) throw new SponsorTransactionError(null, result.errorMessage);
|
|
482
|
+
if (result.transactionHash) return { transactionHash: result.transactionHash };
|
|
483
|
+
if (attempt < MAX_POLLING_ATTEMPTS - 1) await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
484
|
+
}
|
|
485
|
+
throw new SponsorTransactionError(null, `Timed out waiting for sponsored transaction ${requestId}`);
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
//#endregion
|
|
489
|
+
//#region src/gasless/sendSponsoredTransaction/sendSponsoredTransaction.ts
|
|
490
|
+
/**
|
|
491
|
+
* Sends a sponsored EVM transaction and waits for on-chain inclusion.
|
|
492
|
+
*
|
|
493
|
+
* Accepts either a pre-signed transaction or unsigned calls. When given
|
|
494
|
+
* unsigned calls, signs the transaction first via signSponsoredTransaction.
|
|
495
|
+
* Relays the transaction and resolves as soon as the relay reports the
|
|
496
|
+
* transaction has been included on-chain.
|
|
497
|
+
*
|
|
498
|
+
* @param params - Either { signedTransaction } or { walletAccount, calls, ... }.
|
|
499
|
+
* @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
|
|
500
|
+
* @returns An object containing the on-chain transaction hash.
|
|
501
|
+
* @throws {SponsorTransactionError} If the relay returns a terminal failure or polling times out.
|
|
502
|
+
* @not-instrumented
|
|
503
|
+
*/
|
|
504
|
+
const sendSponsoredTransaction = async (params, client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => {
|
|
505
|
+
const { requestId } = await relaySponsoredTransaction(params, client);
|
|
506
|
+
return waitForSponsoredTransaction({ requestId }, client);
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
//#endregion
|
|
510
|
+
//#region src/errors/RpcError.ts
|
|
511
|
+
var RpcError = class extends _dynamic_labs_sdk_client.BaseError {
|
|
512
|
+
constructor(args) {
|
|
513
|
+
super({
|
|
514
|
+
cause: args.cause ?? null,
|
|
515
|
+
code: args.code ?? "rpc_error",
|
|
516
|
+
details: args.details,
|
|
517
|
+
docsUrl: args.docsUrl ?? null,
|
|
518
|
+
metaMessages: args.metaMessages,
|
|
519
|
+
name: args.name ?? "RpcError",
|
|
520
|
+
shortMessage: args.shortMessage
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
//#endregion
|
|
526
|
+
//#region src/utils/fetchEvmBalance/fetchEvmBalance.ts
|
|
527
|
+
/** @not-instrumented */
|
|
528
|
+
const fetchEvmBalance = async ({ address, networkData }, client) => {
|
|
529
|
+
const rpcUrl = networkData.rpcUrls.http[0];
|
|
530
|
+
const core = (0, _dynamic_labs_sdk_client_core.getCore)(client);
|
|
531
|
+
try {
|
|
532
|
+
const response = await core.fetch(rpcUrl, {
|
|
533
|
+
body: JSON.stringify({
|
|
534
|
+
id: Math.floor(Date.now() + Math.random() * 1e3),
|
|
535
|
+
jsonrpc: "2.0",
|
|
536
|
+
method: "eth_getBalance",
|
|
537
|
+
params: [address, "latest"]
|
|
538
|
+
}),
|
|
539
|
+
headers: { "Content-Type": "application/json" },
|
|
540
|
+
method: "POST"
|
|
541
|
+
});
|
|
542
|
+
if (!response.ok) throw new RpcError({
|
|
543
|
+
code: "http_error",
|
|
544
|
+
shortMessage: `HTTP error! status: ${response.status}`
|
|
545
|
+
});
|
|
546
|
+
const data = await response.json();
|
|
547
|
+
if (data.error) throw new RpcError({
|
|
548
|
+
cause: data.error instanceof Error ? data.error : void 0,
|
|
549
|
+
code: "json_rpc_error",
|
|
550
|
+
shortMessage: `RPC Error: ${data.error.message}`
|
|
551
|
+
});
|
|
552
|
+
const balanceWeiHex = data.result;
|
|
553
|
+
const balanceWei = BigInt(balanceWeiHex);
|
|
554
|
+
const oneEther = BigInt(0xde0b6b3a7640000);
|
|
555
|
+
return (Number(balanceWei) / Number(oneEther)).toString();
|
|
556
|
+
} catch (error) {
|
|
557
|
+
if (error instanceof Error) throw new RpcError({
|
|
558
|
+
cause: error,
|
|
559
|
+
code: "rpc_error",
|
|
560
|
+
shortMessage: `Failed to fetch balance for address ${address}`
|
|
561
|
+
});
|
|
562
|
+
throw error;
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
//#endregion
|
|
567
|
+
//#region src/utils/createEvmNetworkProvider/createEvmNetworkProvider.ts
|
|
568
|
+
/** @not-instrumented */
|
|
569
|
+
const createEvmNetworkProvider = (networkData, client) => ({
|
|
570
|
+
...(0, _dynamic_labs_sdk_client_core.createBaseNetworkProvider)("EVM", networkData),
|
|
571
|
+
getBalance: async ({ address }) => ({ balance: await fetchEvmBalance({
|
|
572
|
+
address,
|
|
573
|
+
networkData
|
|
574
|
+
}, client) })
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
//#endregion
|
|
578
|
+
//#region src/registerEvmNetworkProviderBuilder/registerEvmNetworkProviderBuilder.ts
|
|
579
|
+
/** @not-instrumented */
|
|
580
|
+
const registerEvmNetworkProviderBuilder = (client) => {
|
|
581
|
+
const networkProviderBuilderRegistry = (0, _dynamic_labs_sdk_client_core.getNetworkProviderBuilderRegistry)(client);
|
|
582
|
+
/**
|
|
583
|
+
* If the Ethereum network provider builder is already registered, return.
|
|
584
|
+
*/
|
|
585
|
+
if (networkProviderBuilderRegistry.get().get("EVM")) return;
|
|
586
|
+
networkProviderBuilderRegistry.register({
|
|
587
|
+
builder: (networkData) => createEvmNetworkProvider(networkData, client),
|
|
588
|
+
chain: "EVM"
|
|
589
|
+
});
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
//#endregion
|
|
593
|
+
//#region src/utils/isEvmWalletAccount/isEvmWalletAccount.ts
|
|
594
|
+
/**
|
|
595
|
+
* Type guard function to check if a wallet account is an EVM wallet account.
|
|
596
|
+
*
|
|
597
|
+
* @param walletAccount - The wallet account to check.
|
|
598
|
+
* @returns True if the wallet account is an EVM wallet account, false otherwise.
|
|
599
|
+
* @not-instrumented
|
|
600
|
+
*/
|
|
601
|
+
const isEvmWalletAccount = (walletAccount) => walletAccount.chain === "EVM";
|
|
602
|
+
|
|
603
|
+
//#endregion
|
|
604
|
+
//#region src/utils/evmConfirmTransaction/evmConfirmTransaction.ts
|
|
605
|
+
/**
|
|
606
|
+
* Waits for an EVM transaction to be confirmed on-chain.
|
|
607
|
+
*
|
|
608
|
+
* @param params.transactionHash - The transaction hash to wait for.
|
|
609
|
+
* @param params.walletAccount - The EVM wallet account used to resolve the active network.
|
|
610
|
+
* @param client - The Dynamic client instance.
|
|
611
|
+
* @not-instrumented
|
|
612
|
+
*/
|
|
613
|
+
const evmConfirmTransaction = async ({ transactionHash, walletAccount }, client) => {
|
|
614
|
+
if (!isEvmWalletAccount(walletAccount)) throw new _dynamic_labs_sdk_client.InvalidParamError("Wallet account is not an EVM wallet account");
|
|
615
|
+
const { networkData } = await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, client);
|
|
616
|
+
(0, _dynamic_labs_sdk_client_core.assertDefined)(networkData, `No network data found for wallet account ${walletAccount.address}`);
|
|
617
|
+
await require_createWalletClientForWalletAccount.createPublicClientFromNetworkData({ networkData }).waitForTransactionReceipt({ hash: transactionHash });
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
//#endregion
|
|
621
|
+
//#region src/gasless/isEvmGasSponsorshipEnabled/isEvmGasSponsorshipEnabled.ts
|
|
622
|
+
/**
|
|
623
|
+
* Checks if EVM gas sponsorship is enabled for the current project.
|
|
624
|
+
*
|
|
625
|
+
* @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
|
|
626
|
+
* @returns True if EVM gas sponsorship is enabled, false otherwise.
|
|
627
|
+
* @not-instrumented
|
|
628
|
+
*/
|
|
629
|
+
const isEvmGasSponsorshipEnabled = (client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => {
|
|
630
|
+
(0, _dynamic_labs_sdk_client_core.assertDefined)(client.projectSettings, "Project settings are not defined");
|
|
631
|
+
return client.projectSettings.sdk.embeddedWallets?.evmGasSponsorshipEnabled ?? false;
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
//#endregion
|
|
635
|
+
//#region src/utils/approveErc20/approveErc20.ts
|
|
636
|
+
/**
|
|
637
|
+
* Sends an ERC-20 `approve` transaction, granting a spender an allowance
|
|
638
|
+
* to transfer tokens on behalf of the wallet account.
|
|
639
|
+
*
|
|
640
|
+
* Encodes the `approve(spender, amount)` call using viem's `encodeFunctionData`
|
|
641
|
+
* and sends it through the wallet account's viem wallet client.
|
|
642
|
+
*
|
|
643
|
+
* @param params.amount - The amount to approve in the token's smallest unit.
|
|
644
|
+
* @param params.spenderAddress - The address being granted the allowance.
|
|
645
|
+
* @param params.tokenAddress - The ERC-20 token contract address.
|
|
646
|
+
* @param params.walletAccount - The EVM wallet account sending the approval.
|
|
647
|
+
* @param client - The Dynamic client instance.
|
|
648
|
+
* @returns The approval transaction hash.
|
|
649
|
+
* @not-instrumented
|
|
650
|
+
*/
|
|
651
|
+
const approveErc20 = async ({ amount, spenderAddress, tokenAddress, walletAccount }, client) => {
|
|
652
|
+
const walletClient = await require_createWalletClientForWalletAccount.createWalletClientForWalletAccount({ walletAccount }, client);
|
|
653
|
+
const data = (0, viem.encodeFunctionData)({
|
|
654
|
+
abi: viem.erc20Abi,
|
|
655
|
+
args: [spenderAddress, amount],
|
|
656
|
+
functionName: "approve"
|
|
657
|
+
});
|
|
658
|
+
return { transactionHash: await walletClient.sendTransaction({
|
|
659
|
+
data,
|
|
660
|
+
to: tokenAddress
|
|
661
|
+
}) };
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
//#endregion
|
|
665
|
+
//#region src/utils/getErc20Allowance/getErc20Allowance.ts
|
|
666
|
+
/**
|
|
667
|
+
* Reads the current ERC-20 token allowance granted by an owner to a spender.
|
|
668
|
+
*
|
|
669
|
+
* Uses a viem public client derived from the wallet account's active network
|
|
670
|
+
* to call the `allowance(owner, spender)` method on the token contract.
|
|
671
|
+
*
|
|
672
|
+
* @param params.tokenAddress - The ERC-20 token contract address.
|
|
673
|
+
* @param params.ownerAddress - The address that granted the allowance.
|
|
674
|
+
* @param params.spenderAddress - The address allowed to spend the tokens.
|
|
675
|
+
* @param params.walletAccount - The EVM wallet account used to resolve the active network.
|
|
676
|
+
* @param [params.networkData] - The network data to use for the public client. If not provided, the active network data will be used.
|
|
677
|
+
* @param client - The Dynamic client instance.
|
|
678
|
+
* @returns The current allowance as a bigint in the token's smallest unit.
|
|
679
|
+
* @not-instrumented
|
|
680
|
+
*/
|
|
681
|
+
const getErc20Allowance = async ({ networkData, ownerAddress, spenderAddress, tokenAddress, walletAccount }, client) => {
|
|
682
|
+
if (!networkData) networkData = (await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, client)).networkData;
|
|
683
|
+
(0, _dynamic_labs_sdk_client_core.assertDefined)(networkData, `No network data found for wallet account ${walletAccount.address}`);
|
|
684
|
+
return require_createWalletClientForWalletAccount.createPublicClientFromNetworkData({ networkData }).readContract({
|
|
685
|
+
abi: viem.erc20Abi,
|
|
686
|
+
address: tokenAddress,
|
|
687
|
+
args: [ownerAddress, spenderAddress],
|
|
688
|
+
functionName: "allowance"
|
|
689
|
+
});
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
//#endregion
|
|
693
|
+
//#region src/utils/approveErc20IfRequiredAndWaitReceipt/approveErc20IfRequiredAndWaitReceipt.ts
|
|
694
|
+
/**
|
|
695
|
+
* Approves an ERC-20 token if the current allowance is insufficient and waits for the transaction receipt.
|
|
696
|
+
*
|
|
697
|
+
* @param params.amount - The amount of tokens to approve.
|
|
698
|
+
* @param params.ownerAddress - The address that granted the allowance.
|
|
699
|
+
* @param params.spenderAddress - The address allowed to spend the tokens.
|
|
700
|
+
* @param params.tokenAddress - The ERC-20 token contract address.
|
|
701
|
+
* @param params.walletAccount - The EVM wallet account used to resolve the active network.
|
|
702
|
+
* @param client - The Dynamic client instance.
|
|
703
|
+
* @returns The transaction receipt if an approval was sent, otherwise undefined.
|
|
704
|
+
* @not-instrumented
|
|
705
|
+
*/
|
|
706
|
+
const approveErc20IfRequiredAndWaitReceipt = async ({ amount, spenderAddress, tokenAddress, walletAccount }, client) => {
|
|
707
|
+
const { networkData } = await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, client);
|
|
708
|
+
(0, _dynamic_labs_sdk_client_core.assertDefined)(networkData, `No network data found for wallet account ${walletAccount.address}`);
|
|
709
|
+
const currentAllowance = await getErc20Allowance({
|
|
710
|
+
networkData,
|
|
711
|
+
ownerAddress: walletAccount.address,
|
|
712
|
+
spenderAddress,
|
|
713
|
+
tokenAddress,
|
|
714
|
+
walletAccount
|
|
715
|
+
}, client);
|
|
716
|
+
const approvalAmount = BigInt(amount);
|
|
717
|
+
if (currentAllowance >= approvalAmount) return;
|
|
718
|
+
const approvalTransactionHash = (await approveErc20({
|
|
719
|
+
amount: approvalAmount,
|
|
720
|
+
spenderAddress,
|
|
721
|
+
tokenAddress,
|
|
722
|
+
walletAccount
|
|
723
|
+
}, client)).transactionHash;
|
|
724
|
+
return { receipt: await require_createWalletClientForWalletAccount.createPublicClientFromNetworkData({ networkData }).waitForTransactionReceipt({ hash: approvalTransactionHash }) };
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
//#endregion
|
|
728
|
+
//#region src/utils/evmExecuteSponsoredSwapTransaction/evmExecuteSponsoredSwapTransaction.ts
|
|
729
|
+
/**
|
|
730
|
+
* Executes an EVM swap as a single gas-sponsored transaction.
|
|
731
|
+
*
|
|
732
|
+
* Unlike the user-paid path, the optional ERC-20 approval and the swap call
|
|
733
|
+
* are batched into one sponsored transaction (EVM gas sponsorship supports
|
|
734
|
+
* call batching), so there is no separate approval transaction hash.
|
|
735
|
+
*
|
|
736
|
+
* 1. If the signing payload includes an `evmApproval`, reads the current
|
|
737
|
+
* allowance and prepends an `approve` call only when it is insufficient
|
|
738
|
+
* 2. Appends the main swap call (gas fields are dropped — the relayer pays gas)
|
|
739
|
+
* 3. Relays the batch via `sendSponsoredTransaction` and waits for inclusion
|
|
740
|
+
*
|
|
741
|
+
* @param params.signingPayload - The signing payload containing `evmTransaction` and optional `evmApproval`.
|
|
742
|
+
* @param params.walletAccount - The embedded EVM wallet account whose gas is sponsored.
|
|
743
|
+
* @param params.onStepChange - Optional callback invoked with `'approval'` or `'transaction'` as each step begins.
|
|
744
|
+
* @param client - The Dynamic client instance.
|
|
745
|
+
* @returns The on-chain transaction hash of the sponsored swap.
|
|
746
|
+
* @not-instrumented
|
|
747
|
+
*/
|
|
748
|
+
const evmExecuteSponsoredSwapTransaction = async ({ onStepChange, signingPayload, walletAccount }, client) => {
|
|
749
|
+
const { evmTransaction, evmApproval } = signingPayload;
|
|
750
|
+
if (!evmTransaction) throw new _dynamic_labs_sdk_client.InvalidParamError("Signing payload is missing EVM transaction data");
|
|
751
|
+
const calls = [];
|
|
752
|
+
if (evmApproval) {
|
|
753
|
+
const approvalAmount = BigInt(evmApproval.amount);
|
|
754
|
+
if (await getErc20Allowance({
|
|
755
|
+
ownerAddress: walletAccount.address,
|
|
756
|
+
spenderAddress: evmApproval.spenderAddress,
|
|
757
|
+
tokenAddress: evmApproval.tokenAddress,
|
|
758
|
+
walletAccount
|
|
759
|
+
}, client) < approvalAmount) {
|
|
760
|
+
onStepChange?.("approval");
|
|
761
|
+
calls.push({
|
|
762
|
+
data: (0, viem.encodeFunctionData)({
|
|
763
|
+
abi: viem.erc20Abi,
|
|
764
|
+
args: [evmApproval.spenderAddress, approvalAmount],
|
|
765
|
+
functionName: "approve"
|
|
766
|
+
}),
|
|
767
|
+
target: evmApproval.tokenAddress,
|
|
768
|
+
value: 0n
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
onStepChange?.("transaction");
|
|
773
|
+
calls.push({
|
|
774
|
+
data: evmTransaction.data,
|
|
775
|
+
target: evmTransaction.to,
|
|
776
|
+
value: evmTransaction.value ? BigInt(evmTransaction.value) : 0n
|
|
777
|
+
});
|
|
778
|
+
const { transactionHash } = await sendSponsoredTransaction({
|
|
779
|
+
calls,
|
|
780
|
+
walletAccount
|
|
781
|
+
}, client);
|
|
782
|
+
return { transactionHash };
|
|
783
|
+
};
|
|
784
|
+
|
|
785
|
+
//#endregion
|
|
786
|
+
//#region src/utils/evmExecuteSwapTransaction/evmExecuteSwapTransaction.ts
|
|
787
|
+
/**
|
|
788
|
+
* Executes an EVM checkout transaction by handling optional ERC-20 approval
|
|
789
|
+
* and sending the main swap transaction on-chain.
|
|
790
|
+
*
|
|
791
|
+
* 1. Validates that the wallet account is an EVM wallet account
|
|
792
|
+
* 2. When EVM gas sponsorship is enabled and the wallet is a Dynamic embedded
|
|
793
|
+
* wallet (and `sponsorshipMode` is not `'off'`), routes the swap through the
|
|
794
|
+
* gas-sponsored path, batching any required approval with the swap call
|
|
795
|
+
* 3. Otherwise, if the signing payload includes an `evmApproval`, checks the
|
|
796
|
+
* current ERC-20 allowance and sends an approve transaction when insufficient
|
|
797
|
+
* 4. Sends the main transaction using the viem wallet client
|
|
798
|
+
*
|
|
799
|
+
* @param params.signingPayload - The chain-aware signing payload containing `evmTransaction` and optional `evmApproval`.
|
|
800
|
+
* @param params.walletAccount - The wallet account used to sign and send transactions.
|
|
801
|
+
* @param params.onStepChange - Optional callback invoked with `'approval'` or `'transaction'` as each step begins.
|
|
802
|
+
* @param params.sponsorshipMode - `'auto'` (default) sponsors when eligible; `'off'` never sponsors.
|
|
803
|
+
* @param client - The Dynamic client instance.
|
|
804
|
+
* @returns The main transaction hash and, if a separate approval was sent, the approval transaction hash.
|
|
805
|
+
* @not-instrumented
|
|
806
|
+
*/
|
|
807
|
+
const evmExecuteSwapTransaction = async ({ onStepChange, signingPayload, sponsorshipMode = "auto", walletAccount }, client) => {
|
|
808
|
+
if (!isEvmWalletAccount(walletAccount)) throw new _dynamic_labs_sdk_client.InvalidParamError("Wallet account is not an EVM wallet account");
|
|
809
|
+
const walletProvider = (0, _dynamic_labs_sdk_client_core.getWalletProviderFromWalletAccount)({ walletAccount }, client);
|
|
810
|
+
if (sponsorshipMode === "auto" && isEvmGasSponsorshipEnabled(client) && require_createWalletClientForWalletAccount.isEvmWalletProviderWithCustomViemClient(walletProvider)) return evmExecuteSponsoredSwapTransaction({
|
|
811
|
+
onStepChange,
|
|
812
|
+
signingPayload,
|
|
813
|
+
walletAccount
|
|
814
|
+
}, client);
|
|
815
|
+
const { evmTransaction, evmApproval } = signingPayload;
|
|
816
|
+
if (!evmTransaction) throw new _dynamic_labs_sdk_client.InvalidParamError("Signing payload is missing EVM transaction data");
|
|
817
|
+
if (evmApproval) {
|
|
818
|
+
onStepChange?.("approval");
|
|
819
|
+
await approveErc20IfRequiredAndWaitReceipt({
|
|
820
|
+
amount: evmApproval.amount,
|
|
821
|
+
spenderAddress: evmApproval.spenderAddress,
|
|
822
|
+
tokenAddress: evmApproval.tokenAddress,
|
|
823
|
+
walletAccount
|
|
824
|
+
}, client);
|
|
825
|
+
}
|
|
826
|
+
onStepChange?.("transaction");
|
|
827
|
+
const walletClient = await require_createWalletClientForWalletAccount.createWalletClientForWalletAccount({ walletAccount }, client);
|
|
828
|
+
let gasParams = {};
|
|
829
|
+
if (evmTransaction.maxFeePerGas && evmTransaction.maxPriorityFeePerGas) gasParams = {
|
|
830
|
+
maxFeePerGas: BigInt(evmTransaction.maxFeePerGas),
|
|
831
|
+
maxPriorityFeePerGas: BigInt(evmTransaction.maxPriorityFeePerGas)
|
|
832
|
+
};
|
|
833
|
+
else gasParams = { ...evmTransaction.gasPrice && { gasPrice: BigInt(evmTransaction.gasPrice) } };
|
|
834
|
+
return { transactionHash: await walletClient.sendTransaction({
|
|
835
|
+
data: evmTransaction.data,
|
|
836
|
+
to: evmTransaction.to,
|
|
837
|
+
value: evmTransaction.value ? BigInt(evmTransaction.value) : 0n,
|
|
838
|
+
...evmTransaction.gasLimit && { gas: BigInt(evmTransaction.gasLimit) },
|
|
839
|
+
...gasParams,
|
|
840
|
+
...evmTransaction.nonce && { nonce: evmTransaction.nonce }
|
|
841
|
+
}) };
|
|
842
|
+
};
|
|
843
|
+
|
|
844
|
+
//#endregion
|
|
845
|
+
//#region src/utils/evmTransferAmount/evmTransferAmount.ts
|
|
846
|
+
const DEFAULT_DECIMALS = 18;
|
|
847
|
+
/** @not-instrumented */
|
|
848
|
+
const evmTransferAmount = async ({ amount, recipient, token, walletAccount }, client) => {
|
|
849
|
+
if (!isEvmWalletAccount(walletAccount)) throw new _dynamic_labs_sdk_client.InvalidParamError("Wallet account is not an EVM wallet account");
|
|
850
|
+
const { networkData } = await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, client);
|
|
851
|
+
(0, _dynamic_labs_sdk_client_core.assertDefined)(networkData, `No network data found for wallet account ${walletAccount.address}`);
|
|
852
|
+
const nonce = await require_createWalletClientForWalletAccount.createPublicClientFromNetworkData({ networkData }).getTransactionCount({ address: walletAccount.address });
|
|
853
|
+
const walletClient = await require_createWalletClientForWalletAccount.createWalletClientForWalletAccount({ walletAccount }, client);
|
|
854
|
+
if (token) {
|
|
855
|
+
const data = (0, viem.encodeFunctionData)({
|
|
856
|
+
abi: viem.erc20Abi,
|
|
857
|
+
args: [recipient, (0, viem.parseUnits)(amount, token.decimals ?? DEFAULT_DECIMALS)],
|
|
858
|
+
functionName: "transfer"
|
|
859
|
+
});
|
|
860
|
+
return { transactionHash: await walletClient.sendTransaction({
|
|
861
|
+
data,
|
|
862
|
+
nonce,
|
|
863
|
+
to: token.address
|
|
864
|
+
}) };
|
|
865
|
+
}
|
|
866
|
+
return { transactionHash: await walletClient.sendTransaction({
|
|
867
|
+
nonce,
|
|
868
|
+
to: recipient,
|
|
869
|
+
value: (0, viem.parseEther)(amount)
|
|
870
|
+
}) };
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
//#endregion
|
|
874
|
+
Object.defineProperty(exports, 'RpcError', {
|
|
875
|
+
enumerable: true,
|
|
876
|
+
get: function () {
|
|
877
|
+
return RpcError;
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
Object.defineProperty(exports, 'SponsorTransactionError', {
|
|
881
|
+
enumerable: true,
|
|
882
|
+
get: function () {
|
|
883
|
+
return SponsorTransactionError;
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
Object.defineProperty(exports, 'evmConfirmTransaction', {
|
|
887
|
+
enumerable: true,
|
|
888
|
+
get: function () {
|
|
889
|
+
return evmConfirmTransaction;
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
Object.defineProperty(exports, 'evmExecuteSwapTransaction', {
|
|
893
|
+
enumerable: true,
|
|
894
|
+
get: function () {
|
|
895
|
+
return evmExecuteSwapTransaction;
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
Object.defineProperty(exports, 'evmTransferAmount', {
|
|
899
|
+
enumerable: true,
|
|
900
|
+
get: function () {
|
|
901
|
+
return evmTransferAmount;
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
Object.defineProperty(exports, 'getEVMSponsoredTransactionStatus', {
|
|
905
|
+
enumerable: true,
|
|
906
|
+
get: function () {
|
|
907
|
+
return getEVMSponsoredTransactionStatus;
|
|
908
|
+
}
|
|
909
|
+
});
|
|
910
|
+
Object.defineProperty(exports, 'is7702DelegationActive', {
|
|
911
|
+
enumerable: true,
|
|
912
|
+
get: function () {
|
|
913
|
+
return is7702DelegationActive;
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
Object.defineProperty(exports, 'isEvmGasSponsorshipEnabled', {
|
|
917
|
+
enumerable: true,
|
|
918
|
+
get: function () {
|
|
919
|
+
return isEvmGasSponsorshipEnabled;
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
Object.defineProperty(exports, 'isEvmWalletAccount', {
|
|
923
|
+
enumerable: true,
|
|
924
|
+
get: function () {
|
|
925
|
+
return isEvmWalletAccount;
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
Object.defineProperty(exports, 'registerEvmNetworkProviderBuilder', {
|
|
929
|
+
enumerable: true,
|
|
930
|
+
get: function () {
|
|
931
|
+
return registerEvmNetworkProviderBuilder;
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
Object.defineProperty(exports, 'relaySponsoredTransaction', {
|
|
935
|
+
enumerable: true,
|
|
936
|
+
get: function () {
|
|
937
|
+
return relaySponsoredTransaction;
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
Object.defineProperty(exports, 'sendSponsoredTransaction', {
|
|
941
|
+
enumerable: true,
|
|
942
|
+
get: function () {
|
|
943
|
+
return sendSponsoredTransaction;
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
Object.defineProperty(exports, 'sign7702Authorization', {
|
|
947
|
+
enumerable: true,
|
|
948
|
+
get: function () {
|
|
949
|
+
return sign7702Authorization;
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
Object.defineProperty(exports, 'signSponsoredTransaction', {
|
|
953
|
+
enumerable: true,
|
|
954
|
+
get: function () {
|
|
955
|
+
return signSponsoredTransaction;
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
Object.defineProperty(exports, 'waitForSponsoredTransaction', {
|
|
959
|
+
enumerable: true,
|
|
960
|
+
get: function () {
|
|
961
|
+
return waitForSponsoredTransaction;
|
|
962
|
+
}
|
|
963
|
+
});
|
|
964
|
+
//# sourceMappingURL=evmTransferAmount-Bb1YvuCX.cjs.map
|