@dynamic-labs/ethereum-gasless-core 0.0.0 → 4.84.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 +6525 -0
- package/LICENSE +21 -0
- package/README.md +7 -0
- package/package.cjs +8 -0
- package/package.js +4 -0
- package/package.json +23 -1
- package/src/index.cjs +53 -0
- package/src/index.d.ts +20 -0
- package/src/index.js +24 -0
- package/src/lib/activate7702Delegation/activate7702Delegation.cjs +17 -0
- package/src/lib/activate7702Delegation/activate7702Delegation.d.ts +18 -0
- package/src/lib/activate7702Delegation/activate7702Delegation.js +13 -0
- package/src/lib/constants.cjs +69 -0
- package/src/lib/constants.d.ts +76 -0
- package/src/lib/constants.js +60 -0
- package/src/lib/create7702DelegationRegistry/create7702DelegationRegistry.cjs +22 -0
- package/src/lib/create7702DelegationRegistry/create7702DelegationRegistry.d.ts +7 -0
- package/src/lib/create7702DelegationRegistry/create7702DelegationRegistry.js +18 -0
- package/src/lib/errors/EthereumGasSponsorshipNotEnabledError/EthereumGasSponsorshipNotEnabledError.cjs +18 -0
- package/src/lib/errors/EthereumGasSponsorshipNotEnabledError/EthereumGasSponsorshipNotEnabledError.d.ts +8 -0
- package/src/lib/errors/EthereumGasSponsorshipNotEnabledError/EthereumGasSponsorshipNotEnabledError.js +14 -0
- package/src/lib/errors/SponsorTransactionError/SponsorTransactionError.cjs +23 -0
- package/src/lib/errors/SponsorTransactionError/SponsorTransactionError.d.ts +10 -0
- package/src/lib/errors/SponsorTransactionError/SponsorTransactionError.js +19 -0
- package/src/lib/generateIntentNonce/generateIntentNonce.cjs +39 -0
- package/src/lib/generateIntentNonce/generateIntentNonce.d.ts +20 -0
- package/src/lib/generateIntentNonce/generateIntentNonce.js +35 -0
- package/src/lib/generateRandomNonce/generateRandomNonce.cjs +22 -0
- package/src/lib/generateRandomNonce/generateRandomNonce.d.ts +11 -0
- package/src/lib/generateRandomNonce/generateRandomNonce.js +18 -0
- package/src/lib/getAvailableEvmGaslessRelayer/getAvailableEvmGaslessRelayer.cjs +35 -0
- package/src/lib/getAvailableEvmGaslessRelayer/getAvailableEvmGaslessRelayer.d.ts +21 -0
- package/src/lib/getAvailableEvmGaslessRelayer/getAvailableEvmGaslessRelayer.js +31 -0
- package/src/lib/getEVMSponsoredTransactionStatus/getEVMSponsoredTransactionStatus.cjs +35 -0
- package/src/lib/getEVMSponsoredTransactionStatus/getEVMSponsoredTransactionStatus.d.ts +15 -0
- package/src/lib/getEVMSponsoredTransactionStatus/getEVMSponsoredTransactionStatus.js +31 -0
- package/src/lib/is7702DelegationActive/is7702DelegationActive.cjs +32 -0
- package/src/lib/is7702DelegationActive/is7702DelegationActive.d.ts +21 -0
- package/src/lib/is7702DelegationActive/is7702DelegationActive.js +28 -0
- package/src/lib/isEthereumGasSponsorshipEnabled/isEthereumGasSponsorshipEnabled.cjs +14 -0
- package/src/lib/isEthereumGasSponsorshipEnabled/isEthereumGasSponsorshipEnabled.d.ts +23 -0
- package/src/lib/isEthereumGasSponsorshipEnabled/isEthereumGasSponsorshipEnabled.js +10 -0
- package/src/lib/relaySponsoredTransaction/relaySponsoredTransaction.cjs +58 -0
- package/src/lib/relaySponsoredTransaction/relaySponsoredTransaction.d.ts +29 -0
- package/src/lib/relaySponsoredTransaction/relaySponsoredTransaction.js +54 -0
- package/src/lib/resolveAuthorization/resolveAuthorization.cjs +32 -0
- package/src/lib/resolveAuthorization/resolveAuthorization.d.ts +27 -0
- package/src/lib/resolveAuthorization/resolveAuthorization.js +28 -0
- package/src/lib/resolveChainId/resolveChainId.cjs +12 -0
- package/src/lib/resolveChainId/resolveChainId.d.ts +11 -0
- package/src/lib/resolveChainId/resolveChainId.js +8 -0
- package/src/lib/sendSponsoredTransaction/sendSponsoredTransaction.cjs +21 -0
- package/src/lib/sendSponsoredTransaction/sendSponsoredTransaction.d.ts +29 -0
- package/src/lib/sendSponsoredTransaction/sendSponsoredTransaction.js +17 -0
- package/src/lib/sign7702Authorization/sign7702Authorization.cjs +22 -0
- package/src/lib/sign7702Authorization/sign7702Authorization.d.ts +21 -0
- package/src/lib/sign7702Authorization/sign7702Authorization.js +18 -0
- package/src/lib/signSponsoredTransaction/signSponsoredTransaction.cjs +61 -0
- package/src/lib/signSponsoredTransaction/signSponsoredTransaction.d.ts +22 -0
- package/src/lib/signSponsoredTransaction/signSponsoredTransaction.js +57 -0
- package/src/lib/toSerializedAuthorization/toSerializedAuthorization.cjs +28 -0
- package/src/lib/toSerializedAuthorization/toSerializedAuthorization.d.ts +11 -0
- package/src/lib/toSerializedAuthorization/toSerializedAuthorization.js +24 -0
- package/src/lib/types.d.ts +83 -0
- package/src/lib/waitForSponsoredTransaction/waitForSponsoredTransaction.cjs +38 -0
- package/src/lib/waitForSponsoredTransaction/waitForSponsoredTransaction.d.ts +16 -0
- package/src/lib/waitForSponsoredTransaction/waitForSponsoredTransaction.js +34 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { UGD_ABI } from '../constants.js';
|
|
3
|
+
import { generateRandomNonce } from '../generateRandomNonce/generateRandomNonce.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generates a random 256-bit bitmap nonce for UGD `AuthorizedExecutions`
|
|
7
|
+
* signing.
|
|
8
|
+
*
|
|
9
|
+
* Uses `crypto.getRandomValues` for entropy; collisions are essentially
|
|
10
|
+
* impossible at 256 bits. As a safety check the freshly-generated nonce is
|
|
11
|
+
* validated against the on-chain `isNonceUsed` view — if the contract call
|
|
12
|
+
* fails (e.g. delegation not yet active), the random nonce is still safe to
|
|
13
|
+
* use because it was generated locally with 256 bits of entropy.
|
|
14
|
+
*/
|
|
15
|
+
const generateIntentNonce = async ({ walletAddress }, { publicClient }) => {
|
|
16
|
+
const nonce = generateRandomNonce();
|
|
17
|
+
try {
|
|
18
|
+
const isUsed = await publicClient.readContract({
|
|
19
|
+
abi: UGD_ABI,
|
|
20
|
+
address: walletAddress,
|
|
21
|
+
args: [nonce],
|
|
22
|
+
functionName: 'isNonceUsed',
|
|
23
|
+
});
|
|
24
|
+
if (isUsed) {
|
|
25
|
+
return generateRandomNonce();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Contract call may fail if delegation is not yet active — the nonce is
|
|
30
|
+
// still safe to use since it was randomly generated.
|
|
31
|
+
}
|
|
32
|
+
return nonce;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export { generateIntentNonce };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Generates a cryptographically random 256-bit nonce for the UGD
|
|
8
|
+
* AuthorizedExecutions bitmap.
|
|
9
|
+
*
|
|
10
|
+
* Uses `crypto.getRandomValues` for 256 bits of entropy. Collisions against
|
|
11
|
+
* the on-chain bitmap are effectively impossible at this width but callers
|
|
12
|
+
* may still validate via `isNonceUsed` as a safety net.
|
|
13
|
+
*
|
|
14
|
+
* @returns A random bigint nonce.
|
|
15
|
+
*/
|
|
16
|
+
const generateRandomNonce = () => {
|
|
17
|
+
const bytes = new Uint8Array(32);
|
|
18
|
+
crypto.getRandomValues(bytes);
|
|
19
|
+
return bytes.reduce((acc, byte) => (acc << BigInt(8)) | BigInt(byte), BigInt(0));
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
exports.generateRandomNonce = generateRandomNonce;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a cryptographically random 256-bit nonce for the UGD
|
|
3
|
+
* AuthorizedExecutions bitmap.
|
|
4
|
+
*
|
|
5
|
+
* Uses `crypto.getRandomValues` for 256 bits of entropy. Collisions against
|
|
6
|
+
* the on-chain bitmap are effectively impossible at this width but callers
|
|
7
|
+
* may still validate via `isNonceUsed` as a safety net.
|
|
8
|
+
*
|
|
9
|
+
* @returns A random bigint nonce.
|
|
10
|
+
*/
|
|
11
|
+
export declare const generateRandomNonce: () => bigint;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
/**
|
|
3
|
+
* Generates a cryptographically random 256-bit nonce for the UGD
|
|
4
|
+
* AuthorizedExecutions bitmap.
|
|
5
|
+
*
|
|
6
|
+
* Uses `crypto.getRandomValues` for 256 bits of entropy. Collisions against
|
|
7
|
+
* the on-chain bitmap are effectively impossible at this width but callers
|
|
8
|
+
* may still validate via `isNonceUsed` as a safety net.
|
|
9
|
+
*
|
|
10
|
+
* @returns A random bigint nonce.
|
|
11
|
+
*/
|
|
12
|
+
const generateRandomNonce = () => {
|
|
13
|
+
const bytes = new Uint8Array(32);
|
|
14
|
+
crypto.getRandomValues(bytes);
|
|
15
|
+
return bytes.reduce((acc, byte) => (acc << BigInt(8)) | BigInt(byte), BigInt(0));
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { generateRandomNonce };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var SponsorTransactionError = require('../errors/SponsorTransactionError/SponsorTransactionError.cjs');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Fetches the relayer address to embed in the EIP-712 sponsored-transaction
|
|
10
|
+
* intent for the given chain.
|
|
11
|
+
*
|
|
12
|
+
* The returned address is owned by the project's relay backend and is the
|
|
13
|
+
* eventual `from` of the on-chain broadcast. It must be set as the `relayer`
|
|
14
|
+
* field of the EIP-712 intent before signing — the on-chain delegate
|
|
15
|
+
* validates the signature against this address.
|
|
16
|
+
*/
|
|
17
|
+
const getAvailableEvmGaslessRelayer = async ({ chainId }, { sdkApi, environmentId }) => {
|
|
18
|
+
let data;
|
|
19
|
+
try {
|
|
20
|
+
data = await sdkApi.getAvailableEVMGaslessRelayer({
|
|
21
|
+
chainId,
|
|
22
|
+
environmentId,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const cause = error instanceof Error ? error : null;
|
|
27
|
+
throw new SponsorTransactionError.SponsorTransactionError(cause);
|
|
28
|
+
}
|
|
29
|
+
if (!data.relayerAddress) {
|
|
30
|
+
throw new SponsorTransactionError.SponsorTransactionError();
|
|
31
|
+
}
|
|
32
|
+
return { relayerAddress: data.relayerAddress };
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
exports.getAvailableEvmGaslessRelayer = getAvailableEvmGaslessRelayer;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Hex } from 'viem';
|
|
2
|
+
import type { EvmGaslessApiDeps } from '../types';
|
|
3
|
+
type GetAvailableEvmGaslessRelayerParams = {
|
|
4
|
+
/** The EVM chain ID the sponsored transaction will target. */
|
|
5
|
+
chainId: number;
|
|
6
|
+
};
|
|
7
|
+
type GetAvailableEvmGaslessRelayerResult = {
|
|
8
|
+
/** Relayer EOA that will broadcast the sponsored transaction on-chain. */
|
|
9
|
+
relayerAddress: Hex;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Fetches the relayer address to embed in the EIP-712 sponsored-transaction
|
|
13
|
+
* intent for the given chain.
|
|
14
|
+
*
|
|
15
|
+
* The returned address is owned by the project's relay backend and is the
|
|
16
|
+
* eventual `from` of the on-chain broadcast. It must be set as the `relayer`
|
|
17
|
+
* field of the EIP-712 intent before signing — the on-chain delegate
|
|
18
|
+
* validates the signature against this address.
|
|
19
|
+
*/
|
|
20
|
+
export declare const getAvailableEvmGaslessRelayer: ({ chainId }: GetAvailableEvmGaslessRelayerParams, { sdkApi, environmentId }: EvmGaslessApiDeps) => Promise<GetAvailableEvmGaslessRelayerResult>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { SponsorTransactionError } from '../errors/SponsorTransactionError/SponsorTransactionError.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fetches the relayer address to embed in the EIP-712 sponsored-transaction
|
|
6
|
+
* intent for the given chain.
|
|
7
|
+
*
|
|
8
|
+
* The returned address is owned by the project's relay backend and is the
|
|
9
|
+
* eventual `from` of the on-chain broadcast. It must be set as the `relayer`
|
|
10
|
+
* field of the EIP-712 intent before signing — the on-chain delegate
|
|
11
|
+
* validates the signature against this address.
|
|
12
|
+
*/
|
|
13
|
+
const getAvailableEvmGaslessRelayer = async ({ chainId }, { sdkApi, environmentId }) => {
|
|
14
|
+
let data;
|
|
15
|
+
try {
|
|
16
|
+
data = await sdkApi.getAvailableEVMGaslessRelayer({
|
|
17
|
+
chainId,
|
|
18
|
+
environmentId,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
const cause = error instanceof Error ? error : null;
|
|
23
|
+
throw new SponsorTransactionError(cause);
|
|
24
|
+
}
|
|
25
|
+
if (!data.relayerAddress) {
|
|
26
|
+
throw new SponsorTransactionError();
|
|
27
|
+
}
|
|
28
|
+
return { relayerAddress: data.relayerAddress };
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { getAvailableEvmGaslessRelayer };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var SponsorTransactionError = require('../errors/SponsorTransactionError/SponsorTransactionError.cjs');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Fetches the current relay state for a sponsored EVM transaction.
|
|
10
|
+
*
|
|
11
|
+
* Returns the lifecycle status, the on-chain transaction hash (when the
|
|
12
|
+
* relay has broadcast it), and any terminal-failure error message. Use this
|
|
13
|
+
* as the building block for custom polling flows; for the common "wait until
|
|
14
|
+
* done" case prefer `waitForSponsoredTransaction`.
|
|
15
|
+
*/
|
|
16
|
+
const getEVMSponsoredTransactionStatus = async ({ requestId }, { sdkApi, environmentId }) => {
|
|
17
|
+
let data;
|
|
18
|
+
try {
|
|
19
|
+
data = await sdkApi.getEVMSponsoredTransactionStatus({
|
|
20
|
+
environmentId,
|
|
21
|
+
requestId,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
const cause = error instanceof Error ? error : null;
|
|
26
|
+
throw new SponsorTransactionError.SponsorTransactionError(cause);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
errorMessage: data.errorMessage,
|
|
30
|
+
status: data.status,
|
|
31
|
+
transactionHash: data.transactionHash,
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
exports.getEVMSponsoredTransactionStatus = getEVMSponsoredTransactionStatus;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EvmGaslessApiDeps, SponsoredTransactionStatusResult } from '../types';
|
|
2
|
+
type GetEVMSponsoredTransactionStatusParams = {
|
|
3
|
+
/** The request ID returned by `relaySponsoredTransaction` / `sendSponsoredTransaction`. */
|
|
4
|
+
requestId: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Fetches the current relay state for a sponsored EVM transaction.
|
|
8
|
+
*
|
|
9
|
+
* Returns the lifecycle status, the on-chain transaction hash (when the
|
|
10
|
+
* relay has broadcast it), and any terminal-failure error message. Use this
|
|
11
|
+
* as the building block for custom polling flows; for the common "wait until
|
|
12
|
+
* done" case prefer `waitForSponsoredTransaction`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const getEVMSponsoredTransactionStatus: ({ requestId }: GetEVMSponsoredTransactionStatusParams, { sdkApi, environmentId }: EvmGaslessApiDeps) => Promise<SponsoredTransactionStatusResult>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { SponsorTransactionError } from '../errors/SponsorTransactionError/SponsorTransactionError.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fetches the current relay state for a sponsored EVM transaction.
|
|
6
|
+
*
|
|
7
|
+
* Returns the lifecycle status, the on-chain transaction hash (when the
|
|
8
|
+
* relay has broadcast it), and any terminal-failure error message. Use this
|
|
9
|
+
* as the building block for custom polling flows; for the common "wait until
|
|
10
|
+
* done" case prefer `waitForSponsoredTransaction`.
|
|
11
|
+
*/
|
|
12
|
+
const getEVMSponsoredTransactionStatus = async ({ requestId }, { sdkApi, environmentId }) => {
|
|
13
|
+
let data;
|
|
14
|
+
try {
|
|
15
|
+
data = await sdkApi.getEVMSponsoredTransactionStatus({
|
|
16
|
+
environmentId,
|
|
17
|
+
requestId,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
const cause = error instanceof Error ? error : null;
|
|
22
|
+
throw new SponsorTransactionError(cause);
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
errorMessage: data.errorMessage,
|
|
26
|
+
status: data.status,
|
|
27
|
+
transactionHash: data.transactionHash,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { getEVMSponsoredTransactionStatus };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var constants = require('../constants.cjs');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Checks whether EIP-7702 delegation to the Dynamic gasless contract is
|
|
10
|
+
* active for the given wallet on the given chain.
|
|
11
|
+
*
|
|
12
|
+
* Positive results are cached in the in-memory registry; missing entries
|
|
13
|
+
* fall back to an on-chain bytecode check (`eth_getCode`). The on-chain
|
|
14
|
+
* delegation marker is `DELEGATION_CODE_PREFIX + DELEGATION_CONTRACT_ADDRESS`.
|
|
15
|
+
*/
|
|
16
|
+
const is7702DelegationActive = async ({ walletAddress }, { chainId, delegationRegistry, publicClient }) => {
|
|
17
|
+
if (delegationRegistry.isDelegated({ chainId, walletAddress })) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
const bytecode = await publicClient.getCode({ address: walletAddress });
|
|
21
|
+
if (!bytecode) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const expectedPrefix = constants.DELEGATION_CODE_PREFIX + constants.DELEGATION_CONTRACT_ADDRESS.slice(2).toLowerCase();
|
|
25
|
+
const isActive = bytecode.toLowerCase().startsWith(expectedPrefix);
|
|
26
|
+
if (isActive) {
|
|
27
|
+
delegationRegistry.markDelegated({ chainId, walletAddress });
|
|
28
|
+
}
|
|
29
|
+
return isActive;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.is7702DelegationActive = is7702DelegationActive;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Chain, Hex, PublicClient, Transport } from 'viem';
|
|
2
|
+
import type { Delegation7702Registry } from '../types';
|
|
3
|
+
type Is7702DelegationActiveParams = {
|
|
4
|
+
/** The wallet address to check delegation status for. */
|
|
5
|
+
walletAddress: Hex;
|
|
6
|
+
};
|
|
7
|
+
type Is7702DelegationActiveDeps = {
|
|
8
|
+
chainId: number;
|
|
9
|
+
delegationRegistry: Delegation7702Registry;
|
|
10
|
+
publicClient: PublicClient<Transport, Chain>;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Checks whether EIP-7702 delegation to the Dynamic gasless contract is
|
|
14
|
+
* active for the given wallet on the given chain.
|
|
15
|
+
*
|
|
16
|
+
* Positive results are cached in the in-memory registry; missing entries
|
|
17
|
+
* fall back to an on-chain bytecode check (`eth_getCode`). The on-chain
|
|
18
|
+
* delegation marker is `DELEGATION_CODE_PREFIX + DELEGATION_CONTRACT_ADDRESS`.
|
|
19
|
+
*/
|
|
20
|
+
export declare const is7702DelegationActive: ({ walletAddress }: Is7702DelegationActiveParams, { chainId, delegationRegistry, publicClient }: Is7702DelegationActiveDeps) => Promise<boolean>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { DELEGATION_CODE_PREFIX, DELEGATION_CONTRACT_ADDRESS } from '../constants.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Checks whether EIP-7702 delegation to the Dynamic gasless contract is
|
|
6
|
+
* active for the given wallet on the given chain.
|
|
7
|
+
*
|
|
8
|
+
* Positive results are cached in the in-memory registry; missing entries
|
|
9
|
+
* fall back to an on-chain bytecode check (`eth_getCode`). The on-chain
|
|
10
|
+
* delegation marker is `DELEGATION_CODE_PREFIX + DELEGATION_CONTRACT_ADDRESS`.
|
|
11
|
+
*/
|
|
12
|
+
const is7702DelegationActive = async ({ walletAddress }, { chainId, delegationRegistry, publicClient }) => {
|
|
13
|
+
if (delegationRegistry.isDelegated({ chainId, walletAddress })) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
const bytecode = await publicClient.getCode({ address: walletAddress });
|
|
17
|
+
if (!bytecode) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const expectedPrefix = DELEGATION_CODE_PREFIX + DELEGATION_CONTRACT_ADDRESS.slice(2).toLowerCase();
|
|
21
|
+
const isActive = bytecode.toLowerCase().startsWith(expectedPrefix);
|
|
22
|
+
if (isActive) {
|
|
23
|
+
delegationRegistry.markDelegated({ chainId, walletAddress });
|
|
24
|
+
}
|
|
25
|
+
return isActive;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { is7702DelegationActive };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Checks whether EVM gas sponsorship is enabled for the current project.
|
|
8
|
+
*
|
|
9
|
+
* Returns `false` when no project settings are available — callers can
|
|
10
|
+
* always treat the return value as a definitive boolean.
|
|
11
|
+
*/
|
|
12
|
+
const isEthereumGasSponsorshipEnabled = ({ projectSettings, }) => projectSettings?.sdk.embeddedWallets?.evmGasSponsorshipEnabled ?? false;
|
|
13
|
+
|
|
14
|
+
exports.isEthereumGasSponsorshipEnabled = isEthereumGasSponsorshipEnabled;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type ProjectSettingsLike = {
|
|
2
|
+
sdk: {
|
|
3
|
+
embeddedWallets?: {
|
|
4
|
+
evmGasSponsorshipEnabled?: boolean;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
type IsEthereumGasSponsorshipEnabledDeps = {
|
|
9
|
+
/**
|
|
10
|
+
* The project settings object resolved by the host (e.g. from the webview
|
|
11
|
+
* manifest or the React SDK's project store). When the settings object is
|
|
12
|
+
* unavailable, returns `false`.
|
|
13
|
+
*/
|
|
14
|
+
projectSettings: ProjectSettingsLike | null | undefined;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Checks whether EVM gas sponsorship is enabled for the current project.
|
|
18
|
+
*
|
|
19
|
+
* Returns `false` when no project settings are available — callers can
|
|
20
|
+
* always treat the return value as a definitive boolean.
|
|
21
|
+
*/
|
|
22
|
+
export declare const isEthereumGasSponsorshipEnabled: ({ projectSettings, }: IsEthereumGasSponsorshipEnabledDeps) => boolean;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
/**
|
|
3
|
+
* Checks whether EVM gas sponsorship is enabled for the current project.
|
|
4
|
+
*
|
|
5
|
+
* Returns `false` when no project settings are available — callers can
|
|
6
|
+
* always treat the return value as a definitive boolean.
|
|
7
|
+
*/
|
|
8
|
+
const isEthereumGasSponsorshipEnabled = ({ projectSettings, }) => projectSettings?.sdk.embeddedWallets?.evmGasSponsorshipEnabled ?? false;
|
|
9
|
+
|
|
10
|
+
export { isEthereumGasSponsorshipEnabled };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var constants = require('../constants.cjs');
|
|
7
|
+
var SponsorTransactionError = require('../errors/SponsorTransactionError/SponsorTransactionError.cjs');
|
|
8
|
+
var signSponsoredTransaction = require('../signSponsoredTransaction/signSponsoredTransaction.cjs');
|
|
9
|
+
|
|
10
|
+
const isSignedTransactionParams = (params) => 'signedTransaction' in params;
|
|
11
|
+
/**
|
|
12
|
+
* Relays a signed sponsored transaction to the Dynamic backend.
|
|
13
|
+
*
|
|
14
|
+
* Accepts either an already-signed payload from `signSponsoredTransaction`
|
|
15
|
+
* or unsigned calls (in which case signing is performed first). Returns the
|
|
16
|
+
* `requestId` the relay backend uses to identify the broadcast attempt — use
|
|
17
|
+
* this with `waitForSponsoredTransaction` to await on-chain inclusion.
|
|
18
|
+
*/
|
|
19
|
+
const relaySponsoredTransaction = async (params, deps) => {
|
|
20
|
+
const signedTransaction = isSignedTransactionParams(params)
|
|
21
|
+
? params.signedTransaction
|
|
22
|
+
: await signSponsoredTransaction.signSponsoredTransaction({
|
|
23
|
+
authorization: params.authorization,
|
|
24
|
+
autoDelegate: params.autoDelegate,
|
|
25
|
+
calls: params.calls,
|
|
26
|
+
validForSeconds: params.validForSeconds ?? constants.DEFAULT_VALID_FOR_SECONDS,
|
|
27
|
+
}, deps);
|
|
28
|
+
let data;
|
|
29
|
+
try {
|
|
30
|
+
data = await deps.sdkApi.sponsorEVMTransaction({
|
|
31
|
+
environmentId: deps.environmentId,
|
|
32
|
+
sponsorEVMTransactionRequest: {
|
|
33
|
+
authorization: signedTransaction.authorization,
|
|
34
|
+
calls: signedTransaction.calls.map((c) => ({
|
|
35
|
+
data: c.data,
|
|
36
|
+
target: c.target,
|
|
37
|
+
value: c.value.toString(),
|
|
38
|
+
})),
|
|
39
|
+
chainId: signedTransaction.chainId,
|
|
40
|
+
deadline: signedTransaction.deadline,
|
|
41
|
+
nonce: signedTransaction.nonce,
|
|
42
|
+
relayer: signedTransaction.relayer,
|
|
43
|
+
signature: signedTransaction.signature,
|
|
44
|
+
walletAddress: signedTransaction.walletAddress,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const cause = error instanceof Error ? error : null;
|
|
50
|
+
throw new SponsorTransactionError.SponsorTransactionError(cause);
|
|
51
|
+
}
|
|
52
|
+
if (!data.requestId) {
|
|
53
|
+
throw new SponsorTransactionError.SponsorTransactionError();
|
|
54
|
+
}
|
|
55
|
+
return { requestId: data.requestId };
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
exports.relaySponsoredTransaction = relaySponsoredTransaction;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SignAuthorizationReturnType } from 'viem/accounts';
|
|
2
|
+
import type { EvmGaslessChainDeps, SignedSponsoredTransaction, SponsoredTransactionCall } from '../types';
|
|
3
|
+
type RelayWithCallsParams = {
|
|
4
|
+
/** Pre-signed EIP-7702 authorization. Takes priority over autoDelegate. */
|
|
5
|
+
authorization?: SignAuthorizationReturnType;
|
|
6
|
+
/** Whether to automatically sign 7702 authorization if not delegated. Defaults to true. */
|
|
7
|
+
autoDelegate?: boolean;
|
|
8
|
+
/** The batch of calls to execute. */
|
|
9
|
+
calls: SponsoredTransactionCall[];
|
|
10
|
+
/** How long the signed intent remains valid, in seconds. Defaults to 600. */
|
|
11
|
+
validForSeconds?: number;
|
|
12
|
+
};
|
|
13
|
+
type RelayWithSignedTxParams = {
|
|
14
|
+
/** A pre-signed sponsored transaction payload from `signSponsoredTransaction`. */
|
|
15
|
+
signedTransaction: SignedSponsoredTransaction;
|
|
16
|
+
};
|
|
17
|
+
type RelaySponsoredTransactionParams = RelayWithCallsParams | RelayWithSignedTxParams;
|
|
18
|
+
/**
|
|
19
|
+
* Relays a signed sponsored transaction to the Dynamic backend.
|
|
20
|
+
*
|
|
21
|
+
* Accepts either an already-signed payload from `signSponsoredTransaction`
|
|
22
|
+
* or unsigned calls (in which case signing is performed first). Returns the
|
|
23
|
+
* `requestId` the relay backend uses to identify the broadcast attempt — use
|
|
24
|
+
* this with `waitForSponsoredTransaction` to await on-chain inclusion.
|
|
25
|
+
*/
|
|
26
|
+
export declare const relaySponsoredTransaction: (params: RelaySponsoredTransactionParams, deps: EvmGaslessChainDeps) => Promise<{
|
|
27
|
+
requestId: string;
|
|
28
|
+
}>;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { DEFAULT_VALID_FOR_SECONDS } from '../constants.js';
|
|
3
|
+
import { SponsorTransactionError } from '../errors/SponsorTransactionError/SponsorTransactionError.js';
|
|
4
|
+
import { signSponsoredTransaction } from '../signSponsoredTransaction/signSponsoredTransaction.js';
|
|
5
|
+
|
|
6
|
+
const isSignedTransactionParams = (params) => 'signedTransaction' in params;
|
|
7
|
+
/**
|
|
8
|
+
* Relays a signed sponsored transaction to the Dynamic backend.
|
|
9
|
+
*
|
|
10
|
+
* Accepts either an already-signed payload from `signSponsoredTransaction`
|
|
11
|
+
* or unsigned calls (in which case signing is performed first). Returns the
|
|
12
|
+
* `requestId` the relay backend uses to identify the broadcast attempt — use
|
|
13
|
+
* this with `waitForSponsoredTransaction` to await on-chain inclusion.
|
|
14
|
+
*/
|
|
15
|
+
const relaySponsoredTransaction = async (params, deps) => {
|
|
16
|
+
const signedTransaction = isSignedTransactionParams(params)
|
|
17
|
+
? params.signedTransaction
|
|
18
|
+
: await signSponsoredTransaction({
|
|
19
|
+
authorization: params.authorization,
|
|
20
|
+
autoDelegate: params.autoDelegate,
|
|
21
|
+
calls: params.calls,
|
|
22
|
+
validForSeconds: params.validForSeconds ?? DEFAULT_VALID_FOR_SECONDS,
|
|
23
|
+
}, deps);
|
|
24
|
+
let data;
|
|
25
|
+
try {
|
|
26
|
+
data = await deps.sdkApi.sponsorEVMTransaction({
|
|
27
|
+
environmentId: deps.environmentId,
|
|
28
|
+
sponsorEVMTransactionRequest: {
|
|
29
|
+
authorization: signedTransaction.authorization,
|
|
30
|
+
calls: signedTransaction.calls.map((c) => ({
|
|
31
|
+
data: c.data,
|
|
32
|
+
target: c.target,
|
|
33
|
+
value: c.value.toString(),
|
|
34
|
+
})),
|
|
35
|
+
chainId: signedTransaction.chainId,
|
|
36
|
+
deadline: signedTransaction.deadline,
|
|
37
|
+
nonce: signedTransaction.nonce,
|
|
38
|
+
relayer: signedTransaction.relayer,
|
|
39
|
+
signature: signedTransaction.signature,
|
|
40
|
+
walletAddress: signedTransaction.walletAddress,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
const cause = error instanceof Error ? error : null;
|
|
46
|
+
throw new SponsorTransactionError(cause);
|
|
47
|
+
}
|
|
48
|
+
if (!data.requestId) {
|
|
49
|
+
throw new SponsorTransactionError();
|
|
50
|
+
}
|
|
51
|
+
return { requestId: data.requestId };
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export { relaySponsoredTransaction };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var is7702DelegationActive = require('../is7702DelegationActive/is7702DelegationActive.cjs');
|
|
7
|
+
var sign7702Authorization = require('../sign7702Authorization/sign7702Authorization.cjs');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Resolves which EIP-7702 authorization (if any) to attach to a sponsored
|
|
11
|
+
* transaction.
|
|
12
|
+
*
|
|
13
|
+
* - If the caller pre-signed an authorization, it is returned as-is.
|
|
14
|
+
* - If `autoDelegate` is false, no authorization is attached.
|
|
15
|
+
* - Otherwise, queries the on-chain delegation state. If delegation is
|
|
16
|
+
* already active, no authorization is needed; if not, signs one.
|
|
17
|
+
*/
|
|
18
|
+
const resolveAuthorization = async ({ authorization, autoDelegate, walletAddress }, deps) => {
|
|
19
|
+
if (authorization) {
|
|
20
|
+
return authorization;
|
|
21
|
+
}
|
|
22
|
+
if (!autoDelegate) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
const isDelegated = await is7702DelegationActive.is7702DelegationActive({ walletAddress }, deps);
|
|
26
|
+
if (isDelegated) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
return sign7702Authorization.sign7702Authorization({}, deps);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.resolveAuthorization = resolveAuthorization;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Account, Chain, Hex, PublicClient, Transport, WalletClient } from 'viem';
|
|
2
|
+
import type { SignAuthorizationReturnType } from 'viem/accounts';
|
|
3
|
+
import type { Delegation7702Registry } from '../types';
|
|
4
|
+
type ResolveAuthorizationParams = {
|
|
5
|
+
/** Pre-signed authorization; when provided it is returned as-is. */
|
|
6
|
+
authorization?: SignAuthorizationReturnType;
|
|
7
|
+
/** When true and no authorization is provided, sign one if delegation is inactive. */
|
|
8
|
+
autoDelegate: boolean;
|
|
9
|
+
walletAddress: Hex;
|
|
10
|
+
};
|
|
11
|
+
type ResolveAuthorizationDeps = {
|
|
12
|
+
chainId: number;
|
|
13
|
+
delegationRegistry: Delegation7702Registry;
|
|
14
|
+
publicClient: PublicClient<Transport, Chain>;
|
|
15
|
+
walletClient: WalletClient<Transport, Chain, Account>;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Resolves which EIP-7702 authorization (if any) to attach to a sponsored
|
|
19
|
+
* transaction.
|
|
20
|
+
*
|
|
21
|
+
* - If the caller pre-signed an authorization, it is returned as-is.
|
|
22
|
+
* - If `autoDelegate` is false, no authorization is attached.
|
|
23
|
+
* - Otherwise, queries the on-chain delegation state. If delegation is
|
|
24
|
+
* already active, no authorization is needed; if not, signs one.
|
|
25
|
+
*/
|
|
26
|
+
export declare const resolveAuthorization: ({ authorization, autoDelegate, walletAddress }: ResolveAuthorizationParams, deps: ResolveAuthorizationDeps) => Promise<SignAuthorizationReturnType | undefined>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { is7702DelegationActive } from '../is7702DelegationActive/is7702DelegationActive.js';
|
|
3
|
+
import { sign7702Authorization } from '../sign7702Authorization/sign7702Authorization.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolves which EIP-7702 authorization (if any) to attach to a sponsored
|
|
7
|
+
* transaction.
|
|
8
|
+
*
|
|
9
|
+
* - If the caller pre-signed an authorization, it is returned as-is.
|
|
10
|
+
* - If `autoDelegate` is false, no authorization is attached.
|
|
11
|
+
* - Otherwise, queries the on-chain delegation state. If delegation is
|
|
12
|
+
* already active, no authorization is needed; if not, signs one.
|
|
13
|
+
*/
|
|
14
|
+
const resolveAuthorization = async ({ authorization, autoDelegate, walletAddress }, deps) => {
|
|
15
|
+
if (authorization) {
|
|
16
|
+
return authorization;
|
|
17
|
+
}
|
|
18
|
+
if (!autoDelegate) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
const isDelegated = await is7702DelegationActive({ walletAddress }, deps);
|
|
22
|
+
if (isDelegated) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
return sign7702Authorization({}, deps);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { resolveAuthorization };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resolves a chain ID from either an explicit override or the chain ID
|
|
8
|
+
* configured in the gasless chain deps.
|
|
9
|
+
*/
|
|
10
|
+
const resolveChainId = ({ chainId }, { chainId: depsChainId }) => chainId ?? depsChainId;
|
|
11
|
+
|
|
12
|
+
exports.resolveChainId = resolveChainId;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { EvmGaslessChainDeps } from '../types';
|
|
2
|
+
type ResolveChainIdParams = {
|
|
3
|
+
/** Optional override; when set the deps' chainId is ignored. */
|
|
4
|
+
chainId?: number;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Resolves a chain ID from either an explicit override or the chain ID
|
|
8
|
+
* configured in the gasless chain deps.
|
|
9
|
+
*/
|
|
10
|
+
export declare const resolveChainId: ({ chainId }: ResolveChainIdParams, { chainId: depsChainId }: Pick<EvmGaslessChainDeps, 'chainId'>) => number;
|
|
11
|
+
export {};
|