Skip to content
This repository has been archived by the owner on May 28, 2024. It is now read-only.

Various #2

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@aztec/sdk": "^2.1.45",
"@aztec/bridge-clients": "^0.1.62",
"@aztec/bridge-clients": "^0.1.63",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^13.2.1",
Expand All @@ -17,6 +17,7 @@
"react-dom": "^18.2.0",
"react-scripts": "4.0.3",
"typescript": "^4.4.2",
"wagmi": "^0.6.7",
"web-vitals": "^2.1.0"
},
"scripts": {
Expand Down
69 changes: 32 additions & 37 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import "./App.css";
import { useEffect, useState } from "react";
import { ethers } from "ethers";
import {
AztecSdk,
createAztecSdk,
EthersAdapter,
EthereumProvider,
SdkFlavour,
AztecSdkUser,
GrumpkinAddress,
SchnorrSigner,
Expand All @@ -17,14 +13,18 @@ import {

import { depositEthToAztec, registerAccount, aztecConnect } from "./utils";
import { fetchBridgeData } from "./bridge-data";
import { useSdk } from "./sdk";
import { useConnect, useSigner } from "wagmi";

declare var window: any;

const App = () => {
const [hasMetamask, setHasMetamask] = useState(false);
const [ethAccount, setEthAccount] = useState<EthAddress | null>(null);
const [initing, setIniting] = useState(false);
const [sdk, setSdk] = useState<null | AztecSdk>(null);
const { connectAsync, connectors } = useConnect();
const { data: l1Signer } = useSigner();
const sdk = useSdk();
const initing = !sdk;
const [account0, setAccount0] = useState<AztecSdkUser | null>(null);
const [userExists, setUserExists] = useState<boolean>(false);
const [accountPrivateKey, setAccountPrivateKey] = useState<Buffer | null>(
Expand All @@ -48,38 +48,26 @@ const App = () => {
}, []);

async function connect() {
if (window.ethereum) {
setIniting(true); // Start init status

const mmConnector = connectors[0];
if (mmConnector && sdk) {
const { account: mmAddressStr } = await connectAsync({
connector: mmConnector,
});
// Get Metamask provider
// TODO: Show error if Metamask is not on Aztec Testnet
const provider = new ethers.providers.Web3Provider(window.ethereum);
const ethereumProvider: EthereumProvider = new EthersAdapter(provider);
const mmProvider = new EthersAdapter(
(await mmConnector.getSigner()).provider
);

// Get Metamask ethAccount
await provider.send("eth_requestAccounts", []);
const mmSigner = provider.getSigner();
const mmAddress = EthAddress.fromString(await mmSigner.getAddress());
const mmAddress = EthAddress.fromString(mmAddressStr);
setEthAccount(mmAddress);

// Initialize SDK
const sdk = await createAztecSdk(ethereumProvider, {
serverUrl: "https://api.aztec.network/aztec-connect-testnet/falafel", // Testnet
pollInterval: 1000,
memoryDb: true,
debug: "bb:*",
flavour: SdkFlavour.PLAIN,
minConfirmation: 1, // ETH block confirmations
});
await sdk.run();
console.log("Aztec SDK initialized:", sdk);
setSdk(sdk);

// Generate user's privacy keypair
// The privacy keypair (also known as account keypair) is used for en-/de-crypting values of the user's spendable funds (i.e. balance) on Aztec
// It can but is not typically used for receiving/spending funds, as the user should be able to share viewing access to his/her Aztec account via sharing his/her privacy private key
const { publicKey: accPubKey, privateKey: accPriKey } =
await sdk.generateAccountKeyPair(mmAddress);
await sdk.generateAccountKeyPair(mmAddress, mmProvider);
console.log("Privacy Key:", accPriKey);
console.log("Public Key:", accPubKey.toString());
setAccountPrivateKey(accPriKey);
Expand All @@ -95,22 +83,23 @@ const App = () => {
// Generate user's spending key & signer
// The spending keypair is used for receiving/spending funds on Aztec
const { privateKey: spePriKey } = await sdk.generateSpendingKeyPair(
mmAddress
mmAddress,
mmProvider
);
const schSigner = await sdk?.createSchnorrSigner(spePriKey);
console.log("Signer:", schSigner);
setSpendingSigner(schSigner);

setIniting(false); // End init status
}
}



// Registering on Aztec enables the use of intuitive aliases for fund transfers
// It registers an human-readable alias with the user's privacy & spending keypairs
// All future funds transferred to the alias would be viewable with the privacy key and spendable with the spending key respectively
async function registerNewAccount() {
if (!l1Signer) {
console.error("Wallet disconnected");
return;
}
try {
const depositTokenQuantity: bigint = ethers.utils
.parseEther(amount.toString())
Expand All @@ -125,7 +114,8 @@ const App = () => {
depositTokenQuantity,
TxSettlementTime.NEXT_ROLLUP,
ethAccount!,
sdk!
sdk!,
l1Signer
);

console.log("Registration TXID:", txId);
Expand All @@ -140,6 +130,10 @@ const App = () => {
}

async function depositEth() {
if (!l1Signer) {
console.error("Wallet disconnected");
return;
}
try {
const depositTokenQuantity: bigint = ethers.utils
.parseEther(amount.toString())
Expand All @@ -150,7 +144,8 @@ const App = () => {
accountPublicKey!,
depositTokenQuantity,
TxSettlementTime.NEXT_ROLLUP,
sdk!
sdk!,
l1Signer
);

console.log("Deposit TXID:", txId);
Expand Down Expand Up @@ -209,7 +204,7 @@ const App = () => {
)
);
}

async function logBridges() {
const bridges = await fetchBridgeData();
console.log("Known bridges on Testnet:", bridges);
Expand Down Expand Up @@ -297,7 +292,7 @@ const App = () => {
// TODO: Fix rendering of this. Not rendered, reason unknown.
"Metamask is not detected. Please make sure it is installed and enabled."
)}
{initing ? <div>Initializing...</div> : ""}
{initing ? <div>Initializing Aztec SDK...</div> : ""}
</div>
);
};
Expand Down
87 changes: 87 additions & 0 deletions src/bridge-data/bridge-client-cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { BridgeData } from "@aztec/bridge-clients/client-dest/src/client/aztec/data-provider/DataProvider";
import { BridgeDataFieldGetters } from "@aztec/bridge-clients/client-dest/src/client/bridge-data";
import { CurveStethBridgeData } from "@aztec/bridge-clients/client-dest/src/client/curve/curve-steth/curve-bridge-data";
import { DCABridgeData } from "@aztec/bridge-clients/client-dest/src/client/dca/dca-bridge-data";
import { EulerBridgeData } from "@aztec/bridge-clients/client-dest/src/client/euler/euler-bridge-data";
import { ElementBridgeData } from "@aztec/bridge-clients/client-dest/src/client/element/element-bridge-data";
import { YearnBridgeData } from "@aztec/bridge-clients/client-dest/src/client/yearn/yearn-bridge-data";
import { EthereumProvider } from "@aztec/sdk";
import {
RogueEthAddress,
rogueEthAddressFromString,
} from "./rogue-eth-address";

type BridgeDataByName = Record<string, BridgeData>;

interface BuildArgs {
provider: EthereumProvider;
rollupContractAddress: RogueEthAddress;
bridges: BridgeDataByName;
falafelGraphQlEndpoint: string;
}

const clientBuilders = {
"curve-lido": (args: BuildArgs) => {
const curvePoolAddress = "0xdc24316b9ae028f1497c275eb9192a3ea0f67022";
const wstETHAddress = "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0";
const lidoOracleAddress = "0x442af784A788A5bd6F42A01Ebe9F287a871243fb";
return CurveStethBridgeData.create(
args.provider,
rogueEthAddressFromString(wstETHAddress),
rogueEthAddressFromString(lidoOracleAddress),
rogueEthAddressFromString(curvePoolAddress)
);
},

dca: (args: BuildArgs) =>
DCABridgeData.create(args.provider, args.bridges["DCA400K"].bridgeAddress),

euler: (args: BuildArgs) => {
const lidoOracleAddress = "0x442af784A788A5bd6F42A01Ebe9F287a871243fb";
return EulerBridgeData.createWithLido(
args.provider,
rogueEthAddressFromString(lidoOracleAddress)
);
},

element: (args: BuildArgs) => {
const balancerAddress = "0xBA12222222228d8Ba445958a75a0704d566BF2C8";
return ElementBridgeData.create(
args.provider,
args.bridges["ElementBridge"].bridgeAddress,
rogueEthAddressFromString(balancerAddress),
args.rollupContractAddress,
args.falafelGraphQlEndpoint
);
},

yearn: (args: BuildArgs) =>
YearnBridgeData.create(args.provider, args.rollupContractAddress as any),
};

export type BridgeClientName = keyof typeof clientBuilders;
export class BridgeClientCache {
private clients = new Map<BridgeClientName, BridgeDataFieldGetters | null>();
private falafelGraphQlEndpoint =
"https://api.aztec.network/aztec-connect-testnet/falafel/graphql";
constructor(
private provider: EthereumProvider,
private rollupContractAddress: RogueEthAddress,
private bridges: BridgeDataByName
) {}

get(name: BridgeClientName) {
if (!this.clients.has(name)) {
this.clients.set(
name,
clientBuilders[name]({
provider: this.provider,
rollupContractAddress: this.rollupContractAddress,
bridges: this.bridges,
falafelGraphQlEndpoint: this.falafelGraphQlEndpoint,
})
);
}
return this.clients.get(name)!;
}
}
26 changes: 26 additions & 0 deletions src/bridge-data/bridge-data-util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {
AztecAssetType,
AztecAsset,
} from "@aztec/bridge-clients/client-dest/src/client/bridge-data";
import { AztecSdk, EthAddress } from "@aztec/sdk";
import { toRogue } from "./rogue-eth-address";

export function toBridgeDataAsset(
sdk: AztecSdk,
assetId: number | null
): AztecAsset {
if (assetId === null) return UNUSED_BRIDGE_DATA_ASSET;
const asset = sdk.getAssetInfo(assetId);
const assetType = assetId === 0 ? AztecAssetType.ETH : AztecAssetType.ERC20;
return {
id: assetId,
assetType,
erc20Address: toRogue(asset.address),
};
}

const UNUSED_BRIDGE_DATA_ASSET: AztecAsset = {
id: 0,
assetType: AztecAssetType.NOT_USED,
erc20Address: toRogue(EthAddress.ZERO),
};
73 changes: 73 additions & 0 deletions src/bridge-data/bridge-data.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React, {
createContext,
useContext,
useEffect,
useRef,
useState,
} from "react";
import {
DataProviderWrapper,
BridgeData,
} from "@aztec/bridge-clients/client-dest/src/client/aztec/data-provider/DataProvider";
import { EthereumProvider, EthersAdapter } from "@aztec/sdk";
import { rogueEthAddressFromString } from "./rogue-eth-address";
import { BridgeClientCache } from "./bridge-client-cache";
import { useProvider } from "wagmi";

interface BridgeDataContextValue {
bridges: BridgeDataByName | null;
bridgeClientCache: BridgeClientCache | null;
}

async function initBridgeData(
provider: EthereumProvider
): Promise<BridgeDataContextValue> {
// This address is stale - needs updating once the contract has been redeployed.
const testnetAddress = "0x525b43be6c67d10c73ca06d790b329820a1967b7";
const dataProvider = DataProviderWrapper.create(
provider,
rogueEthAddressFromString(testnetAddress)
);
const rollupProviderAddressProm = dataProvider.getRollupProvider();
const bridgesProm = dataProvider.getBridges();
const rollupContractAddress = await rollupProviderAddressProm;
const bridges = await bridgesProm;
const bridgeClientCache = new BridgeClientCache(
provider,
rollupContractAddress,
bridges
);
return { bridges, bridgeClientCache };
}

type BridgeDataByName = Record<string, BridgeData>;

const BridgeDataContext = createContext<BridgeDataContextValue>({
bridges: null,
bridgeClientCache: null,
});

export function BridgeDataProvider(props: {
// provider: EthereumProvider;
children: React.ReactNode;
}) {
const [value, setValue] = useState<BridgeDataContextValue>({
bridges: null,
bridgeClientCache: null,
});
const provider = useProvider();
// The first provider should be the stable public provider...
const firstProvider = useRef(provider).current;
useEffect(() => {
initBridgeData(new EthersAdapter(firstProvider)).then(setValue);
}, [firstProvider]);
return (
<BridgeDataContext.Provider value={value}>
{props.children}
</BridgeDataContext.Provider>
);
}

export function useBridgeData() {
return useContext(BridgeDataContext);
}
13 changes: 13 additions & 0 deletions src/bridge-data/rogue-eth-address.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { UnderlyingAsset } from "@aztec/bridge-clients/client-dest/src/client/bridge-data";
import { EthAddress } from "@aztec/sdk";

// Annoying redeclation of EthAddress class resulting from double download of @aztec/barretenberg
export type RogueEthAddress = UnderlyingAsset["address"];

export function rogueEthAddressFromString(str: string) {
return EthAddress.fromString(str) as unknown as RogueEthAddress;
}

export function toRogue(ethAddress: EthAddress): RogueEthAddress {
return ethAddress as unknown as RogueEthAddress;
}
Loading