Skip to content

Commit 1c31a1e

Browse files
authored
[Portal] .NET ThirdwebBridge Onramping & InAppWallet 7702 Account Abstraction (#7017)
1 parent 04c10f8 commit 1c31a1e

File tree

5 files changed

+127
-80
lines changed

5 files changed

+127
-80
lines changed

apps/portal/src/app/dotnet/sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ const walletActions: SidebarLink = (() => {
8181
href: `${parentSlug}/switchnetwork`,
8282
},
8383
{
84-
name: "SignAuthorization (Experimental)",
84+
name: "SignAuthorization",
8585
href: `${parentSlug}/signauthorization`,
8686
},
8787
],

apps/portal/src/app/dotnet/universal-bridge/quickstart/page.mdx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ The design is akin to letting us know what your intent is.
1717
- Buy: "I want to buy x USDC on y Chain using z Token"
1818
- Sell: "I want to sell x USDC on y Chain for z Token"
1919
- Transfer: "Just transfer all my money to vitalik"
20+
- Onramp: "I want to buy x USDC on y Chain by paying with card"
2021

2122
We will return the transactions needed to achieve whatever you desire.
2223
You may then handle execution yourself or use our extensions.
@@ -127,4 +128,43 @@ Console.WriteLine($"Sell hashes: {JsonConvert.SerializeObject(sellHashes, Format
127128
var transferResult = await bridge.Execute(myWallet, preparedTransfer);
128129
var transferHashes = transferResult.Select(receipt => receipt.TransactionHash).ToList();
129130
Console.WriteLine($"Transfer hashes: {JsonConvert.SerializeObject(transferHashes, Formatting.Indented)}");
131+
```
132+
133+
## Onramping with Fiat
134+
The onramp flow will return a link for you to display/open as you please. You may poll the status of that onramp by its ID.
135+
In some cases, you may receive an additional set of onchain steps required to get to your destination token post on-ramp, in such cases, you may use our extension `IsSwapRequiredPostOnramp` to check, and if a swap is indeed required, you may use our `Execute` extensions to execute the transactions, or manually execute them by going through each `Step`.
136+
137+
```csharp
138+
// Onramp - Get a quote for buying crypto with Fiat
139+
var preparedOnramp = await bridge.Onramp_Prepare(
140+
onramp: OnrampProvider.Coinbase,
141+
chainId: 8453,
142+
tokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC on Base
143+
amount: "10000000",
144+
receiver: await myWallet.GetAddress()
145+
);
146+
Console.WriteLine($"Onramp link: {preparedOnramp.Link}");
147+
Console.WriteLine($"Full onramp quote and steps data: {JsonConvert.SerializeObject(preparedOnramp, Formatting.Indented)}");
148+
149+
while (true)
150+
{
151+
var onrampStatus = await bridge.Onramp_Status(id: preparedOnramp.Id);
152+
Console.WriteLine($"Full Onramp Status: {JsonConvert.SerializeObject(onrampStatus, Formatting.Indented)}");
153+
if (onrampStatus.StatusType is StatusType.COMPLETED or StatusType.FAILED)
154+
{
155+
break;
156+
}
157+
await ThirdwebTask.Delay(5000);
158+
}
159+
160+
if (preparedOnramp.IsSwapRequiredPostOnramp())
161+
{
162+
// Execute additional steps that are required post-onramp to get to your token, manually or via the Execute extension
163+
var receipts = await bridge.Execute(myWallet, preparedOnramp);
164+
Console.WriteLine($"Onramp receipts: {JsonConvert.SerializeObject(receipts, Formatting.Indented)}");
165+
}
166+
else
167+
{
168+
Console.WriteLine("No additional steps required post-onramp, you can use the tokens directly!");
169+
}
130170
```

apps/portal/src/app/dotnet/wallets/actions/signauthorization/page.mdx

Lines changed: 18 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,96 +5,37 @@ export const metadata = createMetadata({
55
description: "Sign an EIP-7702 Payload to Set Code to your EOA.",
66
});
77

8-
# [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Integration (Experimental)
8+
# [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Integration (Low-level API)
99
Integrates `authorizationList` for any transactions.
1010
This EIP essentially allows you to set code to an EOA, unlocking a world of possibilities to enhance their functionality.
11-
12-
The best way to understand it outside of reading the EIP is looking at the example below; to preface it: we sign an authorization using the wallet we want to set code to. Another wallet sends a transaction with said authorization passed in, essentially activating it. The authority wallet now has code set to it pointing to an (insecure) [Delegation](https://thirdweb.com/odyssey-911867/0x654F42b74885EE6803F403f077bc0409f1066c58) contract in this case, which allows any wallet to execute any call through it on behalf of the authority. In this example, we call the wallet executing both the authorization and the claim transaction afterwards, the exectuor.
13-
1411
An authority may execute its own authorization, the only difference is internal whereby the authorization nonce is incremented by 1.
1512

16-
```csharp
17-
// Chain and contract addresses
18-
var chainWith7702 = 911867;
19-
var erc20ContractAddress = "0xAA462a5BE0fc5214507FDB4fB2474a7d5c69065b"; // Fake ERC20
20-
var delegationContractAddress = "0x654F42b74885EE6803F403f077bc0409f1066c58"; // BatchCallDelegation
21-
22-
// Initialize contracts normally
23-
var erc20Contract = await ThirdwebContract.Create(client: client, address: erc20ContractAddress, chain: chainWith7702);
24-
var delegationContract = await ThirdwebContract.Create(client: client, address: delegationContractAddress, chain: chainWith7702);
13+
You almost never need to use this API directly, but it's available for low-level access. Use higher level [Account Abstraction](/dotnet/wallets/providers/account-abstraction) APIs instead.
2514

26-
// Initialize a (to-be) 7702 EOA
27-
var eoaWallet = await PrivateKeyWallet.Generate(client);
28-
var eoaWalletAddress = await eoaWallet.GetAddress();
29-
Console.WriteLine($"EOA address: {eoaWalletAddress}");
15+
## Usage
3016

31-
// Initialize another wallet, the "executor" that will hit the eoa's (to-be) execute function
32-
var executorWallet = await PrivateKeyWallet.Generate(client);
33-
var executorWalletAddress = await executorWallet.GetAddress();
34-
Console.WriteLine($"Executor address: {executorWalletAddress}");
17+
```csharp
18+
var authorization = await eoaWallet.SignAuthorization(chainId: chainWith7702Support, contractAddress: delegationContractAddress, willSelfExecute: false);
19+
```
3520

36-
// Fund the executor wallet
37-
var fundingWallet = await PrivateKeyWallet.Create(client, privateKey);
38-
var fundingHash = (await fundingWallet.Transfer(chainWith7702, executorWalletAddress, BigInteger.Parse("0.001".ToWei()))).TransactionHash;
39-
Console.WriteLine($"Funded Executor Wallet: {fundingHash}");
21+
<Details summary="Parameters">
4022

41-
// Sign the authorization to make it point to the delegation contract
42-
var authorization = await eoaWallet.SignAuthorization(chainId: chainWith7702, contractAddress: delegationContractAddress, willSelfExecute: false);
43-
Console.WriteLine($"Authorization: {JsonConvert.SerializeObject(authorization, Formatting.Indented)}");
23+
### chainId (required)
4424

45-
// Execute the delegation
46-
var tx = await ThirdwebTransaction.Create(executorWallet, new ThirdwebTransactionInput(chainId: chainWith7702, to: executorWalletAddress, authorization: authorization));
47-
var hash = (await ThirdwebTransaction.SendAndWaitForTransactionReceipt(tx)).TransactionHash;
48-
Console.WriteLine($"Authorization execution transaction hash: {hash}");
25+
Your chain ID as a `BigInteger` value.
4926

50-
// Prove that code has been deployed to the eoa
51-
var rpc = ThirdwebRPC.GetRpcInstance(client, chainWith7702);
52-
var code = await rpc.SendRequestAsync<string>("eth_getCode", eoaWalletAddress, "latest");
53-
Console.WriteLine($"EOA code: {code}");
27+
### contractAddress (required)
28+
The address of the contract you want to authorize. Your EOA will essentially become a smart contract if this authorization is executed.
5429

55-
// Log erc20 balance of executor before the claim
56-
var executorBalanceBefore = await erc20Contract.ERC20_BalanceOf(executorWalletAddress);
57-
Console.WriteLine($"Executor balance before: {executorBalanceBefore}");
30+
### willSelfExecute (required)
31+
Whether the authorization will be executed by the EOA itself or by a third-party. It will affect the nonce of the authorization.
5832

59-
// Prepare the claim call
60-
var claimCallData = erc20Contract.CreateCallData(
61-
"claim",
62-
new object[]
63-
{
64-
executorWalletAddress, // receiver
65-
100, // quantity
66-
Constants.NATIVE_TOKEN_ADDRESS, // currency
67-
0, // pricePerToken
68-
new object[] { Array.Empty<byte>(), BigInteger.Zero, BigInteger.Zero, Constants.ADDRESS_ZERO }, // allowlistProof
69-
Array.Empty<byte>() // data
70-
}
71-
);
33+
</Details>
7234

73-
// Embed the claim call in the execute call
74-
var executeCallData = delegationContract.CreateCallData(
75-
method: "execute",
76-
parameters: new object[]
77-
{
78-
new List<Thirdweb.Console.Call>
79-
{
80-
new()
81-
{
82-
Data = claimCallData.HexToBytes(),
83-
To = erc20ContractAddress,
84-
Value = BigInteger.Zero
85-
}
86-
}
87-
}
88-
);
35+
<Details summary="Return Value">
8936

90-
// Execute from the executor wallet targeting the eoa which is pointing to the delegation contract
91-
var tx2 = await ThirdwebTransaction.Create(executorWallet, new ThirdwebTransactionInput(chainId: chainWith7702, to: eoaWalletAddress, data: executeCallData));
92-
var hash2 = (await ThirdwebTransaction.SendAndWaitForTransactionReceipt(tx2)).TransactionHash;
93-
Console.WriteLine($"Token claim transaction hash: {hash2}");
37+
### string
9438

95-
// Log erc20 balance of executor after the claim
96-
var executorBalanceAfter = await erc20Contract.ERC20_BalanceOf(executorWalletAddress);
97-
Console.WriteLine($"Executor balance after: {executorBalanceAfter}");
98-
```
39+
The method returns an `EIP7702Authorization` object that can be passed to our `ThirdwebTransaction`/`ThirdwebTransactionInput` related APIs and broadcast as such.
9940

100-
_Note that for the time being this only works on 7702-enabled chains such as [Odyssey](https://thirdweb.com/odyssey-911867) and the feature has only been integrated with `PrivateKeyWallet`._
41+
</Details>

apps/portal/src/app/dotnet/wallets/providers/account-abstraction/page.mdx

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,49 @@ export const metadata = createMetadata({
66
"Instantiate a SmartWallet for enhanced user interactions with blockchain applications.",
77
});
88

9-
# SmartWallet.Create
9+
# Native Account Abstraction (via EIP-7702 Smart EOAs)
10+
11+
With the recent Ethereum upgrade Pectra, EIP-7702 allows you to upgrade your EOA and get SmartWallet-like functionality with:
12+
- Much cheaper gas costs, batching functionality
13+
- No account separation - your wallet address does not change, not even on zksync chains (once they implement EIP-7702)
14+
- Much faster execution, with the option of paying for gas yourself or having thirdweb manage gas sponsorship, similar to SmartWallet.
15+
16+
The API is also drastically simplified!
17+
18+
### ExecutionMode.EIP7702Sponsored
19+
Upgrade to an EIP7702 smart account, unlocking all functionality of 4337 without the downsides, and thirdweb handles the execution and gas sponsorship for you!
20+
```csharp
21+
var smartEoa = await InAppWallet.Create(
22+
client: thirdwebClient,
23+
authProvider: AuthProvider.Google,
24+
executionMode: ExecutionMode.EIP7702Sponsored
25+
);
26+
```
27+
28+
### ExecutionMode.EIP7702
29+
Upgrade to an EIP7702 smart account, unlocking all functionality of 4337 without the downsides, but sponsoring gas yourself.
30+
```csharp
31+
var smartEoa = await InAppWallet.Create(
32+
client: thirdwebClient,
33+
authProvider: AuthProvider.Google,
34+
executionMode: ExecutionMode.EIP7702
35+
);
36+
```
37+
38+
### ExecutionMode.EOA
39+
"Normal" EOA Execution, no smart account functionality
40+
```csharp
41+
var basicEoa = await InAppWallet.Create(
42+
client: thirdwebClient,
43+
authProvider: AuthProvider.Google,
44+
// does not need to be explicitly passed, is the default but we're showing it here
45+
executionMode: ExecutionMode.EOA
46+
);
47+
```
48+
49+
_When using EIP-7702 execution modes - if not already delegated to a smart account - an EIP-7702 authorization will be signed and bundled with your first transaction, similar to how 4337 works with initcode, but without the large gas costs, slower execution and chain specific requirements._
50+
51+
# SmartWallet (via EIP-4337 Bundlers)
1052

1153
Instantiate a `SmartWallet` to enable advanced blockchain interactions, including gasless transactions through account abstraction. This wallet type is especially useful for creating a user-friendly experience in decentralized applications.
1254

apps/portal/src/app/unity/v5/wallets/account-abstraction/page.mdx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,31 @@ export const metadata = createMetadata({
77
"Instantiate a SmartWallet to sign transactions and messages.",
88
});
99

10-
# SmartWallet
10+
# Native Account Abstraction (via EIP-7702 Smart EOAs)
11+
Native Account Abstraction is a system that allows you to set code to an EOA, unlocking a world of possibilities to enhance their functionality. It is available since the Pectra upgrade on various chains.
12+
13+
Enabling it is as simple as creating an `InAppWallet` and passing the `ExecutionMode.EIP7702Sponsored` flag during creation.
14+
15+
```csharp
16+
// Turn your boring EOAs into Smart EOAs!
17+
var smartIaw = await ConnectWallet(
18+
new WalletOptions(
19+
provider: WalletProvider.InAppWallet,
20+
chainId: 11155111, // Sepolia supports EIP-7702
21+
inAppWalletOptions: new InAppWalletOptions(
22+
authprovider: AuthProvider.Google,
23+
executionMode: ExecutionMode.EIP7702Sponsored // new!
24+
)
25+
)
26+
);
27+
ThirdwebDebug.Log("Connected to InAppWallet: " + await smartIaw.GetAddress());
28+
29+
// Execute a transaction as usual, execution is managed by thirdweb seamlessly!
30+
var receipt = await smartIaw.Transfer(11155111, await smartIaw.GetAddress(), 0);
31+
ThirdwebDebug.Log($"Transfer receipt: https://sepolia.etherscan.io/tx/{receipt.TransactionHash}");
32+
```
33+
34+
# SmartWallet (via EIP-4337 Bundlers)
1135

1236
Instantiate or upgrade any other wallet to a `SmartWallet` to enable advanced blockchain interactions, including gasless transactions through Account Abstraction (ERC4337 as well as ZkSync Native AA).
1337

0 commit comments

Comments
 (0)